omg.wtf.bbq.

because arshan’s too cheap to license OneNote

Browsing Posts published by arshan dabirsiaghi

I haven’t blogged or released much research in the last two years. If you care about that, which I doubt you do, then I’m sorry.

I’ve been putting all of my energy into Contrast, a completely new way of finding vulnerabilities in applications.

Contrast uses instrumentation to add “sensors” to your running JVM, including in the JRE, server and your custom code at runtime. A rules engine then detects when vulnerable combinations of those sensors occur. When they do, the “trace” of events is transmitted back to the Contrast site for you to see.

Using this sensor-driven approach, Contrast has all the high-level capabilities present in existing security software:

  • Data flow (source-to-sink stuff like SQL injection, Cross-Site Scripting, etc.)
  • Control flow (lack of authentication, access control, etc.)
  • Configuration checks (lack of HttpOnly, verb tampering vulnerabilities, etc.)
  • Runtime checks (use of MD4 or DES, detected at runtime)

Our rules are specified by a simple domain-specific language that allows you to mix and match the above check types into a single rule.

I’m super proud of the work we’ve done. We’re planning on being perhaps naively open about how Contrast works and our rules. We hope to foster a community that works together to make sure everyone is getting the best security coverage. We’re not kidding when we say Contrast installs in a few minutes (add one line to your server startup script), and doesn’t require any security skill (just browse around your app). Vulnerabilities start popping up, and dashboards and trending reports start to churn.

The NewRelic and AppDynamics companies have been extremely successful using a similar model for measuring performance. I’m not talking about financial success, either. I’m talking about their ability to deliver developers actionable data to meet their goals. Contrast aims to be dead simple, unparalleled in accuracy, and continuously available.

Everything else, to me, is on the wrong side of history.

We’ve released another version of AntiSamy into Maven and on the main downloads page. In terms of the actual code changes, there are just a few things – it’s more of a directional change for our engine. Here’s the changelist:

  • fixed error message not sanitizing CDATA payloads when encountered (should only concern you if you use error messages + exactly version 1.4.3)
  • tags that are allowed to be empty are no longer hardcoded and can be set in the policy file (<allowed-empty-tags>), with a safe default list if none are provided
  • continued to try to make SAX and DOM version semantically if not literally identical output
  • added test cases to regression
  • fixed Julian Cohen’s privately reported stack exhaustion bug by applying a tree depth check (the max depth of a DOM tree is now 250)
  • no longer Java 1.4 compatible

The biggest move of this release is to officially change the default parser/serializer from the DOM engine to the SAX engine. We’ve had two engines for the past few versions, but maintaining two engines concurrently is kinda crazy. The SAX version is twice as fast and much better on memory. Even though all of our test cases pass for both engines, I still anticipate some growing pains in the SAX version, which is why I think most critical applications should stick to 1.4.3 for now.

I strongly believe that DOM-based validation is still the most safe approach because it’s a more organized, thought-to-code translation. SAX forces you to maintain some state which can be very error-prone in this problem space. But, some customers have stringent performance requirements which may preclude the use of an API that builds huge trees and throws them away quite rapidly, even if it’s only on a few code paths.

Anyway, there’s a place for both in the world, so we’ll keep the DOM engine around. You can continue to invoke it by calling AntiSamy like this:

AntiSamy as = new AntiSamy();
as.scan(badInput, policy, AntiSamy.DOM);

In the meantime, I’m inviting all you terrible sla.ckers to beat the crap out of the new smoketest: http://www.antisamysmoketest.com/. Don’t be gentle.

What do you do when you have an arbitrary file upload to a web-accessible directory in J2EE? Obviously, you need a JSP shell! But there’s one problem: the available ones are kind of terrible. The Metasploit reverse shell is only intended to serve as placeholder for an already-owned box. The world needs a JSP shell that really helps a blackbox attacker pivot to important assets, so I took a stab at it. It’s called quite lamely called pwnshell.

What is it?
A single JSP file, embedded with jQuery and everything else you need to make an awesome web shell.

How do you use it?
1. Upload it to the victim server (try it on a local Tomcat server!)
2. Browse to it
3. Pretend you’re on looking at xterm

Where does it work?
- Works across platform
- Works on Java 1.5+ (probably 1.4 too, but I haven’t tested)

Why would you use it?
- Browse around the system (as the web application system user)
- Execute arbitrary system commands (it’s a shell, after all)
- Show and alter session variables
- Dump JNDI entries

Here’s a video:

Finally, some screenshots of the shell in action. The first one shows simple directory browsing. Notice all those directory links are clickable! This makes for a weird Explorer-like interface.

pwnshell - showing ls output

The next screenshot shows the help screen (type ‘help’) and the execution of a system command, ‘netstat’:

The last screenshot shows the shell’s autocomplete functionality.

If you can think of anything cool to add, let me know. Download here!

We released AntiSamy 1.4.2 a few days ago. This is a minor release with a lot of housecleaning behind it. The main purpose for the release was to address a vulnerability in the DOM engine discovered by Michael Kirchner, Barbara Schachner and Jan Wolff. The bypass is hilariously simple and incredibly frustrating:

<![CDATA[]><script>alert(1)</script>]]>

The new SAX parser in AntiSamy was not vulnerable. But wait a minute, isn’t CDATA supposed to be inert? From Wikipedia:

In an XML document or external parsed entity, a CDATA section is a section of element content that is marked for the parser to interpret as only character data, not markup.

Yet, if you execute the above HTML in IE8 or Chrome 5, the JavaScript fires. The browsers have left defenders no choice but to encode the contents of CDATA blocks, which utterly defeats the point of CDATA. I am a little afraid this will break some machine-generated XHTML, but 99% of users should experience zero side effects from this patch.

UPDATE: @Lever_One also points out that an invalid start sequence for CDATA was being honored in my library: <!CDATA[.

Here’s the changelist:

  • Fixed a bug that caused some low range characters to go unencoded during serializiation (no bypass, but still a bug)
  • Added the ability to nest policy files (policy A can include another policy file B)
  • Some performance enhancements
  • Added missing error messages in the SAX engine

There’s also some notable housekeeping for our users:

  • This our last Java 1.4 release. Our next release will be Java 1.5 compliant, and probably will be for a few years.
  • This is the last release where the DOM engine will be the default parsing engine. SAX is much faster and better on memory.
  • AntiSamy has been moved into the Maven central repository, starting with this release (group ID = org.owasp.antisamy, parent group = org.owasp).

Big thanks to Jason Li for his continued assistance on the project and August Detlefsen for his help tracing down some bugs. Biggest props go to Chris Schmidt for refactoring the project in SVN and getting AntiSamy into Maven Central.

All the binaries, source, JavaDocs, POM, etc. have been pushed to the Google Code downloads page. If you want to check signatures, you can download them directly from Maven Central.

As always, feedback is greatly appreciated.

In the past few weeks I used JavaSnoop RC6 to assess a privileged applet application that had it’s own secure message protocol on top of mutually-authenticated HTTPS. Kind of a tough nut to crack, even with JavaSnoop. This assessment exposed a number of performance issues, bugs, and necessary features that were just plain missing.

After probably 100 hours of development and testing, I’m releasing the final JavaSnoop 1.0! On top of everything already available in RC6, there’s a few new cool things:

After 6 release candidates, roughly a thousand bugs fixed, dozens of improvements and features added, I finally think the tool is ready for general availability. It’s had over a thousand downloads, which is much higher than I would have thought after a few months; it’s kind of a niche tool in a niche space. People are using it for things I didn’t anticipate, though – things like malware analysis and game hacking. More important than that, it’s unquestionably the best tool for hacking Java business applications.

No more betas or release candidates. Thanks to the following folks for bug reports, feedback, discussions and inspiration:

  • Hubert Seiwert, NGS
  • Marcin Wielgoszewski, GDS
  • @planetlevel, @_fishman_, @cykyc, Mike Fauzy, Dave Wichers, all from @aspectsecurity
  • Stephen de Vries, Corsaire
To download, visit the Google Code project page.

If you want to know what the hell JavaSnoop is, my BlackHat talk is online:

Happy hacking.

In my likely impossible challenge to ever understand one of Nico Waisman’s talks, I found corelanc0d3r’s site. Wow. Awesome tutorials on everything from direct EIP overwrites to ROP.

His first challenge is to exploit EasyRMtoMP3, some silly little utility that has a known stack buffer overflow when reading lines from .m3u files. His tutorial shows how to exploit it in Windows XP SP3, without ASLR and DEP and all that stuff in the way. I’ll document here the challenges I had to overcome in exploit this reliably in Vista SP2. I won’t rehash the vulnerability itself (he did a great job), but rather list the differences you need to make it work on a more current Windows OS for anyone who finds themselves following his tutorials like I did. In case you’re looking for new techniques, get ready for disappointment: there is absolutely nothing new or novel about any of this.

Step 1: Finding offsets from the start of the overflowed buffer to the saved EIP. Nothing different needs to be done here – the same Metasploit pattern-finding technique works on Vista. However, the output is different. My offset value is 26073 (base10).

Step 2a: Find a way to get to our shellcode. The same calc.exe shellcode is on the stack, but we can’t overwrite EIP with its address because it’s address is 0x000FF65C, emphasis on the 00. This is an unbounded string copy vulnerability, so we can’t have any NULLs in our payload. Without ASLR, this should still be easy. Our shellcode very conveniently lives right at ESP, so all we have to do is find a JMP ESP instruction anywhere in any of the application’s DLL’s, just like Peter did in his tutorial. I anticipated that I wouldn’t have a problem with ASLR because there is no way this little utility’s author would have known to link the executables or DLL’s with the /dynamicbase flag, which is how you enable ASLR. I was right in my expectation about the author, but wrong in my expectation that I wouldn’t still be affected.

Running the program 3 times shows 3 different addresses for the MSRMCc_1 module, despite the fact that it’s not ASLR aware:

001D0000 MSRMCc_1 C:\Program Files\Easy RM to MP3 Converter\MSRMCcodec01.dll
003D0000 MSRMCc_1 C:\Program Files\Easy RM to MP3 Converter\MSRMCcodec01.dll
001C0000 MSRMCc_1 C:\Program Files\Easy RM to MP3 Converter\MSRMCcodec01.dll

As I’m sure people smarter than me already know, this was because of DLL fixup/rebasing. All executable modules have a “preferred” address to live, but when there’s a collision with another existing module they can generally be adjusted (slightly). Because Windows has a ton of DLL’s involved in every process, and they’re randomly placed due to ASLR, there’s a decent chance application DLL’s will generate conflicts and therefore must be “fixed up” to nearby addresses.

So – are we forced to have an unreliable exploit? Nope! Turns out 1 of the application DLL’s can’t be rebased, and therefore must live at it’s preferred address. The output from the pvefinaddr plugin for Immunity Debugger shows us how we discovered that (click to see whole picture):

EasyRMtoMP3 modules

The output of "pvefindaddr modules" shows the modules of our target

This is awesome. We now have a target: MSRMfilter03.dll. Now we just need to find our JMP ESP.

Step 2b: Getting redirection to ESP. So now that we have our target DLL, the next step is to find the location inside the DLL of a JMP ESP. The simple way to do that is to search for the bytes of the instruction in the DLL using OllyDbg/ImmDbg’s Search for->Binary string. You have to know what bytes to search for, though, and the easiest way to figure that out is to replace some random code in the DLL with the assembled instruction for JMP ESP and then look at its contents. If you did that, you’d know the value we’re looking for is the byte sequence FF E4. Surprisingly, this DLL does not contain this byte sequence anywhere (even when looked at totally unaligned).

So, we improvise. For this exploit to work, at the end of the day, you just need some instructions that redirect the user to the address stored in ESP. Another set of instructions that would do that is PUSH ESP; RET. The PUSH ESP will copy the address of our shellcode (ESP) onto the top of the stack. Then, our RET instruction simply pops that address off of the top of the stack and transfers control to it. This byte sequence, 54 C3, is found many times in this DLL, and we pick one of the locations that doesn’t have a NULL in it: 0x1001B058. This technique and many others for figuring out “how the hell do I get to shellcode?” are talked about later in corelanc0d3r’s tutorial series.

Step 3: Fix our shellcode problem. So now we know where our shellcode lives and how we’re going to redirect to it. But, to my chagrin, the exploit still fails. The problem turned out to be some undocumented requirement by Metasploit’s calc.exe shellcode. In his exploit for this issue, the tutorial author used a NOP sled but never indicated why. Everything in our exploit is precise; there is no guessing involved so there should be no need for NOP sleds.  As was pointed out on his forum, this is because the shellcode executes the following instruction near the beginning:

FSTENV SS:[ESP-0xC]

This “FSTENV” instruction saves 28 bytes worth of state at ESP-0xC. Unfortunately, that 28 bytes ends up overlapping with our shellcode, and overwrites 3 bytes of it that we haven’t executed yet. The tutorial author probably just used a NOP sled from the beginning to give himself a little wiggle room and never again looked at why it was used or needed, so he never saw this problem. So, to make sure the shellcode doesn’t partially overwrite itself we need to introduce a 3 byte NOP sled. Our final payload now looks like this:

Stack before: [buff][vars][saved ebp][      saved eip      ][ param data..............................]
Stack smash: [AAAAAA.......................][addr of push, ret][4 bytes junk][3nops][shellcode]
 
Here’s the exploit. Should work on any Vista SP, but I’m not sure about 7 or XP. A cool extension to this exploit would be to do the following:
  • Fix the shellcode’s to not crash after calc.exe executes (crashes after calc pops right now)
  • Repair the application stack and return the vuln function (as if a normal m3u was encountered)
  • Overwrite the malicious .m3u file to contain the same text (to destroy the evidence of the exploit)

Here’s my (possibly distorted) recollection of Immunity’s Hack Cup 2010, complete with terrible security puns. Thanks to my teammates on SensePost/#TeamZA for winning! And thanks to Nico Waisman specifically for organizing and Immunity for sponsoring a great event. And yes – all of this is a joke – as in, not meant to be taken seriously, as in plz don’t hack my computer.

Group Stage (or, who cares?)

CLGT was our first opponent, and they had foreigners from all over. I’m sure with vim + Metasploit and a North Korean relay owned by PHF they’re as dangerous as Glenn Beck’s investment advice, but on the 30ft by 30ft indoor soccer field they posed no threat to the new paradigm of South African/Arshanican synergistic collaboration of competitive footballing excellence. #TeamZA wins 6-2.

Immunity was next, complete with Argentinians, so I gave them some respect. Probably too much respect, it seems, since they beat us in a squeaker in the group stage. They had one good player who had excellent dribbling skills, and I’m afraid I found his jersey in my fist more than once. The notable Mr. Aitel scored against us. We let him score because his Beckham-ish looking kid was watching and we felt bad. You’re welcome, Dave. #TeamZA wins by -1 goal.

Playoffs

Media Whores actually practiced the day before Blackhat. They were banking on preparation. It must have gone very well, because Nathan Hamiel was bragging to me about how he kicked the ball and it got stuck on the moon or some shit. Maybe the MediaWhores should get there 1 month before the next Blackhat for more intense preparation.

We murdered them like a zillion to nothing. I think I scored 6 goals. After one of my last goals, one of their players, (maybe Mr. Naraine?) gave me a look like, “Jesus, man. What are you?Answer: a temporary South African. 0xcharlie and Dion looked like they had some touch, but we were too physical, and frankly, too good-looking. #TeamZA wins 8-2.

Goal++ was unlucky enough to draw us in the semi-finals. They are built up of Sir David “OWASP” Campbell and guys from Intrepidus Group, who are supposedly experts in the mobile field. If that was true, why didn’t they use their mobile skills to call an ambulance halfway into this legendary beatdown? They were physical and fast but lacked the touch to string enough passes together to break down our vaunted defense, led by Dominic “Crazy Legs” White. His lower tentacles consistently reached the ball of his opponents like Paul the Octopus, except with more statistical unlikeliness.

They scored a few goals off of some defensive mistakes (made on purpose because only Allah is perfect). Mr. Campbell tried to pull some crazy Denver FROC shit by repeatedly punching me when the ref wasn’t around. Thankfully, Marco Slaviero pulled his male organ out of Intrepidus’s memcached server just long enough to hit a crazy (left-footed?) banger to the upper 90, completing the psychological domination of these men – these men that were so athletic you might mistake them for brothers. #TeamZA triumphs spiritually, financially and hyperbole with a 5-2 win.

The Finals

The two best teams clearly reached the finals. The Cosmic Kites beat down Immunity in the semi-finals like sirdarckcat and thornmaker beat down the IE8 XSS filter. They also featured a number of Argentinians who were unknown to me. On the other hand, practically everyone here is unknown to me, except the visually distinct Grugq, who was there clearly backing the right horse in #TeamZA.

With many fans of Hack Cup who had traveled over 1 mile to watch the tournament looking on, a battle of epic consequence took place. We were all really tired, and the Cosmic Kites were living up their name flying around the field like LeBron James on HGH and Lance Armstrong’s bike. Even Jurgens van der Merve (gesundheit), our goalie, had put in a hard day’s work pwning CEH-certified types who were silly enough to enter his goal box. He was more Tim Howard than Robert Green.

The game flowed back and forth for a few minutes, until I scored a goal I can’t remember. Then, Cosmic Kites answered with swarming defense and the threat of infecting us with Argentinian herpes, which is worse than avian flu.

I think I scored again, and to my recollection it was a header, which is not very common in indoor soccer (or for me at all) – it must have been a real mess inside the goal box. But, our lungs were tired from all vuvuzelaing and scripted goal celebrations – and Cosmic Kites answered yet again.

The game seemed prime for overtime – except for the work of the extremely coachable Charl van der Walt. As we went through the tournament, I kept telling him to slide the ball to the center and slightly behind from his wing position, where he was consistently an APT, so that I could have an easy finish. In the last 0:04 of the game Charl got the ball and took it up the wing – where to my amazement he slid the ball perfectly to my unmarked right foot in the center for an easy finish! We celebrated as the clock wound down to zero.

To the victor then went the spoils:

Dominic, Juergen, Arshan (me), Marco, Charl

Dominic, Juergen, Arshan (me), Marco, Charl. Yes, we won even though Dominic was wearing that.

I’m trying to expand my skillset to the point where I can understand one of Nico Waisman’s BlackHat talks, and that means I have work to do (and maybe a brain transplant too). I’ve always had decent assembler skills, I can write simple shellcode, beat Gera’s challenges, but Windows has never been my domain. Let alone bypassing any of the more advanced memory protection techniques (DEP, ASLR, /GS, etc.).

So recently I started doing simple reversing/key generation cracking challenges  for  getting used to the world of Windows, Immunity Debugger, and memory corruption. First of all, Immunity Debugger is awesome. It’s basically a skinned OllyDbg with Python integration and other cool extensions. I plan on writing visualization scripts to make the mess of hexadecimal a little easier to parse.

Ok, so the first one I did was keygenme3, which was a keygen challenge. The easiest way to break a keygen challenge is to replace the instructions that check the keygen with a NOP sled. The problem with that simple approach is that the author cleverly used WriteProcessMemory() to re-fill the area with code to break that simple patch. So in the end, you just had to NOP sled the WriteProcessMemory() call, too. Easy in theory, but you had to reverse enough of the program to understand what was happening, and that wasn’t easy for me.

The next challenge was LaFarge #2 keygen challenge. This one was also unique, and a good learning experience. The point of these keygens is not to just get a valid key. That’s easy, just find the code that checks the validity of the key, set a breakpoint, and inspect the “valid” value it’s looking for.

Creating a keygen program that spits out a valid key for any input is a little more work, and is part of the “solution”. The LaFarge#2 application uses a custom XOR-algorithm that would take hours to reverse into another language, which is what I tried to do first. Instead, to create a keygen, I took the existing program, and changed it to spit out the valid key it expects rather than an error message when you input an incorrect key.

Here’s the code block that checks the key:

The top instruction shows the stack address of the expected, valid key

Figure 1: The stack address of the expected key used sent to strcmpA(), and the stack address of the message originally used in the MessageBoxA() call.

The figure highlights an instruction at the top which shows the stack address of the expected, valid key, which was computed based on the user name provided. The second highlighted instruction shows which string (0x004062E7) is used in the MessageBoxA() call to tell the user their key was invalid. An easy way to turn this program into a key generator rather than a key checker is to switch the stack address pushed onto stack in the second instruction to be the first stack address. That way, the user will be shown the expected key instead of the error message. Here we can see we’ve reassembled the code for the second instruction to do just that:

The MessageBoxA() parameters have been tampered with to send the valid, expected key to the MessageBoxA() call.

Figure 2: The MessageBoxA() parameters have been tampered with to send the valid, expected key to the MessageBoxA() call.

Now, we run the program after changing that 1 instruction, and it works as we imagined:

We've re-written the program to spit out the key rather than an error message.

Figure 3: We've re-written the program to spit out the key rather than an error message.

Next project: a Python script to visualize stack frames.

I’m flying back from Blackhat today where I presented and officially released JavaSnoop, a tool that makes security testing thick Java clients really, really easy. We use some magically awesome instrumentation and bytecode engineering. Despite the fact that those buzzwords were in play, Blackhat thought they’d hedge their bet on me by putting the talk in the room furthest away from everything. But don’t worry, we filled it up anyway. And I’m sure that wasn’t because I launched a Twitter misinformation campaign that suggested Dino Dai Zovi would be there dropping 0day – I’m sure it was just because of the suggestive title.

There was an A/V issue that meant I couldn’t see the demo but the audience could, so they had to guide me through it. Other people may look at that as an utter disaster, but from my perspective, I gave the first audience participation demo in Blackhat history (don’t research that).

Here are the slides, the tool itself, and the project home page – complete with videos and screenshots to help you get started. If you do anything cool with JavaSnoop, let me know and I’ll make a video of it, give you credit and put it on the project page to help everyone get to know the tool.

If you’re interested in the magic behind JavaSnoop, check out our SVN. We welcome feedback, patches, success stories, or belittlement. It’s GPLv3, but we’re happy to re-license a copy to you if you have a half of a good reason.

Happy hacking!

You may be thinking, “what the hell happened to 1.4?”  A few things. First, I had a baby. That was really hard.

Then, we were trying to manage all the logistics of moving to a new project structure during our 1.4 release cycle and during that time we added some really important stuff. So, AntiSamy 1.4.1 is out today! New features from 1.4 and 1.4.1:

  • Full Maven support. We’re hosted in the Sonatype OSS repository! Here’s an example dependency to put into your pom for including AntiSamy in your project.
  • Added an experimental SAX version of AntiSamy. This is so huge. It’s an optional alternative method of cleaning the user’s input. It’s way faster (50%) and consumes far less memory. It’s still considered experimental even though all our test cases pass against it because it’s not time or community tested yet. Anybody looking to test can browse over to the test page to provide feedback. It’s practically no different to invoke: instead of AntiSamy.scan(String,*), it’s AntiSamy.scan(String,*,AntiSamy.SAX). Default is still to use DOM-based scanning, our old tried-and-true method. One day, hopefully we’ll default to SAX.
  • Proper support for name/value attributes in <param> tags (see the validateParamAsEmbed directive and Erik’s explanation of the problem it solves)
  • Added noFollowAnchors directive which programmatically adds rel='nofollow' to all links parsed by AntiSamy
  • Added safe support for comments (we’re trying to allow normal comments and prevent IE’s conditional comments)

There were also a number of bug fixes, code improvements and cleanups. This release was not possible without hard work by the following folks:

  • Jonathan Irving, who is a good engineer, project manager, and is way helpful and patient with my well-established personality shortcomings.
  • Erik Innocent, a real-life AntiSamy pioneer who is making sure its real-world capability stays in line with its promise.
  • Fernando Padilla, our resident Maven guru (and good guy).
  • Finally, Lars Trieloff, who submitted a SAX patch that became the template for our SAX scanning option (congrats on the newborn, too!).

If you’re looking for work for your summer intern, we could really use better documentation for AntiSamy, inside and outside of the code. Thanks to everyone involved for making this release our best ever. AntiSamy is now faster, more easily integrated into a project, and hopefully still as safe as ever.

See you after the World Cup!