CVE-2022-47945
Description
ThinkPHP Framework before 6.0.14 allows local file inclusion via the lang parameter when the language pack feature is enabled (lang_switch_on=true). An unauthenticated and remote attacker can exploit this to execute arbitrary operating system commands, as demonstrated by including pearcmd.php.
AI Insight
LLM-synthesized narrative grounded in this CVE's description and references.
CVE-2022-47945 allows unauthenticated remote attackers to achieve local file inclusion and RCE in ThinkPHP prior to 6.0.14 via the lang parameter when language packs are enabled.
Vulnerability
Details
CVE-2022-47945 is a local file inclusion vulnerability in the ThinkPHP framework versions before 6.0.14. The flaw resides in the language pack feature (lang_switch_on=true). When this feature is enabled, the framework's detect() method in the language handling component does not properly sanitize user-supplied input passed through the lang parameter (or via HTTP headers and cookies), allowing directory traversal sequences to reach arbitrary files on the server [1][2][3]. The vulnerable code was removed in commit c4acb8b, which deleted the deprecated detect() method and its insecure handling of the language variable [3].
Exploitation
An unauthenticated remote attacker can exploit this by sending a crafted request with a lang parameter containing path traversal sequences, such as ../../../public/plugins/pearcmd.php. No authentication or special network position is required; the attacker only needs the target to have the language pack feature enabled [1][2]. The official advisory demonstrates that including the pearcmd.php file from a PHP installation (which is not present by default in all configurations but can be leveraged if available) allows the attacker to execute arbitrary operating system commands [1]. The vulnerability affects ThinkPHP versions 6.0.1 through 6.0.13, as well as 5.0.x and 5.1.x when the language pack is enabled [2].
Impact
Successful exploitation leads to arbitrary file inclusion, which an attacker can further weaponize into remote code execution (RCE). By including a file like pearcmd.php, the attacker can pass arguments to execute system commands, potentially gaining full control over the affected server [1][2]. Given the unauthenticated and remote nature, this vulnerability is critical for any exposed ThinkPHP application with the language pack feature turned on.
Mitigation
The vulnerability is patched in ThinkPHP framework version 6.0.14, released in October 2022 [1][4]. Users must upgrade to at least 6.0.14 or, if unable to upgrade, disable the language pack feature by removing the \think\middleware\LoadLangPack::class middleware entry from the application's middleware configuration [2]. Versions 5.x are also affected and may require manual patching or disabling the language pack as a workaround.
AI Insight generated on May 20, 2026. Synthesized from this CVE's description and the cited reference URLs; citations are validated against the source bundle.
Affected packages
Versions sourced from the GitHub Security Advisory.
| Package | Affected versions | Patched versions |
|---|---|---|
topthink/frameworkPackagist | < 6.0.14 | 6.0.14 |
Affected products
2- ThinkPHP/Frameworkdescription
Patches
12 files changed · +13 −67
src/think/Lang.php+0 −54 modified@@ -287,58 +287,4 @@ public function get(string $name = null, array $vars = [], string $range = '') return $value; } - /** - * 自动侦测设置获取语言选择 - * @deprecated - * @access public - * @param Request $request - * @return string - */ - public function detect(Request $request): string - { - // 自动侦测设置获取语言选择 - $langSet = ''; - - if ($request->get($this->config['detect_var'])) { - // url中设置了语言变量 - $langSet = strtolower($request->get($this->config['detect_var'])); - } elseif ($request->header($this->config['header_var'])) { - // Header中设置了语言变量 - $langSet = strtolower($request->header($this->config['header_var'])); - } elseif ($request->cookie($this->config['cookie_var'])) { - // Cookie中设置了语言变量 - $langSet = strtolower($request->cookie($this->config['cookie_var'])); - } elseif ($request->server('HTTP_ACCEPT_LANGUAGE')) { - // 自动侦测浏览器语言 - $match = preg_match('/^([a-z\d\-]+)/i', $request->server('HTTP_ACCEPT_LANGUAGE'), $matches); - if ($match) { - $langSet = strtolower($matches[1]); - if (isset($this->config['accept_language'][$langSet])) { - $langSet = $this->config['accept_language'][$langSet]; - } - } - } - - if (empty($this->config['allow_lang_list']) || in_array($langSet, $this->config['allow_lang_list'])) { - // 合法的语言 - $this->range = $langSet; - } - - return $this->range; - } - - /** - * 保存当前语言到Cookie - * @deprecated - * @access public - * @param Cookie $cookie Cookie对象 - * @return void - */ - public function saveToCookie(Cookie $cookie) - { - if ($this->config['use_cookie']) { - $cookie->set($this->config['cookie_var'], $this->range); - } - } - }
src/think/middleware/LoadLangPack.php+13 −13 modified@@ -70,33 +70,33 @@ protected function detect(Request $request): string if ($request->get($this->config['detect_var'])) { // url中设置了语言变量 - $langSet = strtolower($request->get($this->config['detect_var'])); + $langSet = $request->get($this->config['detect_var']); } elseif ($request->header($this->config['header_var'])) { // Header中设置了语言变量 - $langSet = strtolower($request->header($this->config['header_var'])); + $langSet = $request->header($this->config['header_var']); } elseif ($request->cookie($this->config['cookie_var'])) { // Cookie中设置了语言变量 - $langSet = strtolower($request->cookie($this->config['cookie_var'])); + $langSet = $request->cookie($this->config['cookie_var']); } elseif ($request->server('HTTP_ACCEPT_LANGUAGE')) { // 自动侦测浏览器语言 - $match = preg_match('/^([a-z\d\-]+)/i', $request->server('HTTP_ACCEPT_LANGUAGE'), $matches); - if ($match) { - $langSet = strtolower($matches[1]); - if (isset($this->config['accept_language'][$langSet])) { - $langSet = $this->config['accept_language'][$langSet]; - } + $langSet = $request->server('HTTP_ACCEPT_LANGUAGE'); + } + + if (preg_match('/^([a-z\d\-]+)/i', $langSet, $matches)) { + $langSet = strtolower($matches[1]); + if (isset($this->config['accept_language'][$langSet])) { + $langSet = $this->config['accept_language'][$langSet]; } } if (empty($this->config['allow_lang_list']) || in_array($langSet, $this->config['allow_lang_list'])) { // 合法的语言 - $range = $langSet; - $this->lang->setLangSet($range); + $this->lang->setLangSet($langSet); } else { - $range = $this->lang->getLangSet(); + $langSet = $this->lang->getLangSet(); } - return $range; + return $langSet; } /**
Vulnerability mechanics
Generated on May 9, 2026. Inputs: CWE entries + fix-commit diffs from this CVE's patches. Citations validated against bundle.
References
6- github.com/advisories/GHSA-p4qr-vq2g-22wpghsaADVISORY
- nvd.nist.gov/vuln/detail/CVE-2022-47945ghsaADVISORY
- github.com/top-think/framework/commit/c4acb8b4001b98a0078eda25840d33e295a7f099ghsaWEB
- github.com/top-think/framework/compare/v6.0.13...v6.0.14ghsaWEB
- tttang.com/archive/1865ghsaWEB
- tttang.com/archive/1865/mitre
News mentions
0No linked articles in our index yet.