原理
php是基础c语言实现的,C语言中认为0x00是结束符号,文件上传之所以可以00截断,是因为白名单判断的时候是判断后缀,在进行路径拼接的时候用的其他值,然后在进行move_uploaded_file的时候,这个函数读取到hex值为00的字符,认为读取结束,出现00截断
例如上传图片1.png,filename为1.png,save_path为…/upload/1.php%00  
我们看在代码层面会发生什么 1,取后缀名: $file_ext=png 后缀名在白名单中,符合
2,拼接上传路径:$img_path=…/upload/1.php/3220210812084323.png (1.php后面的%00不见了,因为他变成了hex值为00的结束字符,所以看不见) 3,将上传的文件移动到新位置 :move_uploaded_file函数在进行文件移动的时候,在读取$img_path的值的时候,读到1.php的后面时,遇到了hex值为00的结束字符,他会认为$img_path的值读取完毕,这个时候$img_path=…/upload/1.php,最后上传的文件名为1.php,实现了00截断。
分类
一,检查和拼接的变量为同一个 分情况,如果提取后缀名的函数会被00截断则不行;如果不会被截断,能提取到最后一个后缀名,就可以。经过测试pathinfo()不会被截断,会直接提取到最后一个后缀名。而substr()会被截断,导致提取到php后缀名 这种情况下,00截断就不能成功利用。假如上传的文件为1.php%00.png,那么在 substr()函数读取后缀名的时候就会出现截断,则读取到的后缀为php,无法绕过白名单。
二,检查和拼接的变量不是同一个 可以,见原理分析中的例子
利用条件
- php版本小于5.3.4
- magic_quotes_gpc为off(默认为0n)
|