Charlton's Blog

Edsby XSS Proof-of-Concept

Ping Executes Any Command Entered

Published: Aug 26, 2017
Category: Programming, Projects, Security
Tags: , ,

Check it out on GitHub.

Confirmed to work on Edsby instances with version numbers of at least 17431 and below (also seen as 1492092324). Update: This vulnerability has been fixed in a patch rolled out to all Edsby instances as of June 2017, very shortly after disclosure. Many thanks to CoreFour for their prompt response to the issue:)


Edsby’s backend does not validate URL metadata passed when posting links, and instead posts the included content straight into the DOM, without validation. Using this, we can effectively post arbitrary HTML into any class feed, which gives us a persistent XSS vulnerability.

How does it work?

When a user drafts a message that includes one or more links, Edsby calls its own web spider API and attempts to scrape metadata about the webpage so it can generate a kind of URL preview later on, which it appends to the bottom of the post.

However, an issue arises when including this metadata in a message submission. After scraping and formatting, the link preview JSON (which is attached to the message submission) looks like this. Notice the identical url and href properties:

        "code": 200,
        "description": "Search the world's information, including webpages, images, videos and more. Google has many special features to help you find exactly what you're looking for.",
        "right": {
            "description": "Search the world's information, including webpages, images, videos and more. Google has many special features to help you find exactly what you're looking for.",
            "title": "Google"
        "embedstatus": "complete",
        "uuid": 6,
        "title": "Google",
        "url": "",
        "href": "",
        "type": "link",
        "thumbnail": "",
        "left": {
            "thumbnail": ""

As it turns out, while the href property is used to set the corresponding value in the generated link for the preview, the url property is simply placed inside of the <a> tag without any kind of validation or escaping whatsoever. So, you can place any html you’d like to add to the DOM (including script elements) in here, and it will be rendered by the user’s browser. Assuming that all of the other properties in this object remain unchanged, it’ll still render as a normal link preview. Posts with XSS included are indistinguishable from other posts in your class feed (Scary!).

Side note: I have tested to see if you can post fake links by setting the URL as one value and href as another, but it doesn’t seem to work.

Why is this bad?

If you aren’t already familiar with the security risks posed by XSS vulnerabilities, you should familiarize yourself.

Some nasty things a malicious actor could do with this:
  • Steal the current user’s session cookies and personal information,
  • Perform any action on Edsby as the current user: student, teacher, or administrator,
  • Make a self-replicating worm (like Samy) that spreads throughout your entire instance,
  • Or really anything else.


As of right now, there is no way to prevent the submission of malicious payloads, or for Edsby users to protect themselves from their reciept. You’ll have to sit tight and wait for CoreFour to update the backend so it validates inputs properly.

Update: Has been patched as of early June!


This document includes a Proof-Of-Concept which demonstrates the exploitation process. This section details how it should be configured.

      Set to False to actually send the payload

      Edsby instance hostname

      Your Edsby username

      Your edsby password

      NID of the class you want to post the payload in.
      Must be a class you have permissions to post in.

      Link that the message should appear as. Will be scraped to generate the link preview.

        Default is a manually triggered payload, so the user must click the link for it to run.

        If an automatically running payload were desired, use similar to the following:

        '</a><a href="">nothing illegitimate here<img onerror="alert(\'Whoops.\')"/></a><a>'