PHP is the most commonly used server-side programming and deployed more than 80% in web server all over the world. However, 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.
2. WhoAmI
• Lazy Blogger
– Japan, Security, FOSS, Politics, Christian
– http://narudomr.blogspot.com
• Food Mania
– Steak, Yakiniku, BBQ
– Sushi (especially Otoro)
– All Kinds of Noodle
• 16 Years In PHP Coding, Since v4.0
(3rd fluent programming language next to C & C++)
• Consultant for OWASP Thailand Chapter
• Head of IT Security & Solution Architecture,
Kiatnakin Bank PLC (KKP)
5. Usage of Server-Side Programming
Languages for Websites
PHP
ASP.NET
Java
Static Files
Cold Fusion
Ruby
Perl
JavaScript
Python
Erlang
0.0% 10.0% 20.0% 30.0% 40.0% 50.0% 60.0% 70.0% 80.0% 90.0%
81.9%
15.7%
2.9%
1.5%
0.7%
0.6%
0.4%
0.3%
0.2%
0.1%
W3Techs.com, 11 September 2016
6. Web Apps in PHP are Most Vulnerable
• 86% of applications written in PHP contained at
least one cross-site scripting (XSS) vulnerability.
• 56% of apps included SQLi (SQL injection),
which is one of the dangerous and easy-to-
exploit web application vulnerabilities.
• 67% of apps allowed for directory traversal.
• 61% of apps allowed for code injection.
• 58% of apps had problems with credentials
management
• 73% of apps contained cryptographic issues.
• http://thehackernews.com/2015/12/programming-language-security.html
7. PHP Characteristics
• Unusual → Language + Web Framework
• A large community of libraries that
contribute to programming in PHP
• All three aspects (language, framework,
and libraries) need to be taken into
consideration when trying to secure a PHP
site
8. Language Issues
• Weak typing
• Exceptions and error handling
• php.ini
• Unhelpful builtins
9. Language Issue: Weak Typing
• PHP will automatically convert data of an incorrect
type into the expected type.
$x = 1 + "1"; // x is 2
• Leads to bugs, injections and vulnerabilities if
improperly handles
• Try to use functions and operators that do not do
implicit type conversions (e.g. === and not ==) but
not all operators have strict version (such as < or >)
• Many built-in functions (like in_array) use weakly
typed comparison functions by default, making it
difficult to write correct code.
12. Language Issue:
Exception and Error Handling
• Almost all PHP builtins, and many PHP libraries, do not
use exceptions, but instead report errors then allow the
faulty code to carry on running.
• Many other languages, error conditions that failed to
anticipate will stop running. → Fail Safe
• It is often best to turn up error reporting as high as
possible using the error_reporting function, and never
attempt to suppress error messages — always follow
the warnings and write code that is more robust.
• Try to use set_error_handler function to handle user
defined error handler.
13. Language Issue:
Exception and Error Handling
What is wrong with this code to check blacklist user?
$db = mysqli_connect('localhost', 'dbuser', 'dbpassword', 'dbname');
function can_access_feature($current_user) {
global $db;
$uid = mysqli_real_escape_string($db, $current_user->uid);
$res = mysqli_query($db, "SELECT COUNT(id) FROM blacklist WHERE uid = '$uid';");
$row = mysqli_fetch_array($res);
if ((int)$row[0] > 0) {
return false;
} else {
return true;
}
}
if (!can_access_feature($current_user)) {
exit();
}
// Code for feature here
What happens if db connection is failed?
14. Language Issue: php.ini
• PHP code often depends strongly on the
values of many configuration settings
• Difficult to write code that works correctly in
all circumstances.
• Difficult to correctly use 3rd party code
15. Language Issue: Unhelpful Builtins
• Built-in functions that appear to provide security,
but buggy and hard to handle security problems
– addslashes
– mysql_escape_string
– mysql_real_escape_string
• 'array' data structure
– Extensively used in all PHP code and internally
– Confusing mix between an array and a dictionary
– Cause even experienced PHP developers to
introduce critical security vulnerabilities such as
Drupal SA-CORE-2014-005 (CVE-2014-3704)
16. Framework Issues
• URL Routing: “.php” or not
• Input Handling
– Instead of treating HTTP input as simple strings,
PHP will build arrays from HTTP input
• Template Language
– However, it doesn't do HTML escaping by default
– Lead to Cross-Site Scripting
• Other Inadequacies
– No CSRF protection mechanism
https://www.owasp.org/index.php/PHP_Security_Cheat_Sheet#Framework_issues
17. Input Handling Example
$supplied_nonce = $_GET['nonce'];
$correct_nonce = get_correct_value_somehow();
if (strcmp($supplied_nonce, $correct_nonce) == 0) {
// Go ahead and reset the password
} else {
echo 'Sorry, incorrect link';
}
A password reset code:
If an attacker uses a query string like this:
http://example.com/?nonce[]=a
●
Then $supplied_nonce is an array.
●
The function strcmp() will then return NULL
●
Due to weak typing and the use of the == (equality) operator instead of the
=== (identity) operator, the expression NULL == 0
●
The attacker will be able to reset the password without providing a correct
nonce
19. P1: Remote Code Execution
• Remote Code Execution or Arbitrary Code Execution is the
ability to trigger arbitrary code execution from one machine
on another (especially via a wide-area network such as the
Internet)
• The most widespread PHP security issue since July 2004
• The root causes of this issue are:
– Insufficient validation of user input prior to dynamic file system calls,
such as require or include or fopen()
– allow_url_fopen and PHP wrappers allow this behavior by default,
which is unnecessary for most applications
$handle = fopen("http://www.example.com/", "r");
– Poor permissions and planning by many hosters allowing excessive
default privileges and wide ranging access to what should be off
limits areas.
20. P1: Remote Code Execution (cont’d)
• Version Affected: PHP 4 (after PHP 4.0.4), 5.x
• CVE/CAN Entries: More than 100 such vulnerabilities reported
since July 30, 2004, for examples:
– Magento < 2.0.6 (popular eCommerce platform) Unauthenticated
Remote Code Execution (CVE-2016-4010)
http://netanelrub.in/2016/05/17/magento-unauthenticated-remote-
code-execution/
– Joomla! 1.5.x, 2.x, and 3.x < 3.4.6 allow remote attackers to conduct
PHP object injection attacks and execute arbitrary PHP code via the
HTTP User-Agent header (CVE-2015-8562)
http://www.securityfocus.com/bid/79195
– vBulletin 5 Connect 5.1.2 through 5.1.9 allows remote attackers to
conduct PHP object injection attacks and execute arbitrary PHP code
(CVE-2015-7808) http://blog.checkpoint.com/2015/11/05/check-point-
discovers-critical-vbulletin-0-day/
21. How to Determine If You Are Vulnerable
$report = $_POST[‘report_name’];
include $report;
$username = $_POST[‘username’];
eval(“echo $username”);
Inspect your code for constructs like:
or
Other code constructs to look for include:
●
fopen(), fsockopen()
●
Direct command execution - popen(), system(), ` (backtick operator). Allows remote
attackers to execute code on the system without necessarily introducing remote code.
●
Direct PHP code execution via eval()
●
Limited evaluation if the attacker supplied PHP code is then used within double
quotes in the application code – most useful as an information disclosure
●
include, include_once, require, require_once with dynamic inputs
●
file_get_contents()
●
imagecreatefromXXX()
●
mkdir(), unlink() and rmdir() and so on - PHP 5.0 and later has limited support for
some URL wrappers for almost all file functions
22. How to Protect Against Remote Code
Execution
• Developers should
– Review existing code for file operations, include/require, and
eval() statements to ensure that user input is properly validated
prior to first use
– When writing new code, try to limit the use of dynamic inputs
from users to vulnerable functions either directly or via wrappers
• Hosters should:
– Disable allow_url_fopen in php.ini by setting it to 0
– Enable safe_mode and set open_basedir restrictions (if you
know what you're doing - it's not really that safe!)
– Lockdown the server environment to prevent the server from
making new outbound requests
23. P2: Cross-Site Scripting (XSS)
• Cross-site scripting (aka. HTML injection or user agent
injection) can be in three modes
– Reflected: The attacker provides a link or other payload
containing embedded malicious content, which the application
immediately displays back to the victim. This is the primary form
of phishing via e-mail (such as eBay scams, bank scams, etc)
– Persistent: The attacker stores malicious content within a
database, which is then exposed to victims at a later time. This
is the most common form of XSS attack against forum and web
mail software.
– DOM: The attacker uses the victim site’s JavaScript code to
perform reflected XSS. This technique is not widely used as yet,
but it is just as devastating as any form of cross-site scripting.
24. P2: Cross-Site Scripting (XSS) (cont’d)
• Version Affected: All
• CVE/CAN Entries: More than 100 XSS entries since July
2004.
– WordPress ≤ 4.5.2 Unspecified Cross Site Scripting Vulnerability
(CVE-2016-6634) http://www.securityfocus.com/bid/92390
– Joomla! 3.4.x < 3.4.4 allows remote attackers to inject arbitrary
web script or HTML (CVE-2015-6939)
http://www.securitytracker.com/id/1033541
– VBulletin Cross-site scripting
http://www.securityfocus.com/bid/14874
– Coppermine Display Image Cross-site scripting
http://www.securityfocus.com/bid/14625
– WordPress Edit Cross-site Scripting
http://www.securityfocus.com/bid/13664
25. How to Determine If You Are Vulnerable
• Does the application rely upon register_globals to
work? If so, your application is at a slightly higher
risk, particularly if you do not validate input correctly.
• Inspect user input handling code for unsafe inputs:
• If you use Javascript to redirect the user (via
document.location or window.open any similar
means), output to the user via document.write, or
modifies the DOM in any way, you are likely to be at
risk of DOM injection.
echo $_POST[‘input’];
26. How to Protect Against Cross-site
Scripting
• Turn off register_globals and ensure all variables are properly
initialized
• Obtain user input directly from the correct location ($_POST,
$_GET, etc) rather than relying on register_globals or the request
object ($_REQUEST)
• Validate input properly for type, length, and syntax
• Free text input can only be safely re-displayed to the user after
using HTML entities (htmlentities() function)
• Variables sent back to the user via URLs must be URL encoded
using urlencode()
• Validate JavaScript code against Klein’s DOM Injection paper
(http://crypto.stanford.edu/cs155/CSS.pdf) to ensure that they are
immune from DOM injection attacks
–
•
27. P3: SQL Injection
• A SQL injection attack consists of insertion or
"injection" of a SQL query via the input data from the
client to the application.
• SQL injection exploits can read sensitive data, modify,
execute administration operations and in some cases
issue commands to the operating system
• Most of PHP programmers use input parameters as
concatenated strings to SQL statements
$sql = "SELECT * FROM users WHERE username = '" .
$username . "';";
What if $username is '; DROP TABLE users; --
28. P3: SQL Injection (cont’d)
• Version Affected: All
• CVE/CAN Entries: More than 100 CVE / CAN entries from
multiple vendor, for example:
– vBulletin 3.6.x – 4.2.3 allows remote attackers to execute arbitrary
SQL commands via the postids parameter to
forumrunner/request.php (CVE-2016-6195)
https://enumerated.wordpress.com/2016/07/11/1/
– Wordpress < 4.2.4 SQL injection vulnerability (CVE-2015-2213)
https://core.trac.wordpress.org/changeset/33556
– Joomla! 3.x < 3.4.7 allows attackers to execute arbitrary SQL
commands (CVE-2015-8769)
http://www.securityfocus.com/bid/79679
• Bugtraq usually offers up two to three different PHP
applications with SQL injection vulnerabilities per day
29. vBulletin SQL injection CVE-2016-6195
The root of the vulnerability, /forumrunner/includes/moderation.php:
function do_get_spam_data() {
...
$vbulletin->input->clean_array_gpc('r', array(
'threadid' => TYPE_STRING,
'postids' => TYPE_STRING,
));
…
} else if ($vbulletin->GPC['postids'] != ") {
$postids = $vbulletin->GPC['postids'];
$posts = $db->query_read_slave("SELECT post.postid,
post.threadid, post.visible, post.title, post.userid,
thread.forumid, thread.title AS thread_title, thread.postuserid,
thread.visible AS thread_visible, thread.firstpostid FROM " .
TABLE_PREFIX . "post AS post LEFT JOIN " . TABLE_PREFIX .
"thread AS thread USING (threadid) WHERE postid IN ($postids)");
31. How to Determine If You Are Vulnerable
• Find code which calls mysql_query() or similar database
interfaces
• Inspect if any calls create dynamic queries using user input
$query = "SELECT id, name, inserted, size FROM products
WHERE size = '$size'";
$result = odbc_exec($conn, $query);
' union select '1', concat(uname||'-'||passwd) as name,
'1971-01-01', '0' from usertable;
What if $size is
32. How to Protect Against SQL Injection
• Migrate code to PHP 5.1 and use PDO, or if this is not possible, at
least migrate code to safer constructs, such as PEAR::DB’s
parameterized statements or the MySQLi interfaces
• Validate data for correct type, length, and syntax.
• Do not use dynamic table names - escape functions are not designed
for this use and are not safe for this use.
• Use white listing (positive validation) data over black listing, which is
akin to virus patterns – always out of date, and always insufficient
against advanced attacks
• As a last resort, code should be using mysql_real_escape_string()
(but not addslashes() which is insufficient). This provides limited
protection to simple SQL injections.
• Provide a .htaccess file to ensure that register_globals and
magic_quotes are forced off, and that all variables are properly
initialized and validated
33. P4: PHP Configuration
• PHP Configuration has a direct bearing on the severity of
attacks.
• No agreed "secure" PHP configuration
• Arguments for and against the most common security options:
– register_globals (off by default in PHP ≥ 4.2, should be off, REMOVED
as of PHP 5.4.0)
– allow_url_fopen (enabled by default, should be off, available since PHP
4.0.4)
– magic_quotes_gpc (on by default in modern PHP, should be off,
REMOVED as of PHP 5.4.0)
– magic_quotes_runtime (off by default in modern PHP, should be of,
REMOVED as of PHP 5.4.0)
– safe_mode and open_basedir (disabled by default, should be enabled
and correctly configured. Be aware that safe_mode really isn't safe and
can be worse than useless)
34. P5: File System Attacks
• PHP developers have many ways to obviate security on shared hosts
with local file system attacks, particularly in shared environments:
– Local file inclusion (such as /etc/passwd, configuration files, or logs)
– Local session tampering (which is usually in /tmp)
– Local file upload injection (usually part of image attachment handling)
• As most hosters run PHP as “nobody” under Apache, local file
system vulnerabilities affect all users within a single host.
• Version Affected: PHP 3, 4, 5
• CVE/CAN Entries: As there have been many examples over years,
for examples:
– phpMyAdmin Local file exposure, able to exploit the LOAD LOCAL INFILE
functionality to expose files on the server to the database system. (CVE-
2016-6612) https://www.phpmyadmin.net/security/PMASA-2016-35/
– phpMyAdmin Local File Inclusion (CVE-2011-2643)
https://www.phpmyadmin.net/security/PMASA-2011-10/