[WU]Lord of SQLinjection
los.rubiya.kr
Last updated
Was this helpful?
los.rubiya.kr
Last updated
Was this helpful?
Bài này ta chỉ cần để ý vào câu query: select id from prob_gremlin where id='' and pw=''
Câu query này có 2 tham số id
và password
($_GET[id]
và $_GET[pw]
)
Nếu cả 2 tham số đều tồn tại thì $result
sẽ được trả về giá trị của id
và lúc này challenge sẽ được solved!!!
Việc ta cần làm là khiến cho điều kiện sau where
của query luôn đúng trong khi không id
và pw
.
Payload: ?id=' or 1=1 -- -&pw=gicungduoc
Giải thích: Truyền payload vào id và comment đoạn sau ngay khi kết thúc payload
'
: đóng tham số id
or 1=1
: điều kiện luôn đúng
-- -
: comment phía sau và dấu gạch cuối để bảo có khoảng trắng
Ta cần truyền 2 tham số id
và pw
. Trước khi query pw
sẽ được hash md5
và đặc biệt ta được biết trước có tồn tại 1 giá trị của id
là admin. Vậy để sau where
là một điều kiện luôn đúng thì ta cho id='admin'
và comment đoạn phía sau.
PAYLOAD: ?id=admin' -- -&pw=gicungduoc
Tại bài này ta thấy 1 điều đặc biệt đó là id
đã bị gán mặc định là guest và ta chỉ được truyền dữ liệu cho no
(kiểu int).
Như vậy ta phải tìm cách để query trả về giá trị id là admin.
Thử giá trị của no
lầnlượt là 0, 1 thử thì ta nhận được giá trị của no=1
là của id
guest.
Với câu query ban đầu: select id from prob_goblin where id='guest' and no=1
Điều kiện sau where là TRUE and TRUE = TRUE. Vậy nên sẽ luôn trả về id='guest'
.
Ta không biết được giá trị no
của admin là gì và ta cũng không thay được điều kiện id='guest'
.
Điều kiện trong SQL nếu không có 'ngoặc' thì chúng sẽ thực hiện tuần tự and trước or sau. Nếu phía sau điều kiện id
and với giá trị sai thì kết quả sẽ false và kết hợp với or true/false sẽ trả về true/false theo ta muốn, biểu diễn như sau: TRUE and FALSE or FALSE/TRUE = FALSE/TRUE
Kèm theo dữ kiện no
của guest là 1 thì no của admin sẽ là 1 số khác 1.
PAYLOAD: ?no=0%20or%20no<>1
Ở bài này mới gì vào thì ta thử ngày payload sau:
PAYLOAD: ?pw='or 1=1 -- -
Lúc này chỉ giải quyết được 1 nữa vấn đề.
Ta chú ý tới hàm addslahes()
đã vô hiệu hóa dấu ' mà ta truyền vào.
Bài này mình nghĩ ngay đến phía server dùng GBK (UTF-8, Chinese). Nên thử dùng kỹ thuật multibyte chinese để bypass thử:
PAYLOAD: 縗' OR 1=1 -- -
Thế là phải suy nghĩ lại từ đầu @@ Ở query 1 điều kiện khá yếu và ở query ngoại trừ addslashes()
thì còn phải đúng chính xác password thì mình nghĩ chắc phải viết scipt để blind sqli.
Để có được pasword mình phải làm từng bước như sau:
B1: Có được độ dài của password (id='admin' and 1=1or id='admin' and len(pw)=i)
B2: Đoán từng ký tự của password (id='admin' and 1=1or id='admin' and substr(pw,i,1)='a')
Vì ở đây nhờ khi đoán đúng thì response chứa <h2>Hello admin</h2>
nên kỹ thuật sử dụng ở đây gọi là triggering conditional responses (theo portswigger). Tiến hành viết script python:
Tèn ten đã có kết quả payload lúc này đơn giản là ?pw=095a9852
Ở bài này có 1 hàm login_chk()
khá lạ và phía dưới là filter khoảng trắng.
Việc bypass khoảng trắng ta có thể thay thế bằng những ký tự sau:
comment: /**/
tab: %09
carrage: %0d
return: %0a
Đã có cách bypass filter khoảng trắng giờ kết hợp với logic của bài goblin: TRUE and FALSE or TRUE = TRUE
PAYLOAD: ?pw=1'/**/or/**/id='admin
Bài này thật bất ngờ vì đã filter or
và and
:) Nhưng lại chừa cho ta một con đường sống là union
:D
Điều kiện kiểm tra $result['id'] = 'admin'
là pass vậy chỉ union
với SELECT 'admin' <3
Hoặc đơn giản hơn thay or
với ||.
PAYLOAD: ?pw=' union SELECT 'admin
HOẶC pw=' || id='admin
Bài này kếp hợp của drakelf và orce :> thế là phải viết script để blind sqli.
Từng bước đoán độ dài và đoán từng ký tự ở từng vị trí:
Kết quả nèeeee <3
Tại bài này em đã khóc :< em vắt nát óc ra nghĩ tới 1 payload siêu cấp vũ trụ ơ nhưng không :)
MySQL không có phân biệt chữ hoa chữ thường :D cách giải như cái tên bài vậy :)))))
PAYLOAD: ?id=admiN
Bài này đúng là 1 con vampire :) thay vì hút máu thì nó hút mất admin của ta :D
Vậy thì cho hút :>
PAYLOAD: ?id=adadminmin
(admin sẽ bị replace thì id sẽ còn admin)
Bài này mới vào thử ngay payload cơ bản
Payload: ?pw= ' or id='admin' -- -
Bài này là một bài blind sqli bị filter and
và or
giống bài orge. Ta có thể dùng hàm lenght()
để tìm độ dài password nhưng hàm substr()
đã bị filter nên cái khó là 1 hàm khác thay thế để đoán ra từng ký tự của password. Ngoài ra dấu =
cũng đã bị filter.
Hàm mid()
có chức năng tương tự hàm substr()
và dùng like
thay cho =
. Bắt tay vào viết script:
Bài này có 2 tham số pw
và no
. Với pw
là string mà filter dấu '
là thấy khá khoai. Còn no
là số cũng filter '
thì ít ra cũng dễ thở hơn. ==> Input vào là dãy hex sẽ bypass được các chuỗi cần '
(trong mysql có cơ chế tự động decode hex to text)
Cấm dùng ascii
để chuyển char sang dec thì ta dùng ord
, dùng mid
thay cho substr
và like
thay cho =
. Tiến hành viết script:
Ơ ??? thật không hiểu sao pasword dài 8 ký tự mà result có 7 ký tự thôi @@ mất đâu 1 ký tự.
Mình debug thử thì ký tự mất chính là ký tự cuối chữ f
. Thật khó hiểu?? Ở 7 ký tự đầu tiên đều đúng response <h2>Hello admin</h2>
nhưng riêng ký tự f
cuối cùng thì trả về <h2>Hello guest</h2>
????????? Một sự khó hiểu???? @@
Khó hiểu thế nên mình sửa script lại :))) chứ không cách nào tìm ra nguyên lý để giải thích!!!!
Sửa đoạn hex id like 'admin' thành id like %admin thì sẽ response đúng kết quả mong muốn
Sau khi sửa thì đã có password!!!
Tại bài này là sự kết hợp của tất cả các câu trên. Gồm có blind sqli và những filter khó chịu.
substr : mid
ascii : ord hex
= like : in
or : || (vô tình filter luôn ord vậy sẽ dùng hex)
and : && (%26%26 urlencoded)
' : "
Thử nghiệm 1 payload để check độ dài (mặc định là 8)
?pw=abc&no=0||/**/id/**/in/**/("admin")/**/%26%26/**/length(pw)/**/in/**/("8")/**/%23
Thành công!!! Bắt đầu viết script:
Tại bài này ta phải tách fromprob_giant
ra để được câu query hoàn chỉnh. Nhưng độ dài giới hạn chỉ có 1 (không thể dùng /**/) và filter những ký tự thay cho space như %09 (\t), %0a (\n), %0d (\r). Nhưng sau một hồi tìm hiểu và thử thì mình biết đến 1 ký tự "vertical tab a.k.a %0b a.k.a \v".
PAYLOAD: ?shit=%0b
Thấy like
thì liền dùng % wildcard.
Bước đầu đã thực hiện khá oke, mong muốn tiếp theo là trả về admin chứ không phải guest.
Với ý tưởng ban đầu của mình là kiểu gì password của admin sẽ tồn tại 1 ký tự mà password của guest sẽ không có nên chỉ cần chạy 1 vòng lặp ?pw=a% (thay a với tất cả ký tự thể hiện thị). Ơ :))) nhưng mà fail, chắc là password của admin và guest cùng bộ ký tự đó mà đã được hoán vị. :> Thôi thì đổi cách.
Ý tưởng script sẽ là match từ ký tự thứ nhất pw
cho đến vị trí ký tự của admin và guest khác nhau:
BONUS: mình debug để tìm được pw của cả 2 để tìm lý do fail của ý tưởng ban đầu của mình
PW admin: 902efd10
PW guest: 90d2fe10
=> cả 2 cùng bộ ký tự và hoán vị nhau.
Tại bài này ở 2 tham số id
và pw
đều đã bị filter dấu '
thì khá khó để inject gì vào.
Nhưng nhớ tới chế hoạt động của hàm addslashes()
của php, chèn \
vào trước dấu '
thì Escape character sẽ xảy ra.
PAYLOAD: ?id=\&pw=or 1=1 -- -
(Query: select id from prob_succubus where id='\' and pw=' or 1=1 -- -')
Lúc này phía sau dấu \
(phần in đậm) sẽ thành 1 chuỗi. FALSE or TRUE sẽ return TRUE.
Bài này cả 2 tham số id
và pw
trước khi được truyền vào query thì được đi qua lần lượt 2 hàm addslash()
và strrev()
.
addslash()
thêm \
vào trước những ký tự nào?
Tạ ơn hàm strrev()
vì nhờ hàm này mà sau khi chèn \
sẽ đảo ngược lại và mình áp dụng bài succubus. Ví dụ: " --> \" --> "\ --> ký tự'
phía sau \
sẽ escape!!!
PAYLOAD: id="&pw=- -- 1=1 ro