<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>文章 on linxi的博客</title><link>https://linxi1457-blog.pages.dev/posts/</link><description>Recent content in 文章 on linxi的博客</description><generator>Hugo</generator><language>zh-cn</language><lastBuildDate>Sun, 25 Oct 2026 09:00:00 +0800</lastBuildDate><atom:link href="https://linxi1457-blog.pages.dev/posts/index.xml" rel="self" type="application/rss+xml"/><item><title>木马与 Webshell 识别：从上传入口到行为链</title><link>https://linxi1457-blog.pages.dev/posts/trojan-webshell-detection/</link><pubDate>Sun, 25 Oct 2026 09:00:00 +0800</pubDate><guid>https://linxi1457-blog.pages.dev/posts/trojan-webshell-detection/</guid><description>&lt;p&gt;文件上传功能看起来只是一个普通业务入口，实际却同时连接着文件存储、Web 服务器解析、应用权限和脚本执行多个环节。攻击者一旦能上传一份可被服务器执行的脚本，就可能把它当作 Web 后门，也就是常说的 Webshell。&lt;/p&gt;&#10;&lt;p&gt;判断木马不能只看某个扩展名，也不能只搜索几个固定函数。更可靠的方法是把下面几条链路串起来：&lt;/p&gt;&#10;&lt;ol&gt;&#10;&lt;li&gt;用户如何进入上传入口。&lt;/li&gt;&#10;&lt;li&gt;文件最终保存到哪里。&lt;/li&gt;&#10;&lt;li&gt;服务器把文件当成什么类型解析。&lt;/li&gt;&#10;&lt;li&gt;请求参数是否能进入动态执行或文件操作。&lt;/li&gt;&#10;&lt;li&gt;进程、网络和日志中留下了什么行为。&lt;/li&gt;&#10;&lt;/ol&gt;&#10;&lt;blockquote&gt;&#10;&lt;p&gt;本文面向安全开发和授权排查。文中不提供可直接部署的 Webshell 代码；可疑样本应在隔离环境中处理。&lt;/p&gt;&#10;&lt;/blockquote&gt;&#10;&lt;h2 id="一文件上传的三个关键问题"&gt;一、文件上传的三个关键问题&lt;/h2&gt;&#10;&lt;p&gt;审计上传功能时，可以先问三个问题：&lt;/p&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;文件实际保存到了哪里？&lt;/li&gt;&#10;&lt;li&gt;保存后的文件名和扩展名是什么？&lt;/li&gt;&#10;&lt;li&gt;Web 服务器最终用什么规则解析这个文件？&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;p&gt;前端显示“只允许图片”并不能证明后端安全。浏览器端的文件选择器、JavaScript 校验和 MIME 限制都可以被修改，真正有效的控制必须发生在服务端。&lt;/p&gt;&#10;&lt;p&gt;上传链路通常包括：&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;客户端选择文件&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; -&amp;gt; 后端接收请求&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; -&amp;gt; 校验类型与大小&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; -&amp;gt; 规范化文件名&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; -&amp;gt; 写入存储目录&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; -&amp;gt; 记录元数据&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; -&amp;gt; 后续访问或下载&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;任何一步只依赖客户端提供的信息，都可能产生安全缺口。&lt;/p&gt;&#10;&lt;h2 id="二扩展名黑名单为什么容易失效"&gt;二、扩展名黑名单为什么容易失效&lt;/h2&gt;&#10;&lt;p&gt;不少系统会维护一份“危险扩展名黑名单”，再删除文件名中的对应后缀。这种方法有几个天然问题。&lt;/p&gt;&#10;&lt;h3 id="21-解析规则比后缀更复杂"&gt;2.1 解析规则比后缀更复杂&lt;/h3&gt;&#10;&lt;p&gt;开发者看到一个文件名，服务器看到的可能是另一个文件名。以下因素都可能影响最终结果：&lt;/p&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;大小写处理。&lt;/li&gt;&#10;&lt;li&gt;多重扩展名。&lt;/li&gt;&#10;&lt;li&gt;尾随点或空格。&lt;/li&gt;&#10;&lt;li&gt;URL 解码和 Unicode 规范化。&lt;/li&gt;&#10;&lt;li&gt;Windows 与 Linux 的路径和文件名规则差异。&lt;/li&gt;&#10;&lt;li&gt;不同 Web 服务器的脚本映射配置。&lt;/li&gt;&#10;&lt;li&gt;文件系统或容器层对特殊名称的处理。&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;p&gt;黑名单往往只覆盖开发者想到的写法，而服务器的解析器却可能支持更多组合。&lt;/p&gt;&#10;&lt;h3 id="22-应该使用允许列表"&gt;2.2 应该使用允许列表&lt;/h3&gt;&#10;&lt;p&gt;上传目录只允许业务真正需要的文件类型，例如：&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;允许：jpg、jpeg、png、webp、pdf&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;禁止：其他全部类型&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;允许列表仍不是唯一控制。还需要同时校验：&lt;/p&gt;</description></item><item><title>反序列化漏洞：从数据格式到对象信任边界</title><link>https://linxi1457-blog.pages.dev/posts/deserialization-boundaries/</link><pubDate>Sun, 25 Oct 2026 08:40:00 +0800</pubDate><guid>https://linxi1457-blog.pages.dev/posts/deserialization-boundaries/</guid><description>&lt;p&gt;序列化负责把内存中的对象或数据结构转换成可存储、可传输的格式；反序列化则把这种格式还原成程序可以使用的数据或对象。&lt;/p&gt;&#10;&lt;p&gt;这套机制本身没有问题。真正的风险出现在应用把不可信输入直接交给反序列化器，并且运行环境中还存在能够被串联起来的对象方法时。&lt;/p&gt;&#10;&lt;p&gt;一个典型的危险条件组合是：&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;可控输入&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; + 不安全反序列化&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; + 可利用的类或对象链&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; + 足够的进程权限&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; = 可能造成命令执行、文件访问或服务异常&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;blockquote&gt;&#10;&lt;p&gt;本文讨论识别和防御，不提供针对真实系统的对象链或利用代码。&lt;/p&gt;&#10;&lt;/blockquote&gt;&#10;&lt;h2 id="一序列化解决什么问题"&gt;一、序列化解决什么问题&lt;/h2&gt;&#10;&lt;p&gt;对象通常存在于程序内存中，而内存状态不能直接跨网络传输，也不能长期保存。序列化把这些状态编码成字符串、字节流或其他格式，使它能够：&lt;/p&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;写入缓存。&lt;/li&gt;&#10;&lt;li&gt;保存到文件。&lt;/li&gt;&#10;&lt;li&gt;在服务之间传输。&lt;/li&gt;&#10;&lt;li&gt;进入消息队列。&lt;/li&gt;&#10;&lt;li&gt;作为会话数据保存。&lt;/li&gt;&#10;&lt;li&gt;在进程重启后被恢复。&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;p&gt;常见应用场景包括：&lt;/p&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;Java 的 &lt;code&gt;Serializable&lt;/code&gt; 对象。&lt;/li&gt;&#10;&lt;li&gt;PHP 的 &lt;code&gt;serialize()&lt;/code&gt; 与 &lt;code&gt;unserialize()&lt;/code&gt;。&lt;/li&gt;&#10;&lt;li&gt;Python 的 &lt;code&gt;pickle&lt;/code&gt;。&lt;/li&gt;&#10;&lt;li&gt;.NET 的二进制序列化。&lt;/li&gt;&#10;&lt;li&gt;各种 RPC 框架的自定义编码。&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;p&gt;不同格式的风险并不相同。JSON、Protocol Buffers 等数据格式主要描述普通值，通常不会自动实例化任意类；PHP 对象序列化和 Java 原生序列化则可能带有对象类型和调用语义。&lt;/p&gt;&#10;&lt;h2 id="二理解序列化格式"&gt;二、理解序列化格式&lt;/h2&gt;&#10;&lt;h3 id="21-常见类型标记"&gt;2.1 常见类型标记&lt;/h3&gt;&#10;&lt;p&gt;PHP 序列化字符串使用类型标记和长度描述数据。一个简化的数组示例如下：&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;a:3:{i:0;s:5:&amp;#34;hello&amp;#34;;i:1;i:42;i:2;b:1;}&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;table&gt;&#10;&#9;&lt;thead&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;th&gt;标记&lt;/th&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;th&gt;含义&lt;/th&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&lt;/thead&gt;&#10;&#9;&lt;tbody&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;&lt;code&gt;a&lt;/code&gt;&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;数组&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;&lt;code&gt;i&lt;/code&gt;&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;整数&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;&lt;code&gt;s&lt;/code&gt;&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;字符串&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;&lt;code&gt;d&lt;/code&gt;&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;浮点数&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;&lt;code&gt;b&lt;/code&gt;&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;布尔值&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;&lt;code&gt;N&lt;/code&gt;&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;null&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;&lt;code&gt;O&lt;/code&gt;&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;对象&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&lt;/tbody&gt;&#10;&lt;/table&gt;&#10;&lt;p&gt;理解格式有助于分析数据，但格式本身并不构成漏洞。关键在于接收方如何使用这些内容。&lt;/p&gt;</description></item><item><title>XSS 漏洞：从输出上下文到浏览器安全边界</title><link>https://linxi1457-blog.pages.dev/posts/xss-context-and-defense/</link><pubDate>Sun, 25 Oct 2026 08:20:00 +0800</pubDate><guid>https://linxi1457-blog.pages.dev/posts/xss-context-and-defense/</guid><description>&lt;p&gt;XSS，也就是跨站脚本攻击，本质上是浏览器把不可信输入解释成了代码。&lt;/p&gt;&#10;&lt;p&gt;漏洞通常出现在“用户可以写，页面又会展示”的位置，例如搜索框、评论区、昵称、个人资料和消息提醒。只要输入进入 HTML、属性、URL 或 JavaScript 上下文，而输出处理不正确，就可能越过数据边界。&lt;/p&gt;&#10;&lt;blockquote&gt;&#10;&lt;p&gt;本文不提供可直接用于攻击的 XSS 载荷。安全验证应在授权环境中使用无害标记，重点证明执行条件，而不是窃取数据或影响真实用户。&lt;/p&gt;&#10;&lt;/blockquote&gt;&#10;&lt;h2 id="一xss-成立需要什么条件"&gt;一、XSS 成立需要什么条件&lt;/h2&gt;&#10;&lt;p&gt;一个 XSS 问题通常同时满足以下条件：&lt;/p&gt;&#10;&lt;ol&gt;&#10;&lt;li&gt;不可信输入能够进入页面。&lt;/li&gt;&#10;&lt;li&gt;输入落在浏览器会解释的位置。&lt;/li&gt;&#10;&lt;li&gt;输出编码或过滤没有匹配当前上下文。&lt;/li&gt;&#10;&lt;/ol&gt;&#10;&lt;p&gt;“用户可控”不只包括 URL 参数，还包括：&lt;/p&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;表单字段。&lt;/li&gt;&#10;&lt;li&gt;Cookie 和请求头。&lt;/li&gt;&#10;&lt;li&gt;数据库中的历史内容。&lt;/li&gt;&#10;&lt;li&gt;文件上传后的文件名。&lt;/li&gt;&#10;&lt;li&gt;第三方接口返回的数据。&lt;/li&gt;&#10;&lt;li&gt;WebSocket 消息。&lt;/li&gt;&#10;&lt;li&gt;&lt;code&gt;postMessage&lt;/code&gt; 事件。&lt;/li&gt;&#10;&lt;li&gt;前端路由和 URL 片段。&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;p&gt;风险点不在于输入来自哪里，而在于它最终被放进了什么上下文。&lt;/p&gt;&#10;&lt;h2 id="二常见类型"&gt;二、常见类型&lt;/h2&gt;&#10;&lt;h3 id="21-反射型-xss"&gt;2.1 反射型 XSS&lt;/h3&gt;&#10;&lt;p&gt;反射型 XSS 中，请求参数被服务端立即写回响应页面。恶意参数通常不在服务器长期保存，需要诱导用户访问包含该参数的链接。&lt;/p&gt;&#10;&lt;p&gt;典型链路：&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;请求参数&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; -&amp;gt; 服务端模板&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; -&amp;gt; 未正确编码的 HTML&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; -&amp;gt; 浏览器执行&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;只在当前用户的浏览器中触发，并不意味着风险低。攻击者仍可能借此读取当前页面数据或诱导用户操作。&lt;/p&gt;&#10;&lt;h3 id="22-存储型-xss"&gt;2.2 存储型 XSS&lt;/h3&gt;&#10;&lt;p&gt;存储型 XSS 会把不可信内容保存到数据库、缓存或文件中，其他用户访问页面时再次输出。&lt;/p&gt;&#10;&lt;p&gt;典型场景：&lt;/p&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;评论内容。&lt;/li&gt;&#10;&lt;li&gt;用户昵称和签名。&lt;/li&gt;&#10;&lt;li&gt;工单描述。&lt;/li&gt;&#10;&lt;li&gt;文件名称。&lt;/li&gt;&#10;&lt;li&gt;导入的数据。&lt;/li&gt;&#10;&lt;li&gt;富文本编辑器。&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;p&gt;它的影响范围可能更大，因为内容可能在多个页面和多个用户之间传播。&lt;/p&gt;&#10;&lt;h3 id="23-dom-型-xss"&gt;2.3 DOM 型 XSS&lt;/h3&gt;&#10;&lt;p&gt;DOM 型 XSS 的主要处理发生在浏览器端。服务器返回的 HTML 可能完全正常，但前端脚本把不可信数据写入了危险位置。&lt;/p&gt;</description></item><item><title>逻辑漏洞：越权、竞争与业务状态一致性</title><link>https://linxi1457-blog.pages.dev/posts/logic-vulnerabilities/</link><pubDate>Sun, 25 Oct 2026 08:00:00 +0800</pubDate><guid>https://linxi1457-blog.pages.dev/posts/logic-vulnerabilities/</guid><description>&lt;p&gt;逻辑漏洞通常没有明显的语法错误。页面可以正常打开，接口也能返回成功，但业务流程中的权限、顺序、金额或状态可以被绕过。&lt;/p&gt;&#10;&lt;p&gt;这类问题很难只靠一个通用漏洞扫描器发现，因为“正确行为”由业务规则定义。开发者需要从攻击者视角重新检查：&lt;/p&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;谁能调用这个功能？&lt;/li&gt;&#10;&lt;li&gt;能操作哪一条数据？&lt;/li&gt;&#10;&lt;li&gt;操作顺序能否跳过？&lt;/li&gt;&#10;&lt;li&gt;同一请求能否重复提交？&lt;/li&gt;&#10;&lt;li&gt;客户端提交的金额、角色和状态是否可信？&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;h2 id="一身份认证流程"&gt;一、身份认证流程&lt;/h2&gt;&#10;&lt;p&gt;认证系统是逻辑漏洞最常见的高价值目标。一次认证绕过可能直接导致管理员权限失守。&lt;/p&gt;&#10;&lt;p&gt;检查认证流程时，应关注：&lt;/p&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;用户名、密码和验证码是否都由服务端校验。&lt;/li&gt;&#10;&lt;li&gt;验证码是否与当前会话、用途和有效期绑定。&lt;/li&gt;&#10;&lt;li&gt;登录失败是否会有统一提示，避免用户枚举。&lt;/li&gt;&#10;&lt;li&gt;会话是否在登录后重新生成。&lt;/li&gt;&#10;&lt;li&gt;普通用户创建后是否仍可能访问管理功能。&lt;/li&gt;&#10;&lt;li&gt;高权限账户是否要求多因素认证。&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;h3 id="11-验证码只在前端校验"&gt;1.1 验证码只在前端校验&lt;/h3&gt;&#10;&lt;p&gt;如果页面通过 JavaScript 判断验证码，服务端没有再次验证，那么攻击者可以直接调用接口绕过页面。&lt;/p&gt;&#10;&lt;p&gt;正确流程应满足：&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;用户提交验证码&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; -&amp;gt; 服务端读取当前会话对应挑战&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; -&amp;gt; 检查有效期与尝试次数&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; -&amp;gt; 校验答案&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; -&amp;gt; 一次性销毁挑战&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;验证码不能与账户密码权限发生混淆。无论验证码是否正确，服务端都必须独立完成账户认证和角色授权。&lt;/p&gt;&#10;&lt;h3 id="12-会话固定"&gt;1.2 会话固定&lt;/h3&gt;&#10;&lt;p&gt;用户在登录前获得一个会话标识，登录成功后如果服务端继续使用同一个标识，攻击者可能提前获取它并复用。&lt;/p&gt;&#10;&lt;p&gt;修复方式：&lt;/p&gt;&#10;&lt;ol&gt;&#10;&lt;li&gt;登录成功后生成新的 Session ID。&lt;/li&gt;&#10;&lt;li&gt;作废旧的匿名会话。&lt;/li&gt;&#10;&lt;li&gt;在 Cookie 中设置安全属性。&lt;/li&gt;&#10;&lt;li&gt;退出登录时服务端主动失效会话。&lt;/li&gt;&#10;&lt;/ol&gt;&#10;&lt;h2 id="二cookiesession-与-token"&gt;二、Cookie、Session 与 Token&lt;/h2&gt;&#10;&lt;h3 id="21-cookie"&gt;2.1 Cookie&lt;/h3&gt;&#10;&lt;p&gt;Cookie 是浏览器保存数据的一种机制，不等于完整登录凭证。实际身份通常由服务端会话、签名 Token 或安全存储的数据确定。&lt;/p&gt;&#10;&lt;p&gt;安全属性包括：&lt;/p&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;&lt;code&gt;HttpOnly&lt;/code&gt;：限制 JavaScript 读取。&lt;/li&gt;&#10;&lt;li&gt;&lt;code&gt;Secure&lt;/code&gt;：只通过 HTTPS 发送。&lt;/li&gt;&#10;&lt;li&gt;&lt;code&gt;SameSite&lt;/code&gt;：限制跨站请求携带范围。&lt;/li&gt;&#10;&lt;li&gt;&lt;code&gt;Path&lt;/code&gt; 与 &lt;code&gt;Domain&lt;/code&gt;：控制发送范围。&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;p&gt;Cookie 的值不应直接包含可信角色或权限，除非同时具备可靠的签名和完整性校验。&lt;/p&gt;</description></item><item><title>SQL</title><link>https://linxi1457-blog.pages.dev/posts/sql-injection-and-waf-defense/</link><pubDate>Sun, 27 Sep 2026 11:40:00 +0800</pubDate><guid>https://linxi1457-blog.pages.dev/posts/sql-injection-and-waf-defense/</guid><description>&lt;p&gt;SQL 注入长期位居 Web 安全风险的核心位置，并不是因为它“古老”，而是因为它直接触碰了应用安全中最根本的一条边界：&lt;strong&gt;数据与代码必须分离&lt;/strong&gt;。&lt;/p&gt;&#10;&lt;p&gt;当用户输入被拼接进 SQL 语句时，输入不再只是数据，而有机会改变语句结构。安全产品、输入过滤和 WAF 可以增加攻击成本，但它们不能替代安全的数据访问方式。本文讨论 SQL 注入的主要类型、WAF 绕过的本质、常见检测误区，以及更可靠的工程化防御方案。&lt;/p&gt;&#10;&lt;blockquote&gt;&#10;&lt;p&gt;本文用于安全开发和防御体系建设。涉及真实系统的测试必须在明确授权、可恢复和可追踪的前提下进行。文章不提供针对真实目标的攻击步骤或可直接复用的绕过 payload。&lt;/p&gt;&#10;&lt;/blockquote&gt;&#10;&lt;h2 id="一sql-注入的本质"&gt;一、SQL 注入的本质&lt;/h2&gt;&#10;&lt;p&gt;应用程序通常会根据用户输入构造数据库查询。例如，概念上可能出现这样的逻辑：&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;查询用户名为输入值的管理员记录&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;如果输入始终被当作“用户名”这个数据值处理，那么无论用户输入什么内容，它都不应该改变查询结构。但如果应用采用字符串拼接，输入的语义就可能从“值”变成“语法”。&lt;/p&gt;&#10;&lt;p&gt;SQL 注入成立通常同时需要三个条件：&lt;/p&gt;&#10;&lt;ol&gt;&#10;&lt;li&gt;用户输入进入 SQL 语句。&lt;/li&gt;&#10;&lt;li&gt;输入能够影响 SQL 的语法结构。&lt;/li&gt;&#10;&lt;li&gt;应用或数据库会把执行结果、错误、状态或时间差异暴露给攻击者。&lt;/li&gt;&#10;&lt;/ol&gt;&#10;&lt;p&gt;第三个条件经常被忽略。没有可观测差异，攻击者通常难以持续判断自己的假设是否正确。因此，防御不只是阻止某个字符，而是同时收紧语法边界、数据库权限、错误输出和日志可见性。&lt;/p&gt;&#10;&lt;h2 id="二常见-sql-注入类型"&gt;二、常见 SQL 注入类型&lt;/h2&gt;&#10;&lt;p&gt;SQL 注入可以有多种分类方式。按照攻击者如何观察结果，通常可以分为以下几类。&lt;/p&gt;&#10;&lt;h3 id="1-联合查询型注入"&gt;1. 联合查询型注入&lt;/h3&gt;&#10;&lt;p&gt;部分数据库支持 &lt;code&gt;UNION&lt;/code&gt;，它可以把两条查询结果合并到同一结果集中。&lt;/p&gt;&#10;&lt;p&gt;联合查询型注入成立的前提通常包括：&lt;/p&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;原查询结果能够返回给客户端。&lt;/li&gt;&#10;&lt;li&gt;攻击者能够推断原查询的列数和兼容的数据类型。&lt;/li&gt;&#10;&lt;li&gt;数据库用户的权限允许读取目标数据。&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;p&gt;&lt;code&gt;UNION&lt;/code&gt; 并不会让数据库“忽略权限”。如果数据库账号只能读取一张业务表，即便语句结构被改变，也不可能越过数据库本身的权限边界。&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-sql" data-lang="sql"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;union&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;select&lt;/span&gt;&lt;span class="w"&gt; &#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;因此，防御不能只关注 &lt;code&gt;UNION&lt;/code&gt; 这个关键词，还要确保：&lt;/p&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;应用数据库账号使用最小权限。&lt;/li&gt;&#10;&lt;li&gt;敏感表与业务读取账号隔离。&lt;/li&gt;&#10;&lt;li&gt;查询接口不暴露不必要的字段。&lt;/li&gt;&#10;&lt;li&gt;查询结果在服务端完成权限判断，而不是依赖客户端过滤。&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;h3 id="2-报错型注入"&gt;2. 报错型注入&lt;/h3&gt;&#10;&lt;p&gt;报错型注入依赖应用把数据库错误原样返回给客户端，或者错误信息中包含可观察的表达式结果。&lt;/p&gt;&#10;&lt;p&gt;攻击者真正利用的不是“报错”本身，而是：&lt;/p&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;&#10;&lt;p&gt;错误内容具有差异性。&lt;/p&gt;&#10;&lt;/li&gt;&#10;&lt;li&gt;&#10;&lt;p&gt;错误内容可以被稳定复现。&lt;/p&gt;&#10;&lt;/li&gt;&#10;&lt;li&gt;&#10;&lt;p&gt;错误内容与攻击者提交的数据存在对应关系。&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-sql" data-lang="sql"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;SELECT&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;EXTRACTVALUE&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;CONCAT&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="n"&gt;x7e&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;SELECT&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;DATABASE&lt;/span&gt;&lt;span class="p"&gt;()),&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="n"&gt;x7e&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;-- 返回错误信息: ERROR 1105 (HY000): XPATH syntax error: &amp;#39;~数据库名~&amp;#39;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;p&gt;从工程角度看，生产环境应做到：&lt;/p&gt;</description></item></channel></rss>