PHP Hurts Programmers (and other tales)

PHP Hurts Programmers (and other tales)

Find out some of the sneaky ways the web’s favourite language-to-hate can give unsuspecting users just enough rope to hang themselves with. Take a slightly deeper dive into a few real-world bugs, and see how to (hopefully) avoid them in your own code.

Links from the end:

PHP The Right Way - http://www.phptherightway.com/
PHP: A fractal of bad design

https://eev.ee/blog/2012/04/09/php-a-fractal-of-bad-design/
WordPress vulnerability discussed:
https://blog.sucuri.net/2017/02/content-injection-vulnerability-wordpress-rest-api.html
Simple Machine Forums vulnerability discussed:
https://www.alertlogic.com/blog/writing-exploits-for-exotic-bug-classes-php-type-juggling/
ExpressionEngine vulnerability
https://foxglovesecurity.com/2017/02/07/type-juggling-and-php-object-injection-and-sqli-oh-my/
OWASP Resources
Both of these are “work in progress” / drafts
https://www.owasp.org/index.php/PHP_Security_Cheat_Sheet
https://www.owasp.org/index.php/PHP_Configuration_Cheat_Sheet
https://www.owasp.org/index.php/PHP_Object_Injection
PHP Configuration Checker (php.ini)
https://github.com/sektioneins/pcc
All about shell escaping & php
https://gist.github.com/Zenexer/40d02da5e07f151adeaeeaa11af9ab36
List of static analysis tools for PHP
https://github.com/exakat/php-static-analysis-tools
Gary Bernhardt’s “WAT” talk
https://www.destroyallsoftware.com/talks/wat

3f43ed53e6d1edfd2a7fd9a9b6f96313?s=128

Keith Humm

March 29, 2017
Tweet

Transcript

  1. PHP Hurts Programmers And other tales

  2. $ whoami Keith Humm Button Actuator
 Solvam Corporation Ltd 


    @spronkey
  3. “you pull out the hammer, but to your dismay, it

    has the claw part on both sides”
  4. • The language itself • Dangerous stdlib & extensions •

    PHP deployment & php.ini
  5. • The language itself • Dangerous stdlib & extensions •

    PHP deployment & php.ini
  6. Type Juggling “a variable's type is determined by the context

    in which the variable is used”
  7. Type Juggling when PHP screws with your variables


  8. > $x = “2 plus 3”; string(8)“2 plus 3” >

    $x += 1; int(3) > $x *= 0.333; double(0.999) > $x = $x && true; bool(true)
  9. > “foo” == TRUE true > “foo” == 0 true

    > TRUE == 0 false > “55” == “055” true > 55 != 055 true *https://www.destroyallsoftware.com/talks/wat WAT.
  10. C. A. R. Hoare Invented quicksort … and the null

    pointer “The most important property of a program is whether it accomplishes the intention of its user.”
  11. Real World Example #1 Type Juggling → WordPress Rest API

    content injection https://blog.sucuri.net/2017/02/content-injection- vulnerability-wordpress-rest-api.html
  12. • Posts have an integer id property that’s populated by

    URL router • WordPress sometimes prioritises HTTP GET and POST vars instead • WordPress inconsistent in usage of router id vs request id /wp-json/wp/v2/posts/123 /wp-json/wp/v2/posts/123?id=456haxxed
  13. > update_item_permissions_check() {
 $post = get_post( $request_id );
 
 if($post

    && <no auth>) {
 return WP_Error 
 }
 
 return true;
 } • Our request_id, 456haxxed is nonsense • So no $post is found • Skip right through to return true;
  14. > update_item() {
 $id = (int) $request_id;
 $post = get_post(

    $id );
 if($post) do_update_stuff();
 }
  15. None
  16. > update_item() {
 $id = (int) $request_id;
 $post = get_post(

    $id );
 if($post) do_update_stuff();
 } /wp-json/wp/v2/posts/123?id=456haxxed hax0red j00r bl0g
  17. Rule #1 Rules are hard to remember

  18. How to protect yourself

  19. ✓ Avoid type juggling wherever possible
 Use strict comparison operators

    e.g. === ✓ Use the right tools for the job
 i.e. hash_equals for timing-safe string comparison ✓ … don’t forget to use them for things like CSRF tokens ✓ Consider promoting primitives to objects
 i.e. function verify(ResetToken $t) : boolean ✓ Consider phpdoc annotations & static analysis
 /** @returns boolean **/
 https://github.com/exakat/php-static-analysis-tools ✓ Read www.phptherightway.com
  20. • The language itself • Dangerous stdlib & extensions •

    PHP deployment & php.ini
  21. > array_filter($input, $callback)
 array_map($callback, $input)
 mostly just annoying ✓ Use

    the newer OO APIs where available ✓ Consider third party libs e.g. underscore-php for fnprog
  22. > strip_tags() > strip_tags($str, $allowable_tags)
 welcome to the land of

    XSS ✓ Use HTMLPurifier or OWASP AntiSammy ✓ Check that your template engine does too
  23. > addslashes()
 when all you have is a hammer, 


    everything looks like a nail. ✓ Use an escaping technique fit for purpose - whether you are escaping for the shell, or SQL
  24. > (pre 7.0) mysql_escape_string()
 totally insecure. deprecated in 2002 (!)


    still works in PHP 5.6 (!?!) > (mysql/mysqli)_real_escape_string()
 be very careful—don’t trust this with your life ✓ Use PDO, and PDO::quote ✓ Use prepared statements / parameterised queries ✓ Try not to build SQL with _printf()
  25. > escapeshellarg()
 Sometimes OK in controlled env
 But it’s impossible

    to use safely in all envs > escapeshellcmd()
 Completely insecure
 Actually undermines previous sanitisation ✓ Never use escapeshellcmd ✓ Avoid functions that use it internally - mail(), system() etc. ✓ Avoid shelling out if you can ✓ Use pcntl extension with pcntl_fork and pcntl_exec
  26. > unserialize()
 Not for user input, ever
 Potentially lets users

    control code execution ✓ Never unserialise() user input ✓ Use an interchange format instead ✓ JSON, Protobufs, Msgpack, Thrift are all good choices
  27. > include() / require()
 A bit of a relic. There’s

    a better way™ ✓ Use PHP’s autoloader ✓ Use PSR-1 or PSR-4 and Composer
  28. > mcrypt
 Most popular* crypto extension. Unmaintained since 2007. ✓

    Use libsodium (+Halite), or OpenSSL instead ✓ Use random_bytes or ircmaxell\RandomLib for csprng ✓ Don’t roll your own crypto!
  29. Real World Example #2 Type Juggling → Bypass authentication in

    “Simple Machine Forums” https://www.alertlogic.com/blog/writing-exploits-for- exotic-bug-classes-php-type-juggling/
  30. • Code verifying a password recovery token • Tokens generated

    randomly and emailed to user • User input hashed, then first 10 chars are compared if ( 
 substr(md5($input), 0, 10)
 == 
 substr($storedHash, 0, 10)
 )
  31. > substr($storedHash,0,10) string “0e12345678” > $input = “190539”; > substr(md5($input),0,10)

    string “0e25261622” > (“0e12345678” == “0e25261622”) → bool(?)
  32. > substr($storedHash,0,10) string “0e12345678” > $input = “190539”; > substr(md5($input),0,10)

    string “0e25261622” > (“0e12345678” == “0e25261622”) → bool(true) gained admin access
  33. • Hashes can look like scientific notation “0e12345678” • ==

    operator may coerce either/both sides to ints • …if they “look like numbers” if ( 
 substr(md5($input), 0, 10)
 == 
 substr($storedHash, 0, 10)
 )
  34. None
  35. Real World Example #3 Type Juggling → Object Injection →

    SQLi
 in Expression Engine https://foxglovesecurity.com/2017/02/07/type-juggling- and-php-object-injection-and-sqli-oh-my/
  36. • Cookie $payload storing serialised PHP objects • Cookie signed

    with $signature, supplied in cookie itself • Valid signature in theory shows cookie untampered • sess_crypt_key is private • But $payload is entirely user controlled if ( md5( $payload . $this->sess_crypt_key ) == $signature )
  37. • unserialize() sets username to an actual instance of EE’s

    Token\Variable class, instead of a plain string • System passes username from the new object to EE’s SQL engine where() a:1:{s:13:”:new:username”;O:67:"EllisLab\\\ \\ExpressionEngine\\\\\Library\\\\\Parser\\ \\\Conditional\\\\\Token\\\\Variable":1:{s: 6:"lexeme";s:1:"'; DROP TABLE `users`;”;}}
  38. • EE’s SQL escape routine allows __toString() of this object

    to be included in query verbatim • Instance’s state can be crafted as needed by adjusting serialised data a:1:{s:13:”:new:username”;O:67:"EllisLab\\\ \\ExpressionEngine\\\\\Library\\\\\Parser\\ \\\Conditional\\\\\Token\\\\Variable":1:{s: 6:"lexeme";s:1:"'; DROP TABLE `users`;”;}}
  39. Don’t roll your own cryptography

  40. • The language itself • Dangerous stdlib & extensions •

    PHP deployment & php.ini
  41. > @fopen(‘http://non-existant.file', ‘r’); • allow_url_fopen controls whether this works at

    all • … unless it’s in disable_functions • @ operator suppresses the does-not-exist warning • … unless scream.enabled is set in php.ini • … or it was set with ini_set() • error_reporting setting can also alter this
  42. • display_errors
 Whether errors are output to the browser •

    allow_url_include
 Whether you can include() code from a remote URL • allow_url_fopen
 Whether fopen() can load remote files (use cURL!) • session.use_cookies
 Whether sessions use cookies or URL parameters • zend.multibyte
 Allows encodings like SJIS/BIG5 to be used for source files
  43. ✓ You must control your environment ✓ …or trust whoever

    does ✓ Make environment config part of your deployment ✓ Consider Suhosin if running third party apps ✓ Be careful with Apache mod_php
 What if a user uploads dodgy_script.php7 ? ✓ Use php.ini security analysis tools
 e.g. https://github.com/sektioneins/pcc 

  44. –Porky Pig “That’s all folks!”

  45. Link-fu • PHP The Right Way - http://www.phptherightway.com/ • PHP:

    A fractal of bad design
 https://eev.ee/blog/2012/04/09/php-a-fractal-of-bad-design/ • WordPress vulnerability discussed:
 https://blog.sucuri.net/2017/02/content-injection-vulnerability-wordpress-rest-api.html • Simple Machine Forums vulnerability discussed:
 https://www.alertlogic.com/blog/writing-exploits-for-exotic-bug-classes-php-type-juggling/ • ExpressionEngine vulnerability
 https://foxglovesecurity.com/2017/02/07/type-juggling-and-php-object-injection-and-sqli-oh-my/ • OWASP Resources
 Both of these are “work in progress” / drafts
 https://www.owasp.org/index.php/PHP_Security_Cheat_Sheet 
 https://www.owasp.org/index.php/PHP_Configuration_Cheat_Sheet 
 https://www.owasp.org/index.php/PHP_Object_Injection • PHP Configuration Checker (php.ini)
 https://github.com/sektioneins/pcc • All about shell escaping & php
 https://gist.github.com/Zenexer/40d02da5e07f151adeaeeaa11af9ab36 • List of static analysis tools for PHP
 https://github.com/exakat/php-static-analysis-tools • Gary Bernhardt’s “WAT” talk
 https://www.destroyallsoftware.com/talks/wat