Bug Pattern: PREDICTABLE_RANDOM
The use of a predictable random value can lead to vulnerabilities when used in certain security critical contexts. For example, when the value is used as:
a CSRF token: a predictable token can lead to a CSRF attack as an attacker will know the value of the token a password reset token (sent by email): a predictable password token can lead to an account takeover, since an attacker will guess the URL of the change password form any other secret valueA quick fix could be to replace the use of java.util.Random with something stronger, such as java.security.SecureRandom .
Vulnerable Code:
String generateSecretToken() { Random r = new Random(); return Long.toHexString(r.nextLong()); }Solution:
import org.apache.commons.codec.binary.Hex; String generateSecretToken() { SecureRandom secRandom = new SecureRandom(); byte[] result = new byte[32]; secRandom.nextBytes(result); return Hex.encodeHexString(result); }References
Cracking Random Number Generators - Part 1 (http://jazzy.id.au)
CERT: MSC02-J. Generate strong random numbers
CWE-330: Use of Insufficiently Random Values
Predicting Struts CSRF Token (Example of real-life vulnerability and exploitation) Predictable pseudorandom number generator (Scala)Bug Pattern: PREDICTABLE_RANDOM_SCALA
The use of a predictable random value can lead to vulnerabilities when used in certain security critical contexts. For example, when the value is used as:
a CSRF token: a predictable token can lead to a CSRF attack as an attacker will know the value of the token a password reset token (sent by email): a predictable password token can lead to an account takeover, since an attacker will guess the URL of the change password form any other secret valueA quick fix could be to replace the use of java.util.Random with something stronger, such as java.security.SecureRandom .
Vulnerable Code:
import scala.util.Random def generateSecretToken() { val result = Seq.fill(16)(Random.nextInt) return result.map("%02x" format _).mkString }Solution:
import java.security.SecureRandom def generateSecretToken() { val rand = new SecureRandom() val value = Array.ofDim[Byte](16) rand.nextBytes(value) return value.map("%02x" format _).mkString }References
Cracking Random Number Generators - Part 1 (http://jazzy.id.au)
CERT: MSC02-J. Generate strong random numbers
CWE-330: Use of Insufficiently Random Values
Predicting Struts CSRF Token (Example of real-life vulnerability and exploitation) Untrusted servlet parameterBug Pattern: SERVLET_PARAMETER
The Servlet can read GET and POST parameters from various methods. The value obtained should be considered unsafe. You may need to validate or sanitize those values before passing them to sensitive APIs such as:
SQL query (May lead to SQL injection) File opening (May lead to path traversal) Command execution (Potential Command injection) HTML construction (Potential XSS) etc...Reference
CWE-20: Improper Input Validation Untrusted Content-Type headerBug Pattern: SERVLET_CONTENT_TYPE
The HTTP header Content-Type can be controlled by the client. As such, its value should not be used in any security critical decisions.
Reference
CWE-807: Untrusted Inputs in a Security Decision Untrusted Hostname headerBug Pattern: SERVLET_SERVER_NAME
The hostname header can be controlled by the client. As such, its value should not be used in any security critical decisions. Both ServletRequest.getServerName() and HttpServletRequest.getHeader("Host") have the same behavior which is to extract the Host header.
GET /testpage HTTP/1.1 Host: www.example.com [...]The web container serving your application may redirect requests to your application by default. This would allow a malicious user to place any value in the Host header. It is recommended that you do not trust this value in any security decisions you make with respect to a request.
Reference
CWE-807: Untrusted Inputs in a Security Decision Untrusted session cookie valueBug Pattern: SERVLET_SESSION_ID
The method HttpServletRequest.getRequestedSessionId() typically returns the value of the cookie JSESSIONID . This value is normally only accessed by the session management logic and not normal developer code.
The value passed to the client is generally an alphanumeric value (e.g., JSESSIONID=jp6q31lq2myn ). However, the value can be altered by the client. The following HTTP request illustrates the potential modification.
GET /somePage HTTP/1.1 Host: yourwebsite.com User-Agent: Mozilla/5.0 Cookie: JSESSIONID=Any value of the user's choice!!??'''">As such, the JSESSIONID should only be used to see if its value matches an existing session ID. If it does not, the user should be considered an unauthenticated user. In addition, the session ID value should never be logged. If it is, then the log file could contain valid active session IDs, allowing an insider to hijack any sessions whose IDs have been logged and are still active.
References
OWASP: Session Management Cheat Sheet
CWE-20: Improper Input Validation Untrusted query stringBug Pattern: SERVLET_QUERY_STRING
The query string is the concatenation of the GET parameter names and values. Parameters other than those intended can be passed in.
For the URL request /app/servlet.htm?a=1&b=2 , the query string extract will be a=1&b=2
Just as is true for individual parameter values retrieved via methods like HttpServletRequest.getParameter() , the value obtained from HttpServletRequest.getQueryString() should be considered unsafe. You may need to validate or sanitize anything pulled from the query string before passing it to sensitive APIs.
Reference
CWE-20: Improper Input Validation HTTP headers untrustedBug Pattern: SERVLET_HEADER
Request headers can easily be altered by the requesting user. In general, no assumption should be made that the request came from a regular browser without modification by an attacker. As such, it is recommended that you not trust this value in any security decisions you make with respect to a request.
Reference
CWE-807: Untrusted Inputs in a Security Decision Untrusted Referer headerBug Pattern: SERVLET_HEADER_REFERER
Behavior:
Any value can be assigned to this header if the request is coming from a malicious user. The "Referer" will not be present if the request was initiated from another origin that is secure (https).Recommendations:
No access control should be based on the value of this header. No CSRF protection should be based only on this value ( because it is optional ).Reference
CWE-807: Untrusted Inputs in a Security Decision Untrusted User-Agent headerBug Pattern: SERVLET_HEADER_USER_AGENT
The header "User-Agent" can easily be spoofed by the client. Adopting different behaviors based on the User-Agent (for crawler UA) is not recommended.
Reference
CWE-807: Untrusted Inputs in a Security Decision Potentially sensitive data in a cookieBug Pattern: COOKIE_USAGE
The information stored in a custom cookie should not be sensitive or related to the session. In most cases, sensitive data should only be stored in session and referenced by the user's session cookie. See HttpSession (HttpServletRequest.getSession())
Custom cookies can be used for information that needs to live longer than and is independent of a specific session.
Reference
CWE-315: Cleartext Storage of Sensitive Information in a Cookie Potential Path Traversal (file read)Bug Pattern: PATH_TRAVERSAL_IN
A file is opened to read its content. The filename comes from an input parameter. If an unfiltered parameter is passed to this file API, files from an arbitrary filesystem location could be read.
This rule identifies potential path traversal vulnerabilities. In many cases, the constructed file path cannot be controlled by the user. If that is the case, the reported instance is a false positive.
Vulnerable Code:
@GET @Path("/images/{image}") @Produces("images/*") public Response getImage(@javax.ws.rs.PathParam("image") String image) { File file = new File("resources/images/", image); //Weak point if (!file.exists()) { return Response.status(Status.NOT_FOUND).build(); } return Response.ok().entity(new FileInputStream(file)).build(); }Solution:
import org.apache.commons.io.FilenameUtils; @GET @Path("/images/{image}") @Produces("images/*") public Response getImage(@javax.ws.rs.PathParam("image") String image) { File file = new File("resources/images/", FilenameUtils.getName(image)); //Fix if (!file.exists()) { return Response.status(Status.NOT_FOUND).build(); } return Response.ok().entity(new FileInputStream(file)).build(); }References
WASC: Path Traversal
OWASP: Path Traversal
CAPEC-126: Path Traversal
CWE-22: Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal') Potential Path Traversal (file write)Bug Pattern: PATH_TRAVERSAL_OUT
A file is opened to write to its contents. The filename comes from an input parameter. If an unfiltered parameter is passed to this file API, files at an arbitrary filesystem location could be modified.
This rule identifies potential path traversal vulnerabilities. In many cases, the constructed file path cannot be controlled by the user. If that is the case, the reported instance is a false positive.
References
WASC-33: Path Traversal
OWASP: Path Traversal
CAPEC-126: Path Traversal
CWE-22: Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal') Potential Path Traversal (file read)Bug Pattern: SCALA_PATH_TRAVERSAL_IN
A file is opened to read its content. The filename comes from an input parameter. If an unfiltered parameter is passed to this file API, files from an arbitrary filesystem location could be read.
This rule identifies potential path traversal vulnerabilities. In many cases, the constructed file path cannot be controlled by the user. If that is the case, the reported instance is a false positive.
Vulnerable Code:
def getWordList(value:String) = Action { if (!Files.exists(Paths.get("public/lists/" + value))) { NotFound("File not found") } else { val result = Source.fromFile("public/lists/" + value).getLines().mkString // Weak point Ok(result) } }Solution:
import org.apache.commons.io.FilenameUtils; def getWordList(value:String) = Action { val filename = "public/lists/" + FilenameUtils.getName(value) if (!Files.exists(Paths.get(filename))) { NotFound("File not found") } else { val result = Source.fromFile(filename).getLines().mkString // Fix Ok(result) } }References
WASC: Path Traversal
OWASP: Path Traversal
CAPEC-126: Path Traversal
CWE-22: Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal') Potential Command InjectionBug Pattern: COMMAND_INJECTION
The highlighted API is used to execute a system command. If unfiltered input is passed to this API, it can lead to arbitrary command execution.
Vulnerable Code:
import java.lang.Runtime; Runtime r = Runtime.getRuntime(); r.exec("/bin/sh -c some_tool" + input);References
OWASP: Command Injection
OWASP: Top 10 2013-A1-Injection
CWE-78: Improper Neutralization of Special Elements used in an OS Command ('OS Command Injection') Potential Command Injection (Scala)Bug Pattern: SCALA_COMMAND_INJECTION
The highlighted API is used to execute a system command. If unfiltered input is passed to this API, it can lead to arbitrary command execution.
Vulnerable Code:
def executeCommand(value:String) = Action { val result = value.! Ok("Result:\n"+result) }References
OWASP: Command Injection
OWASP: Top 10 2013-A1-Injection
CWE-78: Improper Neutralization of Special Elements used in an OS Command ('OS Command Injection') FilenameUtils not filtering null bytesBug Pattern: WEAK_FILENAMEUTILS
Some FilenameUtils' methods don't filter NULL bytes ( 0x00 ).
If a null byte is injected into a filename, if this filename is passed to the underlying OS, the file retrieved will be the name of the file that is specified prior to the NULL byte, since at the OS level, all strings are terminated by a null byte even though Java itself doesn't care about null bytes or treat them special. This OS behavior can be used to bypass filename validation that looks at the end of the filename (e.g., endswith ".log") to make sure its a safe file to access.
To fix this, two things are recommended:
Upgrade to Java 7 update 40 or later, or Java 8+ since NULL byte injection in filenames is fixed in those versions . Strongly validate any filenames provided by untrusted users to make sure they are valid (i.e., don't contain null, don't include path characters, etc.)If you know you are using a modern version of Java immune to NULL byte injection, you can probably disable this rule.
References
WASC-28: Null Byte Injection
CWE-158: Improper Neutralization of Null Byte or NUL Character TrustManager that accept any certificatesBug Pattern: WEAK_TRUST_MANAGER
Empty TrustManager implementations are often used to connect easily to a host that is not signed by a root certificate authority . As a consequence, this is vulnerable to Man-in-the-middle attacks since the client will trust any certificate.
A TrustManager allowing specific certificates (based on a truststore for example) should be built. Detailed information for a proper implementation is available at: [1] [2]Vulnerable Code:
class TrustAllManager implements X509TrustManager { @Override public void checkClientTrusted(X509Certificate[] x509Certificates, String s) throws CertificateException { //Trust any client connecting (no certificate validation) } @Override public void checkServerTrusted(X509Certificate[] x509Certificates, String s) throws CertificateException { //Trust any remote server (no certificate validation) } @Override public X509Certificate[] getAcceptedIssuers() { return null; } }Solution (TrustMangager based on a keystore):
KeyStore ks = //Load keystore containing the certificates trusted SSLContext sc = SSLContext.getInstance("TLS"); TrustManagerFactory tmf = TrustManagerFactory.getInstance("SunX509"); tmf.init(ks); sc.init(kmf.getKeyManagers(), tmf.getTrustManagers(),null);References
WASC-04: Insufficient Transport Layer Protection
CWE-295: Improper Certificate Validation HostnameVerifier that accept any signed certificatesBug Pattern: WEAK_HOSTNAME_VERIFIER
A HostnameVerifier that accept any host are often use because of certificate reuse on many hosts. As a consequence, this is vulnerable to Man-in-the-middle attacks since the client will trust any certificate.
A TrustManager allowing specific certificates (based on a truststore for example) should be built. Wildcard certificates should be created for reused on multiples subdomains. Detailed information for a proper implementation is available at: [1] [2]Vulnerable Code:
public class AllHosts implements HostnameVerifier { public boolean verify(final String hostname, final SSLSession session) { return true; } }Solution (TrustMangager based on a keystore):
KeyStore ks = //Load keystore containing the certificates trusted SSLContext sc = SSLContext.getInstance("TLS"); TrustManagerFactory tmf = TrustManagerFactory.getInstance("SunX509"); tmf.init(ks); sc.init(kmf.getKeyManagers(), tmf.getTrustManagers(),null);References
WASC-04: Insufficient Transport Layer Protection
CWE-295: Improper Certificate Validation Found JAX-WS SOAP endpointBug Pattern: JAXWS_ENDPOINT
This method is part of a SOAP Web Service (JSR224).
The security of this web service should be analyzed. For example:
Authentication, if enforced, should be tested. Access control, if enforced, should be tested. The inputs should be tracked for potential vulnerabilities. The communication should ideally be over SSL.References
OWASP: Web Service Security Cheat Sheet
CWE-20: Improper Input Validation Found JAX-RS REST endpointBug Pattern: JAXRS_ENDPOINT
This method is part of a REST Web Service (JSR311).
The security of this web service should be analyzed. For example:
Authentication, if enforced, should be tested. Access control, if enforced, should be tested. The inputs should be tracked for potential vulnerabilities. The communication should ideally be over SSL. If the service supports writes (e.g., via POST), its vulnerability to CSRF should be investigated. [1]References
OWASP: REST Assessment Cheat Sheet
OWASP: REST Security Cheat Sheet
OWASP: Web Service Security Cheat Sheet
1. OWASP: Cross-Site Request Forgery
OWASP: CSRF Prevention Cheat Sheet
CWE-20: Improper Input Validation Found Tapestry pageBug Pattern: TAPESTRY_ENDPOINT
A Tapestry endpoint was discovered at application startup. Tapestry apps are structured with a backing Java class and a corresponding Tapestry Markup Language page (a .tml file) for each page. When a request is received, the GET/POST parameters are mapped to specific inputs in the backing Java class. The mapping is either done with fieldName:
[...] protected String input; [...]or the definition of an explicit annotation:
[...] @org.apache.tapestry5.annotations.Parameter protected String parameter1; @org.apache.tapestry5.annotations.Component(id = "password") private PasswordField passwordField; [...] The page is mapped to the view [/resources/package/PageName].tml.Each Tapestry page in this application should be researched to make sure all inputs that are automatically mapped in this way are properly validated before they are used.
References
Apache Tapestry Home Page
CWE-20: Improper Input Validation Found Wicket WebPageBug Pattern: WICKET_ENDPOINT
This class represents a Wicket WebPage. Input is automatically read from a PageParameters instance passed to the constructor. The current page is mapped to the view [/package/WebPageName].html.Each Wicket page in this application should be researched to make sure all inputs that are automatically mapped in this way are properly validated before they are used.
References
Apache Wicket Home Page
CWE-20: Improper Input Validation MD2, MD4 and MD5 are weak hash functionsBug Pattern: WEAK_MESSAGE_DIGEST_MD5
The algorithms MD2, MD4 and MD5 are not a recommended MessageDigest. PBKDF2 should be used to hash password for example.
"The security of the MD5 hash function is severely compromised. A collision attack exists that can find collisions within seconds on a computer with a 2.6 GHz Pentium 4 processor (complexity of 2 24.1 ).[1] Further, there is also a chosen-prefix collision attack that can produce a collision for two inputs with specified prefixes within hours, using off-the-shelf computing hardware (complexity 2 39 ).[2]"- Wikipedia: MD5 - Security
" SHA-224, SHA-256, SHA-384, SHA-512, SHA-512/224, and SHA-512/256 :
The use of these hash functions is acceptable for all hash function applications."
- NIST: Transitions: Recommendation for Transitioning the Use of Cryptographic Algorithms and Key Lengths p.15
"The main idea of a PBKDF is to slow dictionary or brute force attacks on the passwords by increasing the time needed to test each password. An attacker with a list of likely passwords can evaluate the PBKDF using the known iteration counter and the salt. Since an attacker has to spend a significant amount of computing time for each try, it becomes harder to apply the dictionary or brute force attacks."
- NIST: Recommendation for Password-Based Key Derivation p.12
Vulnerable Code:
MessageDigest md5Digest = MessageDigest.getInstance("MD5"); md5Digest.update(password.getBytes()); byte[] hashValue = md5Digest.digest(); byte[] hashValue = DigestUtils.getMd5Digest().digest(password.getBytes());Solution (Using bouncy castle):
public static byte[] getEncryptedPassword(String password, byte[] salt) throws NoSuchAlgorithmException, InvalidKeySpecException { PKCS5S2ParametersGenerator gen = new PKCS5S2ParametersGenerator(new SHA256Digest()); gen.init(password.getBytes("UTF-8"), salt.getBytes(), 4096); return ((KeyParameter) gen.generateDerivedParameters(256)).getKey(); }Solution (Java 8 and later):
public static byte[] getEncryptedPassword(String password, byte[] salt) throws NoSuchAlgorithmException, InvalidKeySpecException { KeySpec spec = new PBEKeySpec(password.toCharArray(), salt, 4096, 256 * 8); SecretKeyFactory f = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA256"); return f.generateSecret(spec).getEncoded(); }References
[1] On Collisions for MD5 : Master Thesis by M.M.J. Stevens [2] Chosen-prefix collisions for MD5 and applications : Paper written by Marc StevensWikipedia: MD5
NIST: Transitions: Recommendation for Transitioning the Use of Cryptographic Algorithms and Key Lengths
NIST: Recommendation for Password-Based Key Derivation
Stackoverflow: Reliable implementation of PBKDF2-HMAC-SHA256 for Java
CWE-327: Use of a Broken or Risky Cryptographic Algorithm SHA-1 is a weak hash functionBug Pattern: WEAK_MESSAGE_DIGEST_SHA1
The algorithms SHA-1 is not a recommended algorithm for hash password, for signature verification and other uses. PBKDF2 should be used to hash password for example.
" SHA-1 for digital signature generation:
SHA-1 may only be used for digital signature generation where specifically allowed by NIST protocol-specific guidance. For all other applications, SHA-1 shall not be used for digital signature generation .
SHA-1 for digital signature verification:
For digital signature verification, SHA-1 is allowed for legacy-use .
[...]SHA-224, SHA-256, SHA-384, SHA-512, SHA-512/224, and SHA-512/256 :
The use of these hash functions is acceptable for all hash function applications."
- NIST: Transitions: Recommendation for Transitioning the Use of Cryptographic Algorithms and Key Lengths p.15
"The main idea of a PBKDF is to slow dictionary or brute force attacks on the passwords by increasing the time needed to test each password. An attacker with a list of likely passwords can evaluate the PBKDF using the known iteration counter and the salt. Since an attacker has to spend a significant amount of computing time for each try, it becomes harder to apply the dictionary or brute force attacks."
- NIST: Recommendation for Password-Based Key Derivation p.12
Vulnerable Code:
MessageDigest sha1Digest = MessageDigest.getInstance("SHA1"); sha1Digest.update(password.getBytes()); byte[] hashValue = sha1Digest.digest(); byte[] hashValue = DigestUtils.getSha1Digest().digest(password.getBytes());Solution (Using bouncy castle):
public static byte[] getEncryptedPassword(String password, byte[] salt) throws NoSuchAlgorithmException, InvalidKeySpecException { PKCS5S2ParametersGenerator gen = new PKCS5S2ParametersGenerator(new SHA256Digest()); gen.init(password.getBytes("UTF-8"), salt.getBytes(), 4096); return ((KeyParameter) gen.generateDerivedParameters(256)).getKey(); }Solution (Java 8 and later):
public static byte[] getEncryptedPassword(String password, byte[] salt) throws NoSuchAlgorithmException, InvalidKeySpecException { KeySpec spec = new PBEKeySpec(password.toCharArray(), salt, 4096, 256 * 8); SecretKeyFactory f = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA256"); return f.generateSecret(spec).getEncoded(); }References
Qualys blog: SHA1 Deprecation: What You Need to Know
Google Online Security Blog: Gradually sunsetting SHA-1
NIST: Transitions: Recommendation for Transitioning the Use of Cryptographic Algorithms and Key Lengths
NIST: Recommendation for Password-Based Key Derivation
Stackoverflow: Reliable implementation of PBKDF2-HMAC-SHA256 for Java
CWE-327: Use of a Broken or Risky Cryptographic Algorithm DefaultHttpClient with default constructor is not compatible with TLS 1.2Bug Pattern: DEFAULT_HTTP_CLIENT
Vulnerable Code:
HttpClient client = new DefaultHttpClient();Solution:
Upgrade your implementation to use one of the recommended constructs and configure https.protocols JVM option to include TLSv1.2:
Use SystemDefaultHttpClient insteadSample Code:
HttpClient client = new SystemDefaultHttpClient(); Create an HttpClient based on SSLSocketFactory - get an SSLScoketFactory instance with getSystemSocketFactory() and use this instance for HttpClient creation Create an HttpClient based on SSLConnectionSocketFactory - get an instance with getSystemSocketFactory() and use this instance for HttpClient creation Use HttpClientBuilder - call useSystemProperties() before calling build()Sample Code:
HttpClient client = HttpClientBuilder.create().useSystemProperties().build(); HttpClients - call createSystem() to create an instanceSample Code:
HttpClient client = HttpClients.createSystem();
References
Diagnosing TLS, SSL, and HTTPS Weak SSLContextBug Pattern: SSL_CONTEXT
Vulnerable Code:
SSLContext.getInstance("SSL");Solution:
Upgrade your implementation to the following, and configure https.protocols JVM option to include TLSv1.2:
SSLContext.getInstance("TLS");References
Diagnosing TLS, SSL, and HTTPS Message digest is customBug Pattern: CUSTOM_MESSAGE_DIGEST
Implementing a custom MessageDigest is error-prone.
NIST recommends the use of SHA-224, SHA-256, SHA-384, SHA-512, SHA-512/224, or SHA-512/256.
" SHA-1 for digital signature generation:
SHA-1 may only be used for digital signature generation where specifically allowed by NIST protocol-specific guidance. For all other applications, SHA-1 shall not be used for digital signature generation .
SHA-1 for digital signature verification:
For digital signature verification, SHA-1 is allowed for legacy-use .
[...]SHA-224, SHA-256, SHA-384, SHA-512, SHA-512/224, and SHA-512/256 :
The use of these hash functions is acceptable for all hash function applications."
- NIST: Transitions: Recommendation for Transitioning the Use of Cryptographic Algorithms and Key Lengths p.15
Vulnerable Code:
MyProprietaryMessageDigest extends MessageDigest { @Override protected byte[] engineDigest() { [...] //Creativity is a bad idea return [...]; } }Upgrade your implementation to use one of the approved algorithms. Use an algorithm that is sufficiently strong for your specific security needs.
Example Solution:
MessageDigest sha256Digest = MessageDigest.getInstance("SHA256"); sha256Digest.update(password.getBytes());References
NIST Approved Hashing Algorithms
CWE-327: Use of a Broken or Risky Cryptographic Algorithm Tainted filename readBug Pattern: FILE_UPLOAD_FILENAME
The filename provided by the FileUpload API can be tampered with by the client to reference unauthorized files.
For example:
"../../../config/overide_file" "shell.jsp\u0000expected.gif"Therefore, such values should not be passed directly to the filesystem API. If acceptable, the application should generate its own file names and use those. Otherwise, the provided filename should be properly validated to ensure it's properly structured, contains no unauthorized path characters (e.g., / \), and refers to an authorized file.
References
Securiteam: File upload security recommendations
CWE-22: Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal')
WASC-33: Path Traversal
OWASP: Path Traversal
CAPEC-126: Path Traversal
CWE-22: Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal') Regex DOS (ReDOS)Bug Pattern: REDOS
Regular expressions (regexs) are frequently subject to Denial of Service (DOS) attacks (called ReDOS). This is due to the fact that regex engines may take a large amount of time when analyzing certain strings, depending on how the regex is defined.
For example, for the regex: ^(a+)+$ , the input " aaaaaaaaaaaaaaaaX " will cause the regex engine to analyze 65536 different paths.
[1] Example taken from OWASP referencesTherefore, it is possible that a single request may cause a large amount of computation on the server side. The problem with this regex, and others like it, is that there are two different ways the same input character can be accepted by the Regex due to the + (or a *) inside the parenthesis, and the + (or a *) outside the parenthesis. The way this is written, either + could consume the character 'a'. To fix this, the regex should be rewritten to eliminate the ambiguity. For example, this could simply be rewritten as: ^a+$ , which is presumably what the author meant anyway (any number of a's). Assuming that's what the original regex meant, this new regex can be evaluated quickly, and is not subject to ReDOS.
References
Sebastian Kubeck's Weblog: Detecting and Preventing ReDoS Vulnerabilities
[1]OWASP: Regular expression Denial of Service CWE-400: Uncontrolled Resource Consumption ('Resource Exhaustion') XML parsing vulnerable to XXE (XMLStreamReader)Bug Pattern: XXE_XMLSTREAMREADER
AttackXML External Entity (XXE) attacks can occur when an XML parser supports XML entities while processing XML received from an untrusted source.
Risk 1: Expose local file content (XXE: X ML e X ternal E ntity)
<?xml version="1.0" encoding="ISO-8859-1"?> <!DOCTYPE foo [ <!ENTITY xxe SYSTEM "file:///etc/passwd" > ]> <foo>&xxe;</foo> Risk 2: Denial of service (XEE: X ml E ntity E xpansion) <?xml version="1.0"?> <!DOCTYPE lolz [ <!ENTITY lol "lol"> <!ELEMENT lolz (#PCDATA)> <!ENTITY lol1 "&lol;&lol;&lol;&lol;&lol;&lol;&lol;&lol;&lol;&lol;"> <!ENTITY lol2 "&lol1;&lol1;&lol1;&lol1;&lol1;&lol1;&lol1;&lol1;&lol1;&lol1;"> <!ENTITY lol3 "&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;"> [...] <!ENTITY lol9 "&lol8;&lol8;&lol8;&lol8;&lol8;&lol8;&lol8;&lol8;&lol8;&lol8;"> ]> <lolz>&lol9;</lolz> SolutionIn order to avoid exposing dangerous feature of the XML parser, you can do the following change to the code.
Vulnerable Code:
public void parseXML(InputStream input) throws XMLStreamException { XMLInputFactory factory = XMLInputFactory.newFactory(); XMLStreamReader reader = factory.createXMLStreamReader(input); [...] }The following snippets show two available solutions. You can set one property or both.
Solution disabling External Entities:
public void parseXML(InputStream input) throws XMLStreamException { XMLInputFactory factory = XMLInputFactory.newFactory(); factory.setProperty(XMLInputFactory.IS_SUPPORTING_EXTERNAL_ENTITIES, false); XMLStreamReader reader = factory.createXMLStreamReader(input); [...] }Solution disabling DTD:
public void parseXML(InputStream input) throws XMLStreamException { XMLInputFactory factory = XMLInputFactory.newFactory(); factory.setProperty(XMLInputFactory.SUPPORT_DTD, false); XMLStreamReader reader = factory.createXMLStreamReader(input); [...] }References
CWE-611: Improper Restriction of XML External Entity Reference ('XXE')
CERT: IDS10-J. Prevent XML external entity attacks
OWASP.org: XML External Entity (XXE) Processing
WS-Attacks.org: XML Entity Expansion
WS-Attacks.org: XML External Entity DOS
WS-Attacks.org: XML Entity Reference Attack
Identifying Xml eXternal Entity vulnerability (XXE)
JEP 185: Restrict Fetching of External XML Resources XML parsing vulnerable to XXE (XPathExpression)Bug Pattern: XXE_XPATH
AttackXML External Entity (XXE) attacks can occur when an XML parser supports XML entities while processing XML received from an untrusted source.
Risk 1: Expose local file content (XXE: X ML e X ternal E ntity)
<?xml version="1.0" encoding="ISO-8859-1"?> <!DOCTYPE foo [ <!ENTITY xxe SYSTEM "file:///etc/passwd" > ]> <foo>&xxe;</foo> Risk 2: Denial of service (XEE: X ml E ntity E xpansion) <?xml version="1.0"?> <!DOCTYPE lolz [ <!ENTITY lol "