Qualys Blog

www.qualys.com
mayuresh

How ZeroCMS Could Have Avoided Cross-Site Scripting Vulnerability CVE-2014-4710

My job as a Vulnerability Signature Engineer with Qualys means that I try out various proofs of concept (PoCs) for different vulnerabilities, and add false-positive-free detections for them to the QualysGuard scanner. It’s fun to dig into the mechanics of the vulnerabilities, but sometimes it’s the implications of the vulnerabilities that are the more interesting part. Such is the case with the vulnerability I found in ZeroCMS, a very simple Content Management System built using PHP and MySQL written by Perez Karjee.

It turns out ZeroCMS has a very basic vulnerability: None of the fields — Full Name, Email Address, Password or Confirm Password — are sanitized in the user registration page. This means if an end-user creates an account with username  <SCRIPT>alert('QualysXSSTest')</SCRIPT>, the app will display an alert box on every page, which is clearly a security issue.

Given how simple / obvious the vulnerability is (and how easy the fix described below), it seems the author didn’t worry about security, and likely intended ZeroCMS to be a proof of concept rather than an app someone would use in the real world. Or maybe not: the abundance of real-world applications missing input validation makes it unfair to single out ZeroCMS for insecure coding. So, let’s try a different, potentially more useful takeaway: Developers, no matter the purpose of their web apps, should follow secure coding best practices, even if just for the discipline of it. A good place to start is the OWASP Secure Coding Practices Quick Reference Guide. They put input validation at the top of the list.

But even when following OWASP’s secure coding practices, it’s still easy for developers to make mistakes or inadvertently miss adding input validation to a field, especially in a large application with multiple developers working on different components. The solution is the use and knowledge of security tools by developers to automate the best practices. The key is to give developers the ability to scan their own apps BEFORE they go to QA. Then the developer becomes both responsible for addressing security issues early in the software development lifecycle (SDLC), and he has the tools to do it consistently. The best practice video, Find & Fix Web Application Vulnerabilities Early, describes a framework for driving exactly this type of practice in the SDLC.

The Vulnerability in Detail

Here’s detail on the actual vulnerability I found: CVE-2014-4710. My first approach was to test for a SQL injection vulnerability in ZeroCMS. As all of us know, a large number of web application vulnerabilities exist because of insufficient input/output sanitization. The vulnerability has its SQLi PoC available. All I did was test the SQLi with an XSS test string and voila it worked! But by the time I got to report this, someone beat me to it and was already assigned CVE-2014-4034. This got me thinking that the software must be vulnerable in multiple locations. Hence, I started with the often-used functionality, user registration, and was successful yet again!

The vulnerability exists in the latest build and in multiple locations – a core file – header.kate.php which is executed on every page visit and – zero_user_account.php the file that handles user registration. None of the fields – Full Name, Email Address, Password or Confirm Password are sanitized in the user registration page. ALL characters that can possibly be used for XSS are allowed.

first-create-account

But the Full Name field is of special interest to us as it is reflected in every page post a user logon, potentially executing code every time! If only we are able to bypass the strict security on the underlying database software (in this case phpMyAdmin) it would turn into an awesome vulnerability which could do a lot more harm! So, I enter the alert script <SCRIPT>alert('QualysXSSTest')</SCRIPT> and simply hit create account to:

second-index

If you visit all the pages, you can see this prompt on each and every one of them:

third-compose

User control panel:

fourth-control-panel

As I said earlier, all of the unsanitized input is stored in the database. This is evident from:

fifth-control-panel

The CMS as such makes use of popular PHP functions mysql_real_escape_string() and htmlspecialchars() to avoid these kinds of vulnerabilities. However, in this particular case, input processed by zero_user_account.php is passed un-sanitized to zero_transact_user.php and even stored that in the database in an unsanitized manner.

This vulnerability was assigned CVE-2014-4710 by CVE MITRE.

How do you fix this?

I have twice tried to contact Perez. On both occasions, I was not able to get any response. Hence, we’ve had to disclose this vulnerability with a temporary fix, which can be used until Perez fixes this completely. The header.kate.php file picks up the logged in username from the zero_users table. This is the vulnerable code:

if(isset($_SESSION['name'])){
            echo '<p>You are currently logged in as: ' . $_SESSION['name'] . ' </p>';
}

Simply, change it to the following and you have a temporary fix:

if(isset($_SESSION['name'])){
            echo '<p>You are currently logged in as: ' . htmlspecialchars($_SESSION['name']) . ' </p>';
}

This should really just prevent the code from being reflected on every login page:

last-sanitized-input

One response to “How ZeroCMS Could Have Avoided Cross-Site Scripting Vulnerability CVE-2014-4710”

Leave a Reply