New Details On CitiGroup Compromise

The Daily Mail has a short article about how the recent compromise of 200,000+ Citigroup accounts occurred. Of course there is not much technical detail but the vulnerability and exploit are pretty obvious if what the article says is correct: “They simply logged on to the part of the group’s site reserved for credit card customers – and substituted their account numbers which appeared in the browser’s address bar with other numbers.”
Seriously? This sounds like a plain old parameter tampering attack (forceful browsing, or whatever you want to call it). This wasn’t even SQL injection which is easy enough. Even worse than that, the parameter in question sounds like it was an account number and that it was included in the URL of the request rather than within the body in a POST request. Straight out of Hacme Bank:

1.png#asset:400:url

 

9.png#asset:401:url
This attack might sound complicated to the masses who may not be familiar with application security but I assure you it is not. It’s one of those “attacks” that anyone with basic knowledge of a browser is capable of successfully pulling off. It’s an attack so easy that it almost gives some level of credibility to the way Hollywood portrays “hackers.” I just change:
http://www.depthsecuritybank.com/home/?acct=MY_ACC…
to
http://www.depthsecuritybank.com/home/?acct=YOUR_A…
I guess I’m not surprised since I continually run across applications in 2011 that are still vulnerable in a 1999 sort of way. So fair enough, it was an obvious vulnerability just waiting to be exploited by someone who noticed it. But wait, the article then contradicts itself by quoting an “expert” who is “part of the investigation.” “He said: ‘It would have been hard to prepare for this type of vulnerability.'” That’s nonsense. The article also begins with, “It has been called ‘one of the most brazen bank hacking attacks’ in recent years.” Brazen like fuzzing a small integer parameter in a URL until you harvest 200 thousand accounts? I guess so but maybe damaging was the adjective they should have used.
You don’t “prepare” for vulnerabilities; you securely code your applications so that they don’t contain them. You assume developers are going to create security flaws so you continually assess the security of sensitive applications to find and fix these vulnerabilities, especially low-hanging fruit like this one.

Ironically, this is one of those types of vulnerabilities that’s all but impossible for an automated web application vulnerability scanner to find but incredibly easy for even a savvy 12-year-old to discover. Can the security of any system be guaranteed? No way. Can a large bank be expected to prevent these types of vulnerabilities and compromises? Yep.
Some advice to avoid this type of an issue follows:

  1. Enforce authorization for every user request. When a user associated with account 0000001 makes a request for account 0256022, politely decline with a generic error message.
  2. Don’t use direct object references whenever possible. Retrieve information like account numbers by accessing users’ session objects rather than requiring that they be sent to the server. Think about it, why take from the user what you can get with a higher level of reliability from the server or database? If an ‘id’ is necessary for some reason then map a temporary value to the account number rather than using the actual account number in users’ requests.
  3. Don’t send sensitive information in the URL of a request. When in doubt, send parameters within the body of a POST request. This won’t protect you from this type of attack but it makes the flaw slightly less obvious.