Friday, 9 March 2012

Bending MagicTree (Burp import)

In between projects, we at Astyran have an internal project running to streamline reporting of our vulnerability assessments. One of the tools we use is Gremwell’s MagicTree

Earlier I blogged about our XSLT style-sheet to import vulnerability data of the Arachni scanner. This style sheet created views on the data grouped per vulnerability type. However all other import sheets seem to prefer to group vulnerabilities per URL.

Personally I prefer to group vulnerabilities per type:

  • it enables the designer/architect to really see the full picture at once, design a real solution, and assess the possible impact on development.
  • it prevents developers to fix the issues per page, what leads to incomplete or plain wrong solutions and the endless “penetrate and patch” cycle.
  • it gives a less daunting report to business management (“only 1 high rated issue on a total of 10)” as compared to “we have found 300 high rated issues on a total of 1100). Managers like to see that things in their business critical application can be fixed, not that the situation appears hopeless.
  • it makes the development team happy: “only 1 item to fix”, we are not complete losers and did a reasonable good job;
  • it makes the poor soul that imports the data into the change request management program also happy: only 10 items to import, classify, prioritize and follow-up as compared to 1.100 items - of which many will need to be closed as ‘duplicates’.
  • it wastes less disk-space.

Unfortunately, that means that we have to change all XSLT transformation sheets to import the data the way we want.

Here the code to import Burp scanner data according to our wishes. Just as with our Arachni solution, it creates a (non-standard) “scaninfo” section that keeps information about the scans that were imported, as well as the (standard) “testdata” tree, but now ordered per finding and not per URL.

   1:  <?xml version="1.0" encoding="UTF-8"?>
   2:  <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
   3:   
   4:    <xsl:variable name="my_report_signature">
   5:      <xsl:text>Burp</xsl:text>
   6:      <xsl:value-of select="translate(/issues/@burpVersion,'&#x20;&#x9;&#xD;&#xA;&#x2B;&#x2D;&#x3A;','')"/>
   7:      <xsl:value-of select="translate(/issues/@exportTime,'&#x20;&#x9;&#xD;&#xA;&#x2B;&#x2D;&#x3A;','')"/>
   8:    </xsl:variable>    
   9:   
  10:    <xsl:template name="burp-finding">
  11:      <xsl:param name="issue"/>
  12:          <finding class="MtTextObject" status="new">
  13:              <xsl:attribute name="title">
  14:                  <xsl:value-of select="$issue/name" />
  15:              </xsl:attribute>
  16:        <xsl:attribute name="mergeID" >
  17:                  <xsl:value-of select="$issue/name" />
  18:              </xsl:attribute>
  19:        <burptype><xsl:value-of select="$issue/type" /></burptype>
  20:              <source>
  21:          <xsl:text>Burp </xsl:text> 
  22:          <xsl:value-of select="/issues/@exportTime" />      
  23:        </source>
  24:               <xsl:call-template name="burp-severity">
  25:                   <xsl:with-param name="severity" select="$issue/severity"/>
  26:              </xsl:call-template>
  27:              <xsl:value-of select="$issue/issueBackground" />
  28:              <solution title="Solution" class="MtTextObject">
  29:                  <xsl:value-of select="$issue/remediationBackground" />
  30:              </solution>
  31:              <affects>
  32:          <xsl:attribute name="mergeID" >
  33:            <xsl:value-of select="concat($issue/host, $issue/path)" /> <!-- group output by URI -->
  34:          </xsl:attribute>
  35:          <xsl:value-of select="concat($issue/host, $issue/path)"/>
  36:          <output title="Details" class="MtTextObject">
  37:                  <xsl:value-of select="$issue/issueDetail" />
  38:          </output>
  39:          <xsl:if test="string-length(normalize-space(substring-after(substring-before($issue/location,'parameter'),'[')))>0">
  40:            <parameter> <!-- I really hope nobody uses '[' in URLS -->
  41:              <xsl:value-of select="normalize-space(substring-after(substring-before($issue/location,'parameter'),'['))" />
  42:            </parameter>
  43:          </xsl:if>
  44:          <xsl:for-each select="requestresponse">
  45:          <requestresponse><xsl:number value="position()" format="1"/>
  46:          <request class="MtTextObject" title="Request">
  47:          <xsl:value-of select="request" />
  48:          </request>
  49:          <response class="MtTextObject" title="Response">
  50:          <xsl:value-of select="response" />
  51:          </response>
  52:          </requestresponse>
  53:          </xsl:for-each>
  54:        </affects>
  55:          </finding>
  56:    </xsl:template>
  57:   
  58:  <xsl:template name="burp-severity">
  59:    <xsl:param name="severity" />
  60:    <source-severity>
  61:      <xsl:choose>
  62:        <xsl:when test="$severity='High'">
  63:          high<numeric>3</numeric>
  64:        </xsl:when>
  65:        <xsl:when test="$severity='Medium'">
  66:          medium<numeric>3</numeric>
  67:        </xsl:when>
  68:        <xsl:when test="$severity='Low'">
  69:          low<numeric>1</numeric>
  70:        </xsl:when>
  71:        <xsl:when test="$severity='Information'">
  72:          info<numeric>0</numeric>
  73:        </xsl:when>
  74:        <xsl:otherwise>
  75:          unknown<numeric>-1</numeric>
  76:        </xsl:otherwise>
  77:      </xsl:choose>
  78:    </source-severity>
  79:  </xsl:template>
  80:   
  81:  <xsl:template name="get-port">
  82:  <xsl:param name="host" />
  83:      <xsl:variable name="proto" select="substring-before($host, ':')"/>
  84:      <xsl:variable name="host-port" select="substring-after($host, '://')"/>
  85:      <xsl:choose>
  86:          <xsl:when test="string-length(substring-after($host-port,':'))>0">
  87:          <!-- The port is explicitly specified-->
  88:              <xsl:value-of select="substring-after($host-port,':')" />
  89:          </xsl:when>
  90:          <xsl:otherwise>
  91:              <xsl:choose>
  92:                  <xsl:when test="$proto='https'">
  93:                  443
  94:                  </xsl:when>
  95:                  <xsl:otherwise>
  96:                  80
  97:                  </xsl:otherwise>
  98:              </xsl:choose>
  99:          </xsl:otherwise>
 100:      </xsl:choose>
 101:  </xsl:template>
 102:   
 103:    <xsl:template match="/">
 104:      <magictree class="MtBranchObject" xmlns:mt="http://www.gremwell.com/magictree">
 105:      <scaninfo class="MtBranchObject">
 106:        <scan status="new" class="MtTextObject">
 107:          <xsl:attribute name="title">
 108:            <xsl:text>Burp </xsl:text>
 109:            <xsl:value-of select="/issues/@exportTime" />
 110:          </xsl:attribute>
 111:          <!--xsl:attribute name="id">
 112:            This fails during import and MagicTree goes into endless loop
 113:            Reason to use this, was to enable references of items to report
 114:            <xsl:value-of select="$my_report_signature"/>            
 115:          </xsl:attribute-->  
 116:          <xsl:text>Burp </xsl:text>
 117:          <xsl:value-of select="/issues/@exportTime" />
 118:          <version>
 119:            <xsl:value-of select="/issues/@burpVersion" />
 120:          </version>
 121:        </scan>
 122:      </scaninfo> <!-- The end of our information about the scans--> 
 123:    
 124:        <testdata class="MtBranchObject">
 125:          <xsl:for-each select="issues/issue">
 126:            <host><xsl:value-of select="host/@ip" />
 127:                  <ipproto>tcp
 128:                      <port>
 129:                      <xsl:call-template name="get-port">
 130:                          <xsl:with-param name="host" select="host"/>
 131:                      </xsl:call-template>
 132:                      <xsl:choose>
 133:                          <xsl:when test="starts-with(host,'https')">
 134:                          <tunnel>ssl
 135:                              <service>http
 136:                                  <xsl:call-template name="burp-finding">
 137:                                      <xsl:with-param name="issue" select="."/>
 138:                                  </xsl:call-template>
 139:                              </service>
 140:                          </tunnel>
 141:                          </xsl:when>
 142:                          <xsl:otherwise>
 143:                          <service>http
 144:                                  <xsl:call-template name="burp-finding">
 145:                                      <xsl:with-param name="issue" select="."/>
 146:                                  </xsl:call-template>
 147:                          </service>
 148:                          </xsl:otherwise>
 149:                      </xsl:choose>
 150:                   </port>
 151:                  </ipproto>
 152:            </host>
 153:          </xsl:for-each>
 154:        </testdata>
 155:      </magictree>
 156:    </xsl:template>
 157:  </xsl:stylesheet>




And here a screenshot of the result.


burp_magictree_import


Have fun and have a great week-end!

1 comment:

  1. Wow, you are really digging in.

    Our approach to it is grouping the findings in the report template, not in the XSLT. But your workflow may be different from ours. I'd like to hear about your streamlined reporting.

    I agree that grouping findings is important. We are now trying to design a more flexible process for grouping the findings and putting customized texts in the reports. If you have any suggestions, they are very welcome.

    Alla

    ReplyDelete