{"id":738,"date":"2017-05-31T12:30:51","date_gmt":"2017-05-31T12:30:51","guid":{"rendered":"https:\/\/zed.inguardians.com\/?p=738"},"modified":"2018-11-30T21:08:22","modified_gmt":"2018-11-30T21:08:22","slug":"protecting-the-mr-robot-vuln-hub-machine-part-1-breaking-a-password-spray-with-ossec-active-response","status":"publish","type":"post","link":"https:\/\/zed.inguardians.com\/blog\/protecting-the-mr-robot-vuln-hub-machine-part-1-breaking-a-password-spray-with-ossec-active-response\/","title":{"rendered":"Protecting the Mr Robot Vuln Hub Machine \u2013 Part 1 \u2013 Breaking a Password Spray with OSSEC Active Response"},"content":{"rendered":"
(This post has a sequel<\/a>.)<\/p>\n I admit it\u200a\u2014\u200aI haven\u2019t been purely vacationing during my San Diego PTO. I\u2019ve found particular intellectual joy in figuring out how to hack some of the CTF-type virtual machines from VulnHub<\/a>. That led to looking through an answer key (also known as a \u201cwalkthrough\u201d) for one and wanting to publish an attack-defense hybrid walk-through, showing how to attack the machine, but also break each stage of the attack.<\/p>\n Spoilers Ahead! If you want to attack the Mr. Robot virtual machine on VulnHub<\/a>, please come back and read this afterward.<\/p>\n The Mr Robot vulnerable virtual machine\u2019s author got creative with his story tie-in. Take a look at the first screen you see when you find the web application listening on port 80:<\/p>\n <\/p>\n In this blog post, I’ll take you through the attack on this capture-the-flag-style system and then on how you could defend it without stripping out the vulnerabilities.<\/p>\n Looking at the web server\u2019s robots.txt file grants the first flag, as well as a dictionary file for username and password guessing, called fsocity.dic.<\/p>\n <\/p>\n A quick run of dirbuster…<\/p>\n <\/p>\n …finds a WordPress login page.<\/p>\n <\/p>\n This version of WordPress gives differing messages for non-existent user names versus incorrect passwords, allowing us to brute force to get a correct username.<\/p>\n The fsocity.dic file has a ton of repetition, so we sort and uniq it, pruning it from more than 858,000 lines to under 11,500 lines.<\/p>\n It takes under two minutes to find that the elliot username is valid.<\/p>\n <\/p>\n Now, we use wfuzz to try passwords for two and half minutes, when it finds the show\u2019s protagonist\u2019s password, \u201cER28\u20130652.\u201d<\/p>\n <\/p>\n As my friend Skip Duckwall<\/a> likes to say, \u201cWinner, winner, chicken dinner!\u201d<\/p>\n I\u2019ve sent a few over 5,500 login attempts to find a user name, then about the same number to find that user\u2019s password.<\/p>\n <\/p>\n <\/p>\n This is the first point where my defender\u2019s mind just wants to scream, \u201cWhy the heck did you let me send tens of thousands of login attempts?!\u201d Let\u2019s use OSSEC to break that pair of brute forcing attacks. Mike Poor<\/a> introduced me to OSSEC about five years ago. It\u2019s a powerful detection tool, combining four\u00a0major functions:<\/p>\n I teach OSSEC in the newer versions of the Linux Lockdown classes that I\u2019ve been giving since 2001 at conferences like Black Hat, CanSecWest, and RSA and in private corporate trainings. \u00a0(Here’s a link to this year’s Black Hat class<\/a>.) \u00a0OSSEC\u00a0is a good fit here for adding some quick rate limiting to a login page. Let\u2019s break this password spray by installing OSSEC and creating a rule that triggers an iptables DROP rule whenever an attacker tries to login more than, say, twenty (20) times in ten (10) minutes from the same IP address. I note a couple caveats to this approach at the end of this post.<\/p>\n Here\u2019s what we\u2019ll do next:<\/p>\n Let’s start with that installation.<\/p>\n Before installing OSSEC, I used the rest of the attack (covered in this post\u2019s sequel) to get an account on the system, grant it sudo access, and install SSH on the system. Then I downloaded OSSEC from https:\/\/ossec.github.io\/<\/a> and compiled it like so.<\/p>\n First, uncompress the tarball and run the install.sh script. \u00a0Select your language:<\/p>\n <\/p>\n Next, hit enter to being answering questions. \u00a0Choose the “local” installation type, since we’re just applying this to one system:<\/p>\n <\/p>\n Choose whether you’d like integrity checking and rootkit detection turned on:<\/p>\n <\/p>\n Choose to enable active response, with its firewall drop script:<\/p>\n <\/p>\n Now hit enter one more time to end the installation:<\/p>\n <\/p>\n We see the commands to start OSSEC below. \u00a0Note that the entire installation happens in \/var\/ossec:<\/p>\n <\/p>\n We\u2019ve now got OSSEC installed. Let\u2019s tell it what log files to watch for web server requests. The Mr. Robot CTF is based on Ubuntu 14.04 LTS, so we\u2019ll want to watch files in \/var\/log\/apache2\/.<\/p>\n We\u2019ll add this to the end of the \/var\/ossec\/etc\/ossec.conf file, just before the <\/ossec_config> line:<\/p>\n Next, we need to make sure OSSEC will know how to decode an Apache access log. Here\u2019s the kind of line we\u2019re looking for:<\/p>\n Let\u2019s look in OSSEC\u2019s etc\/decoder.xml file, which tells OSSEC how to do its first pass parsing on log files, grouping them into program types and extracting a few items, like IP addresses and URL\u2019s. Scanning through, we find there\u2019s a decoder already created for this:<\/p>\n <\/p>\n This will work for the Apache httpd server, as well as for many others. \u00a0So, if we create rules that specify \u201cweb-accesslog,\u201d we\u2019ll match against items in a web server access log. \u00a0Now we need to find or create a rule to match WordPress login attempts.<\/p>\n It turns out there\u2019s already a rule in place that notes WordPress attacks. It was pretty easy to find. I\u2019d like to say that I found it by running a grep on \/var\/ossec\/rules\/*, but that\u2019s not what happened. I created my own rule, tested it, and found that a OSSEC already shipped with this rule:<\/p>\n Now, we need to create a rule that alerts only if this rule (31509) fires more often than, say, 5 times in 1 minute. I was about to write my own, but found that the very next rule in the same rule file does exactly this, but with different thresholds:<\/p>\n Let\u2019s tweak the thresholds. OSSEC has a counterintuitive way of counting. To say that we want to trigger the higher priority rule (31510) when the number of alerts on rule 31509 exceeds 20 in 10 minutes, we have to change that line to:<\/p>\n I can\u2019t say why, as I haven\u2019t sat down to read the source code, but the documentation is clear on this:<\/p>\n OK. We\u2019ve got a rule that fires once we get 20 attempts on wp-login.php in ten minutes. Let\u2019s tell OSSEC to block the IP address for 10 minutes each time this rule gets triggered.<\/p>\n We open up etc\/ossec.conf and find the active response sections. By default, the firewall drop action is set to trigger on any rule that has severity\/priority of 6 or higher. We\u2019d like to be more targeted, just applying it to one specific rule. We comment out the <level> block and replace it with a <rules_id> block, naming our rule:<\/p>\n Now let\u2019s try 21 login attempts on WordPress. On the 21st<\/sup> attempt, our browser stops being able to connect to the target system. \u00a0Note the “Connecting…” in the tab name and bottom left of the browser — the browser is stuck unable to connect for 5 minutes.<\/p>\n <\/p>\n Here\u2019s what happens in the iptables firewall:<\/p>\n And here\u2019s what we find in the OSSEC active response log:<\/p>\n This was only a five minute delay, but that’s enough to make a password spray start to take painfully long. \u00a0More powerfully, OSSEC can let us make the firewall rule period last increasingly longer. \u00a0If we add a <repeated offenders> directive to the <active-response> firewall section, so it reads as below, our attacker will have a five minute blacklist period the next time he starts, then a one hour blacklist period, and then a one day blacklist period. \u00a0That’s certainly enough to cripple\u00a0a password spray.<\/p>\n In the sequel to this blog post<\/a>, I\u2019ll walk through the rest of the Mr Robot CTF and show how we can break the next two stages of the attack with AppArmor and file permissions.<\/p>\nAttack: Password Spraying the Login\u00a0Page<\/h2>\n
Defense: Break Password Sprays with OSSEC\u2019s\u00a0iptables Active Response<\/h2>\n
\n
\n
Step 1: Install OSSEC<\/h3>\n
Step 2: Configure OSSEC to watch the Apache log file<\/h3>\n
<!-- 201705xx JJB \u2013 tell OSSEC to watch Apache log files -->\r\n <localfile>\r\n <log_format>syslog<\/log_format>\r\n <location>\/opt\/bitnami\/apache2\/logs\/access_log<\/location>\r\n <\/localfile><\/pre>\n
Step 3: Find or Create a Decoder to Read Apache Log Lines<\/h3>\n
10.0.0.178 - - [13\/Nov\/2015:01:22:19 +0000] \"POST \/wp-login.php HTTP\/1.1\" 302 -\r\n<\/pre>\n
Step 4: Find or Create a Rule to Detect WordPress login Attempts<\/h3>\n
<!-- WordPress wp-login.php brute force -->\r\n <rule id=\"31509\" level=\"3\">\r\n <if_sid>31108<\/if_sid>\r\n <url>wp-login.php|\/administrator<\/url>\r\n <regex>] \"POST \\S+wp-login.php| \"POST \/administrator<\/regex>\r\n <description>CMS (WordPress or Joomla) login attempt.<\/description>\r\n <\/rule><\/pre>\n
<!-- If we see frequent wp-login POST's, it is likely a bot. -->\r\n <rule id=\"31510\" level=\"8\" frequency=\"6\" timeframe=\"30\">\r\n <if_matched_sid>31509<\/if_matched_sid>\r\n <same_source_ip \/>\r\n <description>CMS (WordPress or Joomla) brute force attempt.<\/description>\r\n <\/rule><\/pre>\n
<rule id=\"31510\" level=\"8\" frequency=\"18<\/b>\" timeframe=\"1<\/b>0<\/b>\"><\/pre>\n
\u201c[frequency] Specifies the number of times the rule must have matched before firing. The \r\nnumber that triggers the rule is actually 2 more than this setting.\u201d<\/span><\/span><\/span><\/em><\/pre>\n
Step 5: Configure OSSEC to Activate a firewall drop rule<\/h3>\n
<active-response>\r\n <!-- Firewall Drop response. Block the IP for\r\n - 600 seconds on the firewall (iptables,\r\n - ipfilter, etc).\r\n -->\r\n <command>firewall-drop<\/command>\r\n <location>local<\/location>\r\n\t<!-- <level>6<\/level> -->\r\n <rules_id>31510<\/rules_id>\r\n <timeout>600<\/timeout>\r\n <\/active-response><\/pre>\n
Step 6: Verify Effectiveness<\/h3>\n
iptables -A INPUT -s 192.168.17.134\/32 -j DROP<\/pre>\n
\/var\/ossec\/logs # cat active-responses.log\r\nThu May 25 02:11:54 UTC 2017 \/var\/ossec\/active-response\/bin\/host-deny.sh \r\n add - 192.168.17.130 1495678314.2468 31510\r\nThu May 25 02:14:08 UTC 2017 \/var\/ossec\/active-response\/bin\/host-deny.sh \r\n delete - 192.168.17.130 1495678314.2468 31510<\/pre>\n
<active-response>\r\n<command>firewall-drop<\/command>\r\n <location>local<\/location>\r\n<rules_id>31510<\/rule_id>\r\n <timeout>600<\/timeout> \r\n<repeated_offenders>600,3600,86400\r\n<\/repeated_offenders>\r\n <\/active-response><\/pre>\n