upload-labs (pass1-21)

目录

  • Pass-1(前端验证)(php5.2)
  • Pass-2(MIME验证)
  • Pass-3(黑名单验证,特殊后缀)
  • Pass-4
  • Pass-5(黑名单验证,`.user.ini.`)(php5.3、php5.4.45 NTS)
  • Pass-06(黑名单验证,大小写绕过)
  • Pass-07(黑名单验证,空格绕过)
  • Pass-08(黑名单验证,点号绕过)
  • Pass-09(黑名单验证,特殊字符::$DATA绕过)
  • Pass-10(黑名单)
  • Pass-11(黑名单验证,双写绕过)
  • Pass-12(get00截断)
  • Pass-13(post 00截断)
  • Pass-14(图片马unpack)
  • Pass-15(getimagesize图片马)
  • Pass-16(exif_imagetype图片马)
  • Pass-17(二次渲染绕过)
  • Pass-18(条件竞争一)
  • Pass-19(条件竞争二)
  • Pass-20
  • Pass-21(CTF题,代码审计,数组绕过)

Pass-1(前端验证)(php5.2)

  • 1、上传木马文件upload-labs (pass1-21)_第1张图片
    发现只能上传指定格式
  • 2、源代码
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;
} } 
  • 3、方法一:通过断点修改源代码白名单upload-labs (pass1-21)_第2张图片
    修改代码白名单,上传silic.php木马文件
    upload-labs (pass1-21)_第3张图片
    看到图片表示上传成功,右击图片复制图片地址,在新窗口打开
    upload-labs (pass1-21)_第4张图片
    密码为Silicupload-labs (pass1-21)_第5张图片
    现在就可以为所欲为了。

  • 4、方法二:删除前端调用checkFile()函数的语句upload-labs (pass1-21)_第6张图片

  • 5、方法三:禁用浏览器JS功能

  • 在这里插入图片描述

工具

  1. 冰蝎(Behinder)(php5.4)
    server文件夹里面是冰蝎的木马文件
    upload-labs (pass1-21)_第7张图片
    默认密码为rebeyond
    upload-labs (pass1-21)_第8张图片
    连接成功upload-labs (pass1-21)_第9张图片

  2. 哥斯拉(Godzilla)
    1、生产shell文件upload-labs (pass1-21)_第10张图片
    2、上传之后连接upload-labs (pass1-21)_第11张图片
    3、右击进入upload-labs (pass1-21)_第12张图片然后就可以为所欲为了upload-labs (pass1-21)_第13张图片

Pass-2(MIME验证)

  • 1、查看代码
$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.'文件夹不存在,请手工创建!';
	}
}

发现对上传文件的type有格式限制

  • 2、抓包修改typeupload-labs (pass1-21)_第14张图片
    修改Content-Type:字段为白名单中任一个格式,HTML返回shell文件路径

Pass-3(黑名单验证,特殊后缀)

$is_upload = false;
$msg = null;
if (isset($_POST['submit'])) {
if (file_exists(UPLOAD_PATH)) {
$deny_ext = array('.asp','.aspx','.php','.jsp'); //过滤:.asp/.aspx/.php/.jsp文件
//PHP常见的文件格式:php php3 php4 php5 php7 phpt phps phtml等
$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); //收尾去空
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 . '文件夹不存在,请手工创建!';
} }

分析代码,进行黑名单验证,但是黑名单不全,可以使用php3、php5、phtml等等绕过
但是因为靶场是用phpstudy环境搭建的,要进去修改一下配置文件
upload-labs (pass1-21)_第15张图片
修改为AddType application/x-httpd-php .php .phtml .php5 .php3 .php7

Pass-4

  • 1、查看代码
$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); //收尾去空
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 . '文件夹不存在,请手工创建!';
} }

发现这里过滤了所有常见的php文件格式,但是发下有一个文件是没有过滤:.htaccess

  • .htaccess基础知识
    .htaccess文件(或者”分布式配置文件”),全称是Hypertext Access(超文本入口)。提供了针对目录改变配置的方法, 即,在一个特定的文档目录中放置一个包含一个或多个指令的文件, 以作用于此目录及其所有子目录。作为用户,所能使用的命令受到限制。管理员可以通过Apache的AllowOverride指令来设置。
    启用.htaccess,需要修改httpd.conf,启用AllowOverride,并可以用AllowOverride限制特定命令的使用。如果需要使用.htaccess以外的其他文件名,可以用AccessFileName指令来改变。例如,需要使用.config ,则可以在服务器配置文件中按以下方法配置:AccessFileName .config 。它里面有这样一段代码:AllowOverride None,如果我们把None改成All
  • 2、通过构造.htaccess文件(只有后缀),重新定义允许的文件(白名单),代码如下:
<FilesMatch "zdz">
SetHandler application/x-httpd-php
</FilesMatch>

upload-labs (pass1-21)_第16张图片

  • 3、创建zdz文件(这里没有后缀),这里用到phpinfo()函数测试,也可以写木马。代码:
    在这里插入图片描述

  • 4、上传成功后复制zdz文件图片链接打开upload-labs (pass1-21)_第17张图片
    成功

Pass-5(黑名单验证,.user.ini.)(php5.3、php5.4.45 NTS)

  • 1、代码:
$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",".jsp
x",".jsw",".jsv",".jspf",".jtml",".jSp",".jSpx",".jSpa",".jSw",".jSv",".jSpf",".jHtml",".asp",".aspx",".asa",".asax",".ascx",".ashx",".asmx",".cer",".aSp",".aSpx",".aSa",".aS
ax",".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); //首尾去空
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 . '文件夹不存在,请手工创建!';
} }

源码里把所有可以解析的后缀名都给写死了,包括大小写,转换,空格,还有点号,正常的php类文件上传不了了,并且拒绝上传 .htaccess 文件。
反复观察发现没有被限制的后缀名有 .php7 以及 .ini

  • 2、php.ini 是 php的配置文件,.user.ini 中的字段也会被 php 视为配置文件来处理,从而导致 php 的文件解析漏洞。
    但是想要引发 .user.ini 解析漏洞需要三个前提条件:
    § 服务器脚本语言为PHP
    § 服务器使用CGI/FastCGI模式
    § 上传目录下要有可执行的php文件

  • 3、创建一个.user.ini文件:
    在这里插入图片描述
    这里的意思是只要执行php文件就会吧zdz.txt文件包含进去

  • 4、再创建一个zdz.txt文件(只要允许上传的后缀都可以):
    在这里插入图片描述

  • 5、到了这一步与要等五分钟,或者修改配置文件:
    upload-labs (pass1-21)_第18张图片
    可以将这里的时间改为10秒
    再或者直接重启phpstudy

  • 6、测试
    因为木马是php格式,所以这里我们需要执行zdz.txt目录下任意一个php文件,它会把zdz.txt中的代码包含进去upload-labs (pass1-21)_第19张图片
    成功

Pass-06(黑名单验证,大小写绕过)

这里用大小写绕过即可
在这里插入图片描述

Pass-07(黑名单验证,空格绕过)

  • 1、上传抓包,加个空格upload-labs (pass1-21)_第20张图片
    看右边文件路径发现文件被改名了,不过不影响

  • 2、用蚁剑连接
    upload-labs (pass1-21)_第21张图片

  • 3、成功upload-labs (pass1-21)_第22张图片

Pass-08(黑名单验证,点号绕过)

这一关黑名单,没有使用deldot()过滤文件名末尾的点,可以使用文件名后加.进行绕过抓包,修改上传一句话木马文件名zdz.php.upload-labs (pass1-21)_第23张图片
其他和Pass7一样

Pass-09(黑名单验证,特殊字符::$DATA绕过)

补充知识:php在window的时候如果文件名+"::$DATA“会把::$DATA之后的数据当成文件流处理,不会检测后缀名,且保持”::$DATA"之前的文件名 他的目的就是不检查后缀名。
抓包,加::$DATAupload-labs (pass1-21)_第24张图片

其他和Pass7一样

Pass-10(黑名单)

这一关黑名单,最后上传路径直接使用文件名进行拼接,而且只对文件名进行filename=deldot(file_name=deldot(filename=deldot(file_name)操作去除文件名末尾的点,构造后缀绕过黑名单
补充知识:deldot()函数从后向前检测,当检测到末尾的第一个点时会继续它的检测,但是遇到空格会停下来

  • 1、上传zoe.php 然后用bp改后缀加点. .(点空格点)upload-labs (pass1-21)_第25张图片

  • 2、落地Windows后结尾的“.”就没了
    upload-labs (pass1-21)_第26张图片

  • 3、其他和Pass7一样

Pass-11(黑名单验证,双写绕过)

这一关黑名单,使用str_ireplace()函数寻找文件名中存在的黑名单字符串,将它替换成空(即将它删掉),可以使用双写绕过黑名单
补充知识:str_ireplace(find,replace,string,count) 函数替换字符串中的一些字符(不区分大小写)upload-labs (pass1-21)_第27张图片

其他和Pass7一样

Pass-12(get00截断)

(这一关白名单,最终文件的存放位置是以拼接的方式,可以使用%00截断,但需要php版本<5.3.4,并且magic_quotes_gpc关闭。)
原理:php的一些函数的底层是C语言,而move_uploaded_file就是其中之一,遇到0x00会截断,0x表示16进制,URL中%00解码成16
进制就是0x00。
知识补充
○ strrpos(string,find[,start]) 函数查找字符串在另一字符串中最后一次出现的位置(区分大小写)。
○ substr(string,start[,length])函数返回字符串的一部分(从start开始 [,长度为length])
magic_quotes_gpc 着重偏向数据库方面,是为了防止sql注入,但magic_quotes_gpc开启还会对$_REQUEST, G E T , _GET, GET,_POST$_COOKIE 输入的内容进行
过滤

  • 1、BP抓包,添加00截断在这里插入图片描述upload-labs (pass1-21)_第28张图片

  • 2、用蚁剑等工具连接时需要把后面的zdz.php后面多余的后缀删掉

  • 3、其他和Pass7一样

Pass-13(post 00截断)

这一关和12关相似,不同的是因为直接输入的00为十进制,POST不会对里面的数据自动解码,所以这一关实需要HEX中添加00截断。

  • 1、上传抓包
    upload-labs (pass1-21)_第29张图片
    这里的“+”是为了方便找到添加00截断的位置,二进制为2b

  • 2、修改HEX
    upload-labs (pass1-21)_第30张图片
    将这里的2b修改为00
    在这里插入图片描述

  • 3、其他和之前一样

Pass-14(图片马unpack)

代码

function getReailFileType($filename){
$file = fopen($filename, "rb");
$bin = fread($file, 2); //只读2字节 文件前两个字节为文件格式
fclose($file);
$strInfo = @unpack("C2chars", $bin); 
$typeCode = intval($strInfo['chars1'].$strInfo['chars2']); 
$fileType = ''; 
switch($typeCode){ 
case 255216: 
$fileType = 'jpg';
break;
case 13780: 
$fileType = 'png';
break; 
case 7173: 
$fileType = 'gif';
break;
default: 
$fileType = 'unknown';
} 
return $fileType;
}
$is_upload = false;
$msg = null;
if(isset($_POST['submit'])){
$temp_file = $_FILES['upload_file']['tmp_name'];
$file_type = getReailFileType($temp_file);
if($file_type == 'unknown'){
$msg = "文件未知,上传失败!";
}else{
$img_path = UPLOAD_PATH."/".rand(10, 99).date("YmdHis").".".$file_type;
if(move_uploaded_file($temp_file,$img_path)){
$is_upload = true;
} else {
$msg = "上传出错!";
} } }

这一关会读取判断上传文件的前两个字节,判断上传文件类型,并且后端会根据判断得到的文件类型重命名上传文件
使用图片马 + 文件包含 绕过

  • 1、制作图片马
    在这里插入图片描述
    拼接zdz.png和zdz.php文件——>shell.png
    在这里插入图片描述

  • 2、上传图片马

  • 3、利用文件包含漏洞,漏洞链接在这upload-labs (pass1-21)_第31张图片

  • 4、因为图片上传之后被重命名,我们复制图片链接,在蚁剑上利用文件包含漏洞:include.php?file=upload/3420210320172751.png在这里插入图片描述

  • 5、成功upload-labs (pass1-21)_第32张图片

Pass-15(getimagesize图片马)

这里换成通过使用getimagesize()检查是否为图片文件,换汤不换药,所以还是可以用Pass-14的图片马绕过,并使用文件包含
漏洞解析图片马

Pass-16(exif_imagetype图片马)

知识补充: exif_imagetype()读取一个图像的第一个字节并检查其后缀名。
返回值与getimage()函数返回的索引2相同,但是速度比getimage快得多。需要开启php_exif模块。upload-labs (pass1-21)_第33张图片

剩下和Pass-14一样

Pass-17(二次渲染绕过)

这一关对上传图片进行了判断了后缀名、content-type,以及利用imagecreatefromgif判断是否为gif图片,最后再做了一次二次
渲染,但是后端二次渲染需要找到渲染后的图片里面没有发生变化的Hex地方,添加一句话,通过文件包含漏洞执行一句话,使用
蚁剑进行连接
补充知识

  • 二次渲染:后端重写文件内容
  • basename(path[,suffix]) ,没指定suffix则返回后缀名,有则不返回指定的后缀名
  • strrchr(string,char)函数查找字符串在另一个字符串中最后一次出现的位置,并返回从该位置到字符串结尾的所有字符。
  • imagecreatefromgif():创建一块画布,并从 GIF 文件或 URL 地址载入一副图像
  • imagecreatefromjpeg():创建一块画布,并从 JPEG 文件或 URL 地址载入一副图像
  • imagecreatefrompng():创建一块画布,并从 PNG 文件或 URL 地址载入一副图像

我们可以这么做:

  • 1、上传正常的GIF图片下载回显的图片,用WinHex对比上传前后的图片hex值,将没有被渲染的部分写上一句话木马:upload-labs (pass1-21)_第34张图片

  • 2、复制图片链接,和14-16关一样,利用文件包含漏洞用蚁剑连接upload-labs (pass1-21)_第35张图片

Pass-18(条件竞争一)

  • 1、看代码
$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 = '上传出错!';
} }

从源码来看,服务器先是将上传的文件保存下来,然后将文件的后缀名同白名单对比,如果是jpg、png、gif中的一种,就将文件进行重命名。如果不符合的话,unlink()函数就会删除该文件。

  • 2、思路:代码执行的过程是需要耗费时间的。如果我们能在上传的一句话被删除之前访问不就成了。这个也就叫做条件竞争上传绕过。
  • 3、上传用来生成木马的zz.php文件,抓包
 fputs(fopen('shell.php','w'),'');?>

upload-labs (pass1-21)_第36张图片

  • 4、无限上传zz.php文件
    这里不需要替换,所以删除$$,并设置无限发送空的Payloads
    upload-labs (pass1-21)_第37张图片
    这里给他多一点线程
    upload-labs (pass1-21)_第38张图片

  • 5、同样的道理来无限访问zz.php,直到文件执行生成shell.phpupload-labs (pass1-21)_第39张图片
    这里状态200就表示访问成功,查看目录发现生成成功upload-labs (pass1-21)_第40张图片

  • 补充:这里也可以写一个python脚本用来实现一直访问zz.php,代码如下:

import requests
url = "http://xxx.xxx.xxx.xxx/upload-labs/upload/zoe.php" while True:
html = requests.get(url)
if html.status_code == 200:
print("OK")
break 当访问成功后会输出“OK”
补充:这里也可以写一个python脚本用来实现一直访问zz.php,代码如下:
import requests
url = "http://xxx.xxx.xxx.xxx/upload-labs/upload/zoe.php" while True:
html = requests.get(url)
if html.status_code == 200:
print("OK")

break 当访问成功后会输出“OK”

Pass-19(条件竞争二)

这一关作者代码写错了一个地方,文件的下载路径不是upload,这里我们修改一下upload-labs (pass1-21)_第41张图片

Pass-20

这里代码中用到move_uploaded_file()函数通过后缀黑名单对用户输入的文件名做判断,并且并没有对上传的文件做判断。
但move_uploaded_file()函数会忽略文件末尾的/.,我们可以利用这一点

  • 1、上传抓包
    upload-labs (pass1-21)_第42张图片

  • 2、加/.
    upload-labs (pass1-21)_第43张图片

  • 3、上传成功
    upload-labs (pass1-21)_第44张图片

  • 补充:其实直接在这后面加就行,而且加空格也行
    upload-labs (pass1-21)_第45张图片

Pass-21(CTF题,代码审计,数组绕过)

  • 1、代码审计
    upload-labs (pass1-21)_第46张图片

  • 补充
    explode(separator,string[,limit]) 函数,使用一个字符串分割另一个字符串,并返回由字符串组成的数组。
    end(array)函数,输出数组中的当前元素和最后一个元素的值。
    reset(array)函数,把数组的内部指针指向第一个元素,并返回这个元素的值
    count(array)函数,计算数组中的单元数目,或对象中的属性个数

  • 2、抓包修改
    我们要改的就是下面的要求:

    • 1、修改content-type
    • 2、修改POST参数为数组类型,索引[0]为’upload-20.php’,索引[2]为’jpg|png|gif’。
    • 3、只要第二个索引’不为1’, f i l e [ c o u n t ( file[count( file[count(file) - 1]就等价于$file[2-1],值为空
      upload-labs (pass1-21)_第47张图片
  • 3、连接成功upload-labs (pass1-21)_第48张图片

你可能感兴趣的:(web安全,安全)