当前位置:Gxlcms > PHP教程 > ExploitingCommonVulnerabilitiesinPHPApplications

ExploitingCommonVulnerabilitiesinPHPApplications

时间:2021-07-01 10:21:17 帮助过:16人阅读

<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<->>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>A Study In ScarletExploiting Common Vulnerabilities in PHP ApplicationsShaun ClowesSecureReality"A reprint of reminisces from the Blackhat Briefings Asia 2001"<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<->>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>--- < Table of Contents > --------------------------------------------------1. Introduction2. Caveats and Scope3. Global Variables4. Remote Files5. File Upload6. Library Files7. Session Files8. Loose Typing And Associative Arrays9. Target Functions10. Protecting PHP11. Responsibility - Language vs Programmer12. Other"I could imagine his giving a friend a little pinch of the latest vegetablealkaloid, not out of malevolence, you understand, but simply out of a spiritof inquiry in order to have an accurate idea of the effects." - Stamford--- < 1. Introduction > ----------------------------------------------------This paper is based on my speech during the Blackhat briefings in Singaporeand Hong Kong in April 2001. The speech was entitled "Breaking In Throughthe Front Door - The impact of Web Applications and Application ServiceProvision on Traditional Security Models". It initially discussed the trendtowards Web Applications (and ASP) and the holes in traditional securitymethodology exposed by this trend. However, that's a long and boringdiscussion so I'll save it for the policy makers.The rest of the speech was spent talking about PHP. For those reading thispaper who don't know what PHP is, PHP stands for "PHP HypertextPreprocessor". It's a programming language (designed specifically for theWeb) in which PHP code is embedded in web pages. When a client requests apage, the Web Server first passes the page to the language interpreter sothe code can be executed, the resulting page is then returned to the client.Obviously this approach is much more suited to the page by page nature ofweb transactions than traditional CGI languages such as Perl and C. PHP (andto some extent other Web Languages) has the following characteristics:+ Interpreted+ Fast Execution - The interpreter is embedded in the web server, no fork()or setup overhead+ Feature Rich - Hundreds of non trivial builtin functions+ Simple Syntax - Non declared and loosely typed variables, 'wordy'function namesOver the course of this paper I'm going to try to explain why I feel thelast two characteristics make applications written in PHP easy to attack andhard to defend. Then I'll finish off with a rant about distribution of'blame' when it comes to software security."You must study him, then ... you'll find him a knotty problem, though. I'llwager he learns more about you than you about him." - Stamford--- < 2. Caveats and Scope > -----------------------------------------------Almost all the observations in this paper refer to a default install of PHP4.0.4pl1 (with MySQL, PostgreSQL, IMAP and OpenSSL support enabled) runningas a module under Apache 1.3.19 on a Linux machine. This of course meansthat your mileage may vary, in particular, there have been many manyversions of PHP and they sometimes exhibit vastly different behaviour giventhe same input.Also, proponents of PHP tend to defend the language based on its extremeconfigurability. I feel very confident the vast majority of users will notmodify the default PHP configuration at all, lest some of the amazing arrayof freely available PHP software stop working. Thus I don't feel pressuredto defend my position based on configuration options, nonetheless I'veincluded a section about how to go defending PHP applications using theseconfiguration options.Finally, some people deride this kind of work as 'trivial' or 'obvious',particularly since I won't be discussing any specific vulnerabilities inparticular pieces of PHP software. To prove the risks are real and that evenprogrammer's that try hard fall into these traps 4 detailed advisories inregards to specific pieces of vulnerable software will be released shortlyafter this paper."I have to be careful ... for I dabble with poisons a good deal." - SherlockHolmes--- < 3. Global Variables > ------------------------------------------------As mentioned earlier, variables in PHP don't have to be declared, they'reautomatically created the first time they are used. Nor are theyspecifically typed, they're typed automatically based on the context inwhich they are used. This is an extremely convenient way to do things from aprogrammer's perspective (and is obviously a useful feature in a rapidapplication development language). Once a variable is created it can bereferenced anywhere in the program (except in functions where it must beexplicitly included in the namespace with the 'global' function). The resultof these characteristics is that variables are rarely initialized by theprogrammer, after all, when they're first created they are empty (i.e "").Obviously the main function of a PHP based web application is usually totake in some client input (form variables, uploaded files, cookies etc),process the input and return output based on that input. In order to make itas simple as possible for the PHP script to access this input, it's actuallyprovided in the form of PHP global variables. Take the following exampleHTML snippet:Obviously this will display a text box and a submit button. When the userpresses the submit button the PHP script test.php will be run to process theinput. When it runs the variable $hello will contain the text the userentered into the text box. It's important to note the implications of this,this means that a remote attacker can create any variable they wish and haveit declared in the global namespace. If instead of using the form above tocall test.php, an attacker calls it directly with a url like"http://server/test.php?hello=hi&setup=no", not only will $hello = "hi" whenthe script is run but $setup will be "no" also.An example of how this can be a real problem might be a script that wasdesigned to authenticate a user before displaying some importantinformation. For example:In normal operation the above code will check the password to decide if theremote user has successfully authenticated then later check if they areauthenticated and show them the important information. The problem is thatthe code incorrectly assumes that the variable $auth will be empty unless itsets it. Remembering that an attacker can create variables in the globalnamespace, a url like 'http://server/test.php?auth=1' will fail the passwordcheck but the script will still believe the attacker has successfullyauthenticated.To summarize the above, a PHP script _cannot trust ANY variable it has notEXPLICITLY set_. When you've got a rather large number of variables, thiscan be a much harder task than it may sound.Once common approach to protecting a script is to check that the variable isnot in the array HTTP_GET/POST_VARS[] (depending on the method normally usedto submit the form, GET or POST). When PHP is configured with track_varsenabled (as it is by default) variables submitted by the user are availableboth from the global variables and also as elements in the arrays mentionedabove. However, it's important to note that there are FOUR different arraysfor remote user input, HTTP_GET_VARS for variables submitted in the URL ofthe get request, HTTP_POST_VARS for variables submitted in the post sectionof a HTTP request, HTTP_COOKIE_VARS for variables submitted as part of thecookie headers in the HTTP request and to a limited degree theHTTP_POST_FILES array (in more recent versions of PHP). It is completely theend users choice which method they use to submit variables, one request caneasily place variables in all four different arrays, a secure script needsto check all four (though again, the HTTP_POST_FILES array shouldn't be anissue except in exceptional circumstances)."No man burdens his mind with small matters unless he has some very goodreason for doing so." - John Watson--- < 4. Remote Files > ----------------------------------------------------I'm going to repeat this frequently during this document but it bearsrepeating, PHP is an extremely feature rich language. It ships with anamazing amount of functionality out of the box and tries hard to make lifeas easy as possible for the coder (or web designer as the case so often is).From a security perspective, the more superfluous functionality offered by alanguage and the less intuitive the possibilities, the more difficult it isto secure applications written in it. An excellent example of this is theRemote Files functionality of PHP.The following piece of PHP code is designed to open a file:\n");?>The code attempts to open the file specified in the variable $filename forreading and if it fails displays an error. Obviously this could be a simplesecurity issue if the user can set $filename and get the script to expose/etc/passwd for example but one non intuitive this code could end up doingis reading data from another web/ftp site. The remote files functionalitymeans that the majority of PHPs file handling functions can worktransparently on remote files via HTTP and FTP. If $filename were to contain(for example)"http://target/scripts/..%c1%1c../winnt/system32/cmd.exe?/c+dir" PHP willactually make a HTTP request to the server "target", in this case trying toexploit the unicode flaw.This gets more interesting in the context of four other file functions thatsupport remote file functionality (*** except under Windows ***), include(),require(), include_once() and require_once(). These functions take in afilename and read that file and parse it as PHP code. They're typically usedto support the concept of code libraries, where common bits of PHP code arestored in files and included as needed. Now take the following piece ofcode:Presumably $libdir is a configuration variable that is meant to be setearlier in script execution to the directory where the library files arestored. If the attacker can cause the variable not to be set the script(which is typically not a tremendously difficult task) and instead submit itthemselves they can modify the start of the path. This would normally gainthem nothing since they still end up only being able to access languages.phpin a directory of their choosing (poison null attacks like those possible onPerl don't work under PHP) but with remote files the attack can submit anycode they wish to be executed. For example, if the attacker places a file ona web server called languages.php containing the following:then sets $libdir to "http:///" upon encountering the includestatement PHP will make a HTTP request to evilhost, retrieve the attackerscode and execute it, returning a listing of /etc to the attackers webbrowser. Note that the attacking webserver (evilhost) can't be running PHPor the code will be run on the attacking machine rather than the targetmachine (see the "Other" section and its reference to SRADV00006 for anexample of code which survives being on a PHP enabled attacking machine)."There are no crimes and no criminals in these days" - Sherlock Holmes--- < 5. File Upload > -----------------------------------------------------As if PHP hadn't already provided enough to make life easier for theattacker the language provides automatic support for RFC 1867 based fileupload. Take the following form:This form will allow the web browser user to select a file from their localmachine then when they click submit the file will be uploaded to the remoteweb server. This is obviously useful functionality but is PHPs response thatmakes this dangerous. When PHP first receives the request, before it haseven BEGUN to parse the PHP script being called it will automaticallyreceive the file from the remote user, it will then check that the file isno larger than specified in the $MAX_FILE_SIZE variable (10 kb in this case)and the maximum file size set in the PHP configuration file, if it passesthese tests the file is SAVED on the local disk in a temporary directory.Please read that again if that doesn't make you blink, a remote user cansend any file they wish to a PHP enabled machine and before a script haseven specified whether or not it accepts file uploads that file is SAVED onthe local disk.I'm going to ignore any resource exhaustion attacks that may or may not bepossible using file upload functionality, I think they're fairly limited ifnot impossible in any case.First let's consider a script that IS designed to receive file uploads. Asdescribed above the file is received and saved on the local disk (in thelocation specified in the configuration for uploaded files, typically /tmp)with a random filename (e.g "phpxXuoXG"). The PHP script then needsinformation regarding the uploaded file to be able to process it. This isactually provided in two different ways, one has been in use since earlyversions of PHP 3, the other was introduced following our Advisory regardingthe issue I'm about to describe with the former method. Suffice to say theproblem is still alive and well, most scripts continue to use the oldmethod. PHP sets four global variables to describe the uploaded file, forexample (given the upload form above):$hello = Filename on local machine (e.g "/tmp/phpxXuoXG")$hello_size = Size in bytes of file (e.g 1024)$hello_name = The original name of the file on the remote system (e.g"c:\\temp\\hello.txt")$hello_type = Mime type of uploaded file (e.g "text/plain")The PHP script then proceeds to work on the file as located via the $hellovariable. The problem is that it isn't immediately obvious that $hello neednot really be a PHP set variable and can simply be set by a remote attacker.Take the following form input for example:http://vulnhost/vuln.php?hello=/etc/passwd&hello_size=10240&hello_type=text/plain&hello_name=hello.txtThat results in the following global PHP variables (of course POST could beused (even cookies)):$hello = "/etc/passwd"$hello_size = 10240$hello_type = "text/plain"$hello_name = "hello.txt"This form input will provide exactly the variables the PHP scripts expectsto be set by PHP, but instead of working on an uploaded file the script willinfact be working on /etc/passwd (usually resulting in its content beingexposed). This attack can be used to expose the contents of all sorts ofsensitive files (in particular configuration files containing database andother third tier server credentials).I noted above that newer versions of PHP provide different methods fordetermining the uploaded files (it's done via the HTTP_POST_FILES[] arraymentioned earlier). It also provides numerous functions to avoid thisproblem, for example a function to determine if a particular file isactually one that has been uploaded. These methods well and truly fix theproblem but there is certainly no shortage of scripts out there still usingthe old method and still vulnerable to this sort of attack.As an alternate attack assisted by file upload consider the followingexample PHP code:If the attacker can control $theme they can obviously use this to read anyfile on the remote system (except that content inside PHP tags e.g " ---------------------------------------------------I've mentioned the include() and require() functions earlier, I also saidthat they're generally used to support the concept of code libraries. What Imean by that is that common bits of code are put into a separate file andwhen needed in the application simply include()ed from the file. include()and require() will take any specified filename and read the file and parseits contents as PHP code.Initially when people started developing and distributing PHP applicationsthey chose to distinguish library and main application code by givinglibrary files the '.inc' extension. However they quickly found this was abad move in general since such files aren't normally parsed as PHP code bythe PHP interpreter. If requested from the web server they will generallyhave the full source code returned. This is because the PHP interpreter(when used as an apache module) determines which files to parse for PHP codebased on the file's extension, the extensions to be interpreted can bechosen by the administrator but usually a combination of the extensions'.php', '.php4' and '.php3' is chosen. This is a real problem when sensitiveconfiguration data (e.g database credentials) is placed in PHP files thatdon't have an appropriate extension since a remote attacker can easily getthe source.The simplest solution (and the one that has since become favored) is simplyto give EVERY file a PHP parsed extension. This prevents a request to theweb server ever returning the raw source for a file that contains PHP code.The problem here is that though the source will no longer be returned, byrequesting the file a remote attacker can have the code that is meant to beused in a framework of other code executed out of context. This can lead toall of the attacks I've described earlier.An obvious example might be the following:In main.php:In libdir/loadlanguage.php:When libdir/loadlanguage.php is called in the defined context of main.php itis perfectly safe. But because libdir/loadlanguage has the extension .php(it doesn't have to have that extension, include() works on any file) it canbe requested and executed by a remote attacker. When out of context anattacker can set $langDir and $userLang to whatever they wish."You know a conjuror gets no credit when once he has explained his trick andif I show you too much of my method of working, you will come to theconclusion that I am a very ordinary individual after all" - Sherlock Holmes--- < 7. Session Files > ---------------------------------------------------Later versions of PHP (4 and above) provide built-in support for 'sessions'.Their basic purpose is to be able to save state information from page topage in a PHP application. For example, when a user logs in to a web site,the fact that they are logged in (and who they are logged in) could be savedin the session. When they move around the site this information will beavailable to all other PHP pages. What actually happens is that when asession is started (it's typically set in the configuration file to beautomatically started on first request) a random session id is generated,the session persists as long as the remote browser always submits thissession id with requests. This is most easily achieved with a cookie but canalso be done by achieved by putting a form variable (containing the sessionid) on every page. The session is a variable store, a PHP application canchoose to register a particular variable with the session, its value is thenstored in a session file at the end of every PHP script and loaded into thevariable at the start of every script. A trivial example is as follows:Any later PHP scripts will automatically have the variable $session_auth setto "shaun", if they modify it later scripts will receive the modified value.This is obviously a very handy facility to have in a stateless environmentlike the web but caution is also necessary.One obvious problem is with insuring that variables actually come from thesession. For example, given the above code, if a later script does thefollowing:This code makes the assumption that if $session_auth is set, it must havecome from the session and not from remote input. If an attacker specified$session_auth in form input they can gain access to the site. Note that theattacker must use this attack before the variable is registered with thesession, once a variable is in a session it will override any form input.Session data is saved in a file (in a configurable location, usually /tmp)named 'sess_'. This file contains the names of the variables inthe session, their loose type, value and other data. On multi host systemsthis can be an issue since the files are saved as the user running the webserver (typically nobody), a malicious site owner can easily create asession file granting themselves access on another site or even examine thesession files looking for sensitive information.The session mechanism also supplies another convenient place that anattacker have their input saved into a file on the remote machine. Forexamples above where the attacker needed PHP code in a file on the remotemachine, if they cannot use file upload they can often use the applicationand have a session variable set to a value of their choosing. They can thenguess 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 specifyany session id they wish (e.g 'hello') and have a session file created withthat id (for the example '/tmp/sess_hello'). The id can only containalphanumeric characters but this might well be useful in some situations."It is a mistake to confound strangeness with mystery" - Sherlock Holmes--- < 8. Loose Typing And Associative Arrays > -----------------------------Just a quick note about these factors.PHP is a loosely typed language, that is, a variable has different valuesdepending on the context in which it is being evaluated. For example, thevariable $hello set to the empty string "" when evaluated as a number hasthe value 0. This can sometimes lead to non intuitive results (a factor thatwas important in the exploitation of phpMyAdmin in SRADV00008). If $hello isset to "000" it is NOT equal to "0" nor will the function empty() returntrue.PHP arrays are associative, that is, the index to the array is a STRING andcan be set to any string value, it is not numerically evaluated. This meansthat the array entry $hello["000"] is NOT the same as the array entry$hello[0].Applications need to be careful to validate user input with thought to theabove factors and to do so consistently. I.e don't test is something isequal to 0 in one place and then validate it using empty() somewhere else."We want something more than mere preaching now" - Mr. Gregson--- < 9. Target Functions > ------------------------------------------------When looking for holes in PHP applications (when you have the source code)it's useful to have a list of functions that are frequently misused or aregood targets if they happen to be used in a vulnerable manner in the targetapplication. If a remote user can affect the parameters to these functionsexploitation is often possible. The following is a non exhaustive breakdown.PHP Code Execution:require() and include() - Both these functions read a specified file andinterpret the contents as PHP codeeval() - Interprets a given string as PHP codepreg_replace() - When used with the /e modifier this function interprets thereplacement string as PHP codeCommand Execution:exec() - Executes a specified command and returns the last line of theprograms outputpassthru() - Executes a specified command and returns all of the outputdirectly to the remote browser`` (backticks) - Executes the specified command and returns all the outputin an arraysystem() - Much the same as passthru() but doesn't handle binary datapopen() - Executes a specified command and connects its output or inputstream to a PHP file descriptorFile Disclosure:fopen() - Opens a file and associates it with a PHP file descriptorreadfile() - Reads a file and writes its contents directly to the remotebrowserfile() - Reads an entire file into an array"There is mystery about this which stimulates the imagination; where thereis no imagination there is no horror" - Sherlock Holmes--- < 10. Protecting PHP> --------------------------------------------------All of the attacks I've described above work perfectly on a defaultinstallation of PHP 4. However as I've mentioned numerous times PHP isendlessly configurable and many of these attacks can be defeated using thoseconfiguration options. There is always a price for security though, so I'veclassified the following configuration options according to theirpainfulness:* = Mostly painless** = Vaguely painful*** = Seriously hurts**** = Chinese Water TortureObviously my ratings are subjective so don't flame me for them. I will sayone thing though, if you use all of the options you'll have a very securePHP installation, even third party code will be reliably secure, it's justthat most of it won't work :)**** - Set register_globals offThis option will stop PHP creating global variables for user input. That is,if a user submits the form variable 'hello' PHP won't set $hello, onlyHTTP_GET/POST_VARS['hello']. This is the mother of all other options and isbest single option for PHP security, it will also kill basically every thirdparty application available and makes programming PHP a whole lot lessconvenient.*** - Set safe_mode onI'd love to describe exactly what safe_mode does but it isn't documentedcompletely. It introduces a large variety of restrictions including:- The ability to restrict which commands can be executed (by exec() etc)- The ability to restrict which functions can be used- Restricts file access based on ownership of script and target file- Kills file upload completelyThis is a great option for ISP environments (for which it is designed) butit can also greatly improve the security of normal PHP environments givenproper configuration. It can also be a complete pain in the neck.** - Set open_basedirThis option prevents any file operations on files outside specifieddirectories. This can effectively kill a variety of local include() andremote file attacks. Caution is still required in regards to file upload andsession files.** - Set display_errors off, log_errors onThis prevents PHP error messages being displayed in the returned web page.This can effectively limit an attackers exploration of the function of thescript they are attacking. It can also make debugging very frustrating.* - Set allow_url_fopen offThis stops remote files functionality. Very few sites really need thisfunctionality, I absolutely recommend every site set this option.There may well be other great options I'm missing, please consult the PHPdocumentation"Our ideas must be as broad as nature if we are to interpret nature" -Sherlock Holmes--- < 11. Responsibility - Language Vs Programmer> -------------------------I contend that it is very hard to write a secure PHP application (in thedefault configuration of PHP), even if you try. It's not that PHP is a badlanguage, it's amazingly easy to program in and has more builtin featuresthan any other language I know. However PHP has such emphasis on rapiddevelopment and feature richness that two things happen:- Web designers and other non coders end up writing PHP applications. Theyhave no understanding whatsoever of the security implications of the codethey are writing. Partly this is because the mindset isn't what it shouldbe. A PHP application typically runs in the most exposed environmentpossible, a universally accessible page on a web server. This means themindset should be of coding a network daemon that will be routinelyattacked, or of a setuid root application. Instead the mindset isfunctionality at all costs like it would be while writing an unprivilegedlocal application. If your web server is penetrated it provides a gateway tothe third tier, it is always a bad thing, even if the access is as nobody(as penetrating a PHP application will typically provide).- Code behaviour becomes unpredictable. An include() statement thatpostfixes a user variable with "image.php" would normally be perfectly safe,the user can only specify which directory to retrieve that file from (andpresumably cannot create a file image.php on the remote machine). Whenremote files functionality is allowed it becomes a nightmare. This iscompletely non intuitive.A lot of people blame programmer's for the code they write, I personallyfeel that if a language makes it hard for a programmer to write good code(particularly by being counterintuitive) the language must itself take someof the blame for the situation. It's not good enough to just say theprogrammer should know better. In almost every PHP application I've auditedthe programmer's have _tried_ to get it right and only been let down bytheir understanding of the intricacies of PHP. In its search for theultimate functionality PHP has undermined the programmer's ability tounderstand the workings of their code in all situations."I have all the facts in my journal, and the public shall know them" - JohnWatson--- < 12. Other> -----------------------------------------------------------This is just a section for various other resources.At a time when I thought no-one else was interested in PHP security, a fewgreat posts/advisories/papers have popped up:- Rain Forest PuppyRFP 2101 - "RFPlutonium to fuel your PHP-Nuke"http://www.wiretrip.net/rfp/p/doc.asp?id=60&iface=2- Jo? GouveiaMany posts to Bugtraq, check them all out, but as a selectionhttp://www.securityfocus.com/templates/archive.pike?list=1&mid=165519http://www.securityfocus.com/templates/archive.pike?list=1&mid=147104- Jouko Pynnonenhttp://www.securityfocus.com/templates/archive.pike?list=1&mid=169045There are many others, sorry I didn't list them all.SecureReality have released a number of advisories regarding PHPapplications which should serve to illustrate the problems I've outlined inthis paper fairly well:- SRADV00001 - Arbitrary File Disclosure through PHP File Uploadhttp://www.securereality.com.au/sradv00001.html- SRADV00003 - Arbitrary File Disclosure through IMPhttp://www.securereality.com.au/sradv00003.html- SRADV00006 - Remote command execution vulnerabilities in phpGroupWarehttp://www.securereality.com.au/sradv00006.html- SRADV00008 - Remote command execution vulnerabilities in phpMyAdmin andphpPgAdminhttp://www.securereality.com.au/sradv00008.txt- SRADV00009 - Remote command execution vulnerabilities in phpSecurePageshttp://www.securereality.com.au/sradv00009.txt- SRADV00010 - Remote command execution vulnerabilities in SquirrelMailhttp://www.securereality.com.au/sradv00010.txt- SRADV00011 - Remote command execution vulnerabilities in WebCalendarhttp://www.securereality.com.au/sradv00011.txtThe last four were presented during my speech at the BlackHat Briefings inSingapore and Asia in 2001. Audio/Video of the speech will (at some stage)be available at http://www.blackhat.com. For anyone interested in security,I can't suggest more strongly that you go to the briefings.Finally, incase anyone wondered where the title came from and all thosequotes at the end of each section, they're from the short story "A Study InScarlet" by Sir Arthur Conan Doyle which was also the first story in whichthe character Sherlock Holmes appeared."I must thank you for it all. I might not have gone but for you, and so havemissed the finest study I ever came across: a study in scarlet eh?" -Sherlock Holmes

人气教程排行