How Do We Prevent DLL Abuse?

How Do We Prevent DLL Abuse?

Old forum URL: forums.lhotka.net/forums/t/6906.aspx


xxxJasonxxx posted on Wednesday, May 06, 2009

HOW DO WE PREVENT DLL ABUSE?

We have a large ASP.NET web application we use to support several hundred franchises. We've been gradually re-writing the business logic using CSLA. Now that many of the core business objects are complete, we are considering converting the UI from ASP.NET to Windows forms (and using a remote data portal).

However, we are very concerned about our DLLs getting distributed to the franchises' client machines (installed along with the Windows UI). We've already experienced some abuse of our ASP.NET application by some 3rd party developers hired by a handful of our franchises. So we're confident that similar abuse would occur if we distribute DLLs....and we're speculating it could be much worse. Because of politics within the organization we are trying to address this abuse issue technically rather than legally.

Are there any techniques we can use to prevent someone from abusing the DLLs that would get distributed with our Windows app?

RockfordLhotka replied on Wednesday, May 06, 2009

That is very difficult.

You can use obfuscation, but you can't obfuscate public member names (like properties) because that breaks things like data binding and CSLA features like validation/business/authorization rules that drive off the property names. Anything that uses reflection against property names (again, like data binding) can't operate if the property names are randomized.

So obfuscation can protect your algorithmic code (to some degree), but can't stop someone from referencing and using your assembly - and I think that's what you are trying to avoid...

You might consider using Silverlight, as it is harder (maybe impossible?) for someone to create a separate application that interacts directly with the DLLs downloaded as part of a Silverlight application.

I suppose, though, that they could still use JavaScript from a hosting web page to interact with the Silverlight application. I think this is more limited than the arbitrary interaction that would be possible if a developer had direct access to a client-side .NET assembly.

xxxJasonxxx replied on Wednesday, May 06, 2009


Your response sparked another question...

(particularly the part about Silverlight, which I don't have any experience with)

By switching from a Web UI to a Windows UI, our goal was to provide our users with a more interactive UI that was also easier/faster for us to to develop and maintain.

Is there a different UI technology we should consider for achieving this goal?

RockfordLhotka replied on Wednesday, May 06, 2009

It is true that a smart client technology is a far cheaper way to give your users a more interactive UI. And the end result is more scalable than the web.

But the drawback, as you note, is that your assemblies end up on the client workstations and are more vulnerable to hacking.

Windows Forms is a fine technology, but it is nearing the end of its life.

WPF is a similar technology, at the start of its life.

Silverlight is somewhat similar, but today it only runs in the browser - and in any case runs in an isolated sandbox. This is why it may be a good option, as external code has no access to your assemblies, even though they are running on the client.

Without understanding the nature of the hacking threat it is hard to provide more insight. Security is all about threat and risk analysis - determining the attack scenarios, likelihood of attack, cost of successful attacks, cost of preventing each type of attack, etc. Based on that information you can make sound business decisions about what attacks to block or ignore.

xxxJasonxxx replied on Wednesday, May 06, 2009

Thanks Rocky! I appreciate the advice. I'll do some research on Silverlight and probably WPF too.

JoeFallon1 replied on Wednesday, May 06, 2009

RockfordLhotka:

Silverlight is somewhat similar, but today it only runs in the browser - and in any case runs in an isolated sandbox.




I thought that MS recently announced that Silverlight can be run outside the browser now making it a truly cross-platform environment. It would still be in a sandbox though. You might ask why not use WPF in that case? 1. WPF does not run on a Mac. 2. Easier to deploy the Silverlight run time.

Joe

RockfordLhotka replied on Wednesday, May 06, 2009

True, Silverlight 3 will run outside the browser.

But even in that case it is running in an isolated sandbox, so (to my
knowledge) no other Windows (or Mac) application can directly interact with
the assemblies.

If you use WPF to do the same thing, the assemblies are technically
accessible to other Windows applications - they just need to reference the
DLLs.

The only thing with WPF is that if you use ClickOnce, the assemblies are in
an obfuscated folder under each individual user's profile folder. And each
time a new version comes out the new version goes into a different
obfuscated folder. The result is that, while someone could use the
assemblies, they'd have to do some fixup work each time you release a new
version via ClickOnce - so it would be inconvenient anyway...

Rocky

JonnyBee replied on Wednesday, May 06, 2009

Conceptually - what you are looking for is the technique of Friend assemblies (follow the link)

A:
B:

Solution B will make sure at compiletime -  that only those given assemblies are allowed to see your "internal" methods/classes.

At least - no other developer outside your company will then have access to your Business layer.

Extract from MSDN:
"The StrongNameIdentityPermission class is used to define strong-name requirements for access to the public members of a type. The StrongNameIdentityPermissionAttribute attribute can be used to define strong-name requirements at the assembly level. In the .NET Framework version 2.0 and later versions, you can also use InternalsVisibleToAttribute to specify that all nonpublic types in that assembly are visible to another assembly. For more information, see Friend Assemblies (C# Programming Guide) or Friend Assemblies (Visual Basic). "

/jonnybee


xxxJasonxxx replied on Thursday, May 07, 2009

Wow....I wasn't aware of that functionality. At first glance, this appears to be exactly what we need. I'll play around with it and see how it works. Thanks!

tmg4340 replied on Thursday, May 07, 2009

One potential issue I can see with using this technique is that some of CSLA may stop working - specifically, parts of the Data Portal might not be able to work under this environment.  It's also possible that parts of the CSLA base classes could have some issues with this as well.

You might be able to get it to work by signing your CSLA assemblies with your key, and adding additional attributes for those assemblies.  But that could get pretty murky pretty quick.  Certainly worth trying, though.

- Scott

xxxJasonxxx replied on Tuesday, May 12, 2009


DOES ANYONE SEE ANY FLAWS IN THIS APPROACH?

1.) We sign our assembly with our company's strong name key.

2.) In all of our factory methods we call the "CanCallAssembly()" method shown below.

3.) If the "CanCallAssembly()" method returns False, we throw a security exception.

' - - - - - - - - - - - - - - - - - - - - - - - - - -

Public Shared Function CanCallAssembly() As Boolean

' Get the name of the calling assembly.
Dim callingAssembly As String = System.Reflection.Assembly.GetEntryAssembly.FullName

' Get the name of the assembly being called (this assembly).
Dim thisAssembly As String = System.Reflection.Assembly.GetCallingAssembly().FullName

' Get the public key for each assembly.
Dim tokenIndex1 As Integer = thisAssembly.LastIndexOf("PublicKey")
Dim tokenIndex2 As Integer = callingAssembly.LastIndexOf("PublicKey")
Dim testString1 As String = thisAssembly.Substring(tokenIndex1, 31)
Dim testString2 As String = callingAssembly.Substring(tokenIndex2, 31)

' Do the public keys match?
Return testString1.Equals(testString2)

End Function

ajj3085 replied on Tuesday, May 12, 2009

Wouldn't someone be able to decompile and remove the check? Strong naming doesn't help against that.

I think you're in a crunch here.. the only way to be sure would be to expose your application as a web service, and give assemblies that business units can use for rich interactivy... but ultimately the DataPortal_YX calls send out to a web service where the same rules are run.

xxxJasonxxx replied on Tuesday, May 12, 2009

Good thought!

What if we ran our stuff through an obfuscation tool, like PreEmptive Solutions Dotfuscator, to prevent someone from decompiling and altering our code.....then would we be in good shape?

tmg4340 replied on Tuesday, May 12, 2009

You can only obfuscate so much and still have CSLA work. The reflection (and some other advanced .NET techniques) used in CSLA will fail on obfuscated assemblies, depending on the techniques used. Rocky has touched on that in previous posts, so a forum search should give you the particulars.

There have been many discussions on this forum regarding this issue. It's a salient issue in .NET, and not one that's easily dealt with. You can NGEN your assemblies to native code, but that pretty much has to be done on the client machine, and it requires that the original IL assemblies be present, so that doesn't really buy you much. You can obfuscate - but again, only so far if you still want CSLA to work. Using strong naming and some .NET CAS attributes will help, but you'd probably have to propagate much of that throughout CSLA to have all of it work - assuming it does. I have no reason to think it won't, but I've never tried it. You could investigate some sort of licensing scheme, but that's not foolproof either.

Ultimately, as Justin has mentioned, you have no real way to guarantee that a third party won't crack your code base - unless you don't give it to them. Hide your business logic behind a web service, don't trust any calls that come in through the web service, and deal with the consequences of the type of application you have to build under those parameters.

In the end, it's a risk/reward analysis. How much work do you want to go through to mitigate your risk? How much do you want to alter how your application works to make sure some untoward individual doesn't do something they shouldn't? If it really is that important to keep prying eyes out, you don't have a lot of options other than denying them the code base to begin with.

- Scott

ajj3085 replied on Wednesday, May 13, 2009

Just to add what the others have said about obfuscation... even if you could obfuscate everything, it will only slow the determined party down, it won't stop them. So you need to figure out the risk / reward.

Now, if you decide you can't trust the client, that means you'll be building two applications. A web service, with Csla business objects behind it to run your validation / auth rules, and the API client you give to your customers.. which run the same rules. You might be able to figure out a way to do something similar to Csla Silverlight development, where you have some compiler directives to keep most of the code the same, but swap out the data portal code. (The client's DP_XYS would call your web service.. your web service business layer would have DP_XYZ that actually does the update)

Justin replied on Tuesday, May 12, 2009

What kind of abuse are you trying to prevent?

We have found that no matter you architecture, it's very difficult to prevent this sort of thing.

We finally decided to embrace it, we made a well documented soap API and support customer or third parties using it. Any "abuse" is considered our responsibility and we try enforce things better in the server API to prevent the abuse rather than obfuscating the client.

Basically it's a never trust the client approach as the client may be ours or coded by some third party who has no idea what they are doing or are even malicious.

Copyright (c) Marimer LLC