How to Check Your Web App for Security Vulnerabilities

Learn how to pick locks with soapUI - so that your own web applications can be made more safe.

The day of release has arrived; everyone is happy. All reported bugs are fixed, all tests passed, and the servers are configured. The application starts its new life on the grid. Users enter their data, new content is being created. New features are added; new users are coming. Success!

Then, one sunny day, all hell breaks loose. The database is deleted, users identities are being sold, e-mails are missing, servers are not responding… You have been hacked. Your application’s security has been compromised.

It isn’t that your development team doesn’t care about making software secure. It isn’t that fancy new features are more important than mystical security. It’s that many developers don’t know how to go about checking their applications for security vulnerabilities.

Happily, some development tools can provide the expertise that developers and testers personally lack. Among them is the open source soapUI, a functional testing tool. The Pro version's features include security scans that probe your Web services and web applications with the most common attacks – to ensure that your software is not a hacker's toy waiting to happen. In this article I show you how to use soapUI to prevent the most common and most dangerous attacks as described by OWASP.

Our Scenario


Our target, for the purpose of this example, is McAfee Foundstone's Hacme Casino, which the company calls “a learning platform for secure software development.” The (intentionally insecure) web application is a good candidate for a soapUI demonstration.



Analyze The Target


To begin with, let’s check out the casino site as it presents itself online by doing a View Source of this webpage:

view source


The highlighted part of this code is the login form. The user name and password are sent to the server as plain text with POST HTTP method to server action /account/login:

<form action="/account/login" method="post">


The Input parameters for username and password are user_login and user_password:

<input id="user_login" size="30" value=""/><br/>
<label for="user_password">Password:</label><br/>
<input id="user_password" size="30"/>


This is enough for a start. Now we can get to business.

Preparing Probing


Start soapUI and create an empty project; I named mine HackCasino. Add one test suite and one test case, with an HTTP test request to the login form:



I tried one dummy username and password, but as you can see it results in the response, “Login unsuccessful. Please try again.” Notice that the URL is http://localhost:3000/account/login which I set as the request URL. The method is set to POST. Also, I added two parameters: user_login and user_password.

It would be possible to use brute force to guess a username and password. I could use functional testing in soapUI for that, but it would require setting data sources, property transfers, looping, etc. Instead I use security testing in soapUI. Just create a security test and add Custom Security Scan:



Okay: Now lets configure it:



I used the option for auto parameter extraction to get username and password parameters, than added a small Groovy script to read passwords and usernames from my dictionary:

if ( context.getProperty("passwords") == null ) {
context.setProperty("passwords", new File("passwords.txt").readLines())
context.setProperty("passCnt", 0)
}
if ( context.getProperty("users") == null ) {
context.setProperty("users", new File("usernames.txt").readLines())
     context.setProperty("userCnt", 0 )
}
def passwdList = context.getProperty("passwords")
def userList = context.getProperty("users")
def passwdCnt = context.getProperty("passCnt")
def userCnt = context.getProperty("userCnt")

parameters.user_login = userList.get(userCnt)
parameters.user_password = passwdList.get(passwdCnt)
if( ++passwdCnt >= passwdList.size() ) {
context.setProperty("passCnt", 0 )
context.setProperty("userCnt", ++userCnt )
} else
context.setProperty("passCnt", passwdCnt)
if( userCnt < userList.size()  )
return true
else
return false


What does this do? It reads two files, usernames.txt and passwords.txt.  For each username it probes a password. Now all you need is a huge dictionary for usernames and passwords. Press play and relax.

Note that, unless you have some automatic way to recognize that you are logged in, you are doomed. You need to check each response manually. For this example it would be enough just to add an assertion that contains:


Script Understanding


The object context is available in most soapUI Groovy scripts, but only during test runtime. You can add or set the object properties to it with context.setProperty(<property name>, <property value>) and read its property with context.getProperty(<property name>). In this script it explicitly returns true or false as the result purely for readability reasons. The script should return true if there is more iterations to be done, otherwise false.

XPath and SQL injection


Almost always, web applications have a data tier in back. It happens, quite often, that inputs from text fields are directly put in SQL/XPath queries or the input is not checked correctly. The common scenario is like this:

SELECT * FROM our_secret_table WHERE field=<input_field>


If the application directly enters value from input_field without any checking or the checks do not do what they should, any string could be inserted there, even those which modify the SQL statement in a way that lets you gain access to the whole table. Perhaps this example is not the best, but wait — let’s see how this works on our casino.

First add SQL injection:



Notice that in the Advanced tab you see some common SQL injections. You can modify, delete, or add new ones to test for. Also add the same assertion as in the Custom Security Scan.

We can run SQL injection with the default configuration:



Notice that after the second request, the application stops responding. What happens is that the casino web application dies when for user_login ‘—is sent. This is a very serious flaw in the casino application (which is one reason it is a good one to experiment with). You can find more values in the default SoapUI configuration that break the casino.

When you remove all the injection strings that break the casino web application, the SQL test passes.

Now you can add some new options, your own injection strings. Lets add one more SQL injection string in the configuration: ‘) or 1=1-- :


As you can see from the log, when ‘) or 1=1—is inserted in the login name field, we do not get the expected response; something happened. Double click on this message to see details and to inspect the response:



It looks like we managed to login. To verify that this works, go to your browser and insert ‘) or 1=1— for the login name:



Wow, fancy hairstyle.

This means you can login as Andy even if you do not have his password. But what does that mean, exactly? I’m guessing from this behavior that when the username and password is passed to the application the SQL query appears like this:

SELECT * FROM users_tb WHERE (username=’<user_login>’
AND password=’<user_password>’)


And when the injection is done it look like this:

SELECT * FROM users_tb WHERE (username=’) or 1=1-- AND password=’)


And that returns Andy. This is a very common and a very serious security flaw.

Cross Site Scripting Candidate


Before we talk about Cross Site Scripting (XSS) let’s investigate the page for transferring chips and money. Click on Options. You should see:



If you look at the page’s code, you see two interesting forms: transfer chips and cash out. In the same manner we used for the login screen you can easily compose requests for both of them:

http://localhost:3000/account/transfer_chips?transfer=<amount
>&login[]=<user_name>&commit=Transfer+Chips



and

http://localhost:3000/account/cash_out?amount=<money>&account=
<account number>&commit=Cash+Out



If you are logged in, you can click on any on those two links and they will be executed.

Ok, but now you wonder what to do with this? I now have access to Andy’s casino account. If other players transfer chips to Andy’s account, I could than transfer those chips to my account or send its value to my off shore account. Or maybe it would be better if they directly transfer money to my account?

Just make users click on these links:

http://localhost:3000/account/transfer_chips?transfer=1000
&login[]=bobby_blackjack&commit=Transfer+Chips


Or:

http://localhost:3000/account/cash_out?amount=1000
&account=11111-1111-111-111&commit=Cash+Out


Now I’m rich!

The first link works if Bobby is logged in and only if he clicks on it. The second one just needs that user to be logged on — and that can be accomplished if someone plants those links on proper places, such as in an e-mail scam. All you need is to send e-mail to Bobby with some appealing text (“Grand Casino Opening: Free nights at our five star hotel. Please confirm.” ).

The second link is a great candidate for a Cross Site Scripting Attack (XSS), a security flaw when an application allows malicious users to insert a script into its web pages. That script is executed when those infected pages are executed. So, if this casino application has some forum or an attacker knows about forums where these users hang out, the evildoer  could try to inject this URL or script that executes this URL.  Suppose the existence of forums or web applications where these users discuss casino topics. I would create a dummy user and post a message which would have a hidden script that transfers the cash.

To find a proper target for this I would use XSS Security Scan in soapUI:



In similar fashion, like the two previous security scans, SoapUI has predefined insertions but you could add your own. What is different from other attacks is that attacker goes after the server users, not the server itself. A response for request in that inserted attack will not necessarily have attack itself and you do not want to target yourself. That is why this Security Scan has a special assertion Cross Site Scripting Detection:



What is so special is that not only it checks response, but also you could enter a list of URLs that should be checked, or write a Groovy script that generates those URLs.

Tools


Close

Add a little SmartBear to your life

Stay on top of your Software game with the latest developer tips, best practices and news, delivered straight to your inbox

By submitting this form, you agree to our
Terms of Use and Privacy Policy

Thanks for Subscribing

Keep an eye on your inbox for more great content.

Continue Reading