1 / 57

Fortify Source Code Analysis Suite Overview: Section Objectives

Learn about the major components of Fortify SCA and how it analyzes source code to find vulnerabilities. Understand the translation, analysis, and audit processes.

hburgess
Download Presentation

Fortify Source Code Analysis Suite Overview: Section Objectives

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. Fortify Source Code Analysis Suite Overview:Section Objectives • In this section, you will learn: • Major components of SCA • How SCA processes various source code into one representative model • How SCA Analyzers and Rules work together to find possible vulnerabilities in source code • How to use SCA results

  2. Fortify Source Code Analysis Suite Overview • Fortify SCA and its Components • Fortify SCA Translation • Fortify SCA Analysis • Fortify SCA Audit

  3. Threat Intelligence Knowledge of Secure Software Vulnerability Identification Source Code Analyzer (SCA) Program Trace Analyzer (PTA) Real-Time Analyzer (RTA) Remediation Governance Fortify 360

  4. Static source code analysis. Visual interface for analysis of software vulnerabilities. Integrated vulnerability detection into Integrated Development Environments (IDEs). Management for multiple audit projects from a single centralized console. Fortify SCA Audit WorkBench (AWB) Secure Coding Plug-ins Fortify SCA Suite Fortify 360 Server

  5. Fortify SCA Process Flow Translation Analysis Audit Source Code to Fortify Intermediate Model Fortify Intermediate Model to List of Possible Vulnerabilities Vulnerability Verification, Triage and Remediation

  6. Fortify Source Code Analysis Suite Overview • Fortify SCA and its Components • Fortify SCA Translation • Fortify SCA Analysis • Fortify SCA Audit

  7. Fortify SCA – Translation Translation Analysis Audit Source Code to Fortify Intermediate Model Fortify Intermediate Model to List of Possible Vulnerabilities Vulnerability Verification, Triage and Remediation

  8. Fortify SCA – Translation (cont’d) Translate Scan Diagnose Build Integration - Touch - Touchless Source Code to Fortify Intermediate Model Fortify Intermediate Model to FPR File Vulnerability Triage and Remediation GUI (IDE & AWB) Translation Phase

  9. Translation Phase = Compilation • Source code need to be in a compile-able state • C / C++: needs C/C++ compiler to run SCA translator • Java: Java code is translated directly by SCA translator • Partial results can be obtained if the project is not build-able • .NET: Solutions must be build-able and compiled in Debug configuration to create a program database (pdb) file • SCA translator expects .NET assemblies and the pdb files. • Other languages such as JavaScript, SQL, PHP are translated directly by SCA translator

  10. Normalized Syntax Tree (NST Files) • All language translated into a single format • NST Files • Uniform representation of a full application • X-Tier™ Analysis • Static analysis across different tiers of an application

  11. Fortify Source Code Analysis Suite Overview • Fortify SCA and its Components • Fortify SCA Translation • Fortify SCA Analysis • Fortify SCA Audit

  12. Fortify SCA – Analysis Analysis Translation Audit Fortify Intermediate Model to List of Possible Vulnerabilities Source Code to Fortify Intermediate Model Vulnerability Verification, Triage and Remediation

  13. Fortify SCA – Analysis (cont’d) Analysis Phase

  14. Analysis Phase = Analyzers + Rules • Analyzers • Comprised of six distinct analyzers • Analyzers are static analysis algorithms • Each analyzer is associate with a rule type • Rules • Vulnerability definition (pattern) • There are as many number of rule types as the number of analyzers • Each rule type works with one analyzer • Each rule type has its own syntax • Secure Coding Rulepacks • A set of files that contains rules

  15. Fortify SCA Analyzer • Fortify SCA provides six primary analyzers • Data flow • Control flow • Structural • Semantic • Configuration • buffer

  16. Understanding Data Flow – Sample importjava.sql.*; public classSQLInjection { public static void main (Stringargs[]) { Connectionconn = null; try { StringuserName = args [0]; Stringpasswd = args [1]; Stringquery = "select uname, passwd from users where uname like "+userName+"%"; conn = DriverManager.getConnection ("jdbc:odbc:logistics", "admin", "letmein"); Statementstmnt = conn.createStatement (); ResultSetrs = stmnt.executeQuery (query); while ( rs.next() ) { ... } rs.close (); stmnt.close (); conn.close (); } catch (SQLExceptionerr) { err.printStackTrace (); } } }

  17. Data Flow • Find vulnerabilities where non-trusted input can potentially control application operation. • Vulnerabilities to injection attacks • Analyzer uses global taint propagation to trace the flow of non-trusted data • Source • Non-trusted (user controlled) input • Sink • Potentially dangerous function call or operation

  18. Data Flow (cont’d) importjava.sql.*; public classSQLInjection { public static void main (Stringargs[]) { Connectionconn = null; try { StringuserName = args [0]; Stringpasswd = args [1]; Stringquery = "select uname, passwd from users where uname like "+userName+"%"; conn = DriverManager.getConnection ("jdbc:odbc:logistics", "admin", "letmein"); Statementstmnt = conn.createStatement (); ResultSetrs = stmnt.executeQuery (query); while ( rs.next() ) { ... } rs.close (); stmnt.close (); conn.close (); } catch (SQLExceptionerr) { err.printStackTrace (); } } } Source

  19. Data Flow (cont’d) importjava.sql.*; public classSQLInjection { public static void main (Stringargs[]) { Connectionconn = null; try { StringuserName = args [0]; Stringpasswd = args [1]; Stringquery = "select uname, passwd from users where uname like "+userName+"%"; conn = DriverManager.getConnection ("jdbc:odbc:logistics", "admin", "letmein"); Statementstmnt = conn.createStatement (); ResultSetrs = stmnt.executeQuery (query); while ( rs.next() ) { ... } rs.close (); stmnt.close (); conn.close (); } catch (SQLExceptionerr) { err.printStackTrace (); } } } Source args[] is tainted

  20. Data Flow (cont’d) importjava.sql.*; public classSQLInjection { public static void main (Stringargs[]) { Connectionconn = null; try { StringuserName = args [0]; Stringpasswd = args [1]; Stringquery = "select uname, passwd from users where uname like "+userName+"%"; conn = DriverManager.getConnection ("jdbc:odbc:logistics", "admin", "letmein"); Statementstmnt = conn.createStatement (); ResultSetrs = stmnt.executeQuery (query); while ( rs.next() ) { ... } rs.close (); stmnt.close (); conn.close (); } catch (SQLExceptionerr) { err.printStackTrace (); } } } Source args[] is tainted Taint propagated to userName

  21. Data Flow (cont’d) importjava.sql.*; public classSQLInjection { public static void main (Stringargs[]) { Connectionconn = null; try { StringuserName = args [0]; Stringpasswd = args [1]; Stringquery = "select uname, passwd from users where uname like "+userName+"%"; conn = DriverManager.getConnection ("jdbc:odbc:logistics", "admin", "letmein"); Statementstmnt = conn.createStatement (); ResultSetrs = stmnt.executeQuery (query); while ( rs.next() ) { ... } rs.close (); stmnt.close (); conn.close (); } catch (SQLExceptionerr) { err.printStackTrace (); } } } Source args[] is tainted Taint propagated to userName Tainted input userName used in assignment

  22. Data Flow (cont’d) importjava.sql.*; public classSQLInjection { public static void main (Stringargs[]) { Connectionconn = null; try { StringuserName = args [0]; Stringpasswd = args [1]; Stringquery = "select uname, passwd from users where uname like "+userName+"%"; conn = DriverManager.getConnection ("jdbc:odbc:logistics", "admin", "letmein"); Statementstmnt = conn.createStatement (); ResultSetrs = stmnt.executeQuery (query); while ( rs.next() ) { ... } rs.close (); stmnt.close (); conn.close (); } catch (SQLExceptionerr) { err.printStackTrace (); } } } Source args[] is tainted Taint propagated to userName Sink Tainted input userName used in assignment

  23. Data Flow (cont’d) importjava.sql.*; public classSQLInjection { public static void main (Stringargs[]) { Connectionconn = null; try { StringuserName = args [0]; Stringpasswd = args [1]; Stringquery = "select uname, passwd from users where uname like "+userName+"%"; conn = DriverManager.getConnection ("jdbc:odbc:logistics", "admin", "letmein"); Statementstmnt = conn.createStatement (); ResultSetrs = stmnt.executeQuery (query); while ( rs.next() ) { ... } rs.close (); stmnt.close (); conn.close (); } catch (SQLExceptionerr) { err.printStackTrace (); } } } Source args[] is tainted Taint propagated to userName Sink Tainted input userName used in assignment Vulnerability Reported

  24. Understanding Control Flow – Sample private void cmdLogin_Click(object sender, System.EventArgs e) { Label lblMsg = null; try { stringtxtUser = Request.Form["txtUsername"]; stringtxtPassword = Request.Form["txtPassword"]; stringstrCnx ="server=localhost;database=northwind;uid=sa;pwd=;"; SqlConnection cnx = new SqlConnection(strCnx); cnx.Open(); string strQry ="SELECT Count(*) FROM Users WHERE UserName='" + txtUser + "' AND Password='" + txtPassword + "'"; int intRecs; SqlCommand cmd = new SqlCommand(strQry, cnx); intRecs = (int)cmd.ExecuteScalar(); if (intRecs > 0) { FormsAuthentication.RedirectFromLoginPage(txtUser, false); cnx.Close(); } else { lblMsg.Text = "Login attempt failed."; } } catch (Exception err) { Response.Write(err.StackTrace.ToString()); }

  25. Control Flow • Detects potentially dangerous sequences of operations/function calls • Control Flow analyzer simulates state machines using your source code (NST files) to determine the state transitions • Each state machines has an error state which represents the state where a vulnerability could be exploited • Control Flow rules are definition of the state machines

  26. Control Flow (cont’d) private void cmdLogin_Click(object sender, System.EventArgs e) { Label lblMsg = null; try { stringtxtUser = Request.Form["txtUsername"]; stringtxtPassword = Request.Form["txtPassword"]; stringstrCnx ="server=localhost;database=northwind;uid=sa;pwd=;"; SqlConnection cnx = new SqlConnection(strCnx); cnx.Open(); string strQry ="SELECT Count(*) FROM Users WHERE UserName='" + txtUser + "' AND Password='" + txtPassword + "'"; int intRecs; SqlCommand cmd = new SqlCommand(strQry, cnx); intRecs = (int)cmd.ExecuteScalar(); if (intRecs > 0) { FormsAuthentication.RedirectFromLoginPage(txtUser, false); cnx.Close(); } else { lblMsg.Text = "Login attempt failed."; } } catch (Exception err) { Response.Write(err.StackTrace.ToString()); } Variable initialized & assigned

  27. Control Flow (cont’d) private void cmdLogin_Click(object sender, System.EventArgs e) { Label lblMsg = null; try { stringtxtUser = Request.Form["txtUsername"]; stringtxtPassword = Request.Form["txtPassword"]; stringstrCnx ="server=localhost;database=northwind;uid=sa;pwd=;"; SqlConnection cnx = new SqlConnection(strCnx); cnx.Open(); string strQry ="SELECT Count(*) FROM Users WHERE UserName='" + txtUser + "' AND Password='" + txtPassword + "'"; int intRecs; SqlCommand cmd = new SqlCommand(strQry, cnx); intRecs = (int)cmd.ExecuteScalar(); if (intRecs > 0) { FormsAuthentication.RedirectFromLoginPage(txtUser, false); cnx.Close(); } else { lblMsg.Text = "Login attempt failed."; } } catch (Exception err) { Response.Write(err.StackTrace.ToString()); } Variable initialized & assigned Connection closed

  28. Control Flow (cont’d) private void cmdLogin_Click(object sender, System.EventArgs e) { Label lblMsg = null; try { stringtxtUser = Request.Form["txtUsername"]; stringtxtPassword = Request.Form["txtPassword"]; stringstrCnx ="server=localhost;database=northwind;uid=sa;pwd=;"; SqlConnection cnx = new SqlConnection(strCnx); cnx.Open(); string strQry ="SELECT Count(*) FROM Users WHERE UserName='" + txtUser + "' AND Password='" + txtPassword + "'"; int intRecs; SqlCommand cmd = new SqlCommand(strQry, cnx); intRecs = (int)cmd.ExecuteScalar(); if (intRecs > 0) { FormsAuthentication.RedirectFromLoginPage(txtUser, false); cnx.Close(); } else { lblMsg.Text = "Login attempt failed."; } } catch (Exception err) { Response.Write(err.StackTrace.ToString()); } Variable initialized & assigned Connection closed Safe Sequence

  29. Control Flow (cont’d) private void cmdLogin_Click(object sender, System.EventArgs e) { Label lblMsg = null; try { stringtxtUser = Request.Form["txtUsername"]; stringtxtPassword = Request.Form["txtPassword"]; stringstrCnx ="server=localhost;database=northwind;uid=sa;pwd=;"; SqlConnection cnx = new SqlConnection(strCnx); cnx.Open(); string strQry ="SELECT Count(*) FROM Users WHERE UserName='" + txtUser + "' AND Password='" + txtPassword + "'"; int intRecs; SqlCommand cmd = new SqlCommand(strQry, cnx); intRecs = (int)cmd.ExecuteScalar(); if (intRecs > 0) { FormsAuthentication.RedirectFromLoginPage(txtUser, false); cnx.Close(); } else { lblMsg.Text = "Login attempt failed."; } } catch (Exception err) { Response.Write(err.StackTrace.ToString()); } Variable initialized & assigned

  30. Control Flow (cont’d) private void cmdLogin_Click(object sender, System.EventArgs e) { Label lblMsg = null; try { stringtxtUser = Request.Form["txtUsername"]; stringtxtPassword = Request.Form["txtPassword"]; stringstrCnx ="server=localhost;database=northwind;uid=sa;pwd=;"; SqlConnection cnx = new SqlConnection(strCnx); cnx.Open(); string strQry ="SELECT Count(*) FROM Users WHERE UserName='" + txtUser + "' AND Password='" + txtPassword + "'"; int intRecs; SqlCommand cmd = new SqlCommand(strQry, cnx); intRecs = (int)cmd.ExecuteScalar(); if (intRecs > 0) { FormsAuthentication.RedirectFromLoginPage(txtUser, false); cnx.Close(); } else { lblMsg.Text = "Login attempt failed."; } } catch (Exception err) { Response.Write(err.StackTrace.ToString()); } Variable initialized & assigned Control Flow Observe all possible paths

  31. Control Flow (cont’d) private void cmdLogin_Click(object sender, System.EventArgs e) { Label lblMsg = null; try { stringtxtUser = Request.Form["txtUsername"]; stringtxtPassword = Request.Form["txtPassword"]; stringstrCnx ="server=localhost;database=northwind;uid=sa;pwd=;"; SqlConnection cnx = new SqlConnection(strCnx); cnx.Open(); string strQry ="SELECT Count(*) FROM Users WHERE UserName='" + txtUser + "' AND Password='" + txtPassword + "'"; int intRecs; SqlCommand cmd = new SqlCommand(strQry, cnx); intRecs = (int)cmd.ExecuteScalar(); if (intRecs > 0) { FormsAuthentication.RedirectFromLoginPage(txtUser, false); cnx.Close(); } else { lblMsg.Text = "Login attempt failed."; } } catch (Exception err) { Response.Write(err.StackTrace.ToString()); } Variable initialized & assigned Observes all possible paths Analyze until cnx is out of scope

  32. Control Flow (cont’d) private void cmdLogin_Click(object sender, System.EventArgs e) { Label lblMsg = null; try { stringtxtUser = Request.Form["txtUsername"]; stringtxtPassword = Request.Form["txtPassword"]; stringstrCnx ="server=localhost;database=northwind;uid=sa;pwd=;"; SqlConnection cnx = new SqlConnection(strCnx); cnx.Open(); string strQry ="SELECT Count(*) FROM Users WHERE UserName='" + txtUser + "' AND Password='" + txtPassword + "'"; int intRecs; SqlCommand cmd = new SqlCommand(strQry, cnx); intRecs = (int)cmd.ExecuteScalar(); if (intRecs > 0) { FormsAuthentication.RedirectFromLoginPage(txtUser, false); cnx.Close(); } else { lblMsg.Text = "Login attempt failed."; } } catch (Exception err) { Response.Write(err.StackTrace.ToString()); } Vulnerability Reported Variable initialized & assigned Observes all possible paths Analyze until cnx is out of scope

  33. Control Flow (cont’d) private void cmdLogin_Click(object sender, System.EventArgs e) { Label lblMsg = null; try { stringtxtUser = Request.Form["txtUsername"]; stringtxtPassword = Request.Form["txtPassword"]; stringstrCnx ="server=localhost;database=northwind;uid=sa;pwd=;"; SqlConnection cnx = new SqlConnection(strCnx); cnx.Open(); string strQry ="SELECT Count(*) FROM Users WHERE UserName='" + txtUser + "' AND Password='" + txtPassword + "'"; int intRecs; SqlCommand cmd = new SqlCommand(strQry, cnx); intRecs = (int)cmd.ExecuteScalar(); if (intRecs > 0) { FormsAuthentication.RedirectFromLoginPage(txtUser, false); cnx.Close(); } else { lblMsg.Text = "Login attempt failed."; } } catch (Exception err) { Response.Write(err.StackTrace.ToString()); } Variable initialized & assigned Observes all possible paths

  34. Control Flow (cont’d) private void cmdLogin_Click(object sender, System.EventArgs e) { Label lblMsg = null; try { stringtxtUser = Request.Form["txtUsername"]; stringtxtPassword = Request.Form["txtPassword"]; stringstrCnx ="server=localhost;database=northwind;uid=sa;pwd=;"; SqlConnection cnx = new SqlConnection(strCnx); cnx.Open(); string strQry ="SELECT Count(*) FROM Users WHERE UserName='" + txtUser + "' AND Password='" + txtPassword + "'"; int intRecs; SqlCommand cmd = new SqlCommand(strQry, cnx); intRecs = (int)cmd.ExecuteScalar(); if (intRecs > 0) { FormsAuthentication.RedirectFromLoginPage(txtUser, false); cnx.Close(); } else { lblMsg.Text = "Login attempt failed."; } } catch (Exception err) { Response.Write(err.StackTrace.ToString()); } Variable initialized & assigned Observes all possible paths Analyze until cnx is out of scope

  35. Control Flow (cont’d) private void cmdLogin_Click(object sender, System.EventArgs e) { Label lblMsg = null; try { stringtxtUser = Request.Form["txtUsername"]; stringtxtPassword = Request.Form["txtPassword"]; stringstrCnx ="server=localhost;database=northwind;uid=sa;pwd=;"; SqlConnection cnx = new SqlConnection(strCnx); cnx.Open(); string strQry ="SELECT Count(*) FROM Users WHERE UserName='" + txtUser + "' AND Password='" + txtPassword + "'"; int intRecs; SqlCommand cmd = new SqlCommand(strQry, cnx); intRecs = (int)cmd.ExecuteScalar(); if (intRecs > 0) { FormsAuthentication.RedirectFromLoginPage(txtUser, false); cnx.Close(); } else { lblMsg.Text = "Login attempt failed."; } } catch (Exception err) { Response.Write(err.StackTrace.ToString()); } Vulnerability Reported Variable initialized & assigned Observes all possible paths Analyze until cnx is out of scope

  36. Structural • Detects potentially dangerous flaws in the structure or definition of a program • Wide varieties of flaws related to source Structure: • Insecure declaration and use of variables • Overly broad catch blocks • Comments that contain sensitive information, such as password

  37. Structural (cont’d) • Erroneous String comparison publicstaticvoidaddResourceRequest( WikiContext ctx, String type, String resource ) { ... if( type ==RESOURCE_SCRIPT) { resourceString = "<script type='text/javascript' src='"+resource+"'></script>"; } elseif( type ==RESOURCE_STYLESHEET ) { resourceString = "<link rel='stylesheet' type='text/css' href='"+resource+"' />"; } elseif( type ==RESOURCE_INLINECSS ) { resourceString = "<style type='text/css'>\n"+resource+"\n</style>\n"; } elseif( type ==RESOURCE_JSFUNCTION ) { resourceString = resource; } ... Using the == operator does not compare the values of the objects but the objects themselves. Always use the equals () method to compare the values of two strings.

  38. Notice how the comment in the empty catch block. However the code has made it into production now ! Structural (cont’d) • Empty catch block try { page = m_engine.getURLConstructor().parsePage( requestContext, request, m_engine.getContentEncoding() ); if( page !=null) { try { String finalPage = getFinalPageName( page ); if( finalPage !=null) { page = finalPage; } } catch( ProviderException e ) { // FIXME: Should not ignore! } returnpage; } } catch( IOException e ) { log.error("Unable to create context", e ); thrownewInternalWikiException("Big internal booboo, please check logs."); } ...

  39. Structural (cont’d) • Password in Comment //DB password is adminadmin //Set the connection string for the database string connectionstring="Initial Catalog=TestCatalog; Data Source=myDataSource;user id=admin;password=adminadmin;"; string tainted_query= "Select name=" + args[1].Clone() + " fromEmployees"; Password written in a comment block

  40. Structural (cont’d) • Member variables are not thread safe • Unless a Servlet implements the SingleThreadModel, it is a singleton importjavax.servlet.http.*; importjava.io.*; publicclassCreditCardServletextendsHttpServlet { privateStringcreditCardNum; publicvoid doPost (HttpServletRequest request, HttpServletResponse response) throws IOException { creditCardNum = request.getParameter("CC_NUM"); if (creditCardNum != null) { PrintWriterout = response.getWriter(); out.println (creditCardNum); } } } } The value of creditCardNum will keep changing as the application serves web requests. These requests are potentially from different users, so it may expose one user’s data to another

  41. Semantic • Looks for unsafe function calls based on their signature • Signature consists of • Package / namespace • Return types of the method • Types passed to the method • Has similarity to a search function • More limited: Semantic look only at function calls • More powerful: Knows about object oriented concepts • Ability to specify object type that is expected in the function signature

  42. Semantic (cont’d) importjava.sql.*; public classSQLInjection { public static void main (Stringargs[]) { Connectionconn = null; try { StringuserName = args [0]; Stringpasswd = args [1]; Stringquery = "select uname, passwd from users where uname like "+userName+"%"; conn = DriverManager.getConnection ("jdbc:odbc:logistics", "admin", "letmein"); Statementstmnt = conn.createStatement (); ResultSetrs = stmnt.executeQuery (query); while ( rs.next() ) { ... } rs.close (); stmnt.close (); conn.close (); } catch (SQLExceptionerr) { err.printStackTrace (); } } } Hardcoded Password

  43. Semantic (cont’d) char *cmd = new char[256]; const char *safe = "safe_command "; int returnCode; while (1) { cout << "Enter command: "; cin >> cmd; if (strncmp(cmd, safe, strlen(safe)) != 0) { cout << "Unsafe command entered\n"; break; } returnCode = system(cmd); cout << "Command returned " << returnCode << '\n'; } Dangerous Function/Operator

  44. Configuration • Uses XPath queries and name-value matching to identify issues in application’s configuration files • web.xml - J2EE applications • web.config - .NET web applications • other.xml - any well-formed XML files • Properties files - name/value pairs • Primarily searches application configuration files for • Mistakes • Omissions • Weaknesses

  45. Configuration (cont’d) • Incomplete Error Handling … </welcome-file-list> <error-page> <error-code>403</error-code> <location>/error/Forbidden.html</location> </error-page> <resource-ref> … Missing java.lang.Throwable, error code 404, and 500

  46. Configuration (cont’d) • Misconfiguration: Directory Listing <servlet> ... <init-param> <param-name>listings</param-name> <param-value>true</param-value> </init-param> … Listings is set to true. Allow users to view files in the file system.

  47. buffer • buffer analyzer detect access to buffer beyond its boundaries • Converts code to integer programs • Uses constraint solver to detect possible access beyond the buffer boundaries. • Trace the buffer size used in allocation and buf operations • Memory allocation: malloc(), static string, etc • Buffer operation: strcpy(), strncat(), etc

  48. buffer (cont’d) • Buffer Overflow voidfoo() { char* str = "hello world"; char*buf = (char*)malloc(strlen(str)+5); strcpy(buf, str); strcat(buf, "overflow"); return 0; } Buffer size = 16 Written 12 bytes Written 8 bytes

  49. Secure Coding Rules - Fortify • Fortify Rules cover commonly use API • Library that comes with the programming language • Common 3rd party and extension library for the language • Developed by Fortify Security Research Group (SRG) • New rule update every quarter • End of February, May, August, and November • Distributed as encrypted files • Fortify’s intellectual property

  50. Secure Coding Rules - Custom • Why develop custom rules? • Create precise validation rules to improve results accuracy • Enforce your organization security or coding practices • Need to cover your proprietary libraries • Fortify doesn’t know about your library • Need to cover libraries that Fortify Rules have not covered • Contact Fortify and request for rule coverage on the libraries • Custom rule development class is available from Fortify • Different classes for different programming languages

More Related