稍候片刻,月出文自明。
<input value='<?php echo htmlspecialchars($name); ?>'><script>var name = "<?php echo htmlspecialchars($name, ENT_QUOTES); ?>";</script><a href="?page=<?php echo htmlspecialchars($page); ?>">link</a><?php
// 显示文章内容
$id = $_GET['id'];
$article = getArticleById($id);
?>
<div class="post">
<h1><?php echo $article['title']; ?></h1>
<div class="content">
<?php echo $article['content']; ?>
</div>
<div class="meta">
作者:<?php echo $article['author']; ?>,
发布时间:<?php echo $article['time']; ?>
</div>
<input type="button" value="收藏" onclick="addFavorite(<?php echo $article['id']; ?>)">
</div>
代码审计-PHP-XSS
1. XSS 漏洞基础
跨站脚本(Cross-Site Scripting, XSS) 是指攻击者将恶意脚本注入到受信任的网站中,当其他用户浏览该网站时,脚本会在其浏览器中执行,从而窃取 Cookie、会话劫持、钓鱼等。
按存储位置分为:
2. PHP 中 XSS 的常见触发点(输出上下文)
在 PHP 代码中,输出数据到 HTML 的不同位置需要不同的转义,漏掉任一环节都可能产生 XSS。
输出位置
危险函数/语句
示例
**HTML 主体内容**
`echo`, `print`, `print_r`, `var_dump`, `<?= ?>`
`echo $_GET['name'];`
**HTML 标签属性值**
同上,但输出在属性值内
`<input value="<?php echo $val; ?>">`
**JavaScript 字符串**
输出到 `<script>` 标签或事件处理器
`var msg = "<?php echo $msg; ?>";`
**CSS 样式**
输出到 `<style>` 或 `style` 属性
`background: "<?php echo $color; ?>"`
**URL 参数**
输出到 `href` 或 `src`
`<a href="?q=<?php echo $q; ?>">`
3. 代码审计方法论:输入追踪与输出检查
审计 XSS 的核心思路是 “数据流追踪” :
审计四步法:
4. PHP 安全函数分析
htmlspecialchars()
htmlentities()
strip_tags()
filter_var() 配合 FILTER_SANITIZE_STRING
自定义过滤(正则、黑名单)极其危险,几乎总有绕过方法。
5. 绕过安全函数的经典技巧
即便使用了 htmlspecialchars,如果参数配置不当或上下文错误,依然可被利用。
若 $name = "' onclick='alert(1)",则输出 <input value='' onclick='alert(1)'>,成功执行。
若 $name = "alert(1)\";//",输出 var name = "alert(1)\";//";,会提前闭合字符串并注入代码。
若 $page = "javascript:alert(1)",虽然 : 和 alert 不会被转义,但 href 属性支持 javascript: 协议,可直接执行。
6. 不同上下文下的转义要求
上下文
推荐的转义方法
HTML 主体
`htmlspecialchars($data, ENT_QUOTES
HTML 属性(普通)
同上,但属性值必须用双引号包裹(推荐)。
HTML 属性(URL)
先使用 `filter_var($url, FILTER_SANITIZE_URL)` 检查协议,再用 `htmlspecialchars` 输出。
JavaScript 字符串
使用 `json_encode()`(它会自动转义 Unicode 和特殊字符),然后输出。如 `var msg = <?= json_encode($msg); ?>;`
CSS 字符串
使用 `addcslashes` 转义 `\n, \r,`,`,`` 等,或使用 `json_encode` 并放在 JSON 中。 \
URL 参数
使用 `urlencode()` 编码参数值(但参数名不可控)。
7. 存储型 XSS 审计重点
存储型 XSS 的数据来自数据库,因此审计时不仅要追踪请求输入,还要追踪数据库读取后的输出。
常见场景:
审计技巧:
8. 审计工具与辅助技巧
9. 完整审计案例(逐步分析)
假设我们有一段博客系统的 PHP 代码:
审计步骤:
修复建议:
10. 修复方案与安全编码规范