upload-labs 1-17
新年快乐!祝各位师傅们在2023年shell拿到手软!!!
pass-1
第一关,先上传一个php文件,发现限制了只能上传.jpg/.png/.gif格式的文件,然后开始抓包,发现浏览器直接弹窗,并且bp没有抓到靶场的POST请求包,初步判断为前端过滤了,F12看了一下前端代码,发现了是js过滤。
最简单的绕过方法:浏览器直接禁用JavaScript,这种方法缺点就是有些网站禁用之后前端显示混乱。
第二种方法:
修改php文件后缀名为jpg,然后抓包,在数据包里面把.jpg改回.php
这样就能上传成功了,如果要访问这个文件我们就要找到该文件路径,直接F12看网页代码,然后ctrl+f搜刚刚上传的文件名,就找到访问路径了。
pass-2
第二关和第一关的第二个方法一样,直接先上传jpg然后抓包改格式就行。看源码是只校验Content-Type,所以可以用一样的方法。
pass-3
先上传一个php文件,提示不允许上传.asp,.aspx,.php,.jsp后缀文件!,遇到这种典型的黑名单绕过首先考虑使用.phtml ,.php3, .php4的后缀文件,上传一个.php3的后缀文件,直接上传成功,但是访问路径发现文件没有解析。
在网上找了很多资料发现是phpstudy的原因,AddType在高版本phpstudy不管用所以很多教程都说在httpd.conf里面加一句
AddType application/x-httpd-php .php .phtml .phps .php5 .pht
其实是不管用的,解决办法:
一。下载老版本phpstudy,改httpd.conf文件。
二。使用phpts版本,具体方法参考
关于PHPStudy中使用AddType application/x-httpd-php该Apache的设置命令无效的问题 - Article_kelp - 博客园 (cnblogs.com)
pass-4
还是老样子先上传一个.php文件,直接显示此文件不允许上传,并没有给提示。直接看一下过滤部分源码,几乎把所有的文件后缀名都过滤了。
$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",".ini");
$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);//去除字符串::$DATA
$file_ext = trim($file_ext); //收尾去空
那么这里我们可以用到.htaccess文件来更改文件拓展名,关于htaccess文件具体的请参考htaccess_百度百科 (baidu.com)
这里直接我们直接开始写一个.htaccess文件,意思是上传的所有文件都使用php解析
SetHandler application/x-httpd-php
再把要上传的PHP文件改个后缀名就行。
pass-5
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);//去除字符串::$DATA
$file_ext = trim($file_ext); //首尾去空
从源码可以看出来这里把.htaccess文件也禁止了,这一关的思路主要是上面这些过滤只会过滤一次,也就是说我们可以对后缀进行构造让他经过一次过滤之后还是能成功上传,这里直接抓包,在bp里面来对后缀进行构造,我们目标构造一个.php.的文件,因为上面的过滤函数deldot会直接删除文件名末尾的点,但是遇到字符就会停下,所以要有两个点并且要隔开,因此我们可以构造.php. .的文件,因为代码是从上往下执行并且只执行一次,所以代码会先把文件末尾的.去掉,然后最后一行过滤把空格去掉,最后留下就是.php.
也可以使用创建.user.ini文件来过这关
pass-6
看源码,没有转换成小写,直接把文件名改成大写就能上传成功。
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_name = deldot($file_name);//删除文件名末尾的点
$file_ext = strrchr($file_name, '.');
$file_ext = str_ireplace('::$DATA', '', $file_ext);//去除字符串::$DATA
$file_ext = trim($file_ext); //首尾去空
pass-7
看源码,没有首尾去空,所以这一关直接抓包,在文件后缀加个空格即可
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 = $_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);//去除字符串::$DATA
pass-8
看源码,没有删除文件名末尾点的过滤,所以抓包,在文件后缀加个.就行
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);//去除字符串::$DATA
$file_ext = trim($file_ext); //首尾去空
pass-9
看源码,和第5关方法一样.php. .
就能过。其实方法有很多比如双写绕过(使用.pphphp)在前面几关都能。比还如,这里源码没有去除字符串::$DATA,所以可以抓包改.php::$DATA后缀
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_name = deldot($file_name);//删除文件名末尾的点
$file_ext = strrchr($file_name, '.');
$file_ext = strtolower($file_ext); //转换为小写
$file_ext = trim($file_ext); //首尾去空
pass-10
这关也能用.php. .
来过关,也能用双写绕过。
pass-11
if (isset($_POST['submit'])) {
if (file_exists(UPLOAD_PATH)) {
$deny_ext = array("php","php5","php4","php3","php2","html","htm","phtml","pht","jsp","jspa","jspx","jsw","jsv","jspf","jtml","asp","aspx","asa","asax","ascx","ashx","asmx","cer","swf","htaccess","ini");
$file_name = trim($_FILES['upload_file']['name']);
$file_name = str_ireplace($deny_ext,"", $file_name);
$temp_file = $_FILES['upload_file']['tmp_name'];
$img_path = UPLOAD_PATH.'/'.$file_name;
if (move_uploaded_file($temp_file, $img_path)) {
$is_upload = true;
看源码就知道这关能过的方法有很多,一开始我用的.php::$DATA因为源码很明显没有过滤这个字符串,然后试了一下发现上传成功了,但是访问有问题,检查了一下路径,发现php没了,又看了一下源码str_ireplace函数会把检测到的上面那些后缀名删除,但他只会删一次,所以可以双写绕过,用.phphpp文件即可。
pass-12
$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类型文件!";
}
}
前几关都属于黑名单绕过,都是围绕.php后缀名来做文章,这一关看源码就很清楚这里是白名单,一开始没什么思路,提示是上传路径可控,又在网上看了很多师傅的文章才知道这关使用00截断可以看看这篇文章【文件上传】00截断详解_redwand的博客-CSDN博客_00截断
简单来说,如果文件格式是合法的,例如1.jpg,那么path=../upload/会和文件名结合形成文件完整路径../upload/1.jpg,我们自己加上1.php的文件名,并在文件名后面加上%00,然后改filename为合法格式如1.jpg,路径就变成了../upload/1.php%00/1.jpg,%00后面被截断了,就能成功上传。
所以我们可以上传一个的.php文件,抓包,改下面的文件后缀,在最上面的一行path路径加上2.php%00,就成功上传了。
pass-13
和上关差不多接受变成了post,区别是get会自行解码,post不会自行解码,我们需要对%00进行解码
pass-14
这关使用图片马,提示本pass只检查开头2个字节,因此可以将我们的php代码放在图片末尾,可以使用cmd,直接拼接,也能用十六进制编辑器在后面加上去,最简单的方就是bp抓包在文件内容头部加GIF89a来伪造图片头,上传之后,复制重命名后的文件名,到文件包含的界面进行测试。
pass-15
和上关一样。检查函数换成了getimagesize(),方法没变。
pass-16
这关源码提示要打开php_exif,我开了但是一点上传页面就空了,重启phpstudy也没用。
pass-17
这关我用前面的图片马上传成功了,但是到文件包含的时候就失败了,然后检查了一下upload文件夹里面的文件,发现图片尾部的php代码没有,提示是对文件进行了渲染,参考了一下其他师傅的文章,对于这种二次渲染的绕过我们只需要找到在16进制中渲染前后没有变化的文件位置,然后将php代码写在这个位置,就能成功上传了。