Skip to content
This repository has been archived by the owner on Dec 1, 2023. It is now read-only.

PageKit > Cross-site scripting (DOM-based) #962

Open
dharmeshloriya-dev opened this issue Mar 4, 2021 · 7 comments
Open

PageKit > Cross-site scripting (DOM-based) #962

dharmeshloriya-dev opened this issue Mar 4, 2021 · 7 comments

Comments

@dharmeshloriya-dev
Copy link

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

Vulnerability classifications

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, i

Snip

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
@foxnoodles
Copy link

And no one even replied to this? Amazing.

@ahoiroman
Copy link
Contributor

Pagekit is (almost) dead. I suggest to head over to biskuit cms (Pagekit fork)

@tobbexiv
Copy link
Contributor

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

@foxnoodles
Copy link

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.

@tobbexiv
Copy link
Contributor

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.

There is a generic explanation on how such attacks could work. However, it is not stated that this is always possible. In this specific scenario I don't see a possible attack here. Nothing from the URL is passed to the textarea, the textarea is only filled by the user or from server side. The user has to be logged in and have access to the admin panel (which should be granted to trusted users, only).

However, I am open to be convinced by the opposite by a working example.

For example by clicking the link in the comments.

User entered content in the comments is not using this editor component and additionally is sanitized.

This is not something new.

The attack vector is not something new. But, to be a threat it is also require that it can be exploited. And in this particular scenario, I don't see a possibility to exploit.

@foxnoodles
Copy link

Have you inspected an example provided by OP? He managed to inject a code into into DOM via CrossSite request.

P.S. PageKit development is dead anyway so yeah.

@tobbexiv
Copy link
Contributor

tobbexiv commented Apr 8, 2021

I just see a statement that if a textare on the page is filled with a specific value, then this value is printed to the page. This is correct as this is the design of an HTML editor. However, I don't see steps to reproduce this issue. So, there is nothing I could check. I just see a code analysis of a tool from where I don't get what I have to do to reproduce the issue.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants