Secure Java Coding

Disclaimer

Largely based on a talk given by Andrew Lee-Thorp, Principal Consultant Synopsis.

Common Vulnerabilities

(see also the blog > security-shepherd)

  1. Clear text storage of sensitive information in memory (https://cwe.mitre.org/data/definitions/316.html)
  2. Basic Cross Site Scripting (https://cwe.mitre.org/data/definitions/80.html)
  3. SQL injection (https://cwe.mitre.org/data/definitions/89.html)
  4. Information exposure through error messages (https://cwe.mitre.org/data/definitions/209.html)
  5. Use of broken or risky cryptographic algorithms (https://cwe.mitre.org/data/definitions/327.html)
  6. External control of filename or path (https://cwe.mitre.org/data/definitions/73.html)
  7. Improper restriction of XML external entity reference (XXE) (https://cwe.mitre.org/data/definitions/611.html)
  8. Insufficient entropy (https://cwe.mitre.org/data/definitions/331.html)
  9. URL redirection to untrusted site (open redirect) (https://cwe.mitre.org/data/definitions/601.html)
  10. Improper neutralization of CRLF sequences in HTTP headers (HTTP response splitting)  (https://cwe.mitre.org/data/definitions/113.html)

Defense Strategies

For injection attacked check all inputs:

1) Validation

2) Parameterization

3) Output encoding

4) Data normalization

  1. Validation
  • Exact match
  • Whitelist
  • Blacklist

2. Parameterization

Use apis that parameterize the values instead of string concatenation, eg. SQL PreparedStatements.

3. Output Encoding

When input validation is restricted, encode the data after processing and before responding:

  • XML encoding
  • Javascript encoding

4. Data Normalization

Convert data to its canonical form. Eg. file paths, split to root path and expected format.

String baseDir = "/root/foo/bar/"; 
String path = baseDir + filePath;
File f = new File(path);

String canonical = f.getCanonicalPath();
if (!canonical.startsWith(baseDir)) { 
  System.out.println("this is an attack!");
}


Still need to validate the input afterwards.

General Prevention Methods

Input -> (normalize) -> (validate) -> process -> (parameterize db queries, encode results)

1 Clear text in memory

Can dump the java heap of a running program to reveal sensitive data. Using immutable objects prevents clearing out of memory occupied by these objects using updates. Instead use mutable objects, eg use char array in place of String and clear the array after processing.

2 Injection Attacks

Cross-site scripting (XSS)

Bypassing the Same Origin Policy, usually malicious java script executed on the browser to extract information, modify page, hijack the session, redirect to fake sites. The same origin policy requires protocol, host and port to be the same within the site.

Stored XSS

Malicious data in a forum post. When viewed the script now runs on the users browser.

Reflected XSS

URL has a parameter (eg erromsg) which is sent to victim via a email.

DOM-Based XSS

If the DOM is changed by a script looking at t URL this can then be exploited.

Prevention

Encode the result before presentation. (See OWASP Java encoder)

Validate the input before processing.

Use CSP (Content Security Policy), set this in the http response header. See https://developers.google.com/web/fundamentals/security/csp/

3 SQL Injection

Basically avoid concatenation of user input with sql statements, instead use prepared statements (parameterized).

This also applies to stored procedures and ORM frameworks like hibernate.

In situations where parameterized queries are not possible than validate/encode the input.

4 Information Exposure

Information leaking details of the server, the code in stack traces that can be exploited by attackers.

Use a general error page and use this when exceptions occur.

Do not show details of servers.

5 Cryptographic Algorithms


Symmetric: DES3, AES
Asymmetric: RSA, DSA, ECC

Avoid using weak block cipher modes such as ECB, CBC (http://www.crypto-it.net/eng/theory/modes-of-block-ciphers.html)

Avoid using weak algorithms such as RC4, DES.

Consider use of randomly generated Initialization Vector.

Consider encryption limits.

Use strong hashing use SHA-256, 384, 512, SHA3-224, SHA3-512 instead of MD5 or SHA-1.

Consider using random padding for RSA encryption (PKCS#1 v1.5)

For AES (Advanced Encryption Standard) use authenticated mode eg AES-GCM (Galios Counter Mode)  with IvParameterSpec (java) to get the IV.  For code examples see https://javainterviewpoint.com/java-aes-256-gcm-encryption-and-decryption/

RSA

For RSA use 2048 or or larger keys.
For encryption use use RSA-OAEP padding rather than PKCS#1
For signature can use PCKCS#1 or PSS padding

6 Files and Directories

Prevent injection of input that can access operating system, execute remote code modify files etc.

Use canonical path to convert to standard form and check  directory.

String baseDir = "/root/foo/bar/"; 
String path = baseDir + filePath; 
File f = new File(path);
String canonical = f.getCanonicalPath();
if (!canonical.startsWith(baseDir)) { 
	System.out.println("attack!"); 
}

7 XML Entities

Can include local files to access sensitive data

<?xml version="1.0" encoding="ISO-8859-1"?> 
<!DOCTYPE foo [ <!ELEMENT foo ANY > <!ENTITY xxe SYSTEM "file:///etc/passwd" >]> <creds>
    <user>&xxe;</user>
    <pass>mypass</pass>
</creds>

Can scan ports

<!DOCTYPE scan [<!ENTITY test SYSTEM "http://10.26.18.1:22">]> <scan>&test;</scan

Secure parsing using features to prevent external entity injection (XXE).

Either disable completely or set individually if not possible:

saxReader.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true); 
private static final String EXTERNAL_ENTITIES = "http://xml.org/sax/features/external-general-entities";
private static final String EXTERNAL_DTD = "http://apache.org/xml/features/nonvalidating/load-external-dtd";

...
...

SAXParserFactory parserFactory = SAXParserFactory.newInstance();
parserFactory.setNamespaceAware(true);
SAXParser parser = null;
try {
    parserFactory.setFeature(EXTERNAL_ENTITIES, false);
    parserFactory.setFeature(EXTERNAL_DTD, false);
    parserFactory.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true);
    parser = parserFactory.newSAXParser();
} catch (ParserConfigurationException e) {
	throw new SAXException(e);
}

8 Passwords

Use password store never hard code.

Hash the password with a salt stored alongside the hash, use adaptive hash (slows down to brute force search) functions (Bcrypt, Scrypt, PBKDF2, Argon2).

9 Entropy

Randomness for keys, sessions, nonces etc. Use SecureRandom not Random and not setSeed with a custom one but call it periodically.

10 HTTP Response Splitting

Prevent injection of CRLF into http header and allowing additional malicious headers, modification of cookies, addition of javascript.

Attack could be like so:

http://www.vulnerablesite.com/authors?author=JoeHacker\r\n\r\nHTTP/1.1%20200%20OK\r\n

Which would circumvent the normal response.

Any input from the user that is added to the header is a security flaw if not cleansed.


Useful References

https://cwe.mitre.org/

Very short introduction to cryptography