上传漏洞现在很难会出现的,更别说强大的pw了,所以很多朋友是不是认为我这个标题唬人了?不过还确实是上传漏洞,不过呢,这个漏洞的利用需要两个条件,所以说其实很鸡肋,但之前还是蛮好用的,只要满足条件,屡试不爽的。好了,先说条件:
1.必须存在注入,可以注入出$db_siteid,因为前面那里发布的注入(以及其他某些地方的注入),可以轻松得到;
2.必须是IIS6,这个是致命的鸡肋点,漏洞利用的是IIS6的文件解析漏洞(其实不用想也知道,无论dz、pw或者其他cms不会有允许上传php之类后缀文件的)。

由于官方已经在我上报不久一起补丁了,所以我相信应该有人已经通过分析补丁知道漏洞在哪儿了,好了,先看代码(文件是job.php,也很可能在其他可上传的文件中):

...

} elseif ($action == uploadicon) {

    if (empty($_GET[step])) {

        list($db_upload,$db_imglen,$db_imgwidth,$db_imgsize) = explode(" ",$db_upload);
        InitGP(array(uid,verify));//可以控制的两个参数
        $swfhash = GetVerify($uid);
        checkVerify(swfhash);//这里很有趣

        require_once(R_P . lib/upload/faceupload.class.php);
        $face = new FaceUpload($uid);
        PwUpload::upload($face);
        $uploaddb = $face->getAttachs();

        echo $db_bbsurl./.$attachpath./.$uploaddb[fileuploadurl].?.$timestamp;exit;

    } else {

...

先来看看代码中我标注的有趣的地方,看能否绕过checkVerify(swfhash)。找找checkVerify函数:

function checkVerify($hash = verifyhash) {
    GetGP(verify) <> $GLOBALS[$hash] && Showmsg(illegal_request);//看参数是啥了
}

于是checkVerify(swfhash)其实就是检查$swfhash了,而$swfhash是通过GetVerify函数获得的,于是看看GetVerify函数:

function GetVerify($str,$app = null) {
    empty($app) && $app = $GLOBALS[db_siteid];//关键就是db_siteid了,而db_siteid可以通过注入获得
    return substr(md5($str.$app.$GLOBALS[pwServer][HTTP_USER_AGENT]),8,8);
}

于是好办了,先通过注入获得db_siteid,然后获取自己的HTTP_USER_AGENT(直接构造也行),可以轻松绕过前面的限制,接着就直接看上传类了,$uid可以控制就可以自定义上传文件名了:

<?php
!defined(P_W) && exit(Forbidden);

require_once(
R_P lib/upload.class.php);

class 
FaceUpload extends uploadBehavior {
    
    var 
$db;
    var 
$uid;
    var 
$attachs;

    function 
FaceUpload($uid) {
        global 
$db,$db_imgsize;
        
parent::uploadBehavior();
        
$this->uid $uid;//这里没有int就悲剧了...
        
$this->db =& $db;
        
$this->ifftp 0;
        
        !
$db_imgsize && $db_imgsize 1000;
        
$this->ftype = array(
            
gif  => $db_imgsize,                jpg  => $db_imgsize,
            
jpeg => $db_imgsize,                bmp