Writing Custom Agents in WebInspect By Matthew J. Fisher, MCP, CCSE, CISSP A SPI Dynamics Certified Associate Table of Contents Introduction ................................................................................................................................. 1 Running Custom Agents .......................................................................................................... 1 About this Paper....................................................................................................................... 1 Examining Existing Sessions .................................................................................................... 2 Step-By-Step Details................................................................................................................ 3 Anatomy of a Custom Agent: Persistent Cookies ................................................................... 6 Declarations ............................................................................................................................. 7 Sub Main .................................................................................................................................. 7 Function InitGlobal ................................................................................................................... 8 Sub AgentMain......................................................................................................................... 9 Sub PerformCheck................................................................................................................. 10 Function AnalyzeCookie ........................................................................................................ 11 Function GetResponseDate................................................................................................... 12 Function GetCookieDate........................................................................................................ 13 Sub FlagVulnerability ............................................................................................................. 13 Additional Techniques.............................................................................................................. 13 The Business Case for Application Security ......................................................................... 15 About SPI Labs.......................................................................................................................... 15 About SPI Dynamics ................................................................................................................. 15 About the WebInspect Product Line ....................................................................................... 16 About the Author....................................................................................................................... 16 Contact Information .................................................................................................................. 16 © 2004 SPI Dynamics, Inc. All Right Reserved. No reproduction or redistribution without written permission. Page i Introduction WebInspect is the leading commercial product for performing web application security assessments. WebInspect is produced by SPI Dynamics, and the vulnerability database (SecureBaseTM) is developed and maintained by its research and development arm, SPI Labs. At the time this paper was written, SPI Labs had developed more than 3,800 checks (or "agents") that are intrinsic to WebInspect. As with any product, however, it is sometimes desirable to extend WebInspect in a way that SPI Labs cannot anticipate or which may not be applicable beyond one's own specific environment. Custom agents permit users to develop their own checks using the same tools and techniques used by SPI Labs ­ that is, directly extending the WebInspect product in native format. In fact, custom agents don't even have to be vulnerability-related. They can leverage the web application crawling, inspection and alerting infrastructure within WebInspect to perform policy-compliance checks such as checking for warning banners or even testing functional units such as recording event timing. Running Custom Agents WebInspect custom agents are written in SAX, a script language similar toVisual Basic (VB). The modules are created within the Custom Agent Editor, which is actually a SAX Integrated Development Environment (IDE). When saved, the agents appear in the /Custom Agents directory (unless otherwise specified within the Default Settings) and will be listed as a usable check within all policies. They can then be selected for use inside a policy, and will execute within an audit automatically. Additionally, custom agents can be run manually from within the Custom Agent Editor. Custom agents can update all areas of the console: adding new sessions to the site tree, creating vulnerability alerts (at a severity determined by the agent) and full reporting. You access the Custom Agent Editor through the Tools menu or from within the Policy Manager. About this Paper Custom agents typically fall into one of two categories: those that examine existing session information for key criteria, and those that make new requests to the web application, thus creating new sessions. Agents that create new sessions are usually based on the iteration of sessions, making them extremely similar to the first type of agent. Therefore, for the purposes of learning the WebInspect Custom Agent API and writing custom agents in general, this paper deals specifically with the first type of agent ­ one that iterates through the site tree, examining each session for particular criteria. This paper first presents a high-level overview of the process (as it relates to the API). It then details each step of the overview, showing code examples and additional methods. Finally, it describes a real agent created by SPI Labs, with a line-by-line analysis of the code and use of the API. Please note that a working knowledge of Visual Basic or SAX is assumed; this paper does not provide instruction in VB. © 2004 SPI Dynamics, Inc. All Right Reserved. No reproduction or redistribution without written permission. Page 1 Examining Existing Sessions The ability to iterate through existing sessions is fundamental to writing custom agents. Even agents that make new requests to the application will typically iterate through the existing sessions, mutate the request used from the existing session, and create a new request. To begin learning the WebInspect API, we'll start by learning how to parse through and examine existing sessions, since most of the techniques used in that are likewise used in agents that create new requests, such as parsing requests and responses, setting alerts, and reporting. Testing existing sessions follows a basic pattern of selecting a collection of sessions, iterating that collection, and testing the sessions (conditionally followed by alerting and reporting). A high level overview is followed by a step-by-step detailed explanation: Overview of using the WebInspect API to examine existing sessions Initialize oWI to gain access to API interface Use oWI.oServerFactory to return a set of servers in the audit. Loop through servers Use oWI.oSessionFactory to return a set of sessions Loop through sessions Use oSession.HTTPParseRequest or oSession.HTTPParseResponse to isolate portions of the session for testing. Use oSession.UpdateIssue and oSession.Update to create alerts. Use owi.writetoauditlog as necessary to log events. End of sessions End of servers © 2004 SPI Dynamics, Inc. All Right Reserved. No reproduction or redistribution without written permission. Page 2 Step-By-Step Details 1. Initialize oWI (clsCustomCheckGateway). This is the class that allows interaction with WebInspect and must be used in any custom agents that wish to have direct access to WebInspect. Example: Initializing the oWI object Set oWI= New ClsCustomCheckGateway 2. Retrieve some set of servers : oWI.oServerFactory (clsServerFactory). This provides access to all the servers in an audit. It returns a collection of clsServer that can be iterated to provide access to individual servers. Due to the limited characteristics of server, oServerFactory is a fairly simple class: it supports the ability to remove a server via its DeleteServer method, check if a server exists in the audit via the ServerExists method, and four different ways to retrieve servers to act on: GetAllServers, GetByHost, GetByServerID, and GetByServerType. Example: Getting a collection of servers Set g_oServers = oWI.oServerFactory.GetAllServers(True) 3. Retrieve a collection of sessions: oWI.oSessionFactory (clsSessionFactory). This provides access to all the sessions in an audit and returns them as a collection of clsSession much like just the oServerFactory. However, since sessions have so many different characteristics, this class offers substantially more functionality. .GetAllSessions takes one parameter ­ whether to retrieve all sessions ready to be audited (TRUE) or sessions that have been audited (False). Example: Creating a container of sessions Set g_oSessions = oWI.oSessionFactory.GetAllSessions(True) .GetByFileNameExtension retrieves sessions whose request file has a particular extension. The last parameter is the same as the GetAllSessions() and indicate that you wish to receive sessions that are ready to be audited or not. Example: Retrieve only sessions for ASP files oWI.oSessionFactory.GetByFileNameExtension("", "asp", True) The .GetByFilter method is an extremely useful way to retrieve only very specific sessions. This method lets you search various characteristics of either the session Request or Response and returns only sessions that match the search criteria. The available criteria include Cookie Name, Cookie Values, File, File and Extension, Extension, Header Name, Headers, Header Value, Method, Path, Post Data Name, and Post Data Value. There are many more filters available; be sure to get familiar with the extremely useful API call. © 2004 SPI Dynamics, Inc. All Right Reserved. No reproduction or redistribution without written permission. Page 3 Example: Retrieve all sessions that perform a redirect: Set g_oSessions=oWI.oSessionFactory.GetByFilter("302", FilterResponseStatusCode, SessionTypeFull,,False) 4. Iterate through each server and session in each container using standard collection iteration techniques. 5. Clone and Test Each Session : oSession (clsSession). The individual session is reached by iterating through the collection of sessions returned by the oSessionFactory. In SPI Labs templates and agents, you will see the session cloned into a new duplicate session to work on, preserving the original session for later work. At this point, a new object variable name is set for the session as well; this has the added benefit of making it clear in the code that we're working on an individual session as this point. Example: Cloning a Session Set oSession = g_oSessions.CloneForReuse(True, True) When testing or performing an action on a session, you will need to get to the actual portion of the session required for the work. This benefit of the WebInspect API is most apparent here, for without it a horrendous amount of manual parsing would be required. Like the oSessionFactory object, the oSession object contains many extremely useful features; be sure to learn them well. Properties that relate to the entire session (not just the request or response portion) are accessible from the oSession object directly. These properties are: oSession.DisplayURL: the individual URL without host and path oSession.FullURL: the fully qualified URL including protocol, host, port, path and filename oSession.Host: the host to which the request was sent. oSession.Port: the port to which the request was sent. Additionally, the g_oSessions object has the HTTPParseRequest and HTTPParseResponse functions, which provide access to all elements of the sessions, cleanly parsed into individual objects. Of the many elements accessible in the API, the following are used most often. g_oSessions.HTTPParseRequest.GetHeader("User-Agent") returns the User-Agent header from the request. You would use GetHeader when you want to access a very specific header, versus accessing all headers. © 2004 SPI Dynamics, Inc. All Right Reserved. No reproduction or redistribution without written permission. Page 4 g_oSessions.HTTPParseRequest.GetPostdata("Viewstate") returns the Post Data named "Viewstate" from the request. g_oSessions.HTTPParseResponse.StatusCode returns the HTTP status code from the server response (i.e., "200" or "302") g_oSessions.HTTPParseResponse.cHeaders(2) accesses a specific header within the collection of headers. Use the Headers collection to iterate through all headers, as opposed to accessing a specific header with GetHeader. g_oSessions.HTTPParseResponse.Response returns the entire response packet including headers. g_oSessions.HTTPParseResponse.ResponseBody returns just the response body 6. Write Alerts and Log using oSession and oWI. As each session is tested, an alert may be created based on the results of that test. Alerts are performed using oSession.UpdateIssue to create the new alert. Session.Update adds it to the session. owi.FlagVulnerability creates the actual WebInspect alert and associated reporting data that appears in the console. UpdateIssue takes multiple parameters. For the sake of usability, however, these are all defined as variables in the Declarations section of each custom agent. Example: Creating a new alert with UpdateIssue owi.FlagVulnerability (clsSession, HACK_ID, HACK_SEVERITY, HACK_EXECUTION, HACK_SUMMARY, HACK_FIX, HACK_RECOMENDATIONS, HACK_REFERENCES, HACK_IMPLICATIONS,CUSTOM_AGENT_NAME oWI.WriteToAuditLog is used to track the progress of custom agents in the audit log. Note that the audit log is NOT the system log that appears in the WebInspect console; it's the text file \logs\spiauditadaptiveagents.log. The default settings in WebInspect allow several degrees of verbosity in logging: Standard, Detailed, and Debugging. When writing to the audit log, you get to specify which level of verbosity your log entry is used in. If your log entry used the log type "debugging" but the log verbosity in the default settings is set to "Standard," then your log entry will not be written. Example: Writing to the Audit Log with oWI.WriteToAuditLog Call oWI.WriteToAuditLog(Now & " " & CUSTOM_AGENT_NAME & " Starting", LOG_STANDARD) © 2004 SPI Dynamics, Inc. All Right Reserved. No reproduction or redistribution without written permission. Page 5 Anatomy of a Custom Agent: Persistent Cookies This custom agent was written by the author for a federal agency that wanted to check their web applications quickly for the use of persistent cookies in response to a specific policy created by the White House Office of Management and Budget, which severely restricts the use of persistent cookies on Federal (including Dept. of Defense) websites. While the original custom agent was written for a specific need, SPI Labs has since developed it into a standard WebInspect check, maturing the code and checks, and formatting it into the current coding style used by SPI Labs at the time. Before writing the actual agent, some planning went into it. Since this agent is meant to work on existing sessions, the first task was to identify the scope of the sessions to be retrieved. In this case, since we're only looking for persistent cookies, we can limit the scope of our agent to sessions that set cookies. We do not need to check every session, and we don't need to create new requests. Determining the actual test requirements for this agent required some short research to determine the difference between a persistent cookie and a session cookie. In short order it was determined that all cookies are the same except for one specific characteristic: the "expires=" keyword that specifies the expiration date of the cookie. If this expiration date does not exist, or it exists in the past, then the cookie is a session cookie. If the date exists and is set in the future, then it is a persistent cookie. To test this, we will look at each cookie set in the audited application, and check for an expiration date. We then must ensure the expiration date exists in the future. As part of the process of employing this as a full check within WebInspect, SPI Labs also identified the need to test for cookie versions 1 and 2, which use explicit flags to identify persistency and security. As a result, the code shown has been expanded to deal with these. Of course, once the target sessions are identified, an alert must be created. When creating an alert, you specify the severity (critical, high, medium, low or informational), the custom agent name (which appears in the console), as well as the reporting information. For the reporting information on this particular agent, the author decided to include some key information on the OMB directive itself, as well as background information on persistent cookies and the sort. The Persistent Cookies agent has eight different procedures along with the declarations. Not all custom agents need to be this modular; this is simply the preferred coding style employed by SPI Labs at the time this custom agent was turned into a finished, intrinsic check within WebInspect. Each one is briefly described, then examined line by line. © 2004 SPI Dynamics, Inc. All Right Reserved. No reproduction or redistribution without written permission. Page 6 Declarations 1. Option Explicit 2. Private Const CUSTOM_AGENT_NAME As String = "Non Persistent Cookies check" 3. Private Const HACK_ID As Long = 0 4. Private Const HACK_SCORE As Long = 50 5. Private Const HACK_SUMMARY As String = "Cookies are small bits ..." 6. Private Const HACK_EXECUTION As String ="All cookies are set by ..." 7. Private Const HACK_IMPLICATIONS As String = "Persistent cookies are stored ..." 8. Private Const HACK_FIX As String = "From a coding perspective, the only distinction ..." 9. Private Const HACK_RECOMENDATIONS As String= "Remove all 'Expires=' tags ..." 10. Private Const HACK_REFERENCES As String=" White House Office of Management ..." 11. Private oWI As clsCustomCheckGateway 12. Private g_oSessions As clsSession 13. Private g_oServers As clsServer 14. Private g_MaxCookieLifeTime As Integer Here the custom agent declares and initializes several aspects of the agent, including the name, severity, and reporting data. Sub Main 1. Sub Main() 2. Debug.Clear 3. Set oWI = New clsCustomCheckGateway 4. Call oWI.WriteToAuditLog(Now & " " & CUSTOM_AGENT_NAME & " Starting",LOG_STANDARD) 5. If ( InitGlobals() ) Then 6. Call AgentMain 7. End If 8. Call oWI.WriteToAuditLog(Now & " " & CUSTOM_AGENT_NAME & " Complete",LOG_STANDARD) 9. End Sub Sub Main performs three main functions: First, it sets the OWI object variable as a new class: clsCustomCheckGateway. Next, it initializes the global variables via the function InitGlobals with some error handling. Then, assuming the variables initialize properly, it calls AgentMain. © 2004 SPI Dynamics, Inc. All Right Reserved. No reproduction or redistribution without written permission. Page 7 The oWI object is being used to write to the audit log. It's important to note that the audit log is NOT the system log that appears in the console, but is rather /logs/spiadaptiveagents.log. oWI.WriteToAuditLog accepts two parameters: the message and the logging type. The logging type is set to the log type used in the Default Settings within WebInspect. If you set your log type to LOG_DEBUG and WI is using the Standard logging mode, then your log entry will not be recorded. Function InitGlobal 1. Private Function InitGlobals() As Boolean 2. On Error GoTo OnError 3. Set g_oServers = oWI.oServerFactory.GetAllServers(True) 4. If g_oServers.EOF Then 5. Debug.Print "No Server" 6. InitGlobals = False 7. Exit Function 8. End If 9. Call g_oServers.MoveFirst 10. Set g_oSessions = oWI.oSessionFactory.GetDistinctFiles(True) 11. If( g_oSessions.EOF ) Then 12. Debug.Print "No Sessions" 13. InitGlobals = False 14. Exit Function 15. End If 16. InitGlobals = True 17. Exit Function 18. OnError: 19. InitGlobals = False 20. End Function InitGlobal grabs the Server and Session collections, makes sure that the collections are not empty, then moves to the first item in each collection. Rather than do this in the actual iteration process, this is broken out here to provide the capability to handle errors better. On line 3, g_oServers is set to owi.oServerFactory.GetAllServers to grab the list of servers in the audit. If there are no servers to audit, then the g_oServers collection will be at the End of File (EOF) so we handle that error. Otherwise, we move to the first server in the collection with g_oServers.MoveFirst on line 9. © 2004 SPI Dynamics, Inc. All Right Reserved. No reproduction or redistribution without written permission. Page 8 Now that we have successfully moved to the first server, we need to move to the first session. The initial scoping of the custom agent occurs on line 10: the g_oSessions object being set to oWI.oSessionFactory.GetDistinctFiles. The TRUE parameter tells GetDistinctFiles to only get files that haven't been audited yet. Just as with the servers, if there are no sessions to audit (they're at .EOF) then we fail gracefully. Otherwise, InitGlobals returns TRUE to the Main procedure, at which point Main then calls AgentMain. The rest of the custom agent is handled through AgentMain, returning to the Main procedure only after AgentMain has completed all its work. Then, the Main procedure performs some final logging. Additional Techniques for Retrieving Specific Sessions (Scoping) The oSessionFactory object has many different methods available for retrieving sessions to act on. They include: Retrieving existing sessions based on file extension: Set g_oSessions = oWI.oSessionFactory.GetByFileNameExtension("", "asp", True) Retrieve existing sessions based on Filtering: The GetByFilter method of the oSessionFactory object allows retrieval of sessions based on specific characteristics. For example, you can easily retrieve just the sessions that perform a redirect by using the FilterResponseStatusCode. Set g_oSessions=oWI.oSessionFactory.GetByFilter( "302",FilterResponseStatus Code, SessionTypeLite,,True) Sub AgentMain 1. Sub AgentMain() 2. Do While Not g_oServers.EOF 3. g_oSessions.MoveFirst 4. Do While Not g_oSessions.EOF 5. If g_oSessions.ServerID = g_oServers.ServerID Then 6. Call PerformCheck(g_oSessions) 7. End If 8. Call g_oSessions.MoveNext 9. Loop 10. Call g_oServers.MoveNext 11. Loop 12. End Sub © 2004 SPI Dynamics, Inc. All Right Reserved. No reproduction or redistribution without written permission. Page 9 AgentMain iterates through the collection of servers and sessions from the work performed in InitGlobals, calling PerformCheck on each session on line 6. This is all standard collection iteration. Sub PerformCheck 1. Private Sub PerformCheck( oSession As clsSession ) 2. Dim oCookie As clsHTTPParseCookie 3. Dim analyzeReturn As Boolean 4. If( oSession.HTTPParseResponse.cSetCookies.Count < 1 ) Then 5. Exit Sub 6. End If 7. For Each oCookie In oSession.HTTPParseResponse.cSetCookies 8. If( (oCookie.Version = "1") Or (oCookie.Version = "2") ) Then 9. If Not ( oCookie.Discard ) Then 10. analyzeReturn = AnalyzeCookie(oSession.HTTPParseResponse,oCookie) 11. Else 12. analyzeReturn = True 13. End If 14. Else 15. analyzeReturn = AnalyzeCookie(oSession.HTTPParseResponse,oCookie) 16. End If 17. If Not( analyzeReturn ) Then 18. FlagVulnerability(oSession) 19. End If 20. Next 21. End Sub PerformCheck performs the testing operations as it is called by AgentMain on each session. As it tests each session, it sets the AnalyzeReturn Boolean to TRUE. At the end of PerformCheck, if the AnalyzeReturn Boolean is false, indicating a persistent cookie, then PerformCheck calls FlagVulnerability routine, then end. PerformCheck must first test to see if the session it is working on set a cookie. The HTTPParseResponse function parses the server response into clean, manageable objects, and provides all the cookies set by the server during that session as the cSetCookies. HTTPParseHTTPResponse and HTTPParseRequest are two of the mainstays of writing custom agents in WebInspect; they are well worth further investigation. © 2004 SPI Dynamics, Inc. All Right Reserved. No reproduction or redistribution without written permission. Page 10 On lines 4 - 6, PerformCheck checks the cSetCookies.Count. If it is less than 1, meaning that no cookies were set, then it exits the sub and returns to AgentMain, which then iterates to the next session and calls PerformCheck again. When the session has indeed set at least one cookie, then line 7 iterates through each cookie in the collection. First, PerformCheck must determine if the cookie is version 0, version 1, or version 2 since they determine cookie persistency in different manners. Lines 8 -16 handle versions 1 and 2 first by identifying them by their ocookie.version on line 8. If the ocookie.version is 1 or 2, then PerformCheck checks to see if the Discard flag was NOT set on line 9 with an IF block. If the Discard flag was not set, then PerformCheck passes that cookie to the AnalyzeCookie function on line 10, which performs "manual" testing of the cookie expiration date. If the Discard flag was indeed set, then AnalyzeReturn is set to true, the IF block ends, and PerformCheck finished with lines 17 and 18. This still leaves version 0 cookies to be tested. Remember that line 4 already confirmed that there are cookies set. So, if each cookie is not version 1 or 2, then it must be version 0. In this case, the rest of the IF block is skipped, to line 15, which then passes the version 0 cookie to AnalyzeCookie for "manual" testing. Function AnalyzeCookie 1. Private Function AnalyzeCookie( oResponse As clsHTTPParseResponse, oCookie As clsHTTPParseCookie ) As Boolean 2. Dim responseDate As Date 3. Dim cookieDate As Date 4. If( oCookie.Expires = "" ) Then 5. AnalyzeCookie = True 6. Exit Function 7. End If 8. responseDate = GetResponseDate(oResponse) 9. cookieDate = GetCookieDate(oCookie) 10. If( DateDiff("s", responseDate, cookieDate) > g_MaxCookieLifeTime 11. Then 12. AnalyzeCookie = False 13. Exit Function 14. End If 15. AnalyzeCookie = True 16. End Function © 2004 SPI Dynamics, Inc. All Right Reserved. No reproduction or redistribution without written permission. Page 11 This function is used to test version 0 cookies (which do not have a simple "discard" flag as do Version 1 and 2 cookies) or to test version 1 and 2 cookies that did not have their Discard flag set, since it is an optional flag. AnalyzeCookie uses the GetResponseDate and GetCookieDate functions to grab the date of the session response and cookie expiration date, and then compares the two. If the expiration date is greater than the session date, sets the AnaylzeReturn Boolean flag and returns back to PerformCheck, which then uses AnalyzeReturn as the basis for creating an alert. The WebInspect API will parse out various aspects of cookies into usable methods, events, and properties. On lines 4 - 7, AnalyzeCookie checks to see if an Expiration date is set. Any cookie that does not have an expiration date is automatically a session cookie and does not need to be alerted on. In this case, line 5 sets AnalyzeReturn to False, and exits back to PerformCheck. If there is an expiration date on the cookie, then AnalyzeCookie must check the date and test to see if it expires in the future or the past. A small problem needs to be addressed, however: the date and time standard for cookies does not translate into a usable VB date and time format, so we must manually parse it into a standard format before we can compare the two dates and times. To do this, we use the GetResponseDate and GetCookieDate functions on lines 8 and 9 respectively. Now that the dates and times of both the server's response time and the cookie are standardized, they can be tested using the VB DateDiff function. Line 10 uses this function and tests to see if the difference between the time the cookie was set and the time it expires is greater than the g_MaxCookieLifetime variable, which establishes any allowable time "buffers." G_MaxCookieLifeTime can be set to zero to create no buffer. Function GetResponseDate 1. Private Function GetResponseDate( oResponse As clsHTTPParseResponse ) As Date 2. Dim strDate As String 3. Dim respondeDate As Date 4. strDate = oResponse.GetHeader("Date") 5. If( strDate = "" ) Then 6. Debug.Print "Can't find date header " & oResponse.Response 7. GetResponseDate = Now 8. Exit Function 9. End If 10. respondeDate = Mid(strDate, InStr(strDate,",")+1, 21) 11. GetResponseDate = respondeDate 12. End Function © 2004 SPI Dynamics, Inc. All Right Reserved. No reproduction or redistribution without written permission. Page 12 GetResponseDate formats the date and time from the session response header into a date-type usable by SAX. If no date header is present in the server response, then GetResponseDate sets the response date/time to Now. Line 4 shows the oResponse object's GetHeader being used to get a specific header from the collection of HTTP headers returned by the server. Function GetCookieDate 1. Private Function GetCookieDate( oCookie As clsHTTPParseCookie ) As Date 2. Dim strDate As String 3. Dim responseDate As Date 4. strDate = oCookie.Expires 5. responseDate = Mid(strDate, InStr(strDate,",")+1, 21) 6. GetCookieDate = responseDate 7. End Function The GetCookieDate function Gets the date and time from the cookie expiration date, and reformats it into a data-type usable by SAX. Sub FlagVulnerability 1. Private Sub FlagVulnerability( oSession As clsSession ) 2. oWI.WriteToAuditLog("Vulnerability was found on " & oSession.FullURL,LOG_DETAILED) 3. Call oSession.UpdateIssue(HACK_ID, HACK_SEVERITY, HACK_EXECUTION, HACK_SUMMARY, HACK_FIX, HACK_RECOMENDATIONS, HACK_REFERENCES, HACK_IMPLICATIONS, CUSTOM_AGENT_NAME) 4. Call oSession.Update(True, True) 5. End Sub This is the final routine in the custom agent. The FlagVulnerability routine is called by PerformCheck when AnalyzeReturn=TRUE. This procedure performs the actual alerting that updates the WebInspect console. Line 3 creates the alert by identifying the hackID, the reporting data, and the description. Line 4 then actually sets the alert. FlagVulnerability is the deepest the agent gets; once FlagVulnerability ends, control goes back to PerformCheck, which then reverts back to AgentMain. Additional Techniques The WebInspect Custom Agent API contains features that permit much more than what has been demonstrated in this paper. Be sure to explore the API, and remember that you can also use COM objects within your custom agents to greatly extend their capabilities. © 2004 SPI Dynamics, Inc. All Right Reserved. No reproduction or redistribution without written permission. Page 13 Here is a snippet from an agent that was written to perform an MD5 hash on all the sessions in a site, and write them out to a text file. This is considerably more straightforward than the agent we just examined, since neither testing nor alerting is necessary; simply iterate the sessions, hash each one, and move to the next. MD5 Hashing All Sessions using clsMD5 1. Dim filebuffer As String 2. filebuffer="" 3. Do While Not g_oSessions.EOF 4. Set oSession = g_oSessions.CloneForReuse(True, True) 5. Dim md5 As New clsMD5 6. filebuffer=filebuffer & vbCrLf & Date & "," & Time & "," & oSession.FullURL & "," & oSession.DisplayURL(False) & ", " & md5.MD5(oSession.HTTPParseResponse.ResponseBody) & "," & g_oServers.Host 7. g_oSessions.MoveNext ' Increment the session enumerator to the next session in the collection 8. Loop 9. Call g_oSessions.MoveFirst 'Done with that server, so move to the first session. 10. Call g_oServers.MoveNext ' Of the next server 11. Loop ' Loop through all the servers. Once done with this loop, we've gone through all sessions on all servers 12. oWI.WriteFile (filebuffer, "sessionhashes.txt") Line 6 hashesg and builds the filebuffer, adding a string with each iteration that contains the current date and time, the full URL of the session being called, the MD5 hash of that session, and the hostname (in case the agent is run against multiple hosts at the same time). On line 13, the buffer is written to a file using the oWI object's WriteFile method. Note that within the WebInspect API, you can write only an entire file at a time using WriteFile, so you must build the file one line at a time (as Line 6 does). Of course, by referencing a COM object within the agent, you can use the Microsoft File System Object if you desire, or even dump the information directly into a spreadsheet by using the VBA objects. © 2004 SPI Dynamics, Inc. All Right Reserved. No reproduction or redistribution without written permission. Page 14 The Business Case for Application Security Whether a security breach is made public or confined internally, the fact that a hacker has accessed your sensitive data should be a huge concern to your company, your shareholders and, most importantly, your customers. SPI Dynamics has found that the majority of companies that are vigilant and proactive in their approach to application security are better protected. In the long run, these companies enjoy a higher return on investment for their e-business ventures. About SPI Labs SPI Labs is the dedicated application security research and testing team of SPI Dynamics. Composed of some of the industry's top security experts, SPI Labs is focused specifically on researching security vulnerabilities at the web application layer. The SPI Labs mission is to provide objective research to the security community and all organizations concerned with their security practices. SPI Dynamics uses direct research from SPI Labs to provide daily updates to WebInspect, the leading Web application security assessment software. SPI Labs engineers comply with the standards proposed by the Internet Engineering Task Force (IETF) for responsible security vulnerability disclosure. SPI Labs policies and procedures for disclosure are outlined on the SPI Dynamics web site at: http://www.spidynamics.com/spilabs.html. About SPI Dynamics SPI Dynamics, the expert in web application security assessment, provides software and services to help enterprises protect against the loss of confidential data through the web application layer. The company's flagship product line, WebInspect, assesses the security of an organization's applications and web services, the most vulnerable yet least secure IT infrastructure component. Since its inception, SPI Dynamics has focused exclusively on web application security. SPI Labs, the internal research group of SPI Dynamics, is recognized as the industry's foremost authority in this area. Software developers, quality assurance professionals, corporate security auditors and security practitioners use WebInspect products throughout the application lifecycle to identify security vulnerabilities that would otherwise go undetected by traditional measures. The security assurance provided by WebInspect helps Fortune 500 companies and organizations in regulated industries -- including financial services, health care and government -- protect their sensitive data and comply with legal mandates and regulations regarding privacy and information security. SPI Dynamics is privately held with headquarters in Atlanta, Georgia. © 2004 SPI Dynamics, Inc. All Right Reserved. No reproduction or redistribution without written permission. Page 15 About the WebInspect Product Line The WebInspect product line ensures the security of your entire network with intuitive, intelligent, and accurate processes that dynamically scan standard and proprietary web applications to identify known and unidentified application vulnerabilities. WebInspect products provide a new level of protection for your critical business information. With WebInspect products, you find and correct vulnerabilities at their source, before attackers can exploit them. Whether you are an application developer, security auditor, QA professional or security consultant, WebInspect provides the tools you need to ensure the security of your web applications through a powerful combination of unique Adaptive-AgentTM technology and SPI Dynamics' industry-leading and continuously updated vulnerability database, SecureBaseTM. Through Adaptive-Agent technology, you can quickly and accurately assess the security of your web content, regardless of your environment. WebInspect enables users to perform security assessments for any web application, including these industry-leading application platforms: IBM WebSphere Macromedia ColdFusion Lotus Domino Oracle Application Server Macromedia JRun BEA Weblogic Jakarta Tomcat About the Author Matthew Fisher is a senior security engineer at SPI Dynamics. He has also held key positions at Computer Sciences Corporation and Digex, where he was lead technical advisor on large-scale, highly-structured, enterprise-wide web applications for Fortune 500 companies. Mr. Fisher currently provides web application security consulting and technical advice for a variety of government, healthcare, financial, and manufacturing organizations. He holds multiple certifications from Microsoft, Checkpoint, and ISC2 including the CNA, MCP, CCSA, CCSE and CISSP. Contact Information SPI Dynamics 115 Perimeter Center Place Suite 270 Atlanta, GA 30346 Telephone: (678) 781-4800 Fax: (678) 781-4850 Email: info@spidynamics.com Web: www.spidynamics.com © 2004 SPI Dynamics, Inc. All Right Reserved. No reproduction or redistribution without written permission. Page 16