Changing One Digit In The Link Showed Someone Else’s Order

by Serguey Shinder

The address of an order confirmation on our site was the word orders followed by a number, and the numbers went up by one. A customer wrote to us in April to say that she had mistyped the last digit of a link she had bookmarked and was now looking at a stranger's order, with his name on it, his address, and what he had bought.

The page required you to be signed in. It had always required you to be signed in, and in every review anybody had ever done of it, that was the box that got ticked. What it never did was check that the order belonged to the person asking for it. We had written the sentence about who you are and had not written the sentence about whether this particular row is yours, and for three years the difference between those two sentences had never come up, because nobody had a reason to change a digit.

We could answer the question of how often it had happened, which was the one mercy of the week, because the access logs had the order identifier and the signed-in identifier both on the same line. In three years there were forty one occasions where those two did not belong together. Forty of them were within a minute or two of a mistyped link and went nowhere. One was a sequence of four hundred and sixty requests over about nine minutes, walking the numbers upward, from an account that had been created that morning.

The change that mattered was not making the identifiers unguessable, although we did that afterwards and it is worth doing. It was moving the ownership check out of the page and into the query. Nothing in our system loads an order any more without a customer attached to the request, because the function that loads one will not compile without it. A rule that lives in a controller is a rule that every future endpoint has to remember. A rule that lives in the thing that reads the data is a rule that a tired person writing a new screen on a Friday cannot forget, and I would rather design for that person than lecture them.

The distinction I had been carrying loosely for years and now hold properly is that authentication and authorisation are not two parts of one idea. They are two entirely separate questions asked at two different moments, and the first one is asked once at the front door while the second has to be asked again on every single row you return. When I look at a screen now I do not ask whether you have to log in to see it. I ask which row it shows, and what stops it showing me yours.

– Serguey Asael Shinder

Leave a Reply