First we execute the webservices directly using:
which will create this AST generated script file (note: 'the script below was created from the script above', and that makes no sense to you, please read the Using AST technology (from ICSharpCode.NRefactory) to script the creation of a C# file post) :
which when executed results in:
Next step is to load the WS_UserManagement.cs file, get its AST, find the Login Method and add that method to the AClass Ast
The generated code will look like this:
One of the best parts of AST manipulation is that we can easily use on AST to create another one.
In this case we are going to use the WebService’s Login method to create the ‘wrapper/proxy login method’
The script shown above will create this script:
which is exactly what I’m trying to do: a C# based proxy for a web service :)
To quickly test it we can add a method that invoke that wrapper method:
which will create this code:
which when executed will show the login Id on the Log Viewer:
Here is an interesting twist, which also shows the power of this technique to script unit tests.
Since the Login method (in HacmeBank) is vulnerable to SQL injection, we can code a payload on via the AST generation:
which will result in the code and execution result of:
Note the SQL injection error in the Log :)
We can also use a payload that returns an SQL error with a value (like jv’ and 1 = @@version -- )
where we will get this script and execution result (see Log Viewer)
and this traffic in fiddler:
As you can see this is a real powerful technique where I was able to use AST manipulation to programmatically create a Proxy Method for a particular WebService’s WebMethod.
Finally, just to show the interactivity of this type of development (using the GUI explained in Creating a REPL editor that is linked to a Code editor ), this is what my GUI looked like after running the 'AST generated script with the SQL Injection' (note that right-hand-side code editor is populated, compiled and executed in real-time)
Scripts used in this Post:
1) invoking the Login WebService directly:
1: var compilationUnit = new CompilationUnit();
2: compilationUnit.add_Using("O2.DotNetWrappers.ExtensionMethods");
3: compilationUnit.add_Using("System");
4:
5: var aClass = compilationUnit.add_Type("AClass");
6: var aMethod = aClass.add_Method("Main")
7: .setReturnType("void")
8: .public_Static();
9:
10: var wsUserManegementType = "WS_UserManagement".ast_TypeReference();
11:
12: var body = aMethod.add_Body();
13: body.add_Variable("webService", wsUserManegementType.ast_ObjectCreate(),wsUserManegementType);
14: var invocation = "webService".ast_Invocation("Login","jv","jv789");
15:
16: body.add_Variable("result", invocation, "String");
17: body.add_Invocation("result","info");
18: body.add_Invocation("Console","Write","The Login Invocation result is: ");
19: body.add_Invocation("Console","WriteLine","result".identifier());
20:
21:
22:
23: var csharpCode = compilationUnit.csharpCode()
24: .insertAt(0, @"//O2File:E:\O2\O2.Temp\5_10_2013\wsdl_tmpC5E1\WS_UserManagement.cs".line());
25:
26:
27:
28: var tempFile = csharpCode.saveWithExtension(".cs");
29: codeEditor.open(tempFile)
30: .compileCSSharpFile()
31: .executeFirstMethod();
32:
33: return "ok";
34: //using ICSharpCode.NRefactory.Ast
35: //using O2.API.AST.ExtensionMethods.CSharp
36: //O2File:_Extra_methods_To_Add_to_Main_CodeBase.cs
2) creating the ‘login wrapper/proxy’ method
1: var compilationUnit = new CompilationUnit();
2: compilationUnit.add_Using("O2.DotNetWrappers.ExtensionMethods");
3: compilationUnit.add_Using("System");
4:
5: var file = @"E:\O2\O2.Temp\5_10_2013\wsdl_tmpC5E1\WS_UserManagement.cs";
6: var loginMethod = file.csharpAst().method("Login");;
7: var className = loginMethod.Parent.prop("Name").str();
8:
9: var aClass = compilationUnit.add_Type(className + "_Wrapper");
10:
11: var aMethod = aClass.add_Method(loginMethod);
12:
13: var body = new BlockStatement();
14: body.add_Variable("webService",
15: className.ast_TypeReference().ast_ObjectCreate(),
16: className.ast_TypeReference());
17: var parameters = loginMethod.parameters().names().ast_Identifiers().ToArray();
18: var invocation = "webService".ast_Invocation("Login",parameters);
19: var result = body.add_Variable("result", invocation, loginMethod.TypeReference);
20: body.add_Return(result.Name.ast_Identifier());
21:
22: loginMethod.Body = body;
23: loginMethod.Attributes = null;
24:
25:
26:
27: var csharpCode = compilationUnit.csharpCode()
28: .insertAt(0, @"//O2File:{0}".format(file).line());
29:
30: var tempFile = csharpCode.saveWithExtension(".cs");
31: codeEditor.open(tempFile);
3) creating a test method that with an SQL Injection payload:
1: var compilationUnit = new CompilationUnit();
2: compilationUnit.add_Using("O2.DotNetWrappers.ExtensionMethods");
3: compilationUnit.add_Using("System");
4:
5: var file = @"E:\O2\O2.Temp\5_10_2013\wsdl_tmpC5E1\WS_UserManagement.cs";
6: var loginMethod = file.csharpAst().method("Login");;
7: var className = loginMethod.Parent.prop("Name").str();
8:
9: var aClass = compilationUnit.add_Type(className + "_Wrapper");
10:
11: var testBody = aClass.add_Method("testMethod")
12: .setReturnType("void")
13: .add_Body();
14:
15: var loginPayload = "jv' and 1 = @@version --";
16: var loginInvoke = "Login".ast_Invocation(loginPayload,"jv789");
17: var infoInvoke = loginInvoke.add_Invocation("info");
18: testBody.append_AsStatement(infoInvoke);
19:
20:
21: var aMethod = aClass.add_Method(loginMethod);
22:
23: var body = new BlockStatement();
24: body.add_Variable("webService",
25: className.ast_TypeReference().ast_ObjectCreate(),
26: className.ast_TypeReference());
27: var parameters = loginMethod.parameters().names().ast_Identifiers().ToArray();
28: var invocation = "webService".ast_Invocation_onType("Login",parameters);
29: var result = body.add_Variable("result", invocation, loginMethod.TypeReference);
30: body.add_Return(result.Name.ast_Identifier());
31:
32: loginMethod.Body = body;
33: loginMethod.Attributes = null;
34:
35:
36:
37: var csharpCode = compilationUnit.csharpCode()
38: .insertAt(0, @"//O2File:{0}".format(file).line());
39:
40: var tempFile = csharpCode.saveWithExtension(".cs");
41: codeEditor.open(tempFile);
42:
43: if (true)
44: codeEditor.compileCSSharpFile()
45: .executeFirstMethod();
46:
47: return "ok";
48: //using ICSharpCode.NRefactory.Ast
49: //using O2.API.AST.ExtensionMethods.CSharp
50: //O2File:_Extra_methods_To_Add_to_Main_CodeBase.cs