PHP security audits

6,866 views
6,744 views

Published on

How to run a security audit on PHP code.

Published in: Technology

PHP security audits

  1. 1. PHP security audits Assess your code for security<script>alert(‘XSS’..
  2. 2. Agenda How to run an audit Scouting the PHP code Organizing for security
  3. 3. Speaker Damien Seguy Raise elePHPants damien.seguy@alterway.fr
  4. 4. Yes, we take questions
  5. 5. PHP code audits Interview with the developpers : 1 day Black Box testing : 1 day Open Code audit : 2 days Report and review : 1 day
  6. 6. The application http://www.cligraphcrm.com/
  7. 7. Interviewing developpers Review what the application does Explain the code organization Explain the security features
  8. 8. Review the application Best : have a non-programmer explain the application Then have the programmer explain again The differences are interesting
  9. 9. Killer question What is the most important asset to secure on the site? «everything» is not an answer data destruction data exportation client separation company image
  10. 10. How was the app secured? Where are the security functions? How are they applied? How do you check how they are applied ?
  11. 11. I like to hear... Out of web folder Automated deployement Automated tests AND manuals tests Security as a layer (functions and application)
  12. 12. Black Box testing Test from the outside Search the engines Session usurpation Disclosed files Displayed errors Tools : Rats, nikto, Wapiti
  13. 13. Open Code audits What to search for? What are the entry points? How can they be exploited Or protected ?
  14. 14. What to search for? Injections PHP SQL HTML system HTTP
  15. 15. Keep focused Easy to loose focus Tempting to audit everything
  16. 16. PHP injections PHP injections include, require and *_once back ticks ` ` eval(‘’) Using variables
  17. 17. Looking for eval Easy to look for grep Fast, available, convenient 853 occurences Tokenizer Semantic, accurate 37 occurrences
  18. 18. Tokenizer <?php print ("hello $world! "); ?> [1] => Array ( [6] => Array [0] => 266 ( [1] => print [0] => 309 [2] => 1 [1] => $world ) [2] => 1 ) [2] => Array ( [7] => Array [0] => 370 ( [1] => [0] => 314 [2] => 1 [1] => ! ) [2] => 1 ) [3] => ( [4] => " [8] => " [5] => Array [9] => ) ( [10] => ; [0] => 314 [1] => Array [1] => hello ( [2] => 1 [0] => PHP token ) [1] => PHP code [2] => Script line ) [2] => "
  19. 19. Evals ◦ eval('$retour=$GLOBALS["'.$matches[1].'"];') ◦ Variable variables. ◦ eval($contenu_thjipk); ◦ eval($contents_essai); ◦ Content is read into variable, then executed : an include? ◦ eval('$hexdtime = "'.$hexdtime.'";') ◦ Long way to cast a string into a string ◦ eval('$retour2.= '.var_dump($recept->erreur).';') ◦ This doesn’t even make sense...
  20. 20. Assessing the code One liners One line of code is sufficiently to be bad Even though you must follow the code In reverse
  21. 21. Inclusion ◦ require("../params_frm.php") ◦ require(fct_lien_page_custom(TYPE_DOMAINE."/".TYPE_DOC. "_custom.php","abs")) ◦ require(fct_lien_page_custom("params_footer.php","abs")) ◦ Pretty secure inclusions ◦ But 96 variables used in includes ◦ include(fct_lien_page_custom("action/facture_". $format.".php","abs")) ◦ $format, anyone? ◦ require_once("etat_simple_".$choix_page."_trt.php") ◦ $choix_page, anyone ?
  22. 22. $format ? <?php require("../params_trt.php"); $format=htmlentities($_REQUEST['exp_formdoc']); if(empty($_REQUEST['exp_affiche'])) $affichage=0;  else $affichage=$_REQUEST['exp_affiche']; if(empty($_REQUEST['exp_stockdoc'])) $stockage=0;  else $stockage=$_REQUEST['exp_stockdoc']; $cde_id=$_REQUEST['exp_id']; $type_doc=$_REQUEST['exp_typedoc']; require(fct_lien_page_custom("fonctions/fonction_img.php","abs")); include(fct_lien_page_custom("action/facture_". $format.".php","abs")); ?>
  23. 23. $choix_format ?   switch($choix) {     case 0 : $choix_page="tabl";     break;     case 1 : $choix_page="histo1";  if ($gfx_sens_graph=="1") $gfx_margegauche_dft="90";     break;     case 2 : $choix_page="histo2";  if ($gfx_sens_graph=="1") $gfx_margegauche_dft="90";     break;     case 3 : $choix_page="histo3";  if ($gfx_sens_graph=="1") $gfx_margegauche_dft="90";     break;     case 4 : $choix_page="histo4";  if ($gfx_sens_graph=="1") $gfx_margegauche_dft="90";     break; } ###...Way below     require_once("etat_simple_".$choix_page."_trt.php");
  24. 24. Statistical audit Extract one type of information Review it out of context Use this as a starting point for more questions
  25. 25. Comments //echo "<div><a class="texte1" style=... #echo "<pre>"; Left overs : what were they for? #print_r($_REQUEST); No organization for bugs? // hack for mozilla sunbird's extra = signs Look for swearing, TODO, hack
  26. 26. Variables 6883 different variables names All one possible one letter variable 32 chars : $cache_maxsize_UTF8StringToArray Most used : $i (2586 times) $_1904, $samedi, $dummy, $sss, 19 $unknowns 711 variables used only once in the code
  27. 27. Other interesting ideas name of functions name of classes name of constants literal strings, numbers Condition (if, while)
  28. 28. register_globals strikes back
  29. 29. register_globals strikes back Don’t use register globals!!
  30. 30. register_globals strikes back Don’t use register globals!! How can you emulate this behavior?
  31. 31. register_globals strikes back
  32. 32. register_globals strikes back foreach and $$
  33. 33. register_globals strikes back foreach and $$ extract
  34. 34. register_globals strikes back foreach and $$ extract import_request_var
  35. 35. register_globals strikes back foreach and $$ extract import_request_var $GLOBALS
  36. 36. register_globals strikes back foreach and $$ extract import_request_var $GLOBALS parse_str
  37. 37. Found! ◦ ./install/identification.php ◦ extract($_POST)  : 1 ◦ Injection by $_POST ◦ ./fonctions/fonctions_gen.php ◦ $GLOBALS[$k] = $chaine[$k] ◦ $GLOBALS[$this->mode] [$k] = $chaine[$k] ◦ In the fct_urldecode, the values are stripslashed, and then injected in the $GLOBALS, resulting in variable creation
  38. 38. SQL injections Point of entry mysql_query mysqli_real_escape_string SQL query : string with SELECT, UPDATE, ...
  39. 39. Found! ◦ 'UPDATE param_suivi SET      param_suivi_nom="'.str_replace($tr ansf_sp,$transf_fr,$_POST["suivi_nom"])  : 1 ◦ Direct injection via POST ◦ WHERE campagne_nom LIKE '%".addslashes($_REQUEST['rech_nom'])  ◦ Injection from $_REQUEST ◦ "UPDATE even_spl SET even_spl_fait='". $even_fait."',even_spl_modification='".$date_du_jour."'     WHERE even_spl_id='".$even_id."' AND even_spl_affaire_id='". $even_aff_id."'";  : 1 ◦ "INSERT INTO ".$type_doc."_suivi    (". $type_doc."_suivi_param_suivi_id, ".$type_doc."_suivi_". $type_doc."_id, ".$type_doc."_suivi_canal_id,    ". $type_doc."_suivi_action, ".$type_doc."_suivi_commentaire, ". $type_doc."_suivi_creation)    VALUES ('".$id_suivi."', '". $id_doc."', '".$id_canal."', '". $suivi_date."', '".addslashes($suivi_commentaire)
  40. 40. And also Header injection Look for header() XSS look for echo, print look for strings with tags Etc...
  41. 41. Report Executive summary 3 paragraphs, simple to read Problems summary Table, with problems, criticality and load Details Extras
  42. 42. Report Vulnerability Critical Load register_globals High High Injections High Medium SQL injection Medium High headers Low Low
  43. 43. Details Title In code example and explanation Protection suggestions Limitations List of all occurrences Or way to find them
  44. 44. Team Work Security is recommanded at conception time Audit is an after-thought tool Once When necessary Regularly Continuously
  45. 45. PHP Mantra List your mantra The five most important rules you agree upon Have them printed and visible to everyone
  46. 46. Cross audit Group developers by two Have each one review the code of the other Based on the mantra Light weight process Doesn’t have to be in the same project
  47. 47. PHP audit tools Groogle (http://groogle.sourceforge.net) Review Board (http://www.review-board.org/) Rietveld http://codereview.appspot.com/ SmartBear (http://www.smartbear.com/)
  48. 48. Community step up Mantra, cross audits go beyond services and departements Open this outside ? External review? New way of coding ?
  49. 49. Questions? damien.seguy@alterw ay.fr

×