OSWE (WEB-300: Advanced Web Attacks and Exploitation) 考試紀錄 (2023/11)
學習過程
- 基本上OWASP TOP 10 裡面的都有涵蓋到
- 可以學會幾項程式語言DEBUG的SOURCE CODE的方法,像是 JAVA、csharp、node js 等平台
- PT實務上好像比較少有機會 CODE REVIEW
- 課程整體而言算是蠻有趣的,第6、11、12、13章節在工作上有遇到類似的案例所以特別有興趣
- 想想這種考題對 CTF 是打 WEB 的非常友善,還提供 SOURCE CODE
- 基本上學習完這些遠遠還不夠,只能說算是一個起點,WEB的世界變化的太快,只能不斷的去適應新的框架和打法
- 考題算是難度適中,但課程裡面我覺得最難的應該還是和 JavaScript Prototype 相關的
- 工作關係 LAB 時間不足,所以只好再延後一個月 Q_Q
- 考試時間盡量選和自己作息接近的時間,比較不會太累
OSWE 考試紀錄
- 選了早上8點考試,提前15分鐘 (共計 47小時 45分), 用 OSID 跟一組 MD5 hash 值登入監考系統
- 監考是用瀏覽器桌面分享功能,每個螢幕都要
- 半個小時在身份驗證,環境檢查
- 因為我是用 Windows 所以他會要檢查你的process,會跑一組 powershell 並回傳結果
- 上面的驗證都通過後,就會收到官方寄來的郵件,會有考試 vpn 及 vpn 密碼
- 中間休息和考官說要休息,回來的時候也和考官說,基本上和其他Offsec 考試相同
- 第一天 第一題 上午 取得 AuthBypass,晚上取得 RCE 休息8小時睡覺
- 第二天 第二題 上午 取得 AuthBypass,下午取得 RCE,晚上開始寫報告,晚上12點提前結束考試-睡覺
- 第三天 整理報告,中午報告交出
考試環境
- 考試共有五台機器
- Kali 可用來編寫 PoC,但我沒有用,比較習慣在自己機器上做
- 兩台 debugger 提供帳密
- 兩台和 debugger 一樣的機器並提供 source code 模擬
考試回憶
- 要把考試情境描述看完,可以讓你 Code Review 比較有目標,也比較省時
- 課程中的 LAB 算是部分和考題重疊,LAB 一定要做完
- 需要熟練使用binary search 及 多執行續,幫助你在遇到SQL injection 時可以減少執行時間,在VPN 的狀態下差很多。
- 考試前最好要準備你要一鍵SHELL 的框架和function,可以減省不少時間
- 一個好的考試範本筆記也很重要,這次是使用 https://github.com/ret2src/OSCP-Exam-Report-Template-Markdown#docker 有一些東西需要調整 如果你有遇到無法正常產出報告就需要額外在 DOCKER 安裝 xetex 並指定 xetex ,指令
sudo apt install texlive-xetex
- burp 一定要安裝 Copy As Python-Requests,不用在自己手刻 request
- 熟練 python requests ,session 盡量重複使用、requests.post 的 file 、data 會用到
需要特別注意的-考試禁止事項
報告部分截圖
- 基本上寫好的 markdown OSCP-Exam-Report-Template-Markdown#docker 都會自動把格式調整好輸出成PDF
- 封面
Image Not Showing
Possible Reasons
- The image was uploaded to a note which you don't have access to
- The note which the image was originally uploaded to has been deleted
Learn More →
- 大鋼
Image Not Showing
Possible Reasons
- The image was uploaded to a note which you don't have access to
- The note which the image was originally uploaded to has been deleted
Learn More →
- 內容
Image Not Showing
Possible Reasons
- The image was uploaded to a note which you don't have access to
- The note which the image was originally uploaded to has been deleted
Learn More →
考試時使用的一鍵SHELL python 骨架
import os
import argparse
import threading
from http.server import BaseHTTPRequestHandler,HTTPServer
class message ():
def __init__ (self):
self.red = '\033[91m'
self.green = '\033[92m'
self.white = '\033[37m'
self.yellow = '\033[93m'
self.bold = '\033[1m'
self.end = '\033[0m'
def info (self, message):
print(f"[{self.white}*{self.end}] {message}")
def warning (self, message):
print(f"[{self.yellow}!{self.end}] {message}")
def error (self, message):
print(f"[{self.red}x{self.end}] {message}")
def success (self, message):
print(f"[{self.green}✓{self.end}] {self.bold}{message}{self.end}")
def run_nc(port):
output.info("run nc shell")
os.system("/usr/bin/nc -lvvp {}".format(port))
def start_web_server(host,port):
class webHandler(BaseHTTPRequestHandler):
def do_GET(self):
if self.path == '/test.js':
try:
with open('test.js', 'rb') as file:
content = file.read()
self.send_response(200)
self.send_header('Content-type', 'application/javascript; charset=utf-8')
self.end_headers()
self.wfile.write(content)
output.success("XSS Trigger")
except FileNotFoundError:
self.send_error(404, 'File not found')
elif self.path == '/test.txt':
try:
with open('test.txt', 'rb') as file:
content = file.read()
self.send_response(200)
self.send_header('Content-type', 'text/plain')
self.end_headers()
self.wfile.write(content)
except FileNotFoundError:
self.send_error(404, 'File not found')
elif self.path.startswith('/test?name='):
try:
global admin_key
admin_key = self.path.split("=")[1]
if admin_key:
output.success("Get admin Key:" + admin_key)
except Exception as e:
output.error("Error while fetching admin key: " + str(e))
else:
self.send_error(404, 'File not found')
httpd = HTTPServer((host, int(port)), webHandler)
threading.Thread(target=httpd.serve_forever).start()
def writefile(attackerip,httpport):
files = f"""""".format(attackerip,httpport)
with open("files","w+") as f:
f.write(files)
def main():
global output
output = message()
parser = argparse.ArgumentParser()
parser.add_argument('-t', '--target', help='Target ip address or hostname', required=True)
parser.add_argument('-aip', '--attackerip', help='Listening IP address for reverse shell', required=True)
parser.add_argument('-hport', '--httpport', help='Listening port for http', required=True)
parser.add_argument('-aport', '--attackerport', help='Listening port for reverse shell', required=True)
parser.add_argument('-d', '--debug', help='Instruct our web requests to use our defined proxy', action='store_true', required=False)
args = parser.parse_args()
global anserip
anserip = args.target
global proxy_list
proxy_list = None
if args.debug:
for k,v in sorted(vars(args).items()):
if k == 'debug':
proxy_list = {'http': 'http://127.0.0.1:8080', 'https': 'http://127.0.0.1:8080'}
output.warning(f"Debugging Mode: {v}")
else:
output.info(f"{k}: {v}")
if __name__ == '__main__':
main()
過惹
Image Not Showing
Possible Reasons
- The image file may be corrupted
- The server hosting the image is unavailable
- The image path is incorrect
- The image format is not supported
Learn More →
參考連結