title: 2022-07-13 文件上传漏洞
category: /小书匠/笔记/2022-07
对于前端js检测可以通过burp进行中间人修改数据包,先讲webshell文件的后缀改成js支持的后缀,在中间人拦截中改回原后缀
也可以通过前端js检测的方法绕过
对于php文件尾过滤,可以采用phtml,php3,php5,phps等等,也可以采用大小写绕过,对于文件尾过滤过于严谨的可以尝试上传.htaccess文件
对于windows来讲会自动去除文件尾后边的空格,但是对于服务器来讲如果没有trim($file_ext);
首尾去空的函数,则可以在文件尾后面添加一个空格,比如对’.php’过滤,则不会匹配’.php '结尾的文件,服务器仍然会正常解析
对于windows来讲会自动去除文件末尾后面的.,但是对于服务器来讲如果没有deldot($file_name);
删除文件名末尾的点函数,则可以在文件名后面添加一个.,对于’.php’过滤,则不会过滤掉’.php.'文件
如果在检测中没有 strtolower()函数,说明不存在大小写过滤,因此可以考虑大小写绕过
如果是window的服务器可以采用这种方法绕过,因为当文件末尾添加:: D A T A 之后会将该文件当做文件流处理,且保持之前的文件名,比如 " 1. p h p : : DATA之后会将该文件当做文件流处理,且保持之前的文件名,比如"1.php:: DATA之后会将该文件当做文件流处理,且保持之前的文件名,比如"1.php::DATA",Windows会自动去掉末尾的::$DATA变成"1.php"
对于正则表达式过滤掉一些字符,或者某些函数去除.和空格只去除一次,可以进行多写几个空格和点.绕过
.htaccess是apache的特有文件,负责相关目录下的网页配置。通过htaccess文件,可以帮助我们实现:网页301重定向,自定义404错误页面,改变文件扩展名,允许或组织特定的用户或者,目录的访问,禁止目录列表,配置默认文档等功能,其中最重要的则是可以改变文件解析规则,比如将图片文件解析成php文件 #F44336,从而上传一张携带webshell的图片文件,就可以成功链接,
使用方法
<FilesMatch "hello">
SetHandler application/x-httpd-php
</FilesMatch>
对于文件名中存在hello的文件,会自动解析成php文件,对于.htaccess文件不能有前缀,名称只能是.htaccess,否则无用
apache解析漏洞:Apache是从右向左解析,也就是从文件名末尾向文件名首解析,如果不认识后缀就向左移,直到可以识别后缀为止
php版本小于5.3.4(高版本php官方修复了这个漏洞),php的magic_quotes_gpc为OFF状态
%00绕过主要是针对于白名绕过
原理:白名单过滤肯定是从后往前读取后缀,所以读取到.jpg在白名单里就放通了。
但是在调用文件的时候读取文件名是从前往后读,所以看到.php后面的终止符的时候就停止读取了,最终读取的文件名的后缀就是.php
%00是URl编码,只针对get传参,所以不适用与post传输文件地址
原理就是:一般上传的文件不是直接就送到服务器上的,而是先放到临时目录里,然后再重命名(经常我们看到的网页上的图片都是一串数字,那就是重命名之后的),最后再发往服务器
最后重命名之后的文件的存储路径是用的GET传参的参数
对于post请求来讲,已经不适用于%00截断,其他方法和%00相似
现在地址后面输入想要命名的文件名称在末尾添加任意字符,方便后续更改
相关参考链接:https://www.cnblogs.com/domb2235/p/15654493.html
对于一些文件上传漏洞会对文件属性进行检测,不单单是检测文件头尾,这些需要制作图片马,windows下通过copy命令即可.
copy 1.png/b+2.php 3.png
图片马一般不会自动执行,需要配合文件包含漏洞进行利用
有时候服务器会对上传上去的图片进行二次渲染,生成一张新的图片,从而过滤掉webshell脚本,这时只需要将渲染后的图片与渲染前的图片进行对比,查看二者相同的地方,也就是渲染未改动的地方,在此处插入webshell脚本即可,网上推荐用gif图片
相关链接https://ce.pwnthebox.com/writeup?id=956
制作链接:
https://blog.csdn.net/weixin_45519736/article/details/105775721
条件竞争实际上就是通过burp不断的向服务器去传输文件,服务器对文件处理的速度是有限的,只要上传文件的速度大于服务器处理文件的速度,那么上传的文件会短暂的停留在服务器上,这个时候使用python脚本,不断的去请求这个文件,这个文件通常是小马,因为该文件只是短暂停留,因此改文件应当时可以生成木马的文件,当python请求到这个文件的时候,这个文件就会自动生成一个木马,以此来绕过文件过滤机制.
符合条件竞争的代码参考
$is_upload = false;
$msg = null;
if(isset($_POST['submit'])){
$ext_arr = array('jpg','png','gif');
$file_name = $_FILES['upload_file']['name'];
$temp_file = $_FILES['upload_file']['tmp_name'];
$file_ext = substr($file_name,strrpos($file_name,".")+1);
$upload_file = UPLOAD_PATH . '/' . $file_name;
if(move_uploaded_file($temp_file, $upload_file)){
if(in_array($file_ext,$ext_arr)){
$img_path = UPLOAD_PATH . '/'. rand(10, 99).date("YmdHis").".".$file_ext;
rename($upload_file, $img_path);
$is_upload = true;
}else{
$msg = "只允许上传.jpg|.png|.gif类型文件!";
unlink($upload_file);
}
}else{
$msg = '上传出错!';
}
}
关键点:
参考链接:https://ce.pwnthebox.com/writeup?id=962
https://blog.csdn.net/qq_46150940/article/details/115639419
对于一些白名单绕过,有时候会判断接收到的文件名是否是一个数组,如果不是将其以分割成数组
if (!is_array($file)) {
$file = explode('.', strtolower($file));
}
$ext = end($file);
explode(a,b)函数以a为分割,把b转为数组。
end() 把数组内部指针移动到数组最后一个元素,并返回值。
然后再次拼接,
$file_name = reset($file) . '.' . $file[count($file) - 1];
reset()函数把数组内部指针移动到数组第一个元素,并返回值。
count()函数数组元素的数量。
通过$file_name = reset($file) . '.' . $file[count($file) - 1];
可以知道最终的文件名是由数组的第一个和最后一个元素拼接而成
当我们自己传入一个数组的时候
$file[0]=1.php/.
f i l e [ 2 ] = j p g 故 e n d ( ) 函数获取的是 file[2]=jpg 故end()函数获取的是 file[2]=jpg故end()函数获取的是file[2],在代码审计中也可以看到进行文件尾判断是通过end()获取到的内容进行的判断
$ext = end($file);
$allow_suffix = array('jpg','png','gif');
if (!in_array($ext, $allow_suffix)) {
$msg = "禁止上传该后缀文件!";
}
但是count( f i l e ) = 2 , file)=2, file)=2,file[count( f i l e ) − 1 ] = file) - 1]= file)−1]=file[1],我们并没有传入 f i l e [ 1 ] , 所以 file[1],所以 file[1],所以file[1]为空,因此通过$file_name = reset($file) . '.' . $file[count($file) - 1];
函数执行的结果$file=1.php/.
进而通过move_uploaded_file()函数的特性,会忽略掉文件末尾的/.,php文件上传成功
有时候会检测文件内容是否含有’',对于php文件来讲是无法绕开的,可以采用phtml文件绕过,phtml文件可以被正常解析,内容格式如下
<script language="php">
eval($_POST[1]);
script>