Demonstrating Data Leak Bug0:00
You know I mentioned that the, the worst kinds of bugs are the silent bugs. The ones with no errors, they just happen and hopefully someone notices them so that you can find it and fix it. And you know, if the most scary is a security hole, the second to most scary is, well it's data leaking from one user to another And we have a bug that does exactly that. So we have two users.
And we have a bug that does exactly that. So we have two users. First is Alice, then we're gonna sign in with Bob here in a few minutes. But first of all, I want to add some items to the cart as Alice. So Alice likes the super unit book, so she wants to add that to the cart. So we will do that. Then we also want to add something else and, and really this is going to be sufficient,
So we will do that. Then we also want to add something else and, and really this is going to be sufficient, but you know what, let's find some other products. So here's the elite widget, that's 250 bucks. I think that's something that we could spend. And there we go. So we have two items in the cart. Everything looks fine and that's wonderful. So Bob has never really used the website before, so he's gonna sign in for the very first time. There's no cookies, there's nothing there.
before, so he's gonna sign in for the very first time. There's no cookies, there's nothing there. And in fact, edge is popping up. Hey, so if we take a look here, if we go to the cart, the cart's empty and that's really good until we actually do some shopping. So Bob wants to buy a pro set two, there's only one left, so he better grab it and he's gonna do just that. So he is gonna add that to his cart. And his cart is, well it's fine.
So he is gonna add that to his cart. And his cart is, well it's fine. But for Alice, if we refresh the page here, we see that the order summary is $5 and 39 cents. Now we know that that's absolutely wrong because one of the items that we picked was 250 bucks. So we know that the subtotal here is wrong, but the cart and everything else in the cart is correct. We have both of the items in the cart and yeah, so if we look at these amounts then we can
We have both of the items in the cart and yeah, so if we look at these amounts then we can see what is going on. You know, Bob wanted the pro set two, which was 4 99 and after tax it's 5 39. Well that's what we see in Alice's card. But if Alice you know, continues to shop and adds another item to the carts, let's just add ultra item three because that sounds awesome. And if we go back to Bob's cart, now notice the amounts
let's just add ultra item three because that sounds awesome. And if we go back to Bob's cart, now notice the amounts that we now have for Alice when we refresh Bob's cart $318. You know, the cart page shows the correct data or at least as far as the items are concerned, the items are there, their prices are there. Really the only thing that's different are the totals. And the totals persist between two independent browser sessions
And the totals persist between two independent browser sessions for two completely different users. And if it works for, should we say that it works or that it doesn't work, we, we know that the bug works. There we go. We know that the bug works for at least two users. We can assume and probably safely assume that's going to work for multiple and may be all users. So that last bit there
Tracing to Cache Key3:15
to work for multiple and may be all users. So that last bit there that it persists across users, you know and makes you think it could be sessions. But really what's the one thing that persists across users? And it's the cache. We have a caching issue. So let's start by looking at the cart controller. And we want the index method because that is essentially what we saw when we go to the cart, we see the index for the cart there.
because that is essentially what we saw when we go to the cart, we see the index for the cart there. So we see that we get the cart that is handed over to the view, but then we also see that the cart total is sent to the view as well. And that's part of the cart service. So if we take a look at get cart total, let's see, we return cash, remember, then we pass in the key and and that right there that, that's the problem because we are using the same key to get
and that right there that, that's the problem because we are using the same key to get and set the cache for every user. Ideally we would have a unique key for a user that's not happening here. So that's why we are caching the cart total for whoever adds an item into the cart. The last, so there's our bug right there. So of course the solution to this seems rather obvious. We want a unique key for each user.
Designing User-Scoped Key4:33
So of course the solution to this seems rather obvious. We want a unique key for each user. So we can do that based upon the user's id. That makes sense, except that there may not be a signed in user. What if the user is a guest, in which case there's an issue there. So what we can do then is check to see if we have a user ID here and then we can just create a cash key based upon that so
to see if we have a user ID here and then we can just create a cash key based upon that so that we'll have the cart total for the user of user id. And then if it's a guest, I guess we could use the session now you could think, well we could just use the session for, you know, both cases for both the user and for guest users. And that's at least the first thing that I thought of. But then I thought, well you know, if I go to Amazon
And that's at least the first thing that I thought of. But then I thought, well you know, if I go to Amazon and I'm signed in on my mobile device, if I add items to the cart and then I go to a computer sign in and view that cart, I'm gonna see the same cart. Those are two completely different sessions because they are on two completely different devices. So it needs to be based upon the user for a signed in user. Otherwise for a guest we'll use a different key instead of user, we'll say guest
Fixing Cache Invalidation5:44
Otherwise for a guest we'll use a different key instead of user, we'll say guest and then we will get the session id. So we'll call session get id and so there we go. So now we have this cash key that we can use for our cart total. But one thing that we need to check is do we invalidate the cash anytime that the cart changes? Because if it doesn't
that the cart changes? Because if it doesn't then the cart total is never gonna change when someone adds an item to the cart. So let's start by looking at add item. So we get the cart here, we get the existing item, blah blah blah, clear cart cash. So yes that looks like that is being done. However, we need to like take a look at the method and we can see that sure enough we are getting the same
However, we need to like take a look at the method and we can see that sure enough we are getting the same issue here we are clearing out that static key. So what do we do? Uh, the easiest thing to do would be to just copy that code and then paste it in here so that then we could use the cash key and that will clear it out. Pretty simple idea there. Whether or not if it works, we will need to see, uh,
Pretty simple idea there. Whether or not if it works, we will need to see, uh, we could go through the rest of the code and see if that clear cache is called. But it looks like it is for the clear cart, it is for remove item. And yeah, so we are okay there. The main thing is that we needed to clear the correct cash key and let's give this another shot.
Verifying the Fix7:17
to clear the correct cash key and let's give this another shot. We will refresh what we have here and right now the totals look okay, but you know, let's continue shopping for Alice. She wants a premium device 12. We will add that to the cart and we can see that the total now is 360 1 76 for Bob. If we refresh, we are still at 5 39. So just for the sake of completeness, let's add something
Caching Security Takeaways7:40
If we refresh, we are still at 5 39. So just for the sake of completeness, let's add something to Bob's cart, which that was outta stock. We can't do that. Uh, this deluxe device is not, we will add that to the cart. His total is now 10 78, but Alice's still remains at 360 1. So this kind of bug can teach us two things. The first is that performance optimizations can become security problems.
The first is that performance optimizations can become security problems. A cash key that isn't properly scoped is prime for leaking data between users and we don't want that. So then the second thing is really when it comes to caching, we need to question whether, if we need to cache something at all because user specific data is personal data and we need to treat that with care.
and we need to treat that with care.
