天天看点

DVWA-1.9 SQL注入(SQL Injection)1、low级别2、medium级别3、high级别4、impossible级别

目录

1、low级别

step1 判断注入点和注入类型

step2 判断字段数

step3 获取数据库信息

2、medium级别

3、high级别

4、impossible级别

之前使用的是旧的版本,这次去官网换成了1.9版本。

SQL注入的步骤大概包括以下几个步骤:1、判断网站能不能注入;2、判断注入的字段数;3、获取数据库。

1、low级别

low级别的代码如下:

<?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();
}

?> 
           

low级别下使用的是$_REQUEST方式对信息进行提交,和其他级别的主要区别也在这里,medium级别下使用的是$_POST,high级别下使用的是$_SESSION。

step1 判断注入点和注入类型

可以参考https://blog.csdn.net/god_xiangyu/article/details/95389549对网站的是否存在注入点进行判断以及注入的类型。

首先输入 '  等特殊符号,如1'  ,如果报错就说明可能存在注入点,下图是输入 ' 后显示的结果。也可以使用一些工具对注入点进行判断,比如sqlmap。

DVWA-1.9 SQL注入(SQL Injection)1、low级别2、medium级别3、high级别4、impossible级别

如果存在注入点,再去判断此注入点是字符型还是数字型。

字符型即 user_id = '$id' ,如果是字符型,则1 and ‘1’=’1 不报错,1 and ‘1’=’1'会报错('没有闭合)。

数字型即 user_id = $id  ,如果是数字型,则1 and ‘1’=’1 会报错,1 and ‘1’=’1'不报错。

low级别下符合字符型的注入。

step2 判断字段数

因为不能修改本来的代码,所以查找的字段数要与本来的字段数保持一致。

使用1' union select 1 -- ,会报列数不对的错误,如下图所示。然后逐次增加后面的列数,在输入1' union select 1,2 -- 时不会报错,所以low级别的字段为2.

DVWA-1.9 SQL注入(SQL Injection)1、low级别2、medium级别3、high级别4、impossible级别

step3 获取数据库信息

每一个MySQL数据库中都有一个information_schema库来存储这个数据库的元信息,所以可以通过查询此数据库来获取想要的数据。获取用户的账号密码的过程如下。

第一步,在information_schema库的tables表中获得库名,使用

1' union select table_schema,1 from information_schema.tables # 。

DVWA-1.9 SQL注入(SQL Injection)1、low级别2、medium级别3、high级别4、impossible级别

第二步,其中有一个库是dvwa,猜测会存放相关信息,获取它所拥有的表,使用 ' union select 1,table_name from information_schema.tables where table_schema='dvwa' -- 。注意--后一定要带空格,否则会报错。

DVWA-1.9 SQL注入(SQL Injection)1、low级别2、medium级别3、high级别4、impossible级别

第三步,查看users表中的字段,使用 ' union select table_name,column_name from information_schema.columns where table_name='users' -- 

DVWA-1.9 SQL注入(SQL Injection)1、low级别2、medium级别3、high级别4、impossible级别

第四步,获取user字段和password字段的内容,使用 ' union select user,password from dvwa.users -- 

DVWA-1.9 SQL注入(SQL Injection)1、low级别2、medium级别3、high级别4、impossible级别

第五步,经过尝试,密码经过md5加密,使用md5进行解码就可以获得密码。

DVWA-1.9 SQL注入(SQL Injection)1、low级别2、medium级别3、high级别4、impossible级别

验证阶段,使用获得的账户密码可以登录login界面,说明注入成功。

2、medium级别

此级别的代码的主要区别如下。

// Get input
    $id = $_POST[ 'id' ];
    $id = mysql_real_escape_string( $id );
           

此级别下有这两行不一样,第一行使用的是$_POST方式,在提交内容时不会在网址栏中显示其他的内容;第二行用来转义 ' 等的字符,此时就不能使用字符型注入而要进行数字型注入。

因为此级别是一个下拉框,没有进行输入的地方,所以要使用burpsuite进行抓包。

DVWA-1.9 SQL注入(SQL Injection)1、low级别2、medium级别3、high级别4、impossible级别

对这里进行修改即可,类似下图所示。可以参考low级别的步骤。

DVWA-1.9 SQL注入(SQL Injection)1、low级别2、medium级别3、high级别4、impossible级别
DVWA-1.9 SQL注入(SQL Injection)1、low级别2、medium级别3、high级别4、impossible级别

3、high级别

此级别下代码与low级别就一点区别,就是数据提交的方式使用$_SESSION进行。

// Get input
    $id = $_SESSION[ 'id' ];
           

操作步骤与low级别完全相同。

4、impossible级别

代码的变化主要如下。

// Was a number entered?
    if(is_numeric( $id )) {
        // Check the database
        $data = $db->prepare( 'SELECT first_name, last_name FROM users WHERE user_id = (:id) LIMIT 1;' );
        $data->bindParam( ':id', $id, PDO::PARAM_INT );
        $data->execute();
        $row = $data->fetch();

        // Make sure only 1 result is returned
        if( $data->rowCount() == 1 ) {
            // Get values
            $first = $row[ 'first_name' ];
            $last  = $row[ 'last_name' ];

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

之前的级别都是在接收到id后直接或进行处理后进行SQL语句的查询,此级别下线进行判断是否是数字,在进行SQL查询时,使用$data->execute()函数保证输入的参数只有一个。

继续阅读