├── .gitignore ├── .gitmodules ├── README.md ├── honeytraps ├── CHANGELOG.md ├── README.md ├── honeytrap_arch.jpg ├── misp │ ├── README.md │ ├── run_misp.sh │ ├── sample-env │ └── setup_misp.sh ├── screenshots │ ├── Screenshot from 2019-06-16 13-20-34.png │ ├── event-details.png │ ├── events.png │ ├── filebeat_index_create.png │ ├── filebeat_index_create_2.png │ ├── filebeat_logs.png │ ├── honeytrap1_bait.png │ ├── honeytrap1_logs.png │ ├── honeytrap2_bait.png │ ├── honeytrap2_bait_2.png │ ├── honeytrap2_logs.png │ ├── honeytrap3_bait.png │ ├── honeytrap3_bait_2.png │ ├── honeytrap3_logs.png │ ├── honeytrap4_bait.png │ ├── honeytrap4_bait_2.png │ ├── honeytrap4_logs.png │ ├── honeytrap5_bait.png │ ├── honeytrap5_bait_2.png │ ├── honeytrap5_logs.png │ ├── pymisp-key.png │ ├── savedObj1.png │ ├── savedObj2.png │ ├── savedObj3.png │ └── tags.png ├── waf_elk │ ├── README.md │ ├── docker-compose.yml │ ├── kibana │ │ └── export.ndjson │ ├── logstash │ │ ├── Dockerfile │ │ └── pipeline │ │ │ └── logstash.conf │ ├── misp-push │ │ ├── Dockerfile │ │ ├── Pipfile │ │ ├── Pipfile.lock │ │ ├── misp-push.py │ │ ├── sample-env │ │ └── start.sh │ ├── remoteipvis.json │ └── start_docker.sh └── waf_modsec │ ├── AWS Amazon ECS Setup for Modescurity Honeypot.md │ ├── Dockerfile │ ├── README.md │ ├── aws-ecs-container-definition.json │ ├── docker-compose.yml │ ├── example-log.json │ ├── filebeat.yml │ ├── form.html │ ├── httpd.conf │ ├── include.conf │ ├── index.html │ ├── login.html │ ├── login.php │ ├── modsec_entry.sh │ ├── modsecurity-extension.conf │ ├── preprocess-modsec-log.py │ ├── robots.txt │ └── sample-env ├── mds_elk ├── README.md ├── docker-compose.yml ├── screenshots │ ├── filebeat_index_create.png │ ├── filebeat_index_create_2.png │ └── filebeat_logs.png ├── waf_elk │ ├── Dockerfile │ ├── elk_entry.sh │ ├── filebeat_logstash.conf │ └── start.sh └── waf_modsec │ ├── Dockerfile │ ├── docker-entrypoint.sh │ ├── filebeat.yml │ ├── modsec_entry.sh │ └── modsecurity.conf ├── misp-doc ├── README.md ├── create_events.py ├── keys.py └── screenshots │ ├── misp-add-event.png │ ├── misp-add-tag-menu.png │ ├── misp-add-tag.png │ ├── misp-home.png │ ├── misp-link-tag-event.png │ ├── misp-list-events-with-tag.png │ ├── misp-list-tags.png │ ├── pymisp-event.png │ └── pymisp-key.png └── mlogc_elk ├── README.md ├── docker-compose.yml ├── elk ├── Dockerfile ├── elk_entry.sh ├── filebeat_logstash.conf └── start.sh ├── mlogc ├── 10-modsecurty.conf ├── Dockerfile ├── config │ ├── jvm.options │ ├── log4j2.properties │ ├── logstash.yml │ └── startup.options ├── httpd.conf ├── logstash.conf ├── mlogc.conf ├── mod_security.conf ├── modsec_entry.sh ├── modsecurity.conf └── start.sh └── screenshots ├── mlogc_index_create.png ├── mlogc_index_create_2.png └── mlogc_logs.png /.gitignore: -------------------------------------------------------------------------------- 1 | env 2 | .env 3 | .venv/ -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # OWASP Honeypot-Project 2 | 3 | The goal of the OWASP Honeypot Project is to identify emerging attacks against web applications and report them to the community, in order to facilitate protection against such targeted attacks. 4 | 5 | Based around the earlier OWASP/WASC Distributed Web Honeypots Project (https://github.com/SpiderLabs/owasp-distributed-web-honeypots) 6 | 7 | The primary aims of the project are 8 | 9 | * Real-time, detailed Web Application Threat Attack Data 10 | * Threat Reports to the community 11 | 12 | ## Organization of the repository 13 | 14 | This repository is organized into various directories. Below table shows the purpose of each one. 15 | 16 | | Directory | Purpose | 17 | | --- | --- | 18 | | `honeytraps` | Focuses on building honeytraps and reporting threat intelligence | 19 | | `mds_elk` | Shows a PoC for sending the ModSecurity Audit Logs to ELK using Filebeat| 20 | | `misp-doc` | Assists in setting the MISP Server and creating threat events using PyMISP | 21 | | `mlogc_elk` | Shows a PoC for sending the ModSecurity Audit Logs to ELK using ModSecurity Audit Log Collector (mlogc) | 22 | 23 | Please go to respective directories for complete documentation. 24 | 25 | # Project Roadmap 26 | 27 | As of August, 2018, the priorities for the next 6 months are: 28 | 29 | * ~~Setup Proof of Concept to understand how ModSecurity baed Honeypot/Probe interacts with a receiving console (develop a VM and/or Docker based test solution to store logs from multiple probes).~~ 30 | * ~~Evaluate console options to visualise threat data received from ModSecurity Honeypots/probes in MosSecurity Audit Console, WAF-FLE, Fluent and bespoke scripts for single and multiple probes.~~ 31 | * ~~Develop a mechanism to convert from stored MySQL to JSON format.~~ 32 | * ~~Provide a mechanism to convert ModSecurity mlogc audit log output into JSON format.~~ 33 | * ~~Provide a mechanism to convert mlogc audit log output directly into ELK (ElasticSearch/Logstash/Kibana) to visualise the data.~~ 34 | * Provide a mechanism to forward honest output into threat intelligence format such as STIX using something like the MISP project(https://www.misp-project.org) to share Threat data coming from the Honeypots making it easy to export/import data from formats such as STIX and TAXII., may require use of concurrent logs in a format that MISP can deal with. 35 | * ~~Consider new alternatives for log transfer including the use of MLOGC-NG or other possible approaches.~~ 36 | * Develop a new VM based honeypot/probe based on CRS v3.1. 37 | * Develop new alternative small footprint honeypot/probe formats utilising Docker & Raspberry Pi. 38 | * Develop machine learning approach to automatically be able to update the rule set being used by the probe based on cyber threat intelligence received. 39 | -------------------------------------------------------------------------------- /honeytraps/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # To Commit 8170f64 from b32ec05 2 | 3 | * Separated Honeypot from the ELK docker-composer 4 | 5 | * Created Honeypot docker container, also image on docker hub 6 | 7 | * Created AWS ECS task definition for Honeypot 8 | 9 | * Created documentation on how to deploy Honeypot on AWS Elastic Container Service (ECS) using the aws-cli 10 | 11 | * Implemented ModSecurity Log preprocessing so they are completely JSON (reliable, but not the best way) with python. 12 | 13 | * ELK correctly containerized with docker, fixed config file placements and improved separation from each other 14 | 15 | * Changed folder structure to reflect docker changes 16 | 17 | * Pushing events to MISP is containerized as a service 18 | 19 | * Event push service for Elaticsearch->MISP is reworked 20 | 21 | * Improved reliability 22 | 23 | * Switched to ExtendedPyMIP module, the old one is deprecated and will be removed early 2020 24 | 25 | * Using async for connections wherever possible (mainly for elastic connection) 26 | 27 | * Improve MISP tagging and attribute handling for events 28 | -------------------------------------------------------------------------------- /honeytraps/README.md: -------------------------------------------------------------------------------- 1 | ## Building Honeytraps and Reporting Threat Intelligence 2 | 3 | The goal of this PoC to set the ModSecurity based Honeytraps. In this PoC, we will consider different such honeytraps and gather information about the attacker. 4 | 5 | There are three phases of recognizing the attack. 6 | 7 | * Luring the Attacker with a bait 8 | * Identifying the Attacker from his/her actions 9 | * Gathering the Information about the Attacker (From the logs) 10 | 11 | | Bait | Identification of Attacker | 12 | | ------------------------------- | ---------------------------------------------------------------------------------------- | 13 | | Adding Fake Listen Ports | If the web client is trying to access these fake ports, it will tagged as malicious | 14 | | Adding Fake entry in robots.txt | If it accesses the restricted location, it will tagged as malicious | 15 | | Adding Fake HTML comments | If it accesses the Debugging information from HTML comments, it can be marked malicious | 16 | | Adding Fake Hidden Form Fields | If it manipulates the hidden form field(s) set by the web server, it is tagged malicious | 17 | | Adding Fake Cookie Data | If it manipulates the cookies set by the web server, it is tagged malicious | 18 | 19 | Basically we will lay honeytraps using the Core Rule Set (CRS) rules of ModSecurity. ModSecurity is Web Application Firewall which runs on the web server. We gather the attack information using the Audit logs of ModSecurity. In order to handle the audit logs in a structured manner, we send the logs to Elasticsearch Logstash Kibana(ELK) Stack. ELK provides an efficient way for handling the logs and visualizing them. At ELK, we filter the relevant logs from the non-relevant ones. All the relevant log information is reported to Malware Information Sharing Platform (MISP). 20 | 21 | In this setup we have three Docker Containers. Each one for ModSecurity+Apache Web Server, ELK and MISP (as shown in below architecture diagram). 22 | 23 | ![Alt text](./honeytrap_arch.jpg?raw=true "Building Honeytraps and Reporing Threat Intelligence") 24 | 25 | ~~A step by step video demonstration is shown at https://www.youtube.com/watch?v=uE-uYwqEZYA~~ -- **Outdated** 26 | 27 | ### Setup Instructions 28 | 29 | 1. Dependencies for the setup 30 | 31 | * Docker Installed on your Host machine 32 | *    Atleast 8GB of RAM on your Host machine 33 | * Ports listed in docker-compose.yml should be available free in host machine 34 | * If ports are not free, please change to appropriate values in docker-compose.yml 35 | 36 | 2. Clone this repository into your Host Machine 37 | 38 | ```bash 39 | cd ~ 40 | git clone --recurse-submodules https://github.com/OWASP/Honeypot-Project.git 41 | cd ~/Honeypot-Project/honeytraps 42 | ``` 43 | 44 | 3. Setup MISP server, then ELK, then Modsecurity Honeypot as specified in their own README (located in ```misp, waf_elk and waf_modsec``` respecitvely) 45 | 46 | 4. Start all 3 of them them as specified in their own READMEs 47 | 48 | 5. Generate some web traffic using curl 49 | 50 | ```bash 51 | curl 'localhost:9091/index.html?exec=/bin/bash' 52 | curl 'http://localhost:9091/?q=">' 53 | ``` 54 | 55 | The logs should reach MISP in about 1-2 minutes, if you log in (details in the MISP README) you should be able to see them. 56 | 57 | ## Usage 58 | 59 | * **Kibana Dashboard Visualization** 60 | 61 | * Open Kibana [http://localhost:5601/app/kibana](http://localhost:5601/app/kibana) 62 | 63 | * Click on Dashboard from left hand side and click on Honeytrap Dashboard then you will see various information gathered through all honeytraps 64 | ![Alt text](./screenshots/savedObj3.png?raw=true "Saved Object Creation") 65 | 66 | * **Threat Reporting at MISP** 67 | 68 | * All the information gathered through all honeytraps is automically reported at MISP dashboard. Go to MISP URL (https://localhost) for viewing them. 69 | ![Alt text](./screenshots/events.png?raw=true "Honeytrap Events at MISP") 70 | * The events and tags are auto-generated from `misp-push.py` 71 | ![Alt text](./screenshots/tags.png?raw=true "Honeytrap Events at MISP") 72 | ![Alt text](./screenshots/event-details.png?raw=true "Honeytrap Events at MISP") 73 | 74 | ## Implemented Honeytrap Baits 75 | 76 | **HoneyTrap-1 (Adding Fake HTTP Ports for Listening)** 77 | 78 | * In this we will use additional ports of 8000,8080,8888 for listening 79 | 80 | * All the traffic that is received on these port is tagged malicious 81 | 82 | * Open the browser and enter the HostIP with any of above three ports (like shown in the image below) 83 | ![Alt text](./screenshots/honeytrap1_bait.png?raw=true "Accessing Fake Ports") 84 | 85 | * Alternatively run the below command from terminal 86 | 87 | ``` 88 | curl :8888/index.html 89 | ``` 90 | 91 | * Navigate to Discover Menu on the Left Hand Side and Honeytrap-1 Logs can be visualized in Kibana Dashboard 92 | ![Alt text](./screenshots/honeytrap1_logs.png?raw=true "Visualizing the Honeytrap-1 Logs") 93 | 94 | * **HoneyTrap-2 (Adding Fake Disallow Entry in robots.txt file)** 95 | 96 | * Every website maintains its robots.txt to advise the allowed and disallowed entries to the crawler 97 | * Based on these entries, crawler should not access the Disallowed entries, but the Disallow is just a suggestion in the robots.txt, so we will add a fake Disallow entry in the robots.txt file 98 | * Whoever tries to access this location is marked malicious 99 | * We can also have a fake authentication on this fake location to get the username/password pairs from the attacker 100 | * Open the robots.txt page and try to access Fake Disallowed robots.txt Entry (like shown in the image below) 101 | ![Alt text](./screenshots/honeytrap2_bait.png?raw=true "Accessing Fake Disallow robots.txt Entry") 102 | * Access the fake location mentioned in the robots.txt file 103 | ![Alt text](./screenshots/honeytrap2_bait_2.png?raw=true "Accessing Fake Disallow robots.txt Location + Authentication ") 104 | * In the below log screenshot we can see that Attacker has used the Admin as Username and Password as "Password" to get access to the fake location mentioned in robots.txt, all the tries (of username/password) of attacker are logged at ELK 105 | ![Alt text](./screenshots/honeytrap2_logs.png?raw=true "Visualizing the Honeytrap-2 Logs") 106 | 107 | * **HoneyTrap-3 (Adding Fake HTML Comments in the login page)** 108 | 109 | * In this trap, we will add a fake HTML comment in the login page, this fake comment redirects the attacker to some other location. Whoever tries to access this location is tagged malicious 110 | * Open the Host-IP:9091/login.html in browser and try to access comments of page (like shown in the image below). The highlighted line in the below picture shows the fake HTML comment added by the ModSecurity 111 | ![Alt text](./screenshots/honeytrap3_bait.png?raw=true "Accessing Fake HTML comment") 112 | * Try to access the location mentioned in the HTML comment 113 | ![Alt text](./screenshots/honeytrap3_bait_2.png?raw=true "Accessing HTML comment specified location") 114 | * In the below log screenshot we can see that Attacker is tagged 115 | ![Alt text](./screenshots/honeytrap3_logs.png?raw=true "Visualizing the Honeytrap-3 Logs") 116 | 117 | * **HoneyTrap-4 (Adding Fake Hidden Form Fields)** 118 | 119 | * HTML hidden form fields are just like normal form fields, except for one distinct difference: The browser doesn’t display them to the user. Hidden fields are used as a mechanism to pass data from one request to another, and their contents are not supposed to be altered 120 | * This is how the raw HTML hidden form field looks in the source 121 | * `` 122 | * Just as we did with adding fake HTML comments, we can use the same methodology to inject fake HTML hidden form fields. The key to this technique is the closing `` HTML tag. We will inject our honeytrap data just before it. 123 | * Whoever tries to manipulate this form field is tagged malicious 124 | * Open the Host-IP:9091 in browser and try to access hidden form field of page (like shown in the image below). 125 | The highlighted line in the below picture shows the fake HTML comment added by the ModSecurity 126 | ![Alt text](./screenshots/honeytrap4_bait.png?raw=true "Accessing Fake Hidden Form Field") 127 | * Change the hidden field value to true, put some data in the form and submit it 128 | ![Alt text](./screenshots/honeytrap4_bait_2.png?raw=true "Changing the hidden form field value") 129 | * In the below log screenshot we can see that Attacker is tagged at ELK 130 | ![Alt text](./screenshots/honeytrap4_logs.png?raw=true "Visualizing the Honeytrap-4 Logs") 131 | 132 | * **HoneyTrap-5 (Adding Fake Cookies)** 133 | 134 | * The HTTP protocol has no built-in session awareness. This means that each transaction is independent from the others. The application, therefore, needs a method to track who someone is and what actions he has previously taken (for instance, in a multistep process). Cookies were created precisely for this purpose 135 | * The application issues `Set-Cookie` response header data to the client web browser. 136 | * Much like attackers take aim at parameter payloads, they also attempt to alter cookie data that the application hands out. This can be done with the tools like http://www.editthiscookie.com/ 137 | * Open the Host-IP:9091 in browser and open the site information to access the cookie information (like shown in the image below). 138 | The highlighted line in the below picture shows the cookie data is `Admin:0` 139 | ![Alt text](./screenshots/honeytrap5_bait.png?raw=true "Accessing Cookies") 140 | * We try change the cookie data using `editthiscookie` chrome-extension (you can others similar to this). We try to change `Admin:0` to `Admin:5` after that fill the form and submit the data 141 | ![Alt text](./screenshots/honeytrap5_bait_2.png?raw=true "Changing the cookie value") 142 | * In the below log screenshot we can see that Attacker is tagged at ELK who changed the cookie value 143 | ![Alt text](./screenshots/honeytrap4_logs.png?raw=true "Visualizing the Honeytrap-5 Logs") 144 | 145 | * Please check the ```waf_modsec/modsecurity-extension.conf``` file for more information about the honeytraps. 146 | 147 | ## **Known Issues**: 148 | 149 | * max virtual memory areas vm.max_map_count [65530] is too low, increase to at least [262144], Run the below command 150 | 151 | ``` 152 | sudo sysctl -w vm.max_map_count=262144 153 | ``` 154 | 155 | ## **References** 156 | 157 | * Web Application Defender's Cookbook: Battling Hackers and Protecting Users 158 | * http://www.editthiscookie.com/ 159 | * https://www.trustwave.com/en-us/resources/blogs/spiderlabs-blog/detecting-malice-with-modsecurity-honeytraps/ 160 | * https://www.trustwave.com/en-us/resources/blogs/spiderlabs-blog/setting-honeytraps-with-modsecurity-adding-fake-hidden-form-fields/ 161 | * https://www.trustwave.com/en-us/resources/blogs/spiderlabs-blog/setting-honeytraps-with-modsecurity-adding-fake-cookies/ 162 | * https://www.trustwave.com/en-us/resources/blogs/spiderlabs-blog/setting-honeytraps-with-modsecurity-adding-fake-robotstxt-disallow-entries/ 163 | * https://logz.io/learn/complete-guide-elk-stack/ 164 | * https://misp-project.org 165 | * https://github.com/harvard-itsecurity/docker-misp 166 | * https://pymisp.readthedocs.io/ 167 | -------------------------------------------------------------------------------- /honeytraps/honeytrap_arch.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OWASP/Honeypot-Project/45bcf2a30da7e0c6face45882bd1c2f2827e0a0b/honeytraps/honeytrap_arch.jpg -------------------------------------------------------------------------------- /honeytraps/misp/README.md: -------------------------------------------------------------------------------- 1 | # MISP docker image 2 | 3 | ## MISP Setup 4 | 5 | - Create an env file for MISP 6 | 7 | ```bash 8 | cp ~/Honeypot-Project/honeytraps/misp/sample-env ~/Honeypot-Project/honeytraps/misp/env 9 | ``` 10 | 11 | - Set DOCKER_ROOT variable in the env file to a path to your liking (```/docker``` or ```~/docker``` for example) where the database will be intialised and stored on your system. The folder should be only used by docker. 12 | 13 | - Setup MISP 14 | 15 | ```bash 16 | cd ~/Honeypot-Project/honeytraps/misp 17 | ./setup_misp.sh 18 | ``` 19 | 20 | **Note that the ```setup_misp.sh``` script will ask for sudo! It is needed to create the folder if it does not exist and to set the correct permissions. Follow the steps manually in the script if you do not trust it.** 21 | 22 | ## Running MISP 23 | 24 | Run the start script 25 | 26 | ```bash 27 | cd ~/Honeypot-Project/honeytraps/misp 28 | ./run_misp.sh 29 | ``` 30 | 31 | ## Using MISP 32 | 33 | The web interface can be accessed from ```https://localhost```. 34 | 35 | Default Login details: 36 | 37 | ```bash 38 | Login: admin@admin.test 39 | Password: admin 40 | ``` 41 | 42 | You will be asked to change the password the first time you log in. 43 | -------------------------------------------------------------------------------- /honeytraps/misp/run_misp.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | source './env' 3 | docker run -it -p 443:443 -p 80:80 -p 3306:3306 -v $DOCKER_ROOT/misp-db:/var/lib/mysql harvarditsecurity/misp 4 | -------------------------------------------------------------------------------- /honeytraps/misp/sample-env: -------------------------------------------------------------------------------- 1 | DOCKER_ROOT=/docker -------------------------------------------------------------------------------- /honeytraps/misp/setup_misp.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | source './env' #Importing variables from env file 3 | set -u 4 | if [[ -z {$DOCKER_ROOT} ]]; then 5 | echo "DOCKER_ROOT is not set in the env file! exiting" 6 | exit 1 7 | fi 8 | 9 | sudo chown $USER:docker $DOCKER_ROOT 10 | sudo mkdir -p $DOCKER_ROOT/misp-db 11 | sudo chown $USER:docker $DOCKER_ROOT/misp-db 12 | docker pull harvarditsecurity/misp 13 | docker run -it --rm -v $DOCKER_ROOT/misp-db:/var/lib/mysql harvarditsecurity/misp /init-db -------------------------------------------------------------------------------- /honeytraps/screenshots/Screenshot from 2019-06-16 13-20-34.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OWASP/Honeypot-Project/45bcf2a30da7e0c6face45882bd1c2f2827e0a0b/honeytraps/screenshots/Screenshot from 2019-06-16 13-20-34.png -------------------------------------------------------------------------------- /honeytraps/screenshots/event-details.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OWASP/Honeypot-Project/45bcf2a30da7e0c6face45882bd1c2f2827e0a0b/honeytraps/screenshots/event-details.png -------------------------------------------------------------------------------- /honeytraps/screenshots/events.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OWASP/Honeypot-Project/45bcf2a30da7e0c6face45882bd1c2f2827e0a0b/honeytraps/screenshots/events.png -------------------------------------------------------------------------------- /honeytraps/screenshots/filebeat_index_create.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OWASP/Honeypot-Project/45bcf2a30da7e0c6face45882bd1c2f2827e0a0b/honeytraps/screenshots/filebeat_index_create.png -------------------------------------------------------------------------------- /honeytraps/screenshots/filebeat_index_create_2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OWASP/Honeypot-Project/45bcf2a30da7e0c6face45882bd1c2f2827e0a0b/honeytraps/screenshots/filebeat_index_create_2.png -------------------------------------------------------------------------------- /honeytraps/screenshots/filebeat_logs.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OWASP/Honeypot-Project/45bcf2a30da7e0c6face45882bd1c2f2827e0a0b/honeytraps/screenshots/filebeat_logs.png -------------------------------------------------------------------------------- /honeytraps/screenshots/honeytrap1_bait.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OWASP/Honeypot-Project/45bcf2a30da7e0c6face45882bd1c2f2827e0a0b/honeytraps/screenshots/honeytrap1_bait.png -------------------------------------------------------------------------------- /honeytraps/screenshots/honeytrap1_logs.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OWASP/Honeypot-Project/45bcf2a30da7e0c6face45882bd1c2f2827e0a0b/honeytraps/screenshots/honeytrap1_logs.png -------------------------------------------------------------------------------- /honeytraps/screenshots/honeytrap2_bait.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OWASP/Honeypot-Project/45bcf2a30da7e0c6face45882bd1c2f2827e0a0b/honeytraps/screenshots/honeytrap2_bait.png -------------------------------------------------------------------------------- /honeytraps/screenshots/honeytrap2_bait_2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OWASP/Honeypot-Project/45bcf2a30da7e0c6face45882bd1c2f2827e0a0b/honeytraps/screenshots/honeytrap2_bait_2.png -------------------------------------------------------------------------------- /honeytraps/screenshots/honeytrap2_logs.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OWASP/Honeypot-Project/45bcf2a30da7e0c6face45882bd1c2f2827e0a0b/honeytraps/screenshots/honeytrap2_logs.png -------------------------------------------------------------------------------- /honeytraps/screenshots/honeytrap3_bait.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OWASP/Honeypot-Project/45bcf2a30da7e0c6face45882bd1c2f2827e0a0b/honeytraps/screenshots/honeytrap3_bait.png -------------------------------------------------------------------------------- /honeytraps/screenshots/honeytrap3_bait_2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OWASP/Honeypot-Project/45bcf2a30da7e0c6face45882bd1c2f2827e0a0b/honeytraps/screenshots/honeytrap3_bait_2.png -------------------------------------------------------------------------------- /honeytraps/screenshots/honeytrap3_logs.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OWASP/Honeypot-Project/45bcf2a30da7e0c6face45882bd1c2f2827e0a0b/honeytraps/screenshots/honeytrap3_logs.png -------------------------------------------------------------------------------- /honeytraps/screenshots/honeytrap4_bait.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OWASP/Honeypot-Project/45bcf2a30da7e0c6face45882bd1c2f2827e0a0b/honeytraps/screenshots/honeytrap4_bait.png -------------------------------------------------------------------------------- /honeytraps/screenshots/honeytrap4_bait_2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OWASP/Honeypot-Project/45bcf2a30da7e0c6face45882bd1c2f2827e0a0b/honeytraps/screenshots/honeytrap4_bait_2.png -------------------------------------------------------------------------------- /honeytraps/screenshots/honeytrap4_logs.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OWASP/Honeypot-Project/45bcf2a30da7e0c6face45882bd1c2f2827e0a0b/honeytraps/screenshots/honeytrap4_logs.png -------------------------------------------------------------------------------- /honeytraps/screenshots/honeytrap5_bait.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OWASP/Honeypot-Project/45bcf2a30da7e0c6face45882bd1c2f2827e0a0b/honeytraps/screenshots/honeytrap5_bait.png -------------------------------------------------------------------------------- /honeytraps/screenshots/honeytrap5_bait_2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OWASP/Honeypot-Project/45bcf2a30da7e0c6face45882bd1c2f2827e0a0b/honeytraps/screenshots/honeytrap5_bait_2.png -------------------------------------------------------------------------------- /honeytraps/screenshots/honeytrap5_logs.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OWASP/Honeypot-Project/45bcf2a30da7e0c6face45882bd1c2f2827e0a0b/honeytraps/screenshots/honeytrap5_logs.png -------------------------------------------------------------------------------- /honeytraps/screenshots/pymisp-key.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OWASP/Honeypot-Project/45bcf2a30da7e0c6face45882bd1c2f2827e0a0b/honeytraps/screenshots/pymisp-key.png -------------------------------------------------------------------------------- /honeytraps/screenshots/savedObj1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OWASP/Honeypot-Project/45bcf2a30da7e0c6face45882bd1c2f2827e0a0b/honeytraps/screenshots/savedObj1.png -------------------------------------------------------------------------------- /honeytraps/screenshots/savedObj2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OWASP/Honeypot-Project/45bcf2a30da7e0c6face45882bd1c2f2827e0a0b/honeytraps/screenshots/savedObj2.png -------------------------------------------------------------------------------- /honeytraps/screenshots/savedObj3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OWASP/Honeypot-Project/45bcf2a30da7e0c6face45882bd1c2f2827e0a0b/honeytraps/screenshots/savedObj3.png -------------------------------------------------------------------------------- /honeytraps/screenshots/tags.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OWASP/Honeypot-Project/45bcf2a30da7e0c6face45882bd1c2f2827e0a0b/honeytraps/screenshots/tags.png -------------------------------------------------------------------------------- /honeytraps/waf_elk/README.md: -------------------------------------------------------------------------------- 1 | # WAF ELK docker image 2 | 3 | ## Setup ELK 4 | 5 | Best to set up after MISP has been set up 6 | 7 | * Create and populate the env file 8 | 9 | ```bash 10 | cd ~/Honeypot-Project/honeytraps/waf_elk 11 | cp ./misp-push/sample-env ./misp-push/env 12 | ``` 13 | 14 | In the env file change the URL_MISP field to the IP MISP is be running on 15 | 16 | Change the MISP_KEY to your own API key. It can be found after you logged into MISP in Home>Automation section here: 17 | 18 | ![../screenshots/pymisp-key.png?raw=true](../screenshots/pymisp-key.png) 19 | 20 | Change all elasticsearch IPs to the IP that ELK will be running at the docker-compose.yml file 21 | 22 | * Build image 23 | 24 | ```bashag-0-1dttmup1hag-1-1dttmup1h 25 | docker-compose build 26 | # Start containers 27 | ./start_docker.sh 28 | ``` 29 | 30 | * Import Setings into Kibana 31 | 32 | - Open [http://localhost:5601/app/kibana](http://localhost:5601/app/kibana) in your browser 33 | 34 | - Go to Management in Kibana Dashboard and click Saved Objects 35 | 36 | ![](../screenshots/savedObj1.png) 37 | 38 | - Click on Import and upload the export.ndjson file as shown in below figure located in ```Honeypot-Project/honeytraps/waf_elk/kibana/export.json```   39 | 40 | ![](../screenshots/savedObj2.png)   41 | 42 | ## Running ELK 43 | 44 | Run the script - it simply sets vm.max_map_count to the correct value before starting the docker image. 45 | 46 | ```bash 47 | cd ~/Honeypot-Project/honeytraps/waf_elk 48 | ./start_docker.sh 49 | ``` 50 | 51 | ## Accessing ELK 52 | 53 | * Kibana can be accessed on [http://localhost:5601/app/kibana](http://localhost:5601/app/kibana) 54 | -------------------------------------------------------------------------------- /honeytraps/waf_elk/docker-compose.yml: -------------------------------------------------------------------------------- 1 | version: "3" 2 | services: 3 | misp_push: 4 | container_name: misp_push 5 | networks: 6 | - elastic 7 | volumes: 8 | - ./misp-push:/app 9 | env_file: 10 | - ./misp-push/env 11 | build: ./misp-push/ 12 | command: /app/start.sh 13 | links: 14 | - elasticsearch 15 | depends_on: 16 | - elasticsearch 17 | restart: always 18 | extra_hosts: 19 | - "elasticsearch:" 20 | elasticsearch: 21 | container_name: elasticsearch 22 | image: elasticsearch:7.5.1 23 | ports: 24 | - "9200:9200" 25 | - "9300:9300" 26 | environment: 27 | - node.name=elasticsearch 28 | - cluster.name=es-docker-cluster 29 | - discovery.type=single-node 30 | - discovery.seed_hosts=elasticsearch 31 | #- logger.transport.level=trace 32 | - "ES_JAVA_OPTS=-Xms512m -Xmx512m" 33 | extra_hosts: 34 | - "elasticsearch:" 35 | networks: 36 | - elastic 37 | kibana: 38 | container_name: kibana 39 | image: kibana:7.5.1 40 | ports: 41 | - "5601:5601" 42 | links: 43 | - elasticsearch 44 | depends_on: 45 | - elasticsearch 46 | extra_hosts: 47 | - "elasticsearch:" 48 | networks: 49 | - elastic 50 | logstash: 51 | container_name: logstash 52 | links: 53 | - elasticsearch 54 | ports: 55 | - "5044:5044" 56 | volumes: 57 | - ./logstash:/app 58 | - ./logstash/pipeline:/usr/share/logstash/pipeline 59 | build: ./logstash 60 | depends_on: 61 | - elasticsearch 62 | environment: 63 | - PIPENV_VENV_IN_PROJECT=true 64 | command: logstash 65 | extra_hosts: 66 | - "elasticsearch:" 67 | networks: 68 | - elastic 69 | 70 | networks: 71 | elastic: 72 | driver: bridge -------------------------------------------------------------------------------- /honeytraps/waf_elk/logstash/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM logstash:7.5.1 2 | WORKDIR /app/ 3 | COPY ./ /app 4 | COPY ./pipeline /usr/share/logstash/pipeline 5 | USER root 6 | EXPOSE 5044 7 | -------------------------------------------------------------------------------- /honeytraps/waf_elk/logstash/pipeline/logstash.conf: -------------------------------------------------------------------------------- 1 | input { 2 | beats { 3 | port => 5044 4 | type => "mod_security" 5 | codec => json 6 | } 7 | } 8 | 9 | #filter { 10 | # ruby { 11 | # code => " 12 | # event.to_hash.clone.each_value{|v| 13 | # if v.is_a? Hash 14 | # v.each_pair{|k,v| 15 | # event[k] = v 16 | # } 17 | # end 18 | # } 19 | # " 20 | # } 21 | #} 22 | 23 | output { 24 | elasticsearch { 25 | hosts => "elasticsearch:9200" 26 | manage_template => false 27 | index => "%{[@metadata][beat]}-%{+YYYY.MM.dd}" 28 | document_type => "%{[@metadata][type]}" 29 | } 30 | stdout { codec => rubydebug } 31 | } -------------------------------------------------------------------------------- /honeytraps/waf_elk/misp-push/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM ubuntu:focal 2 | WORKDIR /app/ 3 | USER root 4 | ENV LC_ALL="C.UTF-8" 5 | RUN apt-get update 6 | RUN apt-get install -y nano python3-pip 7 | RUN pip3 install pipenv 8 | RUN pipenv install 9 | COPY ./ /app 10 | CMD ["/bin/bash", "/app/start.sh"] 11 | -------------------------------------------------------------------------------- /honeytraps/waf_elk/misp-push/Pipfile: -------------------------------------------------------------------------------- 1 | [[source]] 2 | name = "pypi" 3 | url = "https://pypi.org/simple" 4 | verify_ssl = true 5 | 6 | [dev-packages] 7 | 8 | [packages] 9 | pymisp = "*" 10 | requests = "*" 11 | httpx = "*" 12 | elasticsearch-async = "*" 13 | elasticsearch = "*" 14 | aiohttp = "*" 15 | 16 | -------------------------------------------------------------------------------- /honeytraps/waf_elk/misp-push/sample-env: -------------------------------------------------------------------------------- 1 | URL_MISP=https://192.168.0.12 2 | # The MISP auth key can be found on the MISP web interface under the automation section 3 | MISP_KEY=wnnDqnBxhEV2LeaTf7JzxPMoJ3xV7kqabGpXSMF7 4 | MISP_VERIFYCERT=False -------------------------------------------------------------------------------- /honeytraps/waf_elk/misp-push/start.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | pipenv install 3 | pipenv run python3 /app/misp-push.py -------------------------------------------------------------------------------- /honeytraps/waf_elk/remoteipvis.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "type": "visualization", 4 | "source": { 5 | "title": "Honeypot Ports Used", 6 | "visState": "{\"title\":\"Honeypot Ports Used\",\"type\":\"pie\",\"params\":{\"type\":\"pie\",\"addTooltip\":true,\"addLegend\":true,\"legendPosition\":\"right\",\"isDonut\":true,\"labels\":{\"show\":false,\"values\":true,\"last_level\":true,\"truncate\":100}},\"aggs\":[{\"id\":\"1\",\"enabled\":true,\"type\":\"count\",\"schema\":\"metric\",\"params\":{}},{\"id\":\"2\",\"enabled\":true,\"type\":\"terms\",\"schema\":\"segment\",\"params\":{\"field\":\"transaction.local_port\",\"size\":5,\"order\":\"desc\",\"orderBy\":\"1\",\"otherBucket\":false,\"otherBucketLabel\":\"Other\",\"missingBucket\":false,\"missingBucketLabel\":\"Missing\"}}]}", 7 | "uiStateJSON": "{}", 8 | "description": "", 9 | "version": 1, 10 | "kibanaSavedObjectMeta": { 11 | "searchSourceJSON": "{\"index\":\"bcd07420-932d-11e9-b389-ef3215830bca\",\"query\":{\"query\":\"honeytrap\",\"language\":\"lucene\"},\"filter\":[]}" 12 | } 13 | } 14 | } 15 | ] -------------------------------------------------------------------------------- /honeytraps/waf_elk/start_docker.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | sudo sysctl -w vm.max_map_count=262144 3 | docker-compose up -------------------------------------------------------------------------------- /honeytraps/waf_modsec/AWS Amazon ECS Setup for Modescurity Honeypot.md: -------------------------------------------------------------------------------- 1 | *Located in the repo's Wiki section* 2 | 3 | # Basic AWS Amazon Elastic Container Service (ECS) Setup for Modsecurity Honeypot 4 | 5 | ### WARNING: ALL LINKS PROVIDED ARE FOR THE DEFAULT REGION ON AWS CONSOLE, PLEASE MAKE SURE YOU SELECT YOUR DESIRED REGION. 6 | 7 | ### 0. Install and Set up aws-cli (if needed) 8 | 9 | 1. Install aws-cli 10 | 11 | 2. Go to https://console.aws.amazon.com/iam/home#/security_credentials 12 | 13 | 3. Create or use an Access Key from the "Access Keys" section 14 | 15 | You need: 16 | 17 | * Access Key ID 18 | 19 | * Secret Access Key 20 | 21 | * Default Region ID - what is displayed at the region selection, like "eu-west-1" 22 | 23 | * Default output format (can be none) 24 | 25 | Configure aws-cli: 26 | 27 | ```bash 28 | aws configure 29 | ``` 30 | 31 | ### 1. Set up Task for docker container 32 | 33 | The docker image used for this task can be found [here](https://hub.docker.com/r/floyd0122/honeytrap-modsec): 34 | 35 | 1. Edit the following entries in ```honeytraps/waf_modsec/aws-ecs-container-definition.json```: 36 | 37 | * Change "LOGSTASH_HOST" env value to your logstash server IP and port 38 | 39 | * Change "awslogs-region" in "logConfiguration" to your region 40 | 41 | 2. Create the task: 42 | 43 | ```bash 44 | cd ~/Honeypot-Project/honeytraps/waf_modsec 45 | aws ecs register-task-definition --cli-input-json "$(cat aws-ecs-container-definition.json | tr '\n' ' ')" 46 | ``` 47 | 48 | You can observe the created task [here](https://console.aws.amazon.com/ecs/home#/taskDefinitions). Note that running this command creates a new revision for the Task definition automatically instead overwriting it.     49 | 50 | 3. Create log group for the task 51 | 52 | ```bash 53 | aws logs create-log-group --log-group-name "/ecs/honeytrap-modsec" 54 | ``` 55 | 56 | ### 2. Create Cluster for the Honeypot (if you want to use it in an existing one just skip this) 57 | 58 | Creating a cluster to run services in: 59 | 60 | ```bash 61 | aws ecs create-cluster --cluster-name "modsec-honeytrap" 62 | ``` 63 | 64 | You can observe the created cluster [here](https://eu-west-1.console.aws.amazon.com/ecs/home?region=eu-west-1#/clusters) 65 | 66 | ### 3. Create a Networking for the cluster and service 67 | 68 | This is a specific example, the IP and subnet ranges can be changed freely. 69 | 70 | 1. Create a Virtual Private Cloud (vpc) if you need a separate one ([reference](https://docs.aws.amazon.com/vpc/latest/userguide/what-is-amazon-vpc.html)): 71 | 72 | ```bash 73 | aws ec2 create-vpc --cidr-block 10.0.0.0/16 74 | #note vpc-id 75 | aws ec2 create-internet-gateway 76 | #note internetGateway-id 77 | # Add internet-gateway to private cloud 78 | aws ec2 attach-internet-gateway --internet-gateway-id --vpc-id 79 | # Find route table id 80 | aws ec2 describe-route-tables --filters Name=vpc-id,Values= 81 | # note the route-table-id 82 | # Add route to gateway in the route-table 83 | aws ec2 create-route --route-table-id --destination-cidr-block 0.0.0.0/0 --gateway-id 84 | ``` 85 | 86 | Please note the "VpcId" in the output. 87 | 88 | 2. Create a subnet in the vpc what the service will use: 89 | 90 | ```bash 91 | aws ec2 create-subnet --vpc-id --cidr-block 10.0.0.0/24 92 | ``` 93 | 94 | Please note the "Subnetid" fiels's value in the ouput. 95 | 96 | 3. Create a Security group (port rules) for the Virtual Private Cloud what the Service will use. 97 | 98 | *This is not necessary as a default group is created for the VPC upon creation but it is good practice to separate the services* 99 | 100 | ```bash 101 | aws ec2 create-security-group --group-name "EC2Container-honeytrap" --description "Port rules for the Honeytrap Docker Container" --vpc-id 102 | # Adding the required rules 103 | aws ec2 authorize-security-group-ingress --group-id --protocol tcp --cidr 0.0.0.0/0 --port 80 104 | aws ec2 authorize-security-group-ingress --group-id --protocol tcp --cidr 0.0.0.0/0 --port 8080 105 | aws ec2 authorize-security-group-ingress --group-id --protocol tcp --cidr 0.0.0.0/0 --port 8000 106 | aws ec2 authorize-security-group-ingress --group-id --protocol tcp --cidr 0.0.0.0/0 --port 8888 107 | ``` 108 | 109 | Please note the group ID. 110 | 111 | ```bash 112 | aws ec2 create-network-interface --description "HoneyTrap Network Interface" --subnet-id --groups 113 | ``` 114 | 115 | Note: You can most (not all) of this on through the Web UI [here](https://console.aws.amazon.com/vpc/home#vpcs:sort=VpcId) as well. 116 | 117 | ### 4. Create Service responsible for the Task created above and link them together 118 | 119 | This will be added to the Cluster and ran there using FARGATE (serverless). 120 | 121 | 1. Create Service using the Subnet ID and the Security Group ID: 122 | 123 | ```bash 124 | aws ecs create-service \ 125 | --service-name "honeytrap-service" \ 126 | --cluster "modsec-honeytrap" \ 127 | --task-definition "honeytrap" \ 128 | --desired-count 1 \ 129 | --launch-type "FARGATE" \ 130 | --network-configuration "awsvpcConfiguration={subnets=[],securityGroups=[],assignPublicIp=ENABLED}" 131 | ``` 132 | 133 | If all went well the Service is created and can be observed [here](https://console.aws.amazon.com/ecs/home#/clusters/modsec-honeytrap/services). 134 | 135 | * Select "Tasks" tab 136 | 137 | * Select the running task (Click on the Task id) 138 | 139 | * Observe the Public IP adress 140 | 141 | * Expand the Containter and click on "View logs in CloudWatch" to see the docker output 142 | -------------------------------------------------------------------------------- /honeytraps/waf_modsec/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM owasp/modsecurity-crs:apache 2 | RUN apt update && apt install -y wget nano curl python3-watchdog 3 | COPY include.conf /etc/modsecurity.d/ 4 | RUN wget https://artifacts.elastic.co/downloads/beats/filebeat/filebeat-8.9.0-amd64.deb 5 | RUN dpkg -i filebeat-8.9.0-amd64.deb 6 | COPY filebeat.yml /etc/filebeat/filebeat.yml 7 | RUN chmod go-w /etc/filebeat/filebeat.yml 8 | COPY modsec_entry.sh / 9 | COPY httpd.conf /usr/local/apache2/conf/httpd.conf 10 | COPY robots.txt /usr/local/apache2/htdocs/ 11 | COPY index.html /usr/local/apache2/htdocs/ 12 | COPY login.html /usr/local/apache2/htdocs/ 13 | COPY modsecurity-extension.conf /app/modsecurity-extension.conf 14 | COPY preprocess-modsec-log.py /app/preprocess-modsec-log.py 15 | RUN touch /var/log/modsec_audit_processed.log 16 | RUN cat /app/modsecurity-extension.conf >> /etc/modsecurity.d/modsecurity.conf 17 | RUN chmod +x /modsec_entry.sh 18 | EXPOSE 80/tcp 8080/tcp 8000/tcp 8888/tcp 19 | CMD ["/modsec_entry.sh"] 20 | 21 | #COPY filebeat.template.json /etc/filebeat/filebeat.template.json -------------------------------------------------------------------------------- /honeytraps/waf_modsec/README.md: -------------------------------------------------------------------------------- 1 | # WAF ModSecurity Honeypot docker image 2 | 3 | The AWS ECS setup can be found [here](https://github.com/OWASP/Honeypot-Project/wiki/AWS-ECS-Setup-for-ModSecurity-Honeypot). 4 | 5 | ## Setup Honeypot 6 | 7 | ```bashag-0-1dttmup1hag-1-1dttmup1h 8 | cd ~/Honeypot-Project/honeytraps/waf_modsec 9 | cp sample-env env 10 | # change the IP where your ELK image/service will be running in the "env" file 11 | docker-compose build 12 | ``` 13 | 14 | ## Running Honeypot 15 | 16 | ```bash 17 | cd ~/Honeypot-Project/honeytraps/waf_modsec 18 | docker-compose up 19 | ``` 20 | 21 | ## Accessing the Honeypot 22 | 23 | Port 9091 is open, and can be accessed. 24 | 25 | Port 8000,8080,8888 are open and can be accessed, these will trigger logging. 26 | 27 | ## Uploading (latest) image to DockerHub 28 | 29 | The Honeytrap docker image is needed by the AWS container definition ```honeytraps/waf_modsec/aws-ecs-container-definition.json``` under the ```"image"``` tag. 30 | 31 | The Image currently resides in my personal DockerHub account named as [floyd0122/honeytrap-modsec](https://hub.docker.com/repository/docker/floyd0122/honeytrap-modsec). In the future this needs to be pushed to OWASPs account. 32 | 33 | When it is moved to a new location, the AWS config needs to be changed accordingly. 34 | 35 | #### To upload a new/latest image 36 | 37 | Make sure you are logged in to docker 38 | 39 | ```bash 40 | cd ~/Honeypot-Project/honeytraps/waf_modsec 41 | docker build ./ -t /honeytrap-modsec 42 | docker push /honeytrap-modsec 43 | ``` 44 | 45 | 46 | -------------------------------------------------------------------------------- /honeytraps/waf_modsec/aws-ecs-container-definition.json: -------------------------------------------------------------------------------- 1 | { 2 | "family": "honeytrap", 3 | "executionRoleArn": "arn:aws:iam::544316695133:role/ecsTaskExecutionRole", 4 | "networkMode": "awsvpc", 5 | "cpu": "512", 6 | "containerDefinitions": [ 7 | { 8 | "name": "honeytrap-modsec", 9 | "image": "floyd0122/honeytrap-modsec", 10 | "cpu": 1, 11 | "memoryReservation": 512, 12 | "links": [], 13 | "portMappings": [ 14 | { 15 | "hostPort": 80, 16 | "protocol": "tcp", 17 | "containerPort": 80 18 | }, 19 | { 20 | "hostPort": 8000, 21 | "protocol": "tcp", 22 | "containerPort": 8000 23 | }, 24 | { 25 | "hostPort": 8080, 26 | "protocol": "tcp", 27 | "containerPort": 8080 28 | }, 29 | { 30 | "hostPort": 8888, 31 | "protocol": "tcp", 32 | "containerPort": 8888 33 | } 34 | ], 35 | "essential": true, 36 | "entryPoint": [], 37 | "command": [], 38 | "environment": [ 39 | { 40 | "name": "LOGSTASH_HOST", 41 | "value": "192.168.0.12:5044" 42 | } 43 | ], 44 | "mountPoints": [], 45 | "volumesFrom": [], 46 | "linuxParameters": {}, 47 | "secrets": [], 48 | "privileged": false, 49 | "readonlyRootFilesystem": false, 50 | "dnsServers": [], 51 | "dnsSearchDomains": [], 52 | "disableNetworking": false, 53 | "extraHosts": [], 54 | "systemControls": [], 55 | "logConfiguration": { 56 | "logDriver": "awslogs", 57 | "secretOptions": [], 58 | "options": { 59 | "awslogs-group": "/ecs/honeytrap-modsec", 60 | "awslogs-region": "eu-west-1", 61 | "awslogs-stream-prefix": "ecs" 62 | } 63 | } 64 | } 65 | ], 66 | "placementConstraints": [], 67 | "memory": "1024", 68 | "requiresCompatibilities": [ 69 | "FARGATE" 70 | ] 71 | } -------------------------------------------------------------------------------- /honeytraps/waf_modsec/docker-compose.yml: -------------------------------------------------------------------------------- 1 | modsec_crs: 2 | env_file: 3 | - ./env 4 | ports: 5 | - "9091:80" 6 | - "8000:8000" 7 | - "8080:8080" 8 | - "8888:8888" 9 | environment: 10 | - PARANOIA=5 11 | volumes: 12 | - .:/app 13 | build: ./ 14 | container_name: modsec_app 15 | privileged: true 16 | -------------------------------------------------------------------------------- /honeytraps/waf_modsec/example-log.json: -------------------------------------------------------------------------------- 1 | { 2 | "transaction": { 3 | "time": "08/Jan/2020:09:29:17 +0000", 4 | "transaction_id": "XhWg7dIVjbnaIo0jT3v1-wAAAIA", 5 | "remote_address": "172.17.0.1", 6 | "remote_port": 56224, 7 | "local_address": "172.17.0.2", 8 | "local_port": 80 9 | }, 10 | "request": { 11 | "request_line": "GET /?q=\"> HTTP/1.1", 12 | "headers": { 13 | "Host": "localhost:9091", 14 | "User-Agent": "curl/7.67.0", 15 | "Accept": "*/*" 16 | } 17 | }, 18 | "response": { 19 | "protocol": "HTTP/1.1", 20 | "status": 403, 21 | "headers": { 22 | "Set-Cookie": "(null)=Admin:0", 23 | "Content-Length": "209", 24 | "Content-Type": "text/html; charset=iso-8859-1" 25 | }, 26 | "body": "\n\n403 Forbidden\n\n

Forbidden

\n

You don't have permission to access /\non this server.
\n

\n\n" 27 | }, 28 | "audit_data": { 29 | "messages": ["Warning. Found 9 byte(s) in ARGS:q outside range: 38,44-46,48-58,61,65-90,95,97-122. [file \"/etc/modsecurity.d/owasp-crs/rules/REQUEST-920-PROTOCOL-ENFORCEMENT.conf\"] [line \"1391\"] [id \"920273\"] [msg \"Invalid character in request (outside of very strict set)\"] [data \"ARGS:q=\\x22>\"] [severity \"CRITICAL\"] [ver \"OWASP_CRS/3.2.0\"] [tag \"application-multi\"] [tag \"language-multi\"] [tag \"platform-multi\"] [tag \"attack-protocol\"] [tag \"OWASP_CRS\"] [tag \"OWASP_CRS/PROTOCOL_VIOLATION/EVASION\"] [tag \"paranoia-level/4\"]", "Warning. detected XSS using libinjection. [file \"/etc/modsecurity.d/owasp-crs/rules/REQUEST-941-APPLICATION-ATTACK-XSS.conf\"] [line \"59\"] [id \"941100\"] [msg \"XSS Attack Detected via libinjection\"] [data \"Matched Data: XSS data found within ARGS:q: \\x22>\"] [severity \"CRITICAL\"] [ver \"OWASP_CRS/3.2.0\"] [tag \"application-multi\"] [tag \"language-multi\"] [tag \"platform-multi\"] [tag \"attack-xss\"] [tag \"OWASP_CRS\"] [tag \"OWASP_CRS/WEB_ATTACK/XSS\"] [tag \"WASCTC/WASC-8\"] [tag \"WASCTC/WASC-22\"] [tag \"OWASP_TOP_10/A3\"] [tag \"OWASP_AppSensor/IE1\"] [tag \"CAPEC-242\"]", "Warning. Pattern match \"(?i)]*>[\\\\s\\\\S]*?\" at ARGS:q. [file \"/etc/modsecurity.d/owasp-crs/rules/REQUEST-941-APPLICATION-ATTACK-XSS.conf\"] [line \"90\"] [id \"941110\"] [msg \"XSS Filter - Category 1: Script Tag Vector\"] [data \"Matched Data: \"] [severity \"CRITICAL\"] [ver \"OWASP_CRS/3.2.0\"] [tag \"application-multi\"] [tag \"language-multi\"] [tag \"platform-multi\"] [tag \"attack-xss\"] [tag \"OWASP_CRS\"] [tag \"OWASP_CRS/WEB_ATTACK/XSS\"] [tag \"WASCTC/WASC-8\"] [tag \"WASCTC/WASC-22\"] [tag \"OWASP_TOP_10/A3\"] [tag \"OWASP_AppSensor/IE1\"] [tag \"CAPEC-242\"]", "Warning. Pattern match \"(?i:(?:<\\\\w[\\\\s\\\\S]*[\\\\s\\\\/]|['\\\"](?:[\\\\s\\\\S]*[\\\\s\\\\/])?)(?:on(?:d(?:e(?:vice(?:(?:orienta|mo)tion|proximity|found|light)|livery(?:success|error)|activate)|r(?:ag(?:e(?:n(?:ter|d)|xit)|(?:gestur|leav)e|start|drop|over)|op)|i(?:s(?:c(?:hargingtimechange ...\" at ARGS:q. [file \"/etc/modsecurity.d/owasp-crs/rules/REQUEST-941-APPLICATION-ATTACK-XSS.conf\"] [line \"218\"] [id \"941160\"] [msg \"NoScript XSS InjectionChecker: HTML Injection\"] [data \"Matched Data: \"] [severity \"CRITICAL\"] [ver \"OWASP_CRS/3.2.0\"] [tag \"application-multi\"] [tag \"language-multi\"] [tag \"platform-multi\"] [tag \"attack-xss\"] [tag \"OWASP_CRS\"] [tag \"OWASP_CRS/WEB_ATTACK/XSS\"] [tag \"WASCTC/WASC-8\"] [tag \"WASCTC/WASC-22\"] [tag \"OWASP_TOP_10/A3\"] [tag \"OWASP_AppSensor/IE1\"] [tag \"CAPEC-242\"]", "Warning. Pattern match \"<(?:a|abbr|acronym|address|applet|area|audioscope|b|base|basefront|bdo|bgsound|big|blackface|blink|blockquote|body|bq|br|button|caption|center|cite|code|col|colgroup|comment|dd|del|dfn|dir|div|dl|dt|em|embed|fieldset|fn|font|form|frame|frameset|h1|head ...\" at ARGS:q. [file \"/etc/modsecurity.d/owasp-crs/rules/REQUEST-941-APPLICATION-ATTACK-XSS.conf\"] [line \"879\"] [id \"941320\"] [msg \"Possible XSS Attack Detected - HTML Tag Handler\"] [data \"Matched Data: \"] [severity \"CRITICAL\"] [ver \"OWASP_CRS/3.2.0\"] [tag \"application-multi\"] [tag \"language-multi\"] [tag \"platform-multi\"] [tag \"attack-xss\"] [tag \"OWASP_CRS\"] [tag \"OWASP_CRS/WEB_ATTACK/XSS\"] [tag \"WASCTC/WASC-8\"] [tag \"WASCTC/WASC-22\"] [tag \"OWASP_TOP_10/A2\"] [tag \"OWASP_AppSensor/IE1\"] [tag \"PCI/6.5.1\"] [tag \"paranoia-level/2\"]", "Warning. Pattern match \"(?:^\\\\s*[\\\"'`;]+|[\\\"'`]+\\\\s*$)\" at ARGS:q. [file \"/etc/modsecurity.d/owasp-crs/rules/REQUEST-942-APPLICATION-ATTACK-SQLI.conf\"] [line \"550\"] [id \"942110\"] [msg \"SQL Injection Attack: Common Injection Testing Detected\"] [data \"Matched Data: \\x22 found within ARGS:q: \\x22>\"] [severity \"WARNING\"] [ver \"OWASP_CRS/3.2.0\"] [tag \"application-multi\"] [tag \"language-multi\"] [tag \"platform-multi\"] [tag \"attack-sqli\"] [tag \"OWASP_CRS\"] [tag \"OWASP_CRS/WEB_ATTACK/SQL_INJECTION\"] [tag \"WASCTC/WASC-19\"] [tag \"OWASP_TOP_10/A1\"] [tag \"OWASP_AppSensor/CIE1\"] [tag \"PCI/6.5.2\"] [tag \"paranoia-level/2\"]", "Warning. Pattern match \"(?i:[\\\\s'\\\"`()]*?([\\\\d\\\\w]++)[\\\\s'\\\"`()]*?(?:<(?:=(?:[\\\\s'\\\"`()]*?(?!\\\\1)[\\\\d\\\\w]+|>[\\\\s'\\\"`()]*?(?:\\\\1))|>?[\\\\s'\\\"`()]*?(?!\\\\1)[\\\\d\\\\w]+)|(?:not\\\\s+(?:regexp|like)|is\\\\s+not|>=?|!=|\\\\^)[\\\\s'\\\"`()]*?(?!\\\\1)[\\\\d\\\\w]+|(?:(?:sounds\\\\s+)?like|r(?:egexp|lik ...\" at ARGS:q. [file \"/etc/modsecurity.d/owasp-crs/rules/REQUEST-942-APPLICATION-ATTACK-SQLI.conf\"] [line \"628\"] [id \"942130\"] [msg \"SQL Injection Attack: SQL Tautology Detected.\"] [data \"Matched Data: script>alert found within ARGS:q: \\x22>\"] [severity \"CRITICAL\"] [ver \"OWASP_CRS/3.2.0\"] [tag \"application-multi\"] [tag \"language-multi\"] [tag \"platform-multi\"] [tag \"attack-sqli\"] [tag \"OWASP_CRS\"] [tag \"OWASP_CRS/WEB_ATTACK/SQL_INJECTION\"] [tag \"WASCTC/WASC-19\"] [tag \"OWASP_TOP_10/A1\"] [tag \"OWASP_AppSensor/CIE1\"] [tag \"PCI/6.5.2\"] [tag \"paranoia-level/2\"]", "Warning. Pattern match \"(?i:[\\\"'`]\\\\s*?(?:(?:n(?:and|ot)|(?:x?x)?or|between|\\\\|\\\\||and|div|&&)\\\\s+[\\\\s\\\\w]+=\\\\s*?\\\\w+\\\\s*?having\\\\s+|like(?:\\\\s+[\\\\s\\\\w]+=\\\\s*?\\\\w+\\\\s*?having\\\\s+|\\\\W*?[\\\"'`\\\\d])|[^?\\\\w\\\\s=.,;)(]++\\\\s*?[(@\\\"'`]*?\\\\s*?\\\\w+\\\\W+\\\\w|\\\\*\\\\s*?\\\\w+\\\\W+[\\\"'`])|(?:unio ...\" at ARGS:q. [file \"/etc/modsecurity.d/owasp-crs/rules/REQUEST-942-APPLICATION-ATTACK-SQLI.conf\"] [line \"803\"] [id \"942260\"] [msg \"Detects basic SQL authentication bypass attempts 2/3\"] [data \"Matched Data: \\x22>\"] [severity \"CRITICAL\"] [ver \"OWASP_CRS/3.2.0\"] [tag \"application-multi\"] [tag \"language-multi\"] [tag \"platform-multi\"] [tag \"attack-sqli\"] [tag \"OWASP_CRS\"] [tag \"OWASP_CRS/WEB_ATTACK/SQL_INJECTION\"] [tag \"WASCTC/WASC-19\"] [tag \"OWASP_TOP_10/A1\"] [tag \"OWASP_AppSensor/CIE1\"] [tag \"PCI/6.5.2\"] [tag \"paranoia-level/2\"]", "Warning. Pattern match \"((?:[~!@#\\\\$%\\\\^&\\\\*\\\\(\\\\)\\\\-\\\\+=\\\\{\\\\}\\\\[\\\\]\\\\|:;\\\"'\\xc2\\xb4\\xe2\\x80\\x99\\xe2\\x80\\x98`<>][^~!@#\\\\$%\\\\^&\\\\*\\\\(\\\\)\\\\-\\\\+=\\\\{\\\\}\\\\[\\\\]\\\\|:;\\\"'\\xc2\\xb4\\xe2\\x80\\x99\\xe2\\x80\\x98`<>]*?){6})\" at ARGS:q. [file \"/etc/modsecurity.d/owasp-crs/rules/REQUEST-942-APPLICATION-ATTACK-SQLI.conf\"] [line \"1526\"] [id \"942431\"] [msg \"Restricted SQL Character Anomaly Detection (args): # of special characters exceeded (6)\"] [data \"Matched Data: \\x22>\"] [severity \"WARNING\"] [ver \"OWASP_CRS/3.2.0\"] [tag \"application-multi\"] [tag \"language-multi\"] [tag \"platform-multi\"] [tag \"attack-sqli\"] [tag \"OWASP_CRS\"] [tag \"OWASP_CRS/WEB_ATTACK/SQL_INJECTION\"] [tag \"WASCTC/WASC-19\"] [tag \"OWASP_TOP_10/A1\"] [tag \"OWASP_AppSensor/CIE1\"] [tag \"PCI/6.5.2\"] [tag \"paranoia-level/3\"]", "Warning. Pattern match \"((?:[~!@#\\\\$%\\\\^&\\\\*\\\\(\\\\)\\\\-\\\\+=\\\\{\\\\}\\\\[\\\\]\\\\|:;\\\"'\\xc2\\xb4\\xe2\\x80\\x99\\xe2\\x80\\x98`<>][^~!@#\\\\$%\\\\^&\\\\*\\\\(\\\\)\\\\-\\\\+=\\\\{\\\\}\\\\[\\\\]\\\\|:;\\\"'\\xc2\\xb4\\xe2\\x80\\x99\\xe2\\x80\\x98`<>]*?){2})\" at ARGS:q. [file \"/etc/modsecurity.d/owasp-crs/rules/REQUEST-942-APPLICATION-ATTACK-SQLI.conf\"] [line \"1717\"] [id \"942432\"] [msg \"Restricted SQL Character Anomaly Detection (args): # of special characters exceeded (2)\"] [data \"Matched Data: \\x22> found within ARGS:q: \\x22>\"] [severity \"WARNING\"] [ver \"OWASP_CRS/3.2.0\"] [tag \"application-multi\"] [tag \"language-multi\"] [tag \"platform-multi\"] [tag \"attack-sqli\"] [tag \"OWASP_CRS\"] [tag \"OWASP_CRS/WEB_ATTACK/SQL_INJECTION\"] [tag \"WASCTC/WASC-19\"] [tag \"OWASP_TOP_10/A1\"] [tag \"OWASP_AppSensor/CIE1\"] [tag \"PCI/6.5.2\"] [tag \"paranoia-level/4\"]", "Access denied with code 403 (phase 2). Operator GE matched 5 at TX:anomaly_score. [file \"/etc/modsecurity.d/owasp-crs/rules/REQUEST-949-BLOCKING-EVALUATION.conf\"] [line \"91\"] [id \"949110\"] [msg \"Inbound Anomaly Score Exceeded (Total Score: 44)\"] [severity \"CRITICAL\"] [tag \"application-multi\"] [tag \"language-multi\"] [tag \"platform-multi\"] [tag \"attack-generic\"]", "Warning. Operator GE matched 5 at TX:inbound_anomaly_score. [file \"/etc/modsecurity.d/owasp-crs/rules/RESPONSE-980-CORRELATION.conf\"] [line \"86\"] [id \"980130\"] [msg \"Inbound Anomaly Score Exceeded (Total Inbound Score: 44 - SQLI=19,XSS=20,RFI=0,LFI=0,RCE=0,PHPI=0,HTTP=0,SESS=0): individual paranoia level scores: 15, 18, 3, 8\"] [tag \"event-correlation\"]"], 30 | "error_messages": ["[file \"apache2_util.c\"] [line 273] [level 3] [client 172.17.0.1] ModSecurity: Warning. Found 9 byte(s) in ARGS:q outside range: 38,44-46,48-58,61,65-90,95,97-122. [file \"/etc/modsecurity.d/owasp-crs/rules/REQUEST-920-PROTOCOL-ENFORCEMENT.conf\"] [line \"1391\"] [id \"920273\"] [msg \"Invalid character in request (outside of very strict set)\"] [data \"ARGS:q=\\\\\\\\x22>\"] [severity \"CRITICAL\"] [ver \"OWASP_CRS/3.2.0\"] [tag \"application-multi\"] [tag \"language-multi\"] [tag \"platform-multi\"] [tag \"attack-protocol\"] [tag \"OWASP_CRS\"] [tag \"OWASP_CRS/PROTOCOL_VIOLATION/EVASION\"] [tag \"paranoia-level/4\"] [hostname \"localhost\"] [uri \"/\"] [unique_id \"XhWg7dIVjbnaIo0jT3v1-wAAAIA\"]", "[file \"apache2_util.c\"] [line 273] [level 3] [client 172.17.0.1] ModSecurity: Warning. detected XSS using libinjection. [file \"/etc/modsecurity.d/owasp-crs/rules/REQUEST-941-APPLICATION-ATTACK-XSS.conf\"] [line \"59\"] [id \"941100\"] [msg \"XSS Attack Detected via libinjection\"] [data \"Matched Data: XSS data found within ARGS:q: \\\\\\\\x22>\"] [severity \"CRITICAL\"] [ver \"OWASP_CRS/3.2.0\"] [tag \"application-multi\"] [tag \"language-multi\"] [tag \"platform-multi\"] [tag \"attack-xss\"] [tag \"OWASP_CRS\"] [tag \"OWASP_CRS/WEB_ATTACK/XSS\"] [tag \"WASCTC/WASC-8\"] [tag \"WASCTC/WASC-22\"] [tag \"OWASP_TOP_10/A3\"] [tag \"OWASP_AppSensor/IE1\"] [tag \"CAPEC-242\"] [hostname \"localhost\"] [uri \"/\"] [unique_id \"XhWg7dIVjbnaIo0jT3v1-wAAAIA\"]", "[file \"apache2_util.c\"] [line 273] [level 3] [client 172.17.0.1] ModSecurity: Warning. Pattern match \"(?i)]*>[\\\\\\\\\\\\\\\\s\\\\\\\\\\\\\\\\S]*?\" at ARGS:q. [file \"/etc/modsecurity.d/owasp-crs/rules/REQUEST-941-APPLICATION-ATTACK-XSS.conf\"] [line \"90\"] [id \"941110\"] [msg \"XSS Filter - Category 1: Script Tag Vector\"] [data \"Matched Data: \"] [severity \"CRITICAL\"] [ver \"OWASP_CRS/3.2.0\"] [tag \"application-multi\"] [tag \"language-multi\"] [tag \"platform-multi\"] [tag \"attack-xss\"] [tag \"OWASP_CRS\"] [tag \"OWASP_CRS/WEB_ATTACK/XSS\"] [tag \"WASCTC/WASC-8\"] [tag \"WASCTC/WASC-22\"] [tag \"OWASP_TOP_10/A3\"] [tag \"OWASP_AppSensor/IE1\"] [tag \"CAPEC-242\"] [hostname \"localhost\"] [uri \"/\"] [unique_id \"XhWg7dIVjbnaIo0jT3v1-wAAAIA\"]", "[file \"apache2_util.c\"] [line 273] [level 3] [client 172.17.0.1] ModSecurity: Warning. Pattern match \"(?i:(?:<\\\\\\\\\\\\\\\\w[\\\\\\\\\\\\\\\\s\\\\\\\\\\\\\\\\S]*[\\\\\\\\\\\\\\\\s\\\\\\\\\\\\\\\\/]|['\\\\\\\\\"](?:[\\\\\\\\\\\\\\\\s\\\\\\\\\\\\\\\\S]*[\\\\\\\\\\\\\\\\s\\\\\\\\\\\\\\\\/])?)(?:on(?:d(?:e(?:vice(?:(?:orienta|mo)tion|proximity|found|light)|livery(?:success|error)|activate)|r(?:ag(?:e(?:n(?:ter|d)|xit)|(?:gestur|leav)e|start|drop|over)|op)|i(?:s(?:c(?:hargingtimechange ...\" at ARGS:q. [file \"/etc/modsecurity.d/owasp-crs/rules/REQUEST-941-APPLICATION-ATTACK-XSS.conf\"] [line \"218\"] [id \"941160\"] [msg \"NoScript XSS InjectionChecker: HTML Injection\"] [data \"Matched Data: \"] [severity \"CRITICAL\"] [ver \"OWASP_CRS/3.2.0\"] [tag \"application-multi\"] [tag \"language-multi\"] [tag \"platform-multi\"] [tag \"attack-xss\"] [tag \"OWASP_CRS\"] [tag \"OWASP_CRS/WEB_ATTACK/XSS\"] [tag \"WASCTC/WASC-8\"] [tag \"WASCTC/WASC-22\"] [tag \"OWASP_TOP_10/A3\"] [tag \"OWASP_AppSensor/IE1\"] [tag \"CAPEC-242\"] [hostname \"localhost\"] [uri \"/\"] [unique_id \"XhWg7dIVjbnaIo0jT3v1-wAAAIA\"]", "[file \"apache2_util.c\"] [line 273] [level 3] [client 172.17.0.1] ModSecurity: Warning. Pattern match \"<(?:a|abbr|acronym|address|applet|area|audioscope|b|base|basefront|bdo|bgsound|big|blackface|blink|blockquote|body|bq|br|button|caption|center|cite|code|col|colgroup|comment|dd|del|dfn|dir|div|dl|dt|em|embed|fieldset|fn|font|form|frame|frameset|h1|head ...\" at ARGS:q. [file \"/etc/modsecurity.d/owasp-crs/rules/REQUEST-941-APPLICATION-ATTACK-XSS.conf\"] [line \"879\"] [id \"941320\"] [msg \"Possible XSS Attack Detected - HTML Tag Handler\"] [data \"Matched Data: \"] [severity \"CRITICAL\"] [ver \"OWASP_CRS/3.2.0\"] [tag \"application-multi\"] [tag \"language-multi\"] [tag \"platform-multi\"] [tag \"attack-xss\"] [tag \"OWASP_CRS\"] [tag \"OWASP_CRS/WEB_ATTACK/XSS\"] [tag \"WASCTC/WASC-8\"] [tag \"WASCTC/WASC-22\"] [tag \"OWASP_TOP_10/A2\"] [tag \"OWASP_AppSensor/IE1\"] [tag \"PCI/6.5.1\"] [tag \"paranoia-level/2\"] [hostname \"localhost\"] [uri \"/\"] [unique_id \"XhWg7dIVjbnaIo0jT3v1-wAAAIA\"]", "[file \"apache2_util.c\"] [line 273] [level 3] [client 172.17.0.1] ModSecurity: Warning. Pattern match \"(?:^\\\\\\\\\\\\\\\\s*[\\\\\\\\\"'`;]+|[\\\\\\\\\"'`]+\\\\\\\\\\\\\\\\s*$)\" at ARGS:q. [file \"/etc/modsecurity.d/owasp-crs/rules/REQUEST-942-APPLICATION-ATTACK-SQLI.conf\"] [line \"550\"] [id \"942110\"] [msg \"SQL Injection Attack: Common Injection Testing Detected\"] [data \"Matched Data: \\\\\\\\x22 found within ARGS:q: \\\\\\\\x22>\"] [severity \"WARNING\"] [ver \"OWASP_CRS/3.2.0\"] [tag \"application-multi\"] [tag \"language-multi\"] [tag \"platform-multi\"] [tag \"attack-sqli\"] [tag \"OWASP_CRS\"] [tag \"OWASP_CRS/WEB_ATTACK/SQL_INJECTION\"] [tag \"WASCTC/WASC-19\"] [tag \"OWASP_TOP_10/A1\"] [tag \"OWASP_AppSensor/CIE1\"] [tag \"PCI/6.5.2\"] [tag \"paranoia-level/2\"] [hostname \"localhost\"] [uri \"/\"] [unique_id \"XhWg7dIVjbnaIo0jT3v1-wAAAIA\"]", "[file \"apache2_util.c\"] [line 273] [level 3] [client 172.17.0.1] ModSecurity: Warning. Pattern match \"(?i:[\\\\\\\\\\\\\\\\s'\\\\\\\\\"`()]*?([\\\\\\\\\\\\\\\\d\\\\\\\\\\\\\\\\w]++)[\\\\\\\\\\\\\\\\s'\\\\\\\\\"`()]*?(?:<(?:=(?:[\\\\\\\\\\\\\\\\s'\\\\\\\\\"`()]*?(?!\\\\\\\\\\\\\\\\1)[\\\\\\\\\\\\\\\\d\\\\\\\\\\\\\\\\w]+|>[\\\\\\\\\\\\\\\\s'\\\\\\\\\"`()]*?(?:\\\\\\\\\\\\\\\\1))|>?[\\\\\\\\\\\\\\\\s'\\\\\\\\\"`()]*?(?!\\\\\\\\\\\\\\\\1)[\\\\\\\\\\\\\\\\d\\\\\\\\\\\\\\\\w]+)|(?:not\\\\\\\\\\\\\\\\s+(?:regexp|like)|is\\\\\\\\\\\\\\\\s+not|>=?|!=|\\\\\\\\\\\\\\\\^)[\\\\\\\\\\\\\\\\s'\\\\\\\\\"`()]*?(?!\\\\\\\\\\\\\\\\1)[\\\\\\\\\\\\\\\\d\\\\\\\\\\\\\\\\w]+|(?:(?:sounds\\\\\\\\\\\\\\\\s+)?like|r(?:egexp|lik ...\" at ARGS:q. [file \"/etc/modsecurity.d/owasp-crs/rules/REQUEST-942-APPLICATION-ATTACK-SQLI.conf\"] [line \"628\"] [id \"942130\"] [msg \"SQL Injection Attack: SQL Tautology Detected.\"] [data \"Matched Data: script>alert found within ARGS:q: \\\\\\\\x22>\"] [severity \"CRITICAL\"] [ver \"OWASP_CRS/3.2.0\"] [tag \"application-multi\"] [tag \"language-multi\"] [tag \"platform-multi\"] [tag \"attack-sqli\"] [tag \"OWASP_CRS\"] [tag \"OWASP_CRS/WEB_ATTACK/SQL_INJECTION\"] [tag \"WASCTC/WASC-19\"] [tag \"OWASP_TOP_10/A1\"] [tag \"OWASP_AppSensor/CIE1\"] [tag \"PCI/6.5.2\"] [tag \"paranoia-level/2\"] [hostname \"localhost\"] [uri \"/\"] [unique_id \"XhWg7dIVjbnaIo0jT3v1-wAAAIA\"]", "[file \"apache2_util.c\"] [line 273] [level 3] [client 172.17.0.1] ModSecurity: Warning. Pattern match \"(?i:[\\\\\\\\\"'`]\\\\\\\\\\\\\\\\s*?(?:(?:n(?:and|ot)|(?:x?x)?or|between|\\\\\\\\\\\\\\\\|\\\\\\\\\\\\\\\\||and|div|&&)\\\\\\\\\\\\\\\\s+[\\\\\\\\\\\\\\\\s\\\\\\\\\\\\\\\\w]+=\\\\\\\\\\\\\\\\s*?\\\\\\\\\\\\\\\\w+\\\\\\\\\\\\\\\\s*?having\\\\\\\\\\\\\\\\s+|like(?:\\\\\\\\\\\\\\\\s+[\\\\\\\\\\\\\\\\s\\\\\\\\\\\\\\\\w]+=\\\\\\\\\\\\\\\\s*?\\\\\\\\\\\\\\\\w+\\\\\\\\\\\\\\\\s*?having\\\\\\\\\\\\\\\\s+|\\\\\\\\\\\\\\\\W*?[\\\\\\\\\"'`\\\\\\\\\\\\\\\\d])|[^?\\\\\\\\\\\\\\\\w\\\\\\\\\\\\\\\\s=.,;)(]++\\\\\\\\\\\\\\\\s*?[(@\\\\\\\\\"'`]*?\\\\\\\\\\\\\\\\s*?\\\\\\\\\\\\\\\\w+\\\\\\\\\\\\\\\\W+\\\\\\\\\\\\\\\\w|\\\\\\\\\\\\\\\\*\\\\\\\\\\\\\\\\s*?\\\\\\\\\\\\\\\\w+\\\\\\\\\\\\\\\\W+[\\\\\\\\\"'`])|(?:unio ...\" at ARGS:q. [file \"/etc/modsecurity.d/owasp-crs/rules/REQUEST-942-APPLICATION-ATTACK-SQLI.conf\"] [line \"803\"] [id \"942260\"] [msg \"Detects basic SQL authentication bypass attempts 2/3\"] [data \"Matched Data: \\\\\\\\x22>\"] [severity \"CRITICAL\"] [ver \"OWASP_CRS/3.2.0\"] [tag \"application-multi\"] [tag \"language-multi\"] [tag \"platform-multi\"] [tag \"attack-sqli\"] [tag \"OWASP_CRS\"] [tag \"OWASP_CRS/WEB_ATTACK/SQL_INJECTION\"] [tag \"WASCTC/WASC-19\"] [tag \"OWASP_TOP_10/A1\"] [tag \"OWASP_AppSensor/CIE1\"] [tag \"PCI/6.5.2\"] [tag \"paranoia-level/2\"] [hostname \"localhost\"] [uri \"/\"] [unique_id \"XhWg7dIVjbnaIo0jT3v1-wAAAIA\"]", "[file \"apache2_util.c\"] [line 273] [level 3] [client 172.17.0.1] ModSecurity: Warning. Pattern match \"((?:[~!@#\\\\\\\\\\\\\\\\$%\\\\\\\\\\\\\\\\^&\\\\\\\\\\\\\\\\*\\\\\\\\\\\\\\\\(\\\\\\\\\\\\\\\\)\\\\\\\\\\\\\\\\-\\\\\\\\\\\\\\\\+=\\\\\\\\\\\\\\\\{\\\\\\\\\\\\\\\\}\\\\\\\\\\\\\\\\[\\\\\\\\\\\\\\\\]\\\\\\\\\\\\\\\\|:;\\\\\\\\\"'\\\\\\\\xc2\\\\\\\\xb4\\\\\\\\xe2\\\\\\\\x80\\\\\\\\x99\\\\\\\\xe2\\\\\\\\x80\\\\\\\\x98`<>][^~!@#\\\\\\\\\\\\\\\\$%\\\\\\\\\\\\\\\\^&\\\\\\\\\\\\\\\\*\\\\\\\\\\\\\\\\(\\\\\\\\\\\\\\\\)\\\\\\\\\\\\\\\\-\\\\\\\\\\\\\\\\+=\\\\\\\\\\\\\\\\{\\\\\\\\\\\\\\\\}\\\\\\\\\\\\\\\\[\\\\\\\\\\\\\\\\]\\\\\\\\\\\\\\\\|:;\\\\\\\\\"'\\\\\\\\xc2\\\\\\\\xb4\\\\\\\\xe2\\\\\\\\x80\\\\\\\\x99\\\\\\\\xe2\\\\\\\\x80\\\\\\\\x98`<>]*?){6})\" at ARGS:q. [file \"/etc/modsecurity.d/owasp-crs/rules/REQUEST-942-APPLICATION-ATTACK-SQLI.conf\"] [line \"1526\"] [id \"942431\"] [msg \"Restricted SQL Character Anomaly Detection (args): # of special characters exceeded (6)\"] [data \"Matched Data: \\\\\\\\x22>\"] [severity \"WARNING\"] [ver \"OWASP_CRS/3.2.0\"] [tag \"application-multi\"] [tag \"language-multi\"] [tag \"platform-multi\"] [tag \"attack-sqli\"] [tag \"OWASP_CRS\"] [tag \"OWASP_CRS/WEB_ATTACK/SQL_INJECTION\"] [tag \"WASCTC/WASC-19\"] [tag \"OWASP_TOP_10/A1\"] [tag \"OWASP_AppSensor/CIE1\"] [tag \"PCI/6.5.2\"] [tag \"paranoia-level/3\"] [hostname \"localhost\"] [uri \"/\"] [unique_id \"XhWg7dIVjbnaIo0jT3v1-wAAAIA\"]", "[file \"apache2_util.c\"] [line 273] [level 3] [client 172.17.0.1] ModSecurity: Warning. Pattern match \"((?:[~!@#\\\\\\\\\\\\\\\\$%\\\\\\\\\\\\\\\\^&\\\\\\\\\\\\\\\\*\\\\\\\\\\\\\\\\(\\\\\\\\\\\\\\\\)\\\\\\\\\\\\\\\\-\\\\\\\\\\\\\\\\+=\\\\\\\\\\\\\\\\{\\\\\\\\\\\\\\\\}\\\\\\\\\\\\\\\\[\\\\\\\\\\\\\\\\]\\\\\\\\\\\\\\\\|:;\\\\\\\\\"'\\\\\\\\xc2\\\\\\\\xb4\\\\\\\\xe2\\\\\\\\x80\\\\\\\\x99\\\\\\\\xe2\\\\\\\\x80\\\\\\\\x98`<>][^~!@#\\\\\\\\\\\\\\\\$%\\\\\\\\\\\\\\\\^&\\\\\\\\\\\\\\\\*\\\\\\\\\\\\\\\\(\\\\\\\\\\\\\\\\)\\\\\\\\\\\\\\\\-\\\\\\\\\\\\\\\\+=\\\\\\\\\\\\\\\\{\\\\\\\\\\\\\\\\}\\\\\\\\\\\\\\\\[\\\\\\\\\\\\\\\\]\\\\\\\\\\\\\\\\|:;\\\\\\\\\"'\\\\\\\\xc2\\\\\\\\xb4\\\\\\\\xe2\\\\\\\\x80\\\\\\\\x99\\\\\\\\xe2\\\\\\\\x80\\\\\\\\x98`<>]*?){2})\" at ARGS:q. [file \"/etc/modsecurity.d/owasp-crs/rules/REQUEST-942-APPLICATION-ATTACK-SQLI.conf\"] [line \"1717\"] [id \"942432\"] [msg \"Restricted SQL Character Anomaly Detection (args): # of special characters exceeded (2)\"] [data \"Matched Data: \\\\\\\\x22> found within ARGS:q: \\\\\\\\x22>\"] [severity \"WARNING\"] [ver \"OWASP_CRS/3.2.0\"] [tag \"application-multi\"] [tag \"language-multi\"] [tag \"platform-multi\"] [tag \"attack-sqli\"] [tag \"OWASP_CRS\"] [tag \"OWASP_CRS/WEB_ATTACK/SQL_INJECTION\"] [tag \"WASCTC/WASC-19\"] [tag \"OWASP_TOP_10/A1\"] [tag \"OWASP_AppSensor/CIE1\"] [tag \"PCI/6.5.2\"] [tag \"paranoia-level/4\"] [hostname \"localhost\"] [uri \"/\"] [unique_id \"XhWg7dIVjbnaIo0jT3v1-wAAAIA\"]", "[file \"apache2_util.c\"] [line 273] [level 3] [client 172.17.0.1] ModSecurity: Access denied with code 403 (phase 2). Operator GE matched 5 at TX:anomaly_score. [file \"/etc/modsecurity.d/owasp-crs/rules/REQUEST-949-BLOCKING-EVALUATION.conf\"] [line \"91\"] [id \"949110\"] [msg \"Inbound Anomaly Score Exceeded (Total Score: 44)\"] [severity \"CRITICAL\"] [tag \"application-multi\"] [tag \"language-multi\"] [tag \"platform-multi\"] [tag \"attack-generic\"] [hostname \"localhost\"] [uri \"/\"] [unique_id \"XhWg7dIVjbnaIo0jT3v1-wAAAIA\"]", "[file \"apache2_util.c\"] [line 273] [level 3] [client 172.17.0.1] ModSecurity: Warning. Operator GE matched 5 at TX:inbound_anomaly_score. [file \"/etc/modsecurity.d/owasp-crs/rules/RESPONSE-980-CORRELATION.conf\"] [line \"86\"] [id \"980130\"] [msg \"Inbound Anomaly Score Exceeded (Total Inbound Score: 44 - SQLI=19,XSS=20,RFI=0,LFI=0,RCE=0,PHPI=0,HTTP=0,SESS=0): individual paranoia level scores: 15, 18, 3, 8\"] [tag \"event-correlation\"] [hostname \"localhost\"] [uri \"/\"] [unique_id \"XhWg7dIVjbnaIo0jT3v1-wAAAIA\"]"], 31 | "action": { 32 | "intercepted": true, 33 | "phase": 2, 34 | "message": "Operator GE matched 5 at TX:anomaly_score." 35 | }, 36 | "stopwatch": { 37 | "p1": 413, 38 | "p2": 996, 39 | "p3": 0, 40 | "p4": 0, 41 | "p5": 94, 42 | "sr": 97, 43 | "sw": 0, 44 | "l": 0, 45 | "gc": 0 46 | }, 47 | "response_body_dechunked": true, 48 | "producer": ["ModSecurity for Apache/2.9.3 (http://www.modsecurity.org/)", "OWASP_CRS/3.2.0"], 49 | "server": "Apache", 50 | "engine_mode": "ENABLED" 51 | } 52 | } -------------------------------------------------------------------------------- /honeytraps/waf_modsec/filebeat.yml: -------------------------------------------------------------------------------- 1 | output: 2 | logstash: 3 | enabled: true 4 | hosts: '${LOGSTASH_HOST:?must set LOGSTASH_HOST env variable}' 5 | timeout: 15 6 | 7 | 8 | filebeat: 9 | inputs: 10 | - 11 | paths: 12 | - /var/log/modsec_audit_processed.log 13 | type: log 14 | json.keys_under_root: true 15 | json.add_error_key: true 16 | -------------------------------------------------------------------------------- /honeytraps/waf_modsec/form.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | Login 4 | 5 |

Add entry

6 |

Add another Article

7 |
8 |

9 |

10 | 11 |
12 | 13 | -------------------------------------------------------------------------------- /honeytraps/waf_modsec/httpd.conf: -------------------------------------------------------------------------------- 1 | # 2 | # This is the main Apache HTTP server configuration file. It contains the 3 | # configuration directives that give the server its instructions. 4 | # See for detailed information. 5 | # In particular, see 6 | # 7 | # for a discussion of each configuration directive. 8 | # 9 | # Do NOT simply read the instructions in here without understanding 10 | # what they do. They're here only as hints or reminders. If you are unsure 11 | # consult the online docs. You have been warned. 12 | # 13 | # Configuration and logfile names: If the filenames you specify for many 14 | # of the server's control files begin with "/" (or "drive:/" for Win32), the 15 | # server will use that explicit path. If the filenames do *not* begin 16 | # with "/", the value of ServerRoot is prepended -- so "logs/access_log" 17 | # with ServerRoot set to "/usr/local/apache2" will be interpreted by the 18 | # server as "/usr/local/apache2/logs/access_log", whereas "/logs/access_log" 19 | # will be interpreted as '/logs/access_log'. 20 | 21 | # 22 | # ServerRoot: The top of the directory tree under which the server's 23 | # configuration, error, and log files are kept. 24 | # 25 | # Do not add a slash at the end of the directory path. If you point 26 | # ServerRoot at a non-local disk, be sure to specify a local disk on the 27 | # Mutex directive, if file-based mutexes are used. If you wish to share the 28 | # same ServerRoot for multiple httpd daemons, you will need to change at 29 | # least PidFile. 30 | # 31 | ServerRoot "/usr/local/apache2" 32 | 33 | # 34 | # Mutex: Allows you to set the mutex mechanism and mutex file directory 35 | # for individual mutexes, or change the global defaults 36 | # 37 | # Uncomment and change the directory if mutexes are file-based and the default 38 | # mutex file directory is not on a local disk or is not appropriate for some 39 | # other reason. 40 | # 41 | # Mutex default:logs 42 | 43 | # 44 | # Listen: Allows you to bind Apache to specific IP addresses and/or 45 | # ports, instead of the default. See also the 46 | # directive. 47 | # 48 | # Change this to Listen on specific IP addresses as shown below to 49 | # prevent Apache from glomming onto all bound IP addresses. 50 | # 51 | #Listen 12.34.56.78:80 52 | Listen 80 53 | 54 | # 55 | # Dynamic Shared Object (DSO) Support 56 | # 57 | # To be able to use the functionality of a module which was built as a DSO you 58 | # have to place corresponding `LoadModule' lines at this location so the 59 | # directives contained in it are actually available _before_ they are used. 60 | # Statically compiled modules (those listed by `httpd -l') do not need 61 | # to be loaded here. 62 | # 63 | # Example: 64 | # LoadModule foo_module modules/mod_foo.so 65 | # 66 | LoadModule mpm_event_module modules/mod_mpm_event.so 67 | #LoadModule mpm_prefork_module modules/mod_mpm_prefork.so 68 | #LoadModule mpm_worker_module modules/mod_mpm_worker.so 69 | LoadModule authn_file_module modules/mod_authn_file.so 70 | #LoadModule authn_dbm_module modules/mod_authn_dbm.so 71 | #LoadModule authn_anon_module modules/mod_authn_anon.so 72 | #LoadModule authn_dbd_module modules/mod_authn_dbd.so 73 | #LoadModule authn_socache_module modules/mod_authn_socache.so 74 | LoadModule authn_core_module modules/mod_authn_core.so 75 | LoadModule authz_host_module modules/mod_authz_host.so 76 | LoadModule authz_groupfile_module modules/mod_authz_groupfile.so 77 | LoadModule authz_user_module modules/mod_authz_user.so 78 | #LoadModule authz_dbm_module modules/mod_authz_dbm.so 79 | #LoadModule authz_owner_module modules/mod_authz_owner.so 80 | #LoadModule authz_dbd_module modules/mod_authz_dbd.so 81 | LoadModule authz_core_module modules/mod_authz_core.so 82 | #LoadModule authnz_ldap_module modules/mod_authnz_ldap.so 83 | #LoadModule authnz_fcgi_module modules/mod_authnz_fcgi.so 84 | LoadModule access_compat_module modules/mod_access_compat.so 85 | LoadModule auth_basic_module modules/mod_auth_basic.so 86 | #LoadModule auth_form_module modules/mod_auth_form.so 87 | #LoadModule auth_digest_module modules/mod_auth_digest.so 88 | #LoadModule allowmethods_module modules/mod_allowmethods.so 89 | #LoadModule isapi_module modules/mod_isapi.so 90 | #LoadModule file_cache_module modules/mod_file_cache.so 91 | #LoadModule cache_module modules/mod_cache.so 92 | #LoadModule cache_disk_module modules/mod_cache_disk.so 93 | #LoadModule cache_socache_module modules/mod_cache_socache.so 94 | #LoadModule socache_shmcb_module modules/mod_socache_shmcb.so 95 | #LoadModule socache_dbm_module modules/mod_socache_dbm.so 96 | #LoadModule socache_memcache_module modules/mod_socache_memcache.so 97 | #LoadModule socache_redis_module modules/mod_socache_redis.so 98 | #LoadModule watchdog_module modules/mod_watchdog.so 99 | #LoadModule macro_module modules/mod_macro.so 100 | #LoadModule dbd_module modules/mod_dbd.so 101 | #LoadModule bucketeer_module modules/mod_bucketeer.so 102 | #LoadModule dumpio_module modules/mod_dumpio.so 103 | #LoadModule echo_module modules/mod_echo.so 104 | #LoadModule example_hooks_module modules/mod_example_hooks.so 105 | #LoadModule case_filter_module modules/mod_case_filter.so 106 | #LoadModule case_filter_in_module modules/mod_case_filter_in.so 107 | #LoadModule example_ipc_module modules/mod_example_ipc.so 108 | #LoadModule buffer_module modules/mod_buffer.so 109 | #LoadModule data_module modules/mod_data.so 110 | #LoadModule ratelimit_module modules/mod_ratelimit.so 111 | LoadModule reqtimeout_module modules/mod_reqtimeout.so 112 | #LoadModule ext_filter_module modules/mod_ext_filter.so 113 | #LoadModule request_module modules/mod_request.so 114 | #LoadModule include_module modules/mod_include.so 115 | LoadModule filter_module modules/mod_filter.so 116 | #LoadModule reflector_module modules/mod_reflector.so 117 | #LoadModule substitute_module modules/mod_substitute.so 118 | #LoadModule sed_module modules/mod_sed.so 119 | #LoadModule charset_lite_module modules/mod_charset_lite.so 120 | #LoadModule deflate_module modules/mod_deflate.so 121 | #LoadModule xml2enc_module modules/mod_xml2enc.so 122 | #LoadModule proxy_html_module modules/mod_proxy_html.so 123 | LoadModule mime_module modules/mod_mime.so 124 | #LoadModule ldap_module modules/mod_ldap.so 125 | LoadModule log_config_module modules/mod_log_config.so 126 | #LoadModule log_debug_module modules/mod_log_debug.so 127 | #LoadModule log_forensic_module modules/mod_log_forensic.so 128 | #LoadModule logio_module modules/mod_logio.so 129 | #LoadModule lua_module modules/mod_lua.so 130 | LoadModule env_module modules/mod_env.so 131 | #LoadModule mime_magic_module modules/mod_mime_magic.so 132 | #LoadModule cern_meta_module modules/mod_cern_meta.so 133 | #LoadModule expires_module modules/mod_expires.so 134 | LoadModule headers_module modules/mod_headers.so 135 | #LoadModule ident_module modules/mod_ident.so 136 | #LoadModule usertrack_module modules/mod_usertrack.so 137 | LoadModule unique_id_module modules/mod_unique_id.so 138 | LoadModule setenvif_module modules/mod_setenvif.so 139 | LoadModule version_module modules/mod_version.so 140 | #LoadModule remoteip_module modules/mod_remoteip.so 141 | #LoadModule proxy_module modules/mod_proxy.so 142 | #LoadModule proxy_connect_module modules/mod_proxy_connect.so 143 | #LoadModule proxy_ftp_module modules/mod_proxy_ftp.so 144 | #LoadModule proxy_http_module modules/mod_proxy_http.so 145 | #LoadModule proxy_fcgi_module modules/mod_proxy_fcgi.so 146 | #LoadModule proxy_scgi_module modules/mod_proxy_scgi.so 147 | #LoadModule proxy_uwsgi_module modules/mod_proxy_uwsgi.so 148 | #LoadModule proxy_fdpass_module modules/mod_proxy_fdpass.so 149 | #LoadModule proxy_wstunnel_module modules/mod_proxy_wstunnel.so 150 | #LoadModule proxy_ajp_module modules/mod_proxy_ajp.so 151 | #LoadModule proxy_balancer_module modules/mod_proxy_balancer.so 152 | #LoadModule proxy_express_module modules/mod_proxy_express.so 153 | #LoadModule proxy_hcheck_module modules/mod_proxy_hcheck.so 154 | #LoadModule session_module modules/mod_session.so 155 | #LoadModule session_cookie_module modules/mod_session_cookie.so 156 | #LoadModule session_crypto_module modules/mod_session_crypto.so 157 | #LoadModule session_dbd_module modules/mod_session_dbd.so 158 | #LoadModule slotmem_shm_module modules/mod_slotmem_shm.so 159 | #LoadModule slotmem_plain_module modules/mod_slotmem_plain.so 160 | #LoadModule ssl_module modules/mod_ssl.so 161 | #LoadModule optional_hook_export_module modules/mod_optional_hook_export.so 162 | #LoadModule optional_hook_import_module modules/mod_optional_hook_import.so 163 | #LoadModule optional_fn_import_module modules/mod_optional_fn_import.so 164 | #LoadModule optional_fn_export_module modules/mod_optional_fn_export.so 165 | #LoadModule dialup_module modules/mod_dialup.so 166 | #LoadModule http2_module modules/mod_http2.so 167 | #LoadModule proxy_http2_module modules/mod_proxy_http2.so 168 | #LoadModule lbmethod_byrequests_module modules/mod_lbmethod_byrequests.so 169 | #LoadModule lbmethod_bytraffic_module modules/mod_lbmethod_bytraffic.so 170 | #LoadModule lbmethod_bybusyness_module modules/mod_lbmethod_bybusyness.so 171 | #LoadModule lbmethod_heartbeat_module modules/mod_lbmethod_heartbeat.so 172 | LoadModule unixd_module modules/mod_unixd.so 173 | #LoadModule heartbeat_module modules/mod_heartbeat.so 174 | #LoadModule heartmonitor_module modules/mod_heartmonitor.so 175 | #LoadModule dav_module modules/mod_dav.so 176 | LoadModule status_module modules/mod_status.so 177 | LoadModule autoindex_module modules/mod_autoindex.so 178 | #LoadModule asis_module modules/mod_asis.so 179 | #LoadModule info_module modules/mod_info.so 180 | #LoadModule suexec_module modules/mod_suexec.so 181 | 182 | #LoadModule cgid_module modules/mod_cgid.so 183 | 184 | 185 | #LoadModule cgi_module modules/mod_cgi.so 186 | 187 | #LoadModule dav_fs_module modules/mod_dav_fs.so 188 | #LoadModule dav_lock_module modules/mod_dav_lock.so 189 | #LoadModule vhost_alias_module modules/mod_vhost_alias.so 190 | #LoadModule negotiation_module modules/mod_negotiation.so 191 | LoadModule dir_module modules/mod_dir.so 192 | #LoadModule imagemap_module modules/mod_imagemap.so 193 | #LoadModule actions_module modules/mod_actions.so 194 | #LoadModule speling_module modules/mod_speling.so 195 | #LoadModule userdir_module modules/mod_userdir.so 196 | LoadModule alias_module modules/mod_alias.so 197 | #LoadModule rewrite_module modules/mod_rewrite.so 198 | 199 | 200 | # 201 | # If you wish httpd to run as a different user or group, you must run 202 | # httpd as root initially and it will switch. 203 | # 204 | # User/Group: The name (or #number) of the user/group to run httpd as. 205 | # It is usually good practice to create a dedicated user and group for 206 | # running httpd, as with most system services. 207 | # 208 | User daemon 209 | Group daemon 210 | 211 | 212 | 213 | # 'Main' server configuration 214 | # 215 | # The directives in this section set up the values used by the 'main' 216 | # server, which responds to any requests that aren't handled by a 217 | # definition. These values also provide defaults for 218 | # any containers you may define later in the file. 219 | # 220 | # All of these directives may appear inside containers, 221 | # in which case these default settings will be overridden for the 222 | # virtual host being defined. 223 | # 224 | 225 | # 226 | # ServerAdmin: Your address, where problems with the server should be 227 | # e-mailed. This address appears on some server-generated pages, such 228 | # as error documents. e.g. admin@your-domain.com 229 | # 230 | ServerAdmin you@example.com 231 | 232 | # 233 | # ServerName gives the name and port that the server uses to identify itself. 234 | # This can often be determined automatically, but we recommend you specify 235 | # it explicitly to prevent problems during startup. 236 | # 237 | # If your host doesn't have a registered DNS name, enter its IP address here. 238 | # 239 | #ServerName www.example.com:80 240 | 241 | # 242 | # Deny access to the entirety of your server's filesystem. You must 243 | # explicitly permit access to web content directories in other 244 | # blocks below. 245 | # 246 | 247 | AllowOverride none 248 | Require all denied 249 | 250 | 251 | # 252 | # Note that from this point forward you must specifically allow 253 | # particular features to be enabled - so if something's not working as 254 | # you might expect, make sure that you have specifically enabled it 255 | # below. 256 | # 257 | 258 | # 259 | # DocumentRoot: The directory out of which you will serve your 260 | # documents. By default, all requests are taken from this directory, but 261 | # symbolic links and aliases may be used to point to other locations. 262 | # 263 | DocumentRoot "/usr/local/apache2/htdocs" 264 | 265 | # 266 | # Possible values for the Options directive are "None", "All", 267 | # or any combination of: 268 | # Indexes Includes FollowSymLinks SymLinksifOwnerMatch ExecCGI MultiViews 269 | # 270 | # Note that "MultiViews" must be named *explicitly* --- "Options All" 271 | # doesn't give it to you. 272 | # 273 | # The Options directive is both complicated and important. Please see 274 | # http://httpd.apache.org/docs/2.4/mod/core.html#options 275 | # for more information. 276 | # 277 | Options Indexes FollowSymLinks 278 | 279 | # 280 | # AllowOverride controls what directives may be placed in .htaccess files. 281 | # It can be "All", "None", or any combination of the keywords: 282 | # AllowOverride FileInfo AuthConfig Limit 283 | # 284 | AllowOverride None 285 | 286 | # 287 | # Controls who can get stuff from this server. 288 | # 289 | Require all granted 290 | 291 | 292 | # 293 | # DirectoryIndex: sets the file that Apache will serve if a directory 294 | # is requested. 295 | # 296 | 297 | DirectoryIndex index.html 298 | 299 | 300 | # 301 | # The following lines prevent .htaccess and .htpasswd files from being 302 | # viewed by Web clients. 303 | # 304 | 305 | Require all denied 306 | 307 | 308 | # 309 | # ErrorLog: The location of the error log file. 310 | # If you do not specify an ErrorLog directive within a 311 | # container, error messages relating to that virtual host will be 312 | # logged here. If you *do* define an error logfile for a 313 | # container, that host's errors will be logged there and not here. 314 | # 315 | ErrorLog /proc/self/fd/2 316 | 317 | # 318 | # LogLevel: Control the number of messages logged to the error_log. 319 | # Possible values include: debug, info, notice, warn, error, crit, 320 | # alert, emerg. 321 | # 322 | LogLevel warn 323 | 324 | 325 | # 326 | # The following directives define some format nicknames for use with 327 | # a CustomLog directive (see below). 328 | # 329 | LogFormat "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\"" combined 330 | LogFormat "%h %l %u %t \"%r\" %>s %b" common 331 | 332 | 333 | # You need to enable mod_logio.c to use %I and %O 334 | LogFormat "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\" %I %O" combinedio 335 | 336 | 337 | # 338 | # The location and format of the access logfile (Common Logfile Format). 339 | # If you do not define any access logfiles within a 340 | # container, they will be logged here. Contrariwise, if you *do* 341 | # define per- access logfiles, transactions will be 342 | # logged therein and *not* in this file. 343 | # 344 | CustomLog /proc/self/fd/1 common 345 | 346 | # 347 | # If you prefer a logfile with access, agent, and referer information 348 | # (Combined Logfile Format) you can use the following directive. 349 | # 350 | #CustomLog "logs/access_log" combined 351 | 352 | 353 | 354 | # 355 | # Redirect: Allows you to tell clients about documents that used to 356 | # exist in your server's namespace, but do not anymore. The client 357 | # will make a new request for the document at its new location. 358 | # Example: 359 | # Redirect permanent /foo http://www.example.com/bar 360 | 361 | # 362 | # Alias: Maps web paths into filesystem paths and is used to 363 | # access content that does not live under the DocumentRoot. 364 | # Example: 365 | # Alias /webpath /full/filesystem/path 366 | # 367 | # If you include a trailing / on /webpath then the server will 368 | # require it to be present in the URL. You will also likely 369 | # need to provide a section to allow access to 370 | # the filesystem path. 371 | 372 | # 373 | # ScriptAlias: This controls which directories contain server scripts. 374 | # ScriptAliases are essentially the same as Aliases, except that 375 | # documents in the target directory are treated as applications and 376 | # run by the server when requested rather than as documents sent to the 377 | # client. The same rules about trailing "/" apply to ScriptAlias 378 | # directives as to Alias. 379 | # 380 | ScriptAlias /cgi-bin/ "/usr/local/apache2/cgi-bin/" 381 | 382 | 383 | 384 | 385 | # 386 | # ScriptSock: On threaded servers, designate the path to the UNIX 387 | # socket used to communicate with the CGI daemon of mod_cgid. 388 | # 389 | #Scriptsock cgisock 390 | 391 | 392 | # 393 | # "/usr/local/apache2/cgi-bin" should be changed to whatever your ScriptAliased 394 | # CGI directory exists, if you have that configured. 395 | # 396 | 397 | AllowOverride None 398 | Options None 399 | Require all granted 400 | 401 | 402 | 403 | # 404 | # Avoid passing HTTP_PROXY environment to CGI's on this or any proxied 405 | # backend servers which have lingering "httpoxy" defects. 406 | # 'Proxy' request header is undefined by the IETF, not listed by IANA 407 | # 408 | RequestHeader unset Proxy early 409 | 410 | 411 | 412 | # 413 | # TypesConfig points to the file containing the list of mappings from 414 | # filename extension to MIME-type. 415 | # 416 | TypesConfig conf/mime.types 417 | 418 | # 419 | # AddType allows you to add to or override the MIME configuration 420 | # file specified in TypesConfig for specific file types. 421 | # 422 | #AddType application/x-gzip .tgz 423 | # 424 | # AddEncoding allows you to have certain browsers uncompress 425 | # information on the fly. Note: Not all browsers support this. 426 | # 427 | #AddEncoding x-compress .Z 428 | #AddEncoding x-gzip .gz .tgz 429 | # 430 | # If the AddEncoding directives above are commented-out, then you 431 | # probably should define those extensions to indicate media types: 432 | # 433 | AddType application/x-compress .Z 434 | AddType application/x-gzip .gz .tgz 435 | 436 | # 437 | # AddHandler allows you to map certain file extensions to "handlers": 438 | # actions unrelated to filetype. These can be either built into the server 439 | # or added with the Action directive (see below) 440 | # 441 | # To use CGI scripts outside of ScriptAliased directories: 442 | # (You will also need to add "ExecCGI" to the "Options" directive.) 443 | # 444 | #AddHandler cgi-script .cgi 445 | 446 | # For type maps (negotiated resources): 447 | #AddHandler type-map var 448 | 449 | # 450 | # Filters allow you to process content before it is sent to the client. 451 | # 452 | # To parse .shtml files for server-side includes (SSI): 453 | # (You will also need to add "Includes" to the "Options" directive.) 454 | # 455 | #AddType text/html .shtml 456 | #AddOutputFilter INCLUDES .shtml 457 | 458 | 459 | # 460 | # The mod_mime_magic module allows the server to use various hints from the 461 | # contents of the file itself to determine its type. The MIMEMagicFile 462 | # directive tells the module where the hint definitions are located. 463 | # 464 | #MIMEMagicFile conf/magic 465 | 466 | # 467 | # Customizable error responses come in three flavors: 468 | # 1) plain text 2) local redirects 3) external redirects 469 | # 470 | # Some examples: 471 | #ErrorDocument 500 "The server made a boo boo." 472 | #ErrorDocument 404 /missing.html 473 | #ErrorDocument 404 "/cgi-bin/missing_handler.pl" 474 | #ErrorDocument 402 http://www.example.com/subscription_info.html 475 | # 476 | 477 | # 478 | # MaxRanges: Maximum number of Ranges in a request before 479 | # returning the entire resource, or one of the special 480 | # values 'default', 'none' or 'unlimited'. 481 | # Default setting is to accept 200 Ranges. 482 | #MaxRanges unlimited 483 | 484 | # 485 | # EnableMMAP and EnableSendfile: On systems that support it, 486 | # memory-mapping or the sendfile syscall may be used to deliver 487 | # files. This usually improves server performance, but must 488 | # be turned off when serving from networked-mounted 489 | # filesystems or if support for these functions is otherwise 490 | # broken on your system. 491 | # Defaults: EnableMMAP On, EnableSendfile Off 492 | # 493 | #EnableMMAP off 494 | #EnableSendfile on 495 | 496 | # Supplemental configuration 497 | # 498 | # The configuration files in the conf/extra/ directory can be 499 | # included to add extra features or to modify the default configuration of 500 | # the server, or you may simply copy their contents here and change as 501 | # necessary. 502 | 503 | # Server-pool management (MPM specific) 504 | #Include conf/extra/httpd-mpm.conf 505 | 506 | # Multi-language error messages 507 | #Include conf/extra/httpd-multilang-errordoc.conf 508 | 509 | # Fancy directory listings 510 | #Include conf/extra/httpd-autoindex.conf 511 | 512 | # Language settings 513 | #Include conf/extra/httpd-languages.conf 514 | 515 | # User home directories 516 | #Include conf/extra/httpd-userdir.conf 517 | 518 | # Real-time info on requests and configuration 519 | #Include conf/extra/httpd-info.conf 520 | 521 | # Virtual hosts 522 | #Include conf/extra/httpd-vhosts.conf 523 | 524 | # Local access to the Apache HTTP Server Manual 525 | #Include conf/extra/httpd-manual.conf 526 | 527 | # Distributed authoring and versioning (WebDAV) 528 | #Include conf/extra/httpd-dav.conf 529 | 530 | # Various default settings 531 | #Include conf/extra/httpd-default.conf 532 | 533 | # Configure mod_proxy_html to understand HTML4/XHTML1 534 | 535 | Include conf/extra/proxy-html.conf 536 | 537 | 538 | # Secure (SSL/TLS) connections 539 | #Include conf/extra/httpd-ssl.conf 540 | # 541 | # Note: The following must must be present to support 542 | # starting without SSL on platforms with no /dev/random equivalent 543 | # but a statically compiled-in mod_ssl. 544 | # 545 | 546 | SSLRandomSeed startup builtin 547 | SSLRandomSeed connect builtin 548 | 549 | 550 | ErrorLog /var/log/apache2/error.log 551 | LoadModule security2_module /usr/local/apache2/modules/mod_security2.so 552 | Include conf/extra/httpd-default.conf 553 | 554 | Include /etc/modsecurity.d/include.conf 555 | 556 | Include conf/extra/httpd-logging-after-modsec.conf 557 | ServerName ${SERVERNAME} 558 | 559 | Include conf/extra/httpd-proxy.conf 560 | 561 | 562 | # ------------------------------ 563 | # HoneyTrap Changes 564 | # ------------------------------ 565 | Listen 8000 566 | Listen 8080 567 | Listen 8888 568 | 569 | #Adding Support for robots.txt 570 | 571 | SetHandler None 572 | Require all granted 573 | 574 | #Alias /robots.txt /home/robots.txt -------------------------------------------------------------------------------- /honeytraps/waf_modsec/include.conf: -------------------------------------------------------------------------------- 1 | include "/etc/modsecurity.d/modsecurity.conf" 2 | include /etc/modsecurity.d/owasp-crs/crs-setup.conf 3 | include /etc/modsecurity.d/owasp-crs/rules/*.conf -------------------------------------------------------------------------------- /honeytraps/waf_modsec/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Login 5 | 6 | 7 |

Add entry

8 |

Add another Article

9 |
10 |

11 |

12 | 13 |
14 | 15 | -------------------------------------------------------------------------------- /honeytraps/waf_modsec/login.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Login 5 | 6 | 7 |

Add entry

8 |

Add another Article

9 | 10 |
11 |

12 |

13 | 14 |
15 | 16 | -------------------------------------------------------------------------------- /honeytraps/waf_modsec/login.php: -------------------------------------------------------------------------------- 1 | 14 | 15 | 16 | 17 | 18 | Login 19 | 20 | 21 |
22 | " id="username" name="username" /> 23 | 24 |
25 | 26 |
27 | 28 | -------------------------------------------------------------------------------- /honeytraps/waf_modsec/modsec_entry.sh: -------------------------------------------------------------------------------- 1 | # ~/bin/sh 2 | apachectl 3 | python3 /app/preprocess-modsec-log.py & 4 | filebeat -e -c filebeat.yml -d "publish" 5 | -------------------------------------------------------------------------------- /honeytraps/waf_modsec/modsecurity-extension.conf: -------------------------------------------------------------------------------- 1 | ## APPENDED TO THE END OF 2 | # /etc/modsecurity.d/modsecurity.conf 3 | 4 | 5 | SecAuditLogFormat JSON 6 | SecContentInjection On 7 | SecStreamOutBodyInspection On 8 | 9 | ##HONEYTRAP-1 10 | 11 | # # Generate Alerts for all requests that we receive and # set a variable in the IP Collection to mark the client # as malicious. # 12 | SecRule SERVER_PORT "^(8000|8080|8888)$" \ 13 | "id:'999004',phase:2,t:none,log,block,msg:'HoneyTrap Alert: Traffic Received on Fake Port.',setvar:ip.malicious_client=1" 14 | ##HONEYTRAP-2 15 | #Fake robots.txt file 16 | 17 | SecRule REQUEST_FILENAME "@streq /robots.txt" \ 18 | "id:'999005',phase:4,t:none,nolog,pass,append:'Disallow: /db_backup.%{time_epoch}/'" 19 | 20 | #Identifying the malicious client 21 | 22 | SecRule REQUEST_FILENAME "^/db_backup.\d{10}" "id:'999006',phase:1,t:none,log,block,msg:'HoneyTrap Alert: Disallowed robots.txt Entry Accessed.',logdata:'%{matched_var}',setvar:ip.malicious_client=1" 23 | 24 | #Setting the Fake Authentication 25 | SecRule REQUEST_FILENAME "^/db_backup.\d{10}" "id:'999011',phase:3,t:none,log,deny,status:401,msg:'HoneyTrapAlert:Disallowed robots.txt Entry Accessed.',logdata:'%{matched_var}',setvar:ip.malicious_client=1, setenv:basic_auth=1" 26 | Header always set WWW-Authenticate "Basic realm=\"Admin\"" env=basic_auth 27 | 28 | #For Decoding the Password given by the Hacker 29 | #we use following ruleset to extract and decode thecredentials. 30 | 31 | SecRule REQUEST_FILENAME "^/db_backup.\d{10}" "chain,id:'999012',phase:1,t:none,log,msg:'HoneyTrap Alert: Authentication Attempt to Fake Resource.',logdata:'Credentials used: %{matched_var}'" 32 | 33 | SecRule REQUEST_HEADERS:Authorization "^Basic (.*)" "chain,capture" 34 | 35 | SecRule TX:1 ".*" "t:base64Decode" 36 | 37 | ##HONEYTRAP-3 38 | 39 | ##We will add some fake HTML comments 40 | ##With this data, an attacker may be able to better plan and execute attacks against your web application 41 | 42 | SecRule REQUEST_FILENAME "@streq /login.html" "chain,id:'999007',phase:4,t:none,nolog,pass,setvar:'tx.form_comment_honeytrap=
'" 43 | 44 | SecRule STREAM_OUTPUT_BODY "@rsub s/%{tx.form_comment_honeytrap}/%{tx.form_comment_honeytrap}/d" 45 | 46 | SecRule REQUEST_FILENAME "@streq /login.php.bak" "id:'999008',phase:1,t:none,log,block,msg:'HoneyTrap Alert: Fake HTML Comment Data Used.',setvar:ip.malicious_client=1" 47 | 48 | ##HONEYTRAP-4 49 | 50 | 51 | 52 | # Adding Fake Hidden Form Fields 53 | # 54 | # Add a fake "debug" hidden parameter to forms. 55 | # 56 | # Here are some examples of parameter names/values that could be 57 | # used: 58 | # 59 | # - debug=false 60 | # - debug=0 61 | # - role=user 62 | # - role=1 63 | # - admin=false 64 | # - admin=0 65 | # 66 | # Make sure that your settings here match the detection rules above. 67 | # 68 | SecRule STREAM_OUTPUT_BODY "@rsub s/<\/form>/<\/form>/" "id:'999009',phase:4,t:none,nolog,pass" 69 | 70 | #Detecting the client if the rule is triggered 71 | 72 | SecRule ARGS:debug "!@streq false" "id:'999010',phase:2,t:none,log,block,msg:'HoneyTrap Alert: Fake HIDDEN Form Data Manipulated.',setvar:ip.malicious_client=1" 73 | 74 | ##HONEYTRAP-5 75 | ##Adding Fake Cookies 76 | 77 | SecRule RESPONSE_HEADERS:Set-Cookie "^(.*?)=" "id:'999013',phase:3,t:none,nolog,pass,capture,setenv:honeytrap_cookie_name=%{tx.1}-user_role" 78 | 79 | Header always set Set-Cookie "%{HONEYTRAP_COOKIE_NAME}e=Admin:0" 80 | 81 | SecRule REQUEST_HEADERS:Cookie "@contains %{global.honeytrap_cookie_name}" "chain,id:'999014',phase:1,t:none,log,block,msg:'HoneyTrap Alert: Fake Cookie Data Manipulation'" 82 | 83 | SecRule REQUEST_HEADERS:Cookie "!@contains =Admin:0" "setvar:ip.malicious_client=1" 84 | -------------------------------------------------------------------------------- /honeytraps/waf_modsec/preprocess-modsec-log.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | ## --------------------------------------------------------------------- 3 | ## 4 | ## A hack to preprocess Modsecurity JSON logs into a proper JSON format 5 | ## Hopefully this can be removed as soon as ModSecurity updates to not to 6 | ## have a shitty format for the actual audit_data 7 | ## 8 | ## ---------------------------------------------------------------------- 9 | 10 | ### 11 | ### This script watches var/log/modsec_audit.log and processes logs as they 12 | ### come in, 13 | ### 14 | 15 | import json 16 | import re 17 | import sys 18 | import time 19 | import logging 20 | from typing import Tuple, List, Dict, Any 21 | from watchdog.observers import Observer 22 | from watchdog.events import FileSystemEventHandler 23 | 24 | class LineParser: 25 | '''parses audit_log.messages and audit_log.error_messages''' 26 | __tagRegex__ = ' \[.*? .*?\]|^\[.*? .*?\]' 27 | 28 | def __parseTag__(self, tag) -> Tuple[str, str]: 29 | tag = tag.strip() # Strip leading/trailing whitespace 30 | tag = tag[1:-1] # remove brackets 31 | tag = tag.split(" ", 1) # split by first space to get key and value 32 | key = tag[0] 33 | value = tag[1][1:-1] if tag[1].startswith("\"") else tag[1] # strip quotes from value if its a string 34 | return (key, value) 35 | 36 | def __parseMessages__(self, messages) -> Dict[str, Any]: 37 | events = dict() 38 | index = 0 39 | for message in messages: 40 | event = dict() 41 | # Get all tags in square brackets 42 | tags = re.findall(self.__tagRegex__, message) 43 | for chunk in tags: 44 | [key, value] = self.__parseTag__(chunk) 45 | if (key == "tag"): 46 | if (event.get('tags', None) == None): 47 | event['tags'] = [] 48 | event['tags'].append(value) 49 | pass 50 | else: 51 | event[key] = value 52 | pass 53 | 54 | # Get type and pattern 55 | leftovers = (re.sub(self.__tagRegex__, '', message)) 56 | leftovers = leftovers.split(".") 57 | 58 | event['type'] = leftovers[0].strip() 59 | event['pattern'] = leftovers[1].strip() 60 | events['message-' + str(index)] = event # Logstash can't process nested object arrays so we use dicts 61 | index+= 1 62 | return events 63 | 64 | def parse(self, logLine) -> Dict[str, Any]: 65 | parsed = json.loads(logLine) 66 | #parsed['audit_data']['messages'] = self.__parseMessages__(parsed['audit_data']['messages']) 67 | #parsed['audit_data']['error_messages'] = self.__parseMessages__(parsed['audit_data']['error_messages']) 68 | # Same reason, Logstash can't process deeply nested JSON, putting them into root level instead 69 | parsed['messages'] = self.__parseMessages__(parsed['audit_data']['messages']) 70 | parsed['error_messages'] = self.__parseMessages__(parsed['audit_data']['error_messages']) 71 | del parsed['audit_data']['messages'] 72 | del parsed['audit_data']['error_messages'] 73 | return parsed 74 | 75 | class fileHandler(FileSystemEventHandler): 76 | parser = LineParser() 77 | lineNum = None 78 | processdLineNum = None 79 | originalPath = "/var/log/modsec_audit.log" 80 | processedPath = "/var/log/modsec_audit_processed.log" 81 | 82 | def on_modified(self, event): 83 | if "modsec_audit.log" in event.src_path: 84 | log.info("Logfile changed") 85 | self.processLog() 86 | else: 87 | #log.info("log did not change, path: " + event.src_path) 88 | pass 89 | 90 | def processLog(self) -> None: 91 | # Getting lines and total number of lines 92 | processedLines = self.getLines(self.processedPath) 93 | lines = self.getLines(self.originalPath) 94 | procIndex = 0 if processedLines is None else len(processedLines) 95 | log.debug("Processed file lines", procIndex) 96 | origIndex = 0 if lines is None else len(lines) 97 | log.debug("Original file lines", origIndex) 98 | 99 | # Getting current head to process from 100 | [index, writeMode] = self.getHead(origIndex, procIndex) 101 | log.debug("Head", index) 102 | log.debug("Write Mode", writeMode) 103 | 104 | # Log line prasing/modification 105 | newLines = [] 106 | for i in range(index, len(lines)): 107 | newLines.append(json.dumps(self.parser.parse(lines[i]))) 108 | 109 | # Write to the new file 110 | try: 111 | file = open(self.processedPath, writeMode) 112 | for line in newLines: 113 | file.write(line + "\n") 114 | #log.info(newLines) 115 | file.close() 116 | except Exception as e: 117 | log.error("Error writing to file", e) 118 | 119 | def getLines(self, path) -> List[str]: 120 | try: 121 | file = open(path, "r") 122 | lines = file.readlines() 123 | file.close() 124 | return lines 125 | except FileNotFoundError as e: 126 | return None 127 | 128 | def getHead(self, origFileIndex, newFileIndex) -> Tuple[int, str]: 129 | # returns (index, write mode) 130 | if (origFileIndex <= newFileIndex): return (0, "w") 131 | if (newFileIndex == 0): return (0, "a") 132 | if (newFileIndex > 0 and origFileIndex > newFileIndex): return (newFileIndex, "a") 133 | raise NotImplementedError("Case not implemented") 134 | 135 | if __name__ == "__main__": 136 | PATH="/var/log/" 137 | logging.basicConfig(level=logging.INFO, format='[%(asctime)s][%(levelname)s][%(name)s] %(message)s') 138 | log = logging.getLogger("Python-Script") 139 | handler = logging.FileHandler('/var/log/preprocess-script.log') 140 | formatter = logging.Formatter('[%(asctime)s][%(levelname)s][%(name)s] %(message)s') 141 | handler.setFormatter(formatter) 142 | handler.setLevel(logging.INFO) 143 | log.addHandler(handler) 144 | log.info("Python script is starting up...") 145 | event_handler = fileHandler() 146 | observer = Observer() 147 | observer.schedule(event_handler, PATH, recursive=True) 148 | observer.start() 149 | try: 150 | while True: 151 | time.sleep(1) 152 | except KeyboardInterrupt: 153 | observer.stop() 154 | observer.join() 155 | -------------------------------------------------------------------------------- /honeytraps/waf_modsec/robots.txt: -------------------------------------------------------------------------------- 1 | User-agent: * 2 | Allow: / 3 | User-agent: Googlebot 4 | Disallow: /backup/ 5 | Disallow: /cgi-bin/ 6 | Disallow: /admin.bak/ 7 | Disallow: /old/ 8 | -------------------------------------------------------------------------------- /honeytraps/waf_modsec/sample-env: -------------------------------------------------------------------------------- 1 | LOGSTASH_HOST=192.168.0.12:5044 -------------------------------------------------------------------------------- /mds_elk/README.md: -------------------------------------------------------------------------------- 1 | ## Proof of Concept For Sending the ModSecurity Logs to ELK 2 | 3 | The goal of this PoC to send the ModSecurity Audit Logs to ELK 4 | 5 | In this setup we have two Docker Containers. One for ModSecurity and the other for ELK. 6 | ### Step by Step Instructions 7 | * Dependencies for the setup 8 | * Docker Installed on your Host machine 9 | * Ports listed in docker-compose.yml should be available free in host machine 10 | * If ports are not free, please change to appropriate values in docker-compose.yml 11 | 12 | * Clone this repository in your Host Machine 13 | ``` 14 | cd ~ 15 | git clone https://github.com/OWASP/Honeypot-Project.git 16 | ``` 17 | * To start the setup run the below command 18 | ``` 19 | cd Honeypot-Project/mds_elk/ 20 | docker-compose build 21 | docker-compose up -d 22 | ``` 23 | * Check the status of containers 24 | ``` 25 | docker ps 26 | ``` 27 | 28 | * Send the Logs from ModSec to ELK (Elastic Logstash Kibana) 29 | * Now we are ready to pump the data from the ModSec to ELK with the help of filebeat 30 | ``` 31 | Run the below commands to observe the logs in the rubydebug console of logstash 32 | curl localhost:9091/index.html?exec=/bin/bash 33 | curl 'http://localhost:9091/?q=">' 34 | ``` 35 | 36 | * Wait for a minute or two for the logs to reach the ELK 37 | * Open http://localhost:5601/app/kibana in your browser 38 | * Create an Index with the name filebeat* and Press Next 39 | ![Alt text](./screenshots/filebeat_index_create.png?raw=true "Filebeat index creation") 40 | * Use Time Filter field name: @timestamp 41 | ![Alt text](./screenshots/filebeat_index_create_2.png?raw=true "Filebeat index creation") 42 | * Navigate to Discover Menu on the Left Hand Side and logs can be visualized in Kibana Dashboard 43 | ![Alt text](./screenshots/filebeat_logs.png?raw=true "Visualizing the ModSecurity Audit Logs") 44 | * **Issues**: 45 | * max virtual memory areas vm.max_map_count [65530] is too low, increase to at least [262144], Run the below command 46 | ``` 47 | sudo sysctl -w vm.max_map_count=262144 48 | ``` 49 | * If there is problem running with logstash, try with 50 | ``` 51 | /opt/logstash/bin/logstash --path.data /tmp/logstash/data -e filebeat_logstash.conf 52 | ``` 53 | * **References** 54 | * https://elk-docker.readthedocs.io/ 55 | * https://www.elastic.co/guide/en/beats/filebeat/5.1/filebeat-installation.html 56 | * https://medium.com/tensult/log-centralization-using-filebeat-and-logstash-11640f77cf70 57 | * https://github.com/docker-library/elasticsearch/issues/111 58 | * https://hub.docker.com/r/owasp/modsecurity-crs/ 59 | -------------------------------------------------------------------------------- /mds_elk/docker-compose.yml: -------------------------------------------------------------------------------- 1 | elk: 2 | ports: 3 | - "5601:5601" 4 | - "9200:9200" 5 | - "5044:5044" 6 | volumes: 7 | - .:/app 8 | environment: 9 | - LOGSTASH_START=0 10 | build: ./waf_elk/ 11 | container_name: elk_app 12 | 13 | modsec_crs: 14 | ports: 15 | - "9091:80" 16 | - "8000:8000" 17 | - "8080:8080" 18 | - "8888:8888" 19 | environment: 20 | - PARANOIA=5 21 | volumes: 22 | - .:/app 23 | links: 24 | - elk 25 | build: ./waf_modsec/ 26 | container_name: modsec_app 27 | privileged: true 28 | -------------------------------------------------------------------------------- /mds_elk/screenshots/filebeat_index_create.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OWASP/Honeypot-Project/45bcf2a30da7e0c6face45882bd1c2f2827e0a0b/mds_elk/screenshots/filebeat_index_create.png -------------------------------------------------------------------------------- /mds_elk/screenshots/filebeat_index_create_2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OWASP/Honeypot-Project/45bcf2a30da7e0c6face45882bd1c2f2827e0a0b/mds_elk/screenshots/filebeat_index_create_2.png -------------------------------------------------------------------------------- /mds_elk/screenshots/filebeat_logs.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OWASP/Honeypot-Project/45bcf2a30da7e0c6face45882bd1c2f2827e0a0b/mds_elk/screenshots/filebeat_logs.png -------------------------------------------------------------------------------- /mds_elk/waf_elk/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM sebp/elk 2 | COPY filebeat_logstash.conf /etc/logstash/conf.d/filebeat_logstash.conf 3 | ADD ./start.sh /usr/local/bin/start.sh 4 | RUN chmod +x /usr/local/bin/start.sh 5 | EXPOSE 5601 9200 9300 5044 6 | VOLUME /var/lib/elasticsearch 7 | CMD [ "/usr/local/bin/start.sh" ] 8 | -------------------------------------------------------------------------------- /mds_elk/waf_elk/elk_entry.sh: -------------------------------------------------------------------------------- 1 | cd /etc/logstash/conf.d/ 2 | /opt/logstash/bin/logstash -f filebeat_logstash.conf 3 | -------------------------------------------------------------------------------- /mds_elk/waf_elk/filebeat_logstash.conf: -------------------------------------------------------------------------------- 1 | input { 2 | beats { 3 | port => 5044 4 | } 5 | } 6 | 7 | output { 8 | elasticsearch { 9 | hosts => "localhost:9200" 10 | manage_template => false 11 | index => "%{[@metadata][beat]}-%{+YYYY.MM.dd}" 12 | document_type => "%{[@metadata][type]}" 13 | } 14 | stdout { codec => rubydebug } 15 | } 16 | -------------------------------------------------------------------------------- /mds_elk/waf_elk/start.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # 3 | # /usr/local/bin/start.sh 4 | # Start Elasticsearch, Logstash and Kibana services 5 | # 6 | # spujadas 2015-10-09; added initial pidfile removal and graceful termination 7 | 8 | # WARNING - This script assumes that the ELK services are not running, and is 9 | # only expected to be run once, when the container is started. 10 | # Do not attempt to run this script if the ELK services are running (or be 11 | # prepared to reap zombie processes). 12 | 13 | 14 | ## handle termination gracefully 15 | 16 | _term() { 17 | echo "Terminating ELK" 18 | service elasticsearch stop 19 | service logstash stop 20 | service kibana stop 21 | exit 0 22 | } 23 | 24 | trap _term SIGTERM SIGINT 25 | 26 | 27 | ## remove pidfiles in case previous graceful termination failed 28 | # NOTE - This is the reason for the WARNING at the top - it's a bit hackish, 29 | # but if it's good enough for Fedora (https://goo.gl/88eyXJ), it's good 30 | # enough for me :) 31 | 32 | rm -f /var/run/elasticsearch/elasticsearch.pid /var/run/logstash.pid \ 33 | /var/run/kibana5.pid 34 | 35 | ## initialise list of log files to stream in console (initially empty) 36 | OUTPUT_LOGFILES="" 37 | 38 | 39 | ## override default time zone (Etc/UTC) if TZ variable is set 40 | if [ ! -z "$TZ" ]; then 41 | ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone 42 | fi 43 | 44 | 45 | ## run pre-hooks 46 | if [ -x /usr/local/bin/elk-pre-hooks.sh ]; then 47 | . /usr/local/bin/elk-pre-hooks.sh 48 | fi 49 | 50 | 51 | ## start services as needed 52 | 53 | ### crond 54 | 55 | service cron start 56 | 57 | 58 | ### Elasticsearch 59 | 60 | if [ -z "$ELASTICSEARCH_START" ]; then 61 | ELASTICSEARCH_START=1 62 | fi 63 | if [ "$ELASTICSEARCH_START" -ne "1" ]; then 64 | echo "ELASTICSEARCH_START is set to something different from 1, not starting..." 65 | else 66 | # update permissions of ES data directory 67 | chown -R elasticsearch:elasticsearch /var/lib/elasticsearch 68 | 69 | # override ES_HEAP_SIZE variable if set 70 | if [ ! -z "$ES_HEAP_SIZE" ]; then 71 | awk -v LINE="-Xmx$ES_HEAP_SIZE" '{ sub(/^.Xmx.*/, LINE); print; }' ${ES_PATH_CONF}/jvm.options \ 72 | > ${ES_PATH_CONF}/jvm.options.new && mv ${ES_PATH_CONF}/jvm.options.new ${ES_PATH_CONF}/jvm.options 73 | awk -v LINE="-Xms$ES_HEAP_SIZE" '{ sub(/^.Xms.*/, LINE); print; }' ${ES_PATH_CONF}/jvm.options \ 74 | > ${ES_PATH_CONF}/jvm.options.new && mv ${ES_PATH_CONF}/jvm.options.new ${ES_PATH_CONF}/jvm.options 75 | fi 76 | 77 | if [ ! -z "$ES_HEAP_DISABLE" ]; then 78 | awk -v LINE="#-XX:+HeapDumpOnOutOfMemoryError" '{ sub(/^-XX:\+HeapDumpOnOutOfMemoryError.*/, LINE); print; }' ${ES_PATH_CONF}/jvm.options \ 79 | > ${ES_PATH_CONF}/jvm.options.new && mv ${ES_PATH_CONF}/jvm.options.new ${ES_PATH_CONF}/jvm.options 80 | fi 81 | 82 | # override ES_JAVA_OPTS variable if set 83 | if [ ! -z "$ES_JAVA_OPTS" ]; then 84 | awk -v LINE="ES_JAVA_OPTS=\"$ES_JAVA_OPTS\"" '{ sub(/^#?ES_JAVA_OPTS=.*/, LINE); print; }' /etc/default/elasticsearch \ 85 | > /etc/default/elasticsearch.new && mv /etc/default/elasticsearch.new /etc/default/elasticsearch 86 | fi 87 | 88 | # override MAX_OPEN_FILES variable if set 89 | if [ ! -z "$MAX_OPEN_FILES" ]; then 90 | awk -v LINE="MAX_OPEN_FILES=$MAX_OPEN_FILES" '{ sub(/^#?MAX_OPEN_FILES=.*/, LINE); print; }' /etc/init.d/elasticsearch \ 91 | > /etc/init.d/elasticsearch.new && mv /etc/init.d/elasticsearch.new /etc/init.d/elasticsearch \ 92 | && chmod +x /etc/init.d/elasticsearch 93 | fi 94 | 95 | # override MAX_MAP_COUNT variable if set 96 | if [ ! -z "$MAX_MAP_COUNT" ]; then 97 | awk -v LINE="MAX_MAP_COUNT=$MAX_MAP_COUNT" '{ sub(/^#?MAX_MAP_COUNT=.*/, LINE); print; }' /etc/init.d/elasticsearch \ 98 | > /etc/init.d/elasticsearch.new && mv /etc/init.d/elasticsearch.new /etc/init.d/elasticsearch \ 99 | && chmod +x /etc/init.d/elasticsearch 100 | fi 101 | 102 | service elasticsearch start 103 | 104 | # wait for Elasticsearch to start up before either starting Kibana (if enabled) 105 | # or attempting to stream its log file 106 | # - https://github.com/elasticsearch/kibana/issues/3077 107 | 108 | # set number of retries (default: 30, override using ES_CONNECT_RETRY env var) 109 | re_is_numeric='^[0-9]+$' 110 | if ! [[ $ES_CONNECT_RETRY =~ $re_is_numeric ]] ; then 111 | ES_CONNECT_RETRY=30 112 | fi 113 | 114 | if [ -z "$ELASTICSEARCH_URL" ]; then 115 | ELASTICSEARCH_URL=${ES_PROTOCOL:-http}://localhost:9200 116 | fi 117 | 118 | counter=0 119 | while [ ! "$(curl -k ${ELASTICSEARCH_URL} 2> /dev/null)" -a $counter -lt $ES_CONNECT_RETRY ]; do 120 | sleep 1 121 | ((counter++)) 122 | echo "waiting for Elasticsearch to be up ($counter/$ES_CONNECT_RETRY)" 123 | done 124 | if [ ! "$(curl -k ${ELASTICSEARCH_URL} 2> /dev/null)" ]; then 125 | echo "Couln't start Elasticsearch. Exiting." 126 | echo "Elasticsearch log follows below." 127 | cat /var/log/elasticsearch/elasticsearch.log 128 | exit 1 129 | fi 130 | 131 | # wait for cluster to respond before getting its name 132 | counter=0 133 | while [ -z "$CLUSTER_NAME" -a $counter -lt 30 ]; do 134 | sleep 1 135 | ((counter++)) 136 | CLUSTER_NAME=$(curl -k ${ELASTICSEARCH_URL}/_cat/health?h=cluster 2> /dev/null | tr -d '[:space:]') 137 | echo "Waiting for Elasticsearch cluster to respond ($counter/30)" 138 | done 139 | if [ -z "$CLUSTER_NAME" ]; then 140 | echo "Couln't get name of cluster. Exiting." 141 | echo "Elasticsearch log follows below." 142 | cat /var/log/elasticsearch/elasticsearch.log 143 | exit 1 144 | fi 145 | OUTPUT_LOGFILES+="/var/log/elasticsearch/${CLUSTER_NAME}.log " 146 | fi 147 | 148 | 149 | ### Logstash 150 | 151 | if [ -z "$LOGSTASH_START" ]; then 152 | LOGSTASH_START=1 153 | fi 154 | if [ "$LOGSTASH_START" -ne "1" ]; then 155 | echo "LOGSTASH_START is set to something different from 1, not starting..." 156 | else 157 | # override LS_HEAP_SIZE variable if set 158 | if [ ! -z "$LS_HEAP_SIZE" ]; then 159 | awk -v LINE="-Xmx$LS_HEAP_SIZE" '{ sub(/^.Xmx.*/, LINE); print; }' ${LOGSTASH_PATH_SETTINGS}/jvm.options \ 160 | > ${LOGSTASH_PATH_SETTINGS}/jvm.options.new && mv ${LOGSTASH_PATH_SETTINGS}/jvm.options.new ${LOGSTASH_PATH_SETTINGS}/jvm.options 161 | awk -v LINE="-Xms$LS_HEAP_SIZE" '{ sub(/^.Xms.*/, LINE); print; }' ${LOGSTASH_PATH_SETTINGS}/jvm.options \ 162 | > ${LOGSTASH_PATH_SETTINGS}/jvm.options.new && mv ${LOGSTASH_PATH_SETTINGS}/jvm.options.new ${LOGSTASH_PATH_SETTINGS}/jvm.options 163 | fi 164 | 165 | if [ ! -z "$LS_HEAP_DISABLE" ]; then 166 | awk -v LINE="#-XX:+HeapDumpOnOutOfMemoryError" '{ sub(/^-XX:\+HeapDumpOnOutOfMemoryError.*/, LINE); print; }' ${LOGSTASH_PATH_SETTINGS}/jvm.options \ 167 | > ${LOGSTASH_PATH_SETTINGS}/jvm.options.new && mv ${LOGSTASH_PATH_SETTINGS}/jvm.options.new ${LOGSTASH_PATH_SETTINGS}/jvm.options 168 | fi 169 | 170 | # override LS_OPTS variable if set 171 | if [ ! -z "$LS_OPTS" ]; then 172 | awk -v LINE="LS_OPTS=\"$LS_OPTS\"" '{ sub(/^LS_OPTS=.*/, LINE); print; }' /etc/init.d/logstash \ 173 | > /etc/init.d/logstash.new && mv /etc/init.d/logstash.new /etc/init.d/logstash && chmod +x /etc/init.d/logstash 174 | fi 175 | 176 | service logstash start 177 | OUTPUT_LOGFILES+="/var/log/logstash/logstash-plain.log " 178 | fi 179 | 180 | 181 | ### Kibana 182 | 183 | if [ -z "$KIBANA_START" ]; then 184 | KIBANA_START=1 185 | fi 186 | if [ "$KIBANA_START" -ne "1" ]; then 187 | echo "KIBANA_START is set to something different from 1, not starting..." 188 | else 189 | # override NODE_OPTIONS variable if set 190 | if [ ! -z "$NODE_OPTIONS" ]; then 191 | awk -v LINE="NODE_OPTIONS=\"$NODE_OPTIONS\"" '{ sub(/^NODE_OPTIONS=.*/, LINE); print; }' /etc/init.d/kibana \ 192 | > /etc/init.d/kibana.new && mv /etc/init.d/kibana.new /etc/init.d/kibana && chmod +x /etc/init.d/kibana 193 | fi 194 | 195 | service kibana start 196 | OUTPUT_LOGFILES+="/var/log/kibana/kibana5.log " 197 | fi 198 | 199 | # Exit if nothing has been started 200 | if [ "$ELASTICSEARCH_START" -ne "1" ] && [ "$LOGSTASH_START" -ne "1" ] \ 201 | && [ "$KIBANA_START" -ne "1" ]; then 202 | >&2 echo "No services started. Exiting." 203 | exit 1 204 | fi 205 | 206 | 207 | ## run post-hooks 208 | if [ -x /usr/local/bin/elk-post-hooks.sh ]; then 209 | ### if Kibana was started... 210 | if [ "$KIBANA_START" -eq "1" ]; then 211 | 212 | ### ... then wait for Kibana to be up first to ensure that .kibana index is 213 | ### created before the of post-hooks are executed 214 | # set number of retries (default: 30, override using KIBANA_CONNECT_RETRY env var) 215 | if ! [[ $KIBANA_CONNECT_RETRY =~ $re_is_numeric ]] ; then 216 | KIBANA_CONNECT_RETRY=30 217 | fi 218 | 219 | if [ -z "$KIBANA_URL" ]; then 220 | KIBANA_URL=http://localhost:5601 221 | fi 222 | 223 | counter=0 224 | while [ ! "$(curl ${KIBANA_URL} 2> /dev/null)" -a $counter -lt $KIBANA_CONNECT_RETRY ]; do 225 | sleep 1 226 | ((counter++)) 227 | echo "waiting for Kibana to be up ($counter/$KIBANA_CONNECT_RETRY)" 228 | done 229 | if [ ! "$(curl ${KIBANA_URL} 2> /dev/null)" ]; then 230 | echo "Couln't start Kibana. Exiting." 231 | echo "Kibana log follows below." 232 | cat /var/log/kibana/kibana5.log 233 | exit 1 234 | fi 235 | fi 236 | 237 | . /usr/local/bin/elk-post-hooks.sh 238 | fi 239 | 240 | /opt/logstash/bin/logstash -f /etc/logstash/conf.d/filebeat_logstash.conf 241 | 242 | touch $OUTPUT_LOGFILES 243 | tail -f $OUTPUT_LOGFILES & 244 | wait 245 | -------------------------------------------------------------------------------- /mds_elk/waf_modsec/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM owasp/modsecurity-crs 2 | RUN apt install -y wget nano curl 3 | RUN wget https://artifacts.elastic.co/downloads/beats/filebeat/filebeat-7.2.0-amd64.deb 4 | RUN dpkg -i filebeat-7.2.0-amd64.deb 5 | COPY filebeat.yml /etc/filebeat/filebeat.yml 6 | COPY filebeat.template.json /etc/filebeat/filebeat.template.json 7 | COPY modsec_entry.sh / 8 | COPY modsecurity.conf /etc/modsecurity.d/ 9 | RUN chmod +x /modsec_entry.sh 10 | CMD ["/modsec_entry.sh"] 11 | -------------------------------------------------------------------------------- /mds_elk/waf_modsec/docker-entrypoint.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | curl -H 'Content-Type: application/json' -XPUT 'http://elk:9200/_template/filebeat' -d@/etc/filebeat/filebeat.template.json 3 | -------------------------------------------------------------------------------- /mds_elk/waf_modsec/filebeat.yml: -------------------------------------------------------------------------------- 1 | output: 2 | logstash: 3 | enabled: true 4 | hosts: 5 | - elk:5044 6 | timeout: 15 7 | 8 | 9 | filebeat: 10 | inputs: 11 | - 12 | paths: 13 | - /var/log/modsec_audit.log 14 | document_type: syslog 15 | -------------------------------------------------------------------------------- /mds_elk/waf_modsec/modsec_entry.sh: -------------------------------------------------------------------------------- 1 | # ~/bin/sh 2 | curl -H 'Content-Type: application/json' -XPUT 'http://elk:9200/_template/filebeat' -d@/etc/filebeat/filebeat.template.json 3 | chmod go-w /etc/filebeat/filebeat.yml 4 | apachectl 5 | filebeat -e -c filebeat.yml -d "publish" 6 | -------------------------------------------------------------------------------- /mds_elk/waf_modsec/modsecurity.conf: -------------------------------------------------------------------------------- 1 | # -- Rule engine initialization ---------------------------------------------- 2 | 3 | # Enable ModSecurity, attaching it to every transaction. Use detection 4 | # only to start with, because that minimises the chances of post-installation 5 | # disruption. 6 | # 7 | SecRuleEngine On 8 | 9 | 10 | # -- Request body handling --------------------------------------------------- 11 | 12 | # Allow ModSecurity to access request bodies. If you don't, ModSecurity 13 | # won't be able to see any POST parameters, which opens a large security 14 | # hole for attackers to exploit. 15 | # 16 | SecRequestBodyAccess On 17 | 18 | 19 | # Enable XML request body parser. 20 | # Initiate XML Processor in case of xml content-type 21 | # 22 | SecRule REQUEST_HEADERS:Content-Type "(?:text|application)/xml" \ 23 | "id:'200000',phase:1,t:none,t:lowercase,pass,nolog,ctl:requestBodyProcessor=XML" 24 | 25 | # Enable JSON request body parser. 26 | # Initiate JSON Processor in case of JSON content-type; change accordingly 27 | # if your application does not use 'application/json' 28 | # 29 | SecRule REQUEST_HEADERS:Content-Type "application/json" \ 30 | "id:'200001',phase:1,t:none,t:lowercase,pass,nolog,ctl:requestBodyProcessor=JSON" 31 | 32 | # Maximum request body size we will accept for buffering. If you support 33 | # file uploads then the value given on the first line has to be as large 34 | # as the largest file you are willing to accept. The second value refers 35 | # to the size of data, with files excluded. You want to keep that value as 36 | # low as practical. 37 | # 38 | SecRequestBodyLimit 13107200 39 | SecRequestBodyNoFilesLimit 131072 40 | 41 | # Store up to 128 KB of request body data in memory. When the multipart 42 | # parser reachers this limit, it will start using your hard disk for 43 | # storage. That is slow, but unavoidable. 44 | # 45 | SecRequestBodyInMemoryLimit 131072 46 | 47 | # What do do if the request body size is above our configured limit. 48 | # Keep in mind that this setting will automatically be set to ProcessPartial 49 | # when SecRuleEngine is set to DetectionOnly mode in order to minimize 50 | # disruptions when initially deploying ModSecurity. 51 | # 52 | SecRequestBodyLimitAction Reject 53 | 54 | # Verify that we've correctly processed the request body. 55 | # As a rule of thumb, when failing to process a request body 56 | # you should reject the request (when deployed in blocking mode) 57 | # or log a high-severity alert (when deployed in detection-only mode). 58 | # 59 | SecRule REQBODY_ERROR "!@eq 0" \ 60 | "id:'200002', phase:2,t:none,log,deny,status:400,msg:'Failed to parse request body.',logdata:'%{reqbody_error_msg}',severity:2" 61 | 62 | # By default be strict with what we accept in the multipart/form-data 63 | # request body. If the rule below proves to be too strict for your 64 | # environment consider changing it to detection-only. You are encouraged 65 | # _not_ to remove it altogether. 66 | # 67 | SecRule MULTIPART_STRICT_ERROR "!@eq 0" \ 68 | "id:'200003',phase:2,t:none,log,deny,status:400, \ 69 | msg:'Multipart request body failed strict validation: \ 70 | PE %{REQBODY_PROCESSOR_ERROR}, \ 71 | BQ %{MULTIPART_BOUNDARY_QUOTED}, \ 72 | BW %{MULTIPART_BOUNDARY_WHITESPACE}, \ 73 | DB %{MULTIPART_DATA_BEFORE}, \ 74 | DA %{MULTIPART_DATA_AFTER}, \ 75 | HF %{MULTIPART_HEADER_FOLDING}, \ 76 | LF %{MULTIPART_LF_LINE}, \ 77 | SM %{MULTIPART_MISSING_SEMICOLON}, \ 78 | IQ %{MULTIPART_INVALID_QUOTING}, \ 79 | IP %{MULTIPART_INVALID_PART}, \ 80 | IH %{MULTIPART_INVALID_HEADER_FOLDING}, \ 81 | FL %{MULTIPART_FILE_LIMIT_EXCEEDED}'" 82 | 83 | # Did we see anything that might be a boundary? 84 | # 85 | SecRule MULTIPART_UNMATCHED_BOUNDARY "!@eq 0" \ 86 | "id:'200004',phase:2,t:none,log,deny,msg:'Multipart parser detected a possible unmatched boundary.'" 87 | 88 | # PCRE Tuning 89 | # We want to avoid a potential RegEx DoS condition 90 | # 91 | SecPcreMatchLimit 1000 92 | SecPcreMatchLimitRecursion 1000 93 | 94 | # Some internal errors will set flags in TX and we will need to look for these. 95 | # All of these are prefixed with "MSC_". The following flags currently exist: 96 | # 97 | # MSC_PCRE_LIMITS_EXCEEDED: PCRE match limits were exceeded. 98 | # 99 | SecRule TX:/^MSC_/ "!@streq 0" \ 100 | "id:'200005',phase:2,t:none,deny,msg:'ModSecurity internal error flagged: %{MATCHED_VAR_NAME}'" 101 | 102 | 103 | # -- Response body handling -------------------------------------------------- 104 | 105 | # Allow ModSecurity to access response bodies. 106 | # You should have this directive enabled in order to identify errors 107 | # and data leakage issues. 108 | # 109 | # Do keep in mind that enabling this directive does increases both 110 | # memory consumption and response latency. 111 | # 112 | SecResponseBodyAccess On 113 | 114 | # Which response MIME types do you want to inspect? You should adjust the 115 | # configuration below to catch documents but avoid static files 116 | # (e.g., images and archives). 117 | # 118 | SecResponseBodyMimeType text/plain text/html text/xml 119 | 120 | # Buffer response bodies of up to 512 KB in length. 121 | SecResponseBodyLimit 524288 122 | 123 | # What happens when we encounter a response body larger than the configured 124 | # limit? By default, we process what we have and let the rest through. 125 | # That's somewhat less secure, but does not break any legitimate pages. 126 | # 127 | SecResponseBodyLimitAction ProcessPartial 128 | 129 | 130 | # -- Filesystem configuration ------------------------------------------------ 131 | 132 | # The location where ModSecurity stores temporary files (for example, when 133 | # it needs to handle a file upload that is larger than the configured limit). 134 | # 135 | # This default setting is chosen due to all systems have /tmp available however, 136 | # this is less than ideal. It is recommended that you specify a location that's private. 137 | # 138 | SecTmpDir /tmp/ 139 | 140 | # The location where ModSecurity will keep its persistent data. This default setting 141 | # is chosen due to all systems have /tmp available however, it 142 | # too should be updated to a place that other users can't access. 143 | # 144 | SecDataDir /tmp/ 145 | 146 | 147 | # -- File uploads handling configuration ------------------------------------- 148 | 149 | # The location where ModSecurity stores intercepted uploaded files. This 150 | # location must be private to ModSecurity. You don't want other users on 151 | # the server to access the files, do you? 152 | # 153 | #SecUploadDir /opt/modsecurity/var/upload/ 154 | 155 | # By default, only keep the files that were determined to be unusual 156 | # in some way (by an external inspection script). For this to work you 157 | # will also need at least one file inspection rule. 158 | # 159 | #SecUploadKeepFiles RelevantOnly 160 | 161 | # Uploaded files are by default created with permissions that do not allow 162 | # any other user to access them. You may need to relax that if you want to 163 | # interface ModSecurity to an external program (e.g., an anti-virus). 164 | # 165 | #SecUploadFileMode 0600 166 | 167 | 168 | # -- Debug log configuration ------------------------------------------------- 169 | 170 | # The default debug log configuration is to duplicate the error, warning 171 | # and notice messages from the error log. 172 | # 173 | #SecDebugLog /opt/modsecurity/var/log/debug.log 174 | #SecDebugLogLevel 3 175 | 176 | 177 | # -- Audit log configuration ------------------------------------------------- 178 | 179 | # Log the transactions that are marked by a rule, as well as those that 180 | # trigger a server error (determined by a 5xx or 4xx, excluding 404, 181 | # level response status codes). 182 | # 183 | SecAuditEngine RelevantOnly 184 | SecAuditLogRelevantStatus "^(?:5|4(?!04))" 185 | 186 | # Log everything we know about a transaction. 187 | SecAuditLogParts ABIJDEFHZ 188 | 189 | # Use a single file for logging. This is much easier to look at, but 190 | # assumes that you will use the audit log only ocassionally. 191 | # 192 | SecAuditLogType Serial 193 | SecAuditLog /var/log/modsec_audit.log 194 | 195 | # Specify the path for concurrent audit logging. 196 | #SecAuditLogStorageDir /opt/modsecurity/var/audit/ 197 | 198 | 199 | # -- Miscellaneous ----------------------------------------------------------- 200 | 201 | # Use the most commonly used application/x-www-form-urlencoded parameter 202 | # separator. There's probably only one application somewhere that uses 203 | # something else so don't expect to change this value. 204 | # 205 | SecArgumentSeparator & 206 | 207 | # Settle on version 0 (zero) cookies, as that is what most applications 208 | # use. Using an incorrect cookie version may open your installation to 209 | # evasion attacks (against the rules that examine named cookies). 210 | # 211 | SecCookieFormat 0 212 | 213 | # Specify your Unicode Code Point. 214 | # This mapping is used by the t:urlDecodeUni transformation function 215 | # to properly map encoded data to your language. Properly setting 216 | # these directives helps to reduce false positives and negatives. 217 | # 218 | SecUnicodeMapFile unicode.mapping 20127 219 | 220 | # Improve the quality of ModSecurity by sharing information about your 221 | # current ModSecurity version and dependencies versions. 222 | # The following information will be shared: ModSecurity version, 223 | # Web Server version, APR version, PCRE version, Lua version, Libxml2 224 | # version, Anonymous unique id for host. 225 | SecStatusEngine On 226 | 227 | # # Generate Alerts for all requests that we receive and # set a variable in the IP Collection to mark the client # as malicious. # 228 | # # Generate Alerts for all requests that we receive and # set a variable in the IP Collection to mark the client # as malicious. # 229 | SecRule SERVER_PORT "^(8000|8080|8888)$" \ 230 | "id:'999004',phase:2,t:none,log,block,msg:'HoneyTrap Alert: Traffic Received on Fake Port.',setvar:ip.malicious_client=1" 231 | -------------------------------------------------------------------------------- /misp-doc/README.md: -------------------------------------------------------------------------------- 1 | ## Setting the MISP Server and Creating Threat Events using PyMISP 2 | 3 | Malware Information Sharing Platform (MISP) is an open source threat intelligence platform that develops utilities and documentation for more effective threat intelligence, by sharing indicators of compromise. 4 | 5 | The goal of this PoC to setup the MISP Docker instance and manually create threat events with tags. Later we will automate the threat information sharing using PyMISP. 6 | 7 | Let's breakdown the PoC into two steps. 8 | * MISP Setup 9 | * Event Generation from PyMISP 10 | 11 | Before continuing, please make sure Python3 and Docker are installed on your system. Also ensure ports 443,80 and 3306 are not used. If used please change the port mapping while starting the MISP container. 12 | 13 | 14 | 15 | ### MISP Setup 16 | 17 | * Pull the MISP docker image from Dockerhub. 18 | ``` 19 | docker pull harvarditsecurity/misp 20 | ``` 21 | 22 | * Make sure the MISP image is listed on available docker images. 23 | ``` 24 | docker images 25 | ``` 26 | 27 | * Create a directory for MISP and export a variable `dockerroot` that specifies the path of created directory. 28 | ``` 29 | mkdir ~/misp 30 | export dockerroot=~/misp 31 | ``` 32 | 33 | * Create a Database directory and initialize Database. 34 | ``` 35 | mkdir -p $dockerroot/misp-db 36 | docker run -it --rm -v $dockerroot/misp-db:/var/lib/mysql harvarditsecurity/misp /init-db 37 | ``` 38 | 39 | * Start the MISP container 40 | ``` 41 | docker run -it -d -p 443:443 -p 80:80 -p 3306:3306 -v $dockerroot/misp-db:/var/lib/mysql harvarditsecurity/misp 42 | ``` 43 | 44 | * Access Web URL and change the password. 45 | ``` 46 | Go to: https://localhost 47 | 48 | Login: admin@admin.test 49 | Password: admin 50 | ``` 51 | 52 | * Go to MISP homepage 53 | ![Alt text](./screenshots/misp-home.png?raw=true "MISP Homepage") 54 | 55 | * Add Threat Event 56 | ![Alt text](./screenshots/misp-add-event.png?raw=true "Add Threat Event") 57 | 58 | * Add new tag 59 | ![Alt text](./screenshots/misp-add-tag-menu.png?raw=true "Add Tag Menu") 60 | ![Alt text](./screenshots/misp-add-tag.png?raw=true "Add Tag") 61 | 62 | * List available tags 63 | ![Alt text](./screenshots/misp-list-tags.png?raw=true "List Tags") 64 | 65 | * Double-click on event from list of events and link tag to the created event 66 | ![Alt text](./screenshots/misp-link-tag-event.png?raw=true "Link tag to an event") 67 | 68 | * List of events with tag(s) 69 | ![Alt text](./screenshots/misp-list-events-with-tag.png?raw=true "List Events+Tags") 70 | 71 | 72 | 73 | 74 | ### Event Creation using PyMISP 75 | 76 | * To create events using PyMISP we need an API key. Go to Automation page and copy the key (highlighted in the below image). 77 | ![Alt text](./screenshots/pymisp-key.png?raw=true "API Key for PyMISP") 78 | 79 | 80 | * Update the `misp_key` variable value in keys.py file with the key copied in the above step. 81 | 82 | * Install PyMISP 83 | ``` 84 | sudo pip3 install pymisp 85 | ``` 86 | 87 | * Run the PyMISP code 88 | ``` 89 | python3 create_events.py 90 | ``` 91 | 92 | * Go to list of events. You can see auto-generated event with the new tag "AutoGen-Tag" created from `create_events.py`. 93 | ![Alt text](./screenshots/pymisp-event.png?raw=true "List Events+Tags generated from PyMISP") 94 | 95 | 96 | 97 | * **References** 98 | * https://misp-project.org 99 | * https://github.com/harvard-itsecurity/docker-misp 100 | * https://pymisp.readthedocs.io/ 101 | 102 | -------------------------------------------------------------------------------- /misp-doc/create_events.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | 4 | from pymisp import PyMISP 5 | from keys import misp_url, misp_key, misp_verifycert 6 | 7 | 8 | def init(url, key): 9 | return PyMISP(url, key, misp_verifycert, 'json', debug=True) 10 | 11 | if __name__ == '__main__': 12 | 13 | #### Create an event on MISP 14 | 15 | ##Event consists of distribution, information, analysis and threat 16 | 17 | #The distribution setting used for the attributes and for the newly created event, if relevant. [0-3]. 18 | distrib = 0 19 | 20 | #Used to populate the event info field if no event ID supplied. 21 | info = "This is event generated from PyMISP" 22 | 23 | #The analysis level of the newly created event, if applicable. [0-2] 24 | analysis = 0 25 | 26 | #The threat level ID of the newly created event, if applicable. [1-4] 27 | threat = 1 28 | 29 | misp = init(misp_url, misp_key) 30 | 31 | event = misp.new_event(distrib, threat, analysis, info) 32 | 33 | tag = "Sample-Tag" 34 | misp.add_tag(event, tag, attribute=False) 35 | 36 | new_tag = "AutoGen-Tag" 37 | misp.new_tag(name=new_tag, colour='#00ace6', exportable=True) 38 | 39 | misp.add_tag(event, new_tag, attribute=False) 40 | print(event) 41 | -------------------------------------------------------------------------------- /misp-doc/keys.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | 4 | misp_url = 'https://localhost' 5 | misp_key = 'pfsoob9mktcqSsvb6McHW12Lu8RUA4qvvhhX1Z7t' # The MISP auth key can be found on the MISP web interface under the automation section 6 | misp_verifycert = False 7 | -------------------------------------------------------------------------------- /misp-doc/screenshots/misp-add-event.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OWASP/Honeypot-Project/45bcf2a30da7e0c6face45882bd1c2f2827e0a0b/misp-doc/screenshots/misp-add-event.png -------------------------------------------------------------------------------- /misp-doc/screenshots/misp-add-tag-menu.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OWASP/Honeypot-Project/45bcf2a30da7e0c6face45882bd1c2f2827e0a0b/misp-doc/screenshots/misp-add-tag-menu.png -------------------------------------------------------------------------------- /misp-doc/screenshots/misp-add-tag.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OWASP/Honeypot-Project/45bcf2a30da7e0c6face45882bd1c2f2827e0a0b/misp-doc/screenshots/misp-add-tag.png -------------------------------------------------------------------------------- /misp-doc/screenshots/misp-home.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OWASP/Honeypot-Project/45bcf2a30da7e0c6face45882bd1c2f2827e0a0b/misp-doc/screenshots/misp-home.png -------------------------------------------------------------------------------- /misp-doc/screenshots/misp-link-tag-event.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OWASP/Honeypot-Project/45bcf2a30da7e0c6face45882bd1c2f2827e0a0b/misp-doc/screenshots/misp-link-tag-event.png -------------------------------------------------------------------------------- /misp-doc/screenshots/misp-list-events-with-tag.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OWASP/Honeypot-Project/45bcf2a30da7e0c6face45882bd1c2f2827e0a0b/misp-doc/screenshots/misp-list-events-with-tag.png -------------------------------------------------------------------------------- /misp-doc/screenshots/misp-list-tags.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OWASP/Honeypot-Project/45bcf2a30da7e0c6face45882bd1c2f2827e0a0b/misp-doc/screenshots/misp-list-tags.png -------------------------------------------------------------------------------- /misp-doc/screenshots/pymisp-event.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OWASP/Honeypot-Project/45bcf2a30da7e0c6face45882bd1c2f2827e0a0b/misp-doc/screenshots/pymisp-event.png -------------------------------------------------------------------------------- /misp-doc/screenshots/pymisp-key.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OWASP/Honeypot-Project/45bcf2a30da7e0c6face45882bd1c2f2827e0a0b/misp-doc/screenshots/pymisp-key.png -------------------------------------------------------------------------------- /mlogc_elk/README.md: -------------------------------------------------------------------------------- 1 | ## Proof of Concept For Sending the ModSecurity Logs to ELK 2 | 3 | The goal of this PoC to send the ModSecurity Audit Logs using mlogc to ELK 4 | 5 | In this setup we have two Docker Containers. One for ModSecurity+mlogc and the other for ELK. 6 | ### Step by Step Instructions 7 | * Dependencies for the setup 8 | * Docker Installed on your Host machine 9 | * Ports listed in docker-compose.yml should be available free in host machine 10 | * If ports are not free, please change to appropriate values in docker-compose.yml 11 | 12 | * Clone this repository in your Host Machine 13 | ``` 14 | cd ~ 15 | git clone https://github.com/OWASP/Honeypot-Project.git 16 | ``` 17 | * To start the setup run the below command 18 | ``` 19 | cd Honeypot-Project/mlogc_elk/ 20 | docker-compose build 21 | docker-compose up -d 22 | ``` 23 | * Check the status of containers 24 | ``` 25 | docker ps 26 | ``` 27 | 28 | * Send the Logs from ModSec to ELK (Elastic Logstash Kibana) 29 | * Now we are ready to pump the data from the ModSec to ELK with the help of mlogc 30 | ``` 31 | Run the below commands to observe the logs in the rubydebug console of logstash 32 | curl localhost:9091/index.html?exec=/bin/bash 33 | curl 'http://localhost:9091/?q=">' 34 | ``` 35 | 36 | * Navigate to /var/log/mlogc/data directory 37 | ``` 38 | cd /var/log/mlogc/data 39 | ``` 40 | * You can see the modsecurity logs organized according to date and time. 41 | 42 | 43 | * Wait for a minute or two for the logs to reach the ELK 44 | * Open http://localhost:5601/app/kibana in your browser 45 | * Create an Index with the name mlogc* and Press Next 46 | ![Alt text](./screenshots/mlogc_index_create.png?raw=true "mlogc index creation") 47 | * Use Time Filter field name: @timestamp 48 | ![Alt text](./screenshots/mlogc_index_create_2.png?raw=true "mlogc index creation") 49 | * Navigate to Discover Menu on the Left Hand Side and logs can be visualized in Kibana Dashboard 50 | ![Alt text](./screenshots/mlogc_logs.png?raw=true "Visualizing the ModSecurity Audit Logs") 51 | * **Issues**: 52 | * max virtual memory areas vm.max_map_count [65530] is too low, increase to at least [262144], Run the below command 53 | ``` 54 | sudo sysctl -w vm.max_map_count=262144 55 | ``` 56 | 57 | * **References** 58 | * https://elk-docker.readthedocs.io/ 59 | * https://fossies.org/linux/modsecurity/mlogc/INSTALL 60 | * https://hub.docker.com/r/owasp/modsecurity-crs/ 61 | 62 | -------------------------------------------------------------------------------- /mlogc_elk/docker-compose.yml: -------------------------------------------------------------------------------- 1 | elk: 2 | ports: 3 | - "5601:5601" 4 | - "9200:9200" 5 | - "5044:5044" 6 | - "9300:9300" 7 | volumes: 8 | - .:/app 9 | environment: 10 | - LOGSTASH_START=0 11 | build: ./elk/ 12 | container_name: elk_app 13 | 14 | modsec: 15 | ports: 16 | - "9091:80" 17 | - "8000:8000" 18 | - "8080:8080" 19 | - "8888:8888" 20 | - "9999:9999" 21 | environment: 22 | - PARANOIA=5 23 | volumes: 24 | - .:/app 25 | links: 26 | - elk 27 | build: ./mlogc/ 28 | container_name: mlogc_app 29 | privileged: true 30 | tty: true 31 | -------------------------------------------------------------------------------- /mlogc_elk/elk/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM sebp/elk 2 | ADD ./start.sh /usr/local/bin/start.sh 3 | RUN chmod +x /usr/local/bin/start.sh 4 | EXPOSE 5601 9200 9300 5044 5 | VOLUME /var/lib/elasticsearch 6 | CMD [ "/usr/local/bin/start.sh" ] 7 | -------------------------------------------------------------------------------- /mlogc_elk/elk/elk_entry.sh: -------------------------------------------------------------------------------- 1 | cd /etc/logstash/conf.d/ 2 | /opt/logstash/bin/logstash -f filebeat_logstash.conf 3 | -------------------------------------------------------------------------------- /mlogc_elk/elk/filebeat_logstash.conf: -------------------------------------------------------------------------------- 1 | input { 2 | beats { 3 | port => 5044 4 | } 5 | } 6 | 7 | output { 8 | elasticsearch { 9 | hosts => "localhost:9200" 10 | manage_template => false 11 | index => "%{[@metadata][beat]}-%{+YYYY.MM.dd}" 12 | document_type => "%{[@metadata][type]}" 13 | } 14 | stdout { codec => rubydebug } 15 | } 16 | -------------------------------------------------------------------------------- /mlogc_elk/elk/start.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # 3 | # /usr/local/bin/start.sh 4 | # Start Elasticsearch, Logstash and Kibana services 5 | # 6 | # spujadas 2015-10-09; added initial pidfile removal and graceful termination 7 | 8 | # WARNING - This script assumes that the ELK services are not running, and is 9 | # only expected to be run once, when the container is started. 10 | # Do not attempt to run this script if the ELK services are running (or be 11 | # prepared to reap zombie processes). 12 | 13 | 14 | ## handle termination gracefully 15 | 16 | _term() { 17 | echo "Terminating ELK" 18 | service elasticsearch stop 19 | service logstash stop 20 | service kibana stop 21 | exit 0 22 | } 23 | 24 | trap _term SIGTERM SIGINT 25 | 26 | 27 | ## remove pidfiles in case previous graceful termination failed 28 | # NOTE - This is the reason for the WARNING at the top - it's a bit hackish, 29 | # but if it's good enough for Fedora (https://goo.gl/88eyXJ), it's good 30 | # enough for me :) 31 | 32 | rm -f /var/run/elasticsearch/elasticsearch.pid /var/run/logstash.pid \ 33 | /var/run/kibana5.pid 34 | 35 | ## initialise list of log files to stream in console (initially empty) 36 | OUTPUT_LOGFILES="" 37 | 38 | 39 | ## override default time zone (Etc/UTC) if TZ variable is set 40 | if [ ! -z "$TZ" ]; then 41 | ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone 42 | fi 43 | 44 | 45 | ## run pre-hooks 46 | if [ -x /usr/local/bin/elk-pre-hooks.sh ]; then 47 | . /usr/local/bin/elk-pre-hooks.sh 48 | fi 49 | 50 | 51 | ## start services as needed 52 | 53 | ### crond 54 | 55 | service cron start 56 | 57 | 58 | ### Elasticsearch 59 | 60 | if [ -z "$ELASTICSEARCH_START" ]; then 61 | ELASTICSEARCH_START=1 62 | fi 63 | if [ "$ELASTICSEARCH_START" -ne "1" ]; then 64 | echo "ELASTICSEARCH_START is set to something different from 1, not starting..." 65 | else 66 | # update permissions of ES data directory 67 | chown -R elasticsearch:elasticsearch /var/lib/elasticsearch 68 | 69 | # override ES_HEAP_SIZE variable if set 70 | if [ ! -z "$ES_HEAP_SIZE" ]; then 71 | awk -v LINE="-Xmx$ES_HEAP_SIZE" '{ sub(/^.Xmx.*/, LINE); print; }' ${ES_PATH_CONF}/jvm.options \ 72 | > ${ES_PATH_CONF}/jvm.options.new && mv ${ES_PATH_CONF}/jvm.options.new ${ES_PATH_CONF}/jvm.options 73 | awk -v LINE="-Xms$ES_HEAP_SIZE" '{ sub(/^.Xms.*/, LINE); print; }' ${ES_PATH_CONF}/jvm.options \ 74 | > ${ES_PATH_CONF}/jvm.options.new && mv ${ES_PATH_CONF}/jvm.options.new ${ES_PATH_CONF}/jvm.options 75 | fi 76 | 77 | if [ ! -z "$ES_HEAP_DISABLE" ]; then 78 | awk -v LINE="#-XX:+HeapDumpOnOutOfMemoryError" '{ sub(/^-XX:\+HeapDumpOnOutOfMemoryError.*/, LINE); print; }' ${ES_PATH_CONF}/jvm.options \ 79 | > ${ES_PATH_CONF}/jvm.options.new && mv ${ES_PATH_CONF}/jvm.options.new ${ES_PATH_CONF}/jvm.options 80 | fi 81 | 82 | # override ES_JAVA_OPTS variable if set 83 | if [ ! -z "$ES_JAVA_OPTS" ]; then 84 | awk -v LINE="ES_JAVA_OPTS=\"$ES_JAVA_OPTS\"" '{ sub(/^#?ES_JAVA_OPTS=.*/, LINE); print; }' /etc/default/elasticsearch \ 85 | > /etc/default/elasticsearch.new && mv /etc/default/elasticsearch.new /etc/default/elasticsearch 86 | fi 87 | 88 | # override MAX_OPEN_FILES variable if set 89 | if [ ! -z "$MAX_OPEN_FILES" ]; then 90 | awk -v LINE="MAX_OPEN_FILES=$MAX_OPEN_FILES" '{ sub(/^#?MAX_OPEN_FILES=.*/, LINE); print; }' /etc/init.d/elasticsearch \ 91 | > /etc/init.d/elasticsearch.new && mv /etc/init.d/elasticsearch.new /etc/init.d/elasticsearch \ 92 | && chmod +x /etc/init.d/elasticsearch 93 | fi 94 | 95 | # override MAX_MAP_COUNT variable if set 96 | if [ ! -z "$MAX_MAP_COUNT" ]; then 97 | awk -v LINE="MAX_MAP_COUNT=$MAX_MAP_COUNT" '{ sub(/^#?MAX_MAP_COUNT=.*/, LINE); print; }' /etc/init.d/elasticsearch \ 98 | > /etc/init.d/elasticsearch.new && mv /etc/init.d/elasticsearch.new /etc/init.d/elasticsearch \ 99 | && chmod +x /etc/init.d/elasticsearch 100 | fi 101 | 102 | service elasticsearch start 103 | 104 | # wait for Elasticsearch to start up before either starting Kibana (if enabled) 105 | # or attempting to stream its log file 106 | # - https://github.com/elasticsearch/kibana/issues/3077 107 | 108 | # set number of retries (default: 30, override using ES_CONNECT_RETRY env var) 109 | re_is_numeric='^[0-9]+$' 110 | if ! [[ $ES_CONNECT_RETRY =~ $re_is_numeric ]] ; then 111 | ES_CONNECT_RETRY=30 112 | fi 113 | 114 | if [ -z "$ELASTICSEARCH_URL" ]; then 115 | ELASTICSEARCH_URL=${ES_PROTOCOL:-http}://localhost:9200 116 | fi 117 | 118 | counter=0 119 | while [ ! "$(curl -k ${ELASTICSEARCH_URL} 2> /dev/null)" -a $counter -lt $ES_CONNECT_RETRY ]; do 120 | sleep 1 121 | ((counter++)) 122 | echo "waiting for Elasticsearch to be up ($counter/$ES_CONNECT_RETRY)" 123 | done 124 | if [ ! "$(curl -k ${ELASTICSEARCH_URL} 2> /dev/null)" ]; then 125 | echo "Couln't start Elasticsearch. Exiting." 126 | echo "Elasticsearch log follows below." 127 | cat /var/log/elasticsearch/elasticsearch.log 128 | exit 1 129 | fi 130 | 131 | # wait for cluster to respond before getting its name 132 | counter=0 133 | while [ -z "$CLUSTER_NAME" -a $counter -lt 30 ]; do 134 | sleep 1 135 | ((counter++)) 136 | CLUSTER_NAME=$(curl -k ${ELASTICSEARCH_URL}/_cat/health?h=cluster 2> /dev/null | tr -d '[:space:]') 137 | echo "Waiting for Elasticsearch cluster to respond ($counter/30)" 138 | done 139 | if [ -z "$CLUSTER_NAME" ]; then 140 | echo "Couln't get name of cluster. Exiting." 141 | echo "Elasticsearch log follows below." 142 | cat /var/log/elasticsearch/elasticsearch.log 143 | exit 1 144 | fi 145 | OUTPUT_LOGFILES+="/var/log/elasticsearch/${CLUSTER_NAME}.log " 146 | fi 147 | 148 | 149 | ### Logstash 150 | 151 | if [ -z "$LOGSTASH_START" ]; then 152 | LOGSTASH_START=1 153 | fi 154 | if [ "$LOGSTASH_START" -ne "1" ]; then 155 | echo "LOGSTASH_START is set to something different from 1, not starting..." 156 | else 157 | # override LS_HEAP_SIZE variable if set 158 | if [ ! -z "$LS_HEAP_SIZE" ]; then 159 | awk -v LINE="-Xmx$LS_HEAP_SIZE" '{ sub(/^.Xmx.*/, LINE); print; }' ${LOGSTASH_PATH_SETTINGS}/jvm.options \ 160 | > ${LOGSTASH_PATH_SETTINGS}/jvm.options.new && mv ${LOGSTASH_PATH_SETTINGS}/jvm.options.new ${LOGSTASH_PATH_SETTINGS}/jvm.options 161 | awk -v LINE="-Xms$LS_HEAP_SIZE" '{ sub(/^.Xms.*/, LINE); print; }' ${LOGSTASH_PATH_SETTINGS}/jvm.options \ 162 | > ${LOGSTASH_PATH_SETTINGS}/jvm.options.new && mv ${LOGSTASH_PATH_SETTINGS}/jvm.options.new ${LOGSTASH_PATH_SETTINGS}/jvm.options 163 | fi 164 | 165 | if [ ! -z "$LS_HEAP_DISABLE" ]; then 166 | awk -v LINE="#-XX:+HeapDumpOnOutOfMemoryError" '{ sub(/^-XX:\+HeapDumpOnOutOfMemoryError.*/, LINE); print; }' ${LOGSTASH_PATH_SETTINGS}/jvm.options \ 167 | > ${LOGSTASH_PATH_SETTINGS}/jvm.options.new && mv ${LOGSTASH_PATH_SETTINGS}/jvm.options.new ${LOGSTASH_PATH_SETTINGS}/jvm.options 168 | fi 169 | 170 | # override LS_OPTS variable if set 171 | if [ ! -z "$LS_OPTS" ]; then 172 | awk -v LINE="LS_OPTS=\"$LS_OPTS\"" '{ sub(/^LS_OPTS=.*/, LINE); print; }' /etc/init.d/logstash \ 173 | > /etc/init.d/logstash.new && mv /etc/init.d/logstash.new /etc/init.d/logstash && chmod +x /etc/init.d/logstash 174 | fi 175 | 176 | service logstash start 177 | OUTPUT_LOGFILES+="/var/log/logstash/logstash-plain.log " 178 | fi 179 | 180 | 181 | ### Kibana 182 | 183 | if [ -z "$KIBANA_START" ]; then 184 | KIBANA_START=1 185 | fi 186 | if [ "$KIBANA_START" -ne "1" ]; then 187 | echo "KIBANA_START is set to something different from 1, not starting..." 188 | else 189 | # override NODE_OPTIONS variable if set 190 | if [ ! -z "$NODE_OPTIONS" ]; then 191 | awk -v LINE="NODE_OPTIONS=\"$NODE_OPTIONS\"" '{ sub(/^NODE_OPTIONS=.*/, LINE); print; }' /etc/init.d/kibana \ 192 | > /etc/init.d/kibana.new && mv /etc/init.d/kibana.new /etc/init.d/kibana && chmod +x /etc/init.d/kibana 193 | fi 194 | 195 | service kibana start 196 | OUTPUT_LOGFILES+="/var/log/kibana/kibana5.log " 197 | fi 198 | 199 | # Exit if nothing has been started 200 | if [ "$ELASTICSEARCH_START" -ne "1" ] && [ "$LOGSTASH_START" -ne "1" ] \ 201 | && [ "$KIBANA_START" -ne "1" ]; then 202 | >&2 echo "No services started. Exiting." 203 | exit 1 204 | fi 205 | 206 | 207 | ## run post-hooks 208 | if [ -x /usr/local/bin/elk-post-hooks.sh ]; then 209 | ### if Kibana was started... 210 | if [ "$KIBANA_START" -eq "1" ]; then 211 | 212 | ### ... then wait for Kibana to be up first to ensure that .kibana index is 213 | ### created before the of post-hooks are executed 214 | # set number of retries (default: 30, override using KIBANA_CONNECT_RETRY env var) 215 | if ! [[ $KIBANA_CONNECT_RETRY =~ $re_is_numeric ]] ; then 216 | KIBANA_CONNECT_RETRY=30 217 | fi 218 | 219 | if [ -z "$KIBANA_URL" ]; then 220 | KIBANA_URL=http://localhost:5601 221 | fi 222 | 223 | counter=0 224 | while [ ! "$(curl ${KIBANA_URL} 2> /dev/null)" -a $counter -lt $KIBANA_CONNECT_RETRY ]; do 225 | sleep 1 226 | ((counter++)) 227 | echo "waiting for Kibana to be up ($counter/$KIBANA_CONNECT_RETRY)" 228 | done 229 | if [ ! "$(curl ${KIBANA_URL} 2> /dev/null)" ]; then 230 | echo "Couln't start Kibana. Exiting." 231 | echo "Kibana log follows below." 232 | cat /var/log/kibana/kibana5.log 233 | exit 1 234 | fi 235 | fi 236 | 237 | . /usr/local/bin/elk-post-hooks.sh 238 | fi 239 | 240 | /opt/logstash/bin/logstash -f /etc/logstash/conf.d/filebeat_logstash.conf 241 | 242 | touch $OUTPUT_LOGFILES 243 | tail -f $OUTPUT_LOGFILES & 244 | wait 245 | -------------------------------------------------------------------------------- /mlogc_elk/mlogc/10-modsecurty.conf: -------------------------------------------------------------------------------- 1 | #LoadModule security2_module modules/mod_security2.so 2 | #Include modsecurity.d/*.conf 3 | -------------------------------------------------------------------------------- /mlogc_elk/mlogc/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM owasp/modsecurity-crs 2 | RUN yum install -y mlogc nano 3 | RUN yum install -y java 4 | RUN yum install -y wget 5 | COPY mlogc.conf /etc/mlogc.conf 6 | RUN rm /etc/httpd/modsecurity.d/modsecurity.conf 7 | COPY httpd.conf /etc/httpd/conf/httpd.conf 8 | COPY mod_security.conf /etc/httpd/conf.d/ 9 | COPY 10-modsecurty.conf /etc/httpd/conf.modules.d/ 10 | RUN wget https://artifacts.elastic.co/downloads/logstash/logstash-6.1.0.rpm 11 | RUN rpm -ivh logstash-6.1.0.rpm 12 | COPY logstash.conf /usr/share/logstash/ 13 | ADD config /usr/share/logstash/config 14 | ADD ./start.sh /usr/share/logstash/start.sh 15 | WORKDIR /usr/share/logstash 16 | RUN chmod u+x start.sh 17 | ENTRYPOINT ["./start.sh"] 18 | -------------------------------------------------------------------------------- /mlogc_elk/mlogc/config/jvm.options: -------------------------------------------------------------------------------- 1 | ## JVM configuration 2 | 3 | # Xms represents the initial size of total heap space 4 | # Xmx represents the maximum size of total heap space 5 | 6 | -Xms256m 7 | -Xmx1g 8 | 9 | ################################################################ 10 | ## Expert settings 11 | ################################################################ 12 | ## 13 | ## All settings below this section are considered 14 | ## expert settings. Don't tamper with them unless 15 | ## you understand what you are doing 16 | ## 17 | ################################################################ 18 | 19 | ## GC configuration 20 | -XX:+UseParNewGC 21 | -XX:+UseConcMarkSweepGC 22 | -XX:CMSInitiatingOccupancyFraction=75 23 | -XX:+UseCMSInitiatingOccupancyOnly 24 | 25 | ## optimizations 26 | 27 | # disable calls to System#gc 28 | -XX:+DisableExplicitGC 29 | 30 | ## locale 31 | # Set the locale language 32 | #-Duser.language=en 33 | 34 | # Set the locale country 35 | #-Duser.country=US 36 | 37 | # Set the locale variant, if any 38 | #-Duser.variant= 39 | 40 | ## basic 41 | 42 | # set the I/O temp directory 43 | #-Djava.io.tmpdir=$HOME 44 | 45 | # set to headless, just in case 46 | -Djava.awt.headless=true 47 | 48 | # ensure UTF-8 encoding by default (e.g. filenames) 49 | -Dfile.encoding=UTF-8 50 | 51 | # use our provided JNA always versus the system one 52 | #-Djna.nosys=true 53 | 54 | ## heap dumps 55 | 56 | # generate a heap dump when an allocation from the Java heap fails 57 | # heap dumps are created in the working directory of the JVM 58 | -XX:+HeapDumpOnOutOfMemoryError 59 | 60 | # specify an alternative path for heap dumps 61 | # ensure the directory exists and has sufficient space 62 | #-XX:HeapDumpPath=${LOGSTASH_HOME}/heapdump.hprof 63 | 64 | ## GC logging 65 | #-XX:+PrintGCDetails 66 | #-XX:+PrintGCTimeStamps 67 | #-XX:+PrintGCDateStamps 68 | #-XX:+PrintClassHistogram 69 | #-XX:+PrintTenuringDistribution 70 | #-XX:+PrintGCApplicationStoppedTime 71 | 72 | # log GC status to a file with time stamps 73 | # ensure the directory exists 74 | #-Xloggc:${LS_GC_LOG_FILE} 75 | -------------------------------------------------------------------------------- /mlogc_elk/mlogc/config/log4j2.properties: -------------------------------------------------------------------------------- 1 | status = error 2 | name = LogstashPropertiesConfig 3 | 4 | appender.rolling.type = RollingFile 5 | appender.rolling.name = plain_rolling 6 | appender.rolling.fileName = ${sys:ls.logs}/logstash-${sys:ls.log.format}.log 7 | appender.rolling.filePattern = ${sys:ls.logs}/logstash-${sys:ls.log.format}-%d{yyyy-MM-dd}.log 8 | appender.rolling.policies.type = Policies 9 | appender.rolling.policies.time.type = TimeBasedTriggeringPolicy 10 | appender.rolling.policies.time.interval = 1 11 | appender.rolling.policies.time.modulate = true 12 | appender.rolling.layout.type = PatternLayout 13 | appender.rolling.layout.pattern = [%d{ISO8601}][%-5p][%-25c] %-.10000m%n 14 | 15 | appender.json_rolling.type = RollingFile 16 | appender.json_rolling.name = json_rolling 17 | appender.json_rolling.fileName = ${sys:ls.logs}/logstash-${sys:ls.log.format}.log 18 | appender.json_rolling.filePattern = ${sys:ls.logs}/logstash-${sys:ls.log.format}-%d{yyyy-MM-dd}.log 19 | appender.json_rolling.policies.type = Policies 20 | appender.json_rolling.policies.time.type = TimeBasedTriggeringPolicy 21 | appender.json_rolling.policies.time.interval = 1 22 | appender.json_rolling.policies.time.modulate = true 23 | appender.json_rolling.layout.type = JSONLayout 24 | appender.json_rolling.layout.compact = true 25 | appender.json_rolling.layout.eventEol = true 26 | 27 | rootLogger.level = ${sys:ls.log.level} 28 | rootLogger.appenderRef.rolling.ref = ${sys:ls.log.format}_rolling 29 | -------------------------------------------------------------------------------- /mlogc_elk/mlogc/config/logstash.yml: -------------------------------------------------------------------------------- 1 | # Settings file in YAML 2 | # 3 | # Settings can be specified either in hierarchical form, e.g.: 4 | # 5 | # pipeline: 6 | # batch: 7 | # size: 125 8 | # delay: 5 9 | # 10 | # Or as flat keys: 11 | # 12 | # pipeline.batch.size: 125 13 | # pipeline.batch.delay: 5 14 | # 15 | # ------------ Node identity ------------ 16 | # 17 | # Use a descriptive name for the node: 18 | # 19 | # node.name: test 20 | # 21 | # If omitted the node name will default to the machine's host name 22 | # 23 | # ------------ Data path ------------------ 24 | # 25 | # Which directory should be used by logstash and its plugins 26 | # for any persistent needs. Defaults to LOGSTASH_HOME/data 27 | # 28 | path.data: /var/lib/logstash 29 | # 30 | # ------------ Pipeline Settings -------------- 31 | # 32 | # Set the number of workers that will, in parallel, execute the filters+outputs 33 | # stage of the pipeline. 34 | # 35 | # This defaults to the number of the host's CPU cores. 36 | # 37 | # pipeline.workers: 2 38 | # 39 | # How many workers should be used per output plugin instance 40 | # 41 | # pipeline.output.workers: 1 42 | # 43 | # How many events to retrieve from inputs before sending to filters+workers 44 | # 45 | # pipeline.batch.size: 125 46 | # 47 | # How long to wait before dispatching an undersized batch to filters+workers 48 | # Value is in milliseconds. 49 | # 50 | # pipeline.batch.delay: 5 51 | # 52 | # Force Logstash to exit during shutdown even if there are still inflight 53 | # events in memory. By default, logstash will refuse to quit until all 54 | # received events have been pushed to the outputs. 55 | # 56 | # WARNING: enabling this can lead to data loss during shutdown 57 | # 58 | # pipeline.unsafe_shutdown: false 59 | # 60 | # ------------ Pipeline Configuration Settings -------------- 61 | # 62 | # Where to fetch the pipeline configuration for the main pipeline 63 | # 64 | path.config: /etc/logstash/conf.d/*.conf 65 | # 66 | # Pipeline configuration string for the main pipeline 67 | # 68 | # config.string: 69 | # 70 | # At startup, test if the configuration is valid and exit (dry run) 71 | # 72 | # config.test_and_exit: false 73 | # 74 | # Periodically check if the configuration has changed and reload the pipeline 75 | # This can also be triggered manually through the SIGHUP signal 76 | # 77 | # config.reload.automatic: false 78 | # 79 | # How often to check if the pipeline configuration has changed (in seconds) 80 | # 81 | # config.reload.interval: 3s 82 | # 83 | # Show fully compiled configuration as debug log message 84 | # NOTE: --log.level must be 'debug' 85 | # 86 | # config.debug: false 87 | # 88 | # When enabled, process escaped characters such as \n and \" in strings in the 89 | # pipeline configuration files. 90 | # 91 | # config.support_escapes: false 92 | # 93 | # ------------ Module Settings --------------- 94 | # Define modules here. Modules definitions must be defined as an array. 95 | # The simple way to see this is to prepend each `name` with a `-`, and keep 96 | # all associated variables under the `name` they are associated with, and 97 | # above the next, like this: 98 | # 99 | # modules: 100 | # - name: MODULE_NAME 101 | # var.PLUGINTYPE1.PLUGINNAME1.KEY1: VALUE 102 | # var.PLUGINTYPE1.PLUGINNAME1.KEY2: VALUE 103 | # var.PLUGINTYPE2.PLUGINNAME1.KEY1: VALUE 104 | # var.PLUGINTYPE3.PLUGINNAME3.KEY1: VALUE 105 | # 106 | # Module variable names must be in the format of 107 | # 108 | # var.PLUGIN_TYPE.PLUGIN_NAME.KEY 109 | # 110 | # modules: 111 | # 112 | # ------------ Cloud Settings --------------- 113 | # Define Elastic Cloud settings here. 114 | # Format of cloud.id is a base64 value e.g. dXMtZWFzdC0xLmF3cy5mb3VuZC5pbyRub3RhcmVhbCRpZGVudGlmaWVy 115 | # and it may have an label prefix e.g. staging:dXMtZ... 116 | # This will overwrite 'var.elasticsearch.hosts' and 'var.kibana.host' 117 | # cloud.id: 118 | # 119 | # Format of cloud.auth is: : 120 | # This is optional 121 | # If supplied this will overwrite 'var.elasticsearch.username' and 'var.elasticsearch.password' 122 | # If supplied this will overwrite 'var.kibana.username' and 'var.kibana.password' 123 | # cloud.auth: elastic: 124 | # 125 | # ------------ Queuing Settings -------------- 126 | # 127 | # Internal queuing model, "memory" for legacy in-memory based queuing and 128 | # "persisted" for disk-based acked queueing. Defaults is memory 129 | # 130 | # queue.type: memory 131 | # 132 | # If using queue.type: persisted, the directory path where the data files will be stored. 133 | # Default is path.data/queue 134 | # 135 | # path.queue: 136 | # 137 | # If using queue.type: persisted, the page data files size. The queue data consists of 138 | # append-only data files separated into pages. Default is 250mb 139 | # 140 | # queue.page_capacity: 250mb 141 | # 142 | # If using queue.type: persisted, the maximum number of unread events in the queue. 143 | # Default is 0 (unlimited) 144 | # 145 | # queue.max_events: 0 146 | # 147 | # If using queue.type: persisted, the total capacity of the queue in number of bytes. 148 | # If you would like more unacked events to be buffered in Logstash, you can increase the 149 | # capacity using this setting. Please make sure your disk drive has capacity greater than 150 | # the size specified here. If both max_bytes and max_events are specified, Logstash will pick 151 | # whichever criteria is reached first 152 | # Default is 1024mb or 1gb 153 | # 154 | # queue.max_bytes: 1024mb 155 | # 156 | # If using queue.type: persisted, the maximum number of acked events before forcing a checkpoint 157 | # Default is 1024, 0 for unlimited 158 | # 159 | # queue.checkpoint.acks: 1024 160 | # 161 | # If using queue.type: persisted, the maximum number of written events before forcing a checkpoint 162 | # Default is 1024, 0 for unlimited 163 | # 164 | # queue.checkpoint.writes: 1024 165 | # 166 | # If using queue.type: persisted, the interval in milliseconds when a checkpoint is forced on the head page 167 | # Default is 1000, 0 for no periodic checkpoint. 168 | # 169 | # queue.checkpoint.interval: 1000 170 | # 171 | # ------------ Dead-Letter Queue Settings -------------- 172 | # Flag to turn on dead-letter queue. 173 | # 174 | # dead_letter_queue.enable: false 175 | 176 | # If using dead_letter_queue.enable: true, the maximum size of each dead letter queue. Entries 177 | # will be dropped if they would increase the size of the dead letter queue beyond this setting. 178 | # Default is 1024mb 179 | # dead_letter_queue.max_bytes: 1024mb 180 | 181 | # If using dead_letter_queue.enable: true, the directory path where the data files will be stored. 182 | # Default is path.data/dead_letter_queue 183 | # 184 | # path.dead_letter_queue: 185 | # 186 | # ------------ Metrics Settings -------------- 187 | # 188 | # Bind address for the metrics REST endpoint 189 | # 190 | # http.host: "127.0.0.1" 191 | # 192 | # Bind port for the metrics REST endpoint, this option also accept a range 193 | # (9600-9700) and logstash will pick up the first available ports. 194 | # 195 | # http.port: 9600-9700 196 | # 197 | # ------------ Debugging Settings -------------- 198 | # 199 | # Options for log.level: 200 | # * fatal 201 | # * error 202 | # * warn 203 | # * info (default) 204 | # * debug 205 | # * trace 206 | # 207 | # log.level: info 208 | path.logs: /var/log/logstash 209 | # 210 | # ------------ Other Settings -------------- 211 | # 212 | # Where to find custom plugins 213 | # path.plugins: [] 214 | -------------------------------------------------------------------------------- /mlogc_elk/mlogc/config/startup.options: -------------------------------------------------------------------------------- 1 | ################################################################################ 2 | # These settings are ONLY used by $LS_HOME/bin/system-install to create a custom 3 | # startup script for Logstash. It should automagically use the init system 4 | # (systemd, upstart, sysv, etc.) that your Linux distribution uses. 5 | # 6 | # After changing anything here, you need to re-run $LS_HOME/bin/system-install 7 | # as root to push the changes to the init script. 8 | ################################################################################ 9 | 10 | # Override Java location 11 | JAVACMD=/usr/bin/java 12 | 13 | # Set a home directory 14 | LS_HOME=/usr/share/logstash 15 | 16 | # logstash settings directory, the path which contains logstash.yml 17 | LS_SETTINGS_DIR=/etc/logstash 18 | 19 | # Arguments to pass to logstash 20 | LS_OPTS="--path.settings ${LS_SETTINGS_DIR}" 21 | 22 | # Arguments to pass to java 23 | LS_JAVA_OPTS="" 24 | 25 | # pidfiles aren't used the same way for upstart and systemd; this is for sysv users. 26 | LS_PIDFILE=/var/run/logstash.pid 27 | 28 | # user and group id to be invoked as 29 | LS_USER=logstash 30 | LS_GROUP=logstash 31 | 32 | # Enable GC logging by uncommenting the appropriate lines in the GC logging 33 | # section in jvm.options 34 | LS_GC_LOG_FILE=/var/log/logstash/gc.log 35 | 36 | # Open file limit 37 | LS_OPEN_FILES=16384 38 | 39 | # Nice level 40 | LS_NICE=19 41 | 42 | # Change these to have the init script named and described differently 43 | # This is useful when running multiple instances of Logstash on the same 44 | # physical box or vm 45 | SERVICE_NAME="logstash" 46 | SERVICE_DESCRIPTION="logstash" 47 | 48 | # If you need to run a command or script before launching Logstash, put it 49 | # between the lines beginning with `read` and `EOM`, and uncomment those lines. 50 | ### 51 | ## read -r -d '' PRESTART << EOM 52 | ## EOM 53 | -------------------------------------------------------------------------------- /mlogc_elk/mlogc/httpd.conf: -------------------------------------------------------------------------------- 1 | # 2 | # This is the main Apache HTTP server configuration file. It contains the 3 | # configuration directives that give the server its instructions. 4 | # See for detailed information. 5 | # In particular, see 6 | # 7 | # for a discussion of each configuration directive. 8 | # 9 | # Do NOT simply read the instructions in here without understanding 10 | # what they do. They're here only as hints or reminders. If you are unsure 11 | # consult the online docs. You have been warned. 12 | # 13 | # Configuration and logfile names: If the filenames you specify for many 14 | # of the server's control files begin with "/" (or "drive:/" for Win32), the 15 | # server will use that explicit path. If the filenames do *not* begin 16 | # with "/", the value of ServerRoot is prepended -- so 'log/access_log' 17 | # with ServerRoot set to '/www' will be interpreted by the 18 | # server as '/www/log/access_log', where as '/log/access_log' will be 19 | # interpreted as '/log/access_log'. 20 | 21 | # 22 | # ServerRoot: The top of the directory tree under which the server's 23 | # configuration, error, and log files are kept. 24 | # 25 | # Do not add a slash at the end of the directory path. If you point 26 | # ServerRoot at a non-local disk, be sure to specify a local disk on the 27 | # Mutex directive, if file-based mutexes are used. If you wish to share the 28 | # same ServerRoot for multiple httpd daemons, you will need to change at 29 | # least PidFile. 30 | # 31 | ServerRoot "/etc/httpd" 32 | 33 | # 34 | # Listen: Allows you to bind Apache to specific IP addresses and/or 35 | # ports, instead of the default. See also the 36 | # directive. 37 | # 38 | # Change this to Listen on specific IP addresses as shown below to 39 | # prevent Apache from glomming onto all bound IP addresses. 40 | # 41 | #Listen 12.34.56.78:80 42 | Listen 80 43 | 44 | 45 | ## Listen on additional honeytrap ports: 46 | # - 8000 47 | # - 8080 48 | # - 8888 49 | Listen 8000 50 | Listen 8080 51 | Listen 8888 52 | 53 | 54 | 55 | 56 | # 57 | # Dynamic Shared Object (DSO) Support 58 | # 59 | # To be able to use the functionality of a module which was built as a DSO you 60 | # have to place corresponding `LoadModule' lines at this location so the 61 | # directives contained in it are actually available _before_ they are used. 62 | # Statically compiled modules (those listed by `httpd -l') do not need 63 | # to be loaded here. 64 | # 65 | # Example: 66 | # LoadModule foo_module modules/mod_foo.so 67 | # 68 | Include conf.modules.d/*.conf 69 | 70 | # 71 | # If you wish httpd to run as a different user or group, you must run 72 | # httpd as root initially and it will switch. 73 | # 74 | # User/Group: The name (or #number) of the user/group to run httpd as. 75 | # It is usually good practice to create a dedicated user and group for 76 | # running httpd, as with most system services. 77 | # 78 | User apache 79 | Group apache 80 | 81 | # 'Main' server configuration 82 | # 83 | # The directives in this section set up the values used by the 'main' 84 | # server, which responds to any requests that aren't handled by a 85 | # definition. These values also provide defaults for 86 | # any containers you may define later in the file. 87 | # 88 | # All of these directives may appear inside containers, 89 | # in which case these default settings will be overridden for the 90 | # virtual host being defined. 91 | # 92 | 93 | # 94 | # ServerAdmin: Your address, where problems with the server should be 95 | # e-mailed. This address appears on some server-generated pages, such 96 | # as error documents. e.g. admin@your-domain.com 97 | # 98 | ServerAdmin root@localhost 99 | 100 | # 101 | # ServerName gives the name and port that the server uses to identify itself. 102 | # This can often be determined automatically, but we recommend you specify 103 | # it explicitly to prevent problems during startup. 104 | # 105 | # If your host doesn't have a registered DNS name, enter its IP address here. 106 | # 107 | #ServerName www.example.com:80 108 | 109 | # 110 | # Deny access to the entirety of your server's filesystem. You must 111 | # explicitly permit access to web content directories in other 112 | # blocks below. 113 | # 114 | 115 | AllowOverride none 116 | Require all denied 117 | 118 | 119 | # 120 | # Note that from this point forward you must specifically allow 121 | # particular features to be enabled - so if something's not working as 122 | # you might expect, make sure that you have specifically enabled it 123 | # below. 124 | # 125 | 126 | # 127 | # DocumentRoot: The directory out of which you will serve your 128 | # documents. By default, all requests are taken from this directory, but 129 | # symbolic links and aliases may be used to point to other locations. 130 | # 131 | DocumentRoot "/var/www/html" 132 | 133 | # 134 | # Relax access to content within /var/www. 135 | # 136 | 137 | AllowOverride None 138 | # Allow open access: 139 | Require all granted 140 | 141 | 142 | # Further relax access to the default document root: 143 | 144 | # 145 | # Possible values for the Options directive are "None", "All", 146 | # or any combination of: 147 | # Indexes Includes FollowSymLinks SymLinksifOwnerMatch ExecCGI MultiViews 148 | # 149 | # Note that "MultiViews" must be named *explicitly* --- "Options All" 150 | # doesn't give it to you. 151 | # 152 | # The Options directive is both complicated and important. Please see 153 | # http://httpd.apache.org/docs/2.4/mod/core.html#options 154 | # for more information. 155 | # 156 | Options Indexes FollowSymLinks 157 | 158 | # 159 | # AllowOverride controls what directives may be placed in .htaccess files. 160 | # It can be "All", "None", or any combination of the keywords: 161 | # Options FileInfo AuthConfig Limit 162 | # 163 | AllowOverride None 164 | 165 | # 166 | # Controls who can get stuff from this server. 167 | # 168 | Require all granted 169 | 170 | 171 | # 172 | # DirectoryIndex: sets the file that Apache will serve if a directory 173 | # is requested. 174 | # 175 | 176 | DirectoryIndex index.html 177 | 178 | 179 | # 180 | # The following lines prevent .htaccess and .htpasswd files from being 181 | # viewed by Web clients. 182 | # 183 | 184 | Require all denied 185 | 186 | 187 | # 188 | # ErrorLog: The location of the error log file. 189 | # If you do not specify an ErrorLog directive within a 190 | # container, error messages relating to that virtual host will be 191 | # logged here. If you *do* define an error logfile for a 192 | # container, that host's errors will be logged there and not here. 193 | # 194 | ErrorLog "logs/error_log" 195 | 196 | # 197 | # LogLevel: Control the number of messages logged to the error_log. 198 | # Possible values include: debug, info, notice, warn, error, crit, 199 | # alert, emerg. 200 | # 201 | LogLevel warn 202 | 203 | 204 | # 205 | # The following directives define some format nicknames for use with 206 | # a CustomLog directive (see below). 207 | # 208 | LogFormat "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\"" combined 209 | LogFormat "%h %l %u %t \"%r\" %>s %b" common 210 | 211 | 212 | # You need to enable mod_logio.c to use %I and %O 213 | LogFormat "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\" %I %O" combinedio 214 | 215 | 216 | # 217 | # The location and format of the access logfile (Common Logfile Format). 218 | # If you do not define any access logfiles within a 219 | # container, they will be logged here. Contrariwise, if you *do* 220 | # define per- access logfiles, transactions will be 221 | # logged therein and *not* in this file. 222 | # 223 | #CustomLog "logs/access_log" common 224 | 225 | # 226 | # If you prefer a logfile with access, agent, and referer information 227 | # (Combined Logfile Format) you can use the following directive. 228 | # 229 | CustomLog "logs/access_log" combined 230 | 231 | 232 | 233 | # 234 | # Redirect: Allows you to tell clients about documents that used to 235 | # exist in your server's namespace, but do not anymore. The client 236 | # will make a new request for the document at its new location. 237 | # Example: 238 | # Redirect permanent /foo http://www.example.com/bar 239 | 240 | # 241 | # Alias: Maps web paths into filesystem paths and is used to 242 | # access content that does not live under the DocumentRoot. 243 | # Example: 244 | # Alias /webpath /full/filesystem/path 245 | # 246 | # If you include a trailing / on /webpath then the server will 247 | # require it to be present in the URL. You will also likely 248 | # need to provide a section to allow access to 249 | # the filesystem path. 250 | 251 | # 252 | # ScriptAlias: This controls which directories contain server scripts. 253 | # ScriptAliases are essentially the same as Aliases, except that 254 | # documents in the target directory are treated as applications and 255 | # run by the server when requested rather than as documents sent to the 256 | # client. The same rules about trailing "/" apply to ScriptAlias 257 | # directives as to Alias. 258 | # 259 | ScriptAlias /cgi-bin/ "/var/www/cgi-bin/" 260 | 261 | 262 | 263 | # 264 | # "/var/www/cgi-bin" should be changed to whatever your ScriptAliased 265 | # CGI directory exists, if you have that configured. 266 | # 267 | 268 | AllowOverride None 269 | Options None 270 | Require all granted 271 | 272 | 273 | 274 | # 275 | # TypesConfig points to the file containing the list of mappings from 276 | # filename extension to MIME-type. 277 | # 278 | TypesConfig /etc/mime.types 279 | 280 | # 281 | # AddType allows you to add to or override the MIME configuration 282 | # file specified in TypesConfig for specific file types. 283 | # 284 | #AddType application/x-gzip .tgz 285 | # 286 | # AddEncoding allows you to have certain browsers uncompress 287 | # information on the fly. Note: Not all browsers support this. 288 | # 289 | #AddEncoding x-compress .Z 290 | #AddEncoding x-gzip .gz .tgz 291 | # 292 | # If the AddEncoding directives above are commented-out, then you 293 | # probably should define those extensions to indicate media types: 294 | # 295 | AddType application/x-compress .Z 296 | AddType application/x-gzip .gz .tgz 297 | 298 | # 299 | # AddHandler allows you to map certain file extensions to "handlers": 300 | # actions unrelated to filetype. These can be either built into the server 301 | # or added with the Action directive (see below) 302 | # 303 | # To use CGI scripts outside of ScriptAliased directories: 304 | # (You will also need to add "ExecCGI" to the "Options" directive.) 305 | # 306 | #AddHandler cgi-script .cgi 307 | 308 | # For type maps (negotiated resources): 309 | #AddHandler type-map var 310 | 311 | # 312 | # Filters allow you to process content before it is sent to the client. 313 | # 314 | # To parse .shtml files for server-side includes (SSI): 315 | # (You will also need to add "Includes" to the "Options" directive.) 316 | # 317 | AddType text/html .shtml 318 | AddOutputFilter INCLUDES .shtml 319 | 320 | 321 | # 322 | # Specify a default charset for all content served; this enables 323 | # interpretation of all content as UTF-8 by default. To use the 324 | # default browser choice (ISO-8859-1), or to allow the META tags 325 | # in HTML content to override this choice, comment out this 326 | # directive: 327 | # 328 | AddDefaultCharset UTF-8 329 | 330 | 331 | # 332 | # The mod_mime_magic module allows the server to use various hints from the 333 | # contents of the file itself to determine its type. The MIMEMagicFile 334 | # directive tells the module where the hint definitions are located. 335 | # 336 | MIMEMagicFile conf/magic 337 | 338 | 339 | # 340 | # Customizable error responses come in three flavors: 341 | # 1) plain text 2) local redirects 3) external redirects 342 | # 343 | # Some examples: 344 | #ErrorDocument 500 "The server made a boo boo." 345 | #ErrorDocument 404 /missing.html 346 | #ErrorDocument 404 "/cgi-bin/missing_handler.pl" 347 | #ErrorDocument 402 http://www.example.com/subscription_info.html 348 | # 349 | 350 | # 351 | # EnableMMAP and EnableSendfile: On systems that support it, 352 | # memory-mapping or the sendfile syscall may be used to deliver 353 | # files. This usually improves server performance, but must 354 | # be turned off when serving from networked-mounted 355 | # filesystems or if support for these functions is otherwise 356 | # broken on your system. 357 | # Defaults if commented: EnableMMAP On, EnableSendfile Off 358 | # 359 | #EnableMMAP off 360 | EnableSendfile on 361 | 362 | # Supplemental configuration 363 | # 364 | # Load config files in the "/etc/httpd/conf.d" directory, if any. 365 | IncludeOptional conf.d/*.conf 366 | -------------------------------------------------------------------------------- /mlogc_elk/mlogc/logstash.conf: -------------------------------------------------------------------------------- 1 | input { 2 | file { 3 | type => "mlogc_audit_log" 4 | path => "/var/log/mlogc/data/**/*-*" 5 | } 6 | } 7 | output { 8 | elasticsearch { 9 | hosts => ["192.168.136.88:9200"] 10 | index => "mlogc-audit-%{+yyyy.MM.dd}" 11 | } 12 | stdout { codec => rubydebug } 13 | } 14 | -------------------------------------------------------------------------------- /mlogc_elk/mlogc/mlogc.conf: -------------------------------------------------------------------------------- 1 | ########################################################################## 2 | # Required configuration 3 | # At a minimum, the items in this section will need to be adjusted to 4 | # fit your environment. The remaining options are optional. 5 | ########################################################################## 6 | 7 | # Points to the root of the installation. All relative 8 | # paths will be resolved with the help of this path. 9 | CollectorRoot "/var/log/mlogc" 10 | 11 | # ModSecurity Console receiving URI. You can change the host 12 | # and the port parts but leave everything else as is. 13 | ConsoleURI "https://127.0.0.1:9999/rpc/auditLogReceiver" 14 | 15 | # Sensor credentials 16 | SensorUsername "admin" 17 | SensorPassword "admin" 18 | 19 | # Base directory where the audit logs are stored. This can be specified 20 | # as a path relative to the CollectorRoot, or a full path. 21 | LogStorageDir "data" 22 | 23 | # Transaction log will contain the information on all log collector 24 | # activities that happen between checkpoints. The transaction log 25 | # is used to recover data in case of a crash (or if Apache kills 26 | # the process). 27 | TransactionLog "mlogc-transaction.log" 28 | 29 | # The file where the pending audit log entry data is kept. This file 30 | # is updated on every checkpoint. 31 | QueuePath "mlogc-queue.log" 32 | 33 | # The location of the error log. 34 | ErrorLog "mlogc-error.log" 35 | 36 | # The location of the lock file. 37 | LockFile "mlogc.lck" 38 | 39 | # Keep audit log entries after sending? (0=false 1=true) 40 | # NOTE: This is required to be set in SecAuditLog mlogc config if you 41 | # are going to use a secondary console via SecAuditLog2. 42 | KeepEntries 0 43 | 44 | 45 | ########################################################################## 46 | # Optional configuration 47 | ########################################################################## 48 | 49 | # The error log level controls how much detail there 50 | # will be in the error log. The levels are as follows: 51 | # 0 - NONE 52 | # 1 - ERROR 53 | # 2 - WARNING 54 | # 3 - NOTICE 55 | # 4 - DEBUG 56 | # 5 - DEBUG2 57 | # 58 | ErrorLogLevel 3 59 | 60 | # How many concurrent connections to the server 61 | # are we allowed to open at the same time? Log collector uses 62 | # multiple connections in order to speed up audit log transfer. 63 | # This is especially needed when the communication takes place 64 | # over a slow link (e.g. not over a LAN). 65 | MaxConnections 10 66 | 67 | # How many requests a worker will process before recycling itself. 68 | # This is to help prevent problems due to any memory leaks that may 69 | # exists. If this is set to 0, then no maximum is imposed. The default 70 | # is 1000 requests per worker (the number of workers is controlled by the 71 | # MaxConnections limit). 72 | MaxWorkerRequests 1000 73 | 74 | # The time each connection will sit idle before being reused, 75 | # in milliseconds. Increase if you don't want ModSecurity Console 76 | # to be hit with too many log collector requests. 77 | TransactionDelay 50 78 | 79 | # The time to wait before initialization on startup in milliseconds. 80 | # Increase if mlogc is starting faster then termination when the 81 | # sensor is reloaded. 82 | StartupDelay 5000 83 | 84 | # How often is the pending audit log entry data going to be written 85 | # to a file. The default is 15 seconds. 86 | CheckpointInterval 15 87 | 88 | # If the server fails all threads will back down until the 89 | # problem is sorted. The management thread will periodically 90 | # launch a thread to test the server. The default is to test 91 | # once in 60 seconds. 92 | ServerErrorTimeout 60 93 | 94 | # The following two parameters are not used yet, but 95 | # reserved for future expansion. 96 | # KeepAlive 150 97 | # KeepAliveTimeout 300 98 | 99 | 100 | # When set to '0', mlogc will validate the certificate and the whole 101 | # chain, the root certificate most be trusted. If this check fail the 102 | # connection will be dropped. To ignore the SSL checks, set InsecureNoCheckCert 103 | # to '1' 104 | InsecureNoCheckCert 1 105 | -------------------------------------------------------------------------------- /mlogc_elk/mlogc/mod_security.conf: -------------------------------------------------------------------------------- 1 | 2 | # Default recommended configuration 3 | SecRuleEngine On 4 | SecRequestBodyAccess On 5 | SecRule REQUEST_HEADERS:Content-Type "text/xml" \ 6 | "id:'200000',phase:1,t:none,t:lowercase,pass,nolog,ctl:requestBodyProcessor=XML" 7 | SecRequestBodyLimit 13107200 8 | SecRequestBodyNoFilesLimit 131072 9 | SecRequestBodyInMemoryLimit 131072 10 | SecRequestBodyLimitAction Reject 11 | SecRule REQBODY_ERROR "!@eq 0" \ 12 | "id:'200001', phase:2,t:none,log,deny,status:400,msg:'Failed to parse request body.',logdata:'%{reqbody_error_msg}',severity:2" 13 | SecRule MULTIPART_STRICT_ERROR "!@eq 0" \ 14 | "id:'200002',phase:2,t:none,log,deny,status:400,msg:'Multipart request body \ 15 | failed strict validation: \ 16 | PE %{REQBODY_PROCESSOR_ERROR}, \ 17 | BQ %{MULTIPART_BOUNDARY_QUOTED}, \ 18 | BW %{MULTIPART_BOUNDARY_WHITESPACE}, \ 19 | DB %{MULTIPART_DATA_BEFORE}, \ 20 | DA %{MULTIPART_DATA_AFTER}, \ 21 | HF %{MULTIPART_HEADER_FOLDING}, \ 22 | LF %{MULTIPART_LF_LINE}, \ 23 | SM %{MULTIPART_MISSING_SEMICOLON}, \ 24 | IQ %{MULTIPART_INVALID_QUOTING}, \ 25 | IP %{MULTIPART_INVALID_PART}, \ 26 | IH %{MULTIPART_INVALID_HEADER_FOLDING}, \ 27 | FL %{MULTIPART_FILE_LIMIT_EXCEEDED}'" 28 | 29 | SecRule MULTIPART_UNMATCHED_BOUNDARY "!@eq 0" \ 30 | "id:'200003',phase:2,t:none,log,deny,status:44,msg:'Multipart parser detected a possible unmatched boundary.'" 31 | 32 | SecPcreMatchLimit 1000 33 | SecPcreMatchLimitRecursion 1000 34 | 35 | SecRule TX:/^MSC_/ "!@streq 0" \ 36 | "id:'200004',phase:2,t:none,deny,msg:'ModSecurity internal error flagged: %{MATCHED_VAR_NAME}'" 37 | 38 | SecResponseBodyAccess Off 39 | SecDebugLog /var/log/httpd/modsec_debug.log 40 | SecDebugLogLevel 0 41 | SecAuditEngine RelevantOnly 42 | SecAuditLogRelevantStatus "^(?:5|4(?!04))" 43 | SecAuditLogParts ABIJDEFHZ 44 | #SecAuditLogFormat JSON 45 | SecAuditLogType Concurrent 46 | SecAuditLog "|/usr/bin/mlogc /etc/mlogc.conf" 47 | #SecAuditLog /var/log/httpd/modsec_audit.log 48 | SecAuditLogStorageDir /var/log/mlogc/data 49 | SecArgumentSeparator & 50 | SecCookieFormat 0 51 | SecTmpDir /var/lib/mod_security 52 | SecDataDir /var/lib/mod_security 53 | 54 | # ModSecurity Core Rules Set and Local configuration 55 | IncludeOptional modsecurity.d/*.conf 56 | IncludeOptional modsecurity.d/activated_rules/*.conf 57 | IncludeOptional modsecurity.d/local_rules/*.conf 58 | 59 | 60 | -------------------------------------------------------------------------------- /mlogc_elk/mlogc/modsec_entry.sh: -------------------------------------------------------------------------------- 1 | # ~/bin/sh 2 | httpd 3 | /usr/share/logstash/bin/logstash -f /usr/share/logstash/logstash.conf 4 | -------------------------------------------------------------------------------- /mlogc_elk/mlogc/modsecurity.conf: -------------------------------------------------------------------------------- 1 | # -- Rule engine initialization ---------------------------------------------- 2 | 3 | # Enable ModSecurity, attaching it to every transaction. Use detection 4 | # only to start with, because that minimises the chances of post-installation 5 | # disruption. 6 | # 7 | SecRuleEngine On 8 | 9 | 10 | # -- Request body handling --------------------------------------------------- 11 | 12 | # Allow ModSecurity to access request bodies. If you don't, ModSecurity 13 | # won't be able to see any POST parameters, which opens a large security 14 | # hole for attackers to exploit. 15 | # 16 | SecRequestBodyAccess On 17 | 18 | 19 | # Enable XML request body parser. 20 | # Initiate XML Processor in case of xml content-type 21 | # 22 | SecRule REQUEST_HEADERS:Content-Type "(?:text|application)/xml" "id:'200000',phase:1,t:none,t:lowercase,pass,nolog,ctl:requestBodyProcessor=XML" 23 | 24 | # Enable JSON request body parser. 25 | # Initiate JSON Processor in case of JSON content-type; change accordingly 26 | # if your application does not use 'application/json' 27 | # 28 | SecRule REQUEST_HEADERS:Content-Type "application/json" "id:'200001',phase:1,t:none,t:lowercase,pass,nolog,ctl:requestBodyProcessor=JSON" 29 | # Maximum request body size we will accept for buffering. If you support 30 | # file uploads then the value given on the first line has to be as large 31 | # as the largest file you are willing to accept. The second value refers 32 | # to the size of data, with files excluded. You want to keep that value as 33 | # low as practical. 34 | # 35 | SecRequestBodyLimit 13107200 36 | SecRequestBodyNoFilesLimit 131072 37 | 38 | # Store up to 128 KB of request body data in memory. When the multipart 39 | # parser reachers this limit, it will start using your hard disk for 40 | # storage. That is slow, but unavoidable. 41 | # 42 | SecRequestBodyInMemoryLimit 131072 43 | 44 | # What do do if the request body size is above our configured limit. 45 | # Keep in mind that this setting will automatically be set to ProcessPartial 46 | # when SecRuleEngine is set to DetectionOnly mode in order to minimize 47 | # disruptions when initially deploying ModSecurity. 48 | # 49 | SecRequestBodyLimitAction Reject 50 | 51 | # Verify that we've correctly processed the request body. 52 | # As a rule of thumb, when failing to process a request body 53 | # you should reject the request (when deployed in blocking mode) 54 | # or log a high-severity alert (when deployed in detection-only mode). 55 | # 56 | SecRule REQBODY_ERROR "!@eq 0" \ 57 | "id:'200002', phase:2,t:none,log,deny,status:400,msg:'Failed to parse request body.',logdata:'%{reqbody_error_msg}',severity:2" 58 | 59 | # By default be strict with what we accept in the multipart/form-data 60 | # request body. If the rule below proves to be too strict for your 61 | # environment consider changing it to detection-only. You are encouraged 62 | # _not_ to remove it altogether. 63 | # 64 | SecRule MULTIPART_STRICT_ERROR "!@eq 0" \ 65 | "id:'200003',phase:2,t:none,log,deny,status:400, \ 66 | msg:'Multipart request body failed strict validation: \ 67 | PE %{REQBODY_PROCESSOR_ERROR}, \ 68 | BQ %{MULTIPART_BOUNDARY_QUOTED}, \ 69 | BW %{MULTIPART_BOUNDARY_WHITESPACE}, \ 70 | DB %{MULTIPART_DATA_BEFORE}, \ 71 | DA %{MULTIPART_DATA_AFTER}, \ 72 | HF %{MULTIPART_HEADER_FOLDING}, \ 73 | LF %{MULTIPART_LF_LINE}, \ 74 | SM %{MULTIPART_MISSING_SEMICOLON}, \ 75 | IQ %{MULTIPART_INVALID_QUOTING}, \ 76 | IP %{MULTIPART_INVALID_PART}, \ 77 | IH %{MULTIPART_INVALID_HEADER_FOLDING}, \ 78 | FL %{MULTIPART_FILE_LIMIT_EXCEEDED}'" 79 | 80 | # Did we see anything that might be a boundary? 81 | # 82 | SecRule MULTIPART_UNMATCHED_BOUNDARY "!@eq 0" \ 83 | "id:'200004',phase:2,t:none,log,deny,msg:'Multipart parser detected a possible unmatched boundary.'" 84 | 85 | # PCRE Tuning 86 | # We want to avoid a potential RegEx DoS condition 87 | # 88 | SecPcreMatchLimit 1000 89 | SecPcreMatchLimitRecursion 1000 90 | 91 | # Some internal errors will set flags in TX and we will need to look for these. 92 | # All of these are prefixed with "MSC_". The following flags currently exist: 93 | # 94 | # MSC_PCRE_LIMITS_EXCEEDED: PCRE match limits were exceeded. 95 | # 96 | SecRule TX:/^MSC_/ "!@streq 0" \ 97 | "id:'200005',phase:2,t:none,deny,msg:'ModSecurity internal error flagged: %{MATCHED_VAR_NAME}'" 98 | 99 | 100 | # -- Response body handling -------------------------------------------------- 101 | 102 | # Allow ModSecurity to access response bodies. 103 | # You should have this directive enabled in order to identify errors 104 | # and data leakage issues. 105 | # 106 | # Do keep in mind that enabling this directive does increases both 107 | # memory consumption and response latency. 108 | # 109 | SecResponseBodyAccess On 110 | 111 | # Which response MIME types do you want to inspect? You should adjust the 112 | # configuration below to catch documents but avoid static files 113 | # (e.g., images and archives). 114 | # 115 | SecResponseBodyMimeType text/plain text/html text/xml 116 | 117 | # Buffer response bodies of up to 512 KB in length. 118 | SecResponseBodyLimit 524288 119 | 120 | # What happens when we encounter a response body larger than the configured 121 | # limit? By default, we process what we have and let the rest through. 122 | # That's somewhat less secure, but does not break any legitimate pages. 123 | # 124 | SecResponseBodyLimitAction ProcessPartial 125 | 126 | 127 | # -- Filesystem configuration ------------------------------------------------ 128 | 129 | # The location where ModSecurity stores temporary files (for example, when 130 | # it needs to handle a file upload that is larger than the configured limit). 131 | # 132 | # This default setting is chosen due to all systems have /tmp available however, 133 | # this is less than ideal. It is recommended that you specify a location that's private. 134 | # 135 | SecTmpDir /tmp/ 136 | 137 | # The location where ModSecurity will keep its persistent data. This default setting 138 | # is chosen due to all systems have /tmp available however, it 139 | # too should be updated to a place that other users can't access. 140 | # 141 | SecDataDir /tmp/ 142 | 143 | 144 | # -- File uploads handling configuration ------------------------------------- 145 | 146 | # The location where ModSecurity stores intercepted uploaded files. This 147 | # location must be private to ModSecurity. You don't want other users on 148 | # the server to access the files, do you? 149 | # 150 | #SecUploadDir /opt/modsecurity/var/upload/ 151 | 152 | # By default, only keep the files that were determined to be unusual 153 | # in some way (by an external inspection script). For this to work you 154 | # will also need at least one file inspection rule. 155 | # 156 | #SecUploadKeepFiles RelevantOnly 157 | 158 | # Uploaded files are by default created with permissions that do not allow 159 | # any other user to access them. You may need to relax that if you want to 160 | # interface ModSecurity to an external program (e.g., an anti-virus). 161 | # 162 | #SecUploadFileMode 0600 163 | 164 | 165 | # -- Debug log configuration ------------------------------------------------- 166 | 167 | # The default debug log configuration is to duplicate the error, warning 168 | # and notice messages from the error log. 169 | # 170 | #SecDebugLog /opt/modsecurity/var/log/debug.log 171 | #SecDebugLogLevel 3 172 | 173 | 174 | # -- Audit log configuration ------------------------------------------------- 175 | 176 | # Log the transactions that are marked by a rule, as well as those that 177 | # trigger a server error (determined by a 5xx or 4xx, excluding 404, 178 | # level response status codes). 179 | # 180 | SecAuditEngine RelevantOnly 181 | SecAuditLogRelevantStatus "^(?:5|4(?!04))" 182 | 183 | # Log everything we know about a transaction. 184 | SecAuditLogParts ABIJDEFHZ 185 | 186 | # Use a single file for logging. This is much easier to look at, but 187 | # assumes that you will use the audit log only ocassionally. 188 | # 189 | SecAuditLogType Concurrent 190 | # Pipe audit log to mlogc with your configuration 191 | SecAuditLog "|/usr/bin/mlogc /etc/mlogc.conf" 192 | #SecAuditLog /var/log/modsec_audit.log 193 | # Specify the path for concurrent audit logging. 194 | #SecAuditLogStorageDir /opt/modsecurity/var/audit/ 195 | SecAuditLogStorageDir /var/log/mlogc/data 196 | 197 | 198 | 199 | # -- Miscellaneous ----------------------------------------------------------- 200 | 201 | # Use the most commonly used application/x-www-form-urlencoded parameter 202 | # separator. There's probably only one application somewhere that uses 203 | # something else so don't expect to change this value. 204 | # 205 | SecArgumentSeparator & 206 | 207 | # Settle on version 0 (zero) cookies, as that is what most applications 208 | # use. Using an incorrect cookie version may open your installation to 209 | # evasion attacks (against the rules that examine named cookies). 210 | # 211 | SecCookieFormat 0 212 | 213 | # Specify your Unicode Code Point. 214 | # This mapping is used by the t:urlDecodeUni transformation function 215 | # to properly map encoded data to your language. Properly setting 216 | # these directives helps to reduce false positives and negatives. 217 | # 218 | SecUnicodeMapFile unicode.mapping 20127 219 | 220 | # Improve the quality of ModSecurity by sharing information about your 221 | # current ModSecurity version and dependencies versions. 222 | # The following information will be shared: ModSecurity version, 223 | # Web Server version, APR version, PCRE version, Lua version, Libxml2 224 | # version, Anonymous unique id for host. 225 | SecStatusEngine On 226 | 227 | # # Generate Alerts for all requests that we receive and # set a variable in the IP Collection to mark the client # as malicious. # 228 | # # Generate Alerts for all requests that we receive and # set a variable in the IP Collection to mark the client # as malicious. # 229 | SecRule SERVER_PORT "^(8000|8080|8888)$" \ 230 | "id:'999004',phase:2,t:none,log,block,msg:'HoneyTrap Alert: Traffic Received on Fake Port.',setvar:ip.malicious_client=1" 231 | -------------------------------------------------------------------------------- /mlogc_elk/mlogc/start.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | httpd 3 | bin/logstash -f /usr/share/logstash/logstash.conf 4 | -------------------------------------------------------------------------------- /mlogc_elk/screenshots/mlogc_index_create.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OWASP/Honeypot-Project/45bcf2a30da7e0c6face45882bd1c2f2827e0a0b/mlogc_elk/screenshots/mlogc_index_create.png -------------------------------------------------------------------------------- /mlogc_elk/screenshots/mlogc_index_create_2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OWASP/Honeypot-Project/45bcf2a30da7e0c6face45882bd1c2f2827e0a0b/mlogc_elk/screenshots/mlogc_index_create_2.png -------------------------------------------------------------------------------- /mlogc_elk/screenshots/mlogc_logs.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OWASP/Honeypot-Project/45bcf2a30da7e0c6face45882bd1c2f2827e0a0b/mlogc_elk/screenshots/mlogc_logs.png --------------------------------------------------------------------------------