PROBLEM
Clickjacking is an attack that tricks the users to perform unintended actions… see OWASP’s Testing for Clickjacking (OTG-CLIENT-009)
SOLUTION
To prevent clickjacking attacks, the app must set X-FRAME-OPTIONS header with an appropriate value:-
- DENY: this denies any domain using the page as an iFrame source. This is the best option.
- SAMEORIGIN: this allows pages within the same domain to use other application pages as iFrame sources.
- ALLOW-FROM [whitelisted domains]: this declares a list of domains that are allowed to include the pages as iFrame sources.
If set correctly, the HTTPS response should show X-FRAME-OPTIONS header:-
➜ ~ curl -i -k https://localhost:8443/ HTTP/1.1 200 X-Content-Type-Options: nosniff X-XSS-Protection: 1; mode=block Cache-Control: no-cache, no-store, max-age=0, must-revalidate Pragma: no-cache Expires: 0 Strict-Transport-Security: max-age=31536000 ; includeSubDomains X-Frame-Options: DENY X-Application-Context: application:local:8443 Set-Cookie: JSESSIONID=04ADDAF886A20AA561021E869E980BCC; Path=/; Secure; HttpOnly Content-Type: text/html;charset=UTF-8 Content-Language: en-US Content-Length: 631 Date: Thu, 31 Aug 2017 14:56:57 GMT
There are several ways to set this header.
Solution 1: Using a servlet filter
You may create a servlet filter that sets X-FRAME-OPTIONS in the response header.
Here’s an example using web.xml-less Spring Boot:-
@SpringBootApplication class Application extends SpringBootServletInitializer { static void main(String[] args) { SpringApplication.run(Application, args) } @Override protected SpringApplicationBuilder configure(SpringApplicationBuilder builder) { return builder.sources(Application) } @Bean FilterRegistrationBean clickjackingPreventionFilter() { return new FilterRegistrationBean( urlPatterns: ['/**'], filter: new Filter() { @Override void init(final FilterConfig filterConfig) throws ServletException { } @Override void doFilter(final ServletRequest servletRequest, final ServletResponse servletResponse, final FilterChain filterChain) throws IOException, ServletException { final HttpServletResponse response = (HttpServletResponse) servletResponse response.addHeader('X-FRAME-OPTIONS', 'DENY') filterChain.doFilter(servletRequest, servletResponse) } @Override void destroy() { } } ) } }
Solution 2: Using Spring Security
Spring Security provides a very easy way to set the X-FRAME-OPTIONS header:-
@Configuration @EnableWebSecurity class SecurityConfig extends WebSecurityConfigurerAdapter { @Override protected void configure(final HttpSecurity http) throws Exception { http. headers().frameOptions().deny(). and(). authorizeRequests(). antMatchers('/**').permitAll() } }