Signature-based intrusion detection

Authors: Mikhail Zolotukhin and Timo Hämäläinen

1. Introduction

Due to the exponentially growing number of network attacks intrusion detection has become an important area of research. In this tutorial, we will get familiar with Snort and Zeek, which are free and open source network intrusion detection and prevention systems. To complete this tutorial, you need to configure the virtual environment presented in our previous tutorials.

The remainder of this tutorial is organized as follows. Several preliminary tasks are presented in Section 2. Section 3 describes how to install and configure Snort in pfSense as well as mechanism of writing simple rules for Snort. Section 4 introduces specification-based IDS Zeek. Some simple assignments are listed in Section 5. Section 6 concludes the tutorial.

This tutorial (including assignments) takes on average 9.15 hours to complete.

2. Preliminary questions

Link to download the second article returns 404 and the page shows "This link is not valid". I've tried searching the same article through JykDok, but no luck. Maybe that is just temp problem (no luck even if connected to university network).

29 Sep 23

Thanks, added an alternative link

Edit: the 1st link works again

29 Sep 23 (edited 30 Sep 23)

3. Intrusion detection with Snort

In this part of the tutorial, we install and configure Snort for our pfSense gateway. To complete this part of the tutorial, you are supposed to have the virtual network environment configured during previous exercises.

3.1 Installation and configuration.

  1. Run following VMs: gateway, dnsserv, webserv, alice, bob and kali.
  1. In alice-VM's browser, open

    pfsense.home.arpa 

    and login to our pfSense's web configurator.

  1. Go to System -> Package Manager -> Available packages. Find Snort and click "Install".
  1. After the installation has completed, Snort will appear in Services -> Snort. Open it and get familiar with the interface.

  2. We will test intrusion detection with our attacker, that is in OPT2 subnet. By default, Snort adds machines from all local subnets (in our case those are LAN, OPT1 and OPT2) to the default pass list, which means Snort will not be able to block traffic from those machines. Let's create our own pass list before we start configuring Snort rules.

    First, go to Firewall -> Aliases, switch to "IP" and click "+ Add". Enter name, e.g. "oceanic"; description, e.g. "Bank oceanic web server"; select type "Host(s)", enter IP of our web server "192.168.11.2" and click save. Apply changes.

    In pfSense's menu go back to Services -> Snort, switch to "Pass Lists" and click "+ Add". Enter some name for your new pass list, e.g. "opt2passlist", add some description, e.g. "My passlist for opt2". In section "Auto-Generated IP Addresses" uncheck the option "Local Networks". In section "Custom IP Address from Configured Aliases" type the name of the alias we created ("oceanic"), and click "Save".

  1. Go to "Snort Interfaces". We should now configure Snort on OPT2 interface. Click "+ Add" icon to add Snort interface mapping. In the new window, put a mark to the check-box "Enable interface", select Interface "OPT2" and enter some description.

    In "Alert Settings", check "Send Alerts to System Log". In "Block Settings", check both "Block Offenders" and "Kill States". In dialogue "Which IP to Block" select "SRC". Find dialogue "Pass List" in section "Choose the Networks Snort Should Inspect and Whitelist" and change from "default" to the pass list ("opt2passlist") we created in the previous step.

    Finally, click "Save" and go back to "Snort Interfaces".

3.2 Detection of web-application's password brute-force

  1. Let's write our first simple rule for Snort. For this purpose, click "pencil" button in Actions of our OPT2 interface mapping that has text "Edit this Snort interface mapping". Go to section "OPT2 Rules". In "Category Selection" select "custom.rules". After that, you will see blank form "Defined Custom Rules" where you can add your custom rules.
  1. We are going to create a rule to block bank web-page login bute-force with Hydra. First, let's find out, what signature we should look for. Go to webserv-VM, and run in terminal:

    $ sudo tcpdump -i enp0s3 dst port 80 and 'tcp[((tcp[12:1]&0xf0)>>2):4]=0x504f5354' -v

    to start dumping HTTP POST packets.

  1. Go to kali-VM. Download the password list (if it has not yet been done):

    $ wget http://student:Ties327_2023@users.jyu.fi/%7Emizolotu/teaching/files/password.lst

    Run hydra against Alice's bank account:

    $ hydra 192.168.11.2 http-form-post "/accounts/loginproc.php:username=^USER^&
    password=^PASS^&Submit=Login:index.php" -t 10 -w 60 -l alice -P password.lst -I
  1. If you did not mistype anything in previous two steps, you should see POST packets in webserv-VM's terminal. You can wait until the correct password is found, or just stop brute-force whenever you want.

  2. Look through packets in webserv-VM's terminal. What properties do they have in common? Probably, the most important is timestamp: time interval between two adjacent packets is inhumanly short. All packets use HTTP method POST, targeted to "/accounts/loginproc.php" and contain words "username", "password" and "Submit", that are actually post-data parameters required to login. This information is already enough to detect and block the attacker, however, there are some other parameters identical for all the packets, e.g. user-agent "Hydra" and TCP flags PSH ACK "[P.]", that also can be used.

  1. Go back to "custom.rules" in pfSense's Snort rules for OPT2 and add the following line to the form (symbol "#" here is used to comment the title line, it is required):

    # Password brute-force
    
    alert tcp any any -> 192.168.11.2 80 ( \
    classtype: web-application-attack; \ 
    msg: "Bank Oceanic password brute-force"; \
    content: "/accounts/loginproc.php"; nocase; \
    content: "post"; nocase; \
    content: "username"; nocase; \
    content: "password"; nocase; \
    content: "submit"; nocase; \
    threshold: type both, track by_src, count 10, seconds 1; \
    react: block; \
    sid:000000001; )

    Here "alert" is the rule action, "tcp" is the protocol, the 1-st "any" is the source IP address, the 2-nd "any" is the source port, "->" is direction operator, "192.168.11.2" is the destination IP address, "80" is the destination port, and the structure in brackets is the rule options. The most important part in the rule options is "classtype" that is used to categorize a rule as detecting an attack that is part of a more general type of attack class. Snort provides a default set of attack classes that are used by the default set of rules it provides. Defining classifications for rules provides a way to better organize the event data Snort produces. Snort will not work properly if "classtype" is not specified or specified incorrectly. The "sid" keyword is used to uniquely identify Snort rules, it must be some unique number. As you can notice, the line we just added describes a simple rule which generates an alert when during 1 second at least 10 TCP packets to URI "/accounts/loginproc.php" that contain "POST", "username", "password" and "Submit" go through gateway's Snort interface from any source to the webserver.

    The 4-th line in the rule looked originally as follows:

    uricontent: "/accounts/loginproc.php"; nocase; \ 

    However, somehow it did not work for some students, you can test both variants.

    Once the rule has been added, you can click "Save". Fix typos if present.

    If you have an error of type "!any is not allowed in EXTERNAL_NET", the problem is subnet "0.0.0.0" in HOME_NET. This bug took place in the previous years. You can try to fix it as follows. Create one more pass list in Services -> Snort -> Pass lists, name it e.g. "home_net_list", remove all checkmarks except "Local Networks" go to snort interface OPT2 settings, find "Home Net" in "Choose the networks snort should inspect and whitelist", and select the new list "home_net_list", click "View List" to make sure that "0.0.0.0" is not there, if "0.0.0.0" is somehow still there, go back to editing "home_net_list", remove all checkmarks, add IPs manually: "192.168.10.0/24", "192.168.11.0/24" and "192.168.12.0/24", save, and then select this list in snort OPT2 settings. After that, double check that all other settings are the same as stated in the instructions of the previous subsection and save. Finally, try to save the rule again.

    One more thing you can try is to reinstall Snort, reportedly it resolves most of the issues.

  1. If you do not have any problems, just come back to "Snort Interfaces" and click on "blue arrow" icon in Snort Status to make Snort running on OPT2. If it is already running, restart it by clicking "round arrow" icon in Snort Status of LAN mapping that has text "Restart Snort on this interface". If you see the green check-mark, the configuration is completed and Snort is running.
  1. To test our new rule, on webserv-VM's run tcpdump with the same parameters as before (if it is not already running):

    $ sudo tcpdump -i enp0s3 dst port 80 and 'tcp[((tcp[12:1]&0xf0)>>2):4]=0x504f5354' -v

    and from kali-VM's terminal, start brute-forcing Alice's password again:

    $ hydra 192.168.11.2 http-form-post "/accounts/loginproc.php:username=^USER^&
    password=^PASS^&Submit=Login:index.php" -t 10 -w 60 -l alice -P password.lst -I

    If you configured everything properly, the attack will immediately stop, i.e. you will stop receiving packets on webserv-VM.

  1. Return to the Snort configuration web page opened in the alice-VM's browser and click "Alerts". There should be an alert caused by the web application attack performed by source IP 192.168.12.2.
  1. Go to "Blocked" and find the attacker's IP address currently being blocked by Snort. Alice's bank account has been saved :)
  1. Before we move to the next subsection, first, stop the brute-force attack in kali-VM's terminal, and only after that, stop capturing packets in the webserv-VM's terminal (Ctrl+C) and clear "Alerts" in Snort. Finally, remove the attacker's IP 192.168.12.2 from "Blocked". You can also double-check that the attacker can now access the web server pages.

3.3 Slowloris detection

  1. We are going to create a rule to block Slowlowis attack. In the case of this attack, an attacker tries to hold its connections with the server open as long as possible by periodically sending subsequent HTTP headers, adding to-but never completing-the requests. As a result, the web server keeps these connections open, filling its maximum concurrent connection pool, eventually denying additional connection attempts from clients.
  1. Go to kali-VM. Run slowhttptest against our web server:

    $ slowhttptest -c 1000 -H -i 10 -r 200 -t GET -u http://192.168.11.2/accounts/
    index.php -x 24 -p 3

    Slowhttptest will show how many connections it established with the target server. It should be around 200 for the attack to be successful. When you see "service available NO", you can try to browse

    https://oceanic.ties327.jyu.fi/accounts/ 

    from alice-VM's Firefox. It should be unavailable (or quite slow). Stop the attack from kali-VM.

  1. Let's create a rule to stop the attack. Again click "pencil" button for OPT2 mapping in "Snort Interfaces". Go to section "OPT2 Rules". In "Category Selection" select "custom.rules" and add new lines to the form:

    # Bank Oceanic index page DoS
    
    alert tcp any any -> 192.168.11.2 80 ( \
    classtype: attempted-dos; \ 
    msg: "Bank Oceanic index page DoS"; \
    flow: to_server, established; \
    threshold: type both, track by_src, count 50, seconds 5; \
    react: block; \
    sid:000000002; )

    In this rule, we detect frequent connections to our bank web page (192.168.11.2). If a source establishes 50 connections in 5 seconds, we can reasonably suspect it to be an attacker. Click "Save".

  1. Restart Snort on LAN by clicking "round arrow" icon for OPT2 in "Snort Interfaces".
  1. To test this rule, on kali-VM run slowhttptest again (use http, not https!):

    # slowhttptest -c 1000 -H -i 10 -r 200 -t GET -u http://192.168.11.2/accounts/
    index.php -x 24 -p 3
  2. When you see "service available NO", in alice-VM's Firefox open on Snort configurations check "Blocked" to find that the attacker's IP has been blocked by our rule. The attacker's IP might also be blocked by http_inspect that is by default enabled in Snort. Snort's HTTP INSPECT preprocessor is alerting when some part of a web request or reply does not precisely match the published standards. You can try to browse

    https://oceanic.ties327.jyu.fi/accounts/ 

    from alice-VM's Firefox. It should be available.

  1. Stop the attack from kali-VM. Clear "Alerts". Remove the attacker's IP from "Blocked". Check that you can access the web server from Kali.

3.4 DNS tunneling detection

  1. Finally, let's try to detect DNS tunneling. Start bob-VM.
  1. Go to gateway-VM, enter Shell by pressing "8" in the main menu, and start monitoring DNS traffic on OPT2 interface:

    $ tcpdump -i em3 proto 17 and src port 53 or proto 17 and dst port 53 -vv
  1. Go to kali-VM. Start iodined server:

    $ sudo iodined -f -P 12345 10.0.0.1 kali.ties327another.jyu.fi
  1. In bob-VM's terminal, connect to the iodine server:

    $ sudo iodine -f -P 12345 -r kali.ties327another.jyu.fi
  1. Go back to gateway-VM, and notice a lot of DNS packets with strange payload. They have one thing in common, word "TXT?". Current version of Iodine by default uses TXT type DNS tunneling that we would like to block.

    Important stuff: If you do not see "TXT" in the DNS packets, probably iodine uses different DNS packet type. For example, it can be "NULL" or "CNAME" or something else. Define the type of the tunneling before you go to the next step.

    You can also try to force iodine to use DNS tunneling type you like by using flag -T on the tunnel client (bob-VM), e.g.

    $ sudo iodine -f -P 12345 -r kali.ties327another.jyu.fi -T TXT

    or

    $ sudo iodine -f -P 12345 -r kali.ties327another.jyu.fi -T NULL

    The most important thing is the DNS query type you force should be the same as the DNS tunneling type you try to block with Snort. Or you can just block them all :)

  1. Let's create a rule to stop the attack. Again click "pencil" button for OPT2 mapping in "Snort Interfaces". Go to section "OPT2 Rules". In "Category Selection" select "custom.rules" and add new lines to the form:

    # TXT type DNS tunneling
    
    alert udp any any -> any any ( \
    classtype: bad-unknown; \ 
    msg: "Potential TXT type DNS tunneling"; \
    content: "|01 00|"; offset: 2; \
    content: "|00 00 10 00 01|"; offset: 12; \
    threshold: type both, track by_src, count 10, seconds 5; \
    sid:000000003; )

    This rule starts looking for pattern "01 00" (recursive query) after first 2 bytes of the payload. Then it looks for byte string "00 00 10 00 01" (TXT type query) after 12 bytes of the payload. If both these conditions are met 10 times in 5 seconds from the same source IP, an alert is generated. Do not forget to click "Save".

    If the tunneling type used by iodine is NULL, the rule would look like:

     # NULL type DNS tunneling
    
     alert udp any any -> any any ( \
     classtype: bad-unknown; \ 
     msg: "Potential NULL type DNS tunneling"; \
     content: "|01 00|"; offset: 2; \
     content: "|00 00 0a 00 01|"; offset: 12; \
     threshold: type both, track by_src, count 10, seconds 5; \
     sid:000000004; )

    The only difference with the previous rule is NULL query type "|00 00 0a 00 01|" instead of TXT one "|00 00 10 00 01|".

  1. Restart Snort on LAN by clicking "round arrow" icon for OPT2 in "Snort Interfaces".
  1. To test this rule, on bob-VM simply start sending any kind of traffic to the attacker through the tunnel established, e.g. ping the tunnel server:

    $ ping 10.0.0.1

    After about five packets, ping stops and the tunnel will be blocked.

  1. If this is the case, in alice-VM's Firefox open on Snort configurations check "Blocked" to find that the attacker's IP has been blocked by our rule.
  1. Stop the tunnel from kali-VM. Clear "Alerts". Remove the attacker's IP from "Blocked".

3.5 Community rules for Snort

  1. Obviously, you do not have to write all the rules for Snort by yourself, since there are lots of Snort rule-sets available. On the pfSense configuration web page, find and click "Global settings". There you can choose what Snort rules to download. For example, you can install Snort VRT rules, but before that you should create a user account, ain't nobody got time for that. You can also use Snort Community rules and Emerging rules. Put check-marks in boxes "Click to enable download of Snort GPLv2 Community rules" in category "Snort GPLv2 Community Rules" and "Click to enable download of Emerging Threats Open rules" in the category "Emerging Threats Rules". Click "Save".
  1. Go to Updates and click "Update Rules". Community and Emerging Rules for Snort will be installed.
  1. Once the rules have been updated, return to "Snort Interfaces", find your OPT2 interface and click "pencil" button with text "Edit this snort interface mapping".
  1. In section "OPT2 Categories", select rules you want to apply. Enable "Snort GPLv2 Community Rules" and click "Save".
  1. In section "OPT2 Rules", in Category Selection, select GPLv2_community.rules. You can now enable or disable certain rules from the community set. Finally, click "Apply".
  1. Come back to "Snort Interfaces" and click on "round arrow" button to restart Snort on OPT2. If Snort is not running (cross instead of green check-mark), there are probably mistakes in the rule selected. For example, some of the Emerging rules (if you enabled them) may have errors, which do not allow Snort to run. If you see the green check-mark, the configuration is completed and Snort is running.
  1. When you complete this part of the tutorial, it makes sense to disable Snort on OPT2 interface or at least uncheck "Block offenders" in the Snort's interface settings, so that the IDS will not affect attacks described further. You can enable Snort later when doing assignments.

4. Intrusion detection with Zeek

Zeek is an intrusion detection system, which allows one to capture live traffic and analyze trace files captured using other tools. Even though Zeek comes with its own programming language that can be used to extract and analyze necessary information from the packets captured to detect anomalous traffic patterns, writing a complicated program using this language could be painful. We will use Zeek scripting language to write a simple program that generates an alert (notice) when particular event happens.

  1. In alice-VM's browser, open

    pfsense.home.arpa 

    and login to the pfSense web configurator.

  1. Go to System -> Package Manager -> Available packages. Find Zeek and install it. The installation will take some time.
  1. Once the installation has completed, navigate to Services -> Zeek NSM. Put a check mark into the box "Check to enable the Zeek NSM". Select OPT2 as Zeek interface. In "Local Network Configuration" box, type

    192.168.11.0/24

    Click "Save".

  1. On alice-VM, download file "strange_login_attempt.zeek":

    $ wget http://student:Ties327_2023@users.jyu.fi/%7Emizolotu/teaching/files/
    strange_login_attempt.zeek

    This file allows us to detect HTTP POST entities with URI "/accounts/loginproc.php" and long username-password combinations. Spend some time to look through the content of the file:

    $ gedit strange_login_attempt.zeek

    Almost every line in the file is explained, so it should not cause difficulties to understand.

    Below is an explanation how we split a string in function "preprocess_data()", it sometimes causes difficulties. This function is used to split HTTP POST data string to pieces to extract username-password tuple. For example, if we have string "username=alice&password=hackmenot&Submit=Login", we simply split it by looking for substring "&Submit=". This substring splits our string into two parts: "username=alice&password=hackmenot" and "Login". To retrieve the first part, i.e. "username=alice&password=hackmenot", we simply take element 0 (because count in this programming language starts from 0) and return it as the result. If we wanted the second part, i.e. "Login", we would take element 1).

    In the advanced assignment, you will have to extract the username value, e.g. "alice". You can do it for example by splitting the data string in such a way that substring "username=alice" is extracted, then splitting again to obtain "alice".

  1. Copy this file to the gateway via SSH:

    $ scp strange_login_attempt.zeek admin@192.168.10.1:/usr/local/share/zeek/site/
  1. From alice-VM's terminal, SSH to the gateway:

    $ ssh admin@192.168.10.1

    In the pfsense main menu press 8, to go to the shell.

  1. Open file "/usr/local/share/zeek/site/local.zeek":

    # vi /usr/local/share/zeek/site/local.zeek

    Scroll to the end of the file and insert the following line:

    @load strange_login_attempt

    If you have never used vi before, it can be tricky :) First, use arrows to put cursor on the line you want to edit. Press "i" to start inserting symbols and type the line mentioned above. Finally, press Esc and then type ":wq" to save changes and exit.

    If you do not like using vi, you can scp the file to alice-VM, edit with gedit or nano and scp it back to the gateway-VM.

    You can next run in the SSH session open with gateway-VM:

    # tail /usr/local/share/zeek/site/local.zeek

    to double-check that the line is added correctly.

  1. Finally, we can deploy Zeek:

    # /usr/local/bin/zeekctl deploy

    You can check that Zeek status is "running" with the following command:

    # /usr/local/bin/zeekctl status
  1. To test Zeek, first make sure that you have disabled Snort in the pfSense web configurator and that kali-VM's IP address "192.168.12.2" is not among hosts blocked by Snort. Once Snort has been successfully disabled, in kali-VM's terminal, run Sqlmap as follows:

    $ sqlmap -u http://192.168.11.2/accounts/loginproc.php --data="username=alice&
    password=123&Submit=Login" --flush-session --batch

In task 3.4 webserv was instructed to be turned off. For me the solution for missing notice.log file was just turn webserv back on and run SQLmap twice.

01 Oct 23

removed that "shutdown webserv" instruction, but I am not sure it was the reason why it did not work for the guys below

01 Oct 23 (edited 01 Oct 23)
  1. In Zeek NSM menu in the pfsense web configurator, switch to "Real Time Inspection". In "Log file to view", select "notice.log". The file "notice.log" should contain lots of notices of type "HTTP::Strange_Login_Attempt" with the attacker's IP address. If file "notice.log" is missing, run the sqlmap command from the previous step again, looks like there are some problems with updating notices in the latest version of Zeek. If after that there are still no notices, you probably have done something wrong, double check all the configurations.

    This file "notice.log" can be also checked through the shell opened with pfSense:

    # cat /usr/local/logs/current/notice.log

    Sometimes it is easier to monitor logs in the shell. If you redeploy Zeek as described above, this notice.log will be cleared, the alerts will be saved somewhere in "/usr/local/logs".

I did everything 100% "right" but still no logs from Zeek.

Rebooting pfsense solved the issue.

17 Sep 23

The file doesn't exist for me either. I have triple-checked every configuration step and tried to reboot the machines, but nothing works.

19 Sep 23

I see you both have completed the assignment, so did it work in the end?

Ok, it does not work; probably the latest zeek update broke something...

Edit: it works, but for some reason it required me to run the sqlmap command above two times for the notices to appear... that is not good

21 Sep 23 (edited 21 Sep 23)

It did not work for me, I helped myself with some reverse engineering of the Zeek script.

21 Sep 23

5. Assignment (5p.)

5.1 Preliminary

Complete the test based on the preliminary questions (1 point).

well, it kinda works, but there is something wrong with the notices, it does not generate file notice.log if there are too few notices, not sure exactly how it works... I updated instructions how I managed to do it.

Edit: I don't mind if you process the assignment file with Python or any other programming/scripting language as Julian did

22 Sep 23 (edited 01 Oct 23)
# sbid_basic1

5.2 Basic

The requirements for the assignment do not state that the rules should block the attack, only detect it. However the notion at the end remind the student to unblockt the attacker afterwards.

05 Oct 23

Write a rule in pfSense's Snort, that allows one to detect brute-force attack against the SSH service running on the web server. The requirements are the following:

  • The rule should check TCP connections to the web server's SSH server
  • The rule should search for the packets that contain "SSH-"
  • An alert should be thrown if there are 3 such packets in 10 seconds from the same source

Your rule should follow the requirements above, otherwise full points will not be granted! Test that your rule works correctly, e.g. by performing the SSH brute-force attack as you have done it in the tutorial about pentesting. Copy-paste the rule into the answer box below. Do not forget to unblock the attacker afterwards!

The SSH password brute-force attack detection Snort rule (0.5 points):

que?

06 Oct 23
# sbid_basic2

For the next task, download the following PCAP file on alice-VM:

$ wget http://student:Ties327_2023@users.jyu.fi/%7Emizolotu/teaching/files/sbid_ssh.pcap

Copy it to the temporary directory on the gateway via SSH:

$ scp sbid_ssh.pcap admin@192.168.10.1:/tmp/

Next, SSH to pfSense:

$ ssh admin@192.168.10.1

and press "8" to enter the shell.

Find your Snort configuration file. For this purpose, in the pfSense's shell check:

# ls /usr/local/etc/snort/

and find the directory corresponding to the Snort interface created during the tutorial, it should look similar to "snort_31991_em3", i.e. it should start with "snort" and end with "em3", the number can be different though (not sure what exactly this number means).

Once the directory has been found, run Snort against the capture file downloaded as follows:

# snort -c /usr/local/etc/snort/snort_*_em3/snort.conf -r /tmp/sbid_ssh.pcap -l /tmp -q

This command should work as it is, but you can obviously substitute "snort_*_em3" with the exact name of the Snort interface directory as mentioned above. After that, if your SSH brute-force detection rule is correct, an alert file will be generated in the same directory "/tmp". Check this alert file:

# cat /tmp/alert

and find the IP address corresponding to the SSH password brute-force attack recorded in the capture file analyzed. Enter the IP address into the answer box below. There can be multiple alerts, but if you have done everything correctly, all of them will be caused by the same host. It is worth mentioning, that if you have several active rules in Snort, then they also can generate some alerts. It therefore makes sense to remove or comment out all the rules other than the one you are currently testing.

As previously, do not forget to remove the attacker's IP address from "Blocked" in the pfSense's web configurator. At the end, you can also remove the alert file, because Snort will append new alerts to the same file, if it exists, thus, removing the file will make it easier for you to analyze future alerts, e.g. the ones generated in the next task:

# rm /tmp/alert

The SSH password brute-force attacker's IP address (0.5 points):

# sbid_basic3

Write a rule in pfSense's Snort, that allows one to detect an HTTP POST Sqlmap attack against our web server. The requirements are the following:

  • The rule should check TCP connections to the web server's plain HTTP port
  • The rule should search for the packets that contain some non-alphanumeric symbols
  • An alert should be thrown if there are 3 such packets in 30 seconds from the same source

Test that your rule works correctly, e.g. by performing an SQL injection attack as it has been done in the pentesting tutorial. Tip: a non-alphanumeric symbol in an HTTP POST packet is logged by Snort with "%" followed by its ASCII code, e.g. symbol " ' " (single quotation mark) would be logged as "%27". There are other methods to detect non-alphanumeric symbols, but please use something with "%" to be on the safe side.

Copy-paste the rule into the answer box below. Do not forget to unblock the attacker afterwards!

The SQL injection attack detection Snort rule (0.5 points):

# sbid_basic4

The rule works great, but I only get 0.3 points. Is there a certain way this is supposed to be done?

05 Oct 23

no, resubmit

05 Oct 23 (edited 05 Oct 23)

Tip: please do not use "pcre" if you do not know how it works; the task is easily doable by using only "content"; the rule is very straightforward here.

11 Oct 23 (edited 11 Oct 23)

Download the following PCAP file on alice-VM:

$ wget http://student:Ties327_2023@users.jyu.fi/%7Emizolotu/teaching/files/sbid_sql.pcap

and test your SQL injection detection rule using this file in the same way as it was done in the previous assignment, i.e. copy it to pfSense with scp, SSH to pfSense, run Snort against the PCAP file and check the resulting alert file. As previously, there can be multiple alerts, but if you have done everything correctly, all of them will be caused by the same host. Enter the IP address of this host into the answer box below.

The SQL injection attacker's IP address (0.5 points):

# sbid_basic5

One more tip: I've noticed some students put the same IP to this box as in the SSH brute-force detection assignment; is it because you forgot to clear the alert file and remove the previous rule, or are you just testing your luck? :) In any case, IP is not the same here.

11 Oct 23 (edited 11 Oct 23)

After completing the basic assignments, please disable Snort on OPT2 interface, or at least disable blocking offenders.

5.3 Advanced

Modify Zeek policy "strange_login_attempt.zeek" as follows.

  • Modify function "preprocess_data()" in such a way that it extracts value of parameter "username", e.g. assuming the data string is "username=alice&password=hackmenot&Submit=Login", the result should be just "alice".

  • Change the threshold value up to 3 in the event handler "http_entity_data()".

  • Add one more "if" condition in the event handler "http_entity_data() so that the score is incremented if the username value contains non-alphanumeric symbols.

To check, if a string variable (e.g. my_string) contains a particular substring (e.g. "abc") you can use keyword "in":

if ( "abc" in my_string)
{
    # do something here
}

Again, remember, that all non-alphanumeric symbols in a HTTP POST form are logged with their ASCII codes.

Even though the information above should be enough to modify the policy file, here is the link to Zeek documentation for type string to get familiar with functions for string analysis in Zeek language, just in case.

Once the necessary modifications have been introduced, redeploy Zeek with the new policy file. Next, on kali-VM, download the following text file with username-password tuples:

$ wget http://student:Ties327_2023@users.jyu.fi/%7Emizolotu/teaching/files/sbid_userpass

and run Hydra against our web server using these tuples as follows (one line!):

$ hydra 192.168.11.2 http-form-post "/accounts/loginproc.php:username=^USER^&password=^PASS^
&Submit=Login:index.php" -C sbid_userpass -I

If you have done everything correctly, as the result, file notice.log on pfSense will contain exactly 5 lines corresponding to the strange login attempts. If you see only 4 (or less), then it is probably caused by that bug in Zeek related to the notices update. In this case, just run the Hydra command again. As a result, there should be 5 unique login attempts (the total number of lines will be bigger, but some lines will have the same credentials).

In the case of success, extract unique password values from these notices and copy-paste them into the answer box below, one password per line. Only password values are required. For example, if POSTDATA in notice.log is "username=alice&password=hackmenot&Submit=Login", you have to put "hackmenot" into the answer box. Do not copy extra symbols! The result should look similar to the follows:

123
admin
hackmenot
webserv
anotherone

If you copy more than five, only first five will be evaluated.

Passwords from the strange login attempts detected with Zeek (2 points):

Updated a bit instructions for this assignment because of this notice file bug.

21 Sep 23 (edited 21 Sep 23)
# sbid_advanced

I got the passwords needed, but I must admit that the logfile seemed a bit messy. Sometimes the password wasn't under the "sub" header, but instead under the "src" or even the "remote_location.region" headers. I must have done something wrong, I guess, but I still managed to gain the passwords so does this count :D...? To the comment following this one -> Yes I checked the passwords from the pfsense website GUI. Perhaps that was the reason then, but I guess I found the right answers from the output anyway, so I presume that suffices..?

06 Oct 23 (edited 09 Oct 23)

If you mean notice.log in the gui, yes it will be shown incorrectly, I guess because of the non-alphanumerical characters that are treated by the gui as separators between columns; I therefore recommend looking into notice.log in the console

06 Oct 23 (edited 06 Oct 23)

5.4 General comments and feedback

Let us know how many hours in total have you spent on this assignment:

# sbid_time

On a scale from 1 to 10, estimate how interesting and difficult was the tutorial:

# sbid_interest
# sbid_difficulty

You can also give us some general feedback:

# sbid_feedback

6. Conclusion

In this tutorial, we got familiar with signature-based intrusion detection approach with the help of Snort and Zeek.

More information on the topic can be found at:

7. Comments

These are the current permissions for this document; please modify if needed. You can always modify these permissions from the manage page.