We start with a folder containing the CxWebService.asmx
and an App_Code folder with CxPortalWebService.cs (original C# WSDL) and TM_Proxy_for_CxPortalWebService.cs (proxy that invokes the CxPortalWebService.cs methods)
In order to help up to manage the change (and to help deployment), let’s create a git repository here:
click ok the warning screen that there are files in this folder, and the OK shown below:
next commit the current files:
and create a new branch:
Next I opened VisualStudio 2010 and opened this folder as a WebSite:
… added a new Class file to hold the TeamMentor logic:
I also created a separate project (and solution) to hold the UnitTests:
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’
And with this set-up I can write unit tests like this:
which when executed:
will generate this request (to the real server):
Note that since we can add ‘extra code’ in between the requests, we can do something like this:
which will change the data ‘from the proxy to the real one’ (note the changed value of sessionId)
We can also modify the data ‘returned from the real web service’
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:
Here is a unit test that checks that the GetQueryDescription is working ok
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 GetQueryCollectionForLanguage, GetResults and GetQueryDescription WebService methods
They all have the same pattern of creating an instance of CxTeamMentor object:
and calling the respective filter method
with the GetQueryDescription filter also receiving the cweId
The TMFilterFor_CxQueryCollectionResponse and TMFilterFor_CxWSResponseResultCollection filters are responsible for assigning the CWE value to the negative of QueryID
and
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)
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)
and here is a .NET Command Injection (which has the QueryID of 423)
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
and the QueryId 423 (.NET Command Injection) to the https://www.teammentor.net/article/00000000-0000-0000-0000-0000007a1206
Adding test mappings
To try this out lets start with a simple mappings class:
which is used on the TMFilterFor_CxWSResponseQueryDescription:
And now its working :)
Here is the .Net guidance for the .NET Code Injection query/Vulnerability
And here is the Java guidance for the Java version of the Code Injection query/vulnerability
:)
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: }