What do Rootkits and Xerxes have in common?

August 25, 2009

By: Cris Neckar and Greg Ose

Just think of your kernel as Greece…

It’s probably not the first thing you expected to hear me say but bear with me. The arms race between rootkit development and detection has been raging for years, and although there have been great advancements in detection, rootkit developers have always had the upper hand. You simply cannot defend against what you cannot predict. Recently the battle has become increasingly heated as rootkit developers dig deeper and deeper. One only need look at the Blackhat Briefings for the past few years to see the trend.

Increasingly subversive and complex rootkits threaten to over-run our kernels and turn our business critical systems into slaves. So what are we to do? Should we simply throw up our hands and resolve ourselves to a life of bondage?

To answer this question lets approach the problem from a different angle. It has become clear that we cannot simply monitor everything a rootkit developer might change. There are just too many function pointers, operating modes, and devices to allow us to watch them all. However, one commonality does exist in all kernel mode rootkits. In some way they must all be inserted into the kernel.

There are a number of ways to introduce new code into a running kernel but not nearly so many as there are places to hide once inside. I propose that, instead of building a blacklist and peeking under all the rocks where they have hidden in the past, we instead monitor the entry point. Leonidas used a similar approach when Xerxes threatened Greece, instead of fighting on even ground the Spartans guarded the narrow door through which the Persians must travel to enter Greece.

So, you say, it’s a great theory, but how do we implement it?  Assuming an attacker has compromised a system’s most privileged usermode context, for instance a process running as root, code can be introduced into the running kernel in a number of ways. The most obvious of these is to install a module or driver and be done with it. Aside from that, an attacker would need to patch kernel memory directly, this is not trivial but is still a common method of rootkit insertion. Aside from these options, the attacker would be forced to edit the kernel binary, or an existing module on disk and either cause or wait for a reboot (There is one additional threat which we will save for later). The interesting thing about all of these potential insertion points is that they are events which would almost never occur in a production server (If they do occur an administrator will certainly be aware of the reason). By monitoring these few events we would be notified of the insertion of any existing kernel mode rootkit that I am aware of, as well as any that could be written in the future (barring a further vulnerability.. more on this later).

To implement this on Linux is actually fairly trivial. To monitor for code inserted into the kernel while running we can use the tricks of rootkit developers ourselves. Namely we can hook sys_init_module (for module insertions), and the write() handlers within the kmem and mem file operations structures (for writes to /dev/(k)mem where these are still possible).

The next step is to defend against changes made to kernel components on disk. For the kernel image itself, on a system which is rarely rebooted such as a production server, it is possible to accomplish this by booting a known good kernel. For example a kernel could be booted from media which is only physically attached to the system when the kernel is initially loaded into memory. A similar approach could be used with required kernel modules, or if preferable, they could be compared on load to known good check sums.

Now that we have covered the entry points we can focus on what to do once one of these events occurs. We do not actually need to prevent the insertion as, in some cases, these events may legitimately occur (once a root compromise has occurred a re-image of the system is generally the best approach anyway). Instead we simply need to securely log the event to a location which is not controlled by the intruder. Obviously we can not log locally. Additionally we cannot log with mechanisms which are already under the attackers control (anything accessible from user mode is out). One relatively trivial solution is to simply create a syslog packet and drop it on the network stack when one of our traps triggers. This will provide us with a remote log on a system which (hopefully) has not been compromised. When implementing this you would of course want to be careful to temporarily disable any netfilter hooks (think iptables) as these could allow the intruder to block our logging packet from usermode.

Like Sparta’s defense at Thermopolae, this method also has its mountain path. I mentioned earlier that there was an additional method for introducing code into a running kernel. This would involve the existence of a vulnerability within the kernel or a loaded module which allows arbitrary memory to be written. An attacker could create an exploit which uses such a vulnerability to introduce a rootkit into the kernel. We cannot possibly predict where an exploit will occur (if we could, vulnerability research would be a lot easier :) ) making it impossible (so far ;) ) to guard against this threat using this method. Fortunately a rootkit which used this installation method would be obsolete the moment it was first detected. This means that this type of rootkit could never reach widespread usage and would most likely be used only in a very targeted attack.


Michael Rasmussen Blogs on the topic of GRC

August 11, 2009

Gregg LaRoche, VP Product Management, Neohapsis

I recently spotted an interesting posting on Mr. Rasmussen’s Blog – GRC Pundit entitled “The Forrester GRC ‘Ripple’ (OOOPS . . . I Mean, ‘Wave’)”. In addition to some very candid observations regarding industry analysts’ well-known graphical reports, Neohapsis is mentioned as one of the significant GRC vendors ‘missed’ in this year’s GRC Wave report. As you may know, the Wave criterion includes product deployment metrics to ensure new or Beta products are omitted. Certus GRC is in Beta stage and as such was not eligible for inclusion in the report. Why is Neohapsis’ Certus GRC offering significant although not included? Certus GRC is a ground breaking product that I have no doubt the analyst community will find compelling and will challenge many prior perceptions they have held about the GRC technology space and how Certus GRC can be used to manage highly complex, interrelated GRC relationships in ways that make sense for business stakeholders and employees.

I was particularly interested in Mr. Rasmussen’s perspective on the dangers of relying on the major analyst firms’ industry graphic to make critical technology selection decisions. Enterprise technology decisions are important not only in terms of investment and return, but also can dictate employee and partner experiences and limitations for years to come. Graphical summaries are useful to compare and contrast the largest, most established products at a high level. They can tell us who within that group is investing in technology over time and can also gauge some interesting peer enterprise viewpoints. But what does that tell your enterprise about the performance of that investment, the overall fit, or the user experience for your unique environment and set of business challenges? Rasmussen makes the astute observation that in this particular case, the report has focused on the IT buyer and has missed the essential business buyer. GRC is a discipline and a solution set that spans the enterprise when fully realized, and requires cross functional cooperation and C-level visibility to be truly successful.

I happen to agree with Mr. Rasmussen’s well-informed pros and cons on this topic and also respect and find good value in the analyst firms I work with, including the highly regarded author of the Wave report and others. But like most good things, analyst opinions do need to be measured in the fullness of our own judgment, unique experiences, and those of our customers and stakeholders.

Check out Michael Rasmussen’s post at http://corp-integrity.blogspot.com/2009/07/forrester-grc-ripple-ooops-i-mean-wave.html


ViewStateViewer: A GUI Tool for deserializing/reserializing ViewState

August 3, 2009

By: Patrick Toomey

Background

So, I was reading the usual blogs and came across a post by Mike Tracy from Matasano (Matasano has been having some technical difficulties…this link should work once they have recovered).  In the blog post Mike talks about the development of a ViewState serializer/deserializer for his WWMD web application security assessment console  (please see Mike’s original post for more details).  Mike noted that the tools for viewing/manipulating ViewState from an application testing perspective are pretty weak, and I can’t agree more.  There are a number of ViewState tools floating around that do a tolerable job of taking in a Base64 encoded ViewState string and presenting the user with a static view of the deserialized object. However, no tools up until this point, save for Mike’s new implementation, have allowed a user to change the values within the deserialized object and then reserialize them into a new Base64 string. Mike’s tool does exactly this, and is immensely useful for web application testing. The only downside to Mike’s tools is that it is built for his workflow and not mine (how can I fault the man for that).  So, I decided to build an equivalent that works well for me (and hopefully for you as well).

I tend to have a web proxy of some sort running on my machine throughout the day. There are tons of them out there and everyone seems to have their personal favorite. There is Paros, WebScarab, BurpSuite, and I am sure many others. In the last few months I have been using a newer entrant into the category, Fiddler.  Fiddler is a great web proxy whose only big drawback is that it is Windows only.  However, at least for me, the upsides to Fiddler tend to outweigh the negatives.  Fiddler has a fairly refined workflow (don’t get me started on WebScarab), is stable (don’t get me started on Paros), and is pretty extensible.  There are a number of ways to extend Fiddler, most trivially using their own FiddlerScript hooks.  In addition, there is a public API for extending the application using .NET.  Fiddler has a number of interfaces that can be extended to allow for inspecting and manipulating requests or responses. Please see the Fiddler site for more details on extending Fiddler using either FiddlerScript or .NET.  In particular, take a look at the development section to get a better feel for the facilities provided by Fiddler for extending the application.

Anyway, I had been thinking about writing a ViewState serializer/deserializer for Fiddler for the past month or two when I saw Mike’s blog post.  I decided that it was about time to set aside a little time and write some code.  I was lucky that Fiddler uses .NET, as I was able to leverage all of the system assemblies that Mike had to decompile in Reflector. After a bit of coding I ended up with my ViewStateViewer Fiddler inspector.  Let’s take a quick tour…

ViewStateViewer seamlessly integrates into the Fiddler workflow, allowing a user to manipulate ViewState just as they would any other variable in a HTTP request.  An extremely common scenario for testing involves submitting a request in the browser, trapping the request in a proxy, changing a variable’s value, and forwarding the request on to the server. ViewStateViewer tries to integrate into this workflow as seamlessly as possible.  Upon trapping a request that contains ViewState, ViewStateViewer extract the Base64 encoded ViewState, Base64 decodes it, deserializes the ViewState, and allows a user to manipulate the ViewState as they would any other variable sent to the server.  Let’s take a look at some screenshots to get a better idea of how this works.

ViewStateViewer Tour

Serialized ViewStateSerialized ViewState

By Default, Fiddler lets a user trap requests and view/edit a POST body before submitting the request to the server.  In this case, the POST body contains serialized ViewState that we would like to work with.  Without ViewStateViewer this is non-trivial, as Fiddler only shows us the Base64 encoded serialization.

Deserialized ViewStateDeserialized ViewState

ViewStateViewer adds a new “ViewState” tab within Fiddler that dynamically identifies and deserializes ViewState on the fly.  The top half of the inspector shows the original Base64 serialized ViewState string.  The bottom half of the inspector shows an XML representation of the deserialized ViewState.  In between these two views the user can see if the ViewState is MAC protected and the version of the ViewState being deserialized.  In this case we can see that this is .NET 2.X ViewState and that MAC protection is not enabled.

ReSerialized ViewStateReserialized ViewState

Once the ViewState is deserialized we can manipulate the ViewState by changing the values in the XML representation.  In this example we changed one of the string values to “foobar”, as can be seen in the figure above.  Once we change the value we can reserialize the ViewState using the “encode” button.  The reserialized Base64 encoded ViewState string can be seen in the top half of the ViewStateViewer window.  Once we have “encoded” the ViewState with our modifications, ViewStateViewer automatically updates the POST body with the new serialized ViewState string.  This request can now be “Run to Completion”, which lets Fiddler submit the updated request to the server.

Limitations

It should be noted that if the original ViewState had used MAC protection ViewStateViewer would not be able to reserialize the manipulated ViewState with a valid MAC.  While ViewStateViewer will not prevent you from deserializing, manipulating, and reserializing MAC protected ViewState, it will not be able to append a valid MAC to modified ViewState.  ViewStateViewer will warn us that “Modified ViewState does not contain a valid MAC”.  Modified requests made using reserialized MAC protected ViewState will ultimately fail, as we don’t know the machine key used to produce a valid MAC.  Regardless, sometimes simply being able to view what is being stored in MAC protected ViewState can be useful during an application assessment.

In addition to MAC protection, ViewState can be optionally protected using encryption.  Encryption will prevent any attempt by ViewStateViewer to deserialize the ViewState.  If encryption is detected ViewStateViewer will simply show the user the original Base64 ViewState string.  However, as any application security consultant can attest, there are many applications that do not encrypt or MAC protect their ViewState.  ViewStateViewer is aimed squarely at these use cases.

Finally, ViewStateViewer was written entirely with deserializing/serializing ViewState 2.X in mind. While ViewState 1.X is supported, the support at this time is limited, though completely functional. ViewState 1.X, unlike ViewState 2.X, Base64 decodes into a completely human readable ASCII based serialization format (think JSON).  As such, ViewStateViewer simply Base64 decodes ViewState 1.X and displays the result to the user. The user is then free to make any changes they wish to the decoded ViewState. This works exactly the same as the example shown above, except that the decoded ViewState object will not be a nicely formatted XML document. I might get around to adding true ViewState 1.X support, but the benefits would be purely cosmetic, as the current implementation has no functional limitations.

Wrap Up

ViewState is one of those areas that tends to be under-tested during application assessments, as there have been no good tools for efficiently evaluating the effects of modifying ViewState.  Hopefully the release of ViewStateViewer will make evaluation of ViewState a more common practice.  If you want to give ViewStateViewer a try you can download the Fiddler plugin(with source) here. Simply copy ViewStateViewer.dll into your “Inspectors” folder within your Fiddler install directory.  It should be noted that this inspector is for Fiddler2, so please update your copy of Fiddler if you are out of date.  Finally, this is very much a work in progress.  As I found out during development, there is ton of ViewState out there that is either non-trivial to deserialize/reserialize or is impossible to deserialize/reserialize (non-standard objects being serialized for example).  Maybe I’ll do another blog post detailing some of these difficult/impossible to handle edge cases in a subsequent post.  So, while I have done some limited testing, I am sure there are some bugs that will crop up.  If you happen to find one please don’t hesitate to contact me.


Follow

Get every new post delivered to your Inbox.