Web application security
By 姚 皋 (yaogao)
Neusoft Shenyang Liaoning Province P.R.C
Preface
As a web application developer, I want to develop perfect software. It is correct, robust, efficient and secure, etc. But how can we approach these? I believe that we can inherit experiences from experts or experienced people firstly, read books or documents by them, and then have practices.
Have been developing web application for almost a year, and as we all see, one of base requirement of our program is security. But I find that web application security is difficult to learn and practice, and it is hard to find a web site to search for vulnerabilities too, because it will be regarded as an internet attack if we do it without permission.
Fortunately, I found one on internet, it is Web Goat, and it is the very tool I had been searching for a long time. Web Goat is written in java and therefore installed in any platform with a java virtual machine. Without any complex configuration files, however, it is easy to use. Want to study web application security? The following are my experiences in studying with Web Goat, and appreciate for correcting my mistakes. God give you joy!
What is vulnerability?
Vulnerability is a weakness in an application, which can be a design flaw or an implementation bug, which allows an attacker to cause harm to people who use the application directly or indirectly. The term “vulnerability” is often user loosely. However, here we should distinguish threats, attacks and countermeasure. So what is threat? Here we descript it as the potential that something will happen. And what is an attack? Attacks are techniques that attackers use to exploit vulnerabilities in an application. It means that attackers make use of threats in your application to do something harm. Countermeasures are defensive techniques that detect, deter and deny attacks. Here we will discuss kinds of attacks, but our purpose is not teach someone how to attack a web site, but study how attackers attack and find out countermeasures to make our applications safer.
What happened after we clicked the submit button?
Our browser will send a document request bases on HTTP after submit the form. The web application container (Tomcat) will accept the request and wrap it as a request object (It is a Java object), then send the object to our web application. As soon as the application gets the object, the application will do its business action with the request object, for example, reverse the input or query something from database, then generate HTML documents and display it back to client (Web browser).
We will study the following topics about common web application flaws:
Thread-safety
Web application can handle many HTTP request simultaneously. Developers often use variables that are not thread safe. Thread safety means that fields of objects or class maintain a valid state when accessed concurrently by multiple threads. Because many threads share the same method, and the method area is where all or some of the objects variables stored, so each thread can modify these variables, and we all see, it is dangerous for a application. For example, two users login a site the same time, they might get a wrong username.
Notes:
Make our program thread safe. But how can we approach this, we just make sure our method which can modify class fields structurally have been synchronized, or make our objects will never be accessed by multiple threads.
Code quality
Hackers may take advantage of comments inside your page source code. The can discover clues in the HTML, because some developers left Code Broken, Hack … etc inside the source code.
Notes:
JSP supports two kinds of comments. One of them is server side comments; the server side comments mean that client won’t see these comments. It looks like the following code,
<code> <%-- Add your comments here--%><code>
The other is HTML comments, HTML comments will send to client, so any people may see them.
<code> <!-- Username: yaogao Password: yaogao-- ><code> is HTML comments, curious people may see them and login the system by them.
Notes:
So review our code carefully.
Unvalidated hidden fields
Hidden field is a convenient and easy mechanism. We will use them for tracking, login, pricing etc… information on a loaded page, but we often forget to validate the information that received from the hidden fields. Attackers can modify these information arbitrarily after submit the form by some tools such as Web Scarab.
Notes:
Remember that information from client is not credible; just validate them in your program.
Uncheck email or message
It is always a good practice to validate all inputs. Most sites allows a user to send a message or email to his or her friends, but they don’t check the content of the message or mail, so people can send everything even HTML and JavaScript. But the HTML or JavaScript may do harm to other people. For example, spammers take advantage of this mechanism to send email using your corporate mail server.
Notes:
Just validate them. I think regular expression is a good choice.
JavaScript validation
Client side validation should not be considered as secure means of validating parameters. These validations only help reduce the amount of communications between client and server. Attackers can bypass these mechanisms easily in various ways, for example, using Web Scarab to modify the request. Any client-side validation should be duplicated on the server side.
Notes:
Validate all inputs on the server side, including hidden inputs.
Remote admin access
Applications will often have an administrative interface that allows privileged users to access functionality that normal users could not see and the server as well. Normally the admin interface is controlled via URL parameter.
Notes:
I haven’t got the solution to prevent these. Can anyone clue me in?
Role based access control
To manage a system, we create kinds of users and warrant them different privileges. One kind of a user we could take for a role, so the system is role-based. In a role-based access control scheme, as we have noted above, a role represents a set of access permissions and privileges. A user can assign one or more roles. A role-based control normally consists of two parts: role permission and assignment. A broken role-base control allows a user to perform access that are not allowed by his/her assigned role, or somehow obtain unauthorized roles. These normally caused by developers' or testers' negligence.
Notes:
How do we prevent a broken role-base control? The only answer is test the system strictly.
Path based access control
Most of systems allow normal users to access resources via path or URL. But in a path based access control scheme, an attacker can traverse a path by providing relative path information. Therefore an attacker can use a relative path to access files that normally are not accessible by anyone, or would otherwise be denied if requested directly. For example:
There is a file in d:/parent/child/, its name is "child.log", and file child.log is accessible by anyone login the system. There is another file called "parent.log" in d:/parent/, normally we cannot access "parent.log". But if the system allowed users to access "child.log" by entering "child.log", users would access "parent.log" by entering "../parent.log".
Notes:
Scrub all inputs strictly.
Spoof an authentication cookie
I think many of us have the experience that we don’t enter our user name and password while we can login a site as well. But not all of us know how they approach these. In fact, many applications will automatically log a user into their site if the right authentication is specified. Some times the cookies can be guessed if the algorithm for generating the cookie can be obtained. Some times the cookies are left in the client machine and can be stolen by exploiting another system vulnerability.
Notes:
Cookies should not be trusted, especially for administrative user.
SQL injection
Most systems on the internet are database-driven; these systems store and retrieve information from database by some keywords when we request a page. So we can do something via inputting some particularly literal, these literal consist of some keywords of SQL and something else will effect the SQL, and then we would get some information we cannot see normally. They call this “SQL Injection”.
SQL injection attacks represent a serious of threat to any database-driven site. The methods behind an attack are easy to learn and the damage caused can range from considerable to complete system compromise.
Fortunately, these threats can be totally prevent with a little common-sense and forethought.
For example, the system valid a user by SQL SELECT * FROM user_data WHERE last_name = 'Your Name' , and the Your Name is user inputted. If we inputted name like: “yaogao' or '1'=' 1” , what would happen? We might see all users and their detail information.
If we allowed users to input only letters in alphabet, our system would be safe under this condition.
Notes:
Just validate them. I think regular expression is a good choice.
Bypass a fail open authentication scheme
Most of all login a site via our username and password, and the system will check the username and password. Think about what if the check mechanism is broken? This may allow someone to login without username and password. People call this phenomenon “fail open”. The term “fail open” describes a behavior of a verification mechanism. This is when an error occurs during a verification method causing that the method to evaluate to true. This is especially dangerous during login.
For example, the following code will cause the system “fail open”.
try
{
username = s.getParser().getRawParameter( USERNAME );
password = s.getParser().getRawParameter( PASSWORD );
// if credentials are bad, send the login page
if ( !"webgoat".equals( username ) || !password.equals( "webgoat" ) )
{
s.setMessage( "Invalid username and password entered." );
return ( makeLogin( s ) );
}
}
catch ( Exception e )
{
// The parameter was omitted. set fail open status complete
if ( username.length() > 0 && e.getMessage().indexOf( "not found") != -1 )
{
if ( ( username != null ) && ( username.length() > 0 ) )
{
makeSuccess( s );
return ( makeUser( s, username, "Fail Open Error Handling" ) );
}
}
}
Notes:
Test is important, code review is indispensable as well.
Denial of Service
Our server is not omnipotent, so many sites allows only definition count of user to login. If the all of the connection were consumed, the server would refuse to accept any request. This is “DoS”.
Notes:
Can anyone kindly tell me how to prevent DoS? I don’t think it is not responsibility of application only. Network administrator should take their responsibilities too.
Summary
Think about all topic talked above, we would realize we needn’t to write any complex code or do something difficult to prevent vulnerabilities.
There are two principles:
First, check all inputs from client.
Second, code view is indispensable.
2006-07-22 Neusoft