是在app.py中进行修改,替换libinjection.so
app.py:
from flask import Flask, request, jsonify
import ctypes
import numpy as np
from tensorflow.keras.models import load_model
from tensorflow.keras.preprocessing.sequence import pad_sequences
import pickle
import json
from urllib.parse import unquote
import html
import sys
import base64
import re
from utils.makelog import log_detection
import os
import logging
from logging.handlers import RotatingFileHandler
os.environ['TF_KERAS'] = '1'
os.environ['TF_CPP_MIN_LOG_LEVEL'] = '2' # 1=警告,2=错误,3=静默
os.environ['TF_ENABLE_ONEDNN_OPTS'] = '0' # 关闭 oneDNN 提示
app = Flask(__name__)
log_dir = os.path.join(os.path.dirname(os.path.abspath(__file__)), 'utils')
os.makedirs(log_dir, exist_ok=True)
# 配置文件日志处理器(10MB轮换,保留10个备份)
file_handler = RotatingFileHandler(
os.path.join(log_dir, 'app.log'),
maxBytes=10*1024*1024,
backupCount=10
)
file_handler.setFormatter(logging.Formatter(
'%(asctime)s - %(name)s - %(levelname)s - %(message)s'
))
# 设置日志级别(DEBUG/INFO/WARNING/ERROR/CRITICAL)
app.logger.setLevel(logging.INFO)
file_handler.setLevel(logging.INFO)
app.logger.addHandler(file_handler)
# --- 加载 libinjection ---
try:
libinjection = ctypes.CDLL('/usr/local/lib/libinjection.so', mode=ctypes.RTLD_GLOBAL)
libinjection.libinjection_sqli.argtypes = [
ctypes.c_char_p,
ctypes.c_size_t,
ctypes.c_char_p,
ctypes.c_size_t
]
libinjection.libinjection_sqli.restype = ctypes.c_int
app.logger.info("Libinjection 加载成功")
print("Libinjection 加载成功(控制台输出)")
except Exception as e:
app.logger.error(f"Libinjection 加载失败: {str(e)}", exc_info=True)
exit(1)
# --- 加载深度学习模型和辅助对象 ---
# try:
# model = load_model('/usr/local/flasktest/model/model1.h5')
# app.logger.info("模型 model1.h5 加载成功")
# with open('/usr/local/flasktest/model/model1.pkl', 'rb') as f:
# tokenizer, tfidf_vectorizer = pickle.load(f)
# app.logger.info("模型辅助对象 model1.pkl 加载成功")
# max_seq_length = int(np.load("/usr/local/flasktest/model/max_seq_length1.npy"))
# app.logger.info(f"最大序列长度加载成功: {max_seq_length}")
# with open('/usr/local/flasktest/model/best_threshold1.json', 'r') as f:
# best_threshold = json.load(f)['threshold']
# app.logger.info(f"检测阈值加载成功: {best_threshold}")
# except Exception as e:
# app.logger.error(f"模型加载失败: {str(e)}", exc_info=True)
# exit(1)
# --- 解码辅助函数 ---
def try_base64_decode(s):
try:
if len(s) % 4 != 0:
return s
decoded = base64.b64decode(s).decode('utf-8', errors='ignore')
if all(32 <= ord(c) <= 126 or c in '\t\r\n' for c in decoded):
return decoded
return s
except Exception:
return s
def deep_url_decode(s, max_depth=3):
decoded = s
for _ in range(max_depth):
new_decoded = unquote(decoded)
if new_decoded == decoded:
break
decoded = new_decoded
return decoded
# --- 提取 HTTP 请求中的潜在 SQL 内容 ---
def extract_sql_candidates(data):
candidates = []
def extract_strings(obj):
EXCLUDED_KEYS = {'uri', 'path', 'security', 'PHPSESSID', 'session_id','Login', 'login', 'submit', 'Submit'}
STATIC_RESOURCES = {'.css', '.js', '.png', '.jpg', '.jpeg', '.gif', '.ico', '.woff', '.woff2'}
if isinstance(obj, dict):
for key, value in obj.items():
if key in EXCLUDED_KEYS:
continue
# 检查值是否为静态资源(无需检测)
if isinstance(value, str) and any(ext in value.lower() for ext in STATIC_RESOURCES):
continue
extract_strings(value) # 递归调用,仅传递值
elif isinstance(obj, list):
for item in obj:
extract_strings(item)
elif isinstance(obj, str):
text = obj
# 多层 URL 解码
text = deep_url_decode(text)
# HTML 实体解码
text = html.unescape(text)
# Unicode 转义解码
try:
text = text.encode().decode('unicode_escape')
except Exception:
pass
# Base64 解码
text = try_base64_decode(text)
if len(text) < 1000:
candidates.append(text)
extract_strings(data)
return candidates
# --- 检测策略 ---
# def should_use_libinjection(text):
# return text.isdigit() or ' ' not in text or len(text) > 600
# --- 检测逻辑 ---
def detect_one(query):
if re.match(r'^\/.*\.(php|html|js)$', query):
return {
"检测结果": "正常",
"检测方式": "URI过滤",
"可信度": 1.0
}
result_buf = ctypes.create_string_buffer(8)
is_libi_sqli = libinjection.libinjection_sqli(query.encode('utf-8'), len(query),result_buf,ctypes.sizeof(result_buf))
if is_libi_sqli:
return {
"检测结果": "存在SQL注入",
"检测方式": "Libinjection",
}
else:
return {
"检测结果": "正常",
"检测方式": "Libinjection",
}
# seq = tokenizer.texts_to_sequences([query])
# padded = pad_sequences(seq, maxlen=max_seq_length)
# tfidf_vec = tfidf_vectorizer.transform([query]).toarray()
# prob = model.predict([padded, tfidf_vec], verbose=0)[0][0]
# if prob > best_threshold:
# return {
# "检测结果": "存在SQL注入",
# "检测方式": "CNN-BiLSTM",
# "可信度": float(prob),
# }
# else:
# return {
# "检测结果": "正常",
# "检测方式": "CNN-BiLSTM",
# "可信度":float(1 - prob),
# }
@app.route('/')
def home():
return "SQL 注入检测系统已启动"
@app.route('/detect', methods=['POST'])
def detect():
app.logger.info(f"接收到请求: {request.json}")
try:
data = request.get_json()
if not data:
return jsonify({"error": "缺少 JSON 请求体"}), 400
ip = request.remote_addr
candidates = extract_sql_candidates(data)
results = []
for query in candidates:
result = detect_one(query)
log_detection(ip, query, result)
results.append(result)
return jsonify({"detections": results})
except Exception as e:
return jsonify({"error": f"检测过程中发生错误: {str(e)}"}), 500
if __name__ == '__main__':
app.run(host='0.0.0.0', port=5000, debug=True)