Delete IDOR on a Fashion eCommerce Website

Yes, another IDOR. I find a lot of IDORs. It’s my favourite class of bugs. This is a story of an IDOR I reported on an Asian fashion eCommerce website’s private program. Let’s get on with the story:

The Feature:

Like most eCommerce websites, this website provided a feature to store addresses in the customer’s account. The Account section had an option to manage addresses. The address management API calls looked like these:

Note: Requests have been URL decoded for better readability

Create An Address:
POST /customer/address/create/?ajax=true&address_id= HTTP/1.1

Edit An Address:
POST /customer/address/edit/?ajax=true&address_id=2417909 HTTP/1.1

AddressForm[first_name]=Name&AddressForm[last_name]=Two&AddressForm[cell_phone]=98989898&phone_prefix=8,9&phone_len=7&AddressForm[phone]=&AddressForm[address1]=Lkb 122, asdsaasd sad Rd&AddressForm[address2]=12-321&AddressForm[postcode]=423122&AddressForm[fk_customer_address_region]=&AddressForm[city]=Singapore&AddressForm[fk_country]=198&AddressForm[id_customer_address]=2417909
Delete An Address:
GET /customer/address/delete/?address_id=2418179&YII_CSRF_TOKEN=token HTTP/1.1

Note that there are two injection points for triggering an IDOR in the above requests, except for delete. One in the URL query parameter and another in the POST body parameter. I tried all possible ways to impact an address that I did not own by changing the id’s being passed in the request. I tried things like Parameter Pollution, Passing multiple IDs in a array, varying values in the query parameter and body parameter. But none of them seemed to work.

While hunting further on the application, I noticed that it provided an option to add an address in the checkout flow as well. The thing that caught my attention was that the endpoint called to create an address from the checkout flow was different than the one we saw above. The create address request from checkout flow looked like this:

POST /checkout/shipment/saveaddress/ HTTP/1.1


I immediately tried manipulating the value of the “AddressForm[id_customer_address]” parameter and set it to an address ID belonging to another test account I had created. I checked the ID of the newly created address and the ID returned from the server matched the ID I had entered when creating the request. Feeling elated, I headed over to the other test account to check if the address was deleted from there. I refreshed the page, but somehow the address with the same ID was present there as well and the information contained in the address was unaffected. The manipulated request had caused no visible impact to the victim account’s address.

While I was still logged into the victim’s account, I attempted to edit the target address in the victim’s account. To my surprise, as soon as I tried to edit it, the address disappeared from the list of address in the victim’s account. I realized that something has happened because of my malformed request.

I used the same technique again to delete another address from victim’s account. This time to verify the change, I logged out and logged in again to the victim’s account. This time when I visited the Address Management page, the target address was no longer present in the victim’s account. This proved that I was able to delete addresses from other users’ accounts by manipulating the “AddressForm[id_customer_address]” parameter.

I came to the conclusion that a logout was required to see the change because the request was probably being served by a cache server and hence the address was still visible in the victim’s account after deletion. This is true for a lot of websites. Any unintended changes to a user’s information are reflected when a new session is created.

If you have any feedback or would like to ask any questions related to hacking, hit me up on twitter @ameyanekar. My DMs are open.