Errors Not Specific to a Particular Programming Language [2]

File Uploading Errors

Earlier in this chapter, I described typical errors in PHP scripts that implement file uploading by the user. These don't exhaust dangerous situations. There are a few common mistakes that a programmer can make in scripts, and they aren't related to a particular programming language.

Embedding Shell Code

The most dangerous, easily exploited, and frequent mistake involves allowing a user to upload any file into a directory on the Web server.

For example, users may be allowed to attach any file to their messages in the forum. These files should be accessible using HTTP; otherwise, such a procedure would be pointless.

Suppose that the user is allowed to upload any file with any extension. In this case, the mistake is that some extensions can be associated with certain interpreters. For example, the PHP and PHP3 extensions are associated with the PHP interpreter.

To exploit this vulnerability, the attacker just needs to create a PHP script in a file with the PHP or PHP3 extension and upload it to the server using the available Web interface. For example, he or she is likely to upload PHP shell code to execute any commands on the server. Then the attacker will request the uploaded document using HTTP, and if the document's extension is associated with the PHP interpreter, the document will be executed as a script rather than returned to the client.

It doesn't matter, in which language the script is written. It is important, however, that its extension is associated with the PHP interpreter.

Sometimes, the check for the correct extension of files sent by users is done with a JavaScript function on the client. If you offer users a form to use when uploading files and check the validity of the file name using JavaScript tools, the file won't be uploaded when its name is invalid.

As with other actions on the client, you shouldn't trust this check. The user can easily circumvent it by disabling JavaScript in his or her browser.

Suppose that the attacker wants to circumvent your checks but doesn't want to disable JavaScript. What could the attacker do?

Before the form is sent to the server, the onSubmit event is triggered, and a JavaScript function puts a special value into a hidden field. The receiver application checks whether this field contains this value. It receives the files only if the check returns the positive result. Thus, the program makes sure that JavaScript isn't disabled on the client browser and that the extension of the file is valid.

However, nothing prevents the attacker from creating an HTTP POST request to the target server with the correct value of the special parameter and malicious file contents. No check will be performed in that case.

Using this vulnerability, the attacker can easily upload a PHP shell script. When uploading a Perl shell script, the attacker would need to be aware that in Unix-like operating systems a Perl script sometimes should have rights for execution. It would be impossible to the attacker to create a file on the server with necessary access rights by exploiting this vulnerability.

The attacker also would need to remember that in Unix-like operating systems the character with the OA code is used to denote a new line and that in Windows the ODOA two-character sequence is used. When a Perl script is executed as a CGI application, a 1-byte linefeed indicator is important. Otherwise, the operating system won't detect the interpreter.

To protect your applications from this type of attack, stick to the following rule:



Rule

Don't allow users to upload files into a directory available using HTTP. The name of the uploaded file should belong to a fixed set of valid names. The set should be thoroughly specified depending on the task and taking into account that the uploaded files should be available only for reading, not for execution. If the set of valid names includes files with dangerous extensions such as PHP, CGI, or PL, execution of such files should be barred using other methods.

In any case, you should stick to the following rule:



Rule

Don't trust any data received from a user. Don't assume that applications on the cl lent work correctly and return valid results. (It would be best to assume they don't work at all.)

The best policy in this situation would involve discarding the file name given by the user, assigning another name, and informing the user about this new file name.

Consider an example: Suppose that files are uploaded into a directory inaccessible using HTTP. The http://localhost/2/13.php script can be an example of a script uploading files. After a file is uploaded, the user is given the link to a script that takes a file name as a GET HTTP parameter. This script reads the specified file from the directory inaccessible using HTTP and sends the file to the user's browser. Thus, uploaded files can have any extension, including PHP. The contents of a file, not the result of its execution, will be returned to the user.

Here is an example of a script that outputs a requested file.

http://localhost/2/18.php

<?

if(!empty ($file))

{

$f=fopen("./upload/$file", "r");

while($r=fread($f, 1024))

echo n12br(htmlspecialchars($r));

}

else

{

echo "

<form>

Enter the file name please

<input type=text name=file>

<input type=submit value=Return>

";

}

?>

Therefore, if the ./upload/ directory is protected from access using HTTP, the user will be unable to upload and execute PHP shell code. Any uploaded file will be returned unprocessed to a client who requested it. However, the script that returns the contents of the file contains an error. The attacker can include the directory bypassing sequence into the file name to read any file in the system.

A similar situation can take place if the name of the requested file is changed on the server and sent as a parameter to a vulnerable script. For example, the following directive of Apache's mod_rewrite module can be used:

   RewriteRule ^/2/upload/(.+)$ "/2/18.php?file=$2"

It will convert all requests in the http:/localhost/2/upload/testfile.txt format to the http://localhost/2/18.php?file=testfile.txt format.

This will introduce implicit dynamics into the system. A request to a file that seems static will eventually turn into a request to the PHP script that outputs the contents of the file to the browser.

Because of the directory-bypassing vulnerability contained in the script, the attacker can read any file in the system using an HTTP request like the following:

http://localhost/2/upoad/../18.php

This request returns the contents of the 18.PHP file to the attacker.



Warning

The mod_rewrite module isn't enabled on the CD-ROM that accompanies this book. This example won't work in the test system and is given here just for illustration.

Writing into Any Directory

There is another mistake common to many scripts that process file uploading.

Consider an example that is a modification of an example already familiar to you.

http://localhost/2/19.php

<form enctype="multipart/form-data" method=POST

action=http://localhost/2/19.php>

<input type=hidden name=MAX_FILE_SIZE value=10000>

Send this file: <input name=userfile type=file>

<input type=subbmit value="Send File">

</form>

<?

if (!empty($_FILES["userfile"]["tmp_name"]))

{

if (move_uploaded_file($_FILES["userfile"]["tmp_name"],

"./upload/{$_FILES["userfile"]["name"]}")) {

{

echo "<br> <br>

File is uploaded <a

href=\"./upload/{$_FILES["userflie"]["name"]}\">

./upload/{$_FILES["userfile"]["name"]}</a>";

}

}

?>

This script uses the $_files array to prevent a user from substituting the name of the temporary uploaded file with the name of a target file in the system to access that file. The use of the move_uploaded_file() function guarantees that the file being moved was just uploaded using the HTTP POST method. The script uses the fact that the browser sends the original file name to the system without the path to it.

Look at the HTTP request sent to the server when a user tries to upload a file:

POST /2/19.php HTTP/1.1

Host: localhost

User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.0;

en-US; rv:1.7.2) Gecko/20040803

Accept: */*

Accept-Language: en-us;q=0.5

Accept-Encoding: gzip, deflate

Accept-Charset: windows-1251,utf-8;q=0.7,*;q=0.7

Keep-Alive: 3000

Connection: keep-alive

Referer: http://localhost/2/19.php

Content-Type: multipart/form-data;

boundary----------------------------491299511942

Content-Length: 321

<empty line>

-----------------------------491299511942

Content-Disposition: form-data; name="MAX_FILE_SIZE"

<empty line>

10000

-----------------------------491299511942

Content-Disposition: form-data; name="userfile";

filename="testfilename.txt"

Content-Type: text/plain

<empty line>

this is a test file

-----------------------------491299511942--

As you can see, this is an ordinary HTTP POST request. The body of the request consists of POST parameters, and the type of the body is multipart/form-data. This means the body consists of multiple parts.

The boundary=-----------------------------491299511942 line identifies a delimiter of the parts.

In this example, the body (contents) of the request consists of two parts corresponding to two POST parameters sent in the request. The first one is the MAX_FILE_SIZE parameter that tells the browser the maximum size of the file that will be sent, and the second parameter is the file itself.

In the filename="testfilename.txt" line, the browser tells the server the original file name in the client system. According to the HTTP specification, this is a file name without a path. However, nothing prevents the attacker from inserting the directory-bypassing sequence into the file name. Therefore, applications that use the name of the uploaded file as it is given are vulnerable to an attack that involves writing the uploaded file into any location.

Such an attack will be especially effective if the uploading script doesn't check the extension of the uploaded file, but the HTTP server doesn't permit execution of scripts located in the directory containing uploaded file. For example, this directory can be inaccessible using HTTP.

A successful exploitation of this vulnerability will allow the attacker to upload a malicious file into any directory available for writing to the user who started the HTTP server.

To bypass the directory in this example, it would suffice to change the filename="testfilename.txt" line in the HTTP request to a line such as filename="./../testfilename.txt". The attacker would also need to change the Content-Length field.

The attacker can create a malicious HTTP POST request either using a program such as telnet to connect the directory to the server or using special proxy servers that can change the HTTP requests that pass through them.

This vulnerability is extremely dangerous. File-copying functions used in scripts that upload files can rewrite the target file. Therefore, the attacker can use this vulnerability alone to deface the site, that is, to change its home page.

To write applications secure against this type of attack, specify the set of valid names for uploaded files so that they don't contain the directory bypassing sequence. You'll avoid dangerous situations if the name of the file on the server is generated by a script. If you have to leave the original file name, you should extract the name from the path. To do this, extract characters after the rightmost slash or backslash character.

Note that a PHP script vulnerable to writing uploaded files into any directory will remain vulnerable even if you follow all recommendations in the PHP documentation.

Attempting To Circumvent Extension Filters

After the attacker finds the vulnerability that allows him or her to upload files into any directory, he or she is likely to try circumventing filters for the extensions of uploaded files that can be implemented in the script.

Consider an example and try to circumvent extension filters.

http://localhost/2/20.php

<form enctype="multipart/form-data" method=POST

action=http: //localhost/2/20.php>

<input type=hidden name=MAX_FILE_SIZE value=10000>

Send this file: <input name=userfile type=file>

<input type=submit value="Send File">

</form>

<?

if (!empty($_FILES["userfile"]["tmp_name"]))

{

if (preg_match("/\.txt$/m", $_FILES["userfile"]["name"]))

{

if (move_uploaded_file($_FILES["userfile"]["tmp_name"],

"./upload/ {$ _FILES["userfile"]["name"]}"))

{

echo "<br> <br>

File is uploaded

<a href=\"./upload/{$_FILES["userfile"]["name"]}\">

./upload/{$_FILES["userfile"]["name"]}</a>";

}

}

else

{

echo "<font color=red>

Only text files can be uploaded</font>";

}

}

?>

This script uses a regular expression to check whether the received file has the TXT extension. If it doesn't, it isn't moved.

Try to use the technique already familiar to you: Use the null character in a string. Create an HTTP POST request sending a file, and change the file name so that it contains the desired extension followed by the URL-encoded null character and the .txt character sequence.

Send this request to the server:

   POST /2/20.php HTTP/1.1

Host: localhost

User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.0;

en-US; rv:1.7.2) Gecko/20040803

Accept: */*

Accept-Language: en-us;q=0.5

Accept-Encoding: gzip, deflate

Accept-Charset: windows-1251,utf-8;q=0.7,*;q=0.7

Keep-Alive: 3000

Connection: keep-alive

Referer: http://localhost/2/20.php

Content-Type: multipart/form-data;

boundary=---------------------------491299511942

Content-Length: 320

<empty line>

-----------------------------491299511942

Content-Disposition: form-data; name="MAX_FILE_SIZE"

<empty line>

10000

-----------------------------491299511942

Content-Disposition: form-data; name="userfile";

filename="test.php%00.txt"

Content-Type: text/plain

<empty line>

<? system($cmd); ?>

-----------------------------491299511942-



As a result of this HTTP request, a file with the Image from book TEST.PHP%00.TXT name will be created in the target directory. This is not what you expected. No URL-decoding was done.

Try to change the content type in the part of the HTTP request that contains this file. Substitute it with application/x-www-form-urlencoded.

Even if you change the header fields to the following values, you won't obtain the desired result:

   Content-Disposition: form-data; name="userfile";

filename="test.php%00,txt"

Content-Type: application/x-www-form-urlencoded

Remember that when you change these lines of the request, you also should change the Content-Length header.

So, the characters in the file name aren't URL-encoded. The only way to insert the null character into a file name is to insert it without URL encoding.

Because it is impossible to do this in a program like telnet, a special script is needed to send an appropriate HTTP POST request. Here is such a script.

http://localhost/2/21.php

<?

$in="POST /2/20.php HTTP/1.l\r\n".

"Host: localhost\r\n".

"User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.0; en-US; rv:1.7.2)

Gecko/20040803\r\n".

"Accept: */*\r\n".

"Accept-Language: en-us;q=0.5\r\n".

"Accept-Encoding: gzip, deflate\r\n".

"Accept-Charset: windows-1251,utf-8;q=0.7,*;q=0.7\r\n".

"Keep-Alive: 3000\r\n".

"Connection: keep-alive\r\n".

"Referer: http://localhost/2/20.php\r\n".

"Content-Type: multipart/form-data; boundary----------------------------

491299511942\r\n".

"Content-Length: 341\r\n\r\n".

"-----------------------------491299511942\r\n".

"Content-Disposition: form-data; name=\"MAX_FILE_SIZE\"\r\n\r\n".

"10000\r\n".

"-----------------------------491299511942\r\n"

"Content-Disposition: form-data; name=\"userfile\";

filename=\"test.php".chr(0).".txt\"\r\n".

"Content-Type: application/x-www-form-urlencoded\r\n\r\n".

"<? system($cmd); ?>\r\n".

"-----------------------------491299511942-\r\n\r\n";

$target="127.0.0.1"; // The IP address of the server or a proxy server

// used to send the request

$targetport=80; // The port of the server or a proxy server

$socket = socket_create (AF_INET, SOCK_STREAM, 0);

$result — socket_connect ($socket, $target, $targetport);

socket_write($socket, $in, strlen($in));

$0="";

while ($out = socket_read ($socket, 2048))

{

$o.=$out;

}

echo $o;

?>

The result of execution of this script will be a message informing you that up-loading of text files is allowed.

Additional investigation will show that this message occurs because the $_FILES["userfile"] ["name"] variable obtains the Image from book test.php value. That is, the fragment of the file name that follows the null character is discarded. In other words, you failed to embed the null character into the file name. Although this method doesn't work in this particular case, you shouldn't conclude that it will never work. Perhaps it will be suitable for another programming language or another Web server.

Embedding the null character into a file name is one of the most frequently used methods for circumventing filters and truncating file names after copying.

If you look closely at the piece of code that implements the filter in this example, you'll notice another mistake. The check for the valid extension is done using the /\.txt$/m regular expression. Remember that the dollar sign ($) is used in regular expressions to denote the end of a line. Here, the programmer hopes that only files with the TXT extension will pass the check.

However, a string can contain multiple lines. The m modifier indicates that the string is multiline. In other words, it can contain several linefeed characters, and the "$" character will match each of them.

The next example demonstrates how the m modifier affects a regular expression.

http://localhost/2/22.php

<?

if(preg_match("/\.txt$/m", "test.txt\n.php")) echo "1";

if(preg_match("/\.txt$/m", "test.php\n.txt")) echo "2";

if(preg_match("/\.txt$/", "test.txt\n.php")) echo "3";

if(preg_match("/\.txt$/", "test.php\n.txt")) echo "4";

?>

This script outputs the numbers 1, 2, 3, 4. Therefore, you can suppose that you can circumvent the file extension check in systems, in which a file name can include the linefeed character, for example, in Unix-like operating systems.

As practice shows, it is impossible to circumvent this check in both Unix and Windows. However, you didn't test every possible combination of an operating system, a file system, and an HTTP server. Therefore, you cannot say that this technique will never work.

An attacker is always likely to test this file extension check by inserting certain characters into file names.

Circumventing File Size Checks

An HTTP POST field of a form uploading a file should contain the MAX_FILE_SIZE hidden parameter, which is a recommendation for the browser not to upload larger files. This is just a recommendation, and you cannot predict the client's behavior. What's more, a POST request can be created with a tool other than a browser. In this case, you shouldn't assume that the uploaded file has the recommended size.

The file can have any size, with the MAX_FILE_SIZE value remaining original.

In the simplest case, the attacker just needs to save the page containing the form on the hard disk and edit the MAX_FILE_SIZE value and, possibly, the action parameter of the form to allow his or her browser to upload a large file, thus bypassing the restriction.

When the size of uploaded files is important, you should use other methods to restrict file sizes. For example, you could specify the maximum size of uploaded files or the maximum size of HTTP POST requests in the PHP interpreter's settings. In addition, you can copy an uploaded file from the temporary directory to its final location only if the size of the temporary file doesn't exceed the maximum.

Sending Files Using the Web Interface

Some mail services (both paid and free) allow their users to send and receive e-mail through a Web interface. One or more files can be attached to such e-mail messages.

Because a user can upload files onto the server, all the vulnerabilities described earlier exist here. To exploit one of these vulnerabilities, the attacker can create a message with an attached file that has a dangerous extension or malicious code and send the message to his or her e-mail address. If the e-mail service just copies attached files to a location on the server, it will have the vulnerabilities described earlier.

Making a General Investigation

After the attacker obtains access to a system that allows its users to upload files on the server, he or she is likely to try to find as much information about this vulnerability as possible. The attacker is likely to investigate the system to find answers to the following questions:

  • Is the file name generated automatically, or is the original file name accepted? All the methods for circumventing protection described earlier work only if the original file name is kept on the server.

  • Is the file stored in the file system or in a database? In the latter case, an attack that bypasses directories would be pointless.

  • Are there restrictions on file extensions? If so, the attacker is likely to try circumventing these filters.

  • Is the requested file output unprocessed, or are its contents displayed with a script? The attacker would need to keep in mind that the name of the requested document can be changed on the server. For example, the mod_rewrite module can be used in Apache. In this case, a user will believe the requested document is output directly even though its body is generated with a script.

  • Is any file extension associated with an interpreter on the server? It would make sense to substitute an extension and write shell code into a directory only when at least one extension is associated with an interpreter.

After the attacker answers these questions, he or she will try all suitable methods for collecting as much information about the system as possible and obtaining high privileges to destroy the system or control it.

Remember that if the system also has the local PHP source code injection vulnerability and the attacker can upload files on the server, he or she will be able to exploit this vulnerability by uploading malicious code inside a file and including this code into a script.

The Referer and X-FORWARDED-FOR Header Fields

The header of an HTTP request is generated entirely by the client according to HTTP. Therefore, you shouldn't trust any field of this header.

Many programmers make mistakes by assuming that certain fields in an HTTP request will have expected values. A vulnerability will appear after the attacker creates an HTTP request and assigns these fields malicious values.

The Referer Field

Referer is a field of an HTTP request that tells, from which URL address the user moved to the current page.

The programmer can mistakenly assume that if the value of this field is the address of a document on a friendly server, then the data contained in the request are received from a form generated by the server. For example, it is common that any data contained in a request are accepted only when the value of the Referer field is a page on the current server.

With such a method, the programmer protects the system against a situation, in which a user saves the page on the disk, edits the values and types of certain parameters, and sends the request to the server from the modified form.

Parameters hidden from the user in a form are dangerous when the programmer doesn't filter them, assuming that the user cannot change them so that the Referer header field still points to the current site.

This is often true for some versions of some free forums. The code of one well-known forum has a vulnerability of the MySQL source code injection type. However, this vulnerability cannot be exploited directly from the browser without the use of other tools because the vulnerable script checks the value of the Referer header field of an HTTP request.

Another common mistake is that the programmer doesn't appropriately filter the values of form parameters that have fixed sets of values, for example, checkboxes, radio buttons, and drop-down lists.

Regardless of whether or not the programmer implements the check of the Referer field for validity, the attacker can create an HTTP request by connecting directly to the server using the telnet program, another program, a script that generates any HTTP request (like that described at the beginning of the chapter), or a special proxy server that will change the contents of the header field spontaneously. An example of such a proxy server is the Proxomitron program.

I'd like to give you the following recommendation concerning secure programming in this situation: Don't rely on the check of the Referer field of the HTTP request as sufficient protection. Moreover, it makes little sense to perform this check, because it can be easily circumvented by the attacker and doesn't add security to the system. At the same time, this check can reject a few valid users. Sometimes, common proxy servers delete the Referer field from the HTTP request, or special programmers installed on the client delete this field. In these cases, the users won't be able to work with the system.

This isn't a wrong policy. The user should have the right to decide whether he or she wants to submit to every visited server the URL of a document he or she viewed previously. So, you shouldn't reject such clients.

The X-FORWARDED-FOR Field

x-FORWARDED-FOR is a field of the HTTP header, in which a proxy server can pass the IP address of the client.

Remember, if a client connects to the HTTP server using a proxy server, the IP address of the proxy server, rather than that of the client, is sent to the HTTP server. This is because the proxy server, not the client, establishes the direct connection to the HTTP server.

In this situation, nonanonymous proxy servers can send the IP address of the client within the X-FORWARDED-FOR field of the HTTP header. In addition, the IP address of the client can be sent within the CLIENT-IP field.

When checking for a client's IP address in a script, programmers often make a mistake when they prefer these header fields to the IP address, assuming that this address is a proxy server's address.

Consider an example of a vulnerable script.

http://localhost/2/23.php

<?

$ip=$_SERVER["HTTP_CLIENT_IP"];

if(empty($ip)) $ip=$_SERVER["HTTP_X_FORWARDED_FOR"];

if(empty($ip)) $ip=$_SERVER["REMOTE_ADDR"];

system("echo $ip >> iplog.txt");

echo "Your IP address was saved";

?>

First, the script tries to obtain the value of the CLIENT-IP header field written by the PHP interpreter into the $ SERVER [ "HTTP CLZENT_IP"] variable. Then, if the field is missing from the request or it is empty, the script tries to obtain the value of the x-FORWARDED-FOR header field written by the PHP interpreter into the $ SERVER [ "HTTP x FORWARDED FOR" ] variable. If this variable is also empty, the script obtains the desired information from the $ SERVER [ "REMOTE ADDR"] variable that contains the IP address of a client that established the direct connection to the server. Finally, the script writes the obtained value into the IPLOG.TXT file.

The idea behind this logic is that the script first tries to obtain the values of the fields that usually contain the IP address of the client. If the client connects to the server through a nonanonymous proxy server, one of these HTTP header fields will contain the IP address of the client, and the IP address will be saved in the IPLOG.TXT file. If the client connects to the server directly, the browser shouldn't send additional header fields such as CLIENT-IP or X-FORWARDED-FOR. As a result, the $ip variable will get the value of the $_SERVER [ "REMOTE ADDR"] , which is the IP address of the client.

In PHP, you can obtain the value of any HTTP header field from the $_SERVER array by specifying the name of the desired field in uppercase with the HTTP_prefix and with all hyphens replaced with the underscore characters.

This isn't the value of an HTTP header field. The value of this variable is set based on the IP address of the client directly connected to the server. If a proxy server is used, this will be the IP address of the proxy server. Therefore, if a user connects to the HTTP server through an anonymous proxy server, the proxy won't send the values of these header fields, and its IP address will be saved in the IPLOG.TXT file.

A key to understanding the cause of this vulnerability is that the browser shouldn't send the values of these header fields. With a direct connection to the server, nothing prevents the attacker from sending forged values of either HTTP header field (or both). In this case, the server will receive a fake IP address written, for example, into the X-FORWARDED-FOR header field, and write this value into the IPLOG.TXT file, rather than the IP address of the client.

Here is an example of an HTTP request that makes the server save a fake value in this file:

   F /2/23.php HTTP/1.1

Host: localhost

User-Agent: Mozilla/5.0 (Windows NT 5.0; en-US; rv:1.7.1) Gecko/20040707

Accept: */*

Accept-Language: en-us

Accept-Encoding: gzip, deflate

Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7

X-FORWARDED-FOR: not-valid-ip

Keep-Alive: 3000

Connection: keep-alive

As a result, the IPLOG.TXT file will contain the not-valid-ip line rather than an IP address.

This method will work if the described vulnerability is present and the attacker connects to the server directly. When using a proxy server, it can change the data sent by the attacker in the X-FORWARDED-FOR, header field; for example, it can add the IP address of the client to the forged value.

Another important vulnerability in this example is that the system() function is used to write an IP address into the log file. This function executes any command. When a user connects to the server directly or through an anonymous or nonanonymous proxy server, this function behaves as expected because the value of this field is an IP address that doesn't contain dangerous characters.

However, if an attacker creates a malicious HTTP request, somehow changes the current request, or sends the request through a malicious proxy server, he or she will be able to insert certain control characters of shell code and then execute any code on the server with the rights of the user who started the Web server.

The vulnerability, in which the system() function takes a parameter that can be affected by a remote user, was described earlier in this chapter.

To protect your system from an attacker's ability to change the values of this header, you can use a few approaches. Don't use the values of these headers for identification of the sender's IP. Alternatively, save both these values and the value of the $ SERVER [ "REMOTE ADDR" ] variable, which is the client's IP address (i.e., give these values equal rights).

It is pointless to use the values of these header fields because the attacker can hide his or her computer's IP address if desired. For example, the attacker can use an anonymous proxy server. If you use these HTTP header fields, your system will be vulnerable to an attack that sends a forged value as an IP address.

So, when you write code responsible for obtaining the client's IP address, stick to the following rule (unless you have serious reasons to ignore it):



Rule

Don't use the values of the HTTP X-FORWARDED-FOR and CLIENT-IP header fields for identification of the client's IP address.

Disclosing Other Information

Disclosure of a path is the least dangerous vulnerability that can be present in scripts and programs available using HTTP. This vulnerability allows the attacker to know the exact locations of scripts and programs on the server.

This knowledge isn't dangerous per se. The vulnerability just discloses certain information about the server. It cannot be used for a direct attack on the server. Such vulnerabilities cannot be used by the attacker to obtain higher privileges in the system, gain unauthorized access to it, or destroy it.

However, even this minimal information can make it easier for the attacker to exploit other vulnerabilities in the system.

With certain vulnerabilities related to obtaining access to files, the attacker needs to know the absolute file paths on the server. For example, he or she sometimes needs to know the absolute paths to executable scripts on the server to obtain the code of these scripts.

In addition, if the attacker knows the absolute path to a document available using HTTP, he or she sometimes can make assumptions about the server file system, its type, or the operating system.

For example, if the absolute path includes the disk name (e.g., C:/www/index.php), the attacker can be sure this is Windows. If a path contains a user or other attributes (e.g., /usr/clients/andrew/http/), it will indicate that the site is on a hosting server.

System error messages that appear during execution of a script also disclose certain information. For example, the attacker can know the version of the SQL server:

   Warning: mysql_fetch_object(): supplied argument is not a valid MySQLErrors Not Specific to a Particular Programming Language

result resource in x:\localhost\1\1.php on line 15

This error message discloses the type of the SQL server (MySQL) to the attacker. In addition, it discloses the path to a script.

Such information-disclosing errors rarely manifest during a normal work of the system. So, the attacker has to make the server return as many error messages containing important information as possible.

Sometimes, the attacker needs to test the system by passing it HTTP parameters illogical from the system's point of view. In other cases, the attacker can launch a Denial of Service (DoS) attack on server scripts to get error messages. The maximum number of connections to the database is likely to be exhausted, and if a script uses a database connection, it will eventually be rejected with an appropriate error message.

In addition, error messages can be contained in caches of search engines and other systems that maintain archives of HTTP documents.

Error messages can contain rather important information. For example, the phpbb forum sometimes displays the text of the SQL query that caused an error. This message discloses the query in addition to the paths to files on the server and the database type.

When the attacker knows an SQL query that causes an error message with certain parameters of HTTP parameters, he or she will easily create an HTTP request that exploits the SQL source code injection vulnerability.

To write secure programs, stick to the following rule:



Rule

Don't output debugging information, error messages, and other auxiliary information to the browser. However, disabling the output of error messages shouldn't be the only protection action.

더보기

댓글,