| | {section} |
| | |
| | h2. PHP Security |
| | |
| | This page covers the following topics as related to web application security using PHP. |
| | {toc:type=flat|seperator=pipe|minLevel=3|maxLevel=4} |
| | |
| | h3. Register Globals |
| | |
| | Arguably the most common source of vulnerabilities in PHP applications. |
| | {code:borderStyle=solid} |
| | ?userId=55 |
| | {code} |
| | becomes... |
| | {code:borderStyle=solid} |
| | $userId=55 |
| | {code} |
| | This is bad because there is no way to determine the input source. Uninitialized variables can be injected via user input. All input parameters are translated to variables. |
| | |
| | In addition to being a security hazard, it is an option that may not not be available on all servers. Best practices are to use |
| | {code:borderStyle=solid} |
| | $_GET['userid'] |
| | {code} |
| | or |
| | {code:borderStyle=solid} |
| | $_POST['userid'] |
| | {code} |
| | |
| | ---- |
| | {column:width=80%} |
| | |
| | h3. Session Management |
| | |
| | Session attacks can not be prevented by filtering input and escaping output. |
| | |
| | OWASP recommondations for [PHP session management|http://www.owasp.org/index.php/Session_Management#PHP] |
| | |
| | *Session Fixation* |
| | Session Fixation is an attack technique that forces a user's session ID to an explicit value. Depending on the functionality of the target web site, a number of techniques can be utilized to "fix" the session ID value. These techniques range from Cross-Site Scripting (XSS) exploits to peppering the web site with previously made HTTP requests. After a user's session ID has been fixed, the attacker will wait for them to login. Once a user does so, the attacker uses the predefined session ID value to assume their online identity. |
| | |
| | Preventing Session Fixation |
| | # Do not accept session identifiers from GET/POST variables: |
| | Session identifiers in URL (query string, GET variables) or POST variables are not recommended as it simplifies this attack. It is easy to make links on forms which set GET/POST variables. |
| | # Regenerate the SID on each request: |
| | In PHP use _session_regenerate_id()_. Every time a user's access level changes, it is necessary to regenerate the session identifier. This means that although an attacker may trick a user into accepting a known SID, the SID will be invalid when the attacker attempts to re-use the SID. For example... |
| | {code:title=regenerate_session.php|borderStyle=solid} |
| | // If the user login is successful, regenerate the session ID |
| | if (authenticate()) |
| | { |
| | session_regenerate_id(); |
| | } |
| | {code} |
| | # Accept only server generated SID: |
| | One way to improve security is to not accept session identifiers that were not generated by the server/ |
| | {code:title=server_generated_SID.php|borderStyle=solid} |
| | if(!isset($_SESSION['SERVER_GENERATED_SID'])) { |
| | //destroy all data in session |
| | session_destroy(); |
| | } |
| | // generate a new session identifier |
| | session_regenerate_id( ); |
| | $_SESSION['SERVER_GENERATED_SID']=true; |
| | {code} |
| | |
| | h4. Session Hijacking |
| | Session hijacking is a generic term used to describe any means by which an attacker gains a user's valid session identifier (rather than providing one of her own). For example, suppose the user logs in. If the session identifier is regnerated, they have a new session ID. What if an attacker discovers this new ID and attempts to use it to gain access through that user's session? We now need to use another method to identify the user. |
| | |
| | One way to idenify the user in addition to the session ID is to check various request headers sent by the client. One request header that is particularly helpful and does not change between requests is the _User-Agent_ header. It is unlikely that a legitimate user will change from one browser to another while using the same session. Because of this you can use _User-Agent_ to determine if a possible session hijacking attempt is being made. |
| | {code:borderStyle=solid} |
| | $_SESSION['user_agent'] = $_SERVER['HTTP_USER_AGENT']; |
| | {code} |
| | Then, on subsequent page loads, check to ensure that the _User-Agen_ has not changed. If it has changed, then it is cause for concern and you should make the user log in again. |
| | {code:borderStyle=solid} |
| | if ($_SESSION['user_agent'] != $_SERVER['HTTP_USER_AGENT']) |
| | { |
| | // Force user to log in again |
| | exit; |
| | } |
| | {code} |
| | |
| |  | h3. Numeric Value Validation |
| | | h3. Checking Input |
| | h4. Validating Numbers |
| | If you expect a variable to always contain a numeric value, one simple way to achieve this validation is to use casting. |
| | {code:borderStyle=solid} |
| | //integer validation |
| | if (!empty($_GET['id'])) |
| | $id = (int)$_GET['id']; |
| | else |
| | $id = 0; |
| | |
| | //float validation |
| | if (!empty($_GET['price'])) |
| | $price = (float)$_GET['price']; |
| | else |
| | $price = 0; |
| | {code} |
 | | |
| | h4. Validating Strings |
| | PHP comes with a _ctype_ extension that offers a very quick mechanism for validating string input. Here are some examples: |
| | {code:borderStyle=solid} |
| | if (!ctype_alnum($_GET['login'])) { |
| | echo "Only A-Za-z0-9 are allowed."; |
| | } |
| | |
| | if (!ctype_alpha($_GET['captcha'])){ |
| | echo "Only A-Za-z are allowed."; |
| | } |
| | |
| | if (!ctype_xdigit($_GET['color'])){ |
| | echo "Only hexadecimal values are allowed."; |
| | } |
| | {code} |
| | {column} |
| | {section} |