<?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=Henri+Salo</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=Henri+Salo"/>
		<link rel="alternate" type="text/html" href="https://wiki.owasp.org/index.php/Special:Contributions/Henri_Salo"/>
		<updated>2026-05-30T00:55:12Z</updated>
		<subtitle>User contributions</subtitle>
		<generator>MediaWiki 1.27.2</generator>

	<entry>
		<id>https://wiki.owasp.org/index.php?title=Missing_XML_Validation&amp;diff=203624</id>
		<title>Missing XML Validation</title>
		<link rel="alternate" type="text/html" href="https://wiki.owasp.org/index.php?title=Missing_XML_Validation&amp;diff=203624"/>
				<updated>2015-11-20T09:48:51Z</updated>
		
		<summary type="html">&lt;p&gt;Henri Salo: Removed two actual URL references, which were meant as an example to be filled with real URLs.&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Template:Vulnerability}}&lt;br /&gt;
{{Template:Fortify}}&lt;br /&gt;
&lt;br /&gt;
Last revision (mm/dd/yy): '''{{REVISIONMONTH}}/{{REVISIONDAY}}/{{REVISIONYEAR}}'''&lt;br /&gt;
&lt;br /&gt;
[[ASDR_TOC_Vulnerabilities|Vulnerabilities Table of Contents]]&lt;br /&gt;
&lt;br /&gt;
==Description==&lt;br /&gt;
&lt;br /&gt;
Failure to enable validation when parsing XML gives an attacker the opportunity to supply malicious input.&lt;br /&gt;
&lt;br /&gt;
Most successful attacks begin with a violation of the programmer's assumptions. By accepting an XML document without validating it against a DTD or XML schema, the programmer leaves a door open for attackers to provide unexpected, unreasonable, or malicious input. It is not possible for an XML parser to validate all aspects of a document's content; a parser cannot understand the complete semantics of the data. However, a parser can do a complete and thorough job of checking the document's structure and therefore guarantee to the code that processes the document that the content is well-formed.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Risk Factors==&lt;br /&gt;
&lt;br /&gt;
* Talk about the [[OWASP Risk Rating Methodology|factors]] that make this vulnerability likely or unlikely to actually happen&lt;br /&gt;
* Discuss the technical impact of a successful exploit of this vulnerability&lt;br /&gt;
* Consider the likely [business impacts] of a successful attack&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Examples==&lt;br /&gt;
&lt;br /&gt;
===Short example name===&lt;br /&gt;
: A short example description, small picture, or sample code with [http://www.site.com links]&lt;br /&gt;
&lt;br /&gt;
===Short example name===&lt;br /&gt;
: A short example description, small picture, or sample code with [http://www.site.com links]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Related [[Attacks]]==&lt;br /&gt;
&lt;br /&gt;
* [[Attack 1]]&lt;br /&gt;
* [[Attack 2]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Related [[Vulnerabilities]]==&lt;br /&gt;
&lt;br /&gt;
* [[Vulnerability 1]]&lt;br /&gt;
* [[Vulnerabiltiy 2]]&lt;br /&gt;
&lt;br /&gt;
==Related [[Controls]]==&lt;br /&gt;
&lt;br /&gt;
* [[:Category:Input Validation]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Related [[Technical Impacts]]==&lt;br /&gt;
&lt;br /&gt;
* [[Technical Impact 1]]&lt;br /&gt;
* [[Technical Impact 2]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==References==&lt;br /&gt;
TODO&lt;br /&gt;
&lt;br /&gt;
__NOTOC__&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Category:OWASP ASDR Project]]&lt;br /&gt;
[[Category:Input Validation Vulnerability]]&lt;br /&gt;
[[Category:XML]]&lt;br /&gt;
[[Category:Vulnerability]]&lt;/div&gt;</summary>
		<author><name>Henri Salo</name></author>	</entry>

	<entry>
		<id>https://wiki.owasp.org/index.php?title=Insecure_Configuration_Management&amp;diff=192820</id>
		<title>Insecure Configuration Management</title>
		<link rel="alternate" type="text/html" href="https://wiki.owasp.org/index.php?title=Insecure_Configuration_Management&amp;diff=192820"/>
				<updated>2015-04-07T11:45:02Z</updated>
		
		<summary type="html">&lt;p&gt;Henri Salo: Fix URL address.&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Description==&lt;br /&gt;
&lt;br /&gt;
Web server and application server configurations play a key role in the security of a web application. These servers are responsible for serving content and invoking applications that generate content. In addition, many application servers provide a number of services that web applications can use, including data storage, directory services, mail, messaging, and more. Failure to manage the proper configuration of your servers can lead to a wide variety of security problems. &lt;br /&gt;
&lt;br /&gt;
Frequently, the web development group is separate from the group operating the site. In fact, there is often a wide gap between those who write the application and those responsible for the operations environment. Web application security concerns often span this gap and require members from both sides of the project to properly ensure the security of a site’s application.&lt;br /&gt;
&lt;br /&gt;
There are a wide variety of server configuration problems that can plague the security of a site. These include:&lt;br /&gt;
&lt;br /&gt;
* Unpatched security flaws in the server software &lt;br /&gt;
* Server software flaws or misconfigurations that permit directory listing and directory traversal attacks &lt;br /&gt;
* Unnecessary default, backup, or sample files, including scripts, applications, configuration files, and web pages &lt;br /&gt;
* Improper file and directory permissions &lt;br /&gt;
* Unnecessary services enabled, including content management and remote administration &lt;br /&gt;
* Default accounts with their default passwords &lt;br /&gt;
* Administrative or debugging functions that are enabled or accessible &lt;br /&gt;
* Overly informative error messages (more details in the [[Improper Error Handling|error handling section]]) &lt;br /&gt;
* Misconfigured SSL certificates and encryption settings &lt;br /&gt;
* Use of self-signed certificates to achieve authentication and man-in-the-middle protection &lt;br /&gt;
* Use of default certificates &lt;br /&gt;
* Improper authentication with external systems &lt;br /&gt;
&lt;br /&gt;
Some of these problems can be detected with readily available security scanning tools. Once detected, these problems can be easily exploited and result in total compromise of a website. Successful attacks can also result in the compromise of backend systems including databases and corporate networks. Having secure software and a secure configuration are both required in order to have a secure site.&lt;br /&gt;
&lt;br /&gt;
==Environments Affected==&lt;br /&gt;
&lt;br /&gt;
All web servers, application servers, and web application environments are susceptible to misconfiguration. &lt;br /&gt;
&lt;br /&gt;
==Examples and References==&lt;br /&gt;
&lt;br /&gt;
* [[:Category:OWASP_Guide_Project|OWASP Guide]] to Building Secure Web Applications and Web Services &lt;br /&gt;
* Web Server Security Best Practices: http://www.pcmag.com/article2/0,4149,11525,00.asp &lt;br /&gt;
* Securing Public Web Servers: http://csrc.nist.gov/publications/nistpubs/800-44-ver2/SP800-44v2.pdf&lt;br /&gt;
&lt;br /&gt;
==How to Determine If You Are Vulnerable==&lt;br /&gt;
&lt;br /&gt;
If you have not made a concerted effort to lock down your web and application servers you are most likely vulnerable. Few, if any, server products are secure out of the box. A secure configuration for your platform should be documented and updated frequently. A manual review of the configuration guide should be performed regularly to ensure that it has been kept up to date and is consistent. A comparison to the actual deployed systems is also recommended.&lt;br /&gt;
&lt;br /&gt;
In addition, there are a number of scanning products available that will externally scan a web or application server for known vulnerabilities, including Nessus and Nikto. You should run these tools on a regular basis, at least monthly, to find problems as soon as possible. The tools should be run both internally and externally. External scans should be run from a host located external to the server’s network. Internal scans should be run from the same network as the target servers.&lt;br /&gt;
&lt;br /&gt;
==How to Protect Yourself==&lt;br /&gt;
&lt;br /&gt;
The first step is to create a hardening guideline for your particular web server and application server configuration. This configuration should be used on all hosts running the application and in the development environment as well. We recommend starting with any existing guidance you can find from your vendor or those available from the various existing security organizations such as OWASP, CERT, and SANS and then tailoring them for your particular needs. The hardening guideline should include the following topics:&lt;br /&gt;
&lt;br /&gt;
* Configuring all security mechanisms &lt;br /&gt;
* Turning off all unused services &lt;br /&gt;
* Setting up roles, permissions, and accounts, including disabling all default accounts or changing their passwords &lt;br /&gt;
* Logging and alerts &lt;br /&gt;
&lt;br /&gt;
Once your guideline has been established, use it to configure and maintain your servers. If you have a large number of servers to configure, consider semi-automating or completely automating the configuration process. Use an existing configuration tool or develop your own. A number of such tools already exist. You can also use disk replication tools such as Ghost to take an image of an existing hardened server, and then replicate that image to new servers. Such a process may or may not work for you given your particular environment.&lt;br /&gt;
&lt;br /&gt;
Keeping the server configuration secure requires vigilance. You should be sure that the responsibility for keeping the server configuration up to date is assigned to an individual or team. The maintenance process should include:&lt;br /&gt;
&lt;br /&gt;
* Monitoring the latest security vulnerabilities published &lt;br /&gt;
* Applying the latest security patches &lt;br /&gt;
* Updating the security configuration guideline &lt;br /&gt;
* Regular vulnerability scanning from both internal and external perspectives &lt;br /&gt;
* Regular internal reviews of the server’s security configuration as compared to your configuration guide &lt;br /&gt;
* Regular status reports to upper management documenting overall security posture&lt;br /&gt;
&lt;br /&gt;
__NOEDITSECTION__&lt;/div&gt;</summary>
		<author><name>Henri Salo</name></author>	</entry>

	<entry>
		<id>https://wiki.owasp.org/index.php?title=PHP_Security_Cheat_Sheet&amp;diff=154001</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=154001"/>
				<updated>2013-06-17T17:42:06Z</updated>
		
		<summary type="html">&lt;p&gt;Henri Salo: Added preg_replace information.&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 basic PHP security tips for developers and administrators. Keep in mind that tips mentioned in this page may not be sufficient for securing your web application.&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 open source. The core of PHP is reasonably secure, but its plugins, libraries and third party tools are often insecure. Also no default security mechanism is included in PHP (there were some in the old days, but they usually broke things). &lt;br /&gt;
&lt;br /&gt;
PHP developers are usually better informed than ASPX or JSP developers on how the 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, which is why PHP websites often have more flawed. &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, PHP 5.2.x powered website may become vulnerable. ''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 to confusion and makes your code prone 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 permits the hacking of your website, and every hacker first tries SQL injection flaws, fixing SQL injections are the 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 a 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 once 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 (Object Relational Mappers) are good security practice. If you're using an ORM (like [http://www.doctrine-project.org/ Doctrine]) in your PHP project, you're still 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;
=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. In PHP this function is named 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. Eval is usually also slower.&lt;br /&gt;
&lt;br /&gt;
Function preg_replace() should not be used with unsanitized user input, because the payload will be [http://stackoverflow.com/a/4292439 eval()'ed].&lt;br /&gt;
&lt;br /&gt;
    preg_replace(&amp;quot;/.*/e&amp;quot;,&amp;quot;system('echo /etc/passwd')&amp;quot;);&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 facilities 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;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.  Also beware of versions of this code which make use of the HTTP_X_FORWARDED_FOR variable as this data is effectively user input and therefore susceptible to spoofing (more information [http://www.thespanner.co.uk/2007/12/02/faking-the-unexpected/ here] and [http://security.stackexchange.com/a/34327/37 here] )&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;
== 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>Henri Salo</name></author>	</entry>

	<entry>
		<id>https://wiki.owasp.org/index.php?title=PHP_Security_Cheat_Sheet&amp;diff=154000</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=154000"/>
				<updated>2013-06-17T17:35:26Z</updated>
		
		<summary type="html">&lt;p&gt;Henri Salo: Removed obsolete information and cleaned up code injection -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 basic PHP security tips for developers and administrators. Keep in mind that tips mentioned in this page may not be sufficient for securing your web application.&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 open source. The core of PHP is reasonably secure, but its plugins, libraries and third party tools are often insecure. Also no default security mechanism is included in PHP (there were some in the old days, but they usually broke things). &lt;br /&gt;
&lt;br /&gt;
PHP developers are usually better informed than ASPX or JSP developers on how the 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, which is why PHP websites often have more flawed. &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, PHP 5.2.x powered website may become vulnerable. ''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 to confusion and makes your code prone 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 permits the hacking of your website, and every hacker first tries SQL injection flaws, fixing SQL injections are the 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 a 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 once 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 (Object Relational Mappers) are good security practice. If you're using an ORM (like [http://www.doctrine-project.org/ Doctrine]) in your PHP project, you're still 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. In PHP this function is named 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. Eval is usually also slower.&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 facilities 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;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.  Also beware of versions of this code which make use of the HTTP_X_FORWARDED_FOR variable as this data is effectively user input and therefore susceptible to spoofing (more information [http://www.thespanner.co.uk/2007/12/02/faking-the-unexpected/ here] and [http://security.stackexchange.com/a/34327/37 here] )&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;
== 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>Henri Salo</name></author>	</entry>

	<entry>
		<id>https://wiki.owasp.org/index.php?title=ApplicationLayerIntrustionDetection&amp;diff=88133</id>
		<title>ApplicationLayerIntrustionDetection</title>
		<link rel="alternate" type="text/html" href="https://wiki.owasp.org/index.php?title=ApplicationLayerIntrustionDetection&amp;diff=88133"/>
				<updated>2010-08-28T19:40:50Z</updated>
		
		<summary type="html">&lt;p&gt;Henri Salo: Small corrections&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;'''Application Layer Intrusion Detection'''&lt;br /&gt;
&lt;br /&gt;
Today’s applications are responsible for securely performing critical operations for individuals and businesses around the world. From transferring money, to managing health records, web enabled applications handle immense amounts of sensitive data each day. Despite the critical role they play, the security defenses within these applications are seriously lacking. The attackers are organized, motivated, and backed by a network of resources and talent. If our applications have any hope of standing up to such formidable opponents, then we need to move beyond just attempting to design our applications securely. We need to implement robust attack detection within the application to identify malicious users before they are successful in their attack. Just like in the real world, we would prefer to detect and prevent an attack instead of just responding after a compromise has occurred.&lt;br /&gt;
&lt;br /&gt;
How do we bridge the technology gap to implement appropriate security controls in our critical applications? The first step is to realize that in order to detect and respond to malicious activity at the application layer we need to be able to monitor and understand a user’s actions within the application. Security approaches of previous years are not sufficient. A firewall provides no protection; its purpose is to allow users to access the application. Nor does a network based IDS system since it will have no insight to our application specific traffic. Antivirus is also out of the question since this is a signature based approach that knows nothing of custom web application vulnerabilities.&lt;br /&gt;
&lt;br /&gt;
We need to move into the application layer to understand our attackers. One potential solution is a web application firewall (WAF). A WAF is able to detect generic application attacks such as basic SQL injection attacks or common actions of a known attack sequence. While some detection is better than none, a generic product could never fully understand the intricacies of each custom web application. This approach is just not sufficient to properly protect critical applications that process sensitive financial data or personal user information. Imagine trying to design an effective building alarm system without any knowledge of how the building is designed or even where the doors and windows are located. &lt;br /&gt;
&lt;br /&gt;
The solution is to design and integrate a detection and response system into the application itself. Within the application we have a full understanding of the user initiating an action, the target of that action and whether that action should be allowed for that user. Inside the application our protection system can identify advanced attacks that are attempting to exploit specific features of our application. Within the application we can easily identify attempts to circumvent security controls or use the application in an unintended manner. After we have determined that a particular user has malicious intent and is attempting to identify weaknesses in our system, we can immediately respond and block the user from future access to the application, or take whatever other action is appropriate. Once locked out, such users can no longer login and are limited to attacking the perimeter of an application, which often contains limited functionality and is typically well secured. Alternatively, some organizations may wish to forego an automated lockout response and instead generate an attack alert and allow their security-monitoring center to perform an immediate investigation and decide upon the appropriate response.&lt;br /&gt;
&lt;br /&gt;
The rigor of response is a decision for each organization in relation to their tolerance for risk and specific needs for an application. However, it is clear that this level of detection capability is a must for any organization wishing to prevent skilled and persistent attackers from compromising their critical applications.&lt;br /&gt;
&lt;br /&gt;
'''OWASP AppSensor'''&lt;br /&gt;
&lt;br /&gt;
OWASP is committed to the protection of applications through application attack detection and automated response. The OWASP AppSensor project has been established in response to the clear need for guidance and knowledge in this area.&lt;br /&gt;
&lt;br /&gt;
AppSensor provides the following:&lt;br /&gt;
* Recommendations for what application actions should be detected as malicious along with suggested responses&lt;br /&gt;
* Guidance on designing and implementing an attack detection and response system within an application&lt;br /&gt;
* A Java reference implementation that you can integrate into your application as the basis for your Application Layer Intrusion Detection and Response mechanism&lt;br /&gt;
&lt;br /&gt;
Find out more at: [[:Category:OWASP_AppSensor_Project|The OWASP AppSensor Project]]&lt;/div&gt;</summary>
		<author><name>Henri Salo</name></author>	</entry>

	<entry>
		<id>https://wiki.owasp.org/index.php?title=Insecure_Temporary_File&amp;diff=84455</id>
		<title>Insecure Temporary File</title>
		<link rel="alternate" type="text/html" href="https://wiki.owasp.org/index.php?title=Insecure_Temporary_File&amp;diff=84455"/>
				<updated>2010-06-04T12:18:48Z</updated>
		
		<summary type="html">&lt;p&gt;Henri Salo: Added link to guide in Python-documentation&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Template:Vulnerability}}&lt;br /&gt;
{{Template:Fortify}}&lt;br /&gt;
&lt;br /&gt;
Last revision (mm/dd/yy): '''{{REVISIONMONTH}}/{{REVISIONDAY}}/{{REVISIONYEAR}}'''&lt;br /&gt;
&lt;br /&gt;
[[ASDR_TOC_Vulnerabilities|Vulnerabilities Table of Contents]]&lt;br /&gt;
&lt;br /&gt;
==Description==&lt;br /&gt;
&lt;br /&gt;
Creating and using insecure temporary files can leave application and system data vulnerable to attacks.&lt;br /&gt;
&lt;br /&gt;
Applications require temporary files so frequently that many different mechanisms exist for creating them in the C Library and Windows® API. Most of these functions are vulnerable to various forms of attacks.&lt;br /&gt;
&lt;br /&gt;
==Risk Factors==&lt;br /&gt;
TBD&lt;br /&gt;
&lt;br /&gt;
==Examples==&lt;br /&gt;
&lt;br /&gt;
The following code uses a temporary file for storing intermediate data gathered from the network before it is processed.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;	...&lt;br /&gt;
	if (tmpnam_r(filename)){&lt;br /&gt;
		FILE* tmp = fopen(filename,&amp;quot;wb+&amp;quot;);&lt;br /&gt;
		while((recv(sock,recvbuf,DATA_SIZE, 0) &amp;gt; 0)&amp;amp;&amp;amp;(amt!=0))&lt;br /&gt;
			amt = fwrite(recvbuf,1,DATA_SIZE,tmp);&lt;br /&gt;
	}&lt;br /&gt;
	...&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This otherwise unremarkable code is vulnerable to a number of different attacks because it relies on an insecure method for creating temporary files. The vulnerabilities introduced by this function and others are described in the following sections. The most egregious security problems related to temporary file creation have occurred on Unix-based operating systems, but Windows applications have parallel risks. This section includes a discussion of temporary file creation on both Unix and Windows systems.&lt;br /&gt;
&lt;br /&gt;
Methods and behaviors can vary between systems, but the fundamental risks introduced by each are reasonably constant.&lt;br /&gt;
&lt;br /&gt;
The functions designed to aid in the creation of temporary files can be broken into two groups based whether they simply provide a filename or actually open a new file.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Group 1 – &amp;quot;Unique&amp;quot; Filenames===&lt;br /&gt;
&lt;br /&gt;
The first group of C Library and WinAPI functions designed to help with the process of creating temporary files do so by generating a unique file name for a new temporary file, which the program is then supposed to open. This group includes C Library functions like tmpnam(), tempnam(), mktemp() and their C++ equivalents prefaced with an _ (underscore) as well as the GetTempFileName() function from the Windows API. This group of functions suffers from an underlying race condition on the filename chosen. Although the functions guarantee that the filename is unique at the time it is selected, there is no mechanism to prevent another process or an attacker from creating a file with the same name after it is selected but before the application attempts to open the file. Beyond the risk of a legitimate collision caused by another call to the same function, there is a high probability that an attacker will be able to create a malicious collision because the filenames generated by these functions are not sufficiently randomized to make them difficult to guess.&lt;br /&gt;
&lt;br /&gt;
If a file with the selected name is created, then depending on how the file is opened the existing contents or access permissions of the file may remain intact. If the existing contents of the file are malicious in nature, an attacker may be able to inject dangerous data into the application when it reads data back from the temporary file. If an attacker pre-creates the file with relaxed access permissions, then data stored in the temporary file by the application may be accessed, modified or corrupted by an attacker. On Unix based systems an even more insidious attack is possible if the attacker pre-creates the file as a link to another important file. Then, if the application truncates or writes data to the file, it may unwittingly perform damaging operations for the attacker. This is an especially serious threat if the program operates with elevated permissions.&lt;br /&gt;
&lt;br /&gt;
Finally, in the best case the file will be opened with the a call to open() using the O_CREAT and O_EXCL flags or to CreateFile() using the CREATE_NEW attribute, which will fail if the file already exists and therefore prevent the types of attacks described above. However, if an attacker is able to accurately predict a sequence of temporary file names, then the application may be prevented from opening necessary temporary storage causing a denial of service (DoS) attack. This type of attack would not be difficult to mount given the small amount of randomness used in the selection of the filenames generated by these functions.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Group 2 – &amp;quot;Unique&amp;quot; Files===&lt;br /&gt;
&lt;br /&gt;
The second group of C Library functions attempts to resolve some of the security problems related to temporary files by not only generating a unique file name, but also opening the file. This group includes C Library functions like tmpfile() and its C++ equivalents prefaced with an _ (underscore), as well as the slightly better-behaved C Library function mkstemp().&lt;br /&gt;
&lt;br /&gt;
The tmpfile() style functions construct a unique filename and open it in the same way that fopen() would if passed the flags &amp;quot;wb+&amp;quot;, that is, as a binary file in read/write mode. If the file already exists, tmpfile() will truncate it to size zero, possibly in an attempt to assuage the security concerns mentioned earlier regarding the race condition that exists between the selection of a supposedly unique filename and the subsequent opening of the selected file. However, this behavior clearly does not solve the function's security problems. First, an attacker can pre-create the file with relaxed access-permissions that will likely be retained by the file opened by tmpfile(). Furthermore, on Unix based systems if the attacker pre-creates the file as a link to another important file, the application may use its possibly elevated permissions to truncate that file, thereby doing damage on behalf of the attacker. Finally, if tmpfile() does create a new file, the access permissions applied to that file will vary from one operating system to another, which can leave application data vulnerable even if an attacker is unable to predict the filename to be used in advance.&lt;br /&gt;
&lt;br /&gt;
Finally, mkstemp() is a reasonably safe way to create temporary files. It will attempt to create and open a unique file based on a filename template provided by the user combined with a series of randomly generated characters. If it is unable to create such a file, it will fail and return -1. On modern systems the file is opened using mode 0600, which means the file will be secure from tampering unless the user explicitly changes its access permissions. However, mkstemp() still suffers from the use of predictable file names and can leave an application vulnerable to denial of service attacks if an attacker causes mkstemp() to fail by predicting and pre-creating the filenames to be used.&lt;br /&gt;
&lt;br /&gt;
==Related [[Attacks]]==&lt;br /&gt;
&lt;br /&gt;
* [[Denial of Service]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Related [[Vulnerabilities]]==&lt;br /&gt;
&lt;br /&gt;
* [[Vulnerability 1]]&lt;br /&gt;
* [[Vulnerabiltiy 2]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Related [[Controls]]==&lt;br /&gt;
&lt;br /&gt;
* [[Control 1]]&lt;br /&gt;
* [[Control 2]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Related [[Technical Impacts]]==&lt;br /&gt;
&lt;br /&gt;
* [[Technical Impact 1]]&lt;br /&gt;
* [[Technical Impact 2]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Related Coding==&lt;br /&gt;
&lt;br /&gt;
* [http://docs.python.org/library/tempfile.html#tempfile.mkstemp Python creating a temporary file the most secure manner possible]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==References==&lt;br /&gt;
&lt;br /&gt;
TBD&lt;br /&gt;
&lt;br /&gt;
[[Category:FIXME|add links&lt;br /&gt;
&lt;br /&gt;
In addition, one should classify vulnerability based on the following subcategories: Ex:&amp;lt;nowiki&amp;gt;[[Category:Error Handling Vulnerability]]&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Availability Vulnerability&lt;br /&gt;
&lt;br /&gt;
Authorization Vulnerability&lt;br /&gt;
&lt;br /&gt;
Authentication Vulnerability&lt;br /&gt;
&lt;br /&gt;
Concurrency Vulnerability&lt;br /&gt;
&lt;br /&gt;
Configuration Vulnerability&lt;br /&gt;
&lt;br /&gt;
Cryptographic Vulnerability&lt;br /&gt;
&lt;br /&gt;
Encoding Vulnerability&lt;br /&gt;
&lt;br /&gt;
Error Handling Vulnerability&lt;br /&gt;
&lt;br /&gt;
Input Validation Vulnerability&lt;br /&gt;
&lt;br /&gt;
Logging and Auditing Vulnerability&lt;br /&gt;
&lt;br /&gt;
Session Management Vulnerability]]&lt;br /&gt;
&lt;br /&gt;
__NOTOC__&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Category:OWASP ASDR Project]]&lt;br /&gt;
[[Category:C]]&lt;br /&gt;
[[Category:Code Snippet]]&lt;br /&gt;
[[Category:File System]]&lt;br /&gt;
[[Category:Windows]]&lt;br /&gt;
[[Category:Unix]]&lt;br /&gt;
[[Category:Use of Dangerous API]]&lt;br /&gt;
[[Category:Vulnerability]]&lt;/div&gt;</summary>
		<author><name>Henri Salo</name></author>	</entry>

	</feed>