lab update

This commit is contained in:
Z. Cliffe Schreuders
2017-12-01 15:54:44 +00:00
parent 3d46505609
commit 04fcbed7a5
26 changed files with 1099 additions and 3 deletions

View File

@@ -0,0 +1,35 @@
#!/usr/bin/ruby
require 'base64'
require_relative '../../../../../lib/objects/local_string_encoder.rb'
class CSVEncoder < StringEncoder
def initialize
super
self.module_name = 'CSV Encoder'
end
def encode_all()
require 'csv'
require 'json'
csv_string = CSV.generate do |csv|
strings_to_encode.each do |string_to_encode, count|
row = []
header = []
JSON.parse(string_to_encode).each do |hash|
header << hash[0]
row << hash[1]
end
if count == 0
csv << header
end
csv << row
end
end
self.outputs << csv_string
end
end
CSVEncoder.new.run

View File

@@ -0,0 +1,19 @@
<?xml version="1.0"?>
<encoder xmlns="http://www.github/cliffe/SecGen/encoder"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.github/cliffe/SecGen/encoder">
<name>CSV Encoder</name>
<author>Z. Cliffe Schreuders</author>
<module_license>MIT</module_license>
<description>Converts all of the inputs into a single CSV output. Accepts one layer of JSON hashes. For example, outputs from person generator.</description>
<type>csv</type>
<platform>linux</platform>
<platform>windows</platform>
<read_fact>strings_to_encode</read_fact>
<output_type>csv</output_type>
</encoder>

View File

@@ -3,12 +3,13 @@
<generator xmlns="http://www.github/cliffe/SecGen/generator"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.github/cliffe/SecGen/generator">
<name>Industry Generator</name>
<name>Credit Card Number Generator</name>
<author>Thomas Shaw</author>
<module_license>MIT</module_license>
<description>Industry generator using the Forgery ruby gem.</description>
<description>Credit Card Number Generator generator using the Credy ruby gem.</description>
<type>credit_card</type>
<type>credit_card_generator</type>
<type>personal_sensitive</type>
<type>local_calculation</type>
<platform>linux</platform>
<platform>windows</platform>

View File

@@ -0,0 +1,17 @@
#!/usr/bin/ruby
require_relative '../../../../../lib/objects/local_string_generator.rb'
class NINGenerator < StringGenerator
def initialize
super
self.module_name = 'National Insurance Number Generator'
end
def generate
nino = "QQ"<<(10..99).to_a.sample(3)*''<<("A".."D").to_a.sample
self.outputs << nino
end
end
NINGenerator.new.run

View File

@@ -0,0 +1,20 @@
<?xml version="1.0"?>
<generator xmlns="http://www.github/cliffe/SecGen/generator"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.github/cliffe/SecGen/generator">
<name>National Insurance Number</name>
<author>Z. Cliffe Schreuders</author>
<module_license>MIT</module_license>
<description>Generates a UK NIN (National Insurance Number).</description>
<type>national_insurance_number_generator</type>
<type>sensitive_personal</type>
<type>local_calculation</type>
<platform>linux</platform>
<platform>windows</platform>
<reference>https://codereview.stackexchange.com/questions/9464/national-insurance-number-generator</reference>
<output_type>sensitive_personal</output_type>
</generator>

View File

@@ -0,0 +1,45 @@
#!/usr/bin/ruby
require_relative '../../../../../../lib/objects/local_hackerbot_config_generator.rb'
class IDS < HackerbotConfigGenerator
attr_accessor :web_server_ip
attr_accessor :ids_server_ip
attr_accessor :hackerbot_server_ip
def initialize
super
self.module_name = 'Hackerbot Config Generator IDS'
self.title = 'IDS'
self.local_dir = File.expand_path('../../',__FILE__)
self.templates_path = "#{self.local_dir}/templates/"
self.config_template_path = "#{self.local_dir}/templates/lab.xml.erb"
self.html_template_path = "#{self.local_dir}/templates/labsheet.html.erb"
self.web_server_ip = []
self.ids_server_ip = []
self.hackerbot_server_ip = []
end
def get_options_array
super + [['--web_server_ip', GetoptLong::REQUIRED_ARGUMENT],
['--ids_server_ip', GetoptLong::REQUIRED_ARGUMENT],
['--hackerbot_server_ip', GetoptLong::REQUIRED_ARGUMENT]]
end
def process_options(opt, arg)
super
case opt
when '--web_server_ip'
self.web_server_ip << arg;
when '--ids_server_ip'
self.ids_server_ip << arg;
when '--hackerbot_server_ip'
self.ids_server_ip << arg;
end
end
end
IDS.new.run

View File

@@ -0,0 +1,52 @@
<?xml version="1.0"?>
<generator xmlns="http://www.github/cliffe/SecGen/generator"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.github/cliffe/SecGen/generator">
<name>Hackerbot config for a IDS rules lab</name>
<author>Z. Cliffe Schreuders</author>
<module_license>GPLv3</module_license>
<description>Generates a config file for a hackerbot for a IDS lab.
Topics covered: Writing Snort rules.</description>
<type>hackerbot_config</type>
<platform>linux</platform>
<read_fact>accounts</read_fact>
<read_fact>flags</read_fact>
<read_fact>root_password</read_fact>
<read_fact>web_server_ip</read_fact>
<read_fact>ids_server_ip</read_fact>
<read_fact>hackerbot_server_ip</read_fact>
<!--TODO: require input, such as accounts, or fail?-->
<default_input into="accounts">
<generator type="account">
<input into="username">
<value>vagrant</value>
</input>
</generator>
</default_input>
<!--TODO: less flags-->
<default_input into="flags">
<generator type="flag_generator"/>
<generator type="flag_generator"/>
<generator type="flag_generator"/>
<generator type="flag_generator"/>
<generator type="flag_generator"/>
<generator type="flag_generator"/>
<generator type="flag_generator"/>
<generator type="flag_generator"/>
<generator type="flag_generator"/>
<generator type="flag_generator"/>
</default_input>
<default_input into="root_password">
<value>puppet</value>
</default_input>
<output_type>hackerbot</output_type>
</generator>

View File

@@ -0,0 +1,29 @@
<html>
<head>
<title><%= self.title %></title>
</head>
<body>
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" href="css/github-markdown.css">
<style>
.markdown-body {
box-sizing: border-box;
min-width: 200px;
max-width: 980px;
margin: 0 auto;
padding: 45px;
}
@media (max-width: 767px) {
.markdown-body {
padding: 15px;
}
}
</style>
<article class="markdown-body">
<%= self.html_rendered %>
</article>
<script src="js/code-prettify/loader/run_prettify.js"></script>
</body>
</html>

View File

@@ -0,0 +1,4 @@
## License
This lab by [*Z. Cliffe Schreuders*](http://z.cliffe.schreuders.org) at Leeds Beckett University is licensed under a [*Creative Commons Attribution-ShareAlike 3.0 Unported License*](http://creativecommons.org/licenses/by-sa/3.0/deed.en_GB).
Included software source code is also licensed under the GNU General Public License, either version 3 of the License, or (at your option) any later version.

View File

@@ -0,0 +1,93 @@
## Introduction
This week's lab consists of problem based tasks. You should be able to complete all tasks using VMs on oVirt but may wish to use a prepared VM with OpenDPL pre-installed for task A3.
This week's lab is entirely problem-based.
## Data loss prevention (DLP)
Data loss prevention (DLP) involves monitoring network activity that indicates that sensitive information is being exfiltrated or handled incorrectly. Some DLP systems monitor local systems and data at rest (for example, HIDS), while others are focused on network traffic and data in motion (NIDS). Using DLP software can help to detect insecure processes in an organisation, such as storing sensitive data in unplanned or insecure places. It can also help to mitigate insider threat, and data exfiltration to remote attackers. A report by Bnet shows that 45 percent of employees take data when they change jobs, and data leakage and organisational doxing has become more frequent (for example, the Sony Pictures compromise).
Note that there is a variety of DLP solutions available, and the most robust enterprise solutions provide network monitoring (data in motion), file system monitoring (data at rest), and some DLP systems will also monitor local file transfers (for example, copying files to USB) to block exfiltration using local storage devices.
In order to be effective, an organisation must identify sensitive data in their organisation that should be monitored.
## Snort exfiltration detection (data in motion)
### Text-based exfiltration detection
Choose a file representing data you are going to detect and protect. For example, you may choose to use a document you previously created (such as an assignment you have completed in the past).
Write a Snort rule that detects the transfer of the contents of this file.
Transfer the file via (unencrypted) FTP, and show that your above rule detects the file transfer.
Transfer the file via (unencrypted) HTTP, and show that your above rule detects the file transfer.
Hint: you can include your sensitive data directly in a Snort rule. This is very closely related to the IDS Lab, which will be a helpful resource. Consider using the metadata:service tag in your rule.
It is fine to monitor all ports, so long as your rule(s) detect transfer via FTP and HTTP.
**Label it or save it as "DLP-A1".**
#### Hash-based exfiltration detection
Assuming the data you are protecting is sensitive, you likely don't want your Snort rules to contain direct copies of all your most sensitive data. For this reason, Snort rules can contain hashes to match against.
Write a Snort rule that detects the transfer of the contents of your file, based on hashes, so that the Snort rule does not contain any plain text of your document.
Hint: consider using the protected\_content keyword in your rule.
Transfer the file via (unencrypted) FTP, and show that your rule detects the file transfer.
**Label it or save it as "DLP-A2".**
### OpenDLP (data at rest)
[*OpenDLP*](https://code.google.com/p/opendlp/) is designed to detect sensitive data at rest. Although the project looks to be somewhat inactive, the software is functional and performs tasks similar to various commercial offerings, and is worth exploring to gain an understanding of what is available.
OpenDLP can be run as an agent (on the system you are scanning) or agentless to perform a credentialed scan over the network. Provided with credentials, it can scan Windows file shares.
It can scan directories for files containing matches to regular expressions. It comes with a number of pre-canned regexp, to detect USA social security numbers (SSN), credit card details, and so on. You can configure your own rules to scan for specific sensitive data.
Note that tools such as this can also be helpful in security audits and penetration tests, to identify potentially sensitive documents that are available on systems being scanned.
Use OpenDLP to scan a system, and show that it can be used to detect potentially sensitive data (such as your above document).
Hint: this may involve downloading and running the OpenDLP VM, generating a profile, providing credentials, then running a scan.
**Take screenshots of your use of OpenDLP to detect sensitive data, preferably your own file above, as evidence that you have completed this part of the task. **
**Label it or save it as "DLP-A3".**
### Squid Proxy SSL Bump (encrypted data in motion)
Encryption is an incredibly powerful tool for protecting confidentiality of data in transit, and is critical for enabling secure communication and individual privacy on the Internet. However, in a corporate environment it is often justified for an organisation to monitor network communications, for DLP reasons.
Many organisations configure security products to forcefully intercept and inspect secure connections. One of the most common ways of achieving this is for the organisation to create their own Certificate Authority (CA), adding that certificate to each client system (such as every desktop system in the organisation), and basically performing automated man in the middle (MITM) attacks against all those systems.
The general approach is that every client request (for example, a browser requesting access to a Website) is intercepted, and the interceptor signs its communication to the client using the organisation's CA (which the client is forced to trust, if they want to access the Internet), and forwards requests and responses to and from the actual target servers on the Internet. Thereby the organisation can inspect the traffic from the interception point.
Configure Squid to intercept and MITM all Web access so that even encrypted Websites, such as Facebook, can be monitored.
Related resources:
- [*http://wiki.squid-cache.org/Features/MimicSslServerCert*](http://wiki.squid-cache.org/Features/MimicSslServerCert)
- [*http://blog.davidvassallo.me/2011/03/22/squid-transparent-ssl-interception/*](http://blog.davidvassallo.me/2011/03/22/squid-transparent-ssl-interception/)
Hint: this will involve setting up Squid proxy on a VM, pointing a Web browser at Squid, checking that you can access the internet via the Squid proxy. Then setting up Squid to intercept HTTPS connections using SSL Bump/MimicSslServerCert. This won't be quick, you will need to create a new CA with Public and Private keys, then configure Squid to use these for interception. The CA public key can be imported into the Web browser to remove the untrusted connection warnings.
**Take screenshots of Squid being configured and used to intercept HTTPS, as evidence that you have completed this part of the task. **
**Label it or save it as "DLP-A4".**
Write a description of the security advantages and disadvantages to intercepting HTTPS (one page max).
**A description of the security advantages and disadvantages to intercepting HTTPS. **
**Label it or save it as "DLP-A5".**

View File

@@ -0,0 +1,23 @@
## Data loss prevention (DLP)
Data loss prevention (DLP) involves monitoring network activity that indicates that sensitive information is being exfiltrated or handled incorrectly. Some DLP systems monitor local systems and data at rest (for example, HIDS), while others are focused on network traffic and data in motion (NIDS). Using DLP software can help to detect insecure processes in an organisation, such as storing sensitive data in unplanned or insecure places. It can also help to mitigate insider threat, and data exfiltration to remote attackers. A report by Bnet shows that 45 percent of employees take data when they change jobs, and data leakage and organisational doxing has become more frequent (for example, the Sony Pictures compromise).
Note that there is a variety of DLP solutions available, and the most robust enterprise solutions provide network monitoring (data in motion), file system monitoring (data at rest), and some DLP systems will also monitor local file transfers (for example, copying files to USB) to block exfiltration using local storage devices.
In order to be effective, an organisation must identify sensitive data in their organisation that should be monitored.
## Snort exfiltration detection (data in motion)
### Text-based exfiltration detection
Hint: you can include your sensitive data directly in a Snort rule. This is very closely related to the IDS rules lab, which will be a helpful resource. Consider using the metadata:service tag in your rule.
It is fine to monitor all ports, so long as your rule(s) detect transfer of the file.
#### Hash-based exfiltration detection
Assuming the data you are protecting is sensitive, you likely don't want your Snort rules to contain direct copies of all your most sensitive data. For this reason, Snort rules can contain hashes to match against.
It is possible to write Snort rules that detect the transfer of the contents of your files, based on hashes, so that the Snort rule does not contain any plain text of your document.
Hint: consider using the protected\_content keyword in your rule.

View File

@@ -0,0 +1,86 @@
# Data Loss Prevention and Exfiltration Detection
This week's lab is entirely problem-based.
## Getting started
### VMs in this lab
==Start these VMs== (if you haven't already):
- hackerbot_server (leave it running, you don't log into this)
- ids_server (IP address: <%= $ids_server_ip %>)
- web_server (IP address: <%= $web_server_ip %>, leave it running, you don't log into this)
- desktop
All of these VMs need to be running to complete the lab.
**Ensure the ids_server VM is allowed promiscuous mode.** If you are completing this lab on Leeds Beckett oVirt infrastructure, this should be sorted. Otherwise, if you have used SecGen to spin up VMs, you need to ensure your VMs have permission to monitor networks using promiscuous mode. On the Leeds Beckett oVirt infrastructure we have snoop networks, which mirror all the traffic between systems. On Virtualbox, you would need to go to Advanced network settings for the host-only network on the ids_server and enable promiscious mode.
### Your login details for the "desktop" and "ids_server" VMs
User: <%= $main_user %>
Password: tiaspbiqe2r (**t**his **i**s **a** **s**ecure **p**assword **b**ut **i**s **q**uite **e**asy **2** **r**emember)
You won't login to the hackerbot_server or web_server, but all the VMs need to be running to complete the lab.
### For marks in the module
1. **You need to submit flags**. Note that the flags and the challenges in your VMs are different to other's in the class. Flags will be revealed to you as you complete challenges throughout the module. Flags look like this: ==flag{*somethingrandom*}==. Follow the link on the module page to submit your flags.
2. **You need to document the work and your solutions in a workbook**. This needs to include screenshots (including the flags) of how you solved each Hackerbot challenge and a writeup describing your solution to each challenge, and answering any "Workbook Questions". The workbook will be submitted later in the semester.
## Hackerbot!
![small-right](images/skullandusb.svg)
This exercise involves interacting with Hackerbot, a chatbot who will task you to monitor the network and will attack your systems. If you satisfy Hackerbot by completing the challenges, she will reveal flags to you.
Work through the below exercises, completing the Hackerbot challenges as noted.
---
## Getting Snort up and running
**On the ids_server VM:**
==Change Snort's output== to something more readable:
```bash
sudo vi /etc/snort/snort.conf
```
> (Remember: editing using vi involves pressing "i" to insert/edit text, then *Esc*,
> ":wq" to write changes and quit)
==Add the following lines:==
`output alert_fast`
`include $RULE_PATH/my.rules`
==Create a new rules file:==
```bash
sudo touch /etc/snort/rules/my.rules
```
Let us edit the rules file without sudo:
```bash
sudo chown <%= $main_user %> /etc/snort/rules/my.rules
```
==Change Snort's interface== to the interface with IP address <%= $ids_server_ip %> (likely eth1), and set the local network to your IP address range (or "any"):
```bash
sudo vi /etc/snort/snort.debian.conf
```
> If you are not sure which interface to use, list the interfaces with `ifconfig` or `ip a s`
> Set the interface and HOME network range, and exit vi (Esc, ":wq").
==Restart Snort:==
```bash
sudo service snort stop
sudo service snort start
```
> Using "reload" or "restart" may not update the interface.
Snort should now be running, monitoring network traffic for activity.
It can be helpful to monitor network traffic while writing IDS rules. You can start Wireshark with `kdesudo wireshark &`

View File

@@ -0,0 +1,292 @@
<%
require 'json'
require 'securerandom'
require 'digest/sha1'
require 'fileutils'
require 'erb'
if self.accounts.empty?
abort('Sorry, you need to provide an account')
end
$first_account = JSON.parse(self.accounts.first)
$second_account = JSON.parse(self.accounts[1])
$files = []
$log_files = []
if $second_account.key?("leaked_filenames") && $second_account['leaked_filenames'].size > 0
$files = $second_account['leaked_filenames']
$log_files = $second_account['leaked_filenames'].grep(/log/)
end
if $files.empty?
$files = ['myfile', 'afile', 'filee', 'thefile']
end
if $log_files.empty?
$log_files = ['log', 'thelog', 'logs', 'frogonalog']
end
$main_user = $first_account['username'].to_s
$main_user_pass = $first_account['password'].to_s
$second_user = $second_account['username'].to_s
$example_file = "/home/#{$second_user}/#{$files.sample}"
$example_dir = "/home/#{$second_user}/personal_secrets/"
$web_server_ip = self.web_server_ip.first
$ids_server_ip = self.ids_server_ip.first
$hackerbot_server_ip = self.hackerbot_server_ip.first
$root_password = self.root_password
$flags = self.flags
REQUIRED_FLAGS = 10
while $flags.length < REQUIRED_FLAGS
$flags << "flag{#{SecureRandom.hex}}"
Print.err "Warning: Not enough flags provided to hackerbot_config generator, some flags won't be tracked/marked!"
end
def get_binding
binding
end
%>
<?xml version="1.0"?>
<hackerbot
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.github/cliffe/SecGen/hackerbot">
<!--<hackerbot xmlns="http://www.github/cliffe/SecGen/hackerbotz"-->
<name>Hackerbot</name>
<AIML_chatbot_rules>config/AIML</AIML_chatbot_rules>
<!--Method for gaining shell access, can be overwritten per-attack-->
<!--<get_shell>bash</get_shell>-->
<get_shell>false</get_shell>
<messages>
<show_attack_numbers />
<greeting>Hey there! I need you to make sure our trade secrets and sensitive data are safe. We need to keep track of when the files are on the network, and keep track of copies of the files. If you work with me I'll provide you with some flags.</greeting>
<!--Must provide alternatives for each message-->
<say_ready>When you are ready, simply say 'ready'.</say_ready>
<say_ready>'Ready'?</say_ready>
<next>Ok, I'll do what I can to move things along...</next>
<next>Moving things along to the next one...</next>
<previous>Ok, I'll do what I can to back things up...</previous>
<previous>Ok, backing up.</previous>
<goto>Ok, skipping it along.</goto>
<goto>Let me see what I can do to goto that attack.</goto>
<last_attack>That was the last one for now. You can rest easy, until next time... (End.)</last_attack>
<last_attack>That was the last one. Game over?</last_attack>
<first_attack>You are back to the beginning!</first_attack>
<first_attack>This is where it all began.</first_attack>
<getting_shell>Doing my thing...</getting_shell>
<getting_shell>Here we go...</getting_shell>
<got_shell>...</got_shell>
<got_shell>....</got_shell>
<repeat>Let me know when you are 'ready', if you want to move on say 'next', or 'previous' and I'll move things along.</repeat>
<repeat>Say 'ready', 'next', or 'previous'.</repeat>
<!--Single responses:-->
<help>I am waiting for you to say 'ready', 'next', 'previous', 'list', 'goto *X*', or 'answer *X*'</help>
<say_answer>Say "The answer is *X*".</say_answer>
<no_quiz>There is no question to answer</no_quiz>
<correct_answer>Correct</correct_answer>
<incorrect_answer>Incorrect</incorrect_answer>
<invalid>That's not possible.</invalid>
<non_answer>Wouldn't you like to know.</non_answer>
<!--can be overwritten per-attack-->
<shell_fail_message>Oh no. Failed to get shell... You need to let us in.</shell_fail_message>
</messages>
<tutorial_info>
<title>DLP</title>
<tutorial><%= ERB.new(File.read self.templates_path + 'intro.md.erb').result(self.get_binding) %></tutorial>
<footer>
<%= File.read self.templates_path + 'resources.md.erb' %>
<%= File.read self.templates_path + 'license.md.erb' %>
Randomised instance generated by [SecGen](http://github.com/cliffe/SecGen) (<%= Time.new.to_s %>)
</footer>
<provide_tutorial>true</provide_tutorial>
</tutorial_info>
<attack>
<% $rand_alert0 = SecureRandom.hex(3) %>
<!--<get_shell>msfconsole -x "use exploit/unix/misc/distcc_exec; set RHOST <%= $web_server_ip %>; exploit"</get_shell>-->
<!--<post_command>cat /home/<%= $main_user %>/trade_secrets/clients.csv</post_command>-->
<pre_shell>sshpass -p <%= $root_password %> scp -prv -oStrictHostKeyChecking=no root@<%= $ids_server_ip %>:/var/log/snort/alert /tmp/snort_alert_before; stat1=$?; AAAAA > /dev/null; stat2=$?; sshpass -p <%= $root_password %> scp -prv -oStrictHostKeyChecking=no root@<%= $ids_server_ip %>:/var/log/snort/alert /tmp/snort_alert_after; stat3=$?; echo --$stat1$stat2$stat3; diff -n /tmp/snort_alert_before /tmp/snort_alert_after | tail -n 5</pre_shell>
<get_shell>false</get_shell>
<post_command></post_command>
<prompt>You need to monitor our super sensitive list of clients. You have a copy in /home/<%= $main_user %>/trade_secrets/clients.csv Use one or more Snort rules to detect unencrypted transport of the file. The alert must include the message "<%= $rand_alert0 %>".</prompt>
<condition>
<output_matches>Find the flag</output_matches>
<message>Hope you caught that.</message>
<trigger_next_attack />
</condition>
<condition>
<output_matches>1</output_matches>
<message>:( Failed to contact the web server (<%= $web_server_ip %>)</message>
</condition>
<else_condition>
<message>:( Something was not right...</message>
</else_condition>
<tutorial><%= ERB.new(File.read self.templates_path + 'dlp.md.erb').result(self.get_binding) %></tutorial>
</attack>
<attack>
<% $rand_port = rand(65535)
$rand_alert1 = SecureRandom.hex(3) %>
<pre_shell>sshpass -p <%= $root_password %> scp -prv -oStrictHostKeyChecking=no root@<%= $ids_server_ip %>:/var/log/snort/alert /tmp/snort_alert_before; stat1=$?; nmap -sT -p <%= $rand_port - 1 %>-<%= $rand_port + 1 %> <%= $web_server_ip %> > /dev/null; stat2=$?; sshpass -p <%= $root_password %> scp -prv -oStrictHostKeyChecking=no root@<%= $ids_server_ip %>:/var/log/snort/alert /tmp/snort_alert_after; stat3=$?; echo --$stat1$stat2$stat3; diff -n /tmp/snort_alert_before /tmp/snort_alert_after | tail -n 5</pre_shell>
<get_shell>false</get_shell>
<post_command></post_command>
<prompt>Create a Snort rule that detects any TCP connection attempt to TCP port <%= $rand_port %> to <%= $web_server_ip %>. The alert must include the message "<%= $rand_alert1 %>".</prompt>
<condition>
<output_matches>^--1</output_matches>
<message>:( Failed to scp to your system.</message>
</condition>
<condition>
<output_matches>^--01</output_matches>
<message>:( Failed to scan your system.</message>
</condition>
<condition>
<output_matches>^--[01][01]1</output_matches>
<message>:( Failed to scp to your system (the second time).</message>
</condition>
<condition>
<output_matches>^--00.*<%= $rand_alert1 %>.*<%= $rand_alert1 %></output_matches>
<message>:( Almost. The alert did fire, but it fired more than once!</message>
</condition>
<condition>
<output_matches><%= $rand_alert1 %></output_matches>
<message>:) Well done! <%= $flags.pop %>.</message>
<trigger_next_attack />
</condition>
<else_condition>
<message>:( Your rule didn't get triggered (or didn't include the right message).</message>
</else_condition>
</attack>
<attack>
<% $rand_content1 = SecureRandom.hex(3)
$rand_alert2 = SecureRandom.hex(3) %>
<pre_shell>sshpass -p <%= $root_password %> scp -prv -oStrictHostKeyChecking=no root@<%= $ids_server_ip %>:/var/log/snort/alert /tmp/snort_alert_before; stat1=$?; (sleep 1; echo "USER <%= $rand_content1 %>"; sleep 2; killall -9 nc ) | nc <%= $web_server_ip %> 110 > /dev/null; (sleep 1; echo "user test"; echo "pass test"; echo "stat"; echo "quit"; sleep 2; killall -9 nc ) | nc <%= $web_server_ip %> 110 > /dev/null; stat2=$?; sshpass -p <%= $root_password %> scp -prv -oStrictHostKeyChecking=no root@<%= $ids_server_ip %>:/var/log/snort/alert /tmp/snort_alert_after; stat3=$?; echo --$stat1$stat2$stat3; diff -n /tmp/snort_alert_before /tmp/snort_alert_after | tail -n 5</pre_shell>
<get_shell>false</get_shell>
<post_command></post_command>
<prompt>Create a Snort rule that detects any packet with the contents "<%= $rand_content1 %>" to <%= $web_server_ip %>. The alert must include the message "<%= $rand_alert2 %>".</prompt>
<condition>
<output_matches>^--1</output_matches>
<message>:( Failed to scp to your system.</message>
</condition>
<condition>
<output_matches>^--0.*<%= $rand_alert2 %>.*<%= $rand_alert2 %></output_matches>
<message>:( Almost, but your rule triggered too many times. Are you inspecting the content of the connection?</message>
</condition>
<condition>
<output_matches>^--0.*<%= $rand_alert2 %></output_matches>
<message>:) Well done! <%= $flags.pop %>.</message>
<trigger_next_attack />
</condition>
<else_condition>
<message>:( Your rule didn't get triggered (or didn't include the right message).</message>
</else_condition>
</attack>
<!-- 3 random services -->
<%= ERB.new(File.read self.templates_path + 'random_service_ids_rule.xml.erb').result(self.get_binding) %>
<%= ERB.new(File.read self.templates_path + 'random_service_ids_rule.xml.erb').result(self.get_binding) %>
<%= ERB.new(File.read self.templates_path + 'random_service_ids_rule.xml.erb').result(self.get_binding) %>
<!--Email login attempt
Tries a port scan, then connects twice once with caps, then lower, first with actual user, then incorrect creds, last 2 should trigger the rule
-->
<attack>
<% $rand_alert4 = SecureRandom.hex(3)
$flag1 = $flags.pop
$flag2 = $flags.pop
$flag3 = $flags.pop
%>
<pre_shell>sshpass -p <%= $root_password %> scp -prv -oStrictHostKeyChecking=no root@<%= $ids_server_ip %>:/var/log/snort/alert /tmp/snort_alert_before; stat1=$?; nmap -sT -p 110 <%= $web_server_ip %> > /dev/null; (sleep 1; echo "USER <%= $main_user %>"; echo "PASS <%= $main_user_pass %>"; echo "STAT"; echo "QUIT"; sleep 2; killall -9 nc ) | nc <%= $web_server_ip %> 110; (sleep 1; echo "user test"; echo "pass test"; echo "stat"; echo "quit"; sleep 2; killall -9 nc ) | nc <%= $web_server_ip %> 110; stat2=$?; sshpass -p <%= $root_password %> scp -prv -oStrictHostKeyChecking=no root@<%= $ids_server_ip %>:/var/log/snort/alert /tmp/snort_alert_after; stat3=$?; echo --$stat1$stat2$stat3; diff -n /tmp/snort_alert_before /tmp/snort_alert_after | tail -n 5</pre_shell>
<get_shell>false</get_shell>
<post_command></post_command>
<prompt>Create a Snort rule that detects any unencrypted POP3 email *user authentication attempt* (someone trying to log in), to a mail server on <%= $web_server_ip %>. The alert must include the message "<%= $rand_alert4 %>". Up to three flags will be awarded, based on the quality of the rule.</prompt>
<condition>
<output_matches>^--1</output_matches>
<message>:( Failed to scp to your system.</message>
</condition>
<condition>
<output_matches>^--0.*<%= $rand_alert4 %>.*<%= $rand_alert4 %>.*<%= $rand_alert4 %></output_matches>
<message>:( Almost, but your rule triggered too many times. Are you inspecting the content of the connection?</message>
</condition>
<condition>
<output_matches>^--0.*<%= $rand_alert4 %>.*Classification.*User.*<%= $rand_alert4 %></output_matches>
<message>:-D Well done! ALL THREE FLAGS!: <%= $flag1 %>, <%= $flag2 %>, <%= $flag3 %>.</message>
<trigger_next_attack />
</condition>
<condition>
<output_matches>^--0.*<%= $rand_alert4 %>.*<%= $rand_alert4 %></output_matches>
<message>8-) Well done! Two flags: <%= $flag1 %>, <%= $flag2 %>. Could be further improved with a classification.</message>
<trigger_next_attack />
</condition>
<condition>
<output_matches>^--0.*<%= $rand_alert4 %></output_matches>
<message>:) Well done! <%= $flag1 %>. The alert did get triggered, but it fired only under some conditions. Is your rule caps sensitive? More flags are to be had from a better rule ;-)</message>
<trigger_next_attack />
</condition>
<else_condition>
<message>:( Your rule didn't get triggered (or didn't include the right message).</message>
</else_condition>
</attack>
<attack>
<% $rand_alert5 = SecureRandom.hex(3) %>
<pre_shell>sshpass -p <%= $root_password %> scp -prv -oStrictHostKeyChecking=no root@<%= $ids_server_ip %>:/var/log/snort/alert /tmp/snort_alert_before; stat1=$?; curl <%= $web_server_ip %> >/dev/null; curl <%= $web_server_ip %>/contact.html >/dev/null; stat2=$?; sshpass -p <%= $root_password %> scp -prv -oStrictHostKeyChecking=no root@<%= $ids_server_ip %>:/var/log/snort/alert /tmp/snort_alert_after; stat3=$?; echo --$stat1$stat2$stat3; diff -n /tmp/snort_alert_before /tmp/snort_alert_after | tail -n 5</pre_shell>
<get_shell>false</get_shell>
<post_command></post_command>
<prompt>Create a Snort rule that detects access to http://<%= $web_server_ip %> but NOT http://<%= $web_server_ip %>/contact.html. The alert must include the message "<%= $rand_alert5 %>".</prompt>
<condition>
<output_matches>^--1</output_matches>
<message>:( Failed to scp to your system.</message>
</condition>
<condition>
<output_matches>^--01</output_matches>
<message>:( Failed to test your system.</message>
</condition>
<condition>
<output_matches>^--[01][01]1</output_matches>
<message>:( Failed to scp to your system (the second time).</message>
</condition>
<condition>
<output_matches>^--00.*<%= $rand_alert5 %>.*<%= $rand_alert5 %></output_matches>
<message>:( Almost, but your rule triggered too many times. Are you inspecting the content of the connection?</message>
<trigger_next_attack />
</condition>
<condition>
<output_matches>^--00.*<%= $rand_alert5 %></output_matches>
<message>:) Well done! <%= $flags.pop %>.</message>
<trigger_next_attack />
</condition>
<else_condition>
<message>:( Your rule didn't get triggered (or didn't include the right message).</message>
</else_condition>
</attack>
</hackerbot>

View File

@@ -0,0 +1,121 @@
<html>
<head>
<title><%= self.title %></title>
</head>
<body>
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" href="css/github-markdown.css">
<style>
.markdown-body {
box-sizing: border-box;
min-width: 200px;
max-width: 980px;
margin: 0 auto;
padding: 45px;
}
.markdown-body h4[id^='hackerbot']:after {
display: inline-block;
float: right;
content: url("images/skullandusb.svg");
width: 30px;
}
article {
float: right;
width: calc(100% - 300px);
}
.toc {
float: left;
font-size: smaller;
color: #1a1d22;
width: 300px;
position: fixed;
height: calc(100% - 56px);
overflow-y: scroll;
font-family: sans-serif;
margin-top: 50px;
}
.toc ul {
list-style-type: none;
padding: 0;
margin-left: 1em;
}
.toc li { /* Space between menu items*/
margin: 1em 0;
}
.toc a {
color: #1a1d22;
text-decoration: none;
}
.toc a:hover {
color: #6c036d;
text-decoration: none;
}
.toc a:visited {
color: #1a1d22;
text-decoration: none;
}
.markdown-body pre {
background-color: #570138;
color: whitesmoke;
}
.markdown-body p code span {
color: black !important;
}
.markdown-body p code {
background-color: whitesmoke;
border: 1px solid #eaecef;
}
.markdown-body img[alt="small-left"] {
max-width: 100px;
float: left;
}
.markdown-body img[alt="small-right"] {
max-width: 100px;
float: right;
}
.markdown-body img[alt="tiny-right"] {
max-width: 30px;
float: right;
}
.markdown-body img[alt="small"] {
max-width: 100px;
display: block;
margin-left: auto;
margin-right: auto;
padding: 15px;
}
mark {
background-color: white;
color: #5b29bd;
font-weight: bolder;
}
@media (max-width: 767px) {
.markdown-body {
padding: 15px;
min-width: 200px;
max-width: 980px;
}
.toc {
float: none;
width: 100%;
position: relative;
overflow: auto;
height: auto;
}
article {
float: none;
width: 100%;
}
}
</style>
<div class="toc">
<%= self.html_TOC_rendered %>
</div>
<article class="markdown-body">
<%= self.html_rendered %>
</article>
<script src="js/code-prettify/loader/run_prettify.js?autoload=true&amp;skin=sunburst&amp;lang=css"></script>
</body>
</html>

View File

@@ -0,0 +1,6 @@
## License
This lab by [*Z. Cliffe Schreuders*](http://z.cliffe.schreuders.org) at Leeds Beckett University is licensed under a [*Creative Commons Attribution-ShareAlike 3.0 Unported License*](http://creativecommons.org/licenses/by-sa/3.0/deed.en_GB).
Included software source code is also licensed under the GNU General Public License, either version 3 of the License, or (at your option) any later version.
![small](images/leedsbeckett-logo.png)

View File

@@ -0,0 +1,31 @@
<attack>
<% $services = {'FTP'=>'20','Telnet'=>'23','SMTP'=>'25','HTTP'=>'80','POP3'=>'110','IMAP'=>'143','SNMP'=>'161','LDAP'=>'389','HTTPS'=>'443','LDAPS'=>'636'}
$rand_service1 = $services.keys.sample
$rand_alert3 = SecureRandom.hex(3) %>
<pre_shell>sshpass -p <%= $root_password %> scp -prv -oStrictHostKeyChecking=no root@<%= $ids_server_ip %>:/var/log/snort/alert /tmp/snort_alert_before; stat1=$?; nmap -sT -p 1000,<%= $services[$rand_service1] %> <%= $web_server_ip %> > /dev/null; stat2=$?; sshpass -p <%= $root_password %> scp -prv -oStrictHostKeyChecking=no root@<%= $ids_server_ip %>:/var/log/snort/alert /tmp/snort_alert_after; stat3=$?; echo --$stat1$stat2$stat3; diff -u /tmp/snort_alert_before /tmp/snort_alert_after | tail -n 5</pre_shell>
<get_shell>false</get_shell>
<post_command></post_command>
<prompt>Create a Snort rule that detects any TCP connection attempt to <%= $rand_service1 %> (just the connection attempt, does not require content inspection) on <%= $web_server_ip %>. The alert must include the message "<%= $rand_alert3 %>".</prompt>
<condition>
<output_matches>^--1</output_matches>
<message>:( Failed to scp to your system.</message>
</condition>
<condition>
<output_matches>^--01</output_matches>
<message>:( Failed to scan your system.</message>
</condition>
<condition>
<output_matches>^--[01][01]1</output_matches>
<message>:( Failed to scp to your system (the second time).</message>
</condition>
<condition>
<output_matches><%= $rand_alert3 %></output_matches>
<message>:) Well done! <%= $flags.pop %>.</message>
<trigger_next_attack />
</condition>
<else_condition>
<message>:( Your rule didn't get triggered (or didn't include the right message).</message>
</else_condition>
</attack>

View File

@@ -0,0 +1,3 @@
## Resources
Martin Roesch (n.d.) **Chapter 2:** Writing Snort Rules - How to Write Snort Rules and Keep Your Sanity. In: *Snort Users Manual*. Available from: &lt;[*http://www.snort.org.br/documentacao/SnortUsersManual.pdf*](http://www.snort.org.br/documentacao/SnortUsersManual.pdf)&gt;

View File

@@ -10,6 +10,8 @@ class PersonHashBuilder < StringEncoder
attr_accessor :username
attr_accessor :password
attr_accessor :account
attr_accessor :credit_card
attr_accessor :national_insurance_number
def initialize
super
@@ -20,6 +22,8 @@ class PersonHashBuilder < StringEncoder
self.email_address = ''
self.username = ''
self.password = ''
self.credit_card = ''
self.national_insurance_number = ''
self.account = []
end
@@ -29,6 +33,8 @@ class PersonHashBuilder < StringEncoder
person_hash['address'] = self.address
person_hash['phone_number'] = self.phone_number
person_hash['email_address'] = self.email_address
person_hash['credit_card'] = self.credit_card
person_hash['national_insurance_number'] = self.national_insurance_number
if self.account != []
account = JSON.parse(self.account[0])
@@ -49,6 +55,8 @@ class PersonHashBuilder < StringEncoder
['--email_address', GetoptLong::REQUIRED_ARGUMENT],
['--username', GetoptLong::REQUIRED_ARGUMENT],
['--password', GetoptLong::REQUIRED_ARGUMENT],
['--credit_card', GetoptLong::REQUIRED_ARGUMENT],
['--national_insurance_number', GetoptLong::REQUIRED_ARGUMENT],
['--account', GetoptLong::OPTIONAL_ARGUMENT]]
end
@@ -67,6 +75,10 @@ class PersonHashBuilder < StringEncoder
self.username << arg;
when '--password'
self.password << arg;
when '--credit_card'
self.credit_card << arg;
when '--national_insurance_number'
self.national_insurance_number << arg;
when '--account'
self.account << arg;
end
@@ -79,6 +91,8 @@ class PersonHashBuilder < StringEncoder
'email_address: ' + self.email_address.to_s + print_string_padding +
'username: ' + self.username.to_s + print_string_padding +
'password: ' + self.password.to_s + print_string_padding +
'credit_card: ' + self.credit_card.to_s + print_string_padding +
'national_insurance_number: ' + self.national_insurance_number.to_s + print_string_padding +
'account: ' + self.account.to_s
end
end

View File

@@ -41,6 +41,12 @@
<default_input into="password">
<generator type="password_generator"/>
</default_input>
<default_input into="credit_card">
<generator type="credit_card_generator"/>
</default_input>
<default_input into="national_insurance_number">
<generator type="national_insurance_number_generator"/>
</default_input>
<output_type>person</output_type>
</generator>

View File

@@ -0,0 +1,199 @@
<?xml version="1.0"?>
<scenario xmlns="http://www.github/cliffe/SecGen/scenario"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.github/cliffe/SecGen/scenario">
<system>
<system_name>desktop</system_name>
<base distro="Debian 7.8" type="desktop" name="KDE"/>
<input into_datastore="IP_addresses">
<value>172.16.0.2</value>
<value>172.16.0.3</value>
<value>172.16.0.4</value>
</input>
<!--generate two accounts, YOU and someone else-->
<input into_datastore="accounts">
<generator type="account">
<input into="username">
<generator type="random_word_generator">
<input into="wordlist">
<value>mythical_creatures</value>
</input>
</generator>
</input>
<input into="password">
<value>tiaspbiqe2r</value>
</input>
<input into="super_user">
<value>true</value>
</input>
<input into="leaked_filenames">
<value>trade_secrets/code.pl</value>
<value>personal_secrets/private</value>
<value>trade_secrets/clients.csv</value>
</input>
<input into="strings_to_leak" into_datastore="sensitive_code">
<value>no warnings; `$=`;$_=\%!;($_)=/(.)/;$==++$|;($.,$/,$,,$\,$",$;,$^,$#,$~,$*,$:,@%)=($!=~/(.)(.).(.)(.)(.)(.)..(.)(.)(.)..(.)......(.)/,$"),$=++;$.++;$.++;$_++;$_++;($_,$\,$,)=($~.$"."$;$/$%[$?]$_$\$,$:$%[$?]",$"&amp;$~,$#,);$,++;$,++;$^|=$";`$_$\$,$/$:$;$~$*$%[$?]$.$~$*${#}$%[$?]$;$\$"$^$~$*.>&amp;$=`</value>
<generator type="personal_sensitive" />
<encoder type="csv">
<input into="strings_to_encode" into_datastore="clients">
<generator type="person" />
<generator type="person" />
<generator type="person" />
<generator type="person" />
<generator type="person" />
<generator type="person" />
</input>
</encoder>
</input>
</generator>
<generator type="account">
<input into="username">
<generator type="random_word_generator">
<input into="wordlist">
<value>mythical_creatures</value>
</input>
</generator>
</input>
<input into="password">
<value>test</value>
</input>
<input into="super_user">
<value>false</value>
</input>
<input into="leaked_filenames">
<value></value>
</input>
<input into="strings_to_leak">
<value></value>
</input>
</generator>
<generator type="account">
<input into="username">
<generator type="random_word_generator">
<input into="wordlist">
<value>mythical_creatures</value>
</input>
</generator>
</input>
<input into="password">
<value>test</value>
</input>
<input into="super_user">
<value>false</value>
</input>
<input into="leaked_filenames">
<value></value>
</input>
<input into="strings_to_leak">
<value></value>
</input>
</generator>
</input>
<input into_datastore="hackerbot_access_root_password">
<generator type="strong_password_generator"/>
</input>
<!--Create the users-->
<utility module_path=".*parameterised_accounts">
<input into="accounts">
<datastore>accounts</datastore>
</input>
</utility>
<utility module_path=".*kde_minimal">
<input into="autologin_user">
<datastore access="0" access_json="['username']">accounts</datastore>
</input>
<input into="accounts">
<datastore>accounts</datastore>
</input>
<input into="autostart_konsole">
<value>true</value>
</input>
</utility>
<utility module_path=".*handy_cli_tools"/>
<utility module_path=".*nmap"/>
<utility module_path=".*iceweasel">
<input into="accounts">
<datastore>accounts</datastore>
</input>
<input into="autostart">
<value>true</value>
</input>
<input into="start_page">
<datastore access="1">IP_addresses</datastore>
</input>
</utility>
<utility module_path=".*pidgin">
<input into="server_ip">
<datastore access="1">IP_addresses</datastore>
</input>
<input into="accounts">
<datastore access="0">accounts</datastore>
</input>
</utility>
<vulnerability module_path=".*ssh_root_login">
<input into="root_password">
<datastore>hackerbot_access_root_password</datastore>
</input>
</vulnerability>
<network type="private_network" >
<input into="IP_address">
<datastore access="0">IP_addresses</datastore>
</input>
</network>
</system>
<system>
<system_name>hackerbot_server</system_name>
<base distro="Kali" name="MSF"/>
<service type="ircd"/>
<utility module_path=".*metasploit_framework"/>
<utility module_path=".*handy_cli_tools"/>
<utility module_path=".*nmap"/>
<service type="httpd"/>
<utility module_path=".*hackerbot">
<input into="hackerbot_configs">
<generator module_path=".*ids_exfiltration">
<input into="accounts">
<datastore>accounts</datastore>
</input>
<input into="root_password">
<datastore>hackerbot_access_root_password</datastore>
</input>
<input into="hackerbot_server_ip">
<datastore access="1">IP_addresses</datastore>
</input>
</generator>
</input>
</utility>
<network type="private_network" >
<input into="IP_address">
<datastore access="1">IP_addresses</datastore>
</input>
</network>
<build type="cleanup">
<input into="root_password">
<generator type="strong_password_generator"/>
</input>
</build>
</system>
</scenario>