OWASP O2 Platform Blog

O2 Scripting Samples: Automating Rational AppScan Standard GUI and adding AppScan Standard Findings

Here are a number of smaller scripts I saved when working on the Showing IBM Rational AppScan Source Findings inside AppScan Standard (1st PoC)¬†script. These are great if you are trying to get around O2’s APIs and get a feel for how a complex scripts ‘evolves’ ūüôā

Note that these scripts have to be executed from inside the O2 Scriping environment created via Injecting O2 into IBM Rational AppScan Standard

 

Open up OpenScan dialog: 

var toolScriptButton = (ToolStripButton) MainForm.field("toolStripButtonOpen");
toolScriptButton.PerformClick();

show all values (public and private)  MainForm Fields and Properties

MainForm.details();

Get AppScan Debug Process Information

return AppScan.Diagnostics.Debug.GetProcessInformationLog();
//O2Ref:appscan.exe
//O2Ref:debug.dll

Get Logger

return AppScan.Diagnostics.Debug.Logger;
//O2Ref:appscan.exe
//O2Ref:debug.dll
//O2Ref:Utilities.dll

Get log file

var logger =  AppScan.Diagnostics.Debug.Logger;
var logFile = logger.LogFile;
return logFile;
//O2Ref:appscan.exe
//O2Ref:debug.dll
//O2Ref:Utilities.dll

View log file contents

var logger =  AppScan.Diagnostics.Debug.Logger;
var logFileContents = logger.LogFile.fileContents();
"AppScan Log file Contents".popupWindow()
                           .add_TextArea()
                           .set_Text(logFileContents);
//O2Ref:appscan.exe
//O2Ref:debug.dll
//O2Ref:Utilities.dll

View log file contents in a strongly typed table

var logger =  AppScan.Diagnostics.Debug.Logger;
var logFileContents = logger.LogFile.fileContents();


var logFileData =  (from  line in logFileContents.lines()       
        where line.split("|").size() > 1
       select line.split("|"))
        .Select((items)=>
           new {
                   process = items[0],
                   time = items[1],
                   message = items[2]
               } );
 
"AppScan Log file Contents".popupWindow()
                           .add_TableList()
                           .show(logFileData);                         

return "ok";
//O2Ref:appscan.exe
//O2Ref:debug.dll
//O2Ref:Utilities.dll

 
How to create the AppScan class (which is marked as internal)
Note that this doesn’t return a value (could be because it can only be called once). The constructor is correcly called but there in an internal AppScan error thrown¬†¬†¬†

var appScan =  "AppScanSDK.dll".assembly()
                               .type("AppScan")
                               .ctor();
                             
return appScan;
return "ok";
//using AppScan.GuiLayerImpl
//O2Ref:appscan.exe
//O2Ref:AppScanSDK.dll

Getting a object reference to an IAppScan object

return AppScan.AppScanFactory.CreateInstance();
//O2Ref:appscan.exe
//O2Ref:AppScanSDK.dll

View all (public & private) fields and properties from the IAppScan object (which is an object of type AppScan.GuiLayerImpl.AppScan)


var appScan =  AppScan.AppScanFactory.CreateInstance();
appScan.details();
//O2Ref:appscan.exe
//O2Ref:AppScanSDK.dll

Getting the scan object and returning it full type name (which is AppScan.GuiLayerImpl.Scan.ScanManager)

var appScan =  AppScan.AppScanFactory.CreateInstance();
var scan = appScan.Scan;
return scan.typeFullName();</pre>
//O2Ref:appscan.exe
//O2Ref:AppScanSDK.dll

 
Load scan (doesn’t work, hangs at 95%)¬†

var appScan =  AppScan.AppScanFactory.CreateInstance();
var scan = appScan.Scan;

var scanFileToLoad = @"C:\_WorkDir\IBM\Altoro\AltoroJ21.scan";
return scan.LoadScanData(scanFileToLoad);
 
//O2Ref:appscan.exe
//O2Ref:AppScanSDK.dll

 
Load scan ASync  (works)

var appScan =  AppScan.AppScanFactory.CreateInstance();
var scan = appScan.Scan;

var scanFileToLoad = @"C:\_WorkDir\IBM\Altoro\AltoroJ21.scan";
scan.LoadScanDataAsync(scanFileToLoad);
return "ok";

//O2Ref:appscan.exe
//O2Ref:AppScanSDK.dll

 
Get Reference to main TreeView with site tree, expand all nodes, and select the 5th

var scanTreeView = MainForm.controls<TreeView>(true)[0];
scanTreeView.expandAll();
var node = scanTreeView.allNodes()[5].selected();

return node;
//node.details();
//O2Ref:appscan.exe
//O2Ref:AppScanSDK.dll

 
Get the node type (which is AppScan.Gui.UserControls.TreeNodeWithPaint)

return node.typeFullName();

get the Full Path value (which is an AppScan Scan value )


return node.FullPath;</pre>

 
Show in O2’s LogViewer the FullPath value of the selected node¬†

var scanTreeView = MainForm.controls<TreeView>(true)[0];

scanTreeView.afterSelect<TreeNodeWithPaint>(
    (treeNodeWithPaint)=>
        {
            treeNodeWithPaint.FullPath.info();
        });
 
//using AppScan.Gui.UserControls
//O2Ref:appscan.exe
//O2Ref:UserControls.dll

Show source code of selected treenode in source code viewer (below the TreeView) 

var panelBelowTreeView = scanTreeView.splitContainer().Panel2;
panelBelowTreeView.clear();
var sourceCodeViewer = panelBelowTreeView.add_SourceCodeViewer();
var scanTreeView = MainForm.controls<TreeView>(true)[0];


var sourceFolder = @"C:\....\Altoro\AltoroJ2.1-src\WebContent";

var virtualFile = scanTreeView.selected().FullPath.remove(@"My Application\http://www.altoromutual.com:8080/\altoromutual\");
var pathToFile = sourceFolder.pathCombine(virtualFile); 
sourceCodeViewer.set_Text(pathToFile.fileContents(), ".aspx");
//using AppScan.Gui.UserControls
//O2Ref:appscan.exe
//O2Ref:UserControls.dll

Show source code on TreeNode Click


var sourceFolder = @"C:\...\Altoro\AltoroJ2.1-src\WebContent";

var scanTreeView = MainForm.controls<TreeView>(true)[0];

var panelBelowTreeView = scanTreeView.splitContainer().Panel2;
panelBelowTreeView.clear();
var sourceCodeViewer = panelBelowTreeView.add_SourceCodeViewer();

scanTreeView.afterSelect<TreeNodeWithPaint>(
    (treeNodeWithPaint)=>
        {
            try
            {           
            var virtualFile = scanTreeView.selected().FullPath.remove(@"My Application\http://www.altoromutual.com:8080/\altoromutual\");
            var pathToFile = sourceFolder.pathCombine(virtualFile); 
            if (pathToFile.fileExists())
            {
                sourceCodeViewer.open(pathToFile);
                if (pathToFile.extension(".jsp"))
                    sourceCodeViewer.editor().setDocumentHighlightingStrategy(".aspx");
            }
                else
                    sourceCodeViewer.set_Text("");
        }
        catch()
        {}
        });

return "ok";
//using AppScan.Gui.UserControls
//O2Ref:appscan.exe
//O2Ref:UserControls.dll

Add a top menu (to AppScan) with an menu item to open an *.scan file

Action<string> openScanFile =
    (scanFileToLoad)=>{
                            if (scanFileToLoad.fileExists())
                            {
                                var appScan =  AppScan.AppScanFactory.CreateInstance();
                                appScan.Scan.LoadScanDataAsync(scanFileToLoad);
                            }
                           
                        };

 
var menuStrip =  MainForm.controls<MenuStrip>(); 
var o2Menu = menuStrip.add_MenuItem("AltoroJ"); 
o2Menu.add_MenuItem("Open AltoroJ", ()=>  openScanFile("Where is the AltoroJ *.Scan file".askUser()) );

adding two menu items (one to load the scan file and another to configure the source code mapings)

Action<string> openScanFile =
    (scanFileToLoad)=>{
                            if (scanFileToLoad.fileExists())
                            {
                                var appScan =  AppScan.AppScanFactory.CreateInstance();
                                appScan.Scan.LoadScanDataAsync(scanFileToLoad);
                            }
                           
                        };

//run this only once
Action<string> configureTreeView =
    (sourceFolder)
        =>{
            if (sourceFolder.dirExists().isFalse())
                return;

            var scanTreeView = MainForm.controls<TreeView>(true)[0];
           
            var panelBelowTreeView = scanTreeView.splitContainer().Panel2;
            panelBelowTreeView.clear();
            var sourceCodeViewer = panelBelowTreeView.add_SourceCodeViewer();
           
            scanTreeView.afterSelect<TreeNodeWithPaint>(
                (treeNodeWithPaint)=>
                    {
                        try
                        {           
                            var virtualFile = scanTreeView.selected().FullPath.remove(@"My Application\http://www.altoromutual.com:8080/\altoromutual\");
                            var pathToFile = sourceFolder.pathCombine(virtualFile); 
                            if (pathToFile.fileExists())
                            {
                                sourceCodeViewer.open(pathToFile);
                                if (pathToFile.extension(".jsp"))
                                    sourceCodeViewer.editor().setDocumentHighlightingStrategy(".aspx");
                            }
                                else
                                    sourceCodeViewer.set_Text("");
                        }
                        catch
                        {
                        }
                    });

        };
 
var menuStrip =  MainForm.controls<MenuStrip>(); 
var o2Menu = menuStrip.add_MenuItem("AltoroJ"); 
o2Menu.add_MenuItem("Open AltoroJ", ()=>  openScanFile("Where is the AltoroJ *.Scan file".askUser()) );
o2Menu.add_MenuItem("Configure AltoroJ source code mapping", ()=>  configureTreeView("Where is the AltoroJ source code".askUser()) );

return "ok";

//using AppScan.Gui.UserControls
//O2Ref:appscan.exe
//O2Ref:UserControls.dll
//O2Ref:AppScanSDK.dll

Next step is to add the source code viewer for the AltoroJ AS.Source findings. Lets start by finding the multiple TabControls

return MainForm.controls<TabControl>(true);
//O2Ref:appscan.exe

Adding a test tab to the selected finding TabControl

var selectedFindingTabControl =  MainForm.controls<TabControl>(true)[1];
selectedFindingTabControl.add_Tab("Test");
//O2Ref:appscan.exe

Adding a findings Viewer

var selectedFindingTabControl =  MainForm.controls<TabControl>(true)[1];
var findingsTab = selectedFindingTabControl.add_Tab("SAST Findings");
var findingsViewer = findingsTab.add_FindingsViewer();

//O2Ref:appscan.exe
//using O2.XRules.Database.Findings
//O2File:Findings_ExtensionMethods.cs

load the findings  data and show it

            var o2Findings = ozasmtFile.loadO2Findings();

            var selectedFindingTabControl =  MainForm.controls<TabControl>(true)[1];
            //selectedFindingTabControl.TabPages.Clear();

            var allFindingsViewer =  selectedFindingTabControl.add_Tab("All SAST Findings ")
                                                  .add_FindingsViewer(false);
            var findingsMappedToFileViewer = selectedFindingTabControl.add_Tab("SAST Findings Mapped to Selecteded File")
                                                          .add_FindingsViewer(true);
            allFindingsViewer.show(o2Findings);

            Action<string> showFilteredResults =
                (filter)=>{   
                              var filteredResults = (from o2Finding in o2Findings
                                                     where o2Finding.file.contains(filter)
                                                     select o2Finding).toList();
                              findingsMappedToFileViewer.show(filteredResults);                 
                         };
           

            var scanTreeView = MainForm.controls<TreeView>(true)[0];                     

                scanTreeView.afterSelect<TreeNodeWithPaint>(
                    (treeNodeWithPaint)=>
                        {
                            try
                            {           
                                var virtualFile = scanTreeView.selected().FullPath.remove(@"My Application\http://www.altoromutual.com:8080/\altoromutual\");
                                //var pathToFile = sourceFolder.pathCombine(virtualFile); 
                                showFilteredResults(virtualFile);
                            }
                            catch {}
                        });                   

November 8, 2011 Posted by | .NET, AppScan | Leave a comment

Showing IBM Rational AppScan Source Findings inside AppScan Standard (1st PoC)

Here is a PoC I wrote last night for an IBMer which shows a very first rough pass at loading up IBM Rational AppScan Source findings inside AppScan Standard. The demo uses AltoroJ and at the moment connects the *.jsp AppScan Standard findings into the respective AppScan Source findings.

This is what it looks like after the O2 script has been executed and the data loaded:

for reference this is what AppScan Standard looks like without  the O2 Script execution (and the injection of the AppScan Source findings:


How to replicate this?

At the moment there are a couple steps that need to be done in order to get there:

1) start AppScan under O2 control by executing the Util –¬†Launch AppScan Standard (O2 Version).h2 script¬†(see Injecting O2 into IBM Rational AppScan Standard¬†for details on how this works)

2) After AppScan loads (and the O2 .NET injection occours), you should see an O2 menu (on top) and an O2 Scripting environment on the middle left:

3) now drag and drop the Inside AppScan Standard- Add AltoroJ Menu.h2 script into the O2 Scripting environment, and execute it (note the addition of a new AltoroJ Menu after execution)

4) the AltoroJ has 3 options:

 РOpen AppScan Standard File,  
 РConfigure Source code and
 РMap AppScan Source findings

(the sub menus text is a but different, but that’s what it means)

Note that these need to opened in sequence

5) select ‘Open AltoroJ’ and enter the path to the *.scan file:

this will trigger the load of the saved assessment and should look like this when completed:

6) Next click on ‘Configure AltoroJ source code Mapping’ and enter the path to the source code (note that in this version of the script you need to point to the WebContent folder)

7) test the source code mappings by clicking on a*.jsp  file that exists on the file system

Note how the O2 Scripting control (middle left) was replaced with a SourceCodeViewer control that shows the content of the selected file (in the treeview above it).

Here is an example of another *.jsp file (note that the other servlet mappings are currently not supported (but it is not hard to do since we have access to all artifacts we need))

8) the final step is to select the menu option ‘Map AltoroJ SAST findings’ and enter the location of the AppScan Source saved findings file

9) View all Source code Findings

The last script loaded the findings in memory and added two Tabs to the bottom right tab Control.

The first tab added is called ‘All SAST Findings’ and will show details of all findings loaded

Including a view to see the Finding’s Traces:

10) View the findings that are mapped to the *.Jsp file currently selected

The other tab that was added to the TabControl is called ‘SAST Findings Mapped to Selected File’ and will only show the findings that exist for the file currently loaded:

Here is another example: (note how powerfull it is to see the BlackBox findings on the top and the Source Code findings on the bottom)

11) Next Steps?

There is still a LOT that needs to be done before this script is a good representation of the information that we already have available from both scans

For example one will need to consume the web.xml file in order to get the bean/url mappings from it (we also need to add proper color coding for the *.jsp file loaded on the right , like what happens on the left).  

Another interresting option is to look at the WAFL (Web Application Framework Language) file created by AppScan Source and see if we can extract from it the mappings between the Urls and its the Controllers

November 8, 2011 Posted by | AppScan, Java, Tools | 1 Comment

Creating a Pink version of IBM Rational AppScan Standard

Once you have an O2 script inside AppScan Standard what can you do with it?

(see Injecting O2 into IBM Rational AppScan Standard for details on how it was done)

Well, what about creating a pink version of AppScan (for the female users out there)?

How was this done?

It is actually very easy. Since the O2 Script editor is running under the same process as AppScan Standard, and there is a reference passed into the script envionment with the main GUI (the variable is called MainForm), all we need to do a recursive search for all Windows Controls and change its background color:

foreach(var controls in MainForm.controls(true))
    controls.backColor(Color.Pink);
MainForm.set_Text("AppScan Standard - in Pink");
return MainForm;
//O2Ref:appscan.exe

Over the next weeks I will post more examples on what can be done with these capabilities (namely the ability to add the artifacts that O2 is able to create/consume from other tools or from the target application’s Source Code)

Meanwhile, to help with your first scripts inside AppScan standard, here are a number of code samples that I captured during the development of these scripts:

Get AppScan.Exe assembly object (before AppScan starts)

return "AppScan.exe".assembly()

… get its types

return "AppScan.exe".assembly().types();

… get the MainForm class:

return "AppScan.exe".assembly()
                    .type("MainForm");

… get MainForm class methods:

return "AppScan.exe".assembly()
                    .type("MainForm")
                    .methods();

… get the Main method

return "AppScan.exe".assembly()
                    .type("MainForm")
                    .method("Main");

… invoke the Main method in an STA Thread

O2Thread.staThread(
    ()=>{
            "AppScan.exe".assembly()
                    .type("MainForm")
                    .method("Main").invoke(new object[] {new string[] {} }) ; 
        });

Getting a refrence to the main window and changing its title (after AppScan starts and inside the AppScan process)

var appScan =  "".lastFormLoaded();
appScan.set_Text("O2 version of IBM AppScan - in Pink");

…getting the top level controls:

return appScan.controls();

…getting the list of all GUI controls

return appScan.controls(true);

… getting all treeviews

return appScan.controls<TreeView>(true);

Adding a test node to all treeviews

var treeViews = appScan.controls<TreeView>(true);
foreach(var treeview in treeViews)
    treeview.add_Node("Hello from O2");
return treeViews;

Grabbing a reference to the top Level menu and creating an O2 Menu

var menuStrip =  appScan.controls<MenuStrip>();
var o2Menu = menuStrip.add_MenuItem("O2");

Adding a menu item that opens up an O2 Log Viewer

var appScan =  "".applicationWinForms()[2];
var menuStrip =  appScan.controls<MenuStrip>(); 
var o2Menu = menuStrip.add_MenuItem("O2"); 
o2Menu.add_MenuItem("O2 Log Viewer", ()=>  "O2 Log Viewer".popupWindow(450,200).add_LogViewer() );


Add menu item that opens up a script editor

var appScan =  "".applicationWinForms()[3];
Action<Panel> showO2ScriptEditor =
    (targetPanel)=> {
                        var scriptEditor = targetPanel.add_Script(false) ;
                        scriptEditor.InvocationParameters.add("MainForm", appScan);
                        scriptEditor.Code = "return MainForm;".line() +
                                            "\\O2Ref:appscan.exe";
                    };

var menuStrip =  appScan.controls<MenuStrip>(); 
var o2Menu = menuStrip.add_MenuItem("O2"); 
o2Menu.add_MenuItem("O2 Log Viewer", ()=>  "O2 Log Viewer".popupWindow(450,200).add_LogViewer() );
o2Menu.add_MenuItem("O2 Script Editor", ()=>  showO2ScriptEditor("O2 Script Editor".popupWindow(650,300)) );

August 6, 2011 Posted by | AppScan, Tools | Leave a comment

Injecting O2 into IBM Rational AppScan Standard

If you use AppScan Standard (the BlackBox tool) and want to use O2 to script its GUI or scans, here is a new O2 script that will start AppScan Standard under the same process as O2.

Once the main AppScan gui is loaded this script will add a new O2 Menu and inject an O2 Script editor.

You can find the script that automates the process in your local folder C:\O2\O2Scripts_Database\_Scripts\3rdParty_Tools\IBM\AppScan_Standard:

The script you want to execute is the Util РLaunch AppScan Standard (O2 version).h2  which will

  • Copy all required files (O2 dlls and¬†AppScan_Standard_1st_Script.cs Script) to the AppScan Folder.
  • Compile¬†the AppScan_Standard_O2_Launcher.cs script into AppScan_Standard_O2_Launcher.exe and copy it to AppScan folder
  • In the AppScan folder: execute¬†and compile AppScan_Standard_O2_Launcher.exe
  • The AppScan_Standard_O2_Launcher.exe will compile the AppScan_Standard_1st_Script.cs¬†and execute it¬†
  • the AppScan_Standard_1st_Script.cs script will:
    • open an O2 Log Viewer (so that you get a feel for what is happening),
    • launch AppScan (by using reflection to open the MainForm Form control),
    • wait for the main AppScan gui to load, and when it does:
    • compile and execute the In AppScan – Create O2 Gui.h2 script
  • The In AppScan – Create O2 Gui.h2¬† script is the one that adds a new menu item and injects a O2 Script editor into the main AppScanGui.

The Util – Launch AppScan Standard (O2 version).h2¬† has an editor for all these scripts, but by default this is disabled (see NUnit example for details). The default behaviour of Util – Launch AppScan Standard (O2 version).h2 (when double-clicked from windows explorer) is to execute¬†the above steps in sequence.¬†And if all goes according to plan, you will see the following ‘AppScan Standard – O2 Version’ GUI:

… note the extra O2 Menu and the O2 Scripting Environment….

 

For reference, here is what it looks like while AppScan Standard is loading up (the cmd.exe window was created by AppScan_Standard_O2_Launcher.exe and the LogViewer shows the wait for the main AppScan GUI to load up)

 

These series of scripts are heavily based on the ones previously used and documented in the Injecting O2 into another .NET Process (in this case NUnit.exe) script (see that blog post for more technical details about how this works).

August 6, 2011 Posted by | .NET, AppScan, Interoperability | 1 Comment