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.
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: 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: 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