文章目录
- 基于布尔的盲注
- 工作原理
- 示例代码
- 防御措施
- 基于时间的盲注
- 工作原理
- 示例代码
- 防御措施
- 其他防御措施
- 输入验证
- 错误处理
- 使用WAF(Web应用防火墙)
基于布尔的盲注
工作原理
基于布尔的盲注通过构造SQL查询来判断数据库的响应是否满足某个条件。攻击者通过观察应用程序的响应来推断数据库的信息。
示例代码
假设有一个搜索功能,允许用户通过ID查找用户信息:
from flask import Flask, request, render_template_string
import sqlite3app = Flask(__name__)@app.route('/search')
def search():user_id = request.args.get('id')conn = sqlite3.connect('example.db')cursor = conn.cursor()# 不安全的查询query = f"SELECT * FROM users WHERE id = {user_id}"cursor.execute(query)results = cursor.fetchall()return render_template_string('<pre>{{ results }}</pre>', results=results)if __name__ == '__main__':app.run(debug=True)
攻击者可以通过以下方式尝试注入:
-
探测可注入点:
- 请求:
/search?id=1 AND 1=1
- 请求:
/search?id=1 AND 1=2
- 请求:
-
逐步猜测:
- 请求:
/search?id=1 AND (SELECT substr(password, 1, 1) FROM users WHERE id = 1) = 'a'
- 请求:
/search?id=1 AND (SELECT substr(password, 1, 1) FROM users WHERE id = 1) = 'b'
- 请求:
通过观察应用程序的响应,攻击者可以逐步猜测出密码的第一个字符。
防御措施
使用参数化查询:
@app.route('/search')
def search():user_id = request.args.get('id')conn = sqlite3.connect('example.db')cursor = conn.cursor()# 安全的查询query = "SELECT * FROM users WHERE id = ?"cursor.execute(query, (user_id,))results = cursor.fetchall()return render_template_string('<pre>{{ results }}</pre>', results=results)
基于时间的盲注
工作原理
基于时间的盲注利用数据库的延时函数(如MySQL的SLEEP()
函数),通过控制查询执行的时间来判断SQL语句是否被执行。
示例代码
假设有一个登录功能,允许用户通过用户名和密码登录:
from flask import Flask, request, render_template_string
import pymysqlapp = Flask(__name__)@app.route('/login')
def login():username = request.args.get('username')password = request.args.get('password')conn = pymysql.connect(host='localhost', user='root', password='password', db='example')cursor = conn.cursor()# 不安全的查询query = f"SELECT * FROM users WHERE username = '{username}' AND password = '{password}'"cursor.execute(query)results = cursor.fetchall()if results:return "Login successful"else:return "Login failed"if __name__ == '__main__':app.run(debug=True)
攻击者可以通过以下方式尝试注入:
-
探测可注入点:
- 请求:
/login?username=admin' AND SLEEP(5) AND '1'='1&password=anything
- 请求:
-
逐步猜测:
- 请求:
/login?username=admin' AND IF((SELECT substr(password, 1, 1) FROM users WHERE username = 'admin') = 'a', SLEEP(5), 0) AND '1'='1&password=anything
- 请求:
/login?username=admin' AND IF((SELECT substr(password, 1, 1) FROM users WHERE username = 'admin') = 'b', SLEEP(5), 0) AND '1'='1&password=anything
- 请求:
通过测量响应时间,攻击者可以判断密码的第一个字符。
防御措施
使用参数化查询:
@app.route('/login')
def login():username = request.args.get('username')password = request.args.get('password')conn = pymysql.connect(host='localhost', user='root', password='password', db='example')cursor = conn.cursor()# 安全的查询query = "SELECT * FROM users WHERE username = %s AND password = %s"cursor.execute(query, (username, password))results = cursor.fetchall()if results:return "Login successful"else:return "Login failed"
其他防御措施
输入验证
对所有用户输入进行严格的验证,确保只接受合法的数据。
def validate_input(input_str):# 假设只允许字母和数字if not input_str.isalnum():raise ValueError("Invalid input")return input_str@app.route('/search')
def search():user_id = validate_input(request.args.get('id'))conn = sqlite3.connect('example.db')cursor = conn.cursor()query = "SELECT * FROM users WHERE id = ?"cursor.execute(query, (user_id,))results = cursor.fetchall()return render_template_string('<pre>{{ results }}</pre>', results=results)
错误处理
避免向用户暴露详细的错误信息。
@app.errorhandler(Exception)
def handle_exception(e):return "An error occurred", 500
使用WAF(Web应用防火墙)
部署Web应用防火墙可以自动检测并阻止许多已知的攻击模式。
通过以上措施,可以显著提高应用程序的安全性,防止SQL盲注攻击。希望这些示例和解释能帮助你更好地理解和防范SQL盲注。