
CowCloud was originally created to run recon tools and vulnerability scans in a distributed way; for example, one use case might be by bug bounty hunters. This solution is intended to abstract end users from the underlying work required to distribute workloads in AWS. CowCloud provides users with a friendly web interface to view and create new tasks that later on are consumed by Python code running on worker nodes (EC2 instances). It is intended that the Python code will be customised as well as the EC2 AMIs.
As an example, let’s say you want to run Nmap scans. In that case, you can simply pick an AMI from the AMI Catalog and update the field image_id in Terraform/ec2_module/ec2_module.tf. Then, the file ec2py/template.py would have to be updated to customize the arguments for the Nmap scan (-Pn, -p 443, etc). Lastly, the user_data field in the Terraform/ec2_module/ec2_module.tf configuration file would have to be updated to install Nmap and its dependencies.
Another option is to install and run several commercial tools, in that case, you might want to create your own EC2 instance or snapshot. In this case you would install all the dependencies and activate the licences so you could use this AMI as the gold image for your workers

CowCloud can be broken down into three main components:
These are the key features:
autoscalingStrategy.py)retention_time expiresextra_docker_params in the file (this is explained in the Administrator/maintainer section below)
As a result of executing the Terraform, a new file is created (config.js);, this contains the configuration required for the React JS app to authenticate against the Cognito user pool directory. After the infrastructure has been deployed, you have to build the React app and upload the folder build. In addition, you have to upload the Python code to an S3 bucket that acts as a code repository. This process has been automated in two scripts setup.bat and setup.sh so you don't have to worry about this, this is just to summarize this stage.
The infrastructure is deployed in the us-east-1 region by default, although this can be changed in the locals.tf file within the Terraform folder.
Steps:
variables.tf; the ami variable has to point to an existing EC2 AMI, which could be your golden AMI or one from the EC2 Catalogaws configure. Check you have configured it properly by running this command: aws sts get-caller-identity; when correctly configured this should not return an erroraws ec2 create-key-pair –key-name cowCloud –query “cowCloud” –output text > ec2_module/cowCloud.pemgit clone [email protected]:nccgroup/cowcloud.git
# Deploy the infra
cd cowcloud
cd Terraform
terraform init
terraform plan
terraform apply --auto-approve
Now you are ready to go! Sign up, sign in and create a new task!
Once everything is deployed and the front-end is accessible, you should follow these steps:
CowCloud\ec2py> python .\decypt_file.py 2e8cf87c-5389-11ec-abec-d6d1f378b18d
The person in charge of deploying the infrastructure and maintaining it has to properly sanitise and validate the end-user inputs supplied through the web app. In other words, ensure that the code in ec2py/template.py is not vulnerable to OS command injection.
This point is highlighted as this is the most critical aspect of the system. Special care has been taken to limit the scope of the worker’s permissions and exposure and so reduce the associated risks. Nevertheless, it is the admin’s responsibility to take care of this aspect of system security.
The role policies attached to the EC2 instances profile are listed in the readme.md file inside the Terraform folder
workers_manager.py that is called by the ec2py tool to perform more privileged actions. These actions were moved to a Lambda function to limit the risk in the event that someone compromised the access key of the role attached to the EC2 profile. It works with IMDSv2 nonetheless.
The role policies attached to the Lambda function workers_manager.py are listed in the readme.md file inside the Terraform folderIf you want to capture the stdout and show it through the web interface while the tasks is being executed, then go to the ec2py/template.py and follow these steps::
extra_docker_params variable includes the information required for your Docker containers to send the stdout to CloudWatch log groups. You will need to include this variable in the command line when you want to view the stdout through the front-end.cmd = f"docker run {extra_docker_params} --rm -v {tmp_folder}target.txt:/root/Tools/reconftw/target.txt -v {tmp_folder}reconftw.cfg:/root/Tools/reconftw/reconftw.cfg -v {tmp_folder}Recon/:/root/Tools/reconftw/Recon/ six2dez/reconftw:main -l target.txt -w".split(' ')
You can destroy the infrastructure by running this simple command: terraform destroy --auto-approve this will remove all the existing resources.
Note: don't interrupt this process as this could leave some elements lingering in the cloud which you would then have to identify and remove manually.


terraform destroy --auto-approve -target module.gateway_module.aws_api_gateway_deployment.lambdaterraform apply --auto-approve -target module.gateway_moduletemplate.py| variable | default value | description |
|---|
eipenable | false | If true, the solution allocates a pool of elastic IP addresses associated with the worker nodes as they are spun up. The number of EIP to reserve is worked out using this formulasum([var.max_workers, var.maximum_number_of_terminating_machines]) |
cidr_whitelist | [] | The CIDR whitelist to allow only certain IP ranges in the firewall. E.g. ["195.95.131.0/24"] |
max_workers and max_queued_tasks_per_worker | max_workers: 3, max_queued_tasks_per_worker: 10 | These two settings determine when to scale in or scale out, e.g. max_workers 3, max_queued_tasks_per_worker 10. This means if the number of tasks overpasses ten, a new EC2 instance will be created. If there are more than twenty tasks, a maximum of three EC2 instances will be available to distribute the workloads (check out algorithm present in this script Terraform/dynamodb_module/autoscalingTool/autoscalingStrategy.py). |
maximum_number_of_terminating_machines | 2 | This defines the number of instances that are set to terminate but are on hold until the process/scan completes the task. |
heartbeat_timeout | 900 | This defines the time that those workers are on hold. After this time expires, the worker will be forcibly terminated. |
instance_type | t2.micro | https://aws.amazon.com/ec2/instance-types/ |
ami | null | https://aws.amazon.com/es/amazon-linux-ami/ |
retention_time | 7 | Set the retention time (days) for logs and the expiration of the archive table items (completed tasks). |