Repository: pagekit/pagekit

Issue #815: DOM XSS in editor.js
Created: 2017-04-05T07:11:42Z
DOM XSS was found in editor form (editor.js)
Triggers while copying content (contains XSS payloads) somewhere into editor, or just edit context posted by other user.
PoC


Pagekit version: 1.0.11
Webserver: Apache
Database: MySQL
PHP Version: 7

Duplicate issue #962: PageKit > Cross-site scripting (DOM-based)
Created: 2021-03-04T08:14:15Z
Problem
We have run BurpSuit(Security Scan tool) on our PageKit project and it was providing high-risk bugs in codemirror.js which is internally used in editor.js in Pagekit.
Report Details



Cross-site scripting (DOM-based)
/admin/site/page/edit
Issue detail:

The application may be vulnerable to DOM-based cross-site scripting. Data is read from textarea.value and passed to jQuery.html.


Issue background


DOM-based vulnerabilities arise when a client-side script reads data from a controllable part of the DOM (for example, the URL) and processes this data in an unsafe way.
DOM-based cross-site scripting arises when a script  writes controllable data into the HTML document in an unsafe way. An attacker may be able to use the vulnerability to construct a URL that, if visited by another application user, will cause JavaScript code supplied by the attacker to execute within the user's browser in the context of that user's session with the application.
The attacker-supplied code can perform a wide variety of actions, such as stealing the victim's session token or login credentials, performing arbitrary actions on the victim's behalf, and logging their keystrokes.
Users can be induced to visit the attacker's crafted URL in various ways, similar to the usual attack delivery vectors for reflected cross-site scripting vulnerabilities.
Burp Suite automatically identifies this issue using static code analysis, which may lead to false positives that are not actually exploitable. The relevant code and execution paths should be reviewed to determine whether this vulnerability is indeed present, or whether mitigations are in place that would prevent exploitation.


Issue remediation


The most effective way to avoid DOM-based cross-site scripting vulnerabilities is not to dynamically write data from any untrusted source into the HTML document. If the desired functionality of the application means that this behavior is unavoidable, then defenses must be implemented within the client-side code to prevent malicious data from introducing script code into the document. In many cases, the relevant data can be validated on a whitelist basis, to allow only content that is known to be safe. In other cases, it will be necessary to sanitize or encode the data. This can be a complex task, and depending on the context that the data is to be inserted may need to involve a combination of JavaScript escaping, HTML encoding, and URL encoding, in the appropriate sequence. 

References


Cross-site scripting
		DOM-based cross-site scripting
	


Vulnerability classifications


CWE-79: Improper Neutralization of Input During Web Page Generation ('Cross-site Scripting')
CWE-80: Improper Neutralization of Script-Related HTML Tags in a Web Page (Basic XSS)
CWE-116: Improper Encoding or Escaping of Output
CWE-159: Failure to Sanitize Special Element


Request:
GET /admin/site/page/edit?id=page&menu=administrator HTTP/1.1
Host: pagekit.com
Cookie: pagekit_session=in8ah866le3ra2krdp04ttvtd9; pagekit_auth=BBheftEBY9AqeDiqdBmcdBGdVBR8XiQ8.LjejPpWLZo%2FeZyydLRM%2FFfPX84MBq6v; current_role=MQ%3D%3D; remember_ses=in8ah866le3ra2krdp04ttvtd9
Upgrade-Insecure-Requests: 1
Referer: https://pagekit.com/admin/site/page
Accept: */*
Accept-Language: en-US,en-GB;q=0.9,en;q=0.8
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.88 Safari/537.36
Connection: close
Cache-Control: max-age=0
Accept-Encoding: gzip, deflate

Response:
HTTP/1.1 200 OK
Date: Thu, 04 Feb 2021 15:46:55 GMT
Content-Type: text/html; charset=UTF-8
Content-Length: 19195
Connection: close
Server: Apache
Vary: X-Forwarded-Proto,Accept-Encoding
Set-Cookie: remember_ses=in8ah866le3ra2krdp04ttvtd9; expires=Sat, 06-Feb-2021 15:46:55 GMT; Max-Age=172800; path=/; secure; HttpOnly
Cache-Control: private, max-age=0, no-store, max-age=0
Set-Cookie: current_role=MQ%3D%3D; expires=Fri, 04-Feb-2022 15:46:55 GMT; Max-Age=31536000; path=/; secure; HttpOnly
Set-Cookie: remember_ses=in8ah866le3ra2krdp04ttvtd9; expires=Sat, 06-Feb-2021 15:46:55 GMT; Max-Age=172800; path=/; secure; HttpOnly
Cache-Control: no-cache
Expires: Thu, 04 Feb 2021 15:46:55 GMT
<!DOCTYPE html>
<html lang="en-US">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, iSnip
Dynamic analysis:


Data is read from textarea.value and passed to jQuery.html.



The following value was injected into the source:
m6437stmf5%2527%2522`'"/m6437stmf5/><m6437stmf5/\>orxqqixu24&


The previous value reached the sink:
uhmx5hf1ek%2527%2522`'"/uhmx5hf1ek/><uhmx5hf1ek/\>dynvems276&


The stack trace at source was:
at HTMLTextAreaElement.get [as value] (<anonymous>:1:765266)
at Function.v.fromTextArea (https://pagekit.com/app/assets/codemirror/codemirror.js:43:1640)
at o.init (https://pagekit.com/app/assets/uikit/js/components/htmleditor.min.js:2:1472)
at new o (https://pagekit.com/app/assets/uikit/js/uikit.min.js?v=19e2:2:6776)
at Object.<computed> [as htmleditor] (https://pagekit.com/app/assets/uikit/js/uikit.min.js?v=19e2:2:8068)
at VueComponent.<anonymous> (https://pagekit.com/app/system/modules/editor/app/bundle/editor.js?v=19e2:170:55)


The stack trace at the sink was:
at Object.apply (<anonymous>:1:940882)
at o.render (https://pagekit.com/app/assets/uikit/js/components/htmleditor.min.js:2:6362)
at o.disableMarkdown (https://pagekit.com/app/assets/uikit/js/components/htmleditor.min.js:2:13245)
at HTMLTextAreaElement.disableMarkdown (https://pagekit.com/app/assets/uikit/js/components/htmleditor.min.js:2:13338)
at HTMLTextAreaElement.dispatch (https://pagekit.com/app/assets/jquery/dist/jquery.min.js?v=19e2:3:6466)
at HTMLTextAreaElement.r.handle (https://pagekit.com/app/assets/jquery/dist/jquery.min.js?v=19e2:3:3241)
at Object.trigger (https://pagekit.com/app/assets/jquery/dist/jquery.min.js?v=19e2:3:5574)
at HTMLTextAreaElement.<anonymous> (https://pagekit.com/app/assets/jquery/dist/jquery.min.js?v=19e2:3:11542)
at Function.each (https://pagekit.com/app/assets/jquery/dist/jquery.min.js?v=19e2:2:2882)
at Object.each (https://pagekit.com/app/assets/jquery/dist/jquery.min.js?v=19e2:2:847)
at Object.trigger (https://pagekit.com/app/assets/jquery/dist/jquery.min.js?v=19e2:3:11518)
at o.trigger (https://pagekit.com/app/assets/uikit/js/uikit.min.js?v=19e2:2:7321)
at VueComponent.$watch.immediate (https://pagekit.com/app/system/modules/editor/app/bundle/editor.js?v=19e2:195:25)
at VueComponent.t.$watch (https://pagekit.com/app/assets/vue/dist/vue.min.js?v=19e2:7:2786)
at VueComponent.<anonymous> (https://pagekit.com/app/system/modules/editor/app/bundle/editor.js?v=19e2:194:19)


This was triggered by a load event.






Is there any way to fix this issue? Thanks in advance!!
Technical Details

Pagekit version: 1.0.13
Webserver: Apache
Database: 5.6.10
PHP Version: 7.3.19

Closing comment (2021-03-22T14:49:03Z): DOM-based cross-site scripting arises when a script writes controllable data into the HTML document in an unsafe way. An attacker may be able to use the vulnerability to construct a URL that, if visited by another application user, will cause JavaScript code supplied by the attacker to execute within the user's browser in the context of that user's session with the application.

I don't see how this is possible. The field is filled with either content comming from the database or with content coming from the page user currently visiting the page. Nothing is used from the URL.
Additionally, dupe of #815

Well, it is literally explained in the OP how it works. If a logged in user  navigates to a purposely crafted url their session might get stollen. For example by clicking the link in the comments. This is not something new.