.NET Forum / .NET Framework / Security / November 2004
Signed assemblies easily cracked?
|
|
Thread rating:  |
jc - 09 Nov 2004 17:11 GMT If strong name keys are so easily broken as shown in this article: http://www.codeproject.com/dotnet/NeCoder03.asp
Is there really no security possible with .net assemblies in the end?
Anyone could modify any .net based application if they have access to the assemblies.
I'd be curious to know the assessment of people here as I'm no expert on this subject but am very reliant on it as a shareware author moving to .net.
We previously thought obfuscation and strong names would be enough for implementing a non-obscure licensing scheme, but the above article shows that is not really the case.
Any thoughts would be greatly appreciated.
Nicole Calinoiu - 09 Nov 2004 18:28 GMT > If strong name keys are so easily broken as shown in this article: > http://www.codeproject.com/dotnet/NeCoder03.asp In the article, the strong name is not "broken", it's removed. The strong name mechanism would be broken only if one could tamper with the assembly contents while conserving the strong name signature.
> Is there really no security possible with .net assemblies in the end? Yes, but perhaps not the kind of security that you might prefer.
> Anyone could modify any .net based application if they have access to the > assemblies. Yup.
> I'd be curious to know the assessment of people here as I'm no expert on > this subject but am [quoted text clipped - 3 lines] > implementing a non-obscure licensing scheme, but the above article shows > that is not really the case. The security enhancements in the .NET Framework are meant to protect end users, not software authors. For example, strong naming makes it more difficult to tamper with library assemblies that have already been installed on a user's machine. However, it does nothing to prevent another developer from decompiling your code, modifying it in any way he might like, then recompiling it and distributing it as if it were his own code. He will, however, be unable to make it look like your code via a full strong name signature (unless you lose control of your private key or he manages to crack the private key).
In addition, since you've mentioned using strong names to enforce licensing constraints, you should know that there are ways to circumvent certain types of strong name checks without tampering an assembly.
That said, the failure of strong names to offer the protection you might have liked doesn't mean that obfuscation is useless. Thorough obfuscation of an assembly can be a reasonably effective barrier against misuse, particularly if it can render the perceived effort of reverse engineering greater than the perceived effort of reproducing the functionality from scratch.
> Any thoughts would be greatly appreciated. Frank Wallwitz - 18 Nov 2004 14:31 GMT Hi Nicole,
> > If strong name keys are so easily broken as shown in this article: > > http://www.codeproject.com/dotnet/NeCoder03.asp > > In the article, the strong name is not "broken", it's removed. The strong > name mechanism would be broken only if one could tamper with the assembly > contents while conserving the strong name signature. This can be also done easily: send me a strong named assembly called by another (strong named) assembly. It takes 1 minute to tamper the assembly, leaving the strong name signature untouched. You'll find that your calling assembly still recognizes the tampered as a 'good one'. The point is that the mechanism, responsible for sn signature check can be disabled by changing one byte :(((
Stop to think about strong names as a security mechanism.
Frank
Rahul Kumar - 19 Nov 2004 11:16 GMT > This can be also done easily: send me a strong named assembly called by > another (strong named) assembly. It takes 1 minute to tamper the assembly, [quoted text clipped - 6 lines] > > Frank Hi Frank
Could you share with us, how do you do that in a bit more details please?
 Signature Rahul Kumar http://dotnetyogi.blogspot.com This message is provided "AS IS" with no warranties, and confers no rights. Any opinions or policies stated within it are my own and do not necessarily constitute those of my employer.
Frank Wallwitz - 19 Nov 2004 17:56 GMT Hi Rahul,
> > This can be also done easily: send me a strong named assembly called by > > another (strong named) assembly. It takes 1 minute to tamper the assembly, [quoted text clipped - 5 lines] > > Could you share with us, how do you do that in a bit more details please? Of course I can:
inspecting the structure of .NET assemblies I found, that a strong name signed .NET assembly can be altered this way, that the byte, describing a proerty of the RSA key is set to 00hex (please understand that I do not describe the method more detailed in a public forum). From this moment the FRAMEWORK stops to recognize the assembly as a strong named, so it can be altered as much as we want. The framework will load the assembly without any problems. Remember: we didnt changed the public key or public key token. On the other hand the calling assembly still recognises the tampered by comparing the (unmodified) public key token with public key token compiled into it. And as far as the framework hasn't prevented the loading of the tampered assembly we're done :(
There are a lot of possible scenarios for using this method: from simple patching strong named assemblies to replacing the original assembly by a self-written (with the same interface) with the original public key entered after compiling with a hex editor (thats possible - try it out).
Frank
Rahul Kumar - 22 Nov 2004 16:24 GMT Hi Frank
That sounds interesting. However, what you have demostrated could be a bug in the CLR (may be known to Microsoft) and may be it would be fixed in the next version on the Framework. However I would expect the Gurus like Valery to comment on this.
Regards
 Signature Rahul Kumar http://dotnetyogi.blogspot.com This message is provided "AS IS" with no warranties, and confers no rights. Any opinions or policies stated within it are my own and do not necessarily constitute those of my employer.
> Hi Rahul, > [quoted text clipped - 31 lines] > > Frank Frank Wallwitz - 22 Nov 2004 17:38 GMT Hi Rahul,
> Hi Frank > > That sounds interesting. However, what you have demostrated could be a bug > in the CLR (may be known to Microsoft) and may be it would be fixed in the > next version on the Framework. However I would expect the Gurus like Valery > to comment on this.
> > inspecting the structure of .NET assemblies I found, that a strong name > > signed .NET assembly can be altered this way, that the byte, describing a [quoted text clipped - 14 lines] > entered > > after compiling with a hex editor (thats possible - try it out). I would not call it a bug. It's simply the way Microsoft has implemented the verification of sn-signed assemblies. In the end, there must be a flag, or some code somewhere inside the assembly telling the framework that it is strong named or whatever. Implementing this 'cracker-proof' is very hard (if not impossible). The problem is that an application in fact can't trust while loading a sn assembly, that it is the expected.
As I wrote in my first statement: strong names aren't a method for making your code secure and the are not intended to do this. The intention was to make sure, that only well-known, 'trusted' assemblies can load each other.
From my point of view that's not longer true :(
regards Frank
Rahul Kumar - 23 Nov 2004 08:47 GMT Thanks Frank! I can hear the alarm bells ringing!
Regards,
Rahul Kumar http://dotnetyogi.blogspot.com This message is provided "AS IS" with no warranties, and confers no rights. Any opinions or policies stated within it are my own and do not necessarily constitute those of my employer.
> Hi Rahul, > [quoted text clipped - 46 lines] > regards > Frank Nicole Calinoiu - 25 Nov 2004 17:15 GMT > I would not call it a bug. Interesting. The documentation on strong name use by the .NET Framework would strongly suggest that at least one somebody at Microsoft might disagree with you on this one. (See, for example, http://msdn.microsoft.com/library/en-us/cpguide/html/cpconstrong-namedassemblies.asp.)
> It's simply the way Microsoft has implemented the > verification of sn-signed assemblies. Obviously, but just because it shipped this way doesn't mean it's not a bug in either design or implementation.
> In the end, there must be a flag, or some code somewhere inside the > assembly > telling the framework that it is strong named or whatever. It doesn't have to be a separate flag. The presence of the strong name signature in a reserved position should be a sufficient, self-contained flag for the validation.
> Implementing this > 'cracker-proof' is very hard (if not impossible). Sure, but it could be a lot more robust than allowing a flag byte to disable validation.
> The problem is that an application in fact can't trust while loading a sn > assembly, that it is the expected. Expected by whom? Probably not by folks who've read the documentation on the framework's use of strong names for assembly validation.
> As I wrote in my first statement: strong names aren't a method for making > your code secure and the are not intended to do this. Nope, but they are expected to help protect users from manipulation or substitution of highly trusted assemblies.
> The intention was to make sure, that only well-known, 'trusted' assemblies > can load each other. The documentation would suggest that the main goal was to provide a mechanism to prevent execution of assemblies modified by anyone other than their legitimate author.
> From my point of view that's not longer true :( Do we have any evidence that it was ever true, or has the switch byte been active in all shipped versions of the .NET Framework?
> regards > Frank Valery Pryamikov - 23 Nov 2004 11:28 GMT Thanks Rahul :-).
It's difficult to tell what Frank is actually doing with the assembly (not enough information) however, it is either removing of the strong name or disabling verification of strong name. In any case it should not come up as surprise - both things are achievable and if you check ECMA partition II metadata spec. that describes referencing external assemblies you'll find that conforming CLI need not verify assembly signature when loading linked assemblies (ie. it is optional for CLI implementation to do such validation). It's just it - strong names are good for versioning, but all they (may be with exception to ECMA key) are not security related.
-Valery. http://www.harper.no/valery
> Hi Frank > [quoted text clipped - 47 lines] >> >> Frank Rahul Kumar - 23 Nov 2004 15:46 GMT Thanks Valery and Frank for your wise words. Much appreciated!
 Signature Rahul Kumar http://dotnetyogi.blogspot.com This message is provided "AS IS" with no warranties, and confers no rights. Any opinions or policies stated within it are my own and do not necessarily constitute those of my employer.
> Thanks Rahul :-). > [quoted text clipped - 63 lines] > >> > >> Frank Nicole Calinoiu - 25 Nov 2004 17:22 GMT > Thanks Rahul :-). > > It's difficult to tell what Frank is actually doing with the assembly (not > enough information) however, it is either removing of the strong name or > disabling verification of strong name. Unfortunately, neither of those statements is quite true. His explanation was quite clear, and it only took me a few minutes to find the switch byte he described.
> In any case it should not come up as surprise - both things are achievable > and if you check ECMA partition II metadata spec. that describes > referencing external assemblies you'll find that conforming CLI need not > verify assembly signature when loading linked assemblies (ie. it is > optional for CLI implementation to do such validation). Personally, I'm surprised. While the standard doesn't require validation against a strong name signature, the documentation for the Microsoft implementations states quite clearly that it should not be possible to load a tampered strongly named assembly in these implementations.
> It's just it - strong names are good for versioning, but all they (may be > with exception to ECMA key) are not security related. Well, the docs for the Microsoft .NET Framework sure do make strong name signature verification sound at least in part like a security measure. If you've seen any documentation that would suggest that Microsoft no longer sees things this way, might you perhaps be able to share a reference with the rest of us?
> -Valery. > http://www.harper.no/valery [quoted text clipped - 54 lines] >>> >>> Frank Valery Pryamikov - 25 Nov 2004 19:38 GMT Well, Nicole, you may agree or disagree with me - it's up to you, but that's just it - strong names is not security related thingies, but only usefull for versioning purposes. I've already wrote more than enough about that matter in newsgroups and in my blog. If you interesting to argue it any further - please, read what I've written earlier and argue to that.
-Valery. http://www.harper.no/valery
>> Thanks Rahul :-). >> [quoted text clipped - 92 lines] >>>> >>>> Frank Nicole Calinoiu - 25 Nov 2004 19:55 GMT Valery,
I've read your postings on strong names, but I don't recall seeing anything on this particular aspect of their use. If I've missed something, please provide a link. Also, if you have a Microsoft reference that would suggest that such a trivial bypass of strong name verification should be allowed by an untampered .NET Framework, that would be helpful. Otherwise, we're just arguing opinions since, AFAIK, neither of us was involved in setting the spec...
Nicole
> Well, Nicole, > you may agree or disagree with me - it's up to you, but that's just it - [quoted text clipped - 105 lines] >>>>> >>>>> Frank Valery Pryamikov - 25 Nov 2004 20:15 GMT Nicole, I provided you a link in my post. Just navigate to my blog and search it for strong names. Additionally, it would not take more than one minute to search google groups for my name + strong names for getting references from groups.
-Valery. http://www.harper.no/valery
> Valery, > [quoted text clipped - 119 lines] >>>>>> >>>>>> Frank Nicole Calinoiu - 26 Nov 2004 12:10 GMT Valery,
I've checked again, but found nothing new. Please understand that I don't disagree with you regarding the various weaknesses of strong name signatures. However, neither of our opinions regarding either the overall signature mechanism or its implementation details are really relevant here. What does matter is how strong name verification is intended to behave. The official Microsoft documentation on their CLI implementation makes some pretty unambiguous statements regarding the supposed tamper-proofing role of strong name signatures. For example, take the following statement from http://msdn.microsoft.com/library/en-us/cpguide/html/cpconstrong-namedassemblies.asp:
"Strong names provide a strong integrity check. Passing the .NET Framework security checks guarantees that the contents of the assembly have not been changed since it was built."
Allowing a potential attacker to force verification skipping by making additional changes to an assembly flies in the face of the above stated purpose. In addition, if recognition of the switch byte was included in the shipped production framework intentionally, why bother introducing the "official" verification skipping mechanism when it's so much simpler to just instruct folks to zero out a byte in their delay signed assemblies? (Please don't infer from this that I think support for any verification skipping is a good idea since I most definitely don't.)
Again, I agree with you that Authenticode signing would have been a more robust choice. However, that's not how Microsoft chose to implement integrity checks (presumably because they need to cater to students and hobbyists as much as to CIOs). Given the ease of decompiling IL and determining how to meaningfully tamper with assemblies, it's unlikely that many organizations would allow managed code on their machines if some integrity check mechanism were not in place (or at least not if they consider the issue seriously <g>). The mechanism we've got is strong name verification, not Authenticode signature verification. If strong name verification has weaknesses that are even worse than those incorporated by design, many customers are likely to be very unhappy...
Nicole
> Nicole, > I provided you a link in my post. Just navigate to my blog and search it [quoted text clipped - 128 lines] >>>>>>> >>>>>>> Frank Valery Pryamikov - 26 Nov 2004 14:25 GMT Nicole,
In one of my blog articles I pointed place in ECMA CLI Sec. regarding optionality of verification of the strong name during assembly loading. Here it is again:
ECMA partition II metadata spec 6.3 Referencing Assemblies states following:
"
An assembly reference can store either a full public key or an 8 byte "publickeytoken." Either can be used to validate that the same private key used to sign the assembly at compile time signed the assembly used at runtime.
A conforming implementation of the CLI need not perform this validation, but it is permitted to do so, and it may refuse to load an assembly for which the validation fails...
"
Next is that ECMA spec explicitly states that public key token and public key could be referred interchangeably whenever assembly is referring strong named assembly. Public key token is top 64bits of SHA1 hash of the public key. In reality - current implementation of CLR always use public key token (which can be easily verified with ILDASM). SHA1 is 160 bits, but public key token is 64 bit. Due to birthday paradox - only 2^32 public keys need to be tried before finding a pair of colliding of public key token (different public key/key pair, but the same public key token). If your assembly is referred by public key token and we find colliding public/private keys pair - than resigning assembly with colliding key pair will be considered as valid signature by CLR verification when it loads linked assembly! 2^32 is a very little number for today's computing power. And search procedure for keys producing colliding public key token could be easily parallelized. Means that if I, for example, write such parallelized search routine for searching colliding public key tokens and publish reference to it on Slashdot - it will be a lots of volunteers to participate in demonstration of weakness of Microsoft .Net strong names validation procedure - I even can bet on it! To see how realistic such task of finding colliding public key token consider following algorithm:
1.. define multiple segments of counter that we will use for prime generation and assign 64 bit IV to each segment (could be just sequential numbers); total number of segments should be calculated by dividing 2^32 by amount of key lookup per segment (2^20 keys per segment is quite reasonable size - would require 2^26 ~ 65MB ~ of hard disk storage available for storing intermediate results). 2.. each computer takes one or more segment for calculation and reporting results back to central storage. 3.. use sligthly modified DSA small prime generation procedure to generate our big primes (of size 512 bits) with segment IV as IV, sequential counter and low security parameter (f.e. 2 will be more than enough for our purpose) for better performance (even SHA1 could be replaced by the faster hash algorithm such as MD5 or even MD4). 4.. after finding two primes - calculate SHA1 hash of ASN1 public key blob (p*q) as modulus and 0x10001 as public exponent and store first 8 bytes in intermediate report file. Most time consuming task would be step 3. We would have to try in average 100-130 numbers before we got both primes (according to upper bounds of random search algorithm that should also apply in our case if believed characteristics of SHA1 is hold). If we use only 2 as security parameter (one time trial division by small prime base and one Rabin-Miller test base 2 and one Rabin-Millar test on random base) because we can afford about 2^(-54) probability of false positive but we will benefit from better performance by not doing 3 other Rabin-Miller test random base. On normal nowadays computer with Intel Pentium 2.5 GHz or better CPU (or correspondent AMD CPU) it should take from one to two days to go through the segment. So we only need 2048 participating computers to run for a couple of days to find collision of public key token. After that we take first key from that has colliding public key token and sing assembly with it, link it to another assembly and distribute result to third computer (with adjusting security policy for allowing extra rights). After that, linked assembly is modified, resigned with second key from colliding public key token and redistributed on target computer. Since public key token in modified assembly with be the same as in .assembly extern - all load time validation will succeed! That's it. And believe me that way too many Linux and Java enthusiasts will participate in that kind of experiment given sufficient publicity, so it would not be any problem to get help from 2048 computer for couple of days and its quite possible that someone may even throw in much bigger horsepowers from university nets...
Note: CLI spec doesn't put any security on strong names (except for ECMA key wich is VERY DIFFERENT then the rest of strong keys) and that's due to some good reasons...
-Valery.
http://www.harper.no/valery
> Valery, > [quoted text clipped - 169 lines] >>>>>>>> >>>>>>>> Frank Nicole Calinoiu - 27 Nov 2004 13:31 GMT > In one of my blog articles I pointed place in ECMA CLI Sec. regarding > optionality of verification of the strong name during assembly loading. Yes, and in my first response to you in this thread, I commented on the optionality. Basically, the documentation for the .NET Framework would indicate that Microsoft chose to actually implement this optional requirement from the spec when they built the .NET Framework. The optionality of the requirement in the original spec does not excuse poor execution of the requirement once they chose to implement it.
> SHA1 is 160 bits, but public key token is 64 bit. Due to birthday > paradox... <snip>
> ...it would not be any problem to get help from 2048 computer for couple > of days and its quite possible that someone may even throw in much bigger > horsepowers from university nets... I guess you missed the part of my last message where I stated that I actually agreed with your evaluation of the weaknesses in the strong naming mechanism. However, I stand by my opinion that inclusion of some tamper-proofing mechanism is probably important to many Microsoft clients. The Microsoft documentation states that strong naming provides certain protections in this regard, and Microsoft clients should be able to count on this documented level of protection being in effect, regardless of whether you or I consider the mechanism to be wimpy and/or flawed by design.
> Note: CLI spec doesn't put any security on strong names (except for ECMA > key wich is VERY DIFFERENT then the rest of strong keys) and that's due to > some good reasons... Interesting... The following extract is from section 6.2.1.3:
"At runtime, the information contained in the assembly reference can be combined with the information from the manifest of the assembly located at runtime to ensure that the same private key was used to create both the assembly seen when the reference was created (compile time) and when it is resolved (runtime)."
That "ensure" is a pretty strong verb to use, and it sure does sound to me like the authors were making a statement about verification of assembly identity.
However, that's still not particularly relevant. What is far more relevant is the promises Microsoft has made to its customers regarding the behaviour of the .NET Framework, which is a product, not a spec. If it were another vendor that had delivered an implementation of the CLI that promised strong name verification but allowed a zeroed byte in a tampered assembly to bypass this validation, we would probably be discussing whether it was a stupid mistake or an intentional and potentially malicious inclusion of a back door...
> -Valery. > [quoted text clipped - 177 lines] >>>>>>>>> >>>>>>>>> Frank Valery Pryamikov - 27 Nov 2004 15:35 GMT You know Nicole, frankly, I don't have any slightest wish to continue that conversation any further. You just keep your opinion - fine for me. I've already explained my opinion about strong names. And people can draw their own concusions. I added single comment (below) about my understanding of the exceprt you added to your last post. but this will be my last post to that thread. You can add whatever you want to that - it's entirely up to you, but don't expect my response - I've killfiled this thread.
> Interesting... The following extract is from section 6.2.1.3: > [quoted text clipped - 7 lines] > like the authors were making a statement about verification of assembly > identity. Well, that "ensure" stays right after "reference can be ..." which I understand as "in case if reference is in fact combined ... it can be used to ensure ...". Anyhow, english is my third language that makes me not quite qualified to argue with you the meaning of that quotation from CLI spec, but frankly - I don't even care...
-Valery. http://www.harper.no/valery
Nicole Calinoiu - 25 Nov 2004 16:42 GMT <snipped>
> please understand that I do not > describe the method more detailed in a public forum With your hints, it took me under 5 minutes to identify the switch byte. Do you really think that a potential abuser of the switch is likely to fare any worse?
Rob Teixeira - 09 Nov 2004 21:34 GMT The strong name was not broken, and the signature was not cracked, as you are implying. The strong name was stripped out completely. The app only worked in this case because it was running from a full-trust environment. If policies were in place to grant execution rights based on the key (such as is the case with smart clients) then this would not have worked at all. In fact, any CAS or machine policy granted to the key would break because the key is *completely missing*.
But you also have to look at a few other aspects. Strong naming is meant to keep malicious code from screwing users (thus the policy stuff). It's not meant to protect the contents (code) of the assembly from being pirated. If that's your goal, you NEED a REAL licensing scheme. If your income depends on this, then I highly suggest buying a reputable licensing solution. But to be honest, NOBODY has ever created a successful scheme if the software is completely installed on the user's machine. I remember back in the 80s and 90s, Autodesk (then Kinetix now Discreet) used to sell software that ranged in the mid-thousands of dollars (CAD and 3D Studios, for example). They tried everything under the sun, including requiring a hardware parallel port dongle that authenticated the app. But no matter what they did, there was always a crack just a few months after each version was released. The more in-demand your app is, and the more expensive it is, the bigger a target it becomes for this sort of thing.
-Rob Teixeira
> If strong name keys are so easily broken as shown in this article: > http://www.codeproject.com/dotnet/NeCoder03.asp [quoted text clipped - 13 lines] > > Any thoughts would be greatly appreciated. jc - 10 Nov 2004 17:01 GMT If Microsoft truly want's people to adopt their technologies and develop for it they've got to spend at least an ounce of effort on something that will protect the *author's* rights.
Computer society has swung so far to the rights of the end users at the expense of the authors that it's getting ridiculous. Yes I know any system can be hacked, it's a matter of degrees.
The two foremost .net licensing solutions (Xheo and DesaWare) both depend heavily on the strong name for protection, I emailed Xheo about this and they replied that it *is* a huge vulnerability so other than the convenience of not having to write it ourselves and the slim possibility that it's more secure that what we can come up with, it really makes little difference if you pay for expensive licensing solutions or not, they are easily hacked down the road.
Seems like we are back to relying on the good intentions of the populace once again if we write .net based commercial apps.
This is such a fundamental problem from a commercial authors point of view and there is so little discussion of it seemingly in any .net related newsgroup or website that I'm starting to wonder if .net is yet to surpass hobbyist status.
- John
> The strong name was not broken, and the signature was not cracked, as you > are implying. [quoted text clipped - 47 lines] >> >> Any thoughts would be greatly appreciated. Nicole Calinoiu - 10 Nov 2004 20:22 GMT Personally, I agree that there hasn't been enough focus on protecting software authors, but I haven't found Microsoft folks to be terribly receptive so far. What I find potentially even worse than the ease of abuse of authors' intended protections or the documentation errors and omissions surrounding this issue is the fact that an abuser could most likely get help from PSS. "Hi, I'm having some trouble trying to call a private method via reflection..."
> If Microsoft truly want's people to adopt their technologies and develop > for it they've got to spend at least an ounce of effort on something that [quoted text clipped - 77 lines] >>> >>> Any thoughts would be greatly appreciated. Eugene Mayevski - 10 Nov 2004 21:07 GMT Hello! You wrote on Wed, 10 Nov 2004 09:01:24 -0800:
j> If Microsoft truly want's people to adopt their technologies and develop j> for it they've got to spend at least an ounce of effort on something j> that will protect the *author's* rights.
Hmm? Why would Microsoft spend resources with helping to protect somebody's rights? They are not a charity organization, but a business. They offer a business model and you are free to use it or leave it. .NET was developed for Web Services (anybody knows where they are now?), where main part of the application resides elsewhere, but not on client computer. You can't blame an F1 car for inability to go through the swamp or forest, can you? The same is with .NET. If you want good protection, use plain Win32 or some unmanaged blocks (and put the protection to that blocks).
With best regards, Eugene Mayevski
Free MagazinesGet these publications absolutely FREE for up to 12 months. There are no hidden fees and no obligation. Simply choose a title, complete the application form and submit it. Read more ...
|
|
|