Simple Ways to Add Security to Web Development

As a software developer myself, I have seen developers rushing to finish the feature they are assigned to, with little or no consideration for security in the code—no security guidelines, no coding standards, just a mad dash to finish the feature. Next comes the security review, in which the software obviously fails, and then comes the security-hardening phase.

Although trying to improve code's security obviously is a nice thing to do, the time when it commonly is done is often in the final code development phase, and as with the basic nature of software development, changing the code almost always leads the software away from maturity. So, the software that has almost ended its development phase is again pushed to instability during the security-hardening phase. Is this really necessary?

Why can't developers make the code secure in the first place? What can be done to make developers more aware of application security policies, so they are more informed and alert when they develop their next application? In this article, I discuss how developers can do so effectively.

One simple way is to change developers' coding styles and make them write code that is inherently secure. Also, following simple policies related to application security can make a lot of difference. This is sometimes not a very easy thing to do, but if the practices to follow are simple and easy to adopt, it is not very difficult.

Let's look at some security concerns/flaws typically found in software and the corresponding security mechanisms and policies that can be applied to counter them. These mechanisms generally can be implemented in all programming languages and follow the OWASP code development guidelines. But, for the sake of open-source culture, I use PHP as the language for the examples in this article.

SQL Injection

Let's start with the most famous of the lot. It is also one of the most widely used and one of the most simple for unleashing attacks on the Web. What many people don't know, however, is that it's easy to prevent as well. Let's first consider what an SQL injection attack is.

Suppose you have a text box in your application for a user name field. As the user fills it in, you take the data to the back end and fire a query to the database—something like this:


<Input Type = "Text" value ="username" name = "username">

<?php $username = $_POST['username']; ?>

Then, the SQL query:


SELECT * FROM table WHERE name = '" + $username + '"

A simple way to attack this system would be to type "'" or "'1'='1" in the text box. The resulting database query now will be:


SELECT * FROM table WHERE name = '  ' or  '1'='1'

As you can see, this condition always is true and when executed, the query will just split out all the rows in the table. This was a simple example, but in real-life scenarios, such attacks are very severe and can take down a whole application in a few seconds, because they are targeted directly at the database.

So, how can you prevent this? Simple logic is that instead of passing the input taken from the front end directly, it should be checked thoroughly and only then sent to the database as a part of the query. Here are the most common and effective ways to do that:

Parameterized Queries: such queries result in exactly the same way as normal SQL queries, but the difference is that here you need to define the SQL code first and then pass the parameters to the query later. So, even if someone tries to attack by passing malicious data to the query, the query searches for the exact match of whatever is sent as input. For example, if someone tries to pass ' or '1=1 as the data, the query will look up the DB for a literal match of the data.

Here is an example of how to write parameterized queries in PHP (see your programming language manual for more about parameterized queries):


/* Prepared statement, stage 1: prepare */
if (!($stmt = $mysqli->prepare("INSERT INTO test(id) VALUES (?)"))) {
 echo "Prepare failed: (" . $mysqli->errno . ") " . $mysqli->error;
}

/* Prepared statement, stage 2: bind and execute */
$id = 1;

if (!$stmt->bind_param("i", $id)) {
    echo "Binding parameters failed: (" . $stmt->errno . ") " .
$stmt->error;
}

if (!$stmt->execute()) {   
    echo "Execute failed: (" . $stmt->errno . ") " . $stmt->error;
}

So, the next time you need to look up the database, use a parameterized query for it. But beware, this approach has a downside as well. In some cases, doing this can harm performance, because parameterized queries need server resources. In situations where an application is performance-critical, there are other ways to counter SQL injection attacks.

Stored procedures: this is another commonly used method for countering SQL injection attacks. It works the same as parameterized queries, the only difference being that the procedure or the method is itself stored in the database and called by the application when required. Here's how to write a stored procedure in PHP for MySQL:


/* Create the stored procedure */
if (!$mysqli->query("DROP PROCEDURE IF EXISTS p") ||
    !$mysqli->query("CREATE PROCEDURE p(IN id_val INT) 
     ↪BEGIN INSERT INTO
test VALUES(id_val); END;")) {
    echo "Stored procedure creation failed: (" . $mysqli->errno . ") " .
$mysqli->error;
}

/* Call the stored procedure */
if (!$mysqli->query("CALL p(1)")) {
    echo "CALL failed: (" . $mysqli->errno . ") " . $mysqli->error;
}

This approach is equally effective in preventing SQL injection as the parameterized queries method I mentioned earlier, so you can decide which is better for your situation.

Escaping user supplied input: in this approach, user input is manually (or sometimes with the help of DBMS escaping mechanisms) escaped for valid strings, thus minimizing any chance of SQL injection attacks. Although it is bit weaker than other approaches, it can be useful in cases where you want better performance or are rewriting legacy code and want to finish with lesser effort.

PHP provides an automatic input escape mechanism called magic_quotes_gpc that you can use before sending the input to the back end. But, it would be better to use the escaping mechanism provided by your database, because in the end, the query comes to the database, and the database will know better about what is a valid query. MySQL provides the mysql_real_escape_string() method to escape the input. Check your database documentation to find which escape function is supported.

______________________

Webinar
One Click, Universal Protection: Implementing Centralized Security Policies on Linux Systems

As Linux continues to play an ever increasing role in corporate data centers and institutions, ensuring the integrity and protection of these systems must be a priority. With 60% of the world's websites and an increasing share of organization's mission-critical workloads running on Linux, failing to stop malware and other advanced threats on Linux can increasingly impact an organization's reputation and bottom line.

Learn More

Sponsored by Bit9

Webinar
Linux Backup and Recovery Webinar

Most companies incorporate backup procedures for critical data, which can be restored quickly if a loss occurs. However, fewer companies are prepared for catastrophic system failures, in which they lose all data, the entire operating system, applications, settings, patches and more, reducing their system(s) to “bare metal.” After all, before data can be restored to a system, there must be a system to restore it to.

In this one hour webinar, learn how to enhance your existing backup strategies for better disaster recovery preparedness using Storix System Backup Administrator (SBAdmin), a highly flexible bare-metal recovery solution for UNIX and Linux systems.

Learn More

Sponsored by Storix