Strategies for Securing Java Technology Code (TS-5210)
Presenter is Mark Lambert from Parasoft (parasoft.com).
Goal:
Learn how to develop secure Java technology-based applications and avoid un-authorized access to privileged data.
Introduction:
Application security is not the same as network security. Network doesn't control access to data and resources. Therefore, the application needs to defend itself against attacks to prevent misuse of its access mechanisms. Gartner says 75% of hacks happen at the application level. NIST says 92% of vulnerabilities are at the application level. Security issues are often not taken seriously until they result in threats of litigation.
Misconceptions:
Establish Responsibility:
Gartner says the developer is 3x more likely than sys-admin to be the culprit of a vulnerability. Ethical hacking is not a good solution since it often results in detection of the symptoms, not the cause.
Priorities:
Protecting sensitive data, information integrity, authentication, authorization, and compliance & auditing (HIPPA, SIX, etc).
Implementing a secure application:
Prevention can be done through education and coding standards. Inspection is less desirable since it's performed after-the-fact, but still neccessary.
Inside:
Code analysis, unit tests
Outside:
Penetration tests, regression tests, load tests
"Inside the Code" Strategies:
Coding guidelines, code defensively, expose & correct bugs. Goal is to create clean code from the start.
Coding Guidelines:
Does not mean "beautification." Protect data from external access, ensure that Java security mechanisms are used properly, identify where data is exposed, identify insecure code. Have a consistent way of applying protection mechanisms.
Avoid using inner classes since there is no concept of inner classes in the Java byte code; rather, the compiler translates them into package scoped classes. Solution is to make inner classes private. Don't compare classes by name, since replacement classes can be used to insert malicious code. Make classes non-cloneable since cloning bypasses invocation of the constructor. If cloning is required, make the clone method final. Serialization allows hackers to view the full internal state. Define a final writeObject() method, and mark as transient. Avoid returning mutable objects since it could allow the caller to change the state of the object. All classes and methods should be declared final whenever possible, while documenting exceptions.
Defensive Coding:
Defensive coding includes maintaining centralization of security mechnisms: logging, software firewalls, and database access. Avoid dangerous functions: native code, and external components (have a consistent policy for accessing external components).
Defensive firewalls and not network firewalls, but they operate similarly. They ensure that hackers accessing code cannot access certain sections of the program. This can be done by creating a throwable and validating the stack trace to ensure only certain client code can access vulnerable portions of the system.
All external inputs need to be validated using assertions, "if" statements, and design-by-contract.
SQL injection can be combatted by using PreparedStatement. ExecuteQuery allows construction of SQL statements that might contain malicious instructions. PreparedStatement includes type-checking of arguments without any additional labor.
Design by contract tools are capable of generating pre- and post-conditions automatically, creating a firewall-like system.
A real problem with application-level vulnerabilities is that security bugs are not seen as being in the same class as functional bugs. They often result from unspecified program behavior, so it indicates a mistake as design and implementation time.
Penetration testing guidelines can be found at OWASP (WebGoat), NIST, PCI, others.
Implementing a Security Policy:
There are trade-offs between security and optimal performance, following requirements, and achieving milestones.