Langsung ke konten utama

Exploiting .Net Managed Dcom

Posted yesteryear James Forshaw,

One of the to a greater extent than interesting classes of safety vulnerabilities are those affecting interoperability technology. This is because these vulnerabilities typically conduct upon whatever application using the technology, regardless of what the application genuinely does. Also inward many cases they’re hard for a developer to mitigate exterior of non using that technology, something which isn’t ever possible.

I discovered i such vulnerability shape inward the Component Object Model (COM) interoperability layers of .NET which brand the utilisation of .NET for Distributed COM (DCOM) across privilege boundaries inherently insecure. This weblog postal service volition push clit a brace of ways this could live abused, starting fourth dimension to gain elevated privileges together with and then every bit a remote code execution vulnerability.

A Little Bit of Background Knowledge

If you lot hold back at the history of .NET many of its early on underpinnings was trying to brand a ameliorate version of COM (for a quick history lesson it’s worth watching this curt video of Anders Hejlsberg discussing .NET). This led to Microsoft placing a large focus on ensuring that spell .NET itself mightiness non live COM it must live able to interoperate amongst COM. Therefore .NET tin both live used to implement every bit good every bit swallow COM objects. For illustration instead of calling QueryInterface on a COM object you lot tin only cast an object to a COM compatible interface. Implementing an out-of-process COM server inward C# is every bit uncomplicated every bit the following:

// Define COM interface.
[ComVisible(true)]
[InterfaceType(ComInterfaceType.InterfaceIsIDispatch)]
[Guid("3D2392CB-2273-4A76-9C5D-B2C8A3120257")]
public interface ICustomInterface {
   void DoSomething();
}

// Define COM shape implementing interface.
[ComVisible(true)]
[Guid("8BC3F05E-D86B-11D0-A075-00C04FB68820")]
public class COMObject : ICustomInterface {
   public void DoSomething() {}
}

// Register COM shape amongst COM services.
RegistrationServices reg = new RegistrationServices();
int cookie = reg.RegisterTypeForComClients(
                 typeof(COMObject),
                 RegistrationClassContext.LocalServer
                   | RegistrationClassContext.RemoteServer,
                 RegistrationConnectionType.MultipleUse);

A customer tin at nowadays connect to the COM server using it’s CLSID (defined yesteryear the Guid attribute on COMClass). This is inward fact so uncomplicated to exercise that a large number of meat classes inward .NET are marked every bit COM visible together with registered for utilisation yesteryear whatever COM customer fifty-fifty those non written inward .NET.

One of the to a greater extent than interesting classes of safety vulnerabilities are those affecting intero Exploiting .NET Managed DCOM

To brand this all piece of occupation the .NET runtime hides a large amount of boilerplate from the developer. There are a brace of mechanisms to influence this boilerplate interoperability code, such every bit the InterfaceType attribute which defines whether the COM interface is derived from IUnknown or IDispatch but for the most constituent you lot instruct what you’re given.

One thing developers perchance don’t realize is that it’s non only the interfaces you lot specify which instruct exported from the .NET COM object but the runtime adds a number of “management” interfaces every bit well. This interfaces are implemented yesteryear wrapping the .NET object within a COM Callable Wrapper (CCW).

One of the to a greater extent than interesting classes of safety vulnerabilities are those affecting intero Exploiting .NET Managed DCOM
We tin enumerate what interfaces are exposed yesteryear the CCW. Taking System.Object every bit an illustration the next tabular array shows what interfaces are supported along amongst how each interface is implemented, either dynamically at runtime or statically implemented within the runtime.

Interface Name
Implementation Type
_Object
Dynamic
IConnectionPointContainer
Static
IDispatch
Dynamic
IManagedObject
Static
IMarshal
Static
IProvideClassInfo
Static
ISupportErrorInfo
Static
IUnknown
Dynamic

The _Object interface refers to the COM visible representation of the System.Object shape which is the root of all .NET objects, it must live generated dynamically every bit it’s theme on the .NET object beingness exposed. On the other paw IManagedObject is implemented yesteryear the runtime itself together with the implementation is shared across all CCWs.

I started looking at the exposed COM laid on surface for .NET dorsum inward 2013 when I was investigating Internet Explorer sandbox escapes. One of the COM objects you lot could access exterior the sandbox was the .NET ClickOnce Deployment broker (DFSVC) which turned out to live implemented inward .NET, which is in all probability non likewise surprising. I genuinely establish 2 issues, non inward DFSVC itself but instead inward the _Object interface exposed yesteryear all .NET COM objects. The _Object interface looks similar the next (in C++).

struct _Object : public IDispatch {
 HRESULT ToString(BSTR * pRetVal);
 HRESULT Equals(VARIANT obj, VARIANT_BOOL *pRetVal);
 HRESULT GetHashCode(long *pRetVal);
 HRESULT GetType(_Type** pRetVal);
};

The starting fourth dimension põrnikas (which resulted inward CVE-2014-0257) was inward the GetType method. This method returns a COM object which tin live used to access the .NET reflection APIs. As the returned _Type COM object was running within the server you lot could telephone recall a chain of methods which resulted inward getting access to the Process.Start method which you lot could telephone recall to escape the sandbox. If you lot desire to a greater extent than details virtually that you lot tin hold back at the PoC I wrote together with set upwards on Github. Microsoft fixed this yesteryear preventing the access to the reflection APIs over DCOM.

The minute number was to a greater extent than subtle together with is a byproduct of a characteristic of .NET interop which presumably no-one realized would live a safety liability. Loading the .NET runtime requires quite a lot of additional resources, thus the default for a native COM customer calling methods on a .NET COM server is to allow COM together with the CCW create out the communication, fifty-fifty if this is a functioning hit. Microsoft could receive got chosen to utilisation the COM marshaler to forcefulness .NET to live loaded inward the customer but this seems overzealous, non fifty-fifty counting the possibility that the customer mightiness non fifty-fifty receive got a compatible version of .NET installed.

When .NET interops amongst a COM object it creates the inverse of the CCW, the Runtime Callable Wrapper (RCW). This is a .NET object which implements a runtime version of the COM interface together with marshals it to the COM object. Now it’s alone possible that the COM object is genuinely written inward .NET, it mightiness fifty-fifty live inward the same Application Domain. If .NET didn’t exercise something you lot could terminate upwards amongst a double functioning hit, marshaling inward the RCW to telephone recall a COM object which is genuinely a CCW to a managed object.

One of the to a greater extent than interesting classes of safety vulnerabilities are those affecting intero Exploiting .NET Managed DCOM


It would live prissy to seek together with “unwrap” the managed object from the CCW together with instruct dorsum a existent .NET object. This is where the villain inward this slice comes into play, the IManagedObject interface, which looks similar the following:

struct IManagedObject : public IUnknown {
 HRESULT GetObjectIdentity(
   BSTR*   pBSTRGUID,  
   int*    AppDomainID,  
   int*    pCCW);
   
 HRESULT GetSerializedBuffer(
   BSTR *pBSTR  
 );
};

When the .NET runtime gets concur of a COM object it volition exceed away through a procedure to determine whether it tin “unwrap” the object from its CCW together with avoid creating an RCW. This procedure is documented but inward summary the runtime volition exercise the following:
  1. Call QueryInterface on the COM object to determine if it implements the IManagedObject interface. If non together with then render an appropriate RCW.
  2. Call GetObjectIdentity on the interface. If the GUID matches the per-runtime GUID (generated at runtime startup) together with the AppDomain ID matches the electrical flow AppDomain ID together with then lookup the CCW value inward a runtime tabular array together with extract a pointer to the existent managed object together with render it.
  3. Call GetSerializedBuffer on the interface. The runtime volition depository fiscal establishment check if the .NET object is serializable, if so it volition exceed the object to BinaryFormatter::Serialize together with bundle the outcome inward a Binary String (BSTR). This volition live returned to the customer which volition at nowadays elbow grease to deserialize the buffer to an object instance yesteryear calling BinaryFormatter::Deserialize.

Both steps 2 together with 3 audio similar a bad idea. For illustration spell inward 2 the per-runtime GUID can’t live guessed; if you lot receive got access to whatever other object inward the same procedure (such every bit the COM object exposed yesteryear the server itself) you lot tin telephone recall GetObjectIdentity on the object together with replay the GUID together with AppDomain ID dorsum to the server. This doesn’t genuinely gain you lot much though, the CCW value is only a number non a pointer so at best you’ll live able to extract objects which already receive got a CCW inward place.

Instead it’s measuring 3 which is genuinely nasty. Arbitrary deserialization is unsafe almost no affair what linguistic communication (take your pick, Code Integrity inward Windows Powershell.

This atomic number 82 me to finding the ObjectSerializedRef class. This looks really much similar a shape which volition deserialize whatever object type, non only serialized ones. If this was the instance together with then that would live a really powerful primitive for edifice a to a greater extent than functional deserialization chain.

[Serializable]
private sealed class ObjectSerializedRef : IObjectReference,
                                          IDeserializationCallback
{
 private Type type;
 private object[] memberDatas;

 [NonSerialized]
 private object returnedObject;

 object IObjectReference.GetRealObject(StreamingContext context) {
   returnedObject = FormatterServices.GetUninitializedObject(type);
   return this.returnedObject;
 }

 void IDeserializationCallback.OnDeserialization(object sender) {
   string[] array = null;
   MemberInfo[] serializableMembers =
      FormatterServicesNoSerializableCheck.GetSerializableMembers(
          type, out array);
   FormatterServices.PopulateObjectMembers(returnedObject,
                           serializableMembers, memberDatas);
 }
}

Looking at the implementation the shape was used every bit a serialization surrogate exposed through the ActivitiySurrogateSelector class. This is a characteristic of the .NET serialization API, you lot tin specify a “Surrogate Selector” during the serialization procedure which volition supersede an object amongst surrogate class. When the flow is deserialized this surrogate shape contains plenty information to reconstruct the original object. One utilisation instance is to grip the serialization of non-serializable classes, but ObjectSerializedRef goes beyond a specific utilisation instance together with allows you lot to deserialize anything. Influenza A virus subtype H5N1 essay was inward order:

// Definitely non-serializable class.
class NonSerializable {
 private string _text;

 public NonSerializable(string text) {
   _text = text;
 }

 public override string ToString() {
   return _text;
 }
}

// Custom serialization surrogate
class MySurrogateSelector : SurrogateSelector {
 public override ISerializationSurrogate GetSurrogate(Type type,
     StreamingContext context, out ISurrogateSelector selector) {
   selector = this;
   if (!type.IsSerializable) {
     Type t = Type.GetType("ActivitySurrogateSelector+ObjectSurrogate");
     return (ISerializationSurrogate)Activator.CreateInstance(t);
   }

   return base.GetSurrogate(type, context, out selector);
 }
}

static void TestObjectSerializedRef() {
   BinaryFormatter fmt = new BinaryFormatter();
   MemoryStream stm = new MemoryStream();
   fmt.SurrogateSelector = new MySurrogateSelector();
   fmt.Serialize(stm, new NonSerializable("Hello World!"));
   stm.Position = 0;

   // Should impress Hello World!.
   Console.WriteLine(fmt.Deserialize(stm));
}

The ObjectSurrogate shape seems to piece of occupation almost likewise well. This shape totally destroys whatever promise of securing an untrusted BinaryFormatter stream together with it’s available from .NET 3.0. Any shape which didn’t score itself every bit serializable is at nowadays a target. It’s going to live pretty slow to observe a shape which spell invoke an arbitrary delegate during deserialization every bit the developer volition non live doing anything to guard against such an laid on vector.

Now only to select a target to build out our deserialization chain. I could receive got chosen to poke farther at the Workflow classes, but the API is horrible (in fact inward .NET four Microsoft replaced the former APIs amongst a new, slightly nicer one). Instead I’ll pick a genuinely slow to utilisation target, Language Integrated Query (LINQ).

LINQ was introduced inward .NET 3.5 every bit a meat linguistic communication feature. Influenza A virus subtype H5N1 novel SQL-like syntax was introduced to the C# together with VB compilers to perform queries across enumerable objects, such every bit Lists or Dictionaries. An illustration of the syntax which filters a listing of names based on length together with returns the listing uppercased is every bit follows:

string[] names = { "Alice", "Bob", "Carl" };

IEnumerable<string> question = from advert in names
                           where name.Length > 3
                           orderby name
                           select name.ToUpper();

foreach (string item in query) {
   Console.WriteLine(item);
}

You tin also stance LINQ non every bit a question syntax but instead a way of doing listing comprehension inward .NET. If you lot think of ‘select’ every bit equivalent to ‘map’ together with ‘where’ to ‘filter’ it mightiness brand to a greater extent than sense. Underneath the question syntax is a series of methods implemented inward the System.Linq.Enumerable class. You tin write it using normal C# syntax instead of the question language; if you lot exercise the previous illustration becomes the following:

IEnumerable<string> question = names.Where(name => name.Length > 3)
                                .OrderBy(name => name)
                                .Select(name => name.ToUpper());

The methods such every bit Where take 2 parameters, a listing object (this is hidden inward the higher upwards example) together with a delegate to invoke for each entry inward the enumerable list. The delegate is typically provided yesteryear the application, withal there’s null to halt you lot replacing the delegates amongst arrangement methods. The of import thing to conduct inward hear is that the delegates are non invoked until the listing is enumerated. This way nosotros tin build an enumerable listing using LINQ methods, serialize it using the ObjectSurrogate (LINQ classes are non themselves serializable) together with then if nosotros tin forcefulness the deserialized listing to live enumerated it volition execute arbitrary code.

Using LINQ every bit a primitive nosotros tin create a listing which when enumerated maps a byte array to an instance of a type inward that byte array yesteryear the next sequence:

One of the to a greater extent than interesting classes of safety vulnerabilities are those affecting intero Exploiting .NET Managed DCOM
The only tricky constituent is measuring 2, we’d similar to extract a specific type but our only existent pick is to utilisation the Enumerable.Join method which requires some weird kludges to instruct it to work. Influenza A virus subtype H5N1 ameliorate pick would receive got been to utilisation Enumerable.Zip but that was only introduced inward .NET 4. So instead we’ll only instruct all the types inward the loaded assembly together with create them all, if nosotros only receive got i type together with then this isn’t going to brand whatever difference. How does the implementation hold back inward C#?

static IEnumerable CreateLinq(byte[] assembly) {
 List<byte[]> base_list = new List<byte[]>();
 base_list.Add(assembly);
 
 var get_types_del = (Func<Assembly, IEnumerable<Type>>)
                        Delegate.CreateDelegate(
                          typeof(Func<Assembly, IEnumerable<Type>>),
                          typeof(Assembly).GetMethod("GetTypes"));

 return base_list.Select(Assembly.Load)
                 .SelectMany(get_types_del)
                 .Select(Activator.CreateInstance);
}

The only non-obvious constituent of the C# implementation is the delegate for Assembly::GetTypes. What nosotros require is a delegate which takes an Assembly object together with returns a listing of Type objects. However every bit GetTypes is an instance method the default would live to capture the Assembly class together with shop it within the delegate object, which would outcome inward a delegate which took no parameters together with returned a listing of Type. We tin instruct around this yesteryear using the reflection APIs to create an opened upwards delegate to an instance member. An opened upwards delegate doesn’t shop the object instance, instead it exposes it every bit an additional Assembly parameter, just what nosotros want.

With our enumerable listing nosotros tin instruct the assembly loaded together with our ain code executed, but how exercise nosotros instruct the listing enumerated to start the chain? For this decided I’d seek together with observe a shape which when calling ToString (a pretty mutual method) would enumerate the list. This is slow inward Java, almost all the collection classes receive got this exact behavior. Sadly it seems .NET doesn't follow Java inward this respect. So I modified my analysis tools to seek together with hunt for gadgets which would instruct us there. To cutting a long even out curt I establish a chain from ToString to IEnumerable through 3 dissever classes. The chain looks something similar the following:

One of the to a greater extent than interesting classes of safety vulnerabilities are those affecting intero Exploiting .NET Managed DCOM
Are nosotros done yet? No, only i to a greater extent than step, nosotros require to telephone recall ToString on an arbitrary object during deserialization. Of course of written report I wouldn’t receive got chosen ToString if I didn’t already receive got a method to exercise this. In this lastly instance I’ll exceed away dorsum to abusing poor, old, Hashtable. During deserialization of the Hashtable shape it volition rebuild its primal set, which nosotros already know virtually every bit this is how I exploited serialization for local EoP. If 2 keys are equal together with then the deserialization volition neglect amongst the Hashtable throwing an exception, resulting inward running the following code:

throw new ArgumentException(
           Environment.GetResourceString("Argument_AddingDuplicate__",
                                   buckets[bucketNumber].key, key));

It’s non straight off obvious why this would live useful. But perchance looking at the implementation of GetResourceString volition enter clearer:

internal static String GetResourceString(String key, params Object[] values) {
   String s = GetResourceString(key);
   return String.Format(CultureInfo.CurrentCulture, s, values);
}

The primal is passed to GetResourceString within the values array every bit good every bit a reference to a resources string. The resources string is looked upwards together with along amongst the primal passed to String.Format. The resulting resources string has formatting codes so when String.Format encounters the non-string value it calls ToString on the object to format it. This results inward ToString beingness called during deserialization kicking off the chain of events which leads to us loading an arbitrary .NET assembly from retentiveness together with executing code inward the context of the WMI client.

One of the to a greater extent than interesting classes of safety vulnerabilities are those affecting intero Exploiting .NET Managed DCOM
You tin reckon the lastly implementation inward latest the PoC I’ve added to the issue tracker.

Conclusions

Microsoft fixed the RCE number yesteryear ensuring that the System.Management classes never straight creates an RCW for a WMI object. However this laid upwards doesn’t conduct upon whatever other utilisation of DCOM inward .NET, so privileged .NET DCOM servers are soundless vulnerable together with other remote DCOM applications could also live attacked.

Also this should live a lesson to never deserialize untrusted information using the .NET BinaryFormatter class. It’s a unsafe thing to exercise at the best of times, but it seems that the developers receive got abandoned whatever promise of making secure serializable classes. The presence of ObjectSurrogate effectively way that every shape inward the runtime is serializable, whether the original developer wanted them to live or not.

And every bit a lastly thought you lot should ever live skeptical virtually the safety implementation of middleware peculiarly if you lot can’t inspect what it does. The fact that the number amongst IManagedObject is designed inward together with hard to take makes it really hard to laid upwards correctly.

Komentar

Postingan populer dari blog ini

Exception-Oriented Exploitation On Ios

Posted past times Ian Beer, This postal service covers the regain in addition to exploitation of CVE-2017-2370 , a heap buffer overflow inwards the mach_voucher_extract_attr_recipe_trap mach trap. It covers the bug, the evolution of an exploitation technique which involves repeatedly in addition to deliberately crashing in addition to how to build alive meat introspection features using onetime meat exploits. It’s a trap! Alongside a large number of BSD syscalls (like ioctl, mmap, execve in addition to so on) XNU also has a pocket-sized number of extra syscalls supporting the MACH side of the meat called mach traps. Mach trap syscall numbers start at 0x1000000. Here’s a snippet from the syscall_sw.c file where the trap tabular array is defined: /* 12 */ MACH_TRAP(_kernelrpc_mach_vm_deallocate_trap, 3, 5, munge_wll), /* xiii */ MACH_TRAP(kern_invalid, 0, 0, NULL), /* xiv */ MACH_TRAP(_kernelrpc_mach_vm_protect_trap, 5, 7, munge_wllww), Most of the mach traps a

Lifting The (Hyper) Visor: Bypassing Samsung’S Real-Time Total Protection

Posted yesteryear Gal Beniamini, Traditionally, the operating system’s total is the concluding security boundary standing betwixt an assaulter together with total command over a target system. As such, additional aid must hold upwards taken inwards lodge to ensure the integrity of the kernel. First, when a organization boots, the integrity of its primal components, including that of the operating system’s kernel, must hold upwards verified. This is achieved on Android yesteryear the verified kicking chain . However, only booting an authenticated total is insufficient—what most maintaining the integrity of the total spell the organization is executing? Imagine a scenario where an assaulter is able to abide by together with exploit a vulnerability inwards the operating system’s kernel. Using such a vulnerability, the assaulter may endeavor to subvert the integrity of the total itself, either yesteryear modifying the contents of its code, or yesteryear introducing novel attacker-co

Chrome Bone Exploit: 1 Byte Overflow As Well As Symlinks

The next article is an invitee weblog post from an external researcher (i.e. the writer is non a or Google researcher). This post is most a Chrome OS exploit I reported to Chrome VRP inward September. The folks were squeamish to allow me do a invitee post most it, therefore hither goes. The study includes a detailed writeup , therefore this post volition have got less detail. 1 byte overflow inward a DNS library In Apr I constitute a TCP port listening on localhost inward Chrome OS. It was an HTTP proxy built into shill, the Chrome OS network manager. The proxy has at nowadays been removed equally component of a fix, but its source tin give notice nonetheless move seen from an one-time revision: shill/http_proxy.cc . The code is unproblematic in addition to doesn’t seem to incorporate whatever obvious exploitable bugs, although it is real liberal inward what it accepts equally incoming HTTP. It calls into the c-ares library for resolving DNS. There was a possible 1 byte ov