00截断上传的原理
php解释器是C语言编写的
C语言中学过字符串的结尾会有00作为字符串结束的标志
在url中%00表示ascll码中的0 ,而ascii中0作为特殊字符保留,表示字符串结束,所以当url中出现%00时就会认为读取已结束
0x00,%00,/00之类的截断,都是一样的
条件
%00截断有两个条件php版本小于5.3.4和magic_quotes_gpc为off状态。 如果这时我们将magic_quotes_gpc改为on那么就不能截断了,因为开启magic_quotes_gpc后%00会被加上一个反斜杠转义掉
解读代码
后端验证代码
if (!empty($_POST['submit'])) {
$name = basename($_FILES['file']['name']);//$_FILES['myFile']['name'] 客户端文件的原名称
$info = pathinfo($name);//pathinfo()获取文件的后缀
$ext = $info['extension'];
$whitelist = array("jpg", "png", "gif");
if (in_array($ext, $whitelist)) {
$des = $_GET['road'] . "/" . rand(10, 99) . date("YmdHis") . "." . $ext;
//move_uploaded_file—将上传的文件移动到新位置
if (move_uploaded_file($_FILES['file']['tmp_name'], $des)) {
echo "<script>alert('上传成功')</script>";
} else {
echo "<script>alert('上传失败')</script>";
}
} else {
echo "文件类型不匹配";
}
}
d e s 在 连 接 的 时 候 最 前 面 连 接 的 是 des在连接的时候最前面连接的是 des在连接的时候最前面连接的是_GET[‘road’],而$_GET[‘road’]这个参数又是我们可以编辑指定的,所以可以构造出00截断
$_FILES数组内容
$_FILES[‘myFile’][‘name’] 客户端文件的原名称
$_FILES[‘myFile’][‘type’] 文件的 MIME类型,需要浏览器提供该信息的支持,例如"image/gif"
$_FILES[‘myFile’][‘size’] 已上传文件的大小,单位为字节
$_FILES[‘myFile’][‘tmp_name’] 文件被上传后在服务端储存的临时文件名,一般是系统默认,可以在php.ini的upload_tmp_dir指定,但用 putenv() 函数设置是不起作用的
$_FILES[‘myFile’][‘error’] 和该文件上传相关的错误代码,[‘error’] 是在 PHP 4.2.0版本中增加的,下面是它的说明:(它们在PHP3.0以后成了常量)
注:
1. 文件被上传结束后,默认地被存储在了临时目录中,这时必须将它从临时目录中删除或移动到其它地方,如果没有,则会被删除。也就是不管是否上传成功,脚本执行完后临时目录里的文件肯定会被删除。所以在删除之前要用PHP的copy() 函数将它复制到其它位置,此时,才算完成了上传文件过程。
参考:https://www.cnblogs.com/xzj8023tp/p/8719792.html
https://www.cnblogs.com/52php/p/5660087.html
pathinfo()获取文件的后缀
pathinfo()函数返回的是一个包含了文件信息的数组,数组中有四个元素,分别是dirname、basename、extension、filename。
Array (
[dirname] => /www/mywebsite/images
[basename] => myphoto.jpg
[extension] => jpg
[filename] => myphoto
)
注:pathinfo()、dirname()、basename()都可以获得文件的路径
做题
或者
hex编码修改 更改相应的字节 0x20->0x00【20是空格】
https://blog.csdn.net/qq_26090065/article/details/81458937
CTFhub双写绕过
<!--
$name = basename($_FILES['file']['name']);
$blacklist = array("php", "php5", "php4", "php3", "phtml", "pht", "jsp", "jspa", "jspx", "jsw", "jsv", "jspf", "jtml", "asp", "aspx", "asa", "asax", "ascx", "ashx", "asmx", "cer", "swf", "htaccess", "ini");
$name = str_ireplace($blacklist, "", $name);//把字符串 $name中的字符$blacklist(不区分大小写)替换成空
-->
经过测试发现这个函数只匹配第一个