User Input Vulnerabilities

All Web applications perform some action based on user requests. You should determine what is valid data and reject all other input.

The following example is based on Active Server Pages (ASP) code from a Web site that recommended Web site designers use the following Microsoft® JScript® code in their ASP-based applications to implement forms-based authentication:

// Get the username and password from the form.
if (isValidUserAndPwd(Request.form("name"),
                      Request.form("pwd"))) {
    Response.write("Authenticated!");   
} else {
    Response.write("Access Denied"); 
}

function isValidUserAndPwd(strName, strPwd) {
    var fValid = false; 
    var oConn = new ActiveXObject("ADODB.Connection"); 
    oConn.Open("Data Source=c:\\auth\\auth.mdb;");
   
    var strSQL = "SELECT count(*) FROM client WHERE " + 
        "name='" + strName + "' " + 
        “ and pwd='" + strPwd + "'"; 
    var oRS = new ActiveXObject("DODB.RecordSet");
    oRS.Open(strSQL, oConn);
    fValid = (oRS(0).Value > 0) ? true : false;

    oRS.Close(); 
    delete oRS;
    oConn.Close();
    delete oConn; 

    return fValid;
}

Below is the client code used to send the username and password to the JScript code by using an HTTP POST:

<FORM ACTION="Logon.asp" METHOD=POST>
    <INPUT TYPE=text MAXLENGTH=32 NAME=name>
    <INPUT TYPE=password MAXLENGTH=32 NAME=pwd>
    <INPUT TYPE=submit NAME=submit VALUE="Logon">
</FORM>

The user enters a username and a password by using the HTML form shown above and then clicks the Logon button. The ASP code uses the provided username and password to build a SQL statement to query a database. If the number of rows returned by the query is greater than zero—SELECT count(*) returns the number of rows returned by the SQL query—the username and password combination are valid and the user is allowed to log on to the system.

Both the client and server code are flawed, however, because the solution takes direct user input and uses it to access a database without checking whether the input is valid. In other words, data is transferred from an untrusted source—a user—to a trusted source, the SQL database under application control.

Assume a non-malicious user enters his name, "Blake," and the password "$qu1r+," which builds the following SQL statement:

SELECT count(*) FROM client 
WHERE name='Blake' 
AND pwd='$qu1r+'

If this is a valid username and password combination, count(*) returns a value of at least 1 and allows the user access to the system. The query could potentially return more than 1 if two users exist with the same username and password or if an administrative error leads to the data being entered twice.

Because the username and password are unchecked by the ASP application, the attacker can send any input.

See Also

Do Not Trust User Input Directly

Copyright © 2005 Microsoft Corporation.
All rights reserved.