Web sites are a common form of front-end for system nowadays, and I can say I’ve hacked a decent deal these few years to understand the common flaws of system security on the Internet. I introduce some of the most common ones often displayed by amatuer programmers. If you’re concerned about the security of your web site, some of these might become standard test cases (or even white box testing).
SQL injection occurs when you accept un-validated free-text input and run it against the database. Consider this simple query:
"SELECT * FROM User WHERE id='" +id+ "' AND pwd='" +pwd+ "' AND Active=1"
Simple query to authenticate a user during login. Results are returned if the userid/password combination is correct. However, consider the following input:
id = "admin"
pwd = "' OR 1=1 --"
If the strings passed in were not checked, the effective query run becomes
"SELECT * FROM User WHERE id='admin' AND pwd='' OR 1=1 --' AND Active=1"
This allows the hacker to login as admin, without knowledge of the admin’s password. This is because the clause OR 1=1 is always true therefore all records are returned. the — indicates SQL comments after and are ignored.
The standard solution to SQL injection, is known as escaping. This means altering the special characters in the string, so that they mean literal characters in the query. For SQL, this requires replacing single-quotes with double-single-quotes, etc. The resulting queries actually checks that “‘ OR 1=1 –” is the user’s password.
Depending on your choice of language, this may be done in different manners. For PHP, there’s the mysql_escape() function that automatically escapes the special characters. For Java (JDBC), use the PreparedStatement.setString() to ensure that strings are escaped properly. For other languages that do not provide such services, you can always search for such functions already written by others, or write your own escape function to perform reasonable escaping.
Doing server-side only validation is correct, but not efficient. The server may be spending more time rejecting invalid requests due to simple blank fields, resulting in slower responses for the valid requests.
Therefore if any developer question where should the validation be done? at the browser (client) side or the application (server) side? The answer is both. It may seem duplication of code (violating code reuse), but it is necessary for security (and correctness).
Code injection works the same way as SQL injection. User is allowed to enter unchecked free-text, which is later displayed on the web site itself. Example of such web apps include guestbooks, blog comments, and forums.
Imagine a user entering this in a JSP-based forum:
"Hi guys <% File roots = File.listRoots(); ... ; out.println(...); %>"
When the code goes unchecked and displayed, arbitrary java code is being executed on the server. This may result in information leak (passwords/system info), information corruption (update/delete), or even server takeover (using the server to perform other hacking tasks).
Similar to SQL injection, free-text input MUST be escaped after entering the application.
Security by Linking
Some developers implement “security” by not allowing the user to reach a page by not linking it to any of the accessible pages. This is not sufficient, as the hacker can type the URL directly in the address bar to access the page.
For example, http://yourweb.com/admin/changepass.jsp is only linked from http://yourweb.com/admin/menu.html, which is only shown when the user logs in as admin. However, there’s no stopping the hacker from typing these URLs directly in the address bar, thus able to access this pages and perform the related functions on the server. (assuming the server also relies on linking from the JSPs)
Authenticated pages need to authorise the user for every page the user visits. Both the menu.html and changepass.jsp pages mentioned above NEED to verify that the user has admin rights before showing the page to the user. Similarly, Server functions need to verify the user’s authority before attempting to perform any function. Doing so can prevent a variety of HTTP Direct hacks as well.
This problem is less seen, but nonetheless demonstrates cookie hacking. The application verifies that the user has logged in by writing the username into a cookie. The web app later retrieves this cookie to determine who is user logged in.
The cookie can be easily edited by any hacker, since it is a little file stored on the system. By changing that username, the user can pose as any other user.
Other than writing username, cookies may also pose other problems, for example when admin=0 is used as a cookie, or lastVoteTime=…. for a voting web-app that only allows users to vote once every X mins.
Sessions should be used to implement such properties that needs to be associated with each user. Session libraries that are ready-made in most languages (PHP/Java/.Net) provide excellent implementations. Since sessions only store a single Session ID as a cookie on the client, the hacker can do nothing with the id. Adding properties does not affect the result, and changing the sessionid does not help, unless he knows the id of another logged in user.
Should the language not support sessions (or if you’re writing your own web server), you can implement your own sessions using cookies. Store a map from a String to a Collection, and issue a SessionID as a cookie to the user. The SessionID should be used as the key for the map, and the Collection contains all the objects you wish to associated with the user. As mentioned, the SessionID MUST NOT be sequential (it should appear random), otherwise a hacker may modify the sessionid in his cookie to impersonate the next or previous person who is logged in.
The most powerful of all web attacks, is by using the HTTP protocol directly. It can bypass all security measures that depend on the HTTP protocol. Since all web pages are displayed and processed using HTTP, every web request is a HTTP request. The hacker can send any header and any query string or post data in this mode.
For example, if your web site depends on the HTTP_REFERER header to ensure that this request was sent from your web site, this can be spoofed by sending a direct HTTP request. Although this technique is not safe, it is still used by some applications to fend off simple hackers. The information in that application system is usually not critical, and such techniques are sufficient.
This requires all your server-side validation checks and authorisation checks to be in place. Defending against such attacks require you to have knowledge of the HTTP protocol itself and how you can attack a system. Only with the knowledge and white box testing you will be able to spot possible hacking channels, without employing a security professional.
Web applications, when not designed and developed properly, can be exposed to hackers. Whether for fame or money, these consequences are not desired by the company. All web developers should be aware of these methods, code against them naturally, and perform tests to check for vulnerabilities constantly.
The problems and solutions presented here are only the tip of the iceberg. These examples are only a few of the programming related security issues, and there’re many other non-programming issues like framework security or networking and OS bugs. Security is only as tight as its weakest link, so all the problems need to be considered together if security is of importance to your application.