ThinkSAAS 最新版SQL注入之二

2014-02-20T00:00:00
ID SSV:94341
Type seebug
Reporter Root
Modified 2014-02-20T00:00:00

Description

简要描述:

ThinkSAAS 最新版2.1,官方2月15日更新,SQL注入第二弹

详细说明:

上传资料处/app/attach/action/upload.php:

``` case "do": $userid = intval($_GET['userid']); $albumid = intval($_GET['albumid']); if($userid=='0' || $albumid == 0){ echo '00000'; exit; }

    $attachid = $new['attach']->create('attach',array(
        'userid'    => $userid,
        'locationid'=>aac('user')->getLocationId($userid),
        'albumid'=>$albumid,
        'addtime'   => date('Y-m-d H:i:s'),
    ));

    //上传
    $arrUpload = tsUpload($_FILES['Filedata'],$attachid,'attach',array('pptx','docx','pdf','jpg','gif','png','rar','zip','doc','ppt','txt'));

    if($arrUpload){
        $new['attach']->update('attach',array(
            'attachid'=>$attachid,
        ),array(
            'attachname'=>$arrUpload['name'],
            'attachtype'=>$arrUpload['type'],
            'attachurl'=>$arrUpload['url'],
            'attachsize'=>$arrUpload['size'],
        ));

        //对积分进行处理
        aac('user')->doScore($app,$ac,$ts,$userid);


    }
    echo $attachid;
    break;

```

然后使用tsUpload函数对文件进行上传。$_FILES['Filedata']是上传表单的名字。

``` function tsUpload($files, $projectid, $dir, $uptypes) { if ($files ['size'] > 0) {

    $menu2 = intval ( $projectid / 1000 );

    $menu1 = intval ( $menu2 / 1000 );

    $path = $menu1 . '/' . $menu2;

    $dest_dir = 'uploadfile/' . $dir . '/' . $path;

    createFolders ( $dest_dir );

    //$ext = pathinfo($files['name'],PATHINFO_EXTENSION);

    $arrType = explode ( '.', strtolower ( $files ['name'] ) ); // 转小写一下

    $type = array_pop ( $arrType );

    if (in_array ( $type, $uptypes )) {

        $name = $projectid . '.' . $type;

        $dest = $dest_dir . '/' . $name;

        // 先删除
        unlink ( $dest );
        // 后上传
        move_uploaded_file ( $files ['tmp_name'], mb_convert_encoding ( $dest, "gb2312", "UTF-8" ) );

        chmod ( $dest, 0777 );

        $filesize = filesize ( $dest );
        if (intval ( $filesize ) > 0) {
            return array (
                    'name' => tsFilter($files ['name']),
                    'path' => $path,
                    'url' => $path . '/' . $name,
                    'type' => $type,
                    'size' => $files ['size'] 
            );
        } else {
            return false;
        }
    } else {
        return false;
    }
}

} ```

有一个过滤的函数tsFilter:

``` function tsFilter($value){ $value = trim($value); //定义不允许提交的SQl命令和关键字 $words = array(); $words[] = "add "; $words[] = "and "; $words[] = "count "; $words[] = "order "; $words[] = "table "; $words[] = "by "; $words[] = "create "; $words[] = "delete "; $words[] = "drop "; $words[] = "from "; $words[] = "grant "; $words[] = "insert "; $words[] = "select "; $words[] = "truncate "; $words[] = "update "; $words[] = "use "; $words[] = "--"; $words[] = "#"; $words[] = "group_concat"; $words[] = "column_name"; $words[] = "information_schema.columns"; $words[] = "table_schema"; $words[] = "union "; $words[] = "where "; $words[] = "alert"; $value = strtolower($value);//转换为小写 foreach($words as $word){ if(strstr($value,$word)){ $value = str_replace($word,'',$value); } }

return $value;

} ```

过滤了关键字及注释符号。 可是仔细一看,过滤的是类似“select ”这种,关键字后面加了个空格。 但是我们可以用制表符,它能完美代替空格。 我们来看看update函数:

public function update($table, $conditions, $row) { $where = ""; if (empty ( $row )) return FALSE; if (is_array ( $conditions )) { $join = array (); foreach ( $conditions as $key => $condition ) { $condition = $this->escape ( $condition ); $join [] = "{$key} = {$condition}"; } $where = "WHERE " . join ( " AND ", $join ); } else { if (null != $conditions) $where = "WHERE " . $conditions; } foreach ( $row as $key => $value ) { $vals [] = "`$key` = '$value'"; } $values = join ( ", ", $vals ); $sql = "UPDATE " . dbprefix . "{$table} SET {$values} {$where}"; return $this->db->query ( $sql ); }

在conditions处做了处理,但是我们这是在row中,没有处理,导致SQL注入。

漏洞证明:

保证最新版:

<img src="https://images.seebug.org/upload/201402/200949052d2dbba40648649bb750ef6c798655e0.png" alt="0.png" width="600" onerror="javascript:errimg(this);">

发送下面的请求:

<img src="https://images.seebug.org/upload/201402/200949288436360c6bc9230be940113fe4f6d4d2.png" alt="1.png" width="600" onerror="javascript:errimg(this);">

这个cms还有一个特点,它不会显示mysql错误,但会把错误保存在/logs/文件夹里,名字就是日期+-mysql-error.txt。这样,我们就可以看到mysql的报错信息,从而爆出得到管理员账号密码。

<img src="https://images.seebug.org/upload/201402/20095034ad31a43beb2cc02251b0f87ecf112225.png" alt="2.png" width="600" onerror="javascript:errimg(this);">