You are here: Home Blog BreakingPoint Labs Blog

Constantly Hacking Ruby Constants

Here at BreakingPoint, we write all of our application simulation code in Ruby. Lately, I've been working on adding a slew of new behaviors to our IMAPv4 implementation so users can fine-tune their IMAP Application Simulator and Client Simulator flows. At first, this seemed like it would mean a whole lot of typing to wire up twelve new actions.

Instead of copying and pasting all over the place (and dreading the possibility of fixing the same bug in fifteen zillion places), I needed to come up with a code reuse technique that takes advantage of the existing codebase written using standardized naming conventions. Since I'm swimming in these standard names, I figured there must be a way to use Ruby's dynamic typing and extensible classes to make this easier on myself, both now and in the future.

The first trick is to programmatically figure out which application profile class to use when I'm in a particular protocol. For example, if we're in a function in the "Imap" object, I need to get protocol configuration from the "ImapProfile" singleton object. This is pretty easy with Ruby's introspection and the nifty Kernel.const_get() function.

So, let's say we have a (simplified) ImapProfile class:

class ImapProfile
 def self.config
	{:username => "todb",
	 :password => "Shadowfax" # Unguessable! 
	}
 end
end

In the Imap subclass of Application Manager, I'll want to get a hold of those configuration parameters. I can do so with something like this:

module AppManager
 class Imap

  # Get my class name, strip off the superclass
  def my_protocol
  self.class.name.to_s.split("::").last
  end

  # get_profile_params() takes the string from 
my_profile_object(), # gets the associated constant, and invokes
the config() method. def get_profile_params Kernel.const_get(my_protocol + "Profile").send :config end end end

Now we can call the profile object's "config" method by deriving the class name from our own class's name:

irb(main):001:0> @app = AppManager::Imap.new
=> #
irb(main):002:0> @app.get_profile_params
=> {:username="todb", :password=>"Shadowfax"}

That's pretty neat and all, but the real trick is to figure out how to do the same thing with a method name, since (as you'll see) they bear a resembelence to individual action classes. After a little bit of research, it turns out we can perform something similar with the Kernel.caller() function, and again use some string manipulation to get what we want:

def caller_action_to_constant
	caller[1] =~ /`([^']+?)'/
	$1 =~ /^do_(client|server)_(.*)/
	$2.split("_").map {|s| s.capitalize}.join
end

This function takes the second element of the execution stack, extracts the calling method's name (the first regex), extracts the part we care about (the second regex), then splits on the underscores in order to CamelCase the result. In the end, the string:

"do_client_send_user_name"

becomes 

SendUserName

Why not the first element of the call stack array? Well, I'm wrapping this up in an intermediary function, called the action_executor, which takes this string and performs another const_get to actually use it for something:

def action_executor(args={})
 Kernel.const_get
(my_protocol + caller_action_to_constant + "Cmd").send :data end

So, from now on, the do_ actions can call the action_executor in order to track down the right classes to get the data from:

def do_client_send_user_name(args={})
	action_executor(args)
end

Pretty neat, if you ask me. A complete code listing should be available here, at Pastie.

In the end, this strikes me as an implementation of the OO Delegation design pattern. However, it includes some extra smarts about where the delegatee is, all based on a common naming convention for classes and methods. While the example code is sparse, in reality, the application actions I'm replacing in IMAP were each around 15 lines, and this technique compresses them down to one. I also get the added bonus of centralizing a common function to one spot, to ease future tweaks to the way application protocols work, or, the laughably remote possibility that there's ever a bug discovered there.

Posted by Tod Beardsley (2009/06/23)
0 comments | Tags: Ruby //

Protocol Realism: OSCAR File Transfer

The last Protocol Realism article we published here on the BreakingPoint Labs Blog was about AIM, and how it's possible to fingerprint AIMv6 over TLS by observing packet lengths. The latest Application Protocol & Strike Pack now supports simulating AIMv6 file transfers with the AIM6-Rendezvous Application Simulator component.

AIM file transfers are interesting for a couple reasons. First off, for a 'proprietary protocol,' the OFT protocol (OSCAR File Transfer) is surprisingly well-documented. This is due, in no small part, to the efforts of Jonathan Clark and his paper, On Sending Files via OSCAR. Although the paper is now a couple years old, OFT has remained essentially unchanged. If you're interested in the nitty-gritty of OFT, I can't recommend Clark's paper enough.

OFT Privacy

One aspect that struck me, though, is that if you're using the AOL-provided client (AIM version 6.8.14.6 for Windows), your file transfers are proxied through AOL's servers on port 443, just like your usual chat channels. However, unlike regular chat, these file transfers are not encrypted. This is great for IPS folks who like to watch file transfers for worm and trojan content, but maybe not so much for people who have been assuming that their port 443 file transfers have been enjoying the benefits of TLS encryption.

Note that third-party clients, such as Pidgin, have a configuration setting to prefer direct IP connections over AIM's proxies, which causes file transfers to be negotiated directly between peers over random ports. However, this also exposes that peer's IP address to other peers. This is not usually that big of a deal, but sometimes people get touchy about that sort of thing. The moral of the story here is, there can be no assumption of privacy when using OSCAR file transfers.

The OFT Checksum

While Clark's paper made implementing our Application Simulator component relatively easy, his paper defers detailing the checksum algorithm used to other, existing implementations -- specifically, Joscar's mJava-based and Gaim's (now Pidgin's) C-based implementations. Existing, open source implementations are great references for writing Application Simulator components, so all I had to do was reimplement it in Ruby.

The checksum algorithm itself has been described variously as "nonintuitive" (Clark) and "the weirdest I've ever seen" (Gaim). Since Ruby code is generally pretty readable, I've included an implementation below, so you can decide if you've seen any weirder.

# OFT Checksum calculator. 
def calc_checksum(buffer='',prev_checksum=0xffff,odd_start=false)
  checksum = (prev_checksum >> 16) & 0xffff
  buffer.split(//).each_with_index do |x,i|
    old_checksum = checksum
    # Even bytes are high, odd are low, unless the last chunk ended up starting
    # this chunk on an odd byte, in which case the reverse is true. Note that
    # the first chunk (and often the only chunk) is always starting on 0, thus,
    # even. This is the typical use case. Implementations should set the 
    # odd_start flag and the prev_checksum value if this is the case.
    if odd_start
      value = (!(i % 2).zero? ? x[0] << 8 : x[0])
    else
      value = ((i % 2).zero? ? x[0] << 8 : x[0]) # usually this one.
    end	
    checksum -= value
    checksum -= 1 if checksum > old_checksum 
  end
  2.times {checksum = (checksum & 0x0000ffff) + (checksum >> 16) }
  checksum << 16
end

Granted, this (sometimes backwards) high byte/low byte business is not as straight forward as the standard Internet checksum, nor nearly as useful as a proper cryptographic hash. I can't know why AOL felt the need to reinvent the wheel with this, but my suspicion is that it was introduced purely to irritate third-party OSCAR implementations. Since that didn't work, AOL has no doubt learned that there is no stopping the efforts of dedicated protocol reverse engineers.

Posted by Tod Beardsley (2009/04/10 10:30:00 GMT+0)

Protocol Realism: AOL Instant Messenger and TLS

The latest Application Protocol & Strike Pack includes support for AOL Instant Messenger, version 6. AIMv6 (as opposed to AIMv4 and earlier) has built-in support for conducting most of its business over an encrypted channel on port 443, and this encrypted communication is on by default. If that sounds like TLS/SSLv3 to you, you'd be right -- up to a point. There is an area where the encrypted AIM traffic (in its default configuration on Windows) diverges rather starkly from your usual TLS traffic, and I'd like to highlight that today to illustrate the value in realistic protocol implementation.

Cryptographic Traffic Analysis

While researching the post-authentication sequence for AIM, I noticed that certain message lengths and message sequences kept popping up during particular phases of the protocol. For example, message lengths of 32 bytes seem to be common from the client to the server during the post-authentication sequence of setting a user's initial status, retrieving buddy list information, and filling in the online/offline properties of buddies. In fact, the initial post-authentication sequence is quite static, from the message length and message sequence standpoint. It looks something like this for the first dozen application data packets:

---- Channel Setup ----

AIM Client (C) ---- Hello -------------------> AIM Server (S)
(C) <----------- Hello, Change Cipher Spec, Handshake --- (S)
(C) --------------- Change Cipher Spec, Handshake ------> (S)

---- Application Data ----

(C) <----- AppData:26 ------- (S)
(C) ------ AppData:457 -----> (S)
(C) <----- AppData:62 ------- (S)
(C) ------ AppData:76 ------> (S)
(C) <----- AppData:92,46 ---- (S) * Two messages, one packet
(C) ------ AppData:32 ------> (S)
(C) <----- AppData:1477 ----- (S) * Split across two packets
(C) ------ AppData:42 ------> (S)
(C) ------ AppData:660,22,38,38,32,38,32,32 ----> (S) * First field varies
(C) <----- AppData:254,62,50,48,44 ----- (S) * First field varies
(C) ------ AppData:258 -----> (S)

It goes on from here and gets more varied the further in we get to the post-authentication sequence. More importantly, it does happen every time an AIMv6 user logs in, and this is distinct from "normal" TLS in some important ways.

First, the usual use of TLS over port 443 is for secure web browsing. These sessions tend to have a client request of between five hundred and a thousand bytes, followed by a slew of server responses with sizes all over the place, varying wildly by site and page the user happens to be requesting. Because we see here some relatively small message lengths, and a more even client, server, client, server request and response pattern, it's clear that this is more interactive than your typical web browsing.

Secondly, the stacked Application Data messages are pretty unusual. Most client/server TLS implementations will dedicate each message to a TCP packet, and won't normally concatenate small messages into larger (and more bandwidth efficient) packets. When I first captured some AIM traffic to look at, this jumped out immediately and I needed to double-check that this wasn't a transmission or capture error, since I've never seen it before in normal traffic.

So, who cares?

People who are into DPI, that's who. Let's say you wanted to build a device that, among its many wonderful inspection capabilities, should be able to pick out AIMv6 traffic from other encrypted traffic for the purpose of rate limiting or ensuring QoS or whatever. Well, without the above insight, that task may be an expensive proposition -- a DPI device would have to monitor connections to first find the AOL keyserver certificate, then deduce from that connection where the communications channel is going to show up (either through guesswork or some clever man-in-the-middle SSL proxy shenanigans). Alternatively, they could keep tabs on the IP addresses AOL uses for their AIM switchboard servers, and just go by those addresses to pick out the interesting from the uninteresting encrypted data...but they risk false positives/false negatives any time AOL removes or adds an IP address to their switchboard server farm. Since these approaches are unreliable hassles, I would go for traffic analysis to decide if I'm looking at AIM.

Maybe there's some other reason why modeling encrypted applications accurately is important. Imagine there's an inspection device (like an IPS), that performs a length check on the Application Data messages of TLS sessions, and due to a parsing error, that device blows up if it sees TCP packets with four or five of them all stacked together. That fault wouldn't be detected if a testing apparatus didn't include some of this unusual traffic -- traffic that is otherwise perfectly realistic and based on real-world network usage.

Perhaps there's some other reason that we haven't thought of here yet. After all, some of our customers can be the secretive sort, since they tend to be designing, building, and testing the next generation of network hardware, so we don't always have perfect insight into what they're up to with our Application Simulator protocols. Hopefully, with BreakingPoint's dedication to protocol realism, those customers are able to test features and discover bugs that we haven't anticipated yet.

Posted by Tod Beardsley (2009/03/31 10:33:29.480 GMT-5)

MS09-008: Web Proxy Auto-Discovery (WPAD), Illustrated

It's not every day we get to talk about a ten year old vulnerability like it's new, but this week, Microsoft has given me just this opportunity with MS09-008, aka, "Vulnerabilities in DNS and WINS Server Could Allow Spoofing." A lot of people may not know about the role of WPAD in their desktop environment, so hopefully, this post will clear the air about what WPAD is and isn't, its sketchy security history, what MS09-008 proposes, and a quickie demo.

Amidst the global Y2k freakout in December of 1999, Microsoft released MS99-054, which purports to patch WPAD spoofing....

"Wait, what's WPAD?" you ask? Well, WPAD is a browser control protocol that allows network administrators let your browser figure out what proxy it ought to use to talk to the rest of the world. For IE, this functionality is on by default, and IE asks about WPAD with a DHCP request when it's first enabled. If it doesn't find one there, then it asks DNS.

Oh, and there's no cryptographic security at all built in to WPAD. DNS (or, more rarely, DHCP) tells your browser where to fetch the wpad.dat file... which is really just a series of Javascript directives to configure your browser for you... silently... without any real guarantee about where it came from aside from a DNS name.

Well, this is a bit of a problem, thanks to some built-in recursive searching. See, if your browser -- which is determined to reconfigure itself based on some unauthenticated guy's say-so -- couldn't find a machine called "wpad.site.yourcompany.com," it would ask about "wpad.yourcompany.com." Lucky for users of the time, it wouldn't automatically try to hit wpad.com, who could be anybody (but is in reality a nice guy named Duane Wessels). Unlucky for the fine people at haggisunlimited.co.uk, Internet Explorer thought that "co.uk" was still one step away from the world at large. Legend has it, Microsoft fixed that up in December of 1999. Also according to rumor and heresay, Microsoft fixed it again in 2005 (after some people got phished by wpad.org.uk), and later published a frank and useful KB article about the vagaries of DNS and WPAD around 2007.

So this week, the whole matter is finally behind us, right? Surely, the MS09-008 patch is going to be the end of this heady, devil-may-care decade of trusting DNS with auto-configuring proxy settings, right?

Sadly, not quite. MS09-008 does make it harder for a local attacker to sneak a new A record into your local DNS via a WINS registration, so that's good. But we're still relying on DNS to give us a trustworthy source for proxy configuration -- and that trust is really based on nothing. DNS spoofing and cache poisoning has been all the rage lately -- heck, MS09-008 also lumps in a couple more fixes to Windows DNS precisely for a couple spoofing attacks CVE-2009-0223 and CVE-2009-0224). Color me jaded, but I somehow doubt these are the last tricks we're going to pull out of DNS's hat.

Don't get me wrong; automatically configuring a proxy is not, in and of itself, a Bad Idea. It's plenty clever. It's just more clever when it's part of a DHCP request (which is baked in to Internet Explorer). At least that's somewhat more limited to a local(ish) network -- after all, if the adversary can compromise your local DHCP service, he can just hand you an evil gateway and monkey with all your traffic, not just web traffic. It would be more clever if the wpad.dat config file could be cryptographically signed in the same way that other critical paths are, like VPN connections. But for my money, it would be the cleverest of all if there was a way to force your browser to trust only WPAD information if and only if it's signed by some specific entity. At least, then, if something goes horribly, horribly wrong with DNS (ahem), users still will get a red button to ignore when they get an evil wpad.dat.

"Hey, where's my demo?" I hear you ask. Never fear, I didn't forget. So here we go, the magic of untrustable proxy configuration, just in case you're curious and haven't seen it in action. For this, you'll have to trust me... and some anonymous person in China who I've never met, since we're going to use his open proxy that he's advertising to the world. Hey, you can't back out now, you were the one rhetorically complaining in the first place. But, to make it fair, I won't give you screenshots of each button click -- honestly, performing the below without knowing what you're getting into is a Very Bad Idea. Oh, and since this whole problem isn't just Microsoft's bag, we'll do this thing with Firefox running on Windows XP.

First, you'll want to pretend to join my domain. Go to your Network Connections control panel, then navigate to TCP/IP Properties: Advanced, and add the domain "example.classself.com" to your DNS search order and as your DNS suffix. Hit OK, and close that out. Mind the spelling -- three es's.

Next, open up Firefox, and navigate to Edit: Preferences: Settings: Advanced: Network: Settings, and click on the "Auto-detect proxy settings." button. Hit okay, close that out.

Fire up Firefox again, and go to http://www.ipv6.org -- it should proudly tell you that you're visiting from "121.22.29.185," which is exactly the proxy that I just set for you. (I knew IPv6 was good for something!) If you don't believe me, you can go to http://wpad.example.classself.com/wpad.dat and see for yourself. It's text/plain javascript, so it shouldn't run in your browser.

Now, go log in to your PayPal account and ignore the warning about the invalid certificate... oh, I kid. That's the end of the demo. Please now, right away, uncheck your auto-proxy option, and forget that example.classself.com domain that you've pretended to join. This is a remarkably unwise networking state to be in.

Come to think of it, that last bit is good advice even if you were using WPAD legitimately before the demo. Seriously. You have no business asking strangers to proxy your web traffic for you, unless a) it's absolutely required by your local network, and b) you have a promise from your network administrator that you'll get the WPAD goods only by DHCP, or c) that he'll at least be very careful about how he implements DNS recursive queries, and he'll mind the wpad server like a hawk.

Posted by Tod Beardsley (2009/03/13 09:00:00 GMT+0)

HTTP, FTP, & IPS: YMMV

The other day, I was looking up some information on the Samba project and how they went about initially decoding and implementing SMB, and came across the Myths about Samba page. You'll notice that it looks like most any other web page. Nothing too exciting.

When I passed the link on in an IM, though, I noticed that this Samba document was not, in fact, being served by HTTP, but FTP. I double checked, and sure enough, my browser was quite happy to render the HTML elements. P and H tags, some BReaks, etc. Though I never really put much thought into it before, it turns out that my browser doesn't care if it gets HTML pages over HTTP or FTP.

So, I did what any protocol nerd would do, and I whipped together a page that exercises the usual gamut of HTML markup, and dropped it on an anonymous FTP server. It has some HTML, some Javascript, an ActiveX control, and an embedded Flash movie, all without a single http URI handler (check it here). It all renders just fine. To make sure my browser wasn't performing some protocol prestidigitation under the hood, I confirmed my traffic in Wireshark, and saw a typical passive FTP session.

Client (C) ---- connect -------> FTP Server (S)
(C) <---- 220 FTP Banner ------------------ (S)
(C) ----- USER anonymous -----------------> (S)
(C) <---- 331 OK -------------------------- (S)
(C) ----- PASS mozilla@example.com -------> (S)
(C) <---- 230 Logged in ------------------- (S)
(C) ----- SYST ---------------------------> (S)
(C) <---- 215 UNIX Type ------------------- (S)
(C) ----- PWD ----------------------------> (S)
(C) <---- 257 "/" is current directory.---- (S)
(C) ----- TYPE I -------------------------> (S)
(C) <---- 200 OK -------------------------- (S)
(C) ----- PASV ---------------------------> (S)
(C) <---- 227 Entering Passive Mode... ---- (S)
(C) ----- SIZE filename.html -------------> (S)
(C) ===== connect =======> FTP Data Channel (D)
(C) <---- 213 8535 ------------------------ (S)
(C) ----- RETR filename.html -------------> (S)
(C) <---- 150 Opening BINARY mode data... - (S)
(C) <==== File data ========================(D)
(C) <---- 226 Transfer Complete ----------- (S)
(C) ===== Session Close ==================> (D)

I'm sure you see where I'm going with this: This means all the browser exploits you've heard of will also work just fine over FTP. All your ActiveX buffer overflows, all your image parsing bugs, all your scammy spyware drive-by download sites, they're all perfectly at home in FTP-land.

Now, for browsers, this isn't that big of a deal. Browser patches tend to fix problems with the rendering engine anyway, and don't care that the offending file got here over HTTP, FTP, a local file read, Gopher, or whatever. The same goes for typical browser security features. Web proxies will tend to also proxy passive FTP, browser add-ons like NoScript and Flashblock don't worry about the transport protocol, and Internet Explorer's trust zones don't distinguish between HTTP and FTP sites in a given domain.

But for IPS and IDS, this is kind of a big deal. Most network inspection devices require either port correctness -- in this case, something like port 80 -- and/or protocol correctness -- like an HTTP 200 message signaling the start of an HTML download. Neither of these are present for FTP-transported client-side attacks. Passive FTP occurs on a port chosen at random (well, sort of -- more on that in another blog post), and there's no preamble to the download on the data session (the RETR command happens on the command channel). So, in order to catch these browser attacks, an inspection device would need to be performing deep inspection on all packets, or have anticipated this evasion by keeping state for all FTP sessions to be able to follow along with the right data session port number.

Neither of these are impossible, of course. Maybe your IDS or IPS is ahead of the curve and accurately picks out browser attacks delivered via FTP. Lucky for BreakingPoint customers, they can find out how your IPS stacks up against an FTP-delivered attack -- the last StrikePack has a new category of "Browser FTP" strikes. Therein, customers will find 146 Internet Explorer strikes which have been ported over from HTTP to FTP. If you're relying on IPS to help buy some time for your unpatched browsers, you might want to see how it stands up to the HTTP vs FTP versions of these strikes.

Posted by Tod Beardsley (2009/02/12 13:47:57.496 US/Central)
0 comments | Tags:

<<previous posts