Tuesday 21 May 2013

Using WebServices Proxy Wrapper to replace Checkmarx’s CWE Guidance with TeamMentor’s Articles

After Creating a WebServices Proxy Wrapper for Checkmarx’s CxWebService its time to replace the existing guidance with TeamMentor’s articles.

We start with a folder containing the CxWebService.asmx


image

and an App_Code folder with CxPortalWebService.cs (original C# WSDL) and TM_Proxy_for_CxPortalWebService.cs (proxy that invokes the CxPortalWebService.cs methods)

image

In order to help up to manage the change (and to help deployment), let’s create a git repository here:

image

click ok the warning screen that there are files in this folder, and the OK shown below:

image

next  commit the current files:

image

and create a new branch:

image

Next I opened VisualStudio 2010 and opened this folder as a WebSite:

image

… added a new Class file to hold the TeamMentor logic:

image

I also created a separate project (and solution) to hold the UnitTests:

image

where I added a number of Nuget dependencies to help development and debugging of the unit tests (NUnit, FluentSharp.CoreLib, FluentSharp.BCL,  FluentSharp.REPL), and added the App_Data files as ‘links’

image

And with this set-up I can write unit tests like this:

image

which when executed:

image

will generate this request (to the real server):

image

Note that since we can add ‘extra code’ in between the requests, we can do something like this:

image

which will change the data ‘from the proxy to the real one’ (note the changed value of sessionId)

image

We can also modify the data ‘returned from the real web service’

image

which in this case will make our test fail (since it was expected an false value in the IsSuccesfull field

Back to our unit test writing ...

Here is a unit test that checks that we can login ok as admin:

image

Here is a unit test that checks that the GetQueryDescription is working ok

image


Using Negative CWE Ids to represent QueryId

One of the problems that we have in mapping CWE data to TeamMentor articles is that there are lots of cases where there is not a 1 to 1 mapping between both sets of guidance. For example TeamMentor has language specific articles, where CWE Guidance tends to be generic.

Another scenario is the fact that TeamMentor clients might have customized versions of those Articles, providing Application Specific guidance.

The good news is that Checkmarx rules are already written by technology, which means that we can use the finding’s queryID to map to an TM article.

The bad news is that when the Cx multiple GUIs (web interface, Client app and IDE plug-ins) fetch guidance for a particular finding, they use the CWE ID and not the QueryID.

As mentioned before I was looking for a way to make this change without requiring any code change of the main Checkmarx code base or files, and with the CxWebService proxy I was able to achieve exactly that.

What I’ve done was to add a special filter to the GetQueryCollectionForLanguageGetResults and GetQueryDescription WebService methods

They all have the same pattern of creating an instance of CxTeamMentor object:

image

and calling the respective filter method

image

with the GetQueryDescription filter also receiving the cweId

image

The  TMFilterFor_CxQueryCollectionResponse and TMFilterFor_CxWSResponseResultCollection filters are responsible for assigning the CWE value to the negative of QueryID

image

and

image

The the TMFilterFor_CxWSResponseQueryDescription is responsible for handling the response, which is this first case, is just making a small change to the description value (if the CWE value is negative)

image

To see this in action, I here is the CxClient app trying to load the description of a Java Command Injection vulnerability (which has the QueryID of 587)

image

and here is a .NET Command Injection (which has the QueryID of 423)

image

This means that we need to map the Query ID 587 (Java Command Injection) to the https://teammentor.net/article/00000000-0000-0000-0000-000000859bca article

image

and the QueryId 423 (.NET Command Injection) to the https://www.teammentor.net/article/00000000-0000-0000-0000-0000007a1206

image


Adding test mappings

To try this out lets start with a simple mappings class:

image

which is used on the TMFilterFor_CxWSResponseQueryDescription:


image

And now its working :)

Here is the .Net guidance for the .NET Code Injection query/Vulnerability

image

And  here is the Java guidance for the Java version of the Code Injection query/vulnerability

image

:)

Source used in Post

1) CxTeamMentor file (at the time of this blog post)
   1: using System;

   2: using System.Collections.Generic;

   3: using System.Linq;

   4:  

   5:  

   6: public class CxTeamMentor_Mappings

   7: {

   8:     public static Dictionary<int, string> Tm_QueryId_Mappings  { get; set; }

   9:     public static string                  HtmlRedirectTemplate { get; set; }  

  10:  

  11:     static CxTeamMentor_Mappings()

  12:     {

  13:         LoadData();

  14:     }

  15:  

  16:     public static void LoadData()

  17:     {

  18:         HtmlRedirectTemplate = "<html><head><meta http-equiv=\"refresh\" content=\"0;"+

  19:                                " url=http://teammentor.net/article/{0} \"></head></html>";

  20:  

  21:         Tm_QueryId_Mappings = new Dictionary<int, string>

  22:             {

  23:                 {-587, "00000000-0000-0000-0000-000000859bca"},

  24:                 {-423, "00000000-0000-0000-0000-0000000b0d98"}

  25:             };

  26:     }

  27: }

  28:  

  29: public class CxTeamMentor

  30: {

  31:  

  32:     public void TMFilterFor_CxQueryCollectionResponse(CxQueryCollectionResponse cxQueryCollectionResponse)

  33:     {

  34:         var queries = from queryGroup in cxQueryCollectionResponse.QueryGroups

  35:                       from query in queryGroup.Queries

  36:                       select query;

  37:         foreach (var query in queries)

  38:         {

  39:             query.Cwe = -query.QueryId;             // set the Cwe value to the negative of the QueryId

  40:             query.Name += "_TM";                    // Temp query name minor change

  41:         }

  42:     }

  43:     public void TMFilterFor_CxWSResponseResultCollection(CxWSResponseResultCollection cxWsResponseResultCollection)

  44:     {

  45:         var results = cxWsResponseResultCollection.ResultCollection.Results;

  46:         foreach (var result in results)

  47:         {

  48:             result.CWE = -result.QueryId;           // set the Cwe value to the negative of the QueryId

  49:             result.QueryName += "_TM";              // Temp query name minor change

  50:         }

  51:     }

  52:  

  53:     public void TMFilterFor_CxWSResponseQueryDescription(int cweId, CxWSResponseQueryDescription cxWsResponseQueryDescription)

  54:     {

  55:         if (cxWsResponseQueryDescription.IsSuccesfull)

  56:         {

  57:             if (cweId < 0)

  58:             {

  59:                 if (CxTeamMentor_Mappings.Tm_QueryId_Mappings.ContainsKey(cweId))

  60:                 {                    

  61:                     cxWsResponseQueryDescription.QueryDescription =

  62:                         String.Format(CxTeamMentor_Mappings.HtmlRedirectTemplate, 

  63:                                       CxTeamMentor_Mappings.Tm_QueryId_Mappings[cweId]);

  64:                 }

  65:                 else

  66:                     cxWsResponseQueryDescription.QueryDescription =

  67:                         String.Format("The TeamMentor article with Id {0} could not be found", cweId);

  68:             }

  69:         }

  70:     }

  71:  

  72: }