Figure 1 IPrincipal and IIdentity namespace System.Security.Principal {
interface IPrincipal {
IIDentity Identity { get; }
bool IsInRole(string role);
}
interface IIdentity {
bool IsAuthenticated { get; }
string AuthenticationType { get; }
string name { get; }
}
}
Figure 2 Imperative Role Check void Withdraw(double amount) {
if (amount <= REASONABLE_AMOUNT) {
// any teller can do this
// ...
}
else {
IPrincipal p = Thread.CurrentPrincipal;
if (!p.IsInRole("Supervisors")) {
string msg = "A supervisor must agree " +
"to this withdrawal";
throw new SecurityException(msg);
}
// only supervisors can do this
// ...
}
}
Figure 3 App::foo .method private hidebysig static void StartTheMachinery() cil managed
{
.permissionset noncasdemand =
(3C 00 50 00 65 00 72 00 6D 00 69 00 73 00 73 00 // <.P.e.r.m.i.s.s.
69 00 6F 00 6E 00 53 00 65 00 74 00 20 00 63 00 // i.o.n.S.e.t. .c.
6C 00 61 00 73 00 73 00 3D 00 22 00 53 00 79 00 // l.a.s.s.=.".S.y.
73 00 74 00 65 00 6D 00 2E 00 53 00 65 00 63 00 // s.t.e.m...S.e.c.
75 00 72 00 69 00 74 00 79 00 2E 00 50 00 65 00 // u.r.i.t.y...P.e.
72 00 6D 00 69 00 73 00 73 00 69 00 6F 00 6E 00 // r.m.i.s.s.i.o.n.
53 00 65 00 74 00 22 00 0D 00 0A 00 20 00 20 00 // S.e.t."..... . .
20 00 20 00 20 00 20 00 20 00 20 00 20 00 20 00 // . . . . . . . .
20 00 20 00 20 00 20 00 20 00 76 00 65 00 72 00 // . . . . .v.e.r.
73 00 69 00 6F 00 6E 00 3D 00 22 00 31 00 22 00 // s.i.o.n.=.".1.".
3E 00 0D 00 0A 00 20 00 20 00 20 00 3C 00 50 00 // >..... . . .<.P.
65 00 72 00 6D 00 69 00 73 00 73 00 69 00 6F 00 // e.r.m.i.s.s.i.o.
6E 00 20 00 63 00 6C 00 61 00 73 00 73 00 3D 00 // n. .c.l.a.s.s.=.
22 00 53 00 79 00 73 00 74 00 65 00 6D 00 2E 00 // ".S.y.s.t.e.m...
53 00 65 00 63 00 75 00 72 00 69 00 74 00 79 00 // S.e.c.u.r.i.t.y.
2E 00 50 00 65 00 72 00 6D 00 69 00 73 00 73 00 // ..P.e.r.m.i.s.s.
69 00 6F 00 6E 00 73 00 2E 00 50 00 72 00 69 00 // i.o.n.s...P.r.i.
6E 00 63 00 69 00 70 00 61 00 6C 00 50 00 65 00 // n.c.i.p.a.l.P.e.
72 00 6D 00 69 00 73 00 73 00 69 00 6F 00 6E 00 // r.m.i.s.s.i.o.n.
2C 00 20 00 6D 00 73 00 63 00 6F 00 72 00 6C 00 // ,. .m.s.c.o.r.l.
69 00 62 00 2C 00 20 00 56 00 65 00 72 00 73 00 // i.b.,. .V.e.r.s.
69 00 6F 00 6E 00 3D 00 31 00 2E 00 30 00 2E 00 // i.o.n.=.1...0...
32 00 34 00 31 00 31 00 2E 00 30 00 2C 00 20 00 // 2.4.1.1...0.,. .
43 00 75 00 6C 00 74 00 75 00 72 00 65 00 3D 00 // C.u.l.t.u.r.e.=.
6E 00 65 00 75 00 74 00 72 00 61 00 6C 00 2C 00 // n.e.u.t.r.a.l.,.
20 00 50 00 75 00 62 00 6C 00 69 00 63 00 4B 00 // .P.u.b.l.i.c.K.
65 00 79 00 54 00 6F 00 6B 00 65 00 6E 00 3D 00 // e.y.T.o.k.e.n.=.
62 00 37 00 37 00 61 00 35 00 63 00 35 00 36 00 // b.7.7.a.5.c.5.6.
31 00 39 00 33 00 34 00 65 00 30 00 38 00 39 00 // 1.9.3.4.e.0.8.9.
22 00 0D 00 0A 00 20 00 20 00 20 00 20 00 20 00 // "..... . . . . .
20 00 20 00 20 00 20 00 20 00 20 00 20 00 20 00 // . . . . . . . .
20 00 20 00 76 00 65 00 72 00 73 00 69 00 6F 00 // . .v.e.r.s.i.o.
6E 00 3D 00 22 00 31 00 22 00 3E 00 0D 00 0A 00 // n.=.".1.".>.....
20 00 20 00 20 00 20 00 20 00 20 00 3C 00 49 00 // . . . . . .<.I.
64 00 65 00 6E 00 74 00 69 00 74 00 79 00 20 00 // d.e.n.t.i.t.y. .
41 00 75 00 74 00 68 00 65 00 6E 00 74 00 69 00 // A.u.t.h.e.n.t.i.
63 00 61 00 74 00 65 00 64 00 3D 00 22 00 74 00 // c.a.t.e.d.=.".t.
72 00 75 00 65 00 22 00 0D 00 0A 00 20 00 20 00 // r.u.e."..... . .
20 00 20 00 20 00 20 00 20 00 20 00 20 00 20 00 // . . . . . . . .
20 00 20 00 20 00 20 00 20 00 20 00 52 00 6F 00 // . . . . . .R.o.
6C 00 65 00 3D 00 22 00 53 00 75 00 70 00 65 00 // l.e.=.".S.u.p.e.
72 00 76 00 69 00 73 00 6F 00 72 00 73 00 22 00 // r.v.i.s.o.r.s.".
2F 00 3E 00 0D 00 0A 00 20 00 20 00 20 00 3C 00 // /.>..... . . .<.
2F 00 50 00 65 00 72 00 6D 00 69 00 73 00 73 00 // /.P.e.r.m.i.s.s.
69 00 6F 00 6E 00 3E 00 0D 00 0A 00 3C 00 2F 00 // i.o.n.>.....<./.
50 00 65 00 72 00 6D 00 69 00 73 00 73 00 69 00 // P.e.r.m.i.s.s.i.
6F 00 6E 00 53 00 65 00 74 00 3E 00 0D 00 0A 00 ) // o.n.S.e.t.>.....
// Code size 11 (0xb)
.maxstack 8
IL_0000: ldstr "Starting the machinery..."
IL_0005: call void [mscorlib]System.Console::WriteLine(string)
IL_000a: ret
} // end of method App::foo
Figure 5 asm.cs using System;
using System.Web;
using System.Security;
public class MyModule : IHttpModule {
public void Init(HttpApplication app) {
app.Error += new EventHandler(OnError);
}
public void Dispose() {}
static void OnError(object sender, EventArgs args) {
HttpContext ctx = HttpContext.Current;
foreach (Exception x in ctx.AllErrors) {
if (hasSecurityException(x)) {
// Ask IIS to authenticate the user
// if they are currently anonymous.
// This may allow a second request to succeed.
ctx.Response.StatusCode = 401;
ctx.Response.StatusDescription = "Unauthorized";
// don't show the user that vanilla error page
ctx.ClearError();
ctx.Response.Write("<h2>You are not authorized " +
"to view this page</h2>");
break;
}
}
}
static bool hasSecurityException(Exception x) {
if (x is SecurityException) {
return true;
}
else if (null != x.InnerException) {
return hasSecurityException(x.InnerException);
}
else return false;
}
}
Figure 6 Evil Code Access using System.Threading;
using System.Security.Principal;
public class EvilComponent : ICalculator {
public int Add(int a, int b) {
string[] roles = { "Supervisors" };
IPrincipal fake =
new GenericPrincipal(
new GenericIdentity("Bob"),
roles);
// the following line of code
// should worry you!
Thread.CurrentPrincipal = fake;
return a + b;
}
}
|