Bare Knuckled Antivirus Breaking

Author: b

Endpoint security products provide an attractive target for attackers because of their widespread use and high-privileged access to system resources. Researchers have already demonstrated the risks of complex input parsing with unmanaged code and even sloppy implementation of client- and server-side components of these products. While these attacks are still relevant, it is still generally overlooked how security software breaches some important security boundaries of the operating system. In this research we first present a generic self-defense bypass technique that allows deactivation of multiple endpoint security products. Then we demonstrate that self-defense can hide exploitable attack surface by exploiting local privilege escalation vulnerabilities in 6 products of 3 different vendors. You can download our whitepaper here:

Bare-Knuckled Antivirus Breaking (PDF)

The following part of this blog post contains demonstration videos and some additional notes about the exploits described in the paper. We will also use this post to publish up-to-date information about affected vendors and fixes.

(more…)


Emulating custom crytography with ripr

Author: b

Custom cryptography and obfuscation are recurring patterns that we encounter during our engagements and research projects. Our experience shows that despite industry best practices and long history of failures these constructs are not getting fixed without clear demonstration of their flaws. Most of the time demonstration requires instrumenting the original software or reimplementing the algorithms from scratch. This way we can create specially crafted encrypted messages, find hash collisions etc.

Ripr  is a really exciting tool “that automatically extracts and packages snippets of machine code into a functionally identical python class backed by Unicorn-Engine”. I was really curious about how effectively this tool can be used so I decided to create a new sample that models some of the algorithms we’ve seen and write up my experiences as a reference for others.

The test program

To put ripr  to the test I grabbed the first decent looking RC4 implementation in C* and added an additional XOR step with a hardcoded 4-byte key to it. This small addition would simulate hardcoded keys, lookup tables and other constants that are commonly used in standard and non-standard algorithms alike. As we will see, resolution of these structures is not a trivial task for a static analyzer.

I compiled the code with GCC, not stripping the symbols, so I could work as if I already did the reversing work to identify the subroutines of interest. I then loaded the binary to Binary Ninja and made ripr export the key scheduler (KSA) and the keystream generator (PRGA) functions as two Python classes that I copied to a single script. As this was in the middle of a busy day I just slapped some instantiation code to it to see if the thing runs without any obvious compilation errors.

ksa=KSA() # Instanitate key scheduler
ksa.run(key,S) # initialize cipher state (S) with key
print repr(S) 
prga=PRGA() # Instantiate keystream generator
prga.run(S,plain,cipher) # Run keystream generator with the calculated state
print repr(cipher)

It did, but in order to make the code do anything useful we need to understand what was and what wasn’t generated for us by ripr.

* I didn’t verify the correctness of this implementation and even noticed some oddities (like calculation of the ciphertext size), but any mistakes would make my candidate even better for a “homebrew” algorithm.

First commit (e1569ae)

The first thing I noticed is that the generated code doesn’t handle output arguments: Arguments are just written to the memory of the emulator, but ripr doesn’t know that some of these allocations will contain important data at the end of the run of the function. This can be easily fixed by reading memory from addresses pointed to by the argAddr_N variables. In our case the key scheduler populates the S buffer, so we have to read back the memory of arg_1 of KSA.run():

-        return self.mu.reg_read(UC_X86_REG_RAX)
+        return self.mu.mem_read(argAddr_1,256)

As you can see I chose to implement more “pythonic” interface for this method, returning the object of interest instead of using an output variable. You can see similar changes in the later commits where I’m finalizing the code.

When I executed this code the KSA function executed successfully (but not necessarily correctly!) but the PRGA raised the following exception:

Traceback (most recent call last):
  File "prga.py", line 115, in <module>
    prga.run(S,plain,cipher)
  File "prga.py", line 57, in run
    self._start_unicorn(0x400733)
  File "prga.py", line 44, in _start_unicorn
    raise e
unicorn.unicorn.UcError: Invalid memory write (UC_ERR_WRITE_UNMAPPED)

 

Second commit (aaf375c)

It seems that the emulated program tries to access unmapped memory. Since the exception is caused by emulated code, the stack trace doesn’t provide information about what exactly went wrong. To debug this we need to know the instruction and the context where the emulation fails. One way to do this is to hook each instruction in Unicorn Engine but for me it was easier to extend the auto-generated exception handler code to print out context information when an unhandled exception happens:

             else:
+                print "RIP: %08X" % self.mu.reg_read(UC_X86_REG_RIP)  # 0x4007dd: mov eax, dword [rbp-0x1c]
+                print "EAX: %08X" % (self.mu.reg_read(UC_X86_REG_EAX))
                 raise e

The offending instruction can be seen as comment above. EAX pointed to memory at slightly above 0x4000 so I simply added a new mapping to the constructor of PRGA and the exception went away:

+        self.mu.mem_map(0x1000 * 4, 0x1000) # Missed mapping

After looking at the exception handlers I also tried to implement strlen() as a hook function that is meant to replace the original import call during emulation. Hooks for impoerted functions work by checking memory access exceptions against a defined list of addresses: if the saved return address points after an imported function call, the generated code handles the exception by calling the corresponding hook function. As far as I can tell return values should be manually set in the hook function (in this case setting EAX to the string length), but I also gave the function a return value for easier debugging (it turned out my original code had a pretty obvious bug, can you spot it?).

Third commit (5680b36)

So the code ran fine, but the results were different from what I got from the original binary. Two things were suspicious though:

  • My static obfuscator string (“ABCD”) was nowhere to be found in the generated code. This shows that manual reverse engineering is still crucial when using ripr.
  • My strlen() implementation was never called. Since hook functions are really easy to write, I suggest to always add some debug code (even simple prints) to them to prevent bugs like this. This is also a good way to have a high-level trace of the execution of the emulator.

With enough infromation obtained by reversing the program the first problem can be resolved easily. In this case I also had a suspicious piece of memory in the generated code that I couldn’t originally connect to anything:

self.data_0 = '00000000000000000000000000000000540a400000000000'.decode('hex')

It turns out that my obfuscator key is located at 0x400a54. This piece of memory held the pointer to it, but that region was not properly populated (although it was mapped so it didn’t cause an exception). Similarly, the import for strlen() was located at 0x4004d0 in the original binary, but not populated in the generated code by ripr. Adding these two lines to the PRGA constructor resolved these issues:

self.mu.mem_write(0x400a54L, "4142434400".decode('hex'))
self.mu.mem_write(0x4004d0L, "ff25410b2000".decode('hex'))

Note that the code written for the strlen() import is just a jump pointing to some memory unmapped in the emulator. This way an exception will be raised that can be handled by the code responsible for calling the hook function in Python.

Fourth commit (c9c7d3c)

What I failed to notice before this commit was that KSA also relied on strlen(). But since it was in a separate class using a different emulator instance my previous changes didn’t affect it. One could merge the classes, but for the sake of simplicity I chose to just duplicate the code. After this the emulated and the original program gave identical results.

Conclusion

All in all I managed to create a working emulator in about two hours, without any prior experience with ripr. Assuming proper understanding of the targeted program I expect about the same effort needed for experienced users in case of real life targets: the complexity of the task is mostly dependent on the number of unresolved data and code references, not the complexity of the algorithm itself. Considering the amount of work needed to reimplement cryptographic code, or instrumenting large software, ripr will definitely be on the top of my list of tools when the next homebrew crypto-monster appears!


Conditional DDE

Author: b

Here’s a little trick we’d like to share in the end-of-year rush:

DDE is the new black, malware authors quickly adopted the technique and so did pentesters and red teams in order to simulate the latest attacks. According to our experience trivial DDE payloads (like fully readable PowerShell scripts) slip through conventional detections, but process monitoring can cause some headache: powershell.exe launched from Office is surely an obvious indicator of something phishy.

Malware sandboxes (that execute incoming files in virtualized environments to learn more about their purpose) are an example of defensive tools that implement such detection. And although they are commonly seen as all-in-one APT stoppers, these tools are in fact quite limited in terms of simulating an actual target, that provides a broad venue for their bypass.  Evasion is generally performed by conditional checks to determine if the payload would run in the right domain, timezone, etc. If the condition is not met, the payload remains dormant so the instrumentation in the sandbox won’t catch anything suspicious.

So how do we implement this with DDE? Looking at some public obfuscation techniques it’s easy to spot the IF field code, that allows conditional parsing of other fields in the document. We can combine this with the DATE or TIME codes to construct a document with time-based execution:

{SET P {IF {TIME \@ "m"} > 13 "C:\\Winows\\System32\\calc.exe" ""}}
{DDEAUTO {REP P} "s2"}

The above DDE construct only executes calc.exe if the minutes of the hour are past 13. Suppose you send attachments that only execute code after 9:00 AM during the night – by the time someone opens the bait, the analyzer already marked it safe hours ago. Or better yet, you can rely on the resource constraints of the sandbox and make it cache/whitelist your first shot before you send the rest. These methods can be further refined with the use of fields like USERNAME or even FILENAME.

By the way, is DDE Turing-complete?


Notes on McAfee Security Scan Plus RCE (CVE-2017-3897)

Author: b

At the end of last month, McAfee published a fix for a remote code execution vulnerability in its Security Scan Plus software. Beyond Security, who we worked with for vulnerability coordination published the details of the issue and our PoC exploit on their blog. While the vulnerability itself got some attention due to its frightening simplicity, this is not the first time SSP contained similarly dangerous problems, and it’s certainly not the last. In this post, I’d like to share some additional notes about the wider context of the issue.

(more…)


Fools of Golden Gate

Author: b

In this blog post, we once again demonstrate that excessive reliance on automated tools can hide significant risks from the eyes of defense. Meanwhile, we discuss technical details of critical vulnerabilities of Oracle Golden Gate and show another disappointing example of the security industries approach to product quality.

(more…)


An update on MD5 poisoning

Author: b

Last year we published a proof-of-concept tool to demonstrate bypasses against security products that still rely on the obsolete MD5 cryptographic hash function.

Summary: The method allows bypassing malicious executable detection and whitelists by creating two executables with colliding MD5 hashes. One of the executables (“sheep”) is harmless and can even perform some useful task and is expected to be categorized as goodware by the victim. After the sheep is accepted by the victim, the colliding malicious version (“wolf”) is sent. Because affected products rely solely on the MD5 fingerprints to identify known good executables, wolf is already whitelisted and can run.

Although the reception of the research was generally positive, some were skeptical about the extent and even the validity of the issue. Although in the meantime we received information about more affected products, NDA’s prevented us from further demonstrating that the problem indeed exists and affects multiple vendors. 

Today we are able to share a demonstration of the problem affecting Panda Adaptive Defense 360. The issue is demonstrated against the stricter “Lock mode” of the product meaning that the Panda agent only allows known good executables to run (application whitelisting). For the sake of this video we manually unblock the harmless executable version (sheep4.exe) to speed up the process, as otherwise the analysis could take several hours to complete (it was confirmed that the “sheep” executables aren’t detected as malicious by the cloud scanner in case they are not manually unblocked):


(You can skip 01:00-01:55 if you are not interested in the policy update)

We notified Panda Security about this issue through their Hungarian partner (see the timeline at the end of this post). Panda responded that this is a known issue that is expected to be fixed in the next major version, but no ETA was provided. Panda stated that MD5 was used because of performance reasons. We informed Panda that the BLAKE2 hash function can provide higher level of security at better performance than MD5 (thanks to Tony Arcieri for this update!).

We’d like to stress that this research is not about individual vendors but about bad practices prevalent in the security industry. We now know of at least four vendors affected by the above problem and several others still provide MD5 fingerprints only in their tools and public reports. It is shameful that while hard work is put into phasing out SHA-1, in the security industry it is still generally accepted to use MD5, even after it was exploited in a real-world incident. We understand that there are more straightforward ways for evasion, but think that this issue is a good indicator of how security product development is often approached.

We should do better than this!

Timeline

2016.08.30: Sending technical information to vendor.
2016.09.05: Vendor requests more information, including PCOPInfo logs collected during retest.
2016.09.06: Sending demo video and identification information about product instance. Requesting more information about PCOPInfo usage.
2016.09.06: Vendor responds with instructions about PCOPInfo.
2016.09.08: Sending PCOPInfo logs to vendor.
2016.09.19: Vendor responds that this is a known issue, replacement algorithm is expected to be implemented in the next version.
2016.09.27: Requesting negotiation about issue publication date.
2016.10.12: Requesting negotiation about issue publication date. Including notification about 90-day disclosure deadline in case no agreement would be achieved.
2016.10.19: Vendor responds, internal discussion is still in progress.
2016.11.16: Requesting information about acceptance of publication date.
2016.11.28: Public release.


Bake your own EXTRABACON

Author: b

In the last couple of days we took a closer look at the supposed NSA exploit EXTRABACON,  leaked by Shadow Brokers. As an initial analysis of XORcat concluded, the code is capable of bypassing authentication of Cisco ASA devices after exploiting a memory corruption vulnerability in the SNMP service. We managed analyze and test the code in our lab and even add support for version 9.2(4) (that created quite bit of a hype :). While we don’t plan to release the upgraded code until an official patch is available for all affected versions, in this post we try to give a detailed description of the porting process: what the prerequisites are and how much effort is required to extend its capabilities.  We also hope that this summary will serve as a good resource for those who want to get started with researching Cisco ASA.

(more…)


Finding the salt with SQL inception

Author: b

Introduction

Web application penetration testing is a well researched area with proven tools and methodologies. Still, new techniques and interesting scenarios come up all the time that create new challenges even after a hundred projects.

In this case study we start with a relatively simple blind SQL injection situation and show how this issue could be exploited in a way that made remote code execution possible. The post will also serve as a reference for using Duncan, our simple framework created to facilitate blind exploitation.

(more…)


Poisonous MD5 – Wolves Among the Sheep

Author: b

MD5 is known to be broken for more than a decade now. Practical attacks have been shown since 2006, and public collision generator tools are also available since that time. The dangers of the developed collision attacks were demonstrated by academia and white-hat hackers too, but in case of the Flame malware we’ve also seen malicious parties exploiting the weaknesses in the wild.

And while most have already moved away from MD5, there is still a notable group that heavily uses this obsolete algorithm: security vendors. It seems that MD5 became the de-facto standard of fingerprinting malware samples and the industry doesn’t seem to be willing to move away from this practice. Our friend Zoltán Balázs collected a surprisingly long list of security vendors using MD5, including the biggest names of the field.

The list includes for example Kaspersky, the discoverer of Flame who just recently reminded us that MD5 is dead, but just a few weeks earlier released a report including  MD5 fingerprints only – ironically even the malware they analysed uses SHA-1 internally…

And in case you think that MD5 “good enough” for malware identification let’s take another example. The following picture shows the management console of a FireEye MAS – take a good look at the MD5 hases, the time delays and the status indicators:

fireeye_duplicateDownload sample files

As you can see, binaries submitted for analysis are identified by their MD5 sums and no sandboxed execution is recorded if there is a duplicate (thus the shorter time delay). This means that if I can create two files with the same MD5 sum – one that behaves in a malicious way while the other doesn’t – I can “poison” the database of the product so that it won’t even try to analyze the malicious sample!

After reading the post of Nat McHugh about creating colliding binaries I decided to create a proof-of-concept for this “attack”. Although Nat demonstrated the issue with ELF binaries, the concept is basically the same with Windows (PE) binaries that security products mostly target. The original example works by diverting the program execution flow based on the comparison of two string constants. The collision is achieved by adjusting these constants so that they match in one case, but not in the other.

My goal was to create two binaries with the same MD5 hash; one that executes arbitrary shellcode (wolf) and another that does something completely different (sheep). My implementation is based on the earlier work of Peter Selinger (the PHP script by Nat turned out to be unreliable across platforms…), with some useful additions:

  • A general template for shellcode hiding and execution;
  • RC4 encryption of the shellcode so that the real payload only appears in the memory of the wolf but not on the disk or in the memory of the sheep;
  • Simplified toolchain for Windows, making use of Marc Stevens fastcoll (Peter used a much slower attack, fastcoll reduces collision generation from hours to minutes);

The approach may work with traditional AV software too as many of these also use fingerprinting (not necessarily MD5) to avoid wasting resources on scanning the same files over and over (although the RC4 encryption results in VT 0/57 anyway…). It would be also interesting to see if “threat intelligence” feeds or reputation databases can be poisoned this way.

The code is available on GitHub. Please use it to test the security solutions in your reach and persuade vendors to implement up-to-date algorithms before compiling their next marketing APT report!

For the affected vendors: Stop using MD5 now! Even if you need MD5 as a common denominator, include stronger hashes in your reports, and don’t rely solely on MD5 for fingerprinting!


Testing Oracle Forms

Author: b

SANS Institute accepted my GWAPT Gold Paper about testing Oracle Forms applications, the paper is now published in the Reading Room.

Forms is a typical example of proprietary technology that back in the day might have looked a good idea from business perspective but years later causes serious headaches on both the operational and security sides:

  • Forms uses naively implemented crypto with (effectively) 32-bit RC4
  • The key exchange is trivial to attack to achieve full key recovery
  • Bit-flipping is possible since no integrity checking is implemented
  • Database password set at server side is sent to all clients (you read that correctly)

And in case you’re wondering: applications based on Oracle Forms are still in use, thanks to vendor lock-in…

The full Gold Paper can be downloaded from the website of SANS Institute:

Automated Security Testing of Oracle Forms Applications

The accompanying code is available on GitHub.