Slashdot Mirror


Hijacking .NET

Matt Solnit writes "What can I say - Dan Appleman never fails to please. In this e-book, he takes a look at 'hijacking' .NET by accessing private members in .NET classes. Private members are, in essence, pieces of code that you don't want other programmers to access. You use them to support your own code, and you make public the pieces that you want to make available to other developers. Typically, a language ensures that a member marked as private is hidden from anyone who doesn't have your source code, but Appleman shows how in .NET it's not so." Read on for more of Matt's review of this guide to tricking private members to do your bidding. Hijacking .NET - Volume 1 author Dan Appleman pages 46 publisher Dan Appleman rating 10 reviewer Matt Solnit ISBN (N/A) summary An eye-opening look at how you can use undocumented and private features from the .NET framework.

In the .NET Framework, it's possible to access a private member of any class -- your own, another developer's, or even the classes in the .NET Framework itself! Appleman demonstrates this with a great example that uses private members to get the list of groups that the current user is a member of -- in a single line of code -- by accessing a private member that is not exposed by the .NET Framework.

Appleman also explains the tradeoffs of using this technique. The code you're using is not documented, and it's not guaranteed to be present in future versions. He describes how to deal with these problems, and how to make the most of the technique while remaining relatively safe.

Once the basic technique is explained, Appleman takes you into how to find out what private members are available, and how to call them. He shows how to use the object browser available in Visual Studio .NET and the Microsoft IL Disassembler, freely available in the Framework SDK, to discover the private members in a class and determine how to call them correctly.

The example is great -- Dan shows you how he used "hijacking" with a collection of private members to develop a FileAccessControlList class that can be used to manipulate ACL's on Windows files. This is a piece of functionality that is not included with the .NET Framework, but developers have a need for all the time. To write the code from scratch would take days, including translating Windows API declarations to C# or another .NET language and poring over MSDN documentation. As it turns out, all the pieces are in the Framework -- they're just not public. Appleman accomplishes the task in under 200 lines of code, all of which is included with the e-book. As a bonus, you get a great introduction to how Windows security works, and how the example could be extended to other ACL-controlled things like Registry keys.

The fact that private in .NET isn't really private is something that isn't well known, and even if you're not interested in security, this e-book is worth a read just to get some insight into what you can do with the .NET framework, and what other people might someday try to do to your code.

As far as the author's writing style, I will say that Dan has a great knack for intuiting what needs to be explained and what doesn't. His laid-back approach makes everything seem fun -- this is a book you could read on a Saturday afternoon in a hammock.

This e-book is not for beginning .NET programmers, but should be easy for intermediate developers to understand. The whole text weighs in at just under 50 pages, and is well worth the cost of $9.95. Sample code is provided in both C# and VB .NET.

This e-book can be purchased and downloaded immediately from amazon.com or through the author's web site.

21 of 514 comments (clear)

  1. So .Net is like C++? by Ed+Avis · · Score: 5, Interesting

    In Java, the bytecode interpreter makes sure you can't access private class members. This is needed for security - creating the 'sandbox' which is most well-known from applets, and IMHO isn't used enough elsewhere.

    OTOH in C++ the public/protected/private distinction is enforced solely by the compiler, and code has full access to the machine.

    Obviously in .NET you don't have the same raw hardware access, but it looks like for speed Microsoft omitted to check access qualifiers at run time. But I wonder, is this part of the .NET specifications, or is it just an implementation oversight? Does the same trick work on Mono for example?

    --
    -- Ed Avis ed@membled.com
    1. Re:So .Net is like C++? by Erv+Walter · · Score: 5, Informative

      This .NET behavior is not a security hole.

      The .NET CLR does runtime checks to verify that code is not doing things it's not allowed to do (aka, code can't leave the "sandbox"). Accessing private methods using this technique does not circumvent these checks--the CLR will detect and prevent *inappropriate* accesses.

      The key point is that .NET applications can be running in many different security environments. Installed applications running off your hard drive essentially have no sandbox. Applications running from the network or within a browser have a much more restrictive sandbox and these "hacking .NET" techniques would be caught (assuming the private code being called is inapproriate for the sandbox).

      --
      -- Erv Walter
    2. Re:So .Net is like C++? by patniemeyer · · Score: 5, Insightful

      In the first chapter of my book, Learning Java I make this comparison and show an example of how trivial it is to forge a pointer in C++.

      The thing that many people still just don't get about Java is that it was designed to supply this kind of safety *without* impacting performance. In Java byte code verification happens statically, before the code is executed using a kind of theorem prover.

      With certain concessions from the byte code you can prove that various types of problems (stack overflows/underflows, incorrect casts, etc.) cannot happen and you don't have to check for them at runtime. Of course in OO languages let you do things that require runtime checks, but at the bottom level Java can be statically compiled and optimized amost as far as C/C++ (only runtime array bounds checks are required) and because Java contains so much more information at runtime the new generation of profiling runtimes can do further optimizations dynamically that cannot be done in C/C++ (e.g. optimistically inlining methods and profiling garbage collection routines).

      Pat Niemeyer
      Author of Learning Java, O'Reilly & Associates and the BeanShell Java scripting language.

  2. Dan 'Obvious' Appleman by playtime222 · · Score: 5, Interesting

    Anyone who's looking into reflection at any depth knows that private members can be found and used without too much trouble. The only thing he's done here is actively tried to use the private functions of code he didn't right. What a genuis :-/

  3. C++ by Anonymous Coward · · Score: 5, Informative

    This is nothing new - you can do the same thing in C++. It's easy to access private variables or functions by manipulating a pointer.

    So what's the big deal?

  4. Maybe the title should be changed by julesh · · Score: 5, Insightful

    Maybe the title of this book should be changed to "1001 ways to write bad code". Relying on undocumented private members of classes violates encapsulation and pretty much guarantees that your code will not work with (a) compatible implementations on other platforms, and probably also (b) future versions on the same platform. Just Say No, is my advice.

  5. Duh. Its called reflection by Asmodeus · · Score: 5, Informative

    ..and is a very old technique.
    Java, Modula2, Lisp and smalltalk all allow
    this.
    RTFM

    1. Re:Duh. Its called reflection by egomaniac · · Score: 5, Informative

      I love it when a flat-out wrong post gets modded to 5. You most fucking certainly can access private methods and fields from within Java.

      For instance, to set the private field "x" on a Component:

      import java.awt.*;
      import java.lang.reflect.*;

      public class YouAreWrong {
      public static void main(String[] arg) throws Exception {
      Button youAreWrong = new Button();
      System.out.println("Button.getX() == " + youAreWrong.getX()); // youAreWrong.x = 5; would result in a compile error, as x is a private field
      Field x = Component.class.getDeclaredField("x");
      x.setAccessible(true);
      x.set(youAreWrong, new Integer(5));
      System.out.println("Button.getX() == " + youAreWrong.getX());
      }
      }

      Go try it and see what happens.

      --
      ZFS: because love is never having to say fsck
  6. Private methods and by yatest5 · · Score: 5, Interesting
    members are set as such not as some security method but to protect users of a class from using them. The fact this can be *programmed around* is irrelevant.

    Standard users, using standard techniques are only allowed to use public members and this is correct.

    I think you'll find that if you're willing to write your own compiler, you can access provate methods in any language you care to name.

    As such, this artile is irrelevant, an really just another pathetic excuse for a load of whingers to make cheap attacks on MS when they could *actually be contributing some effort* to the OS movement.

    Carry on guys, good work.

    --
    • Mod parent up! [a] by Anonymous Coward (Score:5) Thurs, June 31, @13:37
  7. Washington Strikes Again (see prior story) by rc5-ray · · Score: 5, Funny

    Read on for more of Matt's review of this guide to tricking private members to do your bidding.

    In related news, Washington State has banned the sale of this book because of gratuitous discussion of "private members".

  8. How it's done by Jabes · · Score: 5, Informative

    This will be done using reflection. It's pretty easy to instantiate private objects, and call private members using the reflection functions in .net (System.Reflection) I'll post an example if anyone is that interested, but there are quite a few examples kicking around on the net.

    However, the security model of .net only allows you to make these reflection calls if your application is running in "full trust". There is a very finely grained security model in .net, and applications can be trusted to make certain calls depending on the location they're running from (eg over the internet from an http:// address, on a network share, on the local disk); on whether the application is signed; by the vendor of the application; or even down to just a single program.

    At the moment .net programmers mostly assume they're running in full trust mode (which if its on the local hard disk, they are). But this is a poor assumption which will fall by the wayside in the future as .net takes off.

    To do other "unsafe" things (like use pointers, or interop into unmanaged code, generate dynamic code) you also need high permission levels.

    Now let's compare this with the unmanaged world. I can load up a DLL and call what the hell I want. I can even jump right into the middle of a function if I want. I can over-run buffers and blow my stack. I can do what the hell I want within my virtual address space. I can send messages to other applications and make them do screwy things. And I'm probably running as a local administrator so I can do things to other processes too.

    So is this a security concern? I don't think so.

    I must admit, I haven't read the book - and I'm not going to shell out $10 to find out if I'm right.

  9. Re:Is this a C# or a .NET problem? by Anonymous Coward · · Score: 5, Informative

    This is no security hole. If you're able to run code on the target machine then you can do pretty much anything you want (or can) already.

    Just because you can find out some "inner state" of an object doesn't mean that you're God now.

    Oh, and the same "exploit" can be done with C++ - does this have a negative affect on security? No.

    Encapsulation was never meant to be a security feature.

  10. Security by cooldev · · Score: 5, Informative

    Private members aren't for hiding code or data from other malicious programs; if they're being used in that way that's a flaw.

    It's simply a compile-time verification that you're using the object through it's intended public interface instead of relying on the internal implementation. If you disregard it you just end up throwing away a lot of the benefits of OO and you build fragile apps.

    That said, people should be aware of this so they don't mistakenly think that "private string m_password" is a secure way to store data.

    BTW: A long time ago I did this in Java by programmatically altering the bytecode of a .class file from another app.

  11. Re:Conclusion by JanneM · · Score: 5, Insightful

    I thought so too at first, but I believe it's not really the same thing here. Neither Perl nor C stuff depends on this encapsulation for any security stuff. For instance, Perl has sandboxing through taint checking and the safe module, and they do not assume that the potentially malicious code cannot access private members. Indeed, the filosophy in Perl is quite different - you are free to access any member function you want, or even 'private' data; it is assumed, though, that you know what you're doing in that case and won't come crying if things break for you as a result.

    --
    Trust the Computer. The Computer is your friend.
  12. Re:Is this a C# or a .NET problem? by Erv+Walter · · Score: 5, Informative

    Keep in mind that there is not always a sandbox for .NET applications. The security policys being enforced are configurable, but by default, installed applications running off your hard drive essentially have no sandbox. On the other hand, applications running from the network or within a browser have a much more restrictive sandbox and these "hacking .NET" techniques would be caught (assuming the private code being called is inapproriate for the sandbox).

    The .NET CLR does runtime checks to verify that code is not doing things it's not allowed to do (aka, code can't leave the "sandbox"). Accessing private methods using this technique does not circumvent these checks--the CLR will detect and prevent *inappropriate* accesses.

    --
    -- Erv Walter
  13. Re:Is this a C# or a .NET problem? by Anonymous Coward · · Score: 5, Insightful

    This whole story is hilarious. All (decent) languages let you hide implementation details from the end user. Finding them isn't `hacking` - its `stupid` as it means that if a chunk of code is changed to use, say, a doubly linked list rather than an array, your code would break, whereas it wouldn't if you accessed only the public methods/variables.
    This `exploit` is laughable, pointless and ultimately going to waste your time. The sort of coders who could use it would have the skill to figure it out in the first place anyway.

  14. Re:Is this a C# or a .NET problem? by 1000StonedMonkeys · · Score: 5, Informative

    Not quite true. .NET has a fine-grained security mechanism that allows code to execute with specific priviledges. It can do that because .NET, like Java, is run by a VM. What the original poster is getting at is that you might be able to bypass these access controls if you're able to access the private data members of .NET system classes.

  15. Completely Irrelevant by sethamin · · Score: 5, Insightful
    Oh for god's sakes people, this is just dumb. There's no real reason to take the performance hit and enforce this at run-time, because the protection of private member variables are there for your benefit. If you want to access undocumented variables that were never meant to be exposed, you're just asking for bugs and future incompatibility.

    Oh, and BTW, this has nothing to do with actual security. Relying on access level specifiers to protect sensitive data in memory is lunacy. The standard coding technique for dealing with things like passwords is to keep them around for as short a period of time as possible and then overwrite that memory afterwards with random bits. If you're storing them long term cleartext in memory then you've got bigger problems.

  16. C++ will let you do anything! by BaldBass · · Score: 5, Informative
    "In C++ the compiler will not let you access private methods or variables."

    No and no. Example:
    producer.h:

    class ThoughtToBeSecure {
    private:
    void highlyGuardedMethod();
    int highlyGuardedVariable;
    };

    hacked_producer.h:

    class ThoughtToBeSecure {
    public:
    inline void protectionBypass() {
    highlyGuardedMethod();
    }
    inline void hackTheVariableToo(int value) {
    highlyGuardedVariable= value;
    }

    private:
    void highlyGuardedMethod();
    int highlyGuardedVariable;
    };

    malicous_user.cpp:

    #include "hacked_producer.h"

    void sandboxHaHa(ThoughtToBeSecure x) {
    x.protectionBypass();
    x.hackTheVariableToo(0);
    }
    Looks like you need to brush up your C++ knowlege.
  17. finding them? sure. calling them? no. by MORTAR_COMBAT! · · Score: 5, Interesting

    Naturally even with rudimentary decompilers (and even the Java reflection API) you can find out what private fields and methods are defined for a given Java class.

    However if they are private, you can't actually find out the values of those fields for a given object, or call those methods. You get an IllegalAccessException.

    This .NET exploit advertises itself to be much different. Sure, you can still find out what private stuff you want.

    But under .NET, it appears you can actually _invoke_ those methods, methods which are probably meant to be hidden under a separate security API layer, etc.

    --
    MORTAR COMBAT!
  18. Re:Is this a C# or a .NET problem? by Anonymous Coward · · Score: 5, Insightful

    Sounds more like FUD from the *nix crowd.

    "The C++ access control mechanisms provide against accident - not against fraud. Any programming language that supports access to raw memory will leave data open to deliberate tampering..." The Annotated C++ Reference Manual, p 239.

    Encapsulation has NOTHING to do with security.