Java Web Security
Antipatterns
Dominik Schadow |
bridging
IT
Failed with nothing but
the best intentions
Architect
Implement
Maintain
A
rc
hit
Software that is secure by design
Know the web application
Know all external entities
Know all data flows
Identify all risks
„
Good engineering involves thinking
about how things can be made to work;
the security mindset involves thinking
about how things can be made to fail. It
involves thinking like an attacker […].
“
www.schneier.com/blog/archives/2008/03/the_security_mi_1.html
Implement
as plaintext
encrypted
trivially hashed
Passw0rd$
d281fdbe0555b913d1c29f99143a3ad7bc66cf83
2e2c68bc1e9187cc6919fcb8564f1483
AKNtqLC_DZM32Jk7pgF4FpRVapo6QFEdROpsflwHkw
2q6rfK2mev4fAQFlRXbH2DecJTYLvF3LMD
Passw0rd$
d281fdbe0555b913d1c29f99143a3ad7bc66cf83
2e2c68bc1e9187cc6919fcb8564f1483
AKNtqLC_DZM32Jk7pgF4FpRVapo6QFEdROpsflwHkw
2q6rfK2mev4fAQFlRXbH2DecJTYLvF3LMD
SHA1
Passw0rd$
d281fdbe0555b913d1c29f99143a3ad7bc66cf83
2e2c68bc1e9187cc6919fcb8564f1483
AKNtqLC_DZM32Jk7pgF4FpRVapo6QFEdROpsflwHkw
2q6rfK2mev4fAQFlRXbH2DecJTYLvF3LMD
SHA1
MD5
Passw0rd$
d281fdbe0555b913d1c29f99143a3ad7bc66cf83
2e2c68bc1e9187cc6919fcb8564f1483
AKNtqLC_DZM32Jk7pgF4FpRVapo6QFEdROpsflwHkw
2q6rfK2mev4fAQFlRXbH2DecJTYLvF3LMD
SHA1
MD5
AES
PBKDF2
Iterations against brute force attacks
Available in plain Java
bcrypt
Iterations against brute force attacks
Integrated in Spring Security
@Configuration
@EnableWebMvcSecurity
public class WebSecurityConfig extends
WebSecurityConfigurerAdapter {
@Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder(10);
}
}
@Configuration
@EnableWebMvcSecurity
public class WebSecurityConfig extends
WebSecurityConfigurerAdapter {
@Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder(10);
}
}
@Configuration
@EnableWebMvcSecurity
public class WebSecurityConfig extends
WebSecurityConfigurerAdapter {
@Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder(10);
}
}
@Configuration
@EnableWebMvcSecurity
public class WebSecurityConfig extends
WebSecurityConfigurerAdapter {
@Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder(10);
}
}
scrypt
Memory against brute force attacks
Set period of time to change passwords
User logs in successfully
Calculate new hash
Update hash & salt Calculate new salt
User tries to log in
Period of time expired
Set not changed passwords to null
<h:inputSecret id="password" maxlength="1024">
<f:validateLength minimum="10" maximum="1024"/> </h:inputSecret>
<h:inputSecret id="password" maxlength="1024">
<f:validateLength minimum="10" maximum="1024"/>
private byte[] hash(PBEKeySpec keySpec) { return secretKeyFactory.generateSecret
(keySpec).getEncoded(); }
private byte[] hash(PBEKeySpec keySpec) {
return secretKeyFactory.generateSecret
(keySpec).getEncoded();
Implement
Changing password
Prevent unintended password change
Cross-Site Request Forgery vulnerability
Session id knowledge
Implement
Disabling pasting passwords
Disabling pasting into password fields
Does not
stop any attack
Does not
provide any more security
Does not
stop any attack
Does not
provide any more security
@WebFilter(urlPatterns = {"/*"})
public class HSTS implements Filter { public void doFilter(…) {HttpServletResponse response = (HttpServletResponse) res;
response.addHeader(
"Strict-Transport-Security",
"max-age=31556926");
chain.doFilter(req, response); } // … }@WebFilter(urlPatterns = {"/*"})
public class HSTS implements Filter { public void doFilter(…) {
HttpServletResponse response = (HttpServletResponse) res;
response.addHeader(
"Strict-Transport-Security",
"max-age=31556926");
chain.doFilter(req, response); } // … }@WebFilter(urlPatterns = {"/*"})
public class HSTS implements Filter { public void doFilter(…) {HttpServletResponse response = (HttpServletResponse) res;
response.addHeader
(
"Strict-Transport-Security",
"max-age=31556926");
chain.doFilter(req, response); } // … }@WebFilter(urlPatterns = {"/*"})
public class HSTS implements Filter { public void doFilter(…) {HttpServletResponse response = (HttpServletResponse) res;
response.addHeader(
"Strict-Transport-Security"
,
"max-age=31556926");
chain.doFilter(req, response); } // … }@WebFilter(urlPatterns = {"/*"})
public class HSTS implements Filter { public void doFilter(…) {HttpServletResponse response = (HttpServletResponse) res;
response.addHeader(
"Strict-Transport-Security",
"max-age=31556926"
);
chain.doFilter(req, response); } // … }HSTS stops any insecure communication
Requires HTTPS connection
No effect on HTTP connections
All resources via HTTPS
Includes scripts, images, …
Requires valid certificate
Implement
SECURITY_SUCCESS
Successful security check (e.g. successful login)
SECURITY_FAILURE
Failed security check (e.g. failed login)
SECURITY_AUDIT
Record security events for audit (e.g. account edited)
Use an always active log level or
separate log file
log.warn(
SecurityMarkers.SECURITY_AUDIT,
"User {} has edited his account“,
username);
log.warn
(
SecurityMarkers.SECURITY_AUDIT,
"User {} has edited his account“,
username);
log.warn(
SecurityMarkers.SECURITY_AUDIT
,
"User {} has edited his account“,
username);
Implement
Skipping session configuration
Keeping session id after log-in
<plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-war-plugin</artifactId> <version>2.6</version> <configuration> <failOnMissingWebXml> false </failOnMissingWebXml> </configuration> </plugin>
<plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-war-plugin</artifactId> <version>2.6</version> <configuration> <failOnMissingWebXml> false </failOnMissingWebXml> </configuration> </plugin>
<web-app ... version="3.1"> <session-config>
<!-- idle timeout after session expires --> <session-timeout>30</session-timeout>
<cookie-config>
<!-- prevent session id script access --> <http-only>true</http-only>
<!-- transfer cookie via https only --> <secure>true</secure>
</cookie-config>
<!-- session id in cookie, not URL --> <tracking-mode>COOKIE</tracking-mode>
</session-config> </web-app>
<web-app ... version="3.1"> <session-config>
<!-- idle timeout after session expires --> <session-timeout>30</session-timeout>
<cookie-config>
<!-- prevent session id script access --> <http-only>true</http-only>
<!-- transfer cookie via https only --> <secure>true</secure>
</cookie-config>
<!-- session id in cookie, not URL --> <tracking-mode>COOKIE</tracking-mode>
</session-config> </web-app>
<web-app ... version="3.1"> <session-config>
<!-- idle timeout after session expires --> <session-timeout>30</session-timeout>
<cookie-config>
<!-- prevent session id script access --> <http-only>true</http-only>
<!-- transfer cookie via https only --> <secure>true</secure>
</cookie-config>
<!-- session id in cookie, not URL --> <tracking-mode>COOKIE</tracking-mode>
</session-config> </web-app>
<web-app ... version="3.1"> <session-config>
<!-- idle timeout after session expires --> <session-timeout>30</session-timeout>
<cookie-config>
<!-- prevent session id script access --> <http-only>true</http-only>
<!-- transfer cookie via https only --> <secure>true</secure>
</cookie-config>
<!-- session id in cookie, not URL --> <tracking-mode>COOKIE</tracking-mode>
</session-config> </web-app>
<web-app ... version="3.1"> <session-config>
<!-- idle timeout after session expires --> <session-timeout>30</session-timeout>
<cookie-config>
<!-- prevent session id script access --> <http-only>true</http-only>
<!-- transfer cookie via https only --> <secure>true</secure>
</cookie-config>
<!-- session id in cookie, not URL --> <tracking-mode>COOKIE</tracking-mode>
</session-config> </web-app>
User usually receives a session id
when entering web application
4E01EF46D8446D1C
10CB5C08EDA69DD1
Session hijacking
Session fixation
<form th:action="@{/logout}" method="post"> <button type="submit">Log out</button>
<form th:action="@{/logout}" method="post"> <button type="submit">Log out</button>
<form action="/logout" method="post">
<input type="hidden"
name="${_csrf.parameterName}" value="${_csrf.token}"/>
<input type="submit" value="Logout"/>
<form action="/logout" method="post">
<input type="hidden"
name="${_csrf.parameterName}" value="${_csrf.token}"/>
<input type="submit" value="Logout"/>
Limit session duration
Force HTTPS
@WebServlet
public class Login extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) { // ...
request.changeSessionId(); // ...
} }
@WebServlet
public class Login extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) { // ...
request.changeSessionId(); // ...
} }
@WebServlet
public class Login extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) { // ...
request.changeSessionId();
// ... }
@WebServlet
public class Logout extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) { // ...
request.getSession().invalidate(); // ...
} }
@WebServlet
public class Logout extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) { // ...
request.getSession().invalidate();
// ... }
M
aint
Frameworks and
libraries decline
<reporting> <plugins><plugin> <groupId>org.owasp</groupId> <artifactId>dependency-check-maven</artifactId> <version>1.3.1</version> <reportSets> <reportSet> <reports> <report>aggregate</report> </reports> </reportSet> </reportSets> </plugin></plugins> </reporting>
Plan security with threat modeling
Think (like an attacker) during implementation
www.bridging-it.de
Demo Projects
github.com/dschadow/JavaSecurity
HTTP Strict Transport Security RFC
tools.ietf.org/html/rfc6797
Microsoft Threat Modeling Tool
www.microsoft.com/en-us/sdl/adopt/ threatmodeling.aspx
Mozilla SeaSponge
air.mozilla.org/mozilla-winter-of-security-seasponge-a-tool-for-easy-threat-modeling
OWASP Dependency Check
www.owasp.org/index.php/
OWASP_Dependency_Check OWASP Security Logging
www.owasp.org/index.php/ OWASP_Security_Logging_Project Spring Security projects.spring.io/spring-security Pictures www.dreamstime.com Koenigstr. 42 70173 Stuttgart Germany Blog blog.dominikschadow.de Twitter @dschadow