Big companies finally wised up and began working with hackers rather than against them. Offering bounties worth thousands, even millions of dollars, they pay hackers to report vulnerabilities either directly to them or through bounty hunter programs such as HackerOne. The process is pretty simple. The hacker sends the vulnerability report to the company, the company patches the vulnerably, the bounty is paid, and finally, the vulnerability disclosed. Everyone wins. Usually (see notes at end of article).
Yelp’s new bug bounty program
On September 6, 2016, Yelp announced the launch of their bug bounty program, inviting hackers to target their websites in search of vulnerabilities. The bounties ranged from $100 to $15,000 per exploit found. The program was managed through HackerOne, a popular vulnerability disclosure company based in San Francisco (same locale as Yelp). In the hacking session below, I found two critical unpatched vulnerabilities on the first Yelp server I targeted. They were reported to Yelp but unfortunately, were flagged as “not applicable” because, well, they were patched after I reported them. More about that at the end of the article…
A day in the life of a bug bounty hunter
What follows is a step-by-step roadmap of the hacking session against Yelp. I included the commands and results along with snippets of my thought process during the session. For the non-hackers, hopefully this provides insight on the process a hacker takes when attempting to penetrate a system.
At the end of the article, I’ve included an explanation of the vulnerabilities found and why Yelp did not pay bounties for the discovery of critical unpatched flaws on their system. Meeting the requirements for the assignment (finding a vulnerability), my hacking session was stopped as soon as the vulnerabilities were identified. In a real exploitation session, we would have gone much further. Of course, that would have required more risk and a much longer article which, well…
A Yelp hacking session
Hackers are more organized than you think
Hacking is vastly different from what is portrayed in movies and TV where a hooded-hacker hunches over a keyboard in a darkened room, fingers wailing away as he jumps effortlessly from command to command. Hacking is a thought process, not really something you can edify, and requires structure and organization. As my first step, I created an encrypted “Yelp” directory in the cloud to store docs, findings, etc.
I also use OneNote to document my findings. I have two OneNote templates I use in hacking sessions – one is an overview template for the target domain which includes general notes, person reconnaissance, business relationships, technical reconnaissance, application reconnaissance, and various bits of info dug out of the Internet via search engines.
The second template falls hierarchically under the first and includes details for each IP address related to the target. Included in this template is OS information, the traceroute to the target, services discovered, potential exploits (todo), found exploits (to report or take advantage of), preventative measures the company has in place (e.g. firewalls, IDS, design structures), user accounts discovered, and a diary and log of events.
Start with whois
After reviewing the bounty program guidelines and setting up the initial notes on each target listed in the program guidelines, a non-invasive whois is a natural first choice for any hack session. Whois provides insight into how the target’s DNS is organized as well as person reconnaissance. In Yelp’s case, it revealed an administrator email address and some tidbits about the company’s “personality”.
From whois, you can tell that Yelp protects their brand names with MarkMonitor and that they are careful not to reveal any employee details in their DNS registration. That’s a tipoff that Yelp might know what they’re doing and exploits may be tougher to find.
Run the traceroute
The natural next step is to run traceroute and document that path to the target. Keep an eye on the IPs right before the destination – they’re likely IDS, IPS, firewalls, network devices, etc. Exploiting these can give you a direct link to the target.
I typically run several Maltego transforms before I begin “hacking” in earnest. Maltego lets you run reconnaissance scripts (called transforms) against a target and presents the results in a graphical representation of the target company’s infrastructure. For some reason, the Maltego visuals stick in my head and help my thought process throughout the remainder of the hacking session. Plus, Maltego typically nudges out some pretty cool information about the target.
I spin off newly discovered nodes into new graphs and drill down into each one. Spinning off the targets into a root node in their own graph keeps things from getting cluttered and mirrors your natural thought process as you focus on different nodes while moving through the graph. Each graph of course, is saved off in the encrypted Yelp project directory for later reference. Interesting snippets are clipped and pasted into OneNote.
Maltego revealed right away that Yelp was running nginx web servers along with several popular third party libraries (Ajax, Google Analytics, JQuery, etc.). It also hinted at Rackspace, Cloudflare, and Amazon EC2 hosting as well as a website on a popular WordPress hosting service. It spat out a few Yelp email addresses and phone numbers which I jotted down in the person reconnaissance notes. Contact information likely wouldn’t be used in a bug bounty hunt where social engineering and brute force password hacking are usually prohibited but in a session where you intend to truly exploit the target, personal information is a valuable gem.
Maltego also revealed a test server (www.test.yelp.com). Although not within the bounty program guidelines, it could be used to pivot off of. It also revealed an unusual debbiedunn.yelp.com domain (redirects to yelp.com) and a few other unusual domains – something to come back and look at later.
An interesting target revealed – WordPress
One node in the Maltego transforms jumped out at me – a Yelp WordPress blog. It was hosted with a popular professional WordPress hosting company which means the network infrastructure was likely pretty tight (boy, was I wrong on that one). However, WordPress is notoriously easy to hack. For one, WordPress itself is a complex CMS consisting of a backend database (e.g. MySql) and a PHP code base. Being Open Source, there’s plenty of opportunity to find bugs in any module that has become outdated.
Secondly,there are two primary reasons for a hacker to jump for joy when stumbling across a WordPress blog. First, WordPress blogs are often managed by a company’s communications department which means technical knowhow is lacking. They are likely to install themes and plugins without considering the potential security ramifications of a third-party addition to their site’s infrastructure. WordPress customizations provide copiousness hacker opportunities.
Secondly, most WordPress admins think that as long as their system is kept patched, they are safe. They may pop over to their Plugins panel and see that everything is patched and up-to-date and breathe a sigh of relief. The problem is, ownership of WordPress plugins are dropped like car keys. The owner of the code may disappear and nobody notices that the plugin is no longer maintained. I’ve seen plugins sit in place for years before somebody realized they are no longer being maintained.
Thus, Yelp’s WordPress blog caught my attention – yelpblog.com at 184.108.40.206 became my first target.
Scanning with nmap
With basic information in hand, it’s time to start mapping out Yelp’s services which means, nmap of course. Nmap is used extensively by hackers and those familiar with it know that it must be finessed to produce good results. The tool is not weak by any means but it’s not a cookie-cutter type solution either. There are many parameters, options, settings, etc. that can be adjusted which is important because corporate security systems regularly block scans. In most cases, you have to tweak nmap settings until you uncover a way through the company’s defenses. I’m not sure whether Yelp left the door open for the bug bounty program or are just poorly secured, but scans against Yelp servers were among the easiest I’ve seen.
I run my hacking toolset in a virtual machine (VM) that is purposely configured to isolated it from my host system – no file sharing, printer sharing, open ports, etc. Also, I typically run two VMs at the same time, each connected through a different VPN connection. This allows me, for example, to run one connection out of Hong Kong with the second connection coming out of Australia (or more realistically, in this case, San Francisco). If a scan gets blocked, you simply change to a different VPN node (I run a mac changer too in case the target’s IPS (Intrusion Protection System) blocks by mac address). The dual machine setup also lets you scan on one machine while spraying decoy packets from the other. Again, in Yelp’s case this was not needed. They pretty much let you scan with impunity which means you can pound their security all day with no repercussions.
I like to run nmap through Metasploit (db_nmap). This lets you use a Metasploit workspace for the session that will automatically keep track of hosts, ports, etc. Faraday could also be used but it seems a bit buggy to me. Make sure the postgresql database is running and Metasploit is connected to the database. Fire up msfconsole and use “workspace -a yelp” to create a new workspace for the Yelp session.
You typically want to start with slow, less noisy nmap scans and progress to riskier scans as you get a feel for how the target server is defended. In Yelp’s case, it’s full speed ahead which saves a lot of time.
Below is the nmap command used.
nmap -sSV -O -v -f –spoof-mac 0 -g 53 –data-length 0 -D 220.127.116.11,18.104.22.168,22.214.171.124,126.96.36.199,188.8.131.52 -T2 184.108.40.206
-sS tells nmap to run a SYN scan (very common) while the -sV says to attempt to identify version information. I usually leave off -sV for the first runs to keep the scan quiet. However, since Yelp freely allows the scans through their defenses, there’s no need to peek through the window when we can just kick in the door.
–spoof-mac 0 instructs nmap to generate a random mac address for the session. -g 53 forces the scan through the DNS port which is typically open for most companies. –data-length 0 randomizes the packet length.
The –D nmap option passes a list of decoy IP address to spray during the scan in an attempt to throw off any IDS (Intrusion Detection System) that may be in place. The first few IP addresses are just random but the last two bear an explanation. The 220.127.116.11 address is there solely for the eyes of anyone who may be manually scanning the logs. It’s meant to stand out, to draw their attention away from the real IP addresses. Again, hacking isn’t a technique, it’s a thought process, and we attempt to do everything possible to avoid detection.
The 18.104.22.168 decoy address is there for the same reason. The 22.214.171.124 decoy IP address is the actual IP address that we are targeting in the scan. Nothing throws a network admin more than seeing traffic in their log that does not make sense. Using the target’s IP as a decoy causes it to show up in log files as the originator of the request rather than the target.
Finally, -T2 slows the scan down a little.
Analyzing nmap results
nmap identified the host as Linux (no surprise given it’s a WordPress site) and discovered the expected port 80/443 web server ports and a subtle attempt to hide ssh at port 2222. However, version detection hinted port 2222 might be FTP so I make a note to investigate this further. If it is indeed a secure shell port, given Yelp’s (or the WordPress host’s) lax security on their border, it could likely be brute-forced. Then again, given the obvious numbering of the port, it could be a decoy too.
Given the WordPess blog already caught my eye, I stopped the TCP scans here. In a more extensive session, with hardier firewalls blocking the attempts, I would run several more scans using different methods to enumerate the server’s services.
Next up, we check the UDP ports with this nmap command:
nmap -sUV -O -v -f –spoof-mac 0 -g 53 –data-length 0 –randomize-hosts -D 126.96.36.199,188.8.131.52,184.108.40.206,220.127.116.11,18.104.22.168 -T2 22.214.171.124
A few interesting ports came up which go in my notes so I can come back to them later. The UDP ports are always interesting.
[*] Nmap: 139/udp open|filtered netbios-ssn
[*] Nmap: 161/udp open|filtered snmp
[*] Nmap: 445/udp open|filtered microsoft-ds
[*] Nmap: 3130/udp open|filtered squid-ipc
[*] Nmap: 5060/udp open|filtered sip
[*] Nmap: 16503/udp open|filtered unknown
[*] Nmap: 21476/udp open|filtered unknown
[*] Nmap: 33355/udp open|filtered unknown
[*] Nmap: 49152/udp open|filtered unknown
Check the site with Burp
While the scans were running (with –T2, they can run about 20 minutes or more), Burp was fired up so I could run through the site and see if anything unusual stands out. Burp is a great hacker tool that lets you easily step through a website noting the web server’s responses to your requests (Webscarab is similar to Burp and also popular with hackers). You can even rewind requests and change input on the fly, fuzz requests, spider the site, and more. I run Burp on the default port and use Firefox with the Proxy Selector extension set to connect through the Burp proxy (I also keep a Chrome browser open with a connection through the VPN to use for its debugging tools and for browsing the Internet outside of Burp).
Especially notable was Yelp’s search function, a potential opportunity to slip something through. I was able to force an HTTP error (Yelp does not trim the length of the search input) and since Yelp had not replaced the default HTTP error pages, I was able to confirm that they were indeed running nginx (no surprise there either). Still, the search function seemed fairly tight so I put it aside for a while, intending to come back to it later. Since they don’t trim the length of the search request, a rookie mistake, I figured there are probably CSRF and XSS vulns in here somewhere.
Most importantly though, after hacking around a while with Burp and checking out the site’s source code, I gained a better feel for Yelp’s blog structure. Some of the WordPress plugins were recognizable so it was time to start scanning WordPress.
Scanning Yelp’s WordPress installation
The first thing you want to do with a WordPress hacking session is fire up wpscan and see what they’ve got running under the hood.
wpscan –url www.yelpblog.com
wpscan found the robots.txt file in which a quick peek confirmed they had the default WordPress admin pages in place. A few tries at the typical WordPress admin URLs revealed a couple of problems with Yelp’s security design. Firstly, even though the default WordPress admin login page is not used, it redirects you to Yelp’s employee login page at https://yelp.onelogin.com/login (OneLogin is a popular access management company – God help us all the day they are hacked). This redirect is a potential security design flaw since it makes the employee login page much too easy to access.
Even uglier, the login page includes a detailed login instructions page and a flawed retrieve password function (see notes below where I hammer this function after I’ve enumerated the Yelp employee accounts). On the instructions page were additional security design issues. Firstly, the page reveals that employees should login to the WordPress blog with their Active Directory username and password. This means security federation in place and more importantly, if we crack a WordPress account, we have a Yelp network account in hand. That’s the biggest problem with exposing network credentials outside the corporate network. I’m surprised that companies allow this. I’m even more surprised that Yelp proudly advertises the fact on their employee login page.
The login instructions also revealed the type of two-factor authentication in use (Duo Security, a popular two-factor authentication service) as well as the email address for their internal help desk (firstname.lastname@example.org) – another design flaw that freely dishes out a critical internal contact we can use in a social engineering attack.
The scan also showed their theme to be yelpblog-v1.0.0. Even though it’s obviously a custom theme, or more likely, a custom theme inheriting off a commercial packaged solution, the 1.0 version brings hope.
Digging deeper into the scan results, wpscan reveals another Yelp goof – the theme’s readme.txt file was left in the themes directory. A quick look at the readme confirms that Yelp’s custom theme is indeed based on a packaged theme from ThemeKraft that serves as a starter theme, hooking in the Bootstrap framework. The readme also kindly documents the framework versions used, the path to the theme’s source, and the config.json which is bound to contain useful details on the site’s layout and infrastructure.
I found it remarkable that Yelp left this file behind but this is not unusual. Company’s often leave Readme’s in place as documentation for developers. It’s a dumb move but hackers appreciate the extra assistance – unless it’s a red herring.
A quick sidenote about red herrings and the hacker’s conspiracists mindset
Most companies don’t take the time to leave red herrings but they should. Just like hackers throw in decoy IP addresses as red herrings during scans, companies have many opportunities to throw red herrings at hackers via fake readmes, bogus banners for services, fake employee ids, and email address traps, etc. It’s not foolproof but certainly leads hackers, at least initially, down the wrong path. However, hackers, by nature, are conspiracists at heart and every piece of information uncovered is suspect in their minds. Were the WordPress user ids we enumerated real or honeypot traps? Is the web server really nginx or was the banner faked by a clever administrators? Is port 2222 really a SSH port or simply a deceptive mask for another service? Questions like these run through hacker’s minds during the hacking session so red herrings won’t necessarily stop them – but they will slow them down or more importantly, force them to take more risks during their investigation.
Given what I already saw about Yelp’s stance toward security, I was pretty sure they weren’t wiley enough to leave a red herring. This was a legit readme which helped me map out the theme used in their WordPress installation.
Finally, at the bottom of the wpscan was the proverbial pot of gold at the end of the rainbow. I was stunned to see that there were two critical vulnerabilities that were left unpatched. Unfortunately, I did not seek to obtain evidence that the vulnerabilities were exploitable – as you’ll see below, a big mistake on my part.
With two vulnerabilities and a host of design issues in hand, I felt I had my bounty but went a bit further in the WordPress scan in order to cleanly wrap up that part of the analysis. I downloaded the wp-json configuration file, formatted it in Visual Studio, and examined it to find several interesting configuration parameters, especially with regards to the search function. I filed the json config away and highlighted a few key configuration values to come back and examine later.
Next I enumerated the plugins with wpscan. As I said, plugins are the easiest way to penetrate a WordPress site so it’s important to determine what third-party plugins the site is running behind the scenes.
wpscan –url www.yelpblog.com –enumerate p
The plugin list was extensive and in addition, the scan revealed Yelp was using “Must Use Plugins” (mu-plugins) which is definitely an advantage for a hacker. Must-use plugins are plugins installed in the content folder which are automatically enabled on all sites in the installation. The great thing about this, for hackers anyway, is that they do not show in the default list of plugins and they don’t show in WordPress update notifications. Yelp’s security was looking sloppier and sloppier as I progressed through the analysis.
[+] We found 15 plugins:
[+] Name: advanced-custom-fields – v4.4.8
| Latest version: 4.4.8 (up to date)
| Location: https://www.yelpblog.com/wp-content/plugins/advanced-custom-fields/
| Readme: https://www.yelpblog.com/wp-content/plugins/advanced-custom-fields/readme.txt
[+] Name: akismet – v3.2
| Latest version: 3.2 (up to date)
| Location: https://www.yelpblog.com/wp-content/plugins/akismet/
| Readme: https://www.yelpblog.com/wp-content/plugins/akismet/readme.txt
[+] Name: capability-manager-enhanced – v1.5.7
| Latest version: 1.5.7 (up to date)
| Location: https://www.yelpblog.com/wp-content/plugins/capability-manager-enhanced/
| Readme: https://www.yelpblog.com/wp-content/plugins/capability-manager-enhanced/readme.txt
[+] Name: easy-twitter-feed-widget – v0.5
| Latest version: 0.5 (up to date)
| Location: https://www.yelpblog.com/wp-content/plugins/easy-twitter-feed-widget/
| Readme: https://www.yelpblog.com/wp-content/plugins/easy-twitter-feed-widget/readme.txt
[+] Name: google
| Latest version: 1.3.5
| Location: https://www.yelpblog.com/wp-content/plugins/google/
[+] Name: html-sitemap
| Latest version: 1.3
| Location: https://www.yelpblog.com/wp-content/plugins/html-sitemap/
[+] Name: multiple-post-thumbnails – v1.6.6
| Latest version: 1.6.6 (up to date)
| Location: https://www.yelpblog.com/wp-content/plugins/multiple-post-thumbnails/
| Readme: https://www.yelpblog.com/wp-content/plugins/multiple-post-thumbnails/readme.txt
[+] Name: raw-html
| Latest version: 1.5
| Location: https://www.yelpblog.com/wp-content/plugins/raw-html/
[+] Name: regenerate-thumbnails – v2.2.6
| Latest version: 2.2.6 (up to date)
| Location: https://www.yelpblog.com/wp-content/plugins/regenerate-thumbnails/
| Readme: https://www.yelpblog.com/wp-content/plugins/regenerate-thumbnails/readme.txt
[+] Name: rest-api – v2.0-beta13.1
| Latest version: 2.0-beta13.1 (up to date)
| Location: https://www.yelpblog.com/wp-content/plugins/rest-api/
| Readme: https://www.yelpblog.com/wp-content/plugins/rest-api/readme.txt
[+] Name: tinymce-advanced – v4.4.1
| Latest version: 4.4.1 (up to date)
| Location: https://www.yelpblog.com/wp-content/plugins/tinymce-advanced/
| Readme: https://www.yelpblog.com/wp-content/plugins/tinymce-advanced/readme.txt
[+] Name: top-10
| Latest version: 2.3.2
| Location: https://www.yelpblog.com/wp-content/plugins/top-10/
[!] We could not determine a version so all vulnerabilities are printed out
[!] Title: top-10 1.9.2 – Setting Manipulation CSRF
[i] Fixed in: 1.9.3
[!] Title: Top 10 <= 2.3.0 – Cross-Site Scripting (XSS)
[i] Fixed in: 2.3.1
[+] Name: twitter
| Latest version: 1.5.0
| Location: https://www.yelpblog.com/wp-content/plugins/twitter/
[+] Name: WordPress-importer – v0.6.3
| Latest version: 0.6.3 (up to date)
| Location: https://www.yelpblog.com/wp-content/plugins/WordPress-importer/
| Readme: https://www.yelpblog.com/wp-content/plugins/WordPress-importer/readme.txt
[+] Name: WordPress-seo – v3.5
| Latest version: 3.5 (up to date)
| Location: https://www.yelpblog.com/wp-content/plugins/WordPress-seo/
| Readme: https://www.yelpblog.com/wp-content/plugins/WordPress-seo/readme.txt
[+] Finished: Thu Sep 8 15:25:59 2016
[+] Requests Done: 1144
[+] Memory used: 154.492 MB
[+] Elapsed time: 00:04:07
Many of the plugins were not patched and/or were custom plugins. Either way, great for hackers. We can download and install the plugins, examine the code (PHP), and hammer them offline looking for vulnerabilities. We’ll need to dig into these further but for now, we have one more enumeration to run. The scan below enumerates WordPress users.
wpscan –url www.yelpblog.com –enumerate u
This scan revealed six Yelp WordPress user accounts. WordPress reveals usernames with nary a blush. On any WordPress site (assuming they have not blocked in their .htaccess file), enter a url like this: https://www.yelpblog.com/?author=1 using a number to retrieve the author. The resulting page will list the user (and in Yelp’s case, e.g. the wpengine user, a technical description of what the account is used for) and any articles they have been posted under that user account. To enumerate users manually, simply start with 1 and work your way up.
If this were an exploitation session, we would almost certainly be able to brute force or social engineer our way through Yelp’s defenses using these accounts.
[+] Identified the following 6 user/s:
| Id | Login | Name |
| 1 | wpe**ine | wpengine, Author at |
| 2 | yelp**blog | Yelp, Author at |
| 3 | l*zz | Lindsay Liebson, Author at |
| 4 | ra**lker | Senior PR |
| 5 | kct**us | Kristen Titus, Author at |
| 6 | kha**ord | PR |
Remembering that earlier I had found Yelp’s employee login page, I fed a few of the newly discovered user accounts through the login process to see what happened. Firstly, supplying a bogus username presents you with a response that appears different from the response you receive when supplying a valid username. This allows the enumeration of accounts. In addition, the error page returned when supplying a valid Yelp username converts the username to the Yelp employee’s email address and returns it with the error message. I tested this by sending an email to a bogus address and another email to the email address resolved in the error page. The bogus email bounced back immediately while the one sent to the WordPress account delivered with no error.
Bingo. This is an email address enumeration flaw. We now have email addresses for all of the enumerated WordPress accounts. If this were an exploit session, we’d start with the lower level employees and social engineer our way into the system.
The remaining WordPress probes would require deeper manual investigation, most of which would be invasive. With the information I already had in hand, it was time to pause and submit the vulnerabilities I discovered up to this point.
The vulnerability report is submitted to Yelp
Through HackerOne, I submitted three vulnerability reports – the two critical vulnerabilities that wpscan dug out and a third report that listed design issues (the WordPress admin redirect, instructions on the employee login page that reveal internal network architecture, email address enumeration, etc.).
Yelp security responds to the report
After a short period of time, I received a response from Yelp’s security team. It was immediately obvious that Yelp’s security team are network guys, not hackers. They found no problem with the design issues I reported and flagged the report as informational.
I was OK with that because indeed, the design issues were informational only – suggestions which could go either way. I would have certainly implemented the fixes that I reported but Yelp has their own ideas and I respect that.
But wait. The critical unpatched vulnerability reports were also nixed as “not applicable”. Huh?
Did Yelp screw the bug bounty hunter?
According to Yelp, the two critical unpatched vulnerabilities were not applicable meaning, they had already been patched. Interesting. Maybe the scan threw a false positive and since I failed to demonstrate the vulnerabilities were exploitable, I accepted it as a true unpatched system without confirming the discovery.
I went back to Yelp’s WordPress site and pulled up the HTML source. The WordPress version is usually pretty easy to determine through the HTML source. Sure enough, they were on 4.6.1. The vulnerabilities were properly patched.
Later that day, I was eating dinner, fuming over my mistake when it hit me. What if they took my report and then patched the system afterward? I went to Google and pulled a cached copy of the page captured earlier that day and to my surprise, as of that morning, they were indeed running an older version of WordPress. My initial report was accurate – Yelp was running a vulnerable unpatched WordPress installation and patched it later that day, after I found the vulnerabilities and reported them to their security team.
To say I was upset would be an understatement. For Yelp to roll out a bug bounty program on a system that seemed to be not only un-hardened but was running an old version of WordPress, one several point-versions behind with multiple known vulnerabilities – well, that confirmed what I saw throughout my hacking session – Yelp’s security guys really aren’t paying attention to detail. It was a master goof on their part – and that’s most likely why the report was slipped under the rug and flagged as “not applicable”.
The problem with bug bounty programs
The problem with bug bounty programs is how the vulnerability report is handled by the company. Typically reports are reviewed by low level security analysts – often those who are responsible for keeping corporate systems safe – and sometimes bug bounties make them look, well, stupid. To roll out an unpatched system into a bug bounty program is far beyond a rookie mistake. At the very least you run a patching system that slams security patches in as fast as possible. According to the cached Google page, Yelp was running a WordPress installation that was several point versions behind. And I’m sure that’s not something a low-level employee would want advertised to their superiors.