<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
		<id>https://wiki.owasp.org/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Manuel+Aude+Morales</id>
		<title>OWASP - User contributions [en]</title>
		<link rel="self" type="application/atom+xml" href="https://wiki.owasp.org/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Manuel+Aude+Morales"/>
		<link rel="alternate" type="text/html" href="https://wiki.owasp.org/index.php/Special:Contributions/Manuel_Aude_Morales"/>
		<updated>2026-04-30T10:02:20Z</updated>
		<subtitle>User contributions</subtitle>
		<generator>MediaWiki 1.27.2</generator>

	<entry>
		<id>https://wiki.owasp.org/index.php?title=Authentication_Cheat_Sheet&amp;diff=148367</id>
		<title>Authentication Cheat Sheet</title>
		<link rel="alternate" type="text/html" href="https://wiki.owasp.org/index.php?title=Authentication_Cheat_Sheet&amp;diff=148367"/>
				<updated>2013-03-21T21:51:58Z</updated>
		
		<summary type="html">&lt;p&gt;Manuel Aude Morales: Added OAuth, OpenId and SAML protocols for password-less authentication&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Introduction  =&lt;br /&gt;
&lt;br /&gt;
'''Authentication''' is the process of verification that an individual or an entity is who it claims to be. Authentication is commonly performed by submitting a user name or ID and one or more items of private information that only a given user should know. &lt;br /&gt;
&lt;br /&gt;
'''Session Management''' is a process by which a server maintains the state of an entity interacting with it. This is required for a server to remember how to react to subsequent requests throughout a transaction. Sessions are maintained on the server by a session identifier which can be passed back and forward between the client and server when transmitting and receiving requests. Sessions should be unique per user and computationally very difficult to predict. &lt;br /&gt;
&lt;br /&gt;
For more information on Authentication, please see the OWASP [[Guide to Authentication]] page.&lt;br /&gt;
&lt;br /&gt;
= Authentication General Guidelines  =&lt;br /&gt;
&lt;br /&gt;
== User IDs ==&lt;br /&gt;
&lt;br /&gt;
Make sure your usernames/userids are case insensitive. Many sites use email addresses for usernames and email addresses are already case insensitive. Regardless, it would be very strange for user 'smith' and user 'Smith' to be different users. Could result in serious confusion.&lt;br /&gt;
&lt;br /&gt;
== Implement Proper Password Strength Controls ==&lt;br /&gt;
&lt;br /&gt;
A key concern when using passwords for authentication is password strength. A &amp;quot;strong&amp;quot; password policy makes it difficult or even improbable for one to guess the password through either manual or automated means. The following characteristics define a strong password: &lt;br /&gt;
&lt;br /&gt;
=== Password Length ===&lt;br /&gt;
&lt;br /&gt;
Longer passwords provide a greater combination of characters and consequently make it more difficult for an attacker to guess. &lt;br /&gt;
&lt;br /&gt;
* '''Minimum''' length of the passwords should be '''enforced''' by the application.&lt;br /&gt;
** Passwords '''shorter than 10 characters''' are considered to be weak ([http://csrc.nist.gov/publications/nistpubs/800-132/nist-sp800-132.pdf]).&lt;br /&gt;
&lt;br /&gt;
While minimum length enforcement may cause problems with memorizing passwords among some users, applications should encourage them to set ''passphrases'' (sentences or combination of words) that can be much longer than typical passwords and yet much easier to remember.&lt;br /&gt;
&lt;br /&gt;
* '''Maximum''' password length should not be set '''too low''', as it will prevent users from creating passphrases. Typical maximum length is 128 characters.&lt;br /&gt;
** Passphrases shorter than 20 characters are usually considered weak if they only consist of lower case Latin characters.&lt;br /&gt;
&lt;br /&gt;
* Every character counts!!&lt;br /&gt;
**Make sure that every character the user types in is actually included in the password. We've seen systems that truncate the password at a length shorter than what the user provided (e.g., truncated at 15 characters when they entered 20).&lt;br /&gt;
**This is usually handled by setting the length of ALL password input fields to be exactly the same length as the maximum length password. This is particularly important if your max password length is short, like 20-30 characters.&lt;br /&gt;
&lt;br /&gt;
=== Password Complexity ===&lt;br /&gt;
&lt;br /&gt;
Applications should enforce password complexity rules to discourage easy to guess passwords. Password mechanisms should allow virtually any character the user can type to be part of their password, including the space character. Passwords should, obviously, be case sensitive in order to increase their complexity. Occasionally, we find systems where passwords aren't case sensitive, frequently due to legacy system issues like old mainframes that didn't have case sensitive passwords.&lt;br /&gt;
&lt;br /&gt;
The password change mechanism should require a minimum level of complexity that makes sense for the application and its user population. For example:&lt;br /&gt;
&lt;br /&gt;
*Password must meet at least 3 out of the following 4 complexity rules&lt;br /&gt;
**at least 1 uppercase character (A-Z) &lt;br /&gt;
**at least 1 lowercase character (a-z) &lt;br /&gt;
**at least 1 digit (0-9) &lt;br /&gt;
**at least 1 special character (!&amp;quot;£$%&amp;amp;amp;...) &amp;amp;mdash; do not forget to treat space as special characters (common in passphrases)&lt;br /&gt;
*at least 10 characters &lt;br /&gt;
*at most 128 characters&lt;br /&gt;
*not more than 2 identical characters in a row (e.g., 111 not allowed)&lt;br /&gt;
&lt;br /&gt;
As application's require more complex password policies, they need to be very clear about what these policies are.&lt;br /&gt;
*The required policy needs to be explicitly stated on the password change page&lt;br /&gt;
** be sure to list every special character you allow, so it's obvious to the user&lt;br /&gt;
&lt;br /&gt;
Recommendation:&lt;br /&gt;
* Ideally, the application would indicate to the user as they type in their new password how much of the complexity policy their new password meets&lt;br /&gt;
**In fact, the submit button should be grayed out until the new password meets the complexity policy and the 2nd copy of the new password matches the 1st. This will make it far easier for the user to understand and comply with your complexity policy.&lt;br /&gt;
&lt;br /&gt;
Regardless of how the UI behaves, when a user submits their password change request:&lt;br /&gt;
*If the new password doesn't comply with the complexity policy, the error message should describe EVERY complexity rule that the new password does not comply with, not just the 1st rule it doesn't comply with&lt;br /&gt;
&lt;br /&gt;
Changing passwords should be EASY, not a hunt in the dark.&lt;br /&gt;
&lt;br /&gt;
== Implement Secure Password Recovery Mechanism ==&lt;br /&gt;
&lt;br /&gt;
It is common for an application to have a mechanism that provides a means for a user to gain access to their account in the event they forget their password. Please see [[Forgot_Password_Cheat_Sheet]] for details on this feature.&lt;br /&gt;
&lt;br /&gt;
== Require Re-authentication for Sensitive Features ==&lt;br /&gt;
&lt;br /&gt;
In order to mitigate CSRF and session hijacking, it's important to require the current credentials for an account before updating sensitive account information such as the user's password, user's email, or before sensitive transactions, such as shipping a purchase to a new address.  Without this countermeasure, an attacker may be able to execute sensitive transactions through a CSRF or XSS attack without needing to know the user's current credentials.  Additionally, an attacker may get temporary physical access to a user's browser or steal their session ID to take over the user's session.&lt;br /&gt;
&lt;br /&gt;
== Utilize Multi-Factor Authentication ==&lt;br /&gt;
&lt;br /&gt;
Multi-factor authentication (MFA) is using more than one authentication factor to logon or process a transaction:&lt;br /&gt;
&lt;br /&gt;
*Something you know (account details or passwords) &lt;br /&gt;
*Something you have (tokens or mobile phones) &lt;br /&gt;
*Something you are (biometrics)&lt;br /&gt;
&lt;br /&gt;
Authentication schemes such as One Time Passwords (OTP) implemented using a hardware token can also be key in fighting attacks such as CSRF and client-side malware. A number of hardware tokens suitable for MFA are available in the market that allow good integration with web applications. See: [http://en.wikipedia.org/wiki/Security_token].&lt;br /&gt;
&lt;br /&gt;
=== SSL Client Authentication ===&lt;br /&gt;
&lt;br /&gt;
SSL Client Authentication, also known as two-way SSL authentication, consists of both, browser and server, sending their respective SSL certificates during the TLS handshake process. Just as you can validate the authenticity of a server by using the certificate and asking a well known Certificate Authority (CA) if the certificate is valid, the server can authenticate the user by receiving a certificate from the client and validating against a third party CA or its own CA. To do this, the server most provide the user with a certificate generated specifically for him, assigning values to the subject so that these can be used to determine what user the certificate should validate. The user installs the certificate on a browser and now uses it for the website.&lt;br /&gt;
&lt;br /&gt;
It is a good idea to do this when:&lt;br /&gt;
&lt;br /&gt;
*It is acceptable (or even preferred) that the user only has access to the website from only a single computer/browser.&lt;br /&gt;
*The user is not easily scared by the process of installing SSL certificates on his browser or there will be someone, probably from IT support, that will do this for the user.&lt;br /&gt;
*The website requires an extra step of security.&lt;br /&gt;
*It is also a good thing to use when the website is for an intranet of a company or organization.&lt;br /&gt;
&lt;br /&gt;
It is generally not a good idea to use this method for widely and publicly available websites that will have an average user. For example, it wouldn't be a good idea to implement this for a website like Facebook. While this technique can prevent the user from having to type a password (thus protecting against an average keylogger from stealing it), it is still considered a good idea to consider using both a password and SSL client authentication combined.&lt;br /&gt;
&lt;br /&gt;
For more information, see: [http://publib.boulder.ibm.com/infocenter/tivihelp/v5r1/index.jsp?topic=%2Fcom.ibm.itim.infocenter.doc%2Fcpt%2Fcpt_ic_security_ssl_authent2way.html] or [http://www.codeproject.com/Articles/326574/An-Introduction-to-Mutual-SSL-Authentication]&lt;br /&gt;
&lt;br /&gt;
== Authentication and Error Messages ==&lt;br /&gt;
&lt;br /&gt;
Incorrectly implemented error messages in the case of authentication functionality can be used for the purposes of user ID and password enumeration. An application should respond (both HTTP and HTML) in a generic manner.&lt;br /&gt;
&lt;br /&gt;
==== Authentication Responses ====&lt;br /&gt;
&lt;br /&gt;
An application should respond with a generic error message regardless of whether the user ID or password was incorrect. It should also give no indication to the status of an existing account.&lt;br /&gt;
&lt;br /&gt;
==== Incorrect Response Examples ====&lt;br /&gt;
&lt;br /&gt;
*&amp;quot;Login for User foo: invalid password&amp;quot; &lt;br /&gt;
*&amp;quot;Login failed, invalid user ID&amp;quot; &lt;br /&gt;
*&amp;quot;Login failed; account disabled&amp;quot; &lt;br /&gt;
*&amp;quot;Login failed; this user is not active&amp;quot;&lt;br /&gt;
&lt;br /&gt;
==== Correct Response Example ====&lt;br /&gt;
&lt;br /&gt;
*&amp;quot;Login failed; Invalid userID or password&amp;quot;&lt;br /&gt;
&lt;br /&gt;
The correct response does not indicate if the user ID or password is the incorrect parameter and hence inferring a valid user ID. &lt;br /&gt;
&lt;br /&gt;
==== Error Codes and URL's ====&lt;br /&gt;
&lt;br /&gt;
The application may return a different HTTP Error code depending on the authentication attempt response. It may respond with a 200 for a positive result and a 403 for a negative result. Even though a generic error page is shown to a user, the HTTP response code may differ which can leak information about whether the account is valid or not.&lt;br /&gt;
&lt;br /&gt;
== Transmit Passwords Only Over TLS ==&lt;br /&gt;
&lt;br /&gt;
See: [[Transport Layer Protection Cheat Sheet]]&lt;br /&gt;
&lt;br /&gt;
The login page and all subsequent authenticated pages must be exclusively accessed over TLS. The initial login page, referred to as the &amp;quot;login landing page&amp;quot;, must be served over TLS. Failure to utilize TLS for the login landing page allows an attacker to modify the login form action, causing the user's credentials to be posted to an arbitrary location. Failure to utilize TLS for authenticated pages after the login enables an attacker to view the unencrypted session ID and compromise the user's authenticated session.&lt;br /&gt;
&lt;br /&gt;
== Implement Account Lockout ==&lt;br /&gt;
&lt;br /&gt;
If an attacker is able to guess passwords without the account becoming disabled due to failed authentication attempts, the attacker has an opportunity to continue with a brute force attack until the account is compromised. &lt;br /&gt;
&lt;br /&gt;
Automating brute-force/password guessing attacks on web applications is a trivial challenge. Password lockout mechanisms should be employed that lock out an account if more than a preset number of unsuccessful login attempts are made. &lt;br /&gt;
&lt;br /&gt;
Password lockout mechanisms have a logical weakness. An attacker that undertakes a large number of authentication attempts on known account names can produce a result that locks out entire blocks of user accounts. &lt;br /&gt;
&lt;br /&gt;
Given that the intent of a password lockout system is to protect from brute-force attacks, a sensible strategy is to lockout accounts for a period of time (e.g., 20 minutes). This significantly slows down attackers, while allowing the accounts to reopen automatically for legitimate users.&lt;br /&gt;
&lt;br /&gt;
= Use of authentication protocols that require no password =&lt;br /&gt;
&lt;br /&gt;
While authentication through a user/password combination and using multi-factor authentication is considered generally secure, there are use cases where it isn't considered the best option or even safe. An example of this are third party applications that desire connecting to the web application, either from a mobile device, another website, desktop or other situations. When this happens, it is NOT considered safe to allow the third party application to store the user/password combo, since then it extends the attack surface into their hands, where it isn't in your control. For this, and other use cases, there are several authentication protocols that can protect you from exposing your users' data to attackers.&lt;br /&gt;
&lt;br /&gt;
== OAuth ==&lt;br /&gt;
&lt;br /&gt;
Open Authorization (OAuth) is a protocol that allows an application to authenticate against a server as a user, without requiring passwords or any third party server that acts as an identity provider. It uses a token generated by the server, and provides how the authorization flows most occur, so that a client, such as a mobile application, can tell the server what user is using the service. &lt;br /&gt;
&lt;br /&gt;
The recommendation is to use and implement OAuth 2.0, since the first version has been found to be vulnerable to session fixation.&lt;br /&gt;
&lt;br /&gt;
OAuth 2.0 is currently used and implemented by API's from companies such as Facebook, Google, Twitter and Microsoft.&lt;br /&gt;
&lt;br /&gt;
== OpenId ==&lt;br /&gt;
&lt;br /&gt;
OpenId is an HTTP-based protocol that uses identity providers to validate that a user is who he says he is. It is a very simple protocol which allows a service provider initiated way for single sign-on (SSO). This allows the user to re-use a single identity given to a trusted OpenId identity provider and be the same user in multiple websites, without the need to provide any website the password, except for the OpenId identity provider.&lt;br /&gt;
&lt;br /&gt;
Due to its simplicity and that it provides protection of passwords, OpenId has been well adopted. Some of the well known identity providers for OpenId are Stack Exchange, Google, Facebook and Yahoo!&lt;br /&gt;
&lt;br /&gt;
For non-enterprise environment, OpenId is considered a secure and often better choice, as long as the identity provider is of trust.&lt;br /&gt;
&lt;br /&gt;
== SAML ==&lt;br /&gt;
&lt;br /&gt;
Security Assertion Markup Language (SAML) is often considered to compete with OpenId. The most recommended version is 2.0, since it is very feature complete and provides a strong security. Like with OpenId, SAML uses identity providers, but unlike it, it is XML-based and provides more flexibility. SAML is based on browser redirects which send XML data. Unlike SAML, it isn't only initiated by a service provider, but it can also be initiated from the identity provider. This allows the user to navigate through different portals while still being authenticated without having to do anything, making the process transparent.&lt;br /&gt;
&lt;br /&gt;
While OpenId has taken most of the consumer market, SAML is often the choice for enterprise applications. The reason for this is often that there are few OpenId identity providers which are considered of enterprise class (meaning that the way they validate the user identity doesn't have high standards required for enterprise identity). It is more common to see SAML being used inside of intranet websites, sometimes even using a server from the intranet as the identity provider.&lt;br /&gt;
&lt;br /&gt;
In the past few years, applications like SAP ERP and SharePoint (SharePoint by using Active Directory Federation Services 2.0) have decided to use SAML 2.0 authentication as an often preferred method for single sign-on implementations whenever enterprise federation is required for web services and web applications.&lt;br /&gt;
&lt;br /&gt;
= Session Management General Guidelines  =&lt;br /&gt;
&lt;br /&gt;
Session management is directly related to authentication. The '''Session Management General Guidelines''' previously available on this OWASP Authentication Cheat Sheet have been integrated into the new [https://www.owasp.org/index.php/Session_Management_Cheat_Sheet OWASP Session Management Cheat Sheet]. &lt;br /&gt;
&lt;br /&gt;
= Password Managers =&lt;br /&gt;
&lt;br /&gt;
Password managers are programs, browser plugins or web services that automate management of large number of different credentials, including memorizing and filling-in, generating random passwords on different sites etc. The web application can help password managers by:&lt;br /&gt;
&lt;br /&gt;
* using standard HTML forms for username and password input,&lt;br /&gt;
* not using multi-stage login schemes (username on first screen, then password),&lt;br /&gt;
* not using highly scripted (JavaScript) authentication schemes.&lt;br /&gt;
&lt;br /&gt;
= Authors and Primary Editors  =&lt;br /&gt;
&lt;br /&gt;
Eoin Keary eoinkeary[at]owasp.org &lt;br /&gt;
&lt;br /&gt;
= Other Cheatsheets =&lt;br /&gt;
{{Cheatsheet_Navigation}}&lt;br /&gt;
&lt;br /&gt;
[[Category:Cheatsheets]]&lt;/div&gt;</summary>
		<author><name>Manuel Aude Morales</name></author>	</entry>

	<entry>
		<id>https://wiki.owasp.org/index.php?title=PHP_Security_Cheat_Sheet&amp;diff=148239</id>
		<title>PHP Security Cheat Sheet</title>
		<link rel="alternate" type="text/html" href="https://wiki.owasp.org/index.php?title=PHP_Security_Cheat_Sheet&amp;diff=148239"/>
				<updated>2013-03-20T20:59:35Z</updated>
		
		<summary type="html">&lt;p&gt;Manuel Aude Morales: Added an &amp;quot;Untrusted data&amp;quot; section. Specified not to trust the FILES array.  Added a comment on encoding as string all types indicating to still avoid it and pointing to prepared statements section.&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= DRAFT CHEAT SHEET - WORK IN PROGRESS =&lt;br /&gt;
= Introduction  =&lt;br /&gt;
This page intends to provide quick basic PHP security tips for developers and administrators. Keep in mind that tips mentioned in this page are not enough for securing your web application.&lt;br /&gt;
&lt;br /&gt;
this document is organized with regards to OWASP TOP 10. Solving more common issues helps reduce overal insecurity of &lt;br /&gt;
&lt;br /&gt;
==PHP status on the web==&lt;br /&gt;
PHP is the most commonly used server-side programming language and 72% of web servers deploy PHP. PHP is totally open source and almost no commercial giant supports it. PHP core is considerably secure, but it's plugins, libraries and third party tools are usually unsafe. Also no default security mechanism is included in PHP (there were some in the old days, but they ruined things usually). &lt;br /&gt;
&lt;br /&gt;
PHP developers are usually more informative than ASPX or JSP developers on how web and HTTP works, and that makes for better coding practices, but they both lack basic security knowledge. Other languages have built-in security mechanisms, that's why PHP websites are more flawed these days. &lt;br /&gt;
&lt;br /&gt;
==Update PHP Now==&lt;br /&gt;
'''Important Note: ''' PHP 5.2.x is officially unsupported now. This means that in the near future, when a common security flaw on PHP 5.2.x is discovered, every PHP 5.2.x powered website is bound to be hacked. ''It is of utmost important that you upgrade your PHP to 5.3.x or 5.4.x right now.''&lt;br /&gt;
&lt;br /&gt;
Also keep in mind that you should regularly upgrade your PHP distribution on an operational server. Every day new flaws are discovered and announced in PHP and attackers use these new flaws on random servers frequently.&lt;br /&gt;
&lt;br /&gt;
=Untrusted data=&lt;br /&gt;
All data that is a product, or subproduct, of user input is to NOT be trusted. They have to either be validated, using the correct methodology, or filtered, before considering them untainted.&lt;br /&gt;
&lt;br /&gt;
Super globals which are not to be trusted are $_SERVER, $_GET, $_POST, $_REQUEST, $_FILES and $_COOKIE. Not all data in $_SERVER can be faked by the user, but a considerable amount in it can, particularly and specially everything that deals with HTTP headers (they start with HTTP_).&lt;br /&gt;
&lt;br /&gt;
==Common mistakes on the processing of $_FILES array==&lt;br /&gt;
It is common to find code snippets online doing something similar to the following code:&lt;br /&gt;
&lt;br /&gt;
    if ($_FILES['some_name']['type'] == 'image/jpeg') {  &lt;br /&gt;
        //Proceed to accept the file as a valid image&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
However, the type is not determined by using heuristics that validate it, but by simply reading the data sent by the HTTP request, which is created by a client. A better, yet not perfect, way of validating file types is to use finfo class.&lt;br /&gt;
&lt;br /&gt;
    $finfo = new finfo(FILEINFO_MIME_TYPE);&lt;br /&gt;
    $fileContents = file_get_contents($_FILES['some_name']['tmp_name']);&lt;br /&gt;
    $mimeType = $finfo-&amp;gt;buffer($fileContents);&lt;br /&gt;
&lt;br /&gt;
Where $mimeType is a better checked file type. This uses more resources on the server, but can prevent the user from sending a dangerous file and fooling the code into trusting it as an image, which would normally be regarded as a safe file type.&lt;br /&gt;
&lt;br /&gt;
==Use of $_REQUEST==&lt;br /&gt;
Using $_REQUEST is strongly discouraged. This super global is not recommended since it includes not only POST and GET data, but also the cookies sent by the request. This can lead into confusion and makes your code prompt to mistakes, which could lead to security problems.&lt;br /&gt;
&lt;br /&gt;
=Database Cheat Sheet=&lt;br /&gt;
Since a single SQL Injection vulnerability makes for hacking of your website, and every hacker first tries SQL injection flaws, fixing SQL injections are first step to securing your PHP powered application. Abide to the following rules:&lt;br /&gt;
&lt;br /&gt;
==Encoding Issues==&lt;br /&gt;
===Everything is a string for a database===&lt;br /&gt;
There are ways to send different data types to a database, ints, floats, etc. Never rely on them, instead always send an string to the database. Database engines type cast automatically if they need to. This makes for much safer queries. Make this a habit of yours, and see how many time it saves you. Still, do not concatenate without escaping the values. Check the [[#Use Prepared Statements|Use Prepared Statements]].&lt;br /&gt;
&lt;br /&gt;
====Wrong====&lt;br /&gt;
 $x=1; &lt;br /&gt;
 SELECT * FROM users WHERE ID &amp;gt; $x&lt;br /&gt;
====Right====&lt;br /&gt;
 $x=1; // or $x='1';&lt;br /&gt;
 SELECT * FROM users WHERE ID &amp;gt;'$x';&lt;br /&gt;
&lt;br /&gt;
===Use UTF-8 unless necessary===&lt;br /&gt;
Many new attack vectors rely on encoding bypassing. Use UTF-8 as your database and application charset unless you have a mandatory requirement to use another encoding.&lt;br /&gt;
&lt;br /&gt;
    $DB = new mysqli($Host, $Username, $Password, $DatabaseName);&lt;br /&gt;
    if (mysqli_connect_errno())&lt;br /&gt;
        trigger_error(&amp;quot;Unable to connect to MySQLi database.&amp;quot;);&lt;br /&gt;
    $DB-&amp;gt;set_charset('UTF-8');&lt;br /&gt;
&lt;br /&gt;
==Escaping is not safe== &lt;br /&gt;
'''mysql_real_escape_string''' is not safe. Don't rely on it for your SQL injection prevention.&lt;br /&gt;
&lt;br /&gt;
'''Why:'''&lt;br /&gt;
When you use mysql_real_escape_string on every variable and then concat it to your query, ''you are bound to forget that at least once'', and one is all it takes. You can't force yourself in any way to never forget. Number fields might also be vulnerable if not used as strings. Instead use prepared statements or equivalent.&lt;br /&gt;
&lt;br /&gt;
==Use Prepared Statements==&lt;br /&gt;
Prepared statements are very secure. In a prepared statement, data is separated from the SQL command, so that everything user inputs is considered data and put into the table the way it was. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
====MySQLi Prepared Statements Wrapper====&lt;br /&gt;
The following function, performs a SQL query, returns its results as a 2D array (if query was SELECT) and does all that with prepared statements using MySQLi fast MySQL interface:&lt;br /&gt;
&lt;br /&gt;
    $DB = new mysqli($Host, $Username, $Password, $DatabaseName);&lt;br /&gt;
    if (mysqli_connect_errno())&lt;br /&gt;
        trigger_error(&amp;quot;Unable to connect to MySQLi database.&amp;quot;);&lt;br /&gt;
    $DB-&amp;gt;set_charset('UTF-8');&lt;br /&gt;
&lt;br /&gt;
    function SQL($Query) {&lt;br /&gt;
        global $DB;&lt;br /&gt;
        $args = func_get_args();&lt;br /&gt;
        if (count($args) == 1) {&lt;br /&gt;
            $result = $DB-&amp;gt;query($Query);&lt;br /&gt;
            if ($result-&amp;gt;num_rows) {&lt;br /&gt;
                $out = array();&lt;br /&gt;
                while (null != ($r = $result-&amp;gt;fetch_array(MYSQLI_ASSOC)))&lt;br /&gt;
                    $out [] = $r;&lt;br /&gt;
                return $out;&lt;br /&gt;
            }&lt;br /&gt;
            return null;&lt;br /&gt;
        } else {&lt;br /&gt;
            if (!$stmt = $DB-&amp;gt;prepare($Query))&lt;br /&gt;
                trigger_error(&amp;quot;Unable to prepare statement: {$Query}, reason: &amp;quot; . $DB-&amp;gt;error . &amp;quot;&amp;quot;);&lt;br /&gt;
            array_shift($args); //remove $Query from args&lt;br /&gt;
            //the following three lines are the only way to copy an array values in PHP&lt;br /&gt;
            $a = array();&lt;br /&gt;
            foreach ($args as $k =&amp;gt; &amp;amp;$v)&lt;br /&gt;
                $a[$k] = &amp;amp;$v;&lt;br /&gt;
            $types = str_repeat(&amp;quot;s&amp;quot;, count($args)); //all params are strings, works well on MySQL and SQLite&lt;br /&gt;
            array_unshift($a, $types);&lt;br /&gt;
            call_user_func_array(array($stmt, 'bind_param'), $a);&lt;br /&gt;
            $stmt-&amp;gt;execute();&lt;br /&gt;
            //fetching all results in a 2D array&lt;br /&gt;
            $metadata = $stmt-&amp;gt;result_metadata();&lt;br /&gt;
            $out = array();&lt;br /&gt;
            $fields = array();&lt;br /&gt;
            if (!$metadata)&lt;br /&gt;
                return null;&lt;br /&gt;
            $length = 0;&lt;br /&gt;
            while (null != ($field = mysqli_fetch_field($metadata))) {&lt;br /&gt;
                $fields [] = &amp;amp;$out [$field-&amp;gt;name];&lt;br /&gt;
                $length+=$field-&amp;gt;length;&lt;br /&gt;
            }&lt;br /&gt;
            call_user_func_array(array(&lt;br /&gt;
                $stmt, &amp;quot;bind_result&amp;quot;&lt;br /&gt;
                    ), $fields);&lt;br /&gt;
            $output = array();&lt;br /&gt;
            $count = 0;&lt;br /&gt;
            while ($stmt-&amp;gt;fetch()) {&lt;br /&gt;
                foreach ($out as $k =&amp;gt; $v)&lt;br /&gt;
                    $output [$count] [$k] = $v;&lt;br /&gt;
                $count++;&lt;br /&gt;
            }&lt;br /&gt;
            $stmt-&amp;gt;free_result();&lt;br /&gt;
            return ($count == 0) ? null : $output;&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
Now you could do your every query like the example below:&lt;br /&gt;
&lt;br /&gt;
 $res=SQL(&amp;quot;SELECT * FROM users WHERE ID&amp;gt;? ORDER BY ? ASC LIMIT ?&amp;quot; , 5 , &amp;quot;Username&amp;quot; , 2);&lt;br /&gt;
&lt;br /&gt;
Every instance of ? is bound with an argument of the list, not ''replaced'' with it. MySQL 5.5+ supports ? as ORDER BY and LIMIT clause specifiers. If you're using a database that doesn't support them, see next section.&lt;br /&gt;
&lt;br /&gt;
'''REMEMBER:''' When you use this approach, you should ''NEVER'' concat strings for a SQL query.&lt;br /&gt;
&lt;br /&gt;
====PDO Prepared Statement Wrapper====&lt;br /&gt;
The following function, does the same thing as the above function but using PDO. You can use it with every PDO supported driver.&lt;br /&gt;
&lt;br /&gt;
    try {&lt;br /&gt;
        $DB = new PDO(&amp;quot;{$Driver}:dbname={$DatabaseName};host={$Host};&amp;quot;, $Username, $Password);&lt;br /&gt;
    } catch (Exception $e) {&lt;br /&gt;
        trigger_error(&amp;quot;PDO connection error: &amp;quot; . $e-&amp;gt;getMessage());&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function SQL($Query) {&lt;br /&gt;
        global $DB;&lt;br /&gt;
        $args = func_get_args();&lt;br /&gt;
        if (count($args) == 1) {&lt;br /&gt;
            $result = $DB-&amp;gt;query($Query);&lt;br /&gt;
            if ($result-&amp;gt;rowCount()) {&lt;br /&gt;
                return $result-&amp;gt;fetchAll(PDO::FETCH_ASSOC);&lt;br /&gt;
            }&lt;br /&gt;
            return null;&lt;br /&gt;
        } else {&lt;br /&gt;
            if (!$stmt = $DB-&amp;gt;prepare($Query)) {&lt;br /&gt;
                $Error = $DB-&amp;gt;errorInfo();&lt;br /&gt;
                trigger_error(&amp;quot;Unable to prepare statement: {$Query}, reason: {$Error[2]}&amp;quot;);&lt;br /&gt;
            }&lt;br /&gt;
            array_shift($args); //remove $Query from args&lt;br /&gt;
            $i = 0;&lt;br /&gt;
            foreach ($args as &amp;amp;$v)&lt;br /&gt;
                $stmt-&amp;gt;bindValue(++$i, $v);&lt;br /&gt;
            $stmt-&amp;gt;execute();&lt;br /&gt;
            return $stmt-&amp;gt;fetchAll(PDO::FETCH_ASSOC);&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
 $res=SQL(&amp;quot;SELECT * FROM users WHERE ID&amp;gt;? ORDER BY ? ASC LIMIT 5&amp;quot; , 5 , &amp;quot;Username&amp;quot; );&lt;br /&gt;
&lt;br /&gt;
===Where prepared statements do not work===&lt;br /&gt;
The problem is, when you need to build dynamic queries, or need to set variables not supported as a prepared variable, or your database engine does not support prepared statements. For example, PDO MySQL does not support ? as LIMIT specifier. In these cases, you need to do two things:&lt;br /&gt;
&lt;br /&gt;
====Not Supported Fields====&lt;br /&gt;
When some field does not support binding (like LIMIT clause in PDO), you need to '''whitelist''' the data you're about to use. LIMIT always requires an integer, so cast the variable to an integer. ORDER BY needs a field name, so whitelist it with field names:&lt;br /&gt;
&lt;br /&gt;
    function whitelist($Needle,$Haystack)&lt;br /&gt;
    {&lt;br /&gt;
        if (!in_array($Needle,$Haystack))&lt;br /&gt;
                return reset($Haystack); //first element&lt;br /&gt;
        return $Needle;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    $Limit = $_GET['lim'];&lt;br /&gt;
    $Limit = $Limit * 1; //type cast, integers are safe&lt;br /&gt;
&lt;br /&gt;
    $Order = $_GET['sort'];&lt;br /&gt;
    $Order=whitelist($Order,Array(&amp;quot;ID&amp;quot;,&amp;quot;Username&amp;quot;,&amp;quot;Password&amp;quot;));&lt;br /&gt;
&lt;br /&gt;
This is very important. If you think you're tired and you rather blacklist than whitelist, you're bound to fail.&lt;br /&gt;
&lt;br /&gt;
====Dynamic Queries====&lt;br /&gt;
Now this is a highly delicate situation. Whenever hackers fail to injection SQL in your common application scenarios, they go for Advanced Search features or similars, because those features rely on dynamic queries and dynamic queries are almost always insecurely implemented.&lt;br /&gt;
&lt;br /&gt;
When you're building a dynamic query, the only way is whitelisting. Whitelist every field name, every boolean operator (it should be OR or AND, nothing else) and after building your query, use prepared statements:&lt;br /&gt;
&lt;br /&gt;
    $Query=&amp;quot;SELECT * FROM table WHERE &amp;quot;;&lt;br /&gt;
    foreach ($_GET['fields'] as $g)&lt;br /&gt;
        $Query.=whitelist($g,Array(&amp;quot;list&amp;quot;,&amp;quot;of&amp;quot;,&amp;quot;possible&amp;quot;,&amp;quot;fields&amp;quot;,&amp;quot;here&amp;quot;)).&amp;quot;=?&amp;quot;;&lt;br /&gt;
    $Values=$_GET['values'];&lt;br /&gt;
    array_unshift($Query); //add to the beginning&lt;br /&gt;
    $res=call_user_func_array(SQL, $Values);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==ORM==&lt;br /&gt;
ORMs are good security practice. If you're using an ORM (like Doctrine) in your PHP project, you're mostly prone to SQL attacks. Although injecting queries in ORM's is much harder, keep in mind that concatenating ORM queries makes for the same flaws that concatenating SQL queries, so '''NEVER''' concatenate strings sent to a database. ORM's support prepared statements as well.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=Other Injection Cheat Sheet=&lt;br /&gt;
SQL aside, there are a few more injections possible ''and common'' in PHP:&lt;br /&gt;
&lt;br /&gt;
==Shell Injection==&lt;br /&gt;
A few PHP functions namely&lt;br /&gt;
&lt;br /&gt;
* shell_exec&lt;br /&gt;
* exec&lt;br /&gt;
* passthru&lt;br /&gt;
* system&lt;br /&gt;
* [http://no2.php.net/manual/en/language.operators.execution.php backtick operator] ( ` )&lt;br /&gt;
&lt;br /&gt;
run a string as shell scripts and commands. Input provided to these functions (specially backtick operator that is not like a function). Depending on your configuration, shell script injection can cause your application settings and configuration to leak, or your whole server to be hijacked. This is a very dangerous injection and is somehow considered the haven of an attacker.&lt;br /&gt;
&lt;br /&gt;
Never pass tainted input to these functions - that is input somehow manipulated by the user - unless you're absolutely sure there's no way for it to be dangerous (which you never are without whitelisting). Escaping and any other countermeasures are ineffective, there are plenty of vectors for bypassing each and every one of them; don't believe what novice developers tell you. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Code Injection==&lt;br /&gt;
All interpreted languages such as PHP, have some function that accepts a string and runs that in that language. It is usually named Eval. PHP also has Eval.&lt;br /&gt;
Using Eval is a very bad practice, not just for security. If you're absolutely sure you have no other way but eval, use it without any tainted input.&lt;br /&gt;
&lt;br /&gt;
Reflection also could have code injection flaws. Refer to the appropriate reflection documentations, since it is an advanced topic.&lt;br /&gt;
 &lt;br /&gt;
==Other Injections==&lt;br /&gt;
LDAP, XPath and any other third party application that runs a string, is vulnerable to injection. Always keep in mind that some strings are not data, but commands and thus should be secure before passing to third party libraries.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=XSS Cheat Sheet=&lt;br /&gt;
&lt;br /&gt;
There are two scenarios when it comes to XSS, each one to be mitigated accordingly:&lt;br /&gt;
&lt;br /&gt;
==No Tags==&lt;br /&gt;
Most of the time, output needs no HTML tags. For example when you're about to dump a textbox value, or output user data in a cell. In this scenarios, you can mitigate XSS by simply using the function below. '''Keep in mind that this scenario won't mitigate XSS when you use user input in dangerous elements (style, script, image's src, a, etc.)''', but mostly you don't. Also keep in mind that every output that is not intended to contain HTML tags should be sent to the browser filtered with the following function.&lt;br /&gt;
&lt;br /&gt;
 //xss mitigation functions&lt;br /&gt;
 function xssafe($data,$encoding='UTF-8')&lt;br /&gt;
 {&lt;br /&gt;
 	return htmlspecialchars($data,ENT_QUOTES | ENT_HTML401,$encoding);&lt;br /&gt;
 }&lt;br /&gt;
 function xecho($data)&lt;br /&gt;
 {&lt;br /&gt;
 	echo xssafe($data);&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 //usage example&lt;br /&gt;
 &amp;lt;input type='text' name='test' value='&amp;lt;?php &lt;br /&gt;
 xecho (&amp;quot;' onclick='alert(1)&amp;quot;);&lt;br /&gt;
 ?&amp;gt;' /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Yes Tags==&lt;br /&gt;
When you need tags in your output, such as rich blog comments, forum posts, blog posts and etc., you have to use a '''Secure Encoding''' library. This is usually hard and slow, and that's why most applications have XSS vulnerabilities in them. OWASP ESAPI has a bunch of codecs for encoding different sections of data. There's also OWASP AntiSammy and HTMLPurifier for PHP. Each of these require lots of configuration and learning to perform well, but you need them when you want that good of an application.&lt;br /&gt;
&lt;br /&gt;
==Templating engines==&lt;br /&gt;
&lt;br /&gt;
There are several templating engines that can help the programmer (and designer) to output data without exposing it too much against XSS vulnerabilities. While their primary goal isn't security, but improving the designing experience, most important templating engines automatically escape the variables on output and force the developer to explicitly indicate if there is a variable that shouldn't be escaped. This makes output of variables have a white-list behavior. There exist several of these engines. A good example is twig[http://twig.sensiolabs.org/]. Other popular template engines are Smarty, Haanga and Rain TPL.&lt;br /&gt;
&lt;br /&gt;
The advantage of following a white-list approach is that the programmer should be less prone to forget about using a function call to clean the output of a variable.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Other Tips==&lt;br /&gt;
&lt;br /&gt;
* We don't have a '''trusted section''' in any web application. Many developers tend to leave admin areas out of XSS mitigation, but most intruders are interested in admin cookies and XSS. Every output should be cleared by the functions provided above, if it has a variable in it. Remove every instance of echo, print, and printf from your application and replace them with the above statement when you see a variable is included, no harm comes with that.&lt;br /&gt;
&lt;br /&gt;
* HTTP-Only cookies are a very good practice, for a near future when every browser is compatible. Start using them now. (See PHP.ini configuration for best practice)&lt;br /&gt;
&lt;br /&gt;
* The function declared above, only works for valid HTML syntax. If you put your Element Attributes without quotation, you're doomed. Go for valid HTML.&lt;br /&gt;
&lt;br /&gt;
* [[Reflected XSS]] is as dangerous as normal XSS, and usually comes at the most dusty corners of an application. Seek it and mitigate it.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=CSRF Cheat Sheet=&lt;br /&gt;
CSRF mitigation is easy in theory, but hard to implement correctly. First, a few tips about CSRF:&lt;br /&gt;
&lt;br /&gt;
* Every request that does something noteworthy, should be CSRF mitigated. Noteworthy things are changes to the system, and reads that take a long time.&lt;br /&gt;
* CSRF mostly happens on GET, but is easy to happen on POST. Don't ever think that post is secure.&lt;br /&gt;
&lt;br /&gt;
The [[PHP_CSRF_Guard|OWASP PHP CSRFGuard]] is a code snippet that shows how to mitigate CSRF. Only copy pasting it is not enough. In the near future, a copy-pasteable version  would be available (hopefully). For now, mix that with the following tips:&lt;br /&gt;
&lt;br /&gt;
* Use re-authentication for critical operations (change password, recovery email, etc.)&lt;br /&gt;
* If you're not sure whether your operation is CSRF proof, consider adding CAPTCHAs (however CAPTCHAs are inconvenience for users)&lt;br /&gt;
* If you're performing operations based on other parts of a request (neither GET nor POST) e.g Cookies or HTTP Headers, you might need to add CSRF tokens there as well.&lt;br /&gt;
* AJAX powered forms need to re-create their CSRF tokens. Use the function provided above (in code snippet) for that and never rely on Javascript.&lt;br /&gt;
* CSRF on GET or Cookies will lead to inconvenience, consider your design and architecture for best practices.&lt;br /&gt;
&lt;br /&gt;
=Authentication and Session Management Cheat Sheet=&lt;br /&gt;
PHP doesn't ship with a readily available authentication module, you need to implement your own or use a PHP framework, unfortunately most PHP frameworks are far from perfect in this manner, due to the fact that they are developed by open source developer community rather than security experts. A few instructive and useful tips are listed below:&lt;br /&gt;
 &lt;br /&gt;
==Session Management==&lt;br /&gt;
PHP's default session facilites are considered safe, the generated PHPSessionID is random enough, but the storage is not necessarily safe:&lt;br /&gt;
&lt;br /&gt;
* Session files are stored in temp (/tmp) folder and are world writable unless suPHP installed, so any LFI or other leak might end-up manipulating them.&lt;br /&gt;
* Sessions are stored in files in default configuration, which is terribly slow for highly visited websites. You can store them on a memory folder (if UNIX).&lt;br /&gt;
* You can implement your own session mechanism, without ever relying on PHP for it. If you did that, store session data in a database. You could use all, some or none of the PHP functionality for session handling if you go with that.&lt;br /&gt;
&lt;br /&gt;
===Session Hijacking Prevention===&lt;br /&gt;
It is good practice to bind sessions to IP addresses, that would prevent most session hijacking scenarios (but not all), however some users might use anonymity tools (such as TOR) and they would have problems with your service.&lt;br /&gt;
&lt;br /&gt;
To implement this, simply store the client IP in the session first time it is created, and enforce it to be the same afterwards. The code snippet below returns client IP address:&lt;br /&gt;
&lt;br /&gt;
 $IP = (getenv ( &amp;quot;HTTP_X_FORWARDED_FOR&amp;quot; )) ? getenv ( &amp;quot;HTTP_X_FORWARDED_FOR&amp;quot; ) : getenv ( &amp;quot;REMOTE_ADDR&amp;quot; );&lt;br /&gt;
&lt;br /&gt;
Keep in mind that in local environments, a valid IP is not returned, and usually the string ''':::1''' or ''':::127''' might pop up, thus adapt your IP checking logic.&lt;br /&gt;
&lt;br /&gt;
===Invalidate Session ID===&lt;br /&gt;
You should invalidate (unset cookie, unset session storage, remove traces) of a session whenever a violation occurs (e.g 2 IP addresses are observed). A log event would prove useful. Many applications also notify the logged in user (e.g GMail).&lt;br /&gt;
&lt;br /&gt;
===Rolling of Session ID===&lt;br /&gt;
You should roll session ID whenever elevation occurs, e.g when a user logs in, the session ID of the session should be changed, since it's importance is changed.&lt;br /&gt;
&lt;br /&gt;
===Exposed Session ID===&lt;br /&gt;
Session IDs are considered confidential, your application should not expose them anywhere (specially when bound to a logged in user). Try not to use URLs as session ID medium.&lt;br /&gt;
&lt;br /&gt;
Transfer session ID over TLS whenever session holds confidential information, otherwise a passive attacker would be able to perform session hijacking.&lt;br /&gt;
&lt;br /&gt;
===Session Fixation===&lt;br /&gt;
Session IDs are to be generated by your application only. Never create a session only because you receive the session ID from the client, the only source of creating a session should be a secure random generator.&lt;br /&gt;
&lt;br /&gt;
===Session Expiration===&lt;br /&gt;
A session should expire after a certain amount of inactivity, and after a certain time of activity as well. The expiration process means invalidating and removing a session, and creating a new one when another request is met.&lt;br /&gt;
&lt;br /&gt;
Also keep the '''log out''' button close, and unset all traces of the session on log out.&lt;br /&gt;
&lt;br /&gt;
====Inactivity Timeout====&lt;br /&gt;
Expire a session if current request is X seconds later than the last request. For this you should update session data with time of the request each time a request is made. The common practice time is 30 minutes, but highly depends on application criteria. &lt;br /&gt;
&lt;br /&gt;
This expiration helps when a user is logged in on a publicly accessible machine, but forgets to log out. It also helps with session hijacking.&lt;br /&gt;
&lt;br /&gt;
====General Timeout====&lt;br /&gt;
Expire a session if current session has been active for a certain amount of time, even if active. This helps keeping track of things. The amount differs but something between a day and a week is usually good. To implement this you need to store start time of a session.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Cookies===&lt;br /&gt;
Handling cookies in a PHP script has some tricks to it:&lt;br /&gt;
&lt;br /&gt;
====Never Serialize====&lt;br /&gt;
Never serialize data stored in a cookie. It can easily be manipulated, resulting in adding variables to your scope.&lt;br /&gt;
&lt;br /&gt;
====Proper Deletion====&lt;br /&gt;
To delete a cookie safely, use the following snippet:&lt;br /&gt;
&lt;br /&gt;
 setcookie ($name, &amp;quot;&amp;quot;, 1);&lt;br /&gt;
 setcookie ($name, false);&lt;br /&gt;
 unset($_COOKIE[$name]);&lt;br /&gt;
The first line ensures that cookie expires in browser, the second line is the standard way of removing a cookie (thus you can't store false in a cookie). The third line removes the cookie from your script. Many guides tell developers to use time() - 3600 for expiry, but it might not work if browser time is not correct.&lt;br /&gt;
&lt;br /&gt;
You can also use '''session_name()''' to retrieve the name default PHP session cookie.&lt;br /&gt;
&lt;br /&gt;
====HTTP Only====&lt;br /&gt;
Most modern browsers support HTTP-only cookies. These cookies are only accessible via HTTP(s) requests and not Javascript, so XSS snippets can not access them. They are very good practice, but are not satisfactory since there are many flaws discovered in major browsers that lead to exposure of HTTP only cookies to javascript.&lt;br /&gt;
&lt;br /&gt;
To use HTTP-only cookies in PHP (5.2+), you should perform session cookie setting [http://php.net/manual/en/function.setcookie.php manually] (not using '''session_start'''):&lt;br /&gt;
 &lt;br /&gt;
 #prototype&lt;br /&gt;
 bool setcookie ( string $name [, string $value [, int $expire = 0 [, string $path [, string $domain [, bool $secure = false [, bool $httponly = false ]]]]]] )&lt;br /&gt;
&lt;br /&gt;
 #usage&lt;br /&gt;
 if (!setcookie(&amp;quot;MySessionID&amp;quot;, $secureRandomSessionID, $generalTimeout, $applicationRootURLwithoutHost, NULL, NULL,true))&lt;br /&gt;
     echo (&amp;quot;could not set HTTP-only cookie&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
The '''path''' parameter sets the path which cookie is valid for, e.g if you have your website at example.com/some/folder the path should be /some/folder or other applications residing at example.com could also see your cookie. If you're on a whole domain, don't mind it. '''Domain''' parameter enforces the domain, if you're accessible on multiple domains or IPs ignore this, otherwise set it accordingly. If '''secure''' parameter is set, cookie can only be transmitted over HTTPS. See the example below:&lt;br /&gt;
&lt;br /&gt;
 $r=setcookie(&amp;quot;SECSESSID&amp;quot;,&amp;quot;1203j01j0s1209jw0s21jxd01h029y779g724jahsa9opk123973&amp;quot;,time()+60*60*24*7 /*a week*/,&amp;quot;/&amp;quot;,&amp;quot;owasp.org&amp;quot;,true,true);&lt;br /&gt;
 if (!$r) die(&amp;quot;Could not set session cookie.&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
====Internet Explorer issues====&lt;br /&gt;
Many version of Internet Explorer tend to have problems with cookies. Mostly setting Expire time to 0 fixes their issues.&lt;br /&gt;
&lt;br /&gt;
==Authentication==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Remember Me===&lt;br /&gt;
Many websites are vulnerable on remember me features. The correct practice is to generate a one-time token for a user and store it in the cookie. The token should also reside in data store of the application to be validated and assigned to user. This token should have '''no relevance''' to username and/or password of the user, a secure long-enough random number is a good practice.&lt;br /&gt;
&lt;br /&gt;
It is better if you imply locking and prevent brute-force on remember me tokens, and make them long enough, otherwise an attacker could brute-force remember me tokens until he gets access to a logged in user without credentials.&lt;br /&gt;
&lt;br /&gt;
* '''Never store username/password or any relevant information in the cookie.'''&lt;br /&gt;
&lt;br /&gt;
=Access Control Cheat Sheet=&lt;br /&gt;
This section aims to mitigate access control issues, as well as '''Insecure Direct Object Reference''' issues. &lt;br /&gt;
&lt;br /&gt;
=Cryptography Cheat Sheet=&lt;br /&gt;
&lt;br /&gt;
=File Inclusion Cheat Sheet=&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=Configuration and Deployment Cheat Sheet=&lt;br /&gt;
Please see [[PHP Configuration Cheat Sheet]].&lt;br /&gt;
&lt;br /&gt;
=Sources of Taint=&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
= OLD. PHP General Guidelines for Secure Web Applications  =&lt;br /&gt;
&lt;br /&gt;
== PHP Version ==&lt;br /&gt;
Use '''PHP 5.3.8'''. Stable versions are always safer then the beta ones. &lt;br /&gt;
&lt;br /&gt;
== Framework==&lt;br /&gt;
Use a framework like '''Zend''' or '''Symfony'''. Try not to re-write the code again and again. Also avoid dead codes. &lt;br /&gt;
&lt;br /&gt;
== Directory==&lt;br /&gt;
Code with most of your code outside of the webroot. This is automatic for Symfony and Zend. Stick to these frameworks. &lt;br /&gt;
&lt;br /&gt;
== Hashing Extension ==&lt;br /&gt;
Not every PHP installation has a working '''mhash''' extension, so if you need to do hashing, check it before using it. Otherwise you can't do SHA-256&lt;br /&gt;
&lt;br /&gt;
== Cryptographic Extension ==&lt;br /&gt;
Not every PHP installation has a working '''mcrypt''' extension, and without it you can't do AES. Do check if you need it.&lt;br /&gt;
&lt;br /&gt;
== Authentication and Authorization ==&lt;br /&gt;
There is no authentication or authorization classes in native PHP. Use '''ZF''' or '''Symfony''' instead.&lt;br /&gt;
&lt;br /&gt;
== Input nput validation ==&lt;br /&gt;
Use $_dirty['foo'] = $_GET['foo'] and then $foo = validate_foo($dirty['foo']); &lt;br /&gt;
&lt;br /&gt;
== Use PDO or ORM ==&lt;br /&gt;
Use PDO with prepared statements or an ORM like Doctrine&lt;br /&gt;
&lt;br /&gt;
== Use PHP Unit and Jenkins ==&lt;br /&gt;
When developing PHP code, make sure you develop with PHP Unit and Jenkins - see http://qualityassuranceinphpprojects.com/pages/tools.html for more details.&lt;br /&gt;
&lt;br /&gt;
== Use Stefan Esser's Hardened PHP Patch ==&lt;br /&gt;
Consider using Stefan Esser's Hardened PHP patch - http://www.hardened-php.net/suhosin/index.html &lt;br /&gt;
(not maintained now, but the concepts are very powerful)&lt;br /&gt;
&lt;br /&gt;
== Avoid Global Variables==&lt;br /&gt;
In terms of secure coding with PHP, do not use globals unless absolutely necessary &lt;br /&gt;
Check your php.ini to ensure register_globals is off Do not run at all with this setting enabled It's extremely dangerous (register_globals has been disabled since 5.0 / 2006, but .... most PHP 4 code needs it, so many hosters have it turned on)&lt;br /&gt;
&lt;br /&gt;
== Avoid Eval() ==&lt;br /&gt;
It basically allows arbitrary PHP code execution, so do not evaluate user supplied input. and if you're not doing that, you can just use PHP directly. eval() is at least 10-100 times slower than native PHP&lt;br /&gt;
&lt;br /&gt;
== Protection against RFI==&lt;br /&gt;
Ensure allow_url_fopen and allow_url_include are both disabled to protect against RFI  But don't cause issues by using the pattern include $user_supplied_data or require &amp;quot;base&amp;quot; + $user_supplied_data - it's just unsafe as you can input /etc/passwd and PHP will try to include it&lt;br /&gt;
&lt;br /&gt;
== Regexes (!)==&lt;br /&gt;
Watch for executable regexes (!) &lt;br /&gt;
&lt;br /&gt;
== Session Rotation ==&lt;br /&gt;
Session rotation is very easy - just after authentication, plonk in session_regenerate_id() and you're done.&lt;br /&gt;
&lt;br /&gt;
== Be aware of PHP filters ==&lt;br /&gt;
PHP filters can be tricky and complex. Be extra-conscious when using them. &lt;br /&gt;
&lt;br /&gt;
== Logging ==&lt;br /&gt;
Set display_errors to 0, and set up logging to go to a file you control, or at least syslog. This is the most commonly neglected area of PHP configuration&lt;br /&gt;
&lt;br /&gt;
== Output encoding ==&lt;br /&gt;
Output encoding is entirely up to you. Just do it, ESAPI for PHP is ready for this job.&lt;br /&gt;
&lt;br /&gt;
These are transparent to you and you need to know about them. php://input: takes input from the console gzip: takes compressed input and might bypass input validation http://au2.php.net/manual/en/filters.php &lt;br /&gt;
&lt;br /&gt;
= Authors and Primary Editors  =&lt;br /&gt;
&lt;br /&gt;
[[User:Abbas Naderi|Abbas Naderi Afooshteh]] ([mailto:abbas.naderi@owasp.org abbas.naderi@owasp.org])&lt;br /&gt;
&lt;br /&gt;
[[User:Achim|Achim]] - [mailto:achim_at_owasp.org Achim at owasp.org]&lt;br /&gt;
&lt;br /&gt;
[mailto:vanderaj@owasp.org Andrew van der Stock]&lt;br /&gt;
&lt;br /&gt;
= Other Cheatsheets =&lt;br /&gt;
{{Cheatsheet_Navigation}}&lt;br /&gt;
&lt;br /&gt;
[[Category:Cheatsheets]]&lt;/div&gt;</summary>
		<author><name>Manuel Aude Morales</name></author>	</entry>

	<entry>
		<id>https://wiki.owasp.org/index.php?title=Password_Storage_Cheat_Sheet&amp;diff=148231</id>
		<title>Password Storage Cheat Sheet</title>
		<link rel="alternate" type="text/html" href="https://wiki.owasp.org/index.php?title=Password_Storage_Cheat_Sheet&amp;diff=148231"/>
				<updated>2013-03-20T20:12:41Z</updated>
		
		<summary type="html">&lt;p&gt;Manuel Aude Morales: Grouped the information regarding work factor to avoid being redundant, while still adding more information. Added an example of the number of iterations used by a large company.&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Introduction =&lt;br /&gt;
&lt;br /&gt;
Media covers the theft of large collections of passwords on an almost daily basis. Media coverage of password theft discloses the password storage scheme, the weakness of that scheme, and often discloses a large population of compromised credentials that can affect multiple web sites or other applications. This article provides guidance on properly storing passwords, secret question responses, and similar credential information. Proper storage helps prevent theft, compromise, and malicious use of credentials.&lt;br /&gt;
Information systems store passwords and other credentials in a variety of protected forms. Common vulnerabilities allow the theft of protected passwords through attack vectors such as SQL Injection. Protected passwords can also be stolen from artifacts such as logs, dumps, and backups.&lt;br /&gt;
&lt;br /&gt;
Specific guidance herein protects against stored credential theft but the bulk of guidance aims to prevent credential compromise. That is, this guidance helps designs resist revealing users’ credentials or allowing system access in the event threats steal protected credential information. For more information and a thorough treatment of this topic, refer to the Secure Password Storage Threat Model here [http://goo.gl/Spvzs http://goo.gl/Spvzs].&lt;br /&gt;
&lt;br /&gt;
= Guidance =&lt;br /&gt;
&lt;br /&gt;
==  Do not limit the character set or length of credentials ==&lt;br /&gt;
&lt;br /&gt;
Some organizations restrict the 1) types of special characters and 2) length of credentials accepted by systems because of their inability to prevent SQL Injection, Cross-site scripting, command-injection and other forms of injection attacks. These restrictions, while well-intentioned, facilitate certain simple attacks such as brute force.&lt;br /&gt;
&lt;br /&gt;
Do not apply length, character set, or encoding restrictions on the entry or storage of credentials. Continue applying encoding, escaping, masking, outright omission, and other best practices to eliminate injection risks.&lt;br /&gt;
&lt;br /&gt;
== Use a cryptographically strong credential-specific salt ==&lt;br /&gt;
&lt;br /&gt;
A salt is fixed-length cryptographically-strong random value. Append credential data to the salt and use this as input to a protective function. Store the protected form appended to the salt as follows:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;[protected form] = [salt] + protect([protection func], [salt] + [credential]);&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Follow these practices to properly implement credential-specific salts:&lt;br /&gt;
&lt;br /&gt;
* Generate a unique salt upon creation of each stored credential (not just per user or system wide);&lt;br /&gt;
* Use cryptographically-strong random [*3] data;&lt;br /&gt;
* As storage permits, use a 32bit or 64b salt (actual size dependent on protection function);&lt;br /&gt;
* Scheme security does not depend on hiding, splitting, or otherwise obscuring the salt.&lt;br /&gt;
&lt;br /&gt;
Salts serve two purposes: 1) prevent the protected form from revealing two identical credentials and 2) augment entropy fed to protecting function without relying on credential complexity. The second aims to make pre-computed lookup attacks [*2] on an individual credential and time-based attacks on a population intractable.&lt;br /&gt;
&lt;br /&gt;
== Impose infeasible verification on attacker ==&lt;br /&gt;
&lt;br /&gt;
The function used to protect stored credentials should balance attacker and defender verification. The defender needs an acceptable response time for verification of users’ credentials during peak use. However, the time required to map &amp;lt;code&amp;gt;&amp;lt;credential&amp;gt; → &amp;lt;protected form&amp;gt;&amp;lt;/code&amp;gt;  must remain beyond threats’ hardware (GPU, FPGA) and technique (dictionary-based, brute force, etc) capabilities.&lt;br /&gt;
&lt;br /&gt;
Two approaches facilitate this, each imperfectly.&lt;br /&gt;
&lt;br /&gt;
=== Leverage an adaptive one-way function ===&lt;br /&gt;
&lt;br /&gt;
Adaptive one-way functions compute a one-way (irreversible) transform. Each function allows configuration of ‘work factor’. Underlying mechanisms used to achieve irreversibility and govern work factors (such as time, space, and parallelism) vary between functions and remain unimportant to this discussion. &lt;br /&gt;
&lt;br /&gt;
Select:&lt;br /&gt;
&lt;br /&gt;
* PBKDF2 [*4] when FIPS certification or enterprise support on many platforms is required;&lt;br /&gt;
* Scrypt [*5] where resisting any/all hardware accelerated attacks is necessary but support isn’t.&lt;br /&gt;
&lt;br /&gt;
Example protect() pseudo-code follows:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;return [salt] + pbkdf2([salt], [credential], c=10000); &amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Designers select one-way adaptive functions to implement protect() because these functions can be configured to cost (linearly or exponentially) more than a hash function to execute. Defenders adjust work factor to keep pace with threats’ increasing hardware capabilities. Those implementing adaptive one-way functions must tune work factors so as to impede attackers while providing acceptable user experience and scale. &lt;br /&gt;
&lt;br /&gt;
Additionally, adaptive one-way functions do not effectively prevent reversal of common dictionary-based credentials (users with password ‘password’) regardless of user population size or salt usage.&lt;br /&gt;
&lt;br /&gt;
==== Work Factor ====&lt;br /&gt;
&lt;br /&gt;
Since resources are normally considered limited, a common rule of thumb for tuning the work factor (or cost) is to make protect() run as slow as possible without affecting the users' experience and without increasing the need for extra hardware over budget. So, if the registration and authentication's cases accept protect() taking up to 1 second, you can tune the cost so that it takes 1 second to run on your hardware. This way, it shouldn't be so slow that your users become affected, but it should also affect the attackers' attempt as much as possible. &lt;br /&gt;
&lt;br /&gt;
While there is a minimum number of iterations recommended to ensure data safety, this value changes every year as technology improves. An example of the iteration count chosen by a well known company is the 10,000 iterations Apple uses for its iTunes passwords (using PBKDF2)[http://images.apple.com/ipad/business/docs/iOS_Security_May12.pdf](PDF file). However, it is critical to understand that a single work factor does not fit all designs. Experimentation is important.[*6]&lt;br /&gt;
&lt;br /&gt;
=== Leverage Keyed functions ===&lt;br /&gt;
&lt;br /&gt;
Keyed functions, such as HMACs, compute a one-way (irreversible) transform using a private key and given input. For example, HMACs inherit properties of hash functions including their speed, allowing for near instant verification. Key size imposes infeasible size- and/or space- requirements on compromise--even for common credentials (aka password = ‘password’).&lt;br /&gt;
Designers protecting stored credentials with keyed functions:&lt;br /&gt;
&lt;br /&gt;
* Use a single “site-wide” key;&lt;br /&gt;
* Protect this key as any private key using best practices;&lt;br /&gt;
* Store the key outside the credential store (aka: not in the database);&lt;br /&gt;
* Generate the key using cryptographically-strong pseudo-random data;&lt;br /&gt;
* Do not worry about output block size (i.e. SHA-256 vs. SHA-512).&lt;br /&gt;
&lt;br /&gt;
Example protect() pseudo-code follows:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;return [salt] + HMAC-SHA-256([key], [salt] + [credential]);  &amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Upholding security improvement over (solely) salted schemes relies on proper key management.&lt;br /&gt;
&lt;br /&gt;
== Design protection/verification for compromise ==&lt;br /&gt;
&lt;br /&gt;
The frequency and ease with which threats steal protected credentials demands “design for failure”. Having detected theft, a credential storage scheme must support continued operation by marking credential data compromised and engaging alternative credential validation workflows as follows:&lt;br /&gt;
&lt;br /&gt;
1) Protect the user’s account&lt;br /&gt;
  a. Invalidate authN ‘shortcuts’ disallowing login without 2nd factors or secret questions&lt;br /&gt;
  b. Disallow changes to account (secret questions, out of band exchange channel setup/selection, etc.)&lt;br /&gt;
&lt;br /&gt;
2) Load and use new protection scheme&lt;br /&gt;
  a. Load a new (stronger) protect(credential) function&lt;br /&gt;
  b. Include version information stored with form&lt;br /&gt;
  c. Set ‘tainted’/‘compromised’ bit until user resets credentials&lt;br /&gt;
  d. Rotate any keys and/or adjust protection function parameters (iter count)&lt;br /&gt;
  e. Increment scheme version number&lt;br /&gt;
&lt;br /&gt;
3) When user logs in:&lt;br /&gt;
  a. Validate credentials based on stored version (old or new); if old demand 2nd factor or secret answers&lt;br /&gt;
  b. Prompt user for credential change, apologize, &amp;amp; conduct OOB confirmation&lt;br /&gt;
  c. Convert stored credentials to new scheme as user successfully log in&lt;br /&gt;
&lt;br /&gt;
Supporting workflow outlined above requires tight integration with Authentication frameworks and workflows.&lt;br /&gt;
&lt;br /&gt;
= References=&lt;br /&gt;
&lt;br /&gt;
* [1] Morris, R. Thompson, K., Password Security: A Case History, 04/03/1978, p4: http://cm.bell-labs.com/cm/cs/who/dmr/passwd.ps&lt;br /&gt;
* [2] Space-based (Lookup) attacks: Space-time Tradeoff: Hellman, M., Crypanalytic Time-Memory Trade-Off, Transactions of Information Theory, Vol. IT-26, No. 4, July, 1980 http://www-ee.stanford.edu/~hellman/publications/36.pdf Rainbow Tables -http://ophcrack.sourceforge.net/tables.php&lt;br /&gt;
* [3] For example: http://docs.oracle.com/javase/6/docs/api/java/security/SecureRandom.html&lt;br /&gt;
* [4] Kalski, B., PKCS #5: Password-Based Cryptography Specification Version 2.0, IETF RFC 2898, September, 2000, p9 http://www.ietf.org/rfc/rfc2898.txt&lt;br /&gt;
* [5] Percival, C., Stronger Key Derivation Via Sequential Memory-Hard Functions, BSDCan ‘09, May, 2009 http://www.tarsnap.com/scrypt/scrypt.pdf&lt;br /&gt;
* [6] For instance, one might set work factors targeting the following run times: (1) Password-generated session key - fraction of a second; (2) User credential - ~0.5 seconds; (3) Password-generated site (or other long-lived) key - potentially a second or more.&lt;br /&gt;
&lt;br /&gt;
= Authors and Primary Editors =&lt;br /&gt;
&lt;br /&gt;
John Steven - john.steven[at]owasp.org&lt;br /&gt;
&lt;br /&gt;
= Other Cheatsheets =&lt;br /&gt;
&lt;br /&gt;
{{Cheatsheet_Navigation}}&lt;br /&gt;
&lt;br /&gt;
[[Category:Cheatsheets]]&lt;/div&gt;</summary>
		<author><name>Manuel Aude Morales</name></author>	</entry>

	<entry>
		<id>https://wiki.owasp.org/index.php?title=User:Manuel_Aude_Morales&amp;diff=148196</id>
		<title>User:Manuel Aude Morales</title>
		<link rel="alternate" type="text/html" href="https://wiki.owasp.org/index.php?title=User:Manuel_Aude_Morales&amp;diff=148196"/>
				<updated>2013-03-20T01:30:04Z</updated>
		
		<summary type="html">&lt;p&gt;Manuel Aude Morales: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;I've been a software developer for the past 8 years. I've focused myself at the web ever since I started. For the past 5 years I've worked mostly as a consultant, particularly on security related issues, but also on scalability and automation processes. I worked at Microsoft for three summers as an intern in Software Development Engineering, while I was doing my CS studies. During the third internship, I developed the current cryptography library used by several teams, following their internal rules. I've taught several advanced PHP courses to undergraduate and graduate students (not as a university professor, but affiliated with the university), as well as in two different symposiums to which I've been invited. I have also taught Node.js courses and was recently invited to give some seminars in my city on JavaScript. I currently own a start up (website should be up within the next 3 weeks, securebt.com, although it will be in Spanish, since it targets a Mexican audience) where security and privacy the most important issues. I also serve as technology adviser to another start up, particularly for software architecture and enforcing good security practices.&lt;br /&gt;
&lt;br /&gt;
Other interests apart from software and computer science are music, movies, food, writing and reading. Football (commonly called soccer in the USA) is also a big interest of mine.&lt;/div&gt;</summary>
		<author><name>Manuel Aude Morales</name></author>	</entry>

	<entry>
		<id>https://wiki.owasp.org/index.php?title=PHP_Security_Cheat_Sheet&amp;diff=148195</id>
		<title>PHP Security Cheat Sheet</title>
		<link rel="alternate" type="text/html" href="https://wiki.owasp.org/index.php?title=PHP_Security_Cheat_Sheet&amp;diff=148195"/>
				<updated>2013-03-20T01:22:40Z</updated>
		
		<summary type="html">&lt;p&gt;Manuel Aude Morales: Added template engines as an alternative against XSS.&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= DRAFT CHEAT SHEET - WORK IN PROGRESS =&lt;br /&gt;
= Introduction  =&lt;br /&gt;
This page intends to provide quick basic PHP security tips for developers and administrators. Keep in mind that tips mentioned in this page are not enough for securing your web application.&lt;br /&gt;
&lt;br /&gt;
this document is organized with regards to OWASP TOP 10. Solving more common issues helps reduce overal insecurity of &lt;br /&gt;
&lt;br /&gt;
==PHP status on the web==&lt;br /&gt;
PHP is the most commonly used server-side programming language and 72% of web servers deploy PHP. PHP is totally open source and almost no commercial giant supports it. PHP core is considerably secure, but it's plugins, libraries and third party tools are usually unsafe. Also no default security mechanism is included in PHP (there were some in the old days, but they ruined things usually). &lt;br /&gt;
&lt;br /&gt;
PHP developers are usually more informative than ASPX or JSP developers on how web and HTTP works, and that makes for better coding practices, but they both lack basic security knowledge. Other languages have built-in security mechanisms, that's why PHP websites are more flawed these days. &lt;br /&gt;
&lt;br /&gt;
==Update PHP Now==&lt;br /&gt;
'''Important Note: ''' PHP 5.2.x is officially unsupported now. This means that in the near future, when a common security flaw on PHP 5.2.x is discovered, every PHP 5.2.x powered website is bound to be hacked. ''It is of utmost important that you upgrade your PHP to 5.3.x or 5.4.x right now.''&lt;br /&gt;
&lt;br /&gt;
Also keep in mind that you should regularly upgrade your PHP distribution on an operational server. Every day new flaws are discovered and announced in PHP and attackers use these new flaws on random servers frequently.&lt;br /&gt;
&lt;br /&gt;
=Database Cheat Sheet=&lt;br /&gt;
Since a single SQL Injection vulnerability makes for hacking of your website, and every hacker first tries SQL injection flaws, fixing SQL injections are first step to securing your PHP powered application. Abide to the following rules:&lt;br /&gt;
&lt;br /&gt;
==Encoding Issues==&lt;br /&gt;
===Everything is a string for a database===&lt;br /&gt;
There are ways to send different data types to a database, ints, floats, etc. Never rely on them, instead always send an string to the database. Database engines type cast automatically if they need to. This makes for much safer queries. Make this a habit of yours, and see how many time it saves you. &lt;br /&gt;
&lt;br /&gt;
====Wrong====&lt;br /&gt;
 $x=1; &lt;br /&gt;
 SELECT * FROM users WHERE ID &amp;gt; $x&lt;br /&gt;
====Right====&lt;br /&gt;
 $x=1; // or $x='1';&lt;br /&gt;
 SELECT * FROM users WHERE ID &amp;gt;'$x';&lt;br /&gt;
&lt;br /&gt;
===Use UTF-8 unless necessary===&lt;br /&gt;
Many new attack vectors rely on encoding bypassing. Use UTF-8 as your database and application charset unless you have a mandatory requirement to use another encoding.&lt;br /&gt;
&lt;br /&gt;
    $DB = new mysqli($Host, $Username, $Password, $DatabaseName);&lt;br /&gt;
    if (mysqli_connect_errno())&lt;br /&gt;
        trigger_error(&amp;quot;Unable to connect to MySQLi database.&amp;quot;);&lt;br /&gt;
    $DB-&amp;gt;set_charset('UTF-8');&lt;br /&gt;
&lt;br /&gt;
==Escaping is not safe== &lt;br /&gt;
'''mysql_real_escape_string''' is not safe. Don't rely on it for your SQL injection prevention.&lt;br /&gt;
&lt;br /&gt;
'''Why:'''&lt;br /&gt;
When you use mysql_real_escape_string on every variable and then concat it to your query, ''you are bound to forget that at least once'', and one is all it takes. You can't force yourself in any way to never forget. Number fields might also be vulnerable if not used as strings. Instead use prepared statements or equivalent.&lt;br /&gt;
&lt;br /&gt;
==Use Prepared Statements==&lt;br /&gt;
Prepared statements are very secure. In a prepared statement, data is separated from the SQL command, so that everything user inputs is considered data and put into the table the way it was. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
====MySQLi Prepared Statements Wrapper====&lt;br /&gt;
The following function, performs a SQL query, returns its results as a 2D array (if query was SELECT) and does all that with prepared statements using MySQLi fast MySQL interface:&lt;br /&gt;
&lt;br /&gt;
    $DB = new mysqli($Host, $Username, $Password, $DatabaseName);&lt;br /&gt;
    if (mysqli_connect_errno())&lt;br /&gt;
        trigger_error(&amp;quot;Unable to connect to MySQLi database.&amp;quot;);&lt;br /&gt;
    $DB-&amp;gt;set_charset('UTF-8');&lt;br /&gt;
&lt;br /&gt;
    function SQL($Query) {&lt;br /&gt;
        global $DB;&lt;br /&gt;
        $args = func_get_args();&lt;br /&gt;
        if (count($args) == 1) {&lt;br /&gt;
            $result = $DB-&amp;gt;query($Query);&lt;br /&gt;
            if ($result-&amp;gt;num_rows) {&lt;br /&gt;
                $out = array();&lt;br /&gt;
                while (null != ($r = $result-&amp;gt;fetch_array(MYSQLI_ASSOC)))&lt;br /&gt;
                    $out [] = $r;&lt;br /&gt;
                return $out;&lt;br /&gt;
            }&lt;br /&gt;
            return null;&lt;br /&gt;
        } else {&lt;br /&gt;
            if (!$stmt = $DB-&amp;gt;prepare($Query))&lt;br /&gt;
                trigger_error(&amp;quot;Unable to prepare statement: {$Query}, reason: &amp;quot; . $DB-&amp;gt;error . &amp;quot;&amp;quot;);&lt;br /&gt;
            array_shift($args); //remove $Query from args&lt;br /&gt;
            //the following three lines are the only way to copy an array values in PHP&lt;br /&gt;
            $a = array();&lt;br /&gt;
            foreach ($args as $k =&amp;gt; &amp;amp;$v)&lt;br /&gt;
                $a[$k] = &amp;amp;$v;&lt;br /&gt;
            $types = str_repeat(&amp;quot;s&amp;quot;, count($args)); //all params are strings, works well on MySQL and SQLite&lt;br /&gt;
            array_unshift($a, $types);&lt;br /&gt;
            call_user_func_array(array($stmt, 'bind_param'), $a);&lt;br /&gt;
            $stmt-&amp;gt;execute();&lt;br /&gt;
            //fetching all results in a 2D array&lt;br /&gt;
            $metadata = $stmt-&amp;gt;result_metadata();&lt;br /&gt;
            $out = array();&lt;br /&gt;
            $fields = array();&lt;br /&gt;
            if (!$metadata)&lt;br /&gt;
                return null;&lt;br /&gt;
            $length = 0;&lt;br /&gt;
            while (null != ($field = mysqli_fetch_field($metadata))) {&lt;br /&gt;
                $fields [] = &amp;amp;$out [$field-&amp;gt;name];&lt;br /&gt;
                $length+=$field-&amp;gt;length;&lt;br /&gt;
            }&lt;br /&gt;
            call_user_func_array(array(&lt;br /&gt;
                $stmt, &amp;quot;bind_result&amp;quot;&lt;br /&gt;
                    ), $fields);&lt;br /&gt;
            $output = array();&lt;br /&gt;
            $count = 0;&lt;br /&gt;
            while ($stmt-&amp;gt;fetch()) {&lt;br /&gt;
                foreach ($out as $k =&amp;gt; $v)&lt;br /&gt;
                    $output [$count] [$k] = $v;&lt;br /&gt;
                $count++;&lt;br /&gt;
            }&lt;br /&gt;
            $stmt-&amp;gt;free_result();&lt;br /&gt;
            return ($count == 0) ? null : $output;&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
Now you could do your every query like the example below:&lt;br /&gt;
&lt;br /&gt;
 $res=SQL(&amp;quot;SELECT * FROM users WHERE ID&amp;gt;? ORDER BY ? ASC LIMIT ?&amp;quot; , 5 , &amp;quot;Username&amp;quot; , 2);&lt;br /&gt;
&lt;br /&gt;
Every instance of ? is bound with an argument of the list, not ''replaced'' with it. MySQL 5.5+ supports ? as ORDER BY and LIMIT clause specifiers. If you're using a database that doesn't support them, see next section.&lt;br /&gt;
&lt;br /&gt;
'''REMEMBER:''' When you use this approach, you should ''NEVER'' concat strings for a SQL query.&lt;br /&gt;
&lt;br /&gt;
====PDO Prepared Statement Wrapper====&lt;br /&gt;
The following function, does the same thing as the above function but using PDO. You can use it with every PDO supported driver.&lt;br /&gt;
&lt;br /&gt;
    try {&lt;br /&gt;
        $DB = new PDO(&amp;quot;{$Driver}:dbname={$DatabaseName};host={$Host};&amp;quot;, $Username, $Password);&lt;br /&gt;
    } catch (Exception $e) {&lt;br /&gt;
        trigger_error(&amp;quot;PDO connection error: &amp;quot; . $e-&amp;gt;getMessage());&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function SQL($Query) {&lt;br /&gt;
        global $DB;&lt;br /&gt;
        $args = func_get_args();&lt;br /&gt;
        if (count($args) == 1) {&lt;br /&gt;
            $result = $DB-&amp;gt;query($Query);&lt;br /&gt;
            if ($result-&amp;gt;rowCount()) {&lt;br /&gt;
                return $result-&amp;gt;fetchAll(PDO::FETCH_ASSOC);&lt;br /&gt;
            }&lt;br /&gt;
            return null;&lt;br /&gt;
        } else {&lt;br /&gt;
            if (!$stmt = $DB-&amp;gt;prepare($Query)) {&lt;br /&gt;
                $Error = $DB-&amp;gt;errorInfo();&lt;br /&gt;
                trigger_error(&amp;quot;Unable to prepare statement: {$Query}, reason: {$Error[2]}&amp;quot;);&lt;br /&gt;
            }&lt;br /&gt;
            array_shift($args); //remove $Query from args&lt;br /&gt;
            $i = 0;&lt;br /&gt;
            foreach ($args as &amp;amp;$v)&lt;br /&gt;
                $stmt-&amp;gt;bindValue(++$i, $v);&lt;br /&gt;
            $stmt-&amp;gt;execute();&lt;br /&gt;
            return $stmt-&amp;gt;fetchAll(PDO::FETCH_ASSOC);&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
 $res=SQL(&amp;quot;SELECT * FROM users WHERE ID&amp;gt;? ORDER BY ? ASC LIMIT 5&amp;quot; , 5 , &amp;quot;Username&amp;quot; );&lt;br /&gt;
&lt;br /&gt;
===Where prepared statements do not work===&lt;br /&gt;
The problem is, when you need to build dynamic queries, or need to set variables not supported as a prepared variable, or your database engine does not support prepared statements. For example, PDO MySQL does not support ? as LIMIT specifier. In these cases, you need to do two things:&lt;br /&gt;
&lt;br /&gt;
====Not Supported Fields====&lt;br /&gt;
When some field does not support binding (like LIMIT clause in PDO), you need to '''whitelist''' the data you're about to use. LIMIT always requires an integer, so cast the variable to an integer. ORDER BY needs a field name, so whitelist it with field names:&lt;br /&gt;
&lt;br /&gt;
    function whitelist($Needle,$Haystack)&lt;br /&gt;
    {&lt;br /&gt;
        if (!in_array($Needle,$Haystack))&lt;br /&gt;
                return reset($Haystack); //first element&lt;br /&gt;
        return $Needle;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    $Limit = $_GET['lim'];&lt;br /&gt;
    $Limit = $Limit * 1; //type cast, integers are safe&lt;br /&gt;
&lt;br /&gt;
    $Order = $_GET['sort'];&lt;br /&gt;
    $Order=whitelist($Order,Array(&amp;quot;ID&amp;quot;,&amp;quot;Username&amp;quot;,&amp;quot;Password&amp;quot;));&lt;br /&gt;
&lt;br /&gt;
This is very important. If you think you're tired and you rather blacklist than whitelist, you're bound to fail.&lt;br /&gt;
&lt;br /&gt;
====Dynamic Queries====&lt;br /&gt;
Now this is a highly delicate situation. Whenever hackers fail to injection SQL in your common application scenarios, they go for Advanced Search features or similars, because those features rely on dynamic queries and dynamic queries are almost always insecurely implemented.&lt;br /&gt;
&lt;br /&gt;
When you're building a dynamic query, the only way is whitelisting. Whitelist every field name, every boolean operator (it should be OR or AND, nothing else) and after building your query, use prepared statements:&lt;br /&gt;
&lt;br /&gt;
    $Query=&amp;quot;SELECT * FROM table WHERE &amp;quot;;&lt;br /&gt;
    foreach ($_GET['fields'] as $g)&lt;br /&gt;
        $Query.=whitelist($g,Array(&amp;quot;list&amp;quot;,&amp;quot;of&amp;quot;,&amp;quot;possible&amp;quot;,&amp;quot;fields&amp;quot;,&amp;quot;here&amp;quot;)).&amp;quot;=?&amp;quot;;&lt;br /&gt;
    $Values=$_GET['values'];&lt;br /&gt;
    array_unshift($Query); //add to the beginning&lt;br /&gt;
    $res=call_user_func_array(SQL, $Values);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==ORM==&lt;br /&gt;
ORMs are good security practice. If you're using an ORM (like Doctrine) in your PHP project, you're mostly prone to SQL attacks. Although injecting queries in ORM's is much harder, keep in mind that concatenating ORM queries makes for the same flaws that concatenating SQL queries, so '''NEVER''' concatenate strings sent to a database. ORM's support prepared statements as well.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=Other Injection Cheat Sheet=&lt;br /&gt;
SQL aside, there are a few more injections possible ''and common'' in PHP:&lt;br /&gt;
&lt;br /&gt;
==Shell Injection==&lt;br /&gt;
A few PHP functions namely&lt;br /&gt;
&lt;br /&gt;
* shell_exec&lt;br /&gt;
* exec&lt;br /&gt;
* passthru&lt;br /&gt;
* system&lt;br /&gt;
* [http://no2.php.net/manual/en/language.operators.execution.php backtick operator] ( ` )&lt;br /&gt;
&lt;br /&gt;
run a string as shell scripts and commands. Input provided to these functions (specially backtick operator that is not like a function). Depending on your configuration, shell script injection can cause your application settings and configuration to leak, or your whole server to be hijacked. This is a very dangerous injection and is somehow considered the haven of an attacker.&lt;br /&gt;
&lt;br /&gt;
Never pass tainted input to these functions - that is input somehow manipulated by the user - unless you're absolutely sure there's no way for it to be dangerous (which you never are without whitelisting). Escaping and any other countermeasures are ineffective, there are plenty of vectors for bypassing each and every one of them; don't believe what novice developers tell you. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Code Injection==&lt;br /&gt;
All interpreted languages such as PHP, have some function that accepts a string and runs that in that language. It is usually named Eval. PHP also has Eval.&lt;br /&gt;
Using Eval is a very bad practice, not just for security. If you're absolutely sure you have no other way but eval, use it without any tainted input.&lt;br /&gt;
&lt;br /&gt;
Reflection also could have code injection flaws. Refer to the appropriate reflection documentations, since it is an advanced topic.&lt;br /&gt;
 &lt;br /&gt;
==Other Injections==&lt;br /&gt;
LDAP, XPath and any other third party application that runs a string, is vulnerable to injection. Always keep in mind that some strings are not data, but commands and thus should be secure before passing to third party libraries.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=XSS Cheat Sheet=&lt;br /&gt;
&lt;br /&gt;
There are two scenarios when it comes to XSS, each one to be mitigated accordingly:&lt;br /&gt;
&lt;br /&gt;
==No Tags==&lt;br /&gt;
Most of the time, output needs no HTML tags. For example when you're about to dump a textbox value, or output user data in a cell. In this scenarios, you can mitigate XSS by simply using the function below. '''Keep in mind that this scenario won't mitigate XSS when you use user input in dangerous elements (style, script, image's src, a, etc.)''', but mostly you don't. Also keep in mind that every output that is not intended to contain HTML tags should be sent to the browser filtered with the following function.&lt;br /&gt;
&lt;br /&gt;
 //xss mitigation functions&lt;br /&gt;
 function xssafe($data,$encoding='UTF-8')&lt;br /&gt;
 {&lt;br /&gt;
 	return htmlspecialchars($data,ENT_QUOTES | ENT_HTML401,$encoding);&lt;br /&gt;
 }&lt;br /&gt;
 function xecho($data)&lt;br /&gt;
 {&lt;br /&gt;
 	echo xssafe($data);&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 //usage example&lt;br /&gt;
 &amp;lt;input type='text' name='test' value='&amp;lt;?php &lt;br /&gt;
 xecho (&amp;quot;' onclick='alert(1)&amp;quot;);&lt;br /&gt;
 ?&amp;gt;' /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Yes Tags==&lt;br /&gt;
When you need tags in your output, such as rich blog comments, forum posts, blog posts and etc., you have to use a '''Secure Encoding''' library. This is usually hard and slow, and that's why most applications have XSS vulnerabilities in them. OWASP ESAPI has a bunch of codecs for encoding different sections of data. There's also OWASP AntiSammy and HTMLPurifier for PHP. Each of these require lots of configuration and learning to perform well, but you need them when you want that good of an application.&lt;br /&gt;
&lt;br /&gt;
==Templating engines==&lt;br /&gt;
&lt;br /&gt;
There are several templating engines that can help the programmer (and designer) to output data without exposing it too much against XSS vulnerabilities. While their primary goal isn't security, but improving the designing experience, most important templating engines automatically escape the variables on output and force the developer to explicitly indicate if there is a variable that shouldn't be escaped. This makes output of variables have a white-list behavior. There exist several of these engines. A good example is twig[http://twig.sensiolabs.org/]. Other popular template engines are Smarty, Haanga and Rain TPL.&lt;br /&gt;
&lt;br /&gt;
The advantage of following a white-list approach is that the programmer should be less prone to forget about using a function call to clean the output of a variable.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Other Tips==&lt;br /&gt;
&lt;br /&gt;
* We don't have a '''trusted section''' in any web application. Many developers tend to leave admin areas out of XSS mitigation, but most intruders are interested in admin cookies and XSS. Every output should be cleared by the functions provided above, if it has a variable in it. Remove every instance of echo, print, and printf from your application and replace them with the above statement when you see a variable is included, no harm comes with that.&lt;br /&gt;
&lt;br /&gt;
* HTTP-Only cookies are a very good practice, for a near future when every browser is compatible. Start using them now. (See PHP.ini configuration for best practice)&lt;br /&gt;
&lt;br /&gt;
* The function declared above, only works for valid HTML syntax. If you put your Element Attributes without quotation, you're doomed. Go for valid HTML.&lt;br /&gt;
&lt;br /&gt;
* [[Reflected XSS]] is as dangerous as normal XSS, and usually comes at the most dusty corners of an application. Seek it and mitigate it.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=CSRF Cheat Sheet=&lt;br /&gt;
CSRF mitigation is easy in theory, but hard to implement correctly. First, a few tips about CSRF:&lt;br /&gt;
&lt;br /&gt;
* Every request that does something noteworthy, should be CSRF mitigated. Noteworthy things are changes to the system, and reads that take a long time.&lt;br /&gt;
* CSRF mostly happens on GET, but is easy to happen on POST. Don't ever think that post is secure.&lt;br /&gt;
&lt;br /&gt;
The [[PHP_CSRF_Guard|OWASP PHP CSRFGuard]] is a code snippet that shows how to mitigate CSRF. Only copy pasting it is not enough. In the near future, a copy-pasteable version  would be available (hopefully). For now, mix that with the following tips:&lt;br /&gt;
&lt;br /&gt;
* Use re-authentication for critical operations (change password, recovery email, etc.)&lt;br /&gt;
* If you're not sure whether your operation is CSRF proof, consider adding CAPTCHAs (however CAPTCHAs are inconvenience for users)&lt;br /&gt;
* If you're performing operations based on other parts of a request (neither GET nor POST) e.g Cookies or HTTP Headers, you might need to add CSRF tokens there as well.&lt;br /&gt;
* AJAX powered forms need to re-create their CSRF tokens. Use the function provided above (in code snippet) for that and never rely on Javascript.&lt;br /&gt;
* CSRF on GET or Cookies will lead to inconvenience, consider your design and architecture for best practices.&lt;br /&gt;
&lt;br /&gt;
=Authentication and Session Management Cheat Sheet=&lt;br /&gt;
PHP doesn't ship with a readily available authentication module, you need to implement your own or use a PHP framework, unfortunately most PHP frameworks are far from perfect in this manner, due to the fact that they are developed by open source developer community rather than security experts. A few instructive and useful tips are listed below:&lt;br /&gt;
 &lt;br /&gt;
==Session Management==&lt;br /&gt;
PHP's default session facilites are considered safe, the generated PHPSessionID is random enough, but the storage is not necessarily safe:&lt;br /&gt;
&lt;br /&gt;
* Session files are stored in temp (/tmp) folder and are world writable unless suPHP installed, so any LFI or other leak might end-up manipulating them.&lt;br /&gt;
* Sessions are stored in files in default configuration, which is terribly slow for highly visited websites. You can store them on a memory folder (if UNIX).&lt;br /&gt;
* You can implement your own session mechanism, without ever relying on PHP for it. If you did that, store session data in a database. You could use all, some or none of the PHP functionality for session handling if you go with that.&lt;br /&gt;
&lt;br /&gt;
===Session Hijacking Prevention===&lt;br /&gt;
It is good practice to bind sessions to IP addresses, that would prevent most session hijacking scenarios (but not all), however some users might use anonymity tools (such as TOR) and they would have problems with your service.&lt;br /&gt;
&lt;br /&gt;
To implement this, simply store the client IP in the session first time it is created, and enforce it to be the same afterwards. The code snippet below returns client IP address:&lt;br /&gt;
&lt;br /&gt;
 $IP = (getenv ( &amp;quot;HTTP_X_FORWARDED_FOR&amp;quot; )) ? getenv ( &amp;quot;HTTP_X_FORWARDED_FOR&amp;quot; ) : getenv ( &amp;quot;REMOTE_ADDR&amp;quot; );&lt;br /&gt;
&lt;br /&gt;
Keep in mind that in local environments, a valid IP is not returned, and usually the string ''':::1''' or ''':::127''' might pop up, thus adapt your IP checking logic.&lt;br /&gt;
&lt;br /&gt;
===Invalidate Session ID===&lt;br /&gt;
You should invalidate (unset cookie, unset session storage, remove traces) of a session whenever a violation occurs (e.g 2 IP addresses are observed). A log event would prove useful. Many applications also notify the logged in user (e.g GMail).&lt;br /&gt;
&lt;br /&gt;
===Rolling of Session ID===&lt;br /&gt;
You should roll session ID whenever elevation occurs, e.g when a user logs in, the session ID of the session should be changed, since it's importance is changed.&lt;br /&gt;
&lt;br /&gt;
===Exposed Session ID===&lt;br /&gt;
Session IDs are considered confidential, your application should not expose them anywhere (specially when bound to a logged in user). Try not to use URLs as session ID medium.&lt;br /&gt;
&lt;br /&gt;
Transfer session ID over TLS whenever session holds confidential information, otherwise a passive attacker would be able to perform session hijacking.&lt;br /&gt;
&lt;br /&gt;
===Session Fixation===&lt;br /&gt;
Session IDs are to be generated by your application only. Never create a session only because you receive the session ID from the client, the only source of creating a session should be a secure random generator.&lt;br /&gt;
&lt;br /&gt;
===Session Expiration===&lt;br /&gt;
A session should expire after a certain amount of inactivity, and after a certain time of activity as well. The expiration process means invalidating and removing a session, and creating a new one when another request is met.&lt;br /&gt;
&lt;br /&gt;
Also keep the '''log out''' button close, and unset all traces of the session on log out.&lt;br /&gt;
&lt;br /&gt;
====Inactivity Timeout====&lt;br /&gt;
Expire a session if current request is X seconds later than the last request. For this you should update session data with time of the request each time a request is made. The common practice time is 30 minutes, but highly depends on application criteria. &lt;br /&gt;
&lt;br /&gt;
This expiration helps when a user is logged in on a publicly accessible machine, but forgets to log out. It also helps with session hijacking.&lt;br /&gt;
&lt;br /&gt;
====General Timeout====&lt;br /&gt;
Expire a session if current session has been active for a certain amount of time, even if active. This helps keeping track of things. The amount differs but something between a day and a week is usually good. To implement this you need to store start time of a session.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Cookies===&lt;br /&gt;
Handling cookies in a PHP script has some tricks to it:&lt;br /&gt;
&lt;br /&gt;
====Never Serialize====&lt;br /&gt;
Never serialize data stored in a cookie. It can easily be manipulated, resulting in adding variables to your scope.&lt;br /&gt;
&lt;br /&gt;
====Proper Deletion====&lt;br /&gt;
To delete a cookie safely, use the following snippet:&lt;br /&gt;
&lt;br /&gt;
 setcookie ($name, &amp;quot;&amp;quot;, 1);&lt;br /&gt;
 setcookie ($name, false);&lt;br /&gt;
 unset($_COOKIE[$name]);&lt;br /&gt;
The first line ensures that cookie expires in browser, the second line is the standard way of removing a cookie (thus you can't store false in a cookie). The third line removes the cookie from your script. Many guides tell developers to use time() - 3600 for expiry, but it might not work if browser time is not correct.&lt;br /&gt;
&lt;br /&gt;
You can also use '''session_name()''' to retrieve the name default PHP session cookie.&lt;br /&gt;
&lt;br /&gt;
====HTTP Only====&lt;br /&gt;
Most modern browsers support HTTP-only cookies. These cookies are only accessible via HTTP(s) requests and not Javascript, so XSS snippets can not access them. They are very good practice, but are not satisfactory since there are many flaws discovered in major browsers that lead to exposure of HTTP only cookies to javascript.&lt;br /&gt;
&lt;br /&gt;
To use HTTP-only cookies in PHP (5.2+), you should perform session cookie setting [http://php.net/manual/en/function.setcookie.php manually] (not using '''session_start'''):&lt;br /&gt;
 &lt;br /&gt;
 #prototype&lt;br /&gt;
 bool setcookie ( string $name [, string $value [, int $expire = 0 [, string $path [, string $domain [, bool $secure = false [, bool $httponly = false ]]]]]] )&lt;br /&gt;
&lt;br /&gt;
 #usage&lt;br /&gt;
 if (!setcookie(&amp;quot;MySessionID&amp;quot;, $secureRandomSessionID, $generalTimeout, $applicationRootURLwithoutHost, NULL, NULL,true))&lt;br /&gt;
     echo (&amp;quot;could not set HTTP-only cookie&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
The '''path''' parameter sets the path which cookie is valid for, e.g if you have your website at example.com/some/folder the path should be /some/folder or other applications residing at example.com could also see your cookie. If you're on a whole domain, don't mind it. '''Domain''' parameter enforces the domain, if you're accessible on multiple domains or IPs ignore this, otherwise set it accordingly. If '''secure''' parameter is set, cookie can only be transmitted over HTTPS. See the example below:&lt;br /&gt;
&lt;br /&gt;
 $r=setcookie(&amp;quot;SECSESSID&amp;quot;,&amp;quot;1203j01j0s1209jw0s21jxd01h029y779g724jahsa9opk123973&amp;quot;,time()+60*60*24*7 /*a week*/,&amp;quot;/&amp;quot;,&amp;quot;owasp.org&amp;quot;,true,true);&lt;br /&gt;
 if (!$r) die(&amp;quot;Could not set session cookie.&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
====Internet Explorer issues====&lt;br /&gt;
Many version of Internet Explorer tend to have problems with cookies. Mostly setting Expire time to 0 fixes their issues.&lt;br /&gt;
&lt;br /&gt;
==Authentication==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Remember Me===&lt;br /&gt;
Many websites are vulnerable on remember me features. The correct practice is to generate a one-time token for a user and store it in the cookie. The token should also reside in data store of the application to be validated and assigned to user. This token should have '''no relevance''' to username and/or password of the user, a secure long-enough random number is a good practice.&lt;br /&gt;
&lt;br /&gt;
It is better if you imply locking and prevent brute-force on remember me tokens, and make them long enough, otherwise an attacker could brute-force remember me tokens until he gets access to a logged in user without credentials.&lt;br /&gt;
&lt;br /&gt;
* '''Never store username/password or any relevant information in the cookie.'''&lt;br /&gt;
&lt;br /&gt;
=Access Control Cheat Sheet=&lt;br /&gt;
This section aims to mitigate access control issues, as well as '''Insecure Direct Object Reference''' issues. &lt;br /&gt;
&lt;br /&gt;
=Cryptography Cheat Sheet=&lt;br /&gt;
&lt;br /&gt;
=File Inclusion Cheat Sheet=&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=Configuration and Deployment Cheat Sheet=&lt;br /&gt;
Please see [[PHP Configuration Cheat Sheet]].&lt;br /&gt;
&lt;br /&gt;
=Sources of Taint=&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
= OLD. PHP General Guidelines for Secure Web Applications  =&lt;br /&gt;
&lt;br /&gt;
== PHP Version ==&lt;br /&gt;
Use '''PHP 5.3.8'''. Stable versions are always safer then the beta ones. &lt;br /&gt;
&lt;br /&gt;
== Framework==&lt;br /&gt;
Use a framework like '''Zend''' or '''Symfony'''. Try not to re-write the code again and again. Also avoid dead codes. &lt;br /&gt;
&lt;br /&gt;
== Directory==&lt;br /&gt;
Code with most of your code outside of the webroot. This is automatic for Symfony and Zend. Stick to these frameworks. &lt;br /&gt;
&lt;br /&gt;
== Hashing Extension ==&lt;br /&gt;
Not every PHP installation has a working '''mhash''' extension, so if you need to do hashing, check it before using it. Otherwise you can't do SHA-256&lt;br /&gt;
&lt;br /&gt;
== Cryptographic Extension ==&lt;br /&gt;
Not every PHP installation has a working '''mcrypt''' extension, and without it you can't do AES. Do check if you need it.&lt;br /&gt;
&lt;br /&gt;
== Authentication and Authorization ==&lt;br /&gt;
There is no authentication or authorization classes in native PHP. Use '''ZF''' or '''Symfony''' instead.&lt;br /&gt;
&lt;br /&gt;
== Input nput validation ==&lt;br /&gt;
Use $_dirty['foo'] = $_GET['foo'] and then $foo = validate_foo($dirty['foo']); &lt;br /&gt;
&lt;br /&gt;
== Use PDO or ORM ==&lt;br /&gt;
Use PDO with prepared statements or an ORM like Doctrine&lt;br /&gt;
&lt;br /&gt;
== Use PHP Unit and Jenkins ==&lt;br /&gt;
When developing PHP code, make sure you develop with PHP Unit and Jenkins - see http://qualityassuranceinphpprojects.com/pages/tools.html for more details.&lt;br /&gt;
&lt;br /&gt;
== Use Stefan Esser's Hardened PHP Patch ==&lt;br /&gt;
Consider using Stefan Esser's Hardened PHP patch - http://www.hardened-php.net/suhosin/index.html &lt;br /&gt;
(not maintained now, but the concepts are very powerful)&lt;br /&gt;
&lt;br /&gt;
== Avoid Global Variables==&lt;br /&gt;
In terms of secure coding with PHP, do not use globals unless absolutely necessary &lt;br /&gt;
Check your php.ini to ensure register_globals is off Do not run at all with this setting enabled It's extremely dangerous (register_globals has been disabled since 5.0 / 2006, but .... most PHP 4 code needs it, so many hosters have it turned on)&lt;br /&gt;
&lt;br /&gt;
== Avoid Eval() ==&lt;br /&gt;
It basically allows arbitrary PHP code execution, so do not evaluate user supplied input. and if you're not doing that, you can just use PHP directly. eval() is at least 10-100 times slower than native PHP&lt;br /&gt;
&lt;br /&gt;
== Don't use $_REQUEST  ==&lt;br /&gt;
Instead of $_REQUEST- use $_GET or $_POST or $_SERVER &lt;br /&gt;
&lt;br /&gt;
== Protection against RFI==&lt;br /&gt;
Ensure allow_url_fopen and allow_url_include are both disabled to protect against RFI  But don't cause issues by using the pattern include $user_supplied_data or require &amp;quot;base&amp;quot; + $user_supplied_data - it's just unsafe as you can input /etc/passwd and PHP will try to include it&lt;br /&gt;
&lt;br /&gt;
== Regexes (!)==&lt;br /&gt;
Watch for executable regexes (!) &lt;br /&gt;
&lt;br /&gt;
== Session Rotation ==&lt;br /&gt;
Session rotation is very easy - just after authentication, plonk in session_regenerate_id() and you're done.&lt;br /&gt;
&lt;br /&gt;
== Be aware of PHP filters ==&lt;br /&gt;
PHP filters can be tricky and complex. Be extra-conscious when using them. &lt;br /&gt;
&lt;br /&gt;
== Logging ==&lt;br /&gt;
Set display_errors to 0, and set up logging to go to a file you control, or at least syslog. This is the most commonly neglected area of PHP configuration&lt;br /&gt;
&lt;br /&gt;
== Output encoding ==&lt;br /&gt;
Output encoding is entirely up to you. Just do it, ESAPI for PHP is ready for this job.&lt;br /&gt;
&lt;br /&gt;
These are transparent to you and you need to know about them. php://input: takes input from the console gzip: takes compressed input and might bypass input validation http://au2.php.net/manual/en/filters.php &lt;br /&gt;
&lt;br /&gt;
= Authors and Primary Editors  =&lt;br /&gt;
&lt;br /&gt;
[[User:Abbas Naderi|Abbas Naderi Afooshteh]] ([mailto:abbas.naderi@owasp.org abbas.naderi@owasp.org])&lt;br /&gt;
&lt;br /&gt;
[[User:Achim|Achim]] - [mailto:achim_at_owasp.org Achim at owasp.org]&lt;br /&gt;
&lt;br /&gt;
[mailto:vanderaj@owasp.org Andrew van der Stock]&lt;br /&gt;
&lt;br /&gt;
= Other Cheatsheets =&lt;br /&gt;
{{Cheatsheet_Navigation}}&lt;br /&gt;
&lt;br /&gt;
[[Category:Cheatsheets]]&lt;/div&gt;</summary>
		<author><name>Manuel Aude Morales</name></author>	</entry>

	<entry>
		<id>https://wiki.owasp.org/index.php?title=Talk:Password_Storage_Cheat_Sheet&amp;diff=148112</id>
		<title>Talk:Password Storage Cheat Sheet</title>
		<link rel="alternate" type="text/html" href="https://wiki.owasp.org/index.php?title=Talk:Password_Storage_Cheat_Sheet&amp;diff=148112"/>
				<updated>2013-03-19T01:39:57Z</updated>
		
		<summary type="html">&lt;p&gt;Manuel Aude Morales: reviving discussion on peppers (&amp;quot;secret salts&amp;quot;)&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;More on the previous dicussions on secret salts. They are usually referred to as pepper on practice. The advantage of having a pepper for the passwords is that you can keep them on the web server. Thus, if the hacker has access to the database data and he has access to all hashed passwords (doesn't matter if they are created using PBKDF2, bcrypt or scrypt, or even simple salt+sha2), he still needs to also hack the web server to obtain the pepper, or fixed salt. It isn't cryptographically significant, but it adds yet another layer to the information the hacker has to obtain before starting to do the brute force.&lt;br /&gt;
I think it would be nice if it was possible to add it to the cheat sheet.&lt;br /&gt;
&lt;br /&gt;
--[[User:Manuel Aude Morales|Manuel Aude Morales]] , 18 March 2013 (UTC)&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
I was considering adding bcrypt to the article. I checked previous versions and noticed it was in it on January, but it was taken out during editions in March. From my knowledge, bcrypt is still a widely recommended adaptative hashing function. While it has limitations (particularly, a 55 bytes limitation) and doesn't protect to all hardware accelerated attacks, it does protect against GPU and works as good as PBKDF2 for most cases. Also, scrypt hasn't existed for nearly as much as bcrypt, and thus it isn't as widely tested or supported by platforms.&lt;br /&gt;
&lt;br /&gt;
Would it be ok to add a table making a comparison between PBKDF2, bcrypt and scrypt, with suggestions on when to use (and clarifying that the three are valid options)?&lt;br /&gt;
--[[User:Manuel Aude Morales|Manuel Aude Morales]] , 18 March 2013 (UTC)&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
I think, for this cheat-sheet, we should begin by identifying and describing the minimum acceptable mechanisms for password storage (IMO, this is probably still salt+hash) first.  Then, describe the additional controls that can be applied to further enhance the protection.&lt;br /&gt;
--[[User:Dan Anderson|Dan Anderson]] 17:33, 8 June 2012 (UTC)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
IMO, this is a good example: [http://fredericiana.com/2012/06/08/lets-talk-about-password-storage/|Let’s talk about password storage]&lt;br /&gt;
--[[User:Dan Anderson|Dan Anderson]] 20:58, 8 June 2012 (UTC)&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
Since the community is focusing more on this page, I think we need a discussion.&lt;br /&gt;
&lt;br /&gt;
A few of the points mentioned on this page are dubious to me :&lt;br /&gt;
&lt;br /&gt;
==Recommendation: Make it hard to steal the salt==&lt;br /&gt;
As far as I know salts are salts, not secrets. They are supposed to be known (in a cryptographic point of view). &lt;br /&gt;
&lt;br /&gt;
* Fixed system salt is a fine practice followed by many,&lt;br /&gt;
but does not increase system security since when concatenated with random salts, its just one long salt with less randomness.&lt;br /&gt;
* Embedding a portion of the salt on source code, is not much different from the configuration file. Same scenario.&lt;br /&gt;
* Generate new salt everytime password changes. That is true, and somehow required. But not to make salt gathering harder.&lt;br /&gt;
* Salt in different location: same old&lt;br /&gt;
==Multiple hashes==&lt;br /&gt;
Oddly many open source software follow this paradigm, but it's totally irrelevant. As in Merkle's TIme-Memory tradeoff and Rainbow algorithms it is obvious that multiple hashes result in the same chain or another chain of the rainbow, thus don't add a single bit of security. I believe it must be mentioned that this practice is wrong. I have seen numerous OSS use&lt;br /&gt;
&lt;br /&gt;
 hash(salt.hash(user.hash(pass)).salt) which is as secure as hash(salt.pass) &lt;br /&gt;
&lt;br /&gt;
or even less (can be exploited somehow).&lt;br /&gt;
&lt;br /&gt;
I strongly suggest that this page be modified and fixed. If other members approve, please let me know.&lt;/div&gt;</summary>
		<author><name>Manuel Aude Morales</name></author>	</entry>

	<entry>
		<id>https://wiki.owasp.org/index.php?title=Talk:Password_Storage_Cheat_Sheet&amp;diff=148111</id>
		<title>Talk:Password Storage Cheat Sheet</title>
		<link rel="alternate" type="text/html" href="https://wiki.owasp.org/index.php?title=Talk:Password_Storage_Cheat_Sheet&amp;diff=148111"/>
				<updated>2013-03-19T01:34:02Z</updated>
		
		<summary type="html">&lt;p&gt;Manuel Aude Morales: formatting&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;I was considering adding bcrypt to the article. I checked previous versions and noticed it was in it on January, but it was taken out during editions in March. From my knowledge, bcrypt is still a widely recommended adaptative hashing function. While it has limitations (particularly, a 55 bytes limitation) and doesn't protect to all hardware accelerated attacks, it does protect against GPU and works as good as PBKDF2 for most cases. Also, scrypt hasn't existed for nearly as much as bcrypt, and thus it isn't as widely tested or supported by platforms.&lt;br /&gt;
&lt;br /&gt;
Would it be ok to add a table making a comparison between PBKDF2, bcrypt and scrypt, with suggestions on when to use (and clarifying that the three are valid options)?&lt;br /&gt;
--[[User:Manuel Aude Morales|Manuel Aude Morales]] , 18 March 2013 (UTC)&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
I think, for this cheat-sheet, we should begin by identifying and describing the minimum acceptable mechanisms for password storage (IMO, this is probably still salt+hash) first.  Then, describe the additional controls that can be applied to further enhance the protection.&lt;br /&gt;
--[[User:Dan Anderson|Dan Anderson]] 17:33, 8 June 2012 (UTC)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
IMO, this is a good example: [http://fredericiana.com/2012/06/08/lets-talk-about-password-storage/|Let’s talk about password storage]&lt;br /&gt;
--[[User:Dan Anderson|Dan Anderson]] 20:58, 8 June 2012 (UTC)&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
Since the community is focusing more on this page, I think we need a discussion.&lt;br /&gt;
&lt;br /&gt;
A few of the points mentioned on this page are dubious to me :&lt;br /&gt;
&lt;br /&gt;
==Recommendation: Make it hard to steal the salt==&lt;br /&gt;
As far as I know salts are salts, not secrets. They are supposed to be known (in a cryptographic point of view). &lt;br /&gt;
&lt;br /&gt;
* Fixed system salt is a fine practice followed by many,&lt;br /&gt;
but does not increase system security since when concatenated with random salts, its just one long salt with less randomness.&lt;br /&gt;
* Embedding a portion of the salt on source code, is not much different from the configuration file. Same scenario.&lt;br /&gt;
* Generate new salt everytime password changes. That is true, and somehow required. But not to make salt gathering harder.&lt;br /&gt;
* Salt in different location: same old&lt;br /&gt;
==Multiple hashes==&lt;br /&gt;
Oddly many open source software follow this paradigm, but it's totally irrelevant. As in Merkle's TIme-Memory tradeoff and Rainbow algorithms it is obvious that multiple hashes result in the same chain or another chain of the rainbow, thus don't add a single bit of security. I believe it must be mentioned that this practice is wrong. I have seen numerous OSS use&lt;br /&gt;
&lt;br /&gt;
 hash(salt.hash(user.hash(pass)).salt) which is as secure as hash(salt.pass) &lt;br /&gt;
&lt;br /&gt;
or even less (can be exploited somehow).&lt;br /&gt;
&lt;br /&gt;
I strongly suggest that this page be modified and fixed. If other members approve, please let me know.&lt;/div&gt;</summary>
		<author><name>Manuel Aude Morales</name></author>	</entry>

	<entry>
		<id>https://wiki.owasp.org/index.php?title=Talk:Password_Storage_Cheat_Sheet&amp;diff=148110</id>
		<title>Talk:Password Storage Cheat Sheet</title>
		<link rel="alternate" type="text/html" href="https://wiki.owasp.org/index.php?title=Talk:Password_Storage_Cheat_Sheet&amp;diff=148110"/>
				<updated>2013-03-19T01:30:27Z</updated>
		
		<summary type="html">&lt;p&gt;Manuel Aude Morales: Making a case for re-adding bcrypt to the article.&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;I was considering adding bcrypt to the article. I checked previous versions and noticed it was in it on January, but it was taken out during editions in March. From my knowledge, bcrypt is still a widely recommended adaptative hashing function. While it has limitations (particularly, a 55 bytes limitation) and doesn't protect to all hardware accelerated attacks, it does protect against GPU and works as good as PBKDF2 for most cases. Also, scrypt hasn't existed for nearly as much as bcrypt, and thus it isn't as widely tested or supported by platforms.&lt;br /&gt;
&lt;br /&gt;
Would it be ok to add a table making a comparison between PBKDF2, bcrypt and scrypt, with suggestions on when to use (and clarifying that the three are valid options)?&lt;br /&gt;
--[[User:Manuel Aude Morales|Manuel Aude Morales]] 17:33, 8 June 2012 (UTC)&lt;br /&gt;
&lt;br /&gt;
I think, for this cheat-sheet, we should begin by identifying and describing the minimum acceptable mechanisms for password storage (IMO, this is probably still salt+hash) first.  Then, describe the additional controls that can be applied to further enhance the protection.&lt;br /&gt;
--[[User:Dan Anderson|Dan Anderson]] 17:33, 8 June 2012 (UTC)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
IMO, this is a good example: [http://fredericiana.com/2012/06/08/lets-talk-about-password-storage/|Let’s talk about password storage]&lt;br /&gt;
--[[User:Dan Anderson|Dan Anderson]] 20:58, 8 June 2012 (UTC)&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
Since the community is focusing more on this page, I think we need a discussion.&lt;br /&gt;
&lt;br /&gt;
A few of the points mentioned on this page are dubious to me :&lt;br /&gt;
&lt;br /&gt;
==Recommendation: Make it hard to steal the salt==&lt;br /&gt;
As far as I know salts are salts, not secrets. They are supposed to be known (in a cryptographic point of view). &lt;br /&gt;
&lt;br /&gt;
* Fixed system salt is a fine practice followed by many,&lt;br /&gt;
but does not increase system security since when concatenated with random salts, its just one long salt with less randomness.&lt;br /&gt;
* Embedding a portion of the salt on source code, is not much different from the configuration file. Same scenario.&lt;br /&gt;
* Generate new salt everytime password changes. That is true, and somehow required. But not to make salt gathering harder.&lt;br /&gt;
* Salt in different location: same old&lt;br /&gt;
==Multiple hashes==&lt;br /&gt;
Oddly many open source software follow this paradigm, but it's totally irrelevant. As in Merkle's TIme-Memory tradeoff and Rainbow algorithms it is obvious that multiple hashes result in the same chain or another chain of the rainbow, thus don't add a single bit of security. I believe it must be mentioned that this practice is wrong. I have seen numerous OSS use&lt;br /&gt;
&lt;br /&gt;
 hash(salt.hash(user.hash(pass)).salt) which is as secure as hash(salt.pass) &lt;br /&gt;
&lt;br /&gt;
or even less (can be exploited somehow).&lt;br /&gt;
&lt;br /&gt;
I strongly suggest that this page be modified and fixed. If other members approve, please let me know.&lt;/div&gt;</summary>
		<author><name>Manuel Aude Morales</name></author>	</entry>

	<entry>
		<id>https://wiki.owasp.org/index.php?title=Password_Storage_Cheat_Sheet&amp;diff=148109</id>
		<title>Password Storage Cheat Sheet</title>
		<link rel="alternate" type="text/html" href="https://wiki.owasp.org/index.php?title=Password_Storage_Cheat_Sheet&amp;diff=148109"/>
				<updated>2013-03-19T01:22:04Z</updated>
		
		<summary type="html">&lt;p&gt;Manuel Aude Morales: Adding criteria on how to tune adaptative hash functions&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Introduction =&lt;br /&gt;
&lt;br /&gt;
Media covers the theft of large collections of passwords on an almost daily basis. Media coverage of password theft discloses the password storage scheme, the weakness of that scheme, and often discloses a large population of compromised credentials that can affect multiple web sites or other applications. This article provides guidance on properly storing passwords, secret question responses, and similar credential information. Proper storage helps prevent theft, compromise, and malicious use of credentials.&lt;br /&gt;
Information systems store passwords and other credentials in a variety of protected forms. Common vulnerabilities allow the theft of protected passwords through attack vectors such as SQL Injection. Protected passwords can also be stolen from artifacts such as logs, dumps, and backups.&lt;br /&gt;
&lt;br /&gt;
Specific guidance herein protects against stored credential theft but the bulk of guidance aims to prevent credential compromise. That is, this guidance helps designs resist revealing users’ credentials or allowing system access in the event threats steal protected credential information. For more information and a thorough treatment of this topic, refer to the Secure Password Storage Threat Model here [http://goo.gl/Spvzs http://goo.gl/Spvzs].&lt;br /&gt;
&lt;br /&gt;
= Guidance =&lt;br /&gt;
&lt;br /&gt;
==  Do not limit the character set or length of credentials ==&lt;br /&gt;
&lt;br /&gt;
Some organizations restrict the 1) types of special characters and 2) length of credentials accepted by systems because of their inability to prevent SQL Injection, Cross-site scripting, command-injection and other forms of injection attacks. These restrictions, while well-intentioned, facilitate certain simple attacks such as brute force.&lt;br /&gt;
&lt;br /&gt;
Do not apply length, character set, or encoding restrictions on the entry or storage of credentials. Continue applying encoding, escaping, masking, outright omission, and other best practices to eliminate injection risks.&lt;br /&gt;
&lt;br /&gt;
== Use a cryptographically strong credential-specific salt ==&lt;br /&gt;
&lt;br /&gt;
A salt is fixed-length cryptographically-strong random value. Append credential data to the salt and use this as input to a protective function. Store the protected form appended to the salt as follows:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;[protected form] = [salt] + protect([protection func], [salt] + [credential]);&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Follow these practices to properly implement credential-specific salts:&lt;br /&gt;
&lt;br /&gt;
* Generate a unique salt upon creation of each stored credential (not just per user or system wide);&lt;br /&gt;
* Use cryptographically-strong random [*3] data;&lt;br /&gt;
* As storage permits, use a 32bit or 64b salt (actual size dependent on protection function);&lt;br /&gt;
* Scheme security does not depend on hiding, splitting, or otherwise obscuring the salt.&lt;br /&gt;
&lt;br /&gt;
Salts serve two purposes: 1) prevent the protected form from revealing two identical credentials and 2) augment entropy fed to protecting function without relying on credential complexity. The second aims to make pre-computed lookup attacks [*2] on an individual credential and time-based attacks on a population intractable.&lt;br /&gt;
&lt;br /&gt;
== Impose infeasible verification on attacker ==&lt;br /&gt;
&lt;br /&gt;
The function used to protect stored credentials should balance attacker and defender verification. The defender needs an acceptable response time for verification of users’ credentials during peak use. However, the time required to map &amp;lt;code&amp;gt;&amp;lt;credential&amp;gt; → &amp;lt;protected form&amp;gt;&amp;lt;/code&amp;gt;  must remain beyond threats’ hardware (GPU, FPGA) and technique (dictionary-based, brute force, etc) capabilities.&lt;br /&gt;
&lt;br /&gt;
Two approaches facilitate this, each imperfectly.&lt;br /&gt;
&lt;br /&gt;
=== Leverage an adaptive one-way function ===&lt;br /&gt;
&lt;br /&gt;
Adaptive one-way functions compute a one-way (irreversible) transform. Each function allows configuration of ‘work factor’. Underlying mechanisms used to achieve irreversibility and govern work factors (such as time, space, and parallelism) vary between functions and remain unimportant to this discussion. &lt;br /&gt;
&lt;br /&gt;
Select:&lt;br /&gt;
&lt;br /&gt;
* PBKDF2 [*4] when FIPS certification or enterprise support on many platforms is required;&lt;br /&gt;
* Scrypt [*5] where resisting any/all hardware accelerated attacks is necessary but support isn’t.&lt;br /&gt;
&lt;br /&gt;
Example protect() pseudo-code follows:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;return [salt] + pbkdf2([salt], [credential], c=10000); &amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Designers select one-way adaptive functions to implement protect() because these functions can be configured to cost (linearly or exponentially) more than a hash function to execute. Defenders adjust work factor to keep pace with threats’ increasing hardware capabilities. Those implementing adaptive one-way functions must tune work factors so as to impede attackers while providing acceptable user experience and scale. &lt;br /&gt;
&lt;br /&gt;
Since resources are normally considered limited, a common rule of thumb for tuning the cost is to make protect() run as slow as possible without affecting the users' experience and without increasing the need for extra hardware over budget. So, if the registration and authentication's cases accept protect() taking up to 1 second, you can tune the cost so that it takes 1 second to run on your hardware. This way, it shouldn't be so slow that your users become affected, but it should also affect the attackers' attempt as much as possible. &lt;br /&gt;
&lt;br /&gt;
Additionally, adaptive one-way functions do not effectively prevent reversal of common dictionary-based credentials (users with password ‘password’) regardless of user population size or salt usage.&lt;br /&gt;
&lt;br /&gt;
==== Work Factor ====&lt;br /&gt;
&lt;br /&gt;
Regardless of the chosen adaptive one-way function, developers must choose a work factor. No one single work factor fits all design situations. Experiment with and configure work factors relative to total function execution time, rather than to a particular chosen value [*6].&lt;br /&gt;
&lt;br /&gt;
=== Leverage Keyed functions ===&lt;br /&gt;
&lt;br /&gt;
Keyed functions, such as HMACs, compute a one-way (irreversible) transform using a private key and given input. For example, HMACs inherit properties of hash functions including their speed, allowing for near instant verification. Key size imposes infeasible size- and/or space- requirements on compromise--even for common credentials (aka password = ‘password’).&lt;br /&gt;
Designers protecting stored credentials with keyed functions:&lt;br /&gt;
&lt;br /&gt;
* Use a single “site-wide” key;&lt;br /&gt;
* Protect this key as any private key using best practices;&lt;br /&gt;
* Store the key outside the credential store (aka: not in the database);&lt;br /&gt;
* Generate the key using cryptographically-strong pseudo-random data;&lt;br /&gt;
* Do not worry about output block size (i.e. SHA-256 vs. SHA-512).&lt;br /&gt;
&lt;br /&gt;
Example protect() pseudo-code follows:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;return [salt] + HMAC-SHA-256([key], [salt] + [credential]);  &amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Upholding security improvement over (solely) salted schemes relies on proper key management.&lt;br /&gt;
&lt;br /&gt;
== Design protection/verification for compromise ==&lt;br /&gt;
&lt;br /&gt;
The frequency and ease with which threats steal protected credentials demands “design for failure”. Having detected theft, a credential storage scheme must support continued operation by marking credential data compromised and engaging alternative credential validation workflows as follows:&lt;br /&gt;
&lt;br /&gt;
1) Protect the user’s account&lt;br /&gt;
  a. Invalidate authN ‘shortcuts’ disallowing login without 2nd factors or secret questions&lt;br /&gt;
  b. Disallow changes to account (secret questions, out of band exchange channel setup/selection, etc.)&lt;br /&gt;
&lt;br /&gt;
2) Load and use new protection scheme&lt;br /&gt;
  a. Load a new (stronger) protect(credential) function&lt;br /&gt;
  b. Include version information stored with form&lt;br /&gt;
  c. Set ‘tainted’/‘compromised’ bit until user resets credentials&lt;br /&gt;
  d. Rotate any keys and/or adjust protection function parameters (iter count)&lt;br /&gt;
  e. Increment scheme version number&lt;br /&gt;
&lt;br /&gt;
3) When user logs in:&lt;br /&gt;
  a. Validate credentials based on stored version (old or new); if old demand 2nd factor or secret answers&lt;br /&gt;
  b. Prompt user for credential change, apologize, &amp;amp; conduct OOB confirmation&lt;br /&gt;
  c. Convert stored credentials to new scheme as user successfully log in&lt;br /&gt;
&lt;br /&gt;
Supporting workflow outlined above requires tight integration with Authentication frameworks and workflows.&lt;br /&gt;
&lt;br /&gt;
= References=&lt;br /&gt;
&lt;br /&gt;
* [1] Morris, R. Thompson, K., Password Security: A Case History, 04/03/1978, p4: http://cm.bell-labs.com/cm/cs/who/dmr/passwd.ps&lt;br /&gt;
* [2] Space-based (Lookup) attacks: Space-time Tradeoff: Hellman, M., Crypanalytic Time-Memory Trade-Off, Transactions of Information Theory, Vol. IT-26, No. 4, July, 1980 http://www-ee.stanford.edu/~hellman/publications/36.pdf Rainbow Tables -http://ophcrack.sourceforge.net/tables.php&lt;br /&gt;
* [3] For example: http://docs.oracle.com/javase/6/docs/api/java/security/SecureRandom.html&lt;br /&gt;
* [4] Kalski, B., PKCS #5: Password-Based Cryptography Specification Version 2.0, IETF RFC 2898, September, 2000, p9 http://www.ietf.org/rfc/rfc2898.txt&lt;br /&gt;
* [5] Percival, C., Stronger Key Derivation Via Sequential Memory-Hard Functions, BSDCan ‘09, May, 2009 http://www.tarsnap.com/scrypt/scrypt.pdf&lt;br /&gt;
* [6] For instance, one might set work factors targeting the following run times: (1) Password-generated session key - fraction of a second; (2) User credential - ~0.5 seconds; (3) Password-generated site (or other long-lived) key - potentially a second or more.&lt;br /&gt;
&lt;br /&gt;
= Authors and Primary Editors =&lt;br /&gt;
&lt;br /&gt;
John Steven - john.steven[at]owasp.org&lt;br /&gt;
&lt;br /&gt;
= Other Cheatsheets =&lt;br /&gt;
&lt;br /&gt;
{{Cheatsheet_Navigation}}&lt;br /&gt;
&lt;br /&gt;
[[Category:Cheatsheets]]&lt;/div&gt;</summary>
		<author><name>Manuel Aude Morales</name></author>	</entry>

	<entry>
		<id>https://wiki.owasp.org/index.php?title=Authentication_Cheat_Sheet&amp;diff=148108</id>
		<title>Authentication Cheat Sheet</title>
		<link rel="alternate" type="text/html" href="https://wiki.owasp.org/index.php?title=Authentication_Cheat_Sheet&amp;diff=148108"/>
				<updated>2013-03-19T01:03:41Z</updated>
		
		<summary type="html">&lt;p&gt;Manuel Aude Morales: Adding SSL Client Authentication section under multi-factor authentication&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Introduction  =&lt;br /&gt;
&lt;br /&gt;
'''Authentication''' is the process of verification that an individual or an entity is who it claims to be. Authentication is commonly performed by submitting a user name or ID and one or more items of private information that only a given user should know. &lt;br /&gt;
&lt;br /&gt;
'''Session Management''' is a process by which a server maintains the state of an entity interacting with it. This is required for a server to remember how to react to subsequent requests throughout a transaction. Sessions are maintained on the server by a session identifier which can be passed back and forward between the client and server when transmitting and receiving requests. Sessions should be unique per user and computationally very difficult to predict. &lt;br /&gt;
&lt;br /&gt;
For more information on Authentication, please see the OWASP [[Guide to Authentication]] page.&lt;br /&gt;
&lt;br /&gt;
= Authentication General Guidelines  =&lt;br /&gt;
&lt;br /&gt;
== User IDs ==&lt;br /&gt;
&lt;br /&gt;
Make sure your usernames/userids are case insensitive. Many sites use email addresses for usernames and email addresses are already case insensitive. Regardless, it would be very strange for user 'smith' and user 'Smith' to be different users. Could result in serious confusion.&lt;br /&gt;
&lt;br /&gt;
== Implement Proper Password Strength Controls ==&lt;br /&gt;
&lt;br /&gt;
A key concern when using passwords for authentication is password strength. A &amp;quot;strong&amp;quot; password policy makes it difficult or even improbable for one to guess the password through either manual or automated means. The following characteristics define a strong password: &lt;br /&gt;
&lt;br /&gt;
=== Password Length ===&lt;br /&gt;
&lt;br /&gt;
Longer passwords provide a greater combination of characters and consequently make it more difficult for an attacker to guess. &lt;br /&gt;
&lt;br /&gt;
* '''Minimum''' length of the passwords should be '''enforced''' by the application.&lt;br /&gt;
** Passwords '''shorter than 10 characters''' are considered to be weak ([http://csrc.nist.gov/publications/nistpubs/800-132/nist-sp800-132.pdf]).&lt;br /&gt;
&lt;br /&gt;
While minimum length enforcement may cause problems with memorizing passwords among some users, applications should encourage them to set ''passphrases'' (sentences or combination of words) that can be much longer than typical passwords and yet much easier to remember.&lt;br /&gt;
&lt;br /&gt;
* '''Maximum''' password length should not be set '''too low''', as it will prevent users from creating passphrases. Typical maximum length is 128 characters.&lt;br /&gt;
** Passphrases shorter than 20 characters are usually considered weak if they only consist of lower case Latin characters.&lt;br /&gt;
&lt;br /&gt;
* Every character counts!!&lt;br /&gt;
**Make sure that every character the user types in is actually included in the password. We've seen systems that truncate the password at a length shorter than what the user provided (e.g., truncated at 15 characters when they entered 20).&lt;br /&gt;
**This is usually handled by setting the length of ALL password input fields to be exactly the same length as the maximum length password. This is particularly important if your max password length is short, like 20-30 characters.&lt;br /&gt;
&lt;br /&gt;
=== Password Complexity ===&lt;br /&gt;
&lt;br /&gt;
Applications should enforce password complexity rules to discourage easy to guess passwords. Password mechanisms should allow virtually any character the user can type to be part of their password, including the space character. Passwords should, obviously, be case sensitive in order to increase their complexity. Occasionally, we find systems where passwords aren't case sensitive, frequently due to legacy system issues like old mainframes that didn't have case sensitive passwords.&lt;br /&gt;
&lt;br /&gt;
The password change mechanism should require a minimum level of complexity that makes sense for the application and its user population. For example:&lt;br /&gt;
&lt;br /&gt;
*Password must meet at least 3 out of the following 4 complexity rules&lt;br /&gt;
**at least 1 uppercase character (A-Z) &lt;br /&gt;
**at least 1 lowercase character (a-z) &lt;br /&gt;
**at least 1 digit (0-9) &lt;br /&gt;
**at least 1 special character (!&amp;quot;£$%&amp;amp;amp;...) &amp;amp;mdash; do not forget to treat space as special characters (common in passphrases)&lt;br /&gt;
*at least 10 characters &lt;br /&gt;
*at most 128 characters&lt;br /&gt;
*not more than 2 identical characters in a row (e.g., 111 not allowed)&lt;br /&gt;
&lt;br /&gt;
As application's require more complex password policies, they need to be very clear about what these policies are.&lt;br /&gt;
*The required policy needs to be explicitly stated on the password change page&lt;br /&gt;
** be sure to list every special character you allow, so it's obvious to the user&lt;br /&gt;
&lt;br /&gt;
Recommendation:&lt;br /&gt;
* Ideally, the application would indicate to the user as they type in their new password how much of the complexity policy their new password meets&lt;br /&gt;
**In fact, the submit button should be grayed out until the new password meets the complexity policy and the 2nd copy of the new password matches the 1st. This will make it far easier for the user to understand and comply with your complexity policy.&lt;br /&gt;
&lt;br /&gt;
Regardless of how the UI behaves, when a user submits their password change request:&lt;br /&gt;
*If the new password doesn't comply with the complexity policy, the error message should describe EVERY complexity rule that the new password does not comply with, not just the 1st rule it doesn't comply with&lt;br /&gt;
&lt;br /&gt;
Changing passwords should be EASY, not a hunt in the dark.&lt;br /&gt;
&lt;br /&gt;
== Implement Secure Password Recovery Mechanism ==&lt;br /&gt;
&lt;br /&gt;
It is common for an application to have a mechanism that provides a means for a user to gain access to their account in the event they forget their password. Please see [[Forgot_Password_Cheat_Sheet]] for details on this feature.&lt;br /&gt;
&lt;br /&gt;
== Require Re-authentication for Sensitive Features ==&lt;br /&gt;
&lt;br /&gt;
In order to mitigate CSRF and session hijacking, it's important to require the current credentials for an account before updating sensitive account information such as the user's password, user's email, or before sensitive transactions, such as shipping a purchase to a new address.  Without this countermeasure, an attacker may be able to execute sensitive transactions through a CSRF or XSS attack without needing to know the user's current credentials.  Additionally, an attacker may get temporary physical access to a user's browser or steal their session ID to take over the user's session.&lt;br /&gt;
&lt;br /&gt;
== Utilize Multi-Factor Authentication ==&lt;br /&gt;
&lt;br /&gt;
Multi-factor authentication (MFA) is using more than one authentication factor to logon or process a transaction:&lt;br /&gt;
&lt;br /&gt;
*Something you know (account details or passwords) &lt;br /&gt;
*Something you have (tokens or mobile phones) &lt;br /&gt;
*Something you are (biometrics)&lt;br /&gt;
&lt;br /&gt;
Authentication schemes such as One Time Passwords (OTP) implemented using a hardware token can also be key in fighting attacks such as CSRF and client-side malware. A number of hardware tokens suitable for MFA are available in the market that allow good integration with web applications. See: [http://en.wikipedia.org/wiki/Security_token].&lt;br /&gt;
&lt;br /&gt;
=== SSL Client Authentication ===&lt;br /&gt;
&lt;br /&gt;
SSL Client Authentication, also known as two-way SSL authentication, consists of both, browser and server, sending their respective SSL certificates during the TLS handshake process. Just as you can validate the authenticity of a server by using the certificate and asking a well known Certificate Authority (CA) if the certificate is valid, the server can authenticate the user by receiving a certificate from the client and validating against a third party CA or its own CA. To do this, the server most provide the user with a certificate generated specifically for him, assigning values to the subject so that these can be used to determine what user the certificate should validate. The user installs the certificate on a browser and now uses it for the website.&lt;br /&gt;
&lt;br /&gt;
It is a good idea to do this when:&lt;br /&gt;
&lt;br /&gt;
*It is acceptable (or even preferred) that the user only has access to the website from only a single computer/browser.&lt;br /&gt;
*The user is not easily scared by the process of installing SSL certificates on his browser or there will be someone, probably from IT support, that will do this for the user.&lt;br /&gt;
*The website requires an extra step of security.&lt;br /&gt;
*It is also a good thing to use when the website is for an intranet of a company or organization.&lt;br /&gt;
&lt;br /&gt;
It is generally not a good idea to use this method for widely and publicly available websites that will have an average user. For example, it wouldn't be a good idea to implement this for a website like Facebook. While this technique can prevent the user from having to type a password (thus protecting against an average keylogger from stealing it), it is still considered a good idea to consider using both a password and SSL client authentication combined.&lt;br /&gt;
&lt;br /&gt;
For more information, see: [http://publib.boulder.ibm.com/infocenter/tivihelp/v5r1/index.jsp?topic=%2Fcom.ibm.itim.infocenter.doc%2Fcpt%2Fcpt_ic_security_ssl_authent2way.html] or [http://www.codeproject.com/Articles/326574/An-Introduction-to-Mutual-SSL-Authentication]&lt;br /&gt;
&lt;br /&gt;
== Authentication and Error Messages ==&lt;br /&gt;
&lt;br /&gt;
Incorrectly implemented error messages in the case of authentication functionality can be used for the purposes of user ID and password enumeration. An application should respond (both HTTP and HTML) in a generic manner.&lt;br /&gt;
&lt;br /&gt;
==== Authentication Responses ====&lt;br /&gt;
&lt;br /&gt;
An application should respond with a generic error message regardless of whether the user ID or password was incorrect. It should also give no indication to the status of an existing account.&lt;br /&gt;
&lt;br /&gt;
==== Incorrect Response Examples ====&lt;br /&gt;
&lt;br /&gt;
*&amp;quot;Login for User foo: invalid password&amp;quot; &lt;br /&gt;
*&amp;quot;Login failed, invalid user ID&amp;quot; &lt;br /&gt;
*&amp;quot;Login failed; account disabled&amp;quot; &lt;br /&gt;
*&amp;quot;Login failed; this user is not active&amp;quot;&lt;br /&gt;
&lt;br /&gt;
==== Correct Response Example ====&lt;br /&gt;
&lt;br /&gt;
*&amp;quot;Login failed; Invalid userID or password&amp;quot;&lt;br /&gt;
&lt;br /&gt;
The correct response does not indicate if the user ID or password is the incorrect parameter and hence inferring a valid user ID. &lt;br /&gt;
&lt;br /&gt;
==== Error Codes and URL's ====&lt;br /&gt;
&lt;br /&gt;
The application may return a different HTTP Error code depending on the authentication attempt response. It may respond with a 200 for a positive result and a 403 for a negative result. Even though a generic error page is shown to a user, the HTTP response code may differ which can leak information about whether the account is valid or not.&lt;br /&gt;
&lt;br /&gt;
== Transmit Passwords Only Over TLS ==&lt;br /&gt;
&lt;br /&gt;
See: [[Transport Layer Protection Cheat Sheet]]&lt;br /&gt;
&lt;br /&gt;
The login page and all subsequent authenticated pages must be exclusively accessed over TLS. The initial login page, referred to as the &amp;quot;login landing page&amp;quot;, must be served over TLS. Failure to utilize TLS for the login landing page allows an attacker to modify the login form action, causing the user's credentials to be posted to an arbitrary location. Failure to utilize TLS for authenticated pages after the login enables an attacker to view the unencrypted session ID and compromise the user's authenticated session.&lt;br /&gt;
&lt;br /&gt;
== Implement Account Lockout ==&lt;br /&gt;
&lt;br /&gt;
If an attacker is able to guess passwords without the account becoming disabled due to failed authentication attempts, the attacker has an opportunity to continue with a brute force attack until the account is compromised. &lt;br /&gt;
&lt;br /&gt;
Automating brute-force/password guessing attacks on web applications is a trivial challenge. Password lockout mechanisms should be employed that lock out an account if more than a preset number of unsuccessful login attempts are made. &lt;br /&gt;
&lt;br /&gt;
Password lockout mechanisms have a logical weakness. An attacker that undertakes a large number of authentication attempts on known account names can produce a result that locks out entire blocks of user accounts. &lt;br /&gt;
&lt;br /&gt;
Given that the intent of a password lockout system is to protect from brute-force attacks, a sensible strategy is to lockout accounts for a period of time (e.g., 20 minutes). This significantly slows down attackers, while allowing the accounts to reopen automatically for legitimate users.&lt;br /&gt;
&lt;br /&gt;
= Session Management General Guidelines  =&lt;br /&gt;
&lt;br /&gt;
Session management is directly related to authentication. The '''Session Management General Guidelines''' previously available on this OWASP Authentication Cheat Sheet have been integrated into the new [https://www.owasp.org/index.php/Session_Management_Cheat_Sheet OWASP Session Management Cheat Sheet]. &lt;br /&gt;
&lt;br /&gt;
= Password Managers =&lt;br /&gt;
&lt;br /&gt;
Password managers are programs, browser plugins or web services that automate management of large number of different credentials, including memorizing and filling-in, generating random passwords on different sites etc. The web application can help password managers by:&lt;br /&gt;
&lt;br /&gt;
* using standard HTML forms for username and password input,&lt;br /&gt;
* not using multi-stage login schemes (username on first screen, then password),&lt;br /&gt;
* not using highly scripted (JavaScript) authentication schemes.&lt;br /&gt;
&lt;br /&gt;
= Authors and Primary Editors  =&lt;br /&gt;
&lt;br /&gt;
Eoin Keary eoinkeary[at]owasp.org &lt;br /&gt;
&lt;br /&gt;
= Other Cheatsheets =&lt;br /&gt;
{{Cheatsheet_Navigation}}&lt;br /&gt;
&lt;br /&gt;
[[Category:Cheatsheets]]&lt;/div&gt;</summary>
		<author><name>Manuel Aude Morales</name></author>	</entry>

	</feed>