Weblog
More weekend hacking
|
So I started adding a Gtk# GUI on top of my previous Cecil / Dot graph hacks (see here and here to see them). Nothing extraordinary about it, in fact nothing interesting enough to show yet ;-) Actually most of my weekend hacking wasn't GUI related at all. Most of it has gone into refactoring the existing source code to reduce duplication (as they all evolved from the same code base, the new permview.exe tool) and to move the different tools into plugins. Plugins are often overrated, and overused, but in this case I know some of them requires quite a lot of memory (e.g. finding all public callers) and many planned (i.e. in a dark corner of my mind) plugins will too have high memory requirements. How much ? well probably more than I have right now, so there's no point having all plugins around at the same time unless necessary (or for a limited number of assemblies). To make this easier the tool operates on working sets which are simply a list of assemblies
and a list of plugins (with their options) to load. So it's possible to work with few assemblies
(e.g. I also did some low-level class to help generating dot files and couldn't resist trying them off for a new kind of graph (funnier than refactoring the existing ones :-). This graph shows the dependencies between assemblies, in this case the Mono.Security.dll dependencies. The graph shows all assemblies referenced by From a security point of view the graph adds two major informations.
And, of course, being both red (unsafe) and accessible from partially trusted callers is far more risky than only one of them could be. Like the previous graphs assembly dependencies can get very ugly. In fact the worst cases I've seen
is for data providers.
They have a lot of dependencies themselves (and some even have unmanaged dependencies not
show in the graphs) and they often links to |
![]() |
4/25/2005 18:35:58 | Comments | Permalink
Mono Security Manager Part V - InheritanceDemand
Another new feature of
Mono 1.1.5
was the support of InheritanceDemand. Inheritance demands very are similar
linkdemands
but easier to understand (mostly because it has less special cases to consider).
Just like linkdemands, inheritance demands do not happen at runtime. Instead they occurs at load time, i.e. in the processing that follows the loading of an assembly by the CLR. This means that, just like linkdemands, imperative inheritance demand do not exists. Inheritance demands are evaluated in two different places during at load time, depending on where the security attributes were applied [1].
Class and Interface
Inheritance demand are used to limit extensibility, via inheritance (hence the name), of classes. A class that wants to inherit from another class must pass the security checks defined by the base class. The same checks can also be required before a class can implement an interface.
This is much finer grained than using the boolean sealed modifier
(which would be applicable to all code). For example the abstract class
System.IO.FileSystemInfo in assembly mscorlib.dll can only be
inherited by code coming from a fully trusted assembly (i.e. FullTrust).
Method (and the likes)
Something similar also occurs for methods, properties, events... Inheritance demands on a methods controls if a method can override the virtual/abstract method defined in the base class. Methods defined in an interface can also be protected.
Like linkdemands, there are many fun things to do with inheritance demands, e.g. you could allow a class to inherit yours only from noon to midnight on weekdays. But, honestly, inheritance demands are almost always used with code identity permissions (e.g. strongnames, publisher, hash, zone, url...). Which also means that their uses will a little more limited with the CLR 2.0 (more on that another time).
Finally it's kind of hard to catch a SecurityException thrown by an
inheritance demand as it is done for all class/methods at load time. So you must
catch them when loading an assembly - which most people prefer not to do manually.
This also makes them harder to test using NUnit :-(
[1] Actually you can apply inheritance demands (and other SecurityAction)
almost anywhere. This is because the restrictions for applying security attributes are
the same as for normal attributes - i.e. it is controlled by the
Attribute class and not by the SecurityAction. However
applying security attributes doesn't mean the CLR will evaluate them.
This would make an interesting rule to create (using
Cecil
of course ;-) in an FxCop style tool.
4/21/2005 19:30:48 | Comments | Permalink
More Cecil/Dot graphs
I did more Cecil/Dot hacking this weekend. The previous graphs has given me good ideas of how some user code could exploit some critical methods. It even shows some of the security checks, the declarative security attributes, on the methods (called before entering the method). But this picture is missing a lot of details, like any security checks done inside the methods (i.e. the imperative security checks).
|
A good example is when access to a file or an environment variable is required.
The name of the resource isn't known until runtime (at least from the framework point of view) so declarative security cannot be used.
This graphic shows the calls made to Note #1: The graphic shows public types/methods in blue. Bold is used on static methods. Note #2: Actually the previous graphic also show another problem. The static constructor (.cctor) of the
Ok, Back to the main issue... we expect to see a CAS permission demand in
| ![]() |
Note #3: Extracting the IL code with Cecil is very simple. See Jean-Baptiste Evain's sample code.
So this time I wanted to add graphs of the IL code, i.e. generate dot files from the previous IL. This is very similar to what other people have been doing. However my version as some security enhancements (well that's the whole point of it ;-). For example I mark some calls to the security runtime in red and display interal calls with "double lines". It's simple but effective as it makes it easy to see if (and where) some code can bypass a security check inside a method.
Now looking at the same IL code as a colored graph makes it perfectly clear.
If the security manager is enabled (first red box) then an EnvironmentPermission
instance is created with the variable name and a Demand (second red box) is made prior to returning
the value.
My only problem is that dot-ing IL can generate very big bitmaps (this one being small). They compress well on disk but their RAM requirements can be very high to display. I'll need to look at dot's options to see if I can squeeze them a little without loosing readability.
I still have many ideas to visualize code using Cecil and Dot but I think it's about time I put some Gtk# GUI on top of this...
4/18/2005 11:09:30 | Comments | Permalink
Mono Security Manager Part IV - LinkDemand
It took me some time to blog about them but a lot of new CAS features have been added in Mono 1.1.5. You can keep an eye on the CAS status page for more frequent updates on any new feature.
One of the new features is support for LinkDemand. LinkDemands are very similar to demands (which are sometimes called "full demands" when compared to linkdemands). The main difference is that linkdemand are executed at JIT time (instead of at run time). If you google about them you'll see that many articles and books will stop their description right there, while some will give more details (e.g. "it's less secure") without explaining why.
First methods are JITed only once (well that's true for the current versions of Mono but even with dynamic re-compilation the method won't be recompiled at every execution). Evaluating the stack at this time would be pointless. E.g.
JITing CallSomethingCritical when being called from DoSomethingSafe
would results in a different decision (stack wise) from JITing it from DoSomethingEvil.
So instead of a stack walk (or the often mis-described one frame stack walk) we reverse the problem
like this:
When JITing DoSomethingSafe we ask ourself if we have the permission to link
to CallSomethingCritical. The same thing happens when we JIT DoSomethingEvil
(hopefully with a different decision). Now the name LinkDemand make a little more sense :-).
The problem with reversing is that we loose the context of the call (actually there isn't much, security wise, at JIT time anyway). This is why this is (truely) less secure than a full demand. But linkdemands make sense when you use them properly (and not as a cheap version of full demands). Want a trick ? when in doubt use full demands ;-).
Another difference is that linkdemands can only be made declaratively by the programmer (or in a few special case by the CLR itself). No big lose since imperative link demand wouldn't make any sense at JIT time.
Special cases
There are a few special cases with linkdemands that requires more details:
- Internal calls are protected by the CLR with something similar to linkdemands. I say similar because it's doesn't quite follow the same rules (you probably guessed that a stack walk wasn't needed/done for icalls). Actually 1.x and 2.0 CLR seems to use different rules about them too. Let's just assume that internal calls aren't made to be called outside a few trusted assemblies (e.g. by any application code) and you'll be safe in the future.
- Some assemblies aren't designed to be executed under partial trust. In fact all strongnamed
assemblies are considered, by default, unsafe for partial trust. The CLR enforce this by adding a
LinkDemand for
FullTruston every publicly accessible (public and protected) methods on all publicly available classes in a assembly - unless the assembly is marked as safe by including the AllowPartiallyTrustedCallers attribute. - Reflection is cool but mess up the caller logic used by linkdemands. This is because the caller is always some code inside corlib (which is fully trusted). This would results in every linkdemand being granted when using reflection (it's not as bad as it sounds as reflection should only be granted to trusted code IMHO). Anyway the fix to this problem is to turn the linkdemand into a full demand. However this isn't not a perfect fix as the demand has far more chance to fail this way (when evaluating all the other frames in the stack).
There is another special case related to unmanaged code that I'll keep for a further entry...
4/15/2005 15:42:02 | Comments | Permalink
The views expressed on this website/weblog are mine alone and do not necessarily reflect the views of my employer.


