You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
I am from the Pwn2Win CTF organization and for this year's edition, one of the challenges we created had as an objective finding a vulnerability on CodiMD that allowed players to retrieve a message from a private note (much like hxp's hackme challenge from last year).
Details on the vulnerability we used to prove that the challenge was solvable can be found below:
CodiMD has a functionality that allows users to import gists through the {%gist gist_id %} syntax.
The gist_id is then run against two different regex rules before a code tag containing a data-gist-id attribute is inserted into the page.
constgistPlugin=newPlugin(// regexp to match/{%gist\s*([\d\D]*?)\s*%}/,(match,utils)=>{constgistid=match[1].split(/[?&=]+/)[0]constcode=`<code data-gist-id="${gistid}"></code>`returncode})
The library tries to fetch the gist from Github and if it fails, prints an error message on the page through the use of JQuery's html method (which is insecure).
The error message also contains the id of the gist.
This means that if we try to load an invalid gist that contains HTML code on its id, an error message will be reflected on the page containing the HTML code we used.
For example - if {%gist <strike>This was reflected as HTML!</strike> %} were to be inserted into a CodiMD note, it would be rendered as HTML, as can be seen below:
The only thing in the way of achieving XSS is the second regex rule which prevents the ?, & and = characters, and due to the existing CSP, inserting only a script tag wouldn't work.
The solution, however, is simple:
Given CodiMD allows a subset of HTML elements we can simply insert <code data-gist-id="payload"></code> directly into the page (bypassing the regex checks), and it will then be executed by the gist-embed library code.
The final payload uses google-analytics.com to bypass the CSP and execute XSS:
Hi!
I am from the Pwn2Win CTF organization and for this year's edition, one of the challenges we created had as an objective finding a vulnerability on CodiMD that allowed players to retrieve a message from a private note (much like hxp's hackme challenge from last year).
Details on the vulnerability we used to prove that the challenge was solvable can be found below:
CodiMD has a functionality that allows users to import gists through the
{%gist gist_id %}
syntax.The
gist_id
is then run against two different regex rules before a code tag containing adata-gist-id
attribute is inserted into the page.The first regex rule is rather lax and allows almost any character, while the second one is a bit more restrictive and prevents the
?
,&
and=
characters (https://github.com/hackmdio/codimd/blob/develop/public/js/extra.js#L1338).Afterward, the
gist_id
is retrieved from thedata-gist-id
attribute of the code tag and rendered by the gist-embed library (https://www.npmjs.com/package/gist-embed/v/2.6.0).The library tries to fetch the gist from Github and if it fails, prints an error message on the page through the use of JQuery's html method (which is insecure).
The error message also contains the id of the gist.
This means that if we try to load an invalid gist that contains HTML code on its id, an error message will be reflected on the page containing the HTML code we used.
For example - if
{%gist <strike>This was reflected as HTML!</strike> %}
were to be inserted into a CodiMD note, it would be rendered as HTML, as can be seen below:The only thing in the way of achieving XSS is the second regex rule which prevents the
?
,&
and=
characters, and due to the existing CSP, inserting only a script tag wouldn't work.The solution, however, is simple:
Given CodiMD allows a subset of HTML elements we can simply insert
<code data-gist-id="payload"></code>
directly into the page (bypassing the regex checks), and it will then be executed by the gist-embed library code.The final payload uses google-analytics.com to bypass the CSP and execute XSS:
The text was updated successfully, but these errors were encountered: