Security News
Oracle Drags Its Feet in the JavaScript Trademark Dispute
Oracle seeks to dismiss fraud claims in the JavaScript trademark dispute, delaying the case and avoiding questions about its right to the name.
github.com/lehoangtu019/ctf-cookie-arena
# CTF-Cookie-Arena
Đây là source code xử lý chính:
Đầu tiên, ta chú ý thấy dòng code 57,58. Trình duyệt sẽ trả lại kết quả flag cho chúng ta nếu biến uid trùng chuỗi kí tự "admin".
Vậy GOAL của chúng ta ở bài là làm cách nào gán được chuỗi kí tự "admin" vào biến uid !!!
Từ dòng 37 đến dòng 44 được dùng để lọc các kí tự trong các chuỗi uid, upw và level.
Đây là ví dụ khi ta nhập chuỗi "admin" vào trường uid trong login
Kết quả trả như chúng ta dự kiến: No Hack!
Sử dụng công cụ BurpSuite để bắt lại gói tin sau khi ta submit để kiểm tra
Trong gói tin, thứ ta gửi đi chỉ có 2 trường uid, upw và nhớ lại xem nào chúng ta có bỏ sót gì không.
Chú ý ở 2 dòng được khoanh đỏ, chúng ta có 1 biến "level" cũng nhận dữ liệu từ web như "uid" và "upw". Và dòng khoanh đỏ còn lại câu lệnh SQL có chứa cả Untrusted Data "level".
Từ dòng 52 đến dòng 58, chuỗi SQL sẽ được xử lý ở dòng 52 bởi hàm execute() và kết quả gán vào biến "req". Sau đó lại sử dụng thêm hàm fetchone() để lấy 1 bản ghi đơn lẻ từ kết quả SQL. Nếu kết quả tồn tại thì lấy phần tử đầu tiên của "result" gán vào "uid".
ta đã kiếm được lỗ hỏng: Untrusted Data (level) + Unsafe method (execute).
Đến đây mình sử dụng 1 web sandbox SQL để kiểm tra cú pháp: https://sqliteonline.com/. Đầu tiên ta xem lại các kí tự bị lọc đi trong đó có bao gồm kí tự space.
Vậy nên ta cần 1 kí tự hoặc 1 chuỗi kí tự khác có chức năng tương tự như space để thay thế nó. Thử sử dụng các kí tự ASCII đều không có khả năng, chúng ta dùng chuỗi kí tự /**/.
Vấn đề tiếp theo là làm sao khi thực thi câu lệnh SQL, thì giá trị "admin" sẽ được gán vào biến "result" nếu chúng ta không thể nhập "admin" vì chúng sẽ bị lọc.
Lúc này ta sẽ đặt câu hỏi rằng thứ gì có thể thay thế chuỗi "admin" và đây sẽ là câu trả lời - Bảng mã ASCII: https://www.asciitable.com/
char(97)||char(100)||char(109)||char(105)||char(110)
Vấn đề cuối cùng: Sau khi thực thi lệnh SQL, làm sao kết quả trả về phải là "admin". Câu lệnh SQL "SELECT uid FROM users WHERE uid='123' and upw='123' and level=7" sẽ trả về cho chúng ta rỗng vì không tồn tại bất kì 1 uid nào như thế trong table users. Vậy sẽ ra sao nếu đoạn code SQL ta chèn thêm phía sau có khả năng tạo ra kết quả trả lại là "admin"? Vì SELECT bị lọc đi mất nên cùng tìm hiểu xem liệu có method nào trả lại giá trị không. Sau khi tìm hiểu, Hàm VALUES('input') sẽ tạo ra 1 hàng 1 cột chứa giá trị "input". Nếu ta để VALUES(1) sẽ trả giá trị 1. Vậy nếu ta để chuỗi "admin" trên vào thì sao?
=> Ta đã có đầy đủ các mảnh ghép cần thiết!!!
Bây giờ ta sử dụng BurpSuite,repeat gói tin đầu tiên gửi đi, tìm đến dòng có chứa biến "uid" và "upw" thêm vào: &level=7//union//values(char(97)||char(100)||char(109)||char(105)||char(110))
Bài này cung cấp cho chúng ta source code chính login.php và register.php
GOAL: Đăng nhập được vào tài khoản admin!!!
Đọc code xử lý chính file login.php, ta thấy rằng câu lệnh SQL được đưa vào biến "stmt" và bằng việc sử dụng hàm bind_param để định dạng thuộc tính chuõi cho 2 biến "username" và "password". Việc sử dụng hàm bind_param này đã phần này nâng tính bảo mật của việc xử lý code vì tất cả những giá trị ta đưa vào biến "username" và biến "password" đều bị định dạng thành string => Không thể sử dụng những phương pháp chèn thêm UNION SELECT, kí tự "'",... được (Hoặc có nếu mình chưa tìm ra :< )
Nhưng chúng ta chỉ mới nhìn qua form login mà thôi, vậy còn form đăng ký thì sao? Trong form đăng ký, có đoạn code kiểm tra tính độc nhất của user (chỉ tồn tại duy nhất 1 tài khoản cùng tên) => Vậy nên ta không thể tạo ra thêm 1 tài khoản "admin" khác được. Và như ta thấy các đoạn code trước khi đưa dữ liệu vào xử lý câu lệnh SQL đều được anh lập trình viên sử dụng hàm bind_param định dạng thành chuỗi hết => Vậy thì cũng chẳng tồn tại lỗ hỏng SQL nào.
Để ý kĩ ta sẽ thấy 1 đoạn code nhỏ góc phải bên dưới là các câu lệnh SQL trong việc tạo tài khoản người dùng cho table users. Tìm hiểu 1 tí ta sẽ nhận ra rằng có tồn tại 1 lỗi mà anh lập trình viên quên ngăn chặn. Đó là SQL Truncation Attack (Tấn công SQL cắt cụt).
Giải thích: Những ai có lập trình php web qua sẽ đều biết rằng khi tạo 1 cơ sở dữ liệu ta thường sẽ phải định dạng cho dữ liệu ấy thuộc kiểu dữ liệu nào và độ dài của dữ liệu.
Minh họa việc tạo cột trong 1 bảng trong phpadmin.
Vậy ta thử đăng ký với giá trị username là "admin 123" và password = "123" và đảm bảo rằng username có hơn 20 kí tự thì khi dữ liệu được đưa vào hệ thống xử lý phần sau giới hạn sẽ tự động bị cắt bỏ đi và như thế sẽ trở thành "admin " tổng cộng 20 kí tự gồm 5 kí tự admin và 15 kí tự khoảng trắng. Lúc này trong table users đã có 1 tài khoản mới username = "admin" và password = "123" tồn tại song song.
Sau khi đăng nhập vào tài khoản admin, ta sẽ được chuyển hướng tới flag.php
Nhấp vào "click me for the flag" trong trang sẽ hiện về kết quả như thế này
Có vẻ trang web cũng không có gì cho chúng ta để tìm. Vậy chúng ta sử dụng tool recon ffuf để tìm các directories và thứ mà mình tìm được là "src"
Vào trong /src sẽ hiện chúng ta nội dung như sau
Đọc kỹ nội dung bên trong ta sẽ tìm được 1 dòng khá "khả nghi" "/super-secret-route-nobody-will-guess'". Quả thật không ai có thể đoán được và thì chúng ta truy cập thử vào sẽ xuất hiện web như thế này
Chúng ta không thể truy cập được, liệu chúng ta có bỏ sót ở đâu không, cùng xem lại thử nào.
Chúng ta đã bỏ quên method "PUT". Thứ chúng ta chạy chính là trên method "GET". Vậy thử lại với burpSuite thay đổi method nào.
Và chúng ta đã thành công giải được bài này !!!
GOAL: tìm đến /flag để lấy flag!!!
Đây là trang web xử lý:
Test thử chức năng "CURL" của trang web:
Đoạn code xử lý chính của bài này sẽ được mình upload lên với tên file là main.go. Tìm hiểu code, ta cần chú ý vào các dòng 18,55,95. Những dòng code này đều đề cập đến địa chỉ IP 127.0.0.1 (đây là địa chỉ IP từ máy host)
=> Vậy ta có thể nhận định rằng đây là lỗi SSRF (Server-Side Request Furgery)
Đối với dạng bài SSRF này, ta không thể truy cập trực tiếp vào dir /flag được vì hệ thống sẽ chỉ cho phép chính host (127.0.0.1) truy cập vào. Và đây là ảnh minh họa khi ta cố gắng truy cập từ địa chỉ IP không phải host.
Vậy phương pháp để giải dạng này dùng chính khả năng "gọi URL" của web (cụ thể ở đây là lệnh CURL) để gọi chính host chạy đến dir "/flag" và trả lại kết quả cho chúng ta. Hoàn thành bước 1: Nhận định lỗi và lên ý tưởng.
Đến bước tiếp theo, ta cần phải lên kế hoạch khai thác các lỗ hỏng, kiểm tra qua code ta nhận thấy rằng ta không thể đưa payload "http://127.0.0.1:1337/flag" vì kí tự "flag" "curl" "%" đã bị chặn. (Không thể sử dụng cả dạng mã hóa)
Nhận định rằng ta không thể truy cập vào /flag bằng cách đó => Tìm những lỗ hỏng khác để hỗ trợ. Ta chú ý rằng chúng ta chỉ mới tìm lỗ hỏng ở trường URL nhưng còn Header_Key và Header_Value thì sao. Tìm hiểu 1 chút trên mạng để xem có cách nào để sử dụng Header có thể chuyển hướng gói tin chúng ta đến dir /flag vượt qua bước kiểm tra. Ở đây mình tìm ra được các cụm từ Header: X-Forwarded-Host, X-Forwarded-Proto, X-Forwarded-Prefix,... Ở đây ta cần điều chỉnh URL để đến với dir /flag nên Header_key ta cần dùng là "X-Forwarded-Prefix"
Thử ý tưởng và ta sẽ lấy được đáp án:
ở đây mình có thêm 1 dấu slash "/" vào thành 127.0.0.1:1337// vì nếu URL được truyền trong tham số truy vấn url bắt đầu bằng dấu gạch chéo đơn (/), hàm http.NewRequest sẽ coi nó là đường dẫn tương đối và nối nó vào đường dẫn cơ sở hiện tại, dẫn đến một đường dẫn không chính xác. Bằng cách sử dụng dấu gạch chéo kép (//), mã đảm bảo rằng đường dẫn được coi là đường dẫn tuyệt đối, và hàm http.NewRequest có thể tạo một yêu cầu HTTP mới chính xác.
GOAL: Bạn chỉ có thể lấy được flag nếu bạn truy cập trang web từ web của https://cookiearena.org/
Đơn giản là ta thêm vào trường Referer với value là web "https://cookiearena.org/"
Và thế ta là đã lấy được flag
"You have to provide a sitemap.xml URL. /?sitemap_url=http://example.com/sitemap.xml"
sitemap.xml
thông qua tham số sitemap_url
. Nếu trang web này có lỗ hổng XXE thì ta có thể khai thác bằng cách chèn 1 tệp XML có chứa mã độc để tấn công hệ thống. <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE urlset [ <!ENTITY xxe SYSTEM "file:///flag.txt" >> ]> <urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9"> <url> <loc>&xxe;</loc> </url> </urlset>
example.com/path_to_file/sitemap.xml
. Ở đây mình chọn upload lên http://fileupload.cyberjutsu-lab.tech:12001/
và mình có được đường dẫn đến file như sau: http://fileupload.cyberjutsu-lab.tech:12001/upload/083efb603c5314185b67448868b84b1a/sitemap.xml
sitemap_url
libxm12
,DOMParser
để tắt khả năng xử lý.FAQs
Unknown package
Did you know?
Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.
Security News
Oracle seeks to dismiss fraud claims in the JavaScript trademark dispute, delaying the case and avoiding questions about its right to the name.
Security News
The Linux Foundation is warning open source developers that compliance with global sanctions is mandatory, highlighting legal risks and restrictions on contributions.
Security News
Maven Central now validates Sigstore signatures, making it easier for developers to verify the provenance of Java packages.