Open sethetter opened 2 years ago
We can post to submit a new job via:
$ curl -d "position=csrf&organization=my_org&url=http://virus.com&description=a_short_description_about_csrf&email=a@b.c" -X POST http://localhost:8080/jobs
Which we might expect, but still may not exactly want to just leave this open for anyone to post to.
Attempted to perform a csrf attack with this:
<!DOCTYPE html>
<html>
<body>
<form action="http://localhost:8080/jobs" method="POST">
<input type="hidden" name="position" value="csrf" />
<input type="hidden" name="organization" value="my org" />
<input type="hidden" name="url" value="https://virus.com" />
<input type="hidden" name="description" value="csrf exploit" />
<input type="hidden" name="email" value="a@b.c" />
</form>
<script>
document.forms[0].submit();
</script>
</body>
</html>
Which succeeded, you can open that html up in any browser and it will post to the site. It's currently targeting the local server, but could target the production site just as easily.
We are already setting the SameSite cookie attribute to strict
via https://github.com/devict/job-board/blob/main/pkg/server/server.go#L45, but we're not exactly using cookie based auth.
Referer-based validation can help, but shouldn't be relied on.
We'll need to additionally add a csrf token to the forms.
Here's another example of implementing csrf tokens: https://portswigger.net/web-security/csrf/preventing
@kevinfalting thanks for confirming the vulnerability! Definitely something to prioritize.
Are you interested in taking this? I'm happy to if not!
@sethetter I'm slowly going through investigating this issue, and am planning to take it on. I don't have a timeline yet, but if you feel it's a high priority, feel free to add the protection. At least I've documented the steps to exploit for testing against. 👍❤️
To implement, we can generate a csrf token. There's an example of how this can be done here: https://github.com/utrack/gin-csrf, but we're not going to pull in that package to do it, and instead write our own middleware.
It looks like we're already using an in-memory session store, so we'll play with that to implement this csrf token middleware.
Reference: