这是一篇很早之前记录的文章,现在重新整理一下。大致看了一下可能会到7.10篇幅可能比较长,所以分开来写。
因为个人水平有限,文中可能会出现错误的地方,还望多多指正。本文仅供交流学习。
1.1 反射型 XSS
0x01 漏洞背景
XSS 攻击全称跨站脚本攻击,是为不和层叠样式表 (Cascading Style Sheets, CSS) 的缩写混淆,故将跨站脚本攻击缩写为 XSS , XSS 是一种在 web 应用中的计算机安全漏洞,它允许恶意 web 用户将代码植入到提供给其它用户使用的页面中。
非持久型跨站:反射型跨站脚本漏洞,最普遍的类型。
0x02 漏洞代码及分析
- 漏洞代码:
<?php
$username = $_GET['user'];
echo " 用户名: ".$username;
?>
将用户输入的 user 内容直接输出到页面,未经过任何过滤。可导致 XSS 漏洞攻击
- 修复建议:
在接收输入后进行 htmlspecialchars 过滤,或者在输出前 htmlspecialchars 过滤 - 建议修复代码:
<?php
$username = $_GET['user'];
echo " 用户名: ".htmlspecialchars($username);
?>
1.2 存储型 XSS
0x01 漏洞背景
XSS 攻击全称跨站脚本攻击,是为不和层叠样式表 (Cascading Style Sheets, CSS) 的缩写混淆,故将跨站脚本攻击缩写为 XSS , XSS 是一种在 web 应用中的计算机安全漏洞,它允许恶意 web 用户将代码植入到提供给其它用户使用的页面中。
存储型跨站:危害大、恶意代码存储服务器 ( 数据库 )
0x02 漏洞代码及分析
- 漏洞代码:
if (!empty($_POST['content'])) {
$content = addslashes($_POST['content']);
if ($mysqli - >query("insert into test (content)values('$content')")) {
echo '发言成功';
} else {
echo '发言失败';
}
}
$data = $mysqli - >query("select content from test");
if ($data - >num_rows !== '0') {
$arr = $data -> fetch_all();
foreach($arr as $a) {
echo '发言:'.$a[0].'<br>';
}
}
用户发言的内容未进行字符串编码,直接存储到数据库中,并取出数据库中带有恶意代码的内容输出到网页中,导致 XSS 攻击
- 修复建议:
在接收输入后进行 htmlspecialchars 过滤,或者在输出前 htmlspecialchars 过滤 - 建议修复代码:
echo ' 发言: '.htmlspecialchars($a[0]).'<br>';
1.3 DOM XSS
0x01 漏洞背景
XSS 攻击全称跨站脚本攻击,是为不和层叠样式表 (Cascading Style Sheets, CSS) 的缩写混淆,故将跨站脚本攻击缩写为 XSS , XSS 是一种在 web 应用中的计
算机安全漏洞,它允许恶意 web 用户将代码植入到提供给其它用户使用的页面中。
DOM XSS :一种特殊类型的反射型 XSS ,它是基于 DOM 文档对象模型的一种漏洞。
0x02 漏洞代码及分析
- 漏洞代码 1 :
<?php
$img = isset($_GET['img']) ? htmlspecialchars($_GET['img']) : 'default.jpg';
?>
<img src="" id="image">
<script>
var test = document.getElementById('image');
test.src = '<?php echo $img;?>';
</script>
使用了 htmlspecialchars 进行过滤,但单引号没有过滤,导致 DOM XSS
- 修复建议:
在接收输入后进行 htmlspecialchars 过滤,并且还有对单引号和反斜杠进行转义 - 建议修复代码:
$img = isset($_GET['img']) ? htmlspecialchars(addslashes($_GET['img'])) : 'default.jpg';
- 漏洞代码 2:
<?php
$content = isset($_GET['content']) ? htmlspecialchars($_GET['content']) : ' 无内容 ';
$content = str_replace("'","\'",$content);
?>
<div id="content">
这是测试内容
</div>
<script>
var test = document.getElementById('content');
test.innerHTML = '<?php echo $content;?>';
</script>
innerHTML 、 documen.write 这种直接修改 html 内容的方法,应对其内容进行严格过滤,否则通过 8 进制或 16 进制编码可绕过 htmlspecialchars 过滤
- 建议修复代码:
$content = isset($_GET['content']) ? htmlspecialchars(addslashes($_GET['content'])) : ' 无内容 ';
2.1 文件读取漏洞
0x01 漏洞背景
任意文件读取漏洞,是 web 安全里高危的漏洞,它可以泄露源码、数据库配置文件等等,导致网站处于极度不安全状态。
0x02 漏洞代码及分析
- 漏洞代码 1 :
<?php
$template = isset($_GET['template']) ? $_GET['template'] : 'index.html';
$file = file_get_contents('2.1/'.$template);
echo $file;
?>
未对 ../ 进行过滤,导致可以跨目录读取文件。未对后缀名进行限制,导致可以读取 php 文件内容。
- 修复建议:
不允许 .. 等跨目录字符出现,使用 addslashes 防止 %00 截断,且限制后缀白名单 - 建议修复代码:
$template = isset($_GET['template']) ? addslashes($_GET['template']) : 'index.html';
if(strstr($template, '..') || substr($template,-5,5) != '.html')
{
echo ' 输入不合法 ';
exit;
}
- 漏洞代码 2 :
<?php
$action = isset($_GET['action']) ? $_GET['action'] : 'login';
$fp="./2.1/".$action."/index.html";
$f= fopen($fp,'r');
$strout = fread($f,filesize($fp));
fclose($f);
echo $strout;
?>
未对 ../ 进行过滤,导致可以跨目录读取文件。未过滤 %00 字节,在 <PHP5.3.4 版本中,可在截断后自定义路径和文件名
- 修复建议:
不允许 .. 等跨目录字符出现,使用 addslashes 防止 %00 截断 - 建议修复代码:
$action = isset($_GET['action']) ? addslashes($_GET['action']) : 'login';
if(strstr($template, '..'))
{
echo ' 输入不合法 ';
exit;
}
2.2 文件上传漏洞
0x01 漏洞背景
上传文件的时候,如果服务器端脚本语言,未对上传的文件进行严格的验证和过滤,就有可能上传恶意的脚本文件,从而控制整个网站,甚至是服务器。
0x02 漏洞代码及分析
- 漏洞代码 1 :
< ?php
if (isset($_FILES['file'])) {
if (($_FILES["file"]["type"] == "image/gif" || $_FILES["file"]["type"] == "image/jpeg" || $_FILES["file"]["type"] == "image/pjpeg") && $_FILES["file"]["size"] < 20000) {
if ($_FILES["file"]["error"] > 0) {
echo "Return Code: ".$_FILES["file"]["error"]."<br />";
} else {
echo "Upload: ".$_FILES["file"]["name"]."<br />";
echo "Type: ".$_FILES["file"]["type"]."<br />";
echo "Size: ".$_FILES["file"]["size"] / 1024." Kb<br />";
echo "Temp file: ".$_FILES["file"]["tmp_name"]."<br />";
if (file_exists("2.2/upload/".$_FILES["file"]["name"])) {
echo $_FILES["file"]["name"]." already exists. ";
} else {
move_uploaded_file($_FILES["file"]["tmp_name"], "2.2/upload/".$_FILES["file"]["name"]);
echo "Stored in: "."2.2/upload/".$_FILES["file"]["name"];
}
}
} else {
echo "Invalid file";
}
} ? >
仅对 Content-type 验证,因为 Content-type 可以伪造导致可以绕过限制图片验证,导致任意文件上传
- 修复建议:
对后缀进行校验,采用白名单模式。保存文件名采用随机文件名 + 后缀的方式保存 - 建议修复代码:
< ?php
if (isset($_FILES['file'])) {
$ext = substr($_FILES["file"]["name"], strrpos($_FILES["file"]["name"], '.') + 1);
$filename = time().rand(100, 999).'.'.$ext;
if (($ext == "jpg" || $ext == "jpeg" || $ext == "png") && $_FILES["file"]["size"] < 20000) {
if ($_FILES["file"]["error"] > 0) {
echo "Return Code: ".$_FILES["file"]["error"]."<br />";
} else {
echo "Upload: ".$_FILES["file"]["name"]."<br />";
echo "Type: ".$_FILES["file"]["type"]."<br />";
echo "Size: ".$_FILES["file"]["size"] / 1024." Kb<br />";
echo "Temp file: ".$_FILES["file"]["tmp_name"]."<br />";
if (file_exists("2.2/upload/".$filename)) {
echo $filename." already exists. ";
} else {
move_uploaded_file($_FILES["file"]["tmp_name"], "2.2/upload/".$filename);
echo "Stored in: "."2.2/upload/".$filename;
}
}
} else {
echo "Invalid file";
}
} ? >
- 漏洞代码 2
< ?php $imageinfo = getimagesize($_FILES['userfile']['tmp_name']);
if ($imageinfo['mime'] != 'image/gif' && $imageinfo['mime'] != 'image/jpeg') {
echo "Sorry, we only accept GIF and JPEG images\n";
exit;
}
$uploaddir = '2.2/upload/';
$uploadfile = $uploaddir.basename($_FILES['userfile']['name']);
if (move_uploaded_file($_FILES['userfile']['tmp_name'], $uploadfile)) {
echo "File is valid, and was successfully uploaded.\n";
} else {
echo "File uploading failed.\n";
} ? >
仅通过读取文件头判断文件类型,可被绕过;后缀名未进行校验,导致任意文件上传、
- 修复建议:
参考漏洞代码 1 的修复方式 - 漏洞代码 3
< ?php $blacklist = array(".php", ".phtml", ".php3", ".php4");
foreach($blacklist as $item) {
if (preg_match("/{$item}\$/i", $_FILES['userfile']['name'])) {
echo "We do not allow uploading PHP files\n";
exit;
}
}
$uploaddir = '2.2/upload/';
$uploadfile = $uploaddir.basename($_FILES['userfile']['name']);
if (move_uploaded_file($_FILES['userfile']['tmp_name'], $uploadfile)) {
echo "File is valid, and was successfully uploaded.\n";
} else {
echo "File uploading failed.\n";
} ? >
扩展名黑名单过滤不严,可上传 .php5 文件进行绕过。导致任意文件上传
- 修复建议:
参考漏洞代码 1 的修复方式
2.3 文件写入漏洞
0x01 漏洞背景
在生成配置文件或者缓存文件的时候,未对传入的内容进行过滤,导致 php 代码执行漏洞
0x02 漏洞代码及分析
- 漏洞代码 1 :
< ?php
if ($isset($_POST['debug'])) {
$setting = $_POST['debug'];
$content = "<?php\r\n";
$content. = "\$YCF['debug'] = '".$setting."';\r\n";
$content. = "?>";
file_put_contents("2.3/config.php", $content);
} ? >
未对传入内容进行任何过滤,用单引号绕出去可以引起代码执行漏洞
- 修复建议:
进行 addslashes 函数过滤。且不要拼接在双引号内,否则同样会引起代码执行漏洞 - 建议修复代码:
$setting = addslashes($_POST['debug']);
2.4 文件删除漏洞
0x01 漏洞背景
删除文件时对路径或文件名过滤不严,会导致任意文件删除
0x02 漏洞代码及分析
- 漏洞代码 1 :
< ?php
if (@$_GET['action'] == 'del') {
if (isset($_GET['img'])) {
$img = $_GET['img'];
unlink('2.4/'.$img);
echo ' 删除图片成功 ';
}
} ? >
对删除文件过滤不严,导致任意文件删除。
- 修复建议:
不允许 .. 等跨目录字符出现。进行 addslashes 函数过滤 - 建议修复代码:
$img = addslashes($_GET['img']);
if(strstr($img, '..'))
{
echo ' 输入不合法 ';
exit;
}
3.1 文件包含漏洞
0x01 漏洞背景
如果允许客户端用户输入控制动态包含在服务器端的文件,会导致恶意代码的执行及敏感信息泄露,主要包括本地文件包含和远程文件包含两种形式。通常
是由于 include 、 require 引起恶意包含
0x02 漏洞代码及分析
- 漏洞代码 1 :
< ?php
if ($_GET['func']) {
include $_GET['func'];
} else {
include '3.1/default.php';
} ? >
在未过滤的情况下,可包含带有恶意代码的 JPG 文件、日志文件,甚至可以远程包含
- 修复建议:
不允许 .. 等跨目录字符出现,对前缀跟后缀都进行限制,使用 addslashes 过滤 %00 防止被截断包含 - 建议修复代码:
< ?php
if ($_GET['func']) {
$file = addslashes($_GET['func']);
if (strstr($file, '..')) {
echo ' 输入不合法 ';
exit;
}
include '3.1/'.$file.'.php';
} else {
include '3.1/default.php';
} ? >
3.2 preg_replace 漏洞
0x01 漏洞背景
preg_replace /e 修正符使 preg_replace() 将 replacement 参数当作 PHP 代码(在适当的逆向引用替换完之后)。提示:要确保 replacement 构成一个合法
的 PHP 代码字符串,否则 PHP 会在报告在包含 preg_replace() 的行中出现语法解析错误。
0x02 漏洞代码及分析
- 漏洞代码 1 :
<?php
echo preg_replace("/test/e",$_GET["h"],"jutst test");
?>
- 漏洞代码 2 :
<?php
function test($str)
{
}
echo preg_replace("/s*[php](.+?)[/php]s*/ies", 'test("\1")', $_GET["h"]);
?>
语法不当的情况下,会导致代码执行漏洞
- 修复建议: 避免使用 /e 模式,第一、二个参数不让用户可控。第二个参数单引号改成双引号
- 建议修复代码:
echo preg_replace("/s*[php](.+?)[/php]s*/ies", "test('\1')", $_GET["h"]);
版权属于:ic翼
本文链接:https://bingyishow.top/Technical-article/154.html
您必须遵守 署名-非商业性使用-相同方式共享 CC BY-NC-SA 使用这篇文章