Results 1 to 1 of 1

Thread: [Computer Security] Defensive programming for web applications.

  1. #1

    Thread Starter
    Hyperactive Member Maven's Avatar
    Join Date
    Feb 2003
    Location
    Greeneville, TN
    Posts
    322

    [Computer Security] Defensive programming for web applications.

    The first rule of programming is to never ever trust the user. In fact, one should make the worse case assumption about users. In computer security, we call this assumption defensive programming. Defensive programming is especially important in the development of web applications because they live in a client-server environment, and they accept connections from the wilderness of the internet. In addition, there are security concerns when web applications take input, process information, and display output. If programmers let their defenses down at any step, hackers will be able to break into the systems. Fortunately or unfortunately (depending on your take), these steps are tightly coupled with user input. The good news is that we at least know what to watch very closely.

    Databases are the primary way web applications provide persistent storage capabilities. Many web sites are written in a language like PHP and access a 3rd party database like MySQL by interfacing over a connection and issuing SQL statements. These SQL statements must be parsed by the database, and it doesn't care what applications send it; instead, it relies on the application developers to distinguish between SQL commands and user data. For these examples, I'm going to use PHP; however, they apply to any language interfacing with a database. So lets take a look at some code:

    Code:
    $var = $_GET['var'];
    $query = $myPdoObject->query("select * from mytable where info=$var");
    The above code takes information sent by the user over a get request and uses it inside of a where clause. This code opens up the web application to SQL injections. Why? The user could send a subqueriy instead of the data you expect him or her to send. He could complete the statement and start a whole new SQL statement.

    **Never ever put unescaped user data directly into a sql statement; instead, use prepared statements:

    Code:
    $var = $_GET['var'];
    $query = $myPdoObject->prepare('select * from my table where info=?');
    $query->bindParam(1, $var);
    In the above code, the separation of user data and SQL commands is guaranteed.

    Unfortunately, prepared statements don't always solve the problem. For example, suppose we want to have pagination functionality that allows the user to order his or her results. We need to use an order by clause in our query, but we can't do this through prepared statements alone. Prepared statements work because it allows the database to make a plan before executing statements. When we change the order on the fly, we result in different plans. So we are really talking about different sql statements.

    Code:
    $order = array(1=>'someField ASC', 2=>'someField DESC');
    $userOrder = $_GET['order'];
    
    if (isset($order[$userOrder]))
    {
    $sql = "select * from my table where info=? order by " . $order[$userOrder];
    } else {
    // either no order was selected or the user tried to give me bad data.
    $sql = "select * from my table where info=?";
    }
    $var = $_GET['var'];
    $query = $myPdoObject->prepare($sql);
    $query->bindParam(1, $var);
    In the above code, I'm using an array to hold the proper order by clauses. I only allow the user to select one of the elements in the array that contains the order by clause.

    The above trick is also very important in the processing stage. Take a look at the following code:

    Code:
    $var = $_GET['var'];
    $someInfo = eval($var);
    The above code has the same problem as the SQL statements. We're praying that the user doesn't try to hack us by issuing commands to eval to get control of our whole system.

    If you really need to use eval, don't let the user decide any part of it! Use the array trick we used above. Provide options for the user, and allow him or her to select from those options. You write the statement that goes inside eval.

    Code:
    $var = $_GET['var'];
    $data = $_GET['data'];
    $outfile = fopen($var, 'w');
    write($outfile, $data);
    fclose($outfile);
    Here we have another example of code that is insecure. Here the code is assuming that the user will be kind and give the correct filepath+filename. They could insert any type of file at any location. If you need to use a pattern like this, you need to carefully escape the string they provide. Don't allow any directory changing characters (/\.). In addition, it's also a good idea to escape the data before you insert it to the file. They could be writing shell code for all you know.

    Another example related to the above, don't trust user uploads. Suppose we want to allow users the ability to upload a picture to a gallery. We shouldn't just move_uploaded_file to some location and start including it on web pages; instead, we should first make sure the user supplied us with an image. In addition, we can't trust the extension to be accurate. Anyone can rename a exe file to a jpeg file.

    Check the mine types of the file before accepting it into the system.

    Code:
    $img_info = getimagesize($imgfile);
    		
    // if our img_info is valid
    if ($img_info !== false)
    {
    // Provide names for the information in the size array.
    $fullWidth = $img_info[0];	// width of image
    $fullHeight = $img_info[1];	// height of image
    			
    // get the image type
    switch($img_info[2])
    { 
    case IMAGETYPE_JPEG:  
               $imageType = "jpg";
               break;   
    default:
     throw new Exception("OMG NOT A JPEG");
    } // end switch
    
    } else {
    // not a image at all
    }
    In a basic nutshell, any kind of resource being used by the application needs to keep a tight lid on user input. Resources like databases, file systems, API statements like eval, or networking can be exploited through bad user input. In addition, hidden fields on forms don't add anything to security. All of the information submitted by a form can be altered by a user.


    Outside of dealing with resources, a word or two needs to be said about output. Don't trust data that came from users even when it is sitting on a database. In php, use functions like HTMLSPECIALCHARS() to output data to a browser. Otherwise, they might put in javascript that will be executed when a browser loads the page. Imagine the kinds of problems that can occur in a site like vbforums if a single user could make a post that executed javascript.

    Finally, these principles are important across programming languages. Always use defensive programming even if your just starting out. Eventually, it'll become second nature.
    Last edited by Maven; Jun 28th, 2014 at 04:59 PM.
    Education is an admirable thing, but it is well to remember from time to time that nothing that is worth knowing can be taught. - Oscar Wilde

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  



Click Here to Expand Forum to Full Width