The project is a python library that automate the process of prepareing the testing enviroment on alicloud and preform BAS. In a nutshell, the project is built with three parts:
- Terraform: To create the testing enviroment
- Ansible: To deploy services on vms and prepare for BAS
- Caldera, Atomic Red Team, PurpleSharp, OpenBAS: To preform BAS
Everything you need is in 'requirements.txt', including terraform, ansible and alicloud python sdk. To install dependency:
pip install -r requirements.txt
After the installation, initialize terraform with:
terraform init
In project directory, create a '.env' file and define enviroment variables.
For exemple:
ALICLOUD_ACCESS_KEY="your_access_key_here"
ALICLOUD_SECRET_KEY="your_secret_key_here"
ALICLOUD_REGION="cn-beijing"You can also export these enviroment variables directly in system.
With the power of terraform and alcloud open api encapsulate in this project, you can easily create and manage instances with your own script.
With ansible, you can automaticly deploy services and configure the machines you created and launch attack remotely.
The repo comes with a demo of how you can make use of this project.
You can deploy a testing enviroment of 8 machines with following file and directory:
- ./terraform
This folder contains terraform config files pre-generated by this project. - ./ansible
This folder contains ansible playbooks of 8 machines and some application install package. - deploy.py
This is a script to run so that we can create the enviroment hands free.
The demo is made of 8 machines:
| Hostname | OS | IP | service | log |
|---|---|---|---|---|
| SPLUNK01 | Ubuntu 20.04 | 172.16.9.109 | Splunk Enterprise | |
| k8s-node1 | Ubuntu 20.04 | 172.16.0.108 | ||
| k8s-master | Ubuntu 20.04 | 172.16.0.107 | Audit Kubernetes |
audit.log access.log |
| proxy | CentOS 7 | 172.16.0.106 | Audit squid |
audit.log squid access log |
| SUSE | Ubuntu 20.04 | 172.16.0.105 | SpringBoot nginx audit |
audit.log access.log |
| WEB02-TEST-LAB | Windows Server 2019 | 172.16.0.103 | IIS SEP |
Windows event log SEP log |
| DC01-TEST_LAB | Windows Server 2022 | 172.16.0.102 | Domain controller sysmon |
Windows event log |
| Web01 | Ubuntu 20.04 | 172.16.0.101 | Atomic Red Team PurpleSharp Caldera |
Attack log |
To create and deploy services on all 8 machines, run:
python3 deploy.py
Perform Attack Simulations with Atomic Red Team:
python3 attack.py simulate -t instance_DC01-TEST-LAB -te T1218.010-1
-t flag indicates the target to attack
-te flag indicates the technique to use. In this case T1218.010-1, which is Regsvr32 local COM scriptlet execution.
python3 attack.py show -t instance_DC01-TEST-LAB -te T1218.010
You will see an ouput like this:
ok: [instance_DC01-TEST-LAB] => {
"output_art.stdout_lines": [
"PathToAtomicsFolder = C:\\AtomicRedTeam\\atomics",
"",
"T1218.010-1 Regsvr32 local COM scriptlet execution",
"T1218.010-2 Regsvr32 remote COM scriptlet execution",
"T1218.010-3 Regsvr32 local DLL execution",
"T1218.010-4 Regsvr32 Registering Non DLL",
"T1218.010-5 Regsvr32 Silent DLL Install Call DllRegisterServer"
]
}
Use the -v flag to increase verbosity
python3 attack.py show -t instance_DC01-TEST-LAB -te T1218.010-1 -v
Navigate to https://github.com/redcanaryco/atomic-red-team/tree/master/atomics for more details about techniques.
Navigate to splunk http://172.16.0.109:8000/
Search index="attack"
You can get the process id of the actual payload which is 980.
Search index="sysmon" | search "980"
We can see the payload actually being executed is RegSvr32.sct. We can modify this payload to do more proxy execution test with regsvr32.
login to any windows host with RDP.
Open up a web browser and access http://172.16.0.101:8888
Find your login credentials in playbook_web01.yml
Login credentials are predefined in caldera installation package located in ansible/resource/caldera.tar.gz Change the local.conf file to modify the password for red and blue team.
Click agents to see available targets
Refer to https://caldera.readthedocs.io/en/latest/Getting-started.html for further details.
The project mainly contains 5 py files:
- alicloud_create_instance.py
- alicloud_instance_utils.py
- alicloud_vpc_utils.py
- ansible_utils.py
- attack.py
The 'enable_winrm.ps1' file is mandatory for creating windows server. By default winrm do not allow password authentification. This blocks our process of automation. This scipt will be injected during the creation of Windows machine which solve our problem.
This file contains functions that generate terraform configuration file and create alicloud instance. Below are some exemples.
alicloud_create_instance():
This function receives a dictionary of configurations, generates a '.tf' file and creates an alicloud instance. After the creation, the '.tf' file will be renamed to '.conf' file. To reuse the terraform conf file, rename it back to '.tf'.
Exemple:
from alicloud_create_instance import alicloud_create_instance
instance_WIN10_TEST_LAB={"resource_name" : "WIN10-TEST-LAB",
"instance_name" : "WIN10-TEST-LAB",
"host_name":"WIN10-TEST-LAB",
"password":"passwordhere",
"stopped_mode":"StopCharging",
"private_ip" : "172.16.0.104",
"security_groups" : ['sg-2ze5noqezzz0b8u65lqa'],
"availability_zone":"cn-beijing-h",
"instance_type":"ecs.e-c1m1.large",
"system_disk_category":"cloud_essd",
"system_disk_size":40,
"image_id":"win2022_21H2_x64_dtc_zh-cn_40G_alibase_20240617.vhd",
"vswitch_id":"vsw-2zefw69ghh41kohj34fh0",
"internet_max_bandwidth_out":1,
"internet_charge_type":"PayByBandwidth",
"instance_charge_type":"PostPaid",
"resource_group_id":"rg-aekz2lelokfmihq"}
alicloud_create_instance(instance_WIN10_TEST_LAB)alicloud_create_multi_instances():
This function receives a list of dict contains configurations, generates a '.tf' file and creates multiple alicloud instances.After the creation, the '.tf' file will be renamed to '.conf' file. To reuse the terraform conf file, rename it back to '.tf'.
Exemple:
from alicloud_create_instance import alicloud_create_multi_instances
instance_test_list=[]
instance_test_list.append(instance_WEB01)
instance_test_list.append(instance_WIN10_TEST_LAB)
alicloud_create_multi_instances(instance_test_list)generate_tf_file():
This functon generates configuration file for terraform in order to create alicloud instance.
from alicloud_create_instance import generate_tf_file
generate_tf_file(instance_WIN10_TEST_LAB)alicloud_apply():
This funtion finds all '.tf' files in current directory and apply them to creates instances.
Exemple:
from alicloud_create_instance import alicloud_apply
alicloud_apply()This file contains functions that encapsulate alicloud openAPI in order to prefrom read, update and delete of instances. Below are some exemples.
list_instances():
This function search for ECS instances matching the arguments, and return their id and ip in a list.
Exemple:
from alicloud_instance_utils import list_instances
list=list_instances("cn-beijing",vsw_id="vsw-2zefw69ghh41kohj34fh0",security_group_id="sg-2ze5noqezzz0b8u65lqa")
for i in list:
print(i)Output:
['i-2zehme9g0gek73ryb4sj', '172.16.0.102']
['i-2zeduokzsdvowtgvlx5u', '172.16.0.108']
['i-2zedomffvxtu3colbafi', '172.16.0.109']
['i-2ze230an0f6y091cf2jp', '172.16.0.103']
['i-2zebezbcmezy6ew4b91i', '172.16.0.107']
['i-2ze079t0frtfri1xtxky', '172.16.0.106']
['i-2zedlsx60tylxn1pbxtj', '172.16.0.105']
['i-2ze6g2qb9eo6s7ilbodg', '172.16.0.174']
show_instances():
This function prints info of all instances matching the arguments.
Exemple:
from alicloud_instance_utils import show_instances
show_instances("cn-beijing")Output:
Instance_name = DC01-TEST-LAB
Instance_id = i-2zehme9g0gek73ryb4sj
Instance_type = ecs.e-c1m1.large
Private_ip_addr = 172.16.0.102
Public_ip_addr = 60.205.224.21
Zone_id = cn-beijing-h
Region_id = cn-beijing
Security_group = sg-2ze5noqezzz0b8u65lqa
Creation_time = 2024-07-30T05:15Z
Serial_number = 3be9a7af-35a3-4283-b5b9-cbfaabcb9d04
Status = Running
Description = {}
OS_name = Windows Server 2022 DataCenter Edition 64bit English Edition
OS_type = windows
CPU = 2
Memory = 2G
destroy_instances():
This function deletes a list of instances.
Exemple:
from alicloud_instance_utils import destroy_instances
destroy_instances(region_id="cn-beijing",instance_ids=['i-2ze6zjac7nxfj46tzs13'])Output:
Delete Success
start_instances(), stop_instances(), reboot_instances():
This function starts/stops/reboots a instance or mutiple instances.
Exemple:
from alicloud_instance_utils import start_instances, stop_instances, reboot_instances
start_instances(region_id="cn-beijing", instance_ids=["i-2ze1aelwkogl3au8xe2k","i-2zeddnxlqffapoxxhksn"])
response=stop_instances(region_id="cn-beijing", instance_ids=["i-2zecr563trog7724w2vk","i-2ze4hma0u1n43s0xnzxo"])
print(response)
response=reboot_instances(region_id="cn-beijing", instance_ids=["i-2ze1aelwkogl3au8xe2k","i-2zeddnxlqffapoxxhksn"])
print(response)refresh_instance_list_csv():
This function campares the 'instance_list.csv' file with alicloud. If an instance no longer exist in alicloud, the function will remove its record in intance_list.csv.
If intance id of localhost machine is not in 'instance_list.csv', this function will append it to the end of the file.
Exemple:
from alicloud_instance_utils import refresh_instance_list_csv
refresh_instance_list_csv(region_id="cn-beijing")find_my_instance_id():
This function detect localhost's ip and search for it's alicloud Instance id.
Exemple:
from alicloud_instance_utils import find_my_instance_id
my_instance=find_my_instance_id("cn-beijing")
print(my_instance)Outout:
['i-2ze6g2qb9eo6s7ilbodg', '172.16.0.174']
check_image_id():
This function return a list of available image ids. If image_id is specified, the function returns the OS type of that image.
Exemple:
from alicloud_instance_utils import check_image_id
image_list=check_image_id(region_id="cn-beijing",OSType="linux",Architecture="x86_64")
for i in image_list:
if "ubuntu" in i[0]:
print(i)Output:
['ubuntu_22_04_x64_20G_alibase_20240710.vhd', 'ubuntu_22_04_x64_20G_alibase_20240710.vhd', 'v2024.7.11', 'Available']
['ubuntu_20_04_x64_20G_alibase_20240630.vhd', 'ubuntu_20_04_x64_20G_alibase_20240630.vhd', 'v2024.7.1', 'Available']
['ubuntu_24_04_x64_20G_alibase_20240508.vhd', 'ubuntu_24_04_x64_20G_alibase_20240508.vhd', 'v2024.5.9', 'Available']
['ubuntu_18_04_x64_20G_alibase_20240223.vhd', 'ubuntu_18_04_x64_20G_alibase_20240223.vhd', 'v2024.2.23', 'Available']
['ubuntu_22_04_uefi_x64_20G_alibase_20230515.vhd', 'ubuntu_22_04_uefi_x64_20G_alibase_20230515.vhd', '', 'Available']
['ubuntu_16_04_x64_20G_alibase_20221227.vhd', 'ubuntu_16_04_x64_20G_alibase_20221227.vhd', '', 'Available']
['ubuntu_18_04_uefi_x64_20G_alibase_20220330.vhd', 'ubuntu_18_04_uefi_x64_20G_alibase_20220330.vhd', '', 'Available']
['ubuntu_20_04_uefi_x64_20G_alibase_20220324.vhd', 'ubuntu_20_04_uefi_x64_20G_alibase_20220324.vhd', '', 'Available']
['ubuntu_20_04_amd_x64_20G_alibase_20200820.vhd', 'ubuntu_20_04_amd_x64_20G_alibase_20200820.vhd', '', 'Available']
['ubuntu_18_04_amd_x64_20G_alibase_20200804.vhd', 'ubuntu_18_04_amd_x64_20G_alibase_20200804.vhd', '', 'Available']
['ubuntu_14_0405_64_20G_alibase_20170824.vhd', 'ubuntu_14_0405_64_20G_alibase_20170824.vhd', '', 'Available']
Exemple:
print(check_image_id(region_id="cn-beijing",image_id="ubuntu_20_04_x64_20G_alibase_20240630.vhd"))Output:
linux
This file contains functions that encapsulate alicloud openAPI. The difference is it is using alicloud VPC api. There are two useful functions:
check_ip():
This function checks if an IP address can be allocated and return bool.
Exemple:
from alicloud_vpc_utils import list_available_region, check_ip
print(check_ip(ip_addr="172.16.0.174",vsw_id="vsw-2zefw69ghh41kohj34fh0",region_id="cn-beijing"))
print(check_ip(ip_addr="172.16.0.120",vsw_id="vsw-2zefw69ghh41kohj34fh0",region_id="cn-beijing"))Output:
False
True
list_available_region():
This function list all available region
print(list_available_region())Output:
['cn-qingdao', 'cn-beijing', 'cn-zhangjiakou', 'cn-huhehaote', 'cn-wulanchabu', 'cn-hangzhou', 'cn-shanghai', 'cn-nanjing', 'cn-shenzhen', 'cn-guangzhou', 'cn-hongkong', 'ap-northeast-1', 'ap-southeast-1', 'ap-southeast-2', 'ap-southeast-3', 'ap-southeast-5', 'ap-south-1', 'us-east-1', 'us-west-1', 'me-east-1', 'eu-central-1', 'me-central-1', 'ap-southeast-6', 'cn-wuhan-lr', 'cn-fuzhou', 'cn-chengdu', 'eu-west-1', 'ap-southeast-7', 'cn-heyuan', 'ap-northeast-2']
This file contains one single function that can generate a ansible configuration file 'ansible.cfg' and a ansible inventory file 'inventory.ini' based on 'instance_list.csv'
The file 'instance_list.csv' is generated by alicloud_apply() function. Each time we successfully create a instance, the basic information of that instance will be append to 'instance_list.csv'.
Exemple of 'instance_list.csv':
alicloud_instance.local_host,i-2ze6g2qb9eo6s7ilbodg
alicloud_instance.SPLUNK01,i-2zedomffvxtu3colbafi,172.16.0.109,60.205.138.130,cn-beijing,linux,passwordhere
alicloud_instance.SUSE,i-2zedlsx60tylxn1pbxtj,172.16.0.105,47.93.241.113,cn-beijing,linux,passwordhere
alicloud_instance.instance_DC01-TEST-LAB,i-2zehme9g0gek73ryb4sj,172.16.0.102,60.205.226.27,cn-beijing,windows,passwordhere
alicloud_instance.instance_WEB02-TEST-LAB,i-2ze230an0f6y091cf2jp,172.16.0.103,123.56.2.159,cn-beijing,windows,passwordhere
alicloud_instance.k8s-master,i-2zebezbcmezy6ew4b91i,172.16.0.107,39.105.203.236,cn-beijing,linux,passwordhere
alicloud_instance.k8s-node1,i-2zeduokzsdvowtgvlx5u,172.16.0.108,39.105.198.250,cn-beijing,linux,passwordhere
alicloud_instance.proxy,i-2ze079t0frtfri1xtxky,172.16.0.106,60.205.181.229,cn-beijing,linux,passwordhereThe colomns are
| resource name | instance id | private ip | public ip | region id | os | password |
|---|
Do not edit this file manuly!
ansible_init():
This funtion generates configuration file and inventory file for ansible.
To generate inventory file, the function needs to read 'instance_list.csv', which is generated by alicloud_apply() function in 'alicloud_create_instance.py'.
Exemple:
from ansible_utils import ansible_init
ansible_init()Outcome:
Exemple of 'ansible.cfg'
[defaults]
inventory=./inventory.ini
inventory_plugins=~/.ansible/plugins/inventory:/usr/share/ansible/plugins/inventory
host_key_checking = False
[inventory]
enable_plugins=host_list, script, auto, yaml, ini, tomlExemple of 'inventory.ini':
SPLUNK01 ansible_host=172.16.0.109 ansible_user=root ansible_password=passwordhere ansible_connection=ssh
SUSE ansible_host=172.16.0.105 ansible_user=root ansible_password=passwordhere ansible_connection=ssh
instance_DC01-TEST-LAB ansible_host=172.16.0.102 ansible_user=administrator ansible_password=passwordhere ansible_connection=winrm ansible_port=5985 ansible_winrm_server_cert_validation=ignore
instance_WEB02-TEST-LAB ansible_host=172.16.0.103 ansible_user=administrator ansible_password=passwordhere ansible_connection=winrm ansible_port=5985 ansible_winrm_server_cert_validation=ignore
k8s-master ansible_host=172.16.0.107 ansible_user=root ansible_password=passwordhere ansible_connection=ssh
k8s-node1 ansible_host=172.16.0.108 ansible_user=root ansible_password=passwordhere ansible_connection=ssh
proxy ansible_host=172.16.0.106 ansible_user=root ansible_password=passwordhere ansible_connection=ssh Use this script to perform Attack Simulations with Atomic Red Team or PurpleSharp. Usage:
python3 attack.py -h
output:
usage: attack.py [-h] {simulate,list,show} ...
Use `attack.py action -h` to get help with any attack action
optional arguments:
-h, --help show this help message and exit
attack actions:
{simulate,list,show}
simulate simulates attack techniques
list list available targets
show Show available attack techniques on a given targets
- Use
simulateflag to simulate a attack
usage: attack.py simulate [-h] [-e ENGINE] -t TARGET [-te TECHNIQUE]
optional arguments:
-h, --help show this help message and exit
-e ENGINE, --engine ENGINE
simulation engine to use. Available options are: PurpleSharp and ART (default)
-t TARGET, --target TARGET
target for attack simulation. Use the hostname in inventory.ini
-te TECHNIQUE, --technique TECHNIQUE
comma delimited list of MITRE ATT&CK technique ID to simulate, example: T1117, T1118
- Use
listflag to list available target - Use
showflag to show technique detail on a given host
usage: attack.py show [-h] [-e ENGINE] -t TARGET [-v] [-te TECHNIQUE]
optional arguments:
-h, --help show this help message and exit
-e ENGINE, --engine ENGINE
simulation engine to use. Available options are: PurpleSharp and ART (default)
-t TARGET, --target TARGET
target name. Use the hostname in inventory.ini
-v, --verbose show technique detail
-te TECHNIQUE, --technique TECHNIQUE
MITRE ATT&CK technique ID to show info, example: T1117, T1118