Thursday 16 May 2013

Adding O2's CSharp REPL to the Checkmarx main WebService

I’m working on the integration of TeamMentor with Checkmarx and needed to have some control on how the data the WebServices returns.

The previous version of this integration made direct changes to the Checkmarx content database, but this time around that will not work, since for example CheckMarx maps it’s guidance to CWE_ID and we want to map the guidance to the Checkmarx’ Query_ID (TeamMentor has technology/application specific guidance, so we can show an SQL Injection article for Java and a different article for .NET (both have the same CWE_ID, but have different Query_ID)

Initially I was going to use PostSharp to add the TM specific code ‘on top’ of Checkmarx dlls, but since in effect this would mean the modification of CheckMarx dlls (to insert PostSharp aspects), I went for an hook on Http Pipeline instead :)

In order to allow me to develop this script, I added (a slightly modified version of ) the O2 WebREPL to a local copy of Checkmarx, so that I can execute C# directly on the server:

image

Since we are in the same process, we have access to all CheckMarx’s dlls, for example the main WebServices one:

image

the example above showed a failed login attempt, and the one below shows a successful one:

image

Since we have lambda methods in this REPL environment, here is a function to get a valid SessionId:

image

Which can then be used to fetch a particular CWE_ID description:

image \

The returned style doesn’t work very well with the REPL css, but we can see that the checkmarx CWE info is there:

image

this is the same content that is currently retrieved from the execution of:

image

which looks like this.

image

So the objective is to have our content (i.e TeamMentor Guidance) to show there


Scripts used in this post

1) Wrap HTML Post requests
   1: var cxPortal = new CxPortalWS.CxPortalWebService();

   2: //var sessionId =  validSessionId();

   3:  

   4: //var cweId = 90;

   5: //return cxPortal.GetQueryDescription(sessionId,cweId)

   6: //                 .QueryDescription;

   7:  

   8: //return validSessionId();

   9:  

  10: System.Action requestCallback=

  11:       ()=>{

  12:               var request = System.Web.HttpContext.Current.Request;

  13:               var response = System.Web.HttpContext.Current.Response;

  14:               //response.ContentType = "text/xml";

  15:               if (request.Url.AbsolutePath == "/CxWebInterface/CxWebService.asmx/GetQueryDescription")

  16:             {

  17:                 

  18:                 var sessionId = request.Form["sessionId"];

  19:                 var cweId = request.Form["cweId"].toInt();

  20:                 //var cweId = 90;

  21:                 var description = cxPortal.GetQueryDescription(sessionId,cweId);

  22:                 description.QueryDescription = description.QueryDescription.replace(">CWE",">AAAAAA_CWE");

  23:                 //response.Write(request.Form);                  

  24:                 response.Write(description.toXml());

  25:                 response.End();                               

  26:             }

  27:               else

  28:             {

  29:               

  30:                 "In url: {0}".info(request.Url.AbsolutePath);

  31:             }

  32:       

  33:         };

  34:       

  35:       

  36: "requestCallback".o2Cache<System.Action>(requestCallback);    

  37: //return "requestCallback".o2Cache<System.Action>();//.invoke();      

  38:  

  39:  

  40:  

  41: return "ok";

  42: //return globalAsa.type().fields().select(field=>field.Name);

  43: //globalAsa.field("BeginRequest_Callback", requestCallback);

  44: //return globalAsa.field("BeginRequest_Callback");

  45:  

  46: Func<string> validSessionId = 

  47:   ()=>{

  48:         var credentials = new Credentials()

  49:                             {

  50:                               User = "admin@cx",

  51:                               Pass = "admin"

  52:                             };

  53:  

  54:         return cxPortal.Login(credentials,0).SessionId;

  55:       };

  56:  

  57:  

  58: //using CxPortalWS;

  59: //O2Ref:CxPortalWebService.dll

  60: //O2Ref:System.Web.Services.dll

2) Getting data from InputStream (when XML form submission)


   1: System.Action requestCallback=

   2:       ()=>{

   3:               var request = System.Web.HttpContext.Current.Request;

   4:               var response = System.Web.HttpContext.Current.Response;

   5:               //response.ContentType = "text/xml";

   6:               //if (request.Url.AbsolutePath == "/CxWebInterface/CxWebService.asmx/GetQueryDescription")

   7:               if (request.Url.AbsolutePath == "/Cxwebinterface/CxWebService.asmx")

   8:             {            

   9:                 var soapHeader = request.Headers["SOAPAction"];

  10:                 if (soapHeader.notNull())

  11:                     {

  12:                           if (soapHeader == "\"http://Checkmarx.com/GetQueryDescription\"")

  13:                         {

  14:                           var xmlSoap = request.InputStream.bytes().ascii();

  15:                           var elements = xmlSoap.xRoot().elementsAll();

  16:                           //.element("{http://Checkmarx.com/}cweId");

  17:                            //return a.xRoot().elementsAll().element("{http://Checkmarx.com/}sessionId");

  18:                           response.Write("\n{0}\n".format(elements.size()));

  19:                             "Handing SoapHeader: {0}".debug(soapHeader);                               

  20:                                response.End();          

  21:                                               

  22:                         }

  23:                         else 

  24:                         {

  25:                            "Could not handle SoapHeader: [{0}]".error(soapHeader);  

  26:                         }

  27:                     }

  28:             }

3) Dynamic Hook in Global.asax.cs

   1: public class Global : System.Web.HttpApplication

   2: {

   3:     

   4:     public Global()

   5:     {

   6:         "requestCallback".o2Cache<Action>(()=>{

   7:                                                 "in Begin Request for :{0}".info(Request.Url.AbsolutePath);

   8:                                               });

   9:     }

  10:     

  11:      

  12:     protected void Application_Start                (object sender, EventArgs e)        

  13:     {

  14:         "[Application_Start]".info();

  15:         "application".o2Cache(()=>this);

  16:     }    

  17:  

  18:     protected void Application_BeginRequest            (object sender, EventArgs e)        

  19:     {                                

  20:         var callback = "requestCallback".o2Cache<Action>();

  21:         callback.invoke();

  22:     }        

  23:         

  24: }