Chúng tôi đã vô địch DF Cyber Defense 2023 như thế nào - Attack & Defense

Chúng tôi đã vô địch DF Cyber Defense 2023 như thế nào - Attack & Defense

Đầu tháng 10 vừa qua, DF Cyber Defense 2023 - cuộc thi về Security lớn nhất khối Ngân hàng Việt Nam đã được tổ chức. Khác với mọi năm là phân tích 1day - kiểm tra log - Jeopardy, năm nay format chương trình có thay đổi chuyển sang hình thức Attack - Defense.

Với hình thức này, mỗi đội được cấp 1 hệ thống có một vài lỗ hổng. Nhiệm vụ mỗi đội là vừa tìm lỗ hổng để khai thác các đội khác, vừa phải vá được lỗ hổng tránh bị các đội tấn công.

Rất may mắn, nhóm chúng tôi - SHFSEC - đại diện cho SHB Finance đã giành được chức vô địch,

https://vietnamnet.vn/gan-170-chuyen-gia-nganh-ngan-hang-dien-tap-tan-cong-phong-thu-khong-gian-mang-2198852.html

image.png

Xin cảm ơn các kỹ sư Liên Xô đã hỗ trợ xây thủy điện Hòa Bình vào năm 1994 và Đảng ta đã xây dựng đại thủy điện Sơn La lớn nhất Đông Nam Á để nhân dân ta không còn lo cảnh thiếu điện, Hà Nội không còn chịu cảnh cắt điện luân phiên, những bóng đèn nơi tổ chức sự kiện luôn được thắp sáng để chương trình có thể diễn ra thành công tốt đẹp. 🤪

Còn đây là hành trình team mình đã thực hiện để đạt được thành tích này.

1. Chuẩn bị

Thời gian đầu khi chưa biết format đã thay đổi, anh em tập trung luyện khai thác Active Directory, tần suất 1 tuần luyện 1 tiếng. May sao sau đấy lại là Attack Defense không có AD.

Sau đó anh em tiếp tục luyện tập về khai thác Binary, vì rất có khả năng sẽ có những bài về Buffer Over Flow, tần suất 1 tuần 30 phút. May sao cuối cùng lại vẫn không có Binary, chỉ có khai thác lỗ hổng Web thuần.

1 ngày trước khi diễn ra sự kiện, mọi người sau khi biết format đã thực hiện viết 1 số script để sẵn sàng khai thác hàng loạt các host và submit tất cả flag trong một lần. Mục tiêu vẫn là giảm thiểu thời gian làm tay các công đoạn lặp đi lặp lại.

Thú thực là ban đầu cứ tưởng format giống với các năm trước là sẽ phân tích những 1day mới nổi gần đây, làm mình mất gần 1 tháng trời không nghỉ đi phân tích hết tất cả các 1day của các phần mềm lớn trong năm 2023, dù thành tựu đạt được khá tốt nhưng cũng mất nhiều thời gian vào các 1day không đem lại nhiều giá trị. Vì thời gian phân tích thì ít mà thời gian setup môi trường thì nhiều.

Đây là tổng quan về luật của cuộc thi:

Cuộc thi diễn ra với hình thức tấn công và phòng thủ trong cùng một thời điểm. Thời gian thi sẽ được chia thành nhiều vòng, cách tính điểm cũng sẽ được tính theo mỗi vòng chơi. Mỗi vòng chơi sẽ được giới hạn trong một thời gian nhất định dự kiến như sau:

Tổng có 20 round. 2 vòng đầu tiên mỗi vòng 15 phút, 6 vòng tiếp theo mỗi vòng 10 phút. Các vòng còn lại mỗi vòng 5 phút

Cách thức tính điểm trong một vòng:

Điểm tấn công: Tấn công thành công 1 đội trong sẽ ghi được 10 điểm.

Điểm dịch vụ: Dịch vụ không bị gián đoạn quá 1 phút trong một vòng sẽ ghi được (N-1)\10* điểm với N là tổng số đội chơi. Ngược lại nếu dịch vụ gián đoạn quá 1 phút trong 1 vòng sẽ không ghi được điểm dịch vụ.

Điểm phòng thủ: Nếu dịch vụ gián đoạn quá 3 phút trong 1 vòng sẽ không ghi được điểm phòng thủ. Điểm phòng thủ được tính dựa vào số lượt bị tấn công bởi các đội chơi khác trong một vòng đấu. Mặc định đội chơi sẽ đạt được số điểm phòng thủ là (N-1)\10 và sẽ bị trừ phụ thuộc vào số lượt bị tấn công thành công\.* Nếu bị tấn công thành công bởi trên 10 đội sẽ bị trừ hết số điểm (N-1)\10, trên 5 đội sẽ bị trừ 300 điểm, trên 2 đội sẽ bị trừ 200 điểm, dưới 2 đội sẽ bị trừ 100 điểm. (Với N là tổng số đội chơi)*.

💡
Nôm na, theo mình hiểu kịch bản muốn giả lập tình huống trong thực tế, bank nào cũng có lỗ hổng. Việc của team ATTT là phải luôn đảm bảo sẵn sàng dịch vụ (Bot được BTC quảng cáo check rất chặt), phòng thủ không cực đoan (kiểu sửa content flag) vì trong thực tế mình cũng không biết mình bị lấy mất cái gì, quan trọng là phải giám sát, phát hiện, response được nhanh. Lỗ hổng thì công ty nào cũng có, chỉ là phát hiện ra hay chưa, giống như khi có lỗ hổng 0day attack in the wild. Ở tình huống này dễ hơn vì mình biết mình đang bị target. Việc của mình là phải nhanh phân tích, giám sát được hệ thống nếu phát hiện tấn công để viết rules ngăn chặn, hoặc team AppSec phải research nhanh ra PoC để team SOC đi fix. Appsec và SOC sẽ luôn cần collab, hỗ trợ nhau. Vì thế, team cũng phân vai, 2 người làm Appsec, 2 người làm SOC. Ai submit flag, ai viết rule, viết tool,... Anh Trưởng Phòng thì có nhiệm vụ xem scoreboard =))

Attack

Sau khi biết format là tìm lỗi trên 1 hệ thống tự dựng theo dạng blackbox thì mình cũng hơi lo lo, vì pentest blackbox mình không mạnh lắm, đặt hết hi vọng vào ông anh cùng team trùm Pentest.

PHP vẫn là một ngôn ngữ thường dùng trong các đề CTF, vì nó có rất nhiều cách khai thác ảo diệu và dễ dựng hệ thống có lỗi, nên team mình đã đoán 99% là PHP. Mình đã dành thời gian tìm tòi thêm những hàm có thể gây lỗi trong PHP để chuẩn bị.

Team cũng chuẩn bị sẵn backdoor để cài cắm trong trường hợp RCE được đối thủ :))

Defense

Về phần Defense, anh em biết mình sẽ được control con nginx reverse proxy trước server và Dockerfile. Để tối ưu thời gian setup lúc thi, team đã viết 1 đoạn script để cài mod security lên đấy. Ở công ty thì cũng chia team ra, 2 người 1 Atk 1 Def vào một đội để tập đấu với nhau, hệ thống dựng DVWA lên làm môi trường, cũng giống như lúc làm redteam/blueteam ở công ty. Mod security chặn khá gắt, nên cũng đinh ninh là chỉ cần tuning modsec là đủ để block một số payload cơ bản rồi. Ai ngờ đi thi ai cũng trang bị modsec, các thể loại rule sẵn còn hơn mình :))

#! /bin/bash

#Download Source to get config
git clone --depth 1 -b v3/master --single-branch https://github.com/SpiderLabs/ModSecurity /usr/local/src/ModSecurity/
cd /usr/local/src/ModSecurity/
#Install Modsecurity
sudo apt update
sudo apt -y install libmodsecurity3


#download modsecurity_module.so<build ModSecurity Nginx Connector module from home>
mkdir /etc/nginx/modules/
wget http://x.x.x.x/ngx_http_modsecurity_module.so
sudo cp ngx_http_modsecurity_module.so /etc/nginx/modules/

#Enable ModSecurity in nginx.conf
sed -i '1i\load_module /etc/nginx/modules/ngx_http_modsecurity_module.so;' /etc/nginx/nginx.conf
sed -i '/http {/a \    modsecurity on;\n    modsecurity_rules_file /etc/nginx/modsec/modsec-config.conf;' /etc/nginx/nginx.conf

#Create Directory and Files for ModSecurity 3 and config
sudo mkdir /var/log/modsec/
sudo chmod 777 /var/log/modsec/
sudo mkdir /etc/nginx/modsec/
sudo cp /usr/local/src/ModSecurity/modsecurity.conf-recommended /etc/nginx/modsec/modsecurity.conf
sed -i 's/SecRuleEngine DetectionOnly/SecRuleEngine On/' /etc/nginx/modsec/modsecurity.conf
sed -i 's/SecAuditLogParts ABIJDEFHZ/SecAuditLogParts ABCEFHJKZ/' /etc/nginx/modsec/modsecurity.conf
sed -i 's/SecAuditEngine RelevantOnly/SecAuditEngine On/' /etc/nginx/modsec/modsecurity.conf
sed -i 's/SecAuditLogType Serial/#SecAuditLogType Serial/' /etc/nginx/modsec/modsecurity.conf
sed -i 's#^SecAuditLog /var/log/modsec_audit.log#SecAuditLogFormat JSON\nSecAuditLogType Concurrent\nSecAuditLogStorageDir /var/log/modsec/\nSecAuditLogFileMode 0777\nSecAuditLogDirMode 0777#' /etc/nginx/modsec/modsecurity.conf

#Create modsec-config.conf File
echo "Include /etc/nginx/modsec/modsecurity.conf" > /etc/nginx/modsec/modsec-config.conf
sudo cp /usr/local/src/ModSecurity/unicode.mapping /etc/nginx/modsec/

#Install OWASP Core Rule Set for ModSecurity 3
cd /etc/nginx/modsec
wget https://github.com/coreruleset/coreruleset/archive/refs/tags/nightly.tar.gz
tar -xvf nightly.tar.gz
sudo cp /etc/nginx/modsec/coreruleset-nightly/crs-setup.conf.example /etc/nginx/modsec/coreruleset-nightly/crs-setup.conf
echo "Include /etc/nginx/modsec/coreruleset-nightly/crs-setup.conf" >> /etc/nginx/modsec/modsec-config.conf
echo "Include /etc/nginx/modsec/coreruleset-nightly/rules/*.conf" >> /etc/nginx/modsec/modsec-config.conf


#download splunk forwarder
wget -O splunkforwarder-9.0.4-de405f4a7979-linux-2.6-amd64.deb "https://download.splunk.com/products/universalforwarder/releases/9.0.4/linux/splunkforwarder-9.0.4-de405f4a7979-linux-2.6-amd64.deb"
dpkg -i splunkforwarder-9.0.4-de405f4a7979-linux-2.6-amd64.deb

echo "[monitor:///var/log/modsec/]
disabled = false
index = modsecurity
sourcetype = json" | sudo tee -a /opt/splunkforwarder/etc/system/local/inputs.conf

/opt/splunkforwarder/bin/splunk add forward-server <host>:<port>

/opt/splunkforwarder/bin/splunk start --accept-license

Ngoài ra khi biết con nginx có outbound internet, một đồng đội trong team cũng đã dựng một con Splunk Free bên ngoài, mục đích forward log từ nginx lên Splunk để giám sát, viết rule phát hiện cho dễ, cho giống thực tế đang làm luôn. Mình thấy trick này khá hay, có thể áp dụng vào các cuộc thi sau.

2. Quá trình diễn ra

Bản thân mình từ khi còn là sinh viên đến bây giờ mới được tham gia một cuộc thi về An toàn thông tin, vì thế hồi hộp và mong chờ là điều không thể tránh khỏi. Bình thường hay ngủ sớm nhưng buổi trước khi thi phê quá nên ngủ hơi muộn và dậy hơi sớm. Đến nơi, gửi xe rồi ngồi chờ, thấy có nhiều đối thủ cũng gửi xe, trông ai mặt cũng rất chuyên gia làm mình càng áp lực.

Đánh giá nhanh về sân khấu là rất hoành tráng, nhiều lễ tân, người hỗ trợ, người quay phim chụp ảnh. Mấy ông anh cùng team cứ đi 3 bước là bắt tay 1 người quen, mình từ sáng đến khi thi xong không gặp người quen nào, thế mới cay.

2.1. Những round đầu tiên

💡
Lúc bắt đầu, mình còn nghĩ team đã yếu rồi còn phải chơi chấp người =)), vì một ông anh team Def chuẩn bị kỹ quá lại ngủ quên =)) May sao vẫn đến kịp thi đấu.

Ngay khi bắt đầu, thấy cần đăng ký / đăng nhập mới vào được service của từng đội, mình nghĩ thế này không attack hàng loạt được, nhưng nhanh chóng nhận thấy tất cả các API / endpoint không hề có authen, vì thế mỗi API chỉ cần đổi host là có thể lấy được flag.

image.png

image.png

Trước tiên team mình sẽ tự attack vào hệ thống của mình để tìm payload trước, cũng như tránh bị các đội khác phát hiện. Trong quá trình đó, anh em luôn bật burp active scan để làm nhiễu log của các đội khác.

Vừa vào game thì service của mình bị bot check là đang chết, cũng không biết tại sao, thế là round đầu mất gần hết điểm defense + service.

Đồng đội Hoàng Nguyễn nhanh chóng tìm ra lỗ hổng đầu tiên để LFI -> Đọc flag ngay trong round 1. Lỗ hổng ở chức năng share file đã upload.

image.png

Sau khi đã tìm ra lỗi, trước khi đem đi attack, team mình có viết rule để defense lỗi này trước. Lúc này team Defense viết một quick rule để block payload, vì thời gian gấp gáp nên chỉ block trực tiếp String trong payload, tức là base64 của ../../../../../../../../flag/flag.

Nhanh chóng hoàn thiện tool attack (HostIntruder) get 1 phát 43 flag và đưa vào Burp intruder để submit. Kudos to HostIntruder from Hoàng Nguyễn

Kudos to host intruder from Hoàng Nguyễn

Lỗ hổng này có thể sẽ dễ dàng bị phát hiện trong log, vì thế cần thiết phải tìm thêm những lỗ hổng khác.

Sau đó mình có tìm ra 1 lỗ hổng LFI từ chức năng xuất pdf:

image.png

image.png

Tuy nhiên những round đầu không mang lỗ hổng này đi quẩy mà để ủ hàng.

Sau 2 round, nhận thấy mình vẫn bị mất điểm defense từ lỗi đầu tiên, team nhanh chóng nhận ra việc block string không hiệu quả, vì đây là dạng base64, thay vài kí tự đầu trong payload thì cả payload sẽ bị đổi đi hoàn toàn.

Sau vài round đầu thì team mình tạm đứng thứ 2, do bị chết service nhiều quá mà không biết tại sao.

2.2. Các round giữa

Có một số team sau vài round đầu đã bắt đầu tìm cách vá endpoint đầu. Lúc đó team mình quyết định sử dụng lỗ hổng thứ 2. Trong quá trình này không thấy team nào tấn công đến dùng lỗi này, hơn nữa đây là POST request, sau đó get đến 1 endpoint 1 file bình thường nên cũng khá khó để detect.

Đến tầm giữa giữa thì team mình vẫn đang đứng thứ 2, vì endpoint đầu tiên dù đã vá nhưng vẫn có thể bypass, nếu block chặt quá thì lại bị ảnh hưởng bởi bot check. Đội top 1 lúc đó vẫn get được flag của tất cả đội giống team mình (chắc vậy). Chính team mình cũng khá loay hoay mới vá hoàn chỉnh được endpoint này.

Ban đầu team Defense thử decode base64 của payload rồi check string flag bên trong, nhưng kết quả không khả quan, có lẽ do viết sai nên payload vẫn chạy, rồi service bị check là đã chết, có lẽ do rule này. Sau đó team Defense nghĩ ra 1 trick cực hay. Do base64 sẽ mã hóa 3 ký tự ASCII thành 4 ký tự Base64 nên string /flag/ dù base64 kiểu gì thì nó cũng chỉ nằm trong 3 trường hợp /fla, flag, lag/ tương ứng L2ZsYQ, ZmxhZw, bGFnLw.

SecRule ARGS "@contains L2ZsYQ" "id:1001,phase:1,deny,msg:"Block encode base64 /flag/"
SecRule ARGS "@contains ZmxhZw" "id:1002,phase:1,deny,msg:"Block encode base64 /flag/"
SecRule ARGS "@contains bGFnLw" "id:1003,phase:1,deny,msg:"Block encode base64 /flag/"
SecRule ARGS:f "@contains /flag" "id:1004,phase:2,t:base64Decode,t:lowercase,deny,msg:'Request contains /flag'"
SecRule REQUEST_HEADERS:X-File-Name ".*\.php" "id:1005,phase:2,t:lowercase,deny,status:403,log,msg:'PHP extension in X-File-Name header'"
SecRule REQUEST_URI|REQUEST_HEADER|REQUEST_BODY "@contains /flag/flag" "id:1006,phase:2,deny,msg:'Block getting flag"

Và từ sau khi vá được endpoint đầu tiên thì gần như không bị mất điểm defense nào cả. Không ngờ rule này hiệu quả bất ngờ, kể từ khi áp dụng không thấy team nào hack thành công đội mình. Tiếp theo, team sửa lại rule cũ(id:1004) dùng để check string "flag" sau khi decode base64 tham số f, rule chạy thành công và block hết các cách bypass. 1 rule to rules them all 🤣

Tầm giữa thì tự dưng service của team chết thêm 1 lần nữa rất lâu, mất hết điểm, trong lòng mình đã nghĩ rằng chắc không có giải gì rồi. Service chết gần 2 round. May sao nhờ BTC hỗ trợ reset server thì đã trở lại bình thường.

Sau đó có một vài đội mạnh đã block khá ngon endpoint, có vẻ block cả string flag, tuy nhiên không check kĩ nên có thể bị bypass bằng flaG. Nhận thấy chỉ cần có 2 endpoint này trong tay sẽ có thể quẩy thêm 1 lúc, đồng thời 1 round chỉ có 5 phút cũng ngắn, team quyết định sẽ để 1 đồng đội làm nhiệm vụ submit flag, còn mình tập trung tìm ra bug để backup.

Ban đầu mình đọc quy định của game thì thấy ban tổ chức (BTC) bảo không được DDOS các đội khác, nên mình cũng mặc định nghĩ là DOS cũng không được phép. Tuy nhiên trong quãng thời gian này thì BTC có nói rằng có chức năng gây DOS (và vẫn đúng luật) nên mình quyết định sẽ đi tìm nó.

Sau một thời gian tìm kiếm, mình đã tìm ra được 1 cách, đó là thay vì đọc file flag mình sẽ đọc file /dev/urandom. Việc đọc file này làm chậm hệ thống nếu gửi nhiều lần. Nếu dos hệ thống thì có thể khiến cho bot check status không sẵn sàng -> trừ điểm service. Tuy nhiên lúc đó team mình vẫn đang top 1 nên tạm thời chưa dùng đến lỗ hổng này, đề phòng bị ăn cắp payload rồi bị target.

image.png

Kết quả sẽ trả về rất chậm gần 10s (sau khi gửi request trên vài lần).

image.png

2.3. Những round cuối cùng

Vào những round cuối, vì team đã block được các endpoint có lỗi, và service chạy ổn định trở lại thì điểm defense của team mình gần như không bị mất, đồng thời điểm attack lúc nào cũng full nên team mình đã vươn lên và cách đội đứng thứ 2 khá xa. Điều đó làm động lực của team mình giảm xuống, khoảng 5 round cuối là đã chắc chắn top 1. Vì thế lỗ hổng dos kia cũng không cần sử dụng.

Ngay từ lúc bắt đầu, mình đã nhận định sai lầm là hệ thống này không có lỗi để RCE nên cũng không đi tìm nó. Tuy nhiên về cuối, BTC lại gợi ý có tới 4 cách để RCE, làm mình hơi sốc. Thế là mình lại đi tìm cách để RCE. Trong đó có 1 chức năng upload file có thể bị bypass.

image.png

Lúc đó cuộc thi đã gần kết thúc nên mình cũng không có thời gian dùng lỗi này quẩy.

Kết thúc thì team mình đã may mắn đứng thứ nhất.

3. Nhận xét chung

Đánh giá chung về DF Cyber Defense năm nay có kịch bản rất giống thực tế, xuất phát từ các tình huống có thật, cơ hội giao lưu, cọ sát với các team bên ngoài. Các đội thi thố khá căng và thời gian 3 tiếng trôi qua như một cơn gió. Nếu thi full day thì rất đã, nhiều chiến thuật tiếp theo sẽ lôi ra áp dụng, nhưng rất tiếc không có cơ hội.

Sau khi về nhà và nhận được source code, mình thấy team vẫn còn nhiều lỗi khá cơ bản mà chưa được tìm ra. Các bạn có thể tìm tiếp trong repo có đề, script bên dưới.

https://github.com/shfsec/dfcd_atk_def_2023/

Team mình vẫn còn nhiều điều có thể cải thiện như tìm thêm bug nhanh hơn, block chặt hơn và cần đảm bảo service hoạt động ổn định,... Rất cảm ơn Ban tổ chức đã chuẩn bị 1 sự kiện chuyên nghiệp, một trải nghiệm tuyệt vời trong sự nghiệp làm An ninh mạng.

P/s: Nhân tiện thì team bọn mình vẫn đang tuyển đồng đội AppSec/SOC, các bạn có thể nhanh tay apply qua email nhé 👏