Vulnerabilities Summary
The Cohu 3960HD Series cameras contain multiple vulnerabilities: directory listing, unauthenticated XMLRPC commands, arbitrary file upload and code execution, source code disclosure, failed session expiration, and client-side input validation vulnerabilities were discovered. The directory listing issue led to the discovery of other included vulnerabilities.
Product Overview
The Cohu 3960HD is a rugged IP enabled pan/tilt/zoom camera designed for outdoor use in critical infrastructure. Research and experience shows they are often used as traffic cameras. The camera has two main interfaces for interaction, a web interface and an API.
Timeline
8/27/2015 - Discovered vulnerabilities
9/10/2015 - Shodan shows ~200 devices directly connected to internet
12/2/2015 - Internal conversations on disclosure (legal issues)
2/29/2016 - Contact with client to discuss remediation of vulnerabilities
3/2/2016 - Vendor notified of vulnerabilities, follow up call scheduled
3/15/2016 - Meeting scheduled, then cancelled
3/17/2016 - Meeting scheduled, then cancelled
4/1/2016 - Email from client to vendor sent requesting follow-up
4/12/2016 - Vendor states they have been performing a security assessment on their newer camera
4/21/2016 - Vendor response states vulnerabilities are corrected in new hardware model
9/29/2016 - Client provides permission to publish vulnerability
5/4/2017 - Vendor contacted to get update and informed of intent to publish. Vulnerabilities not patched as the 3960HD had reached maturity, in other words end-of-life.
Vulnerability Classes
CWE-548 Information Exposure Through Directory Listing
CWE-319 Cleartext Transmission of Sensitive Information
CWE-306 Missing Authentication for Critical Function
CWE-434 Unrestricted Upload of File with Dangerous Type
CWE-540 Information Exposure Through Source Code
CWE-602 Client Side Enforcement of Server-Side Security
CVE IDs
Vulnerability Details
Information Exposure Through Directory Listing
Appending an extra on http://cohu_camera_ip/ results in a full directory listing
GET // HTTP/1.1
Host: cohu_camera_ip
Accept: */*
Accept-Language: en
User-Agent: Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Win64; x64; Trident/5.0)
Connection: close
Cookie: session=-- [REDACTED]
HTTP/1.1 200 OK
Date: Thu, 08 Jan 1970 03:36:38 GMT
Server: Cohu Camera
Content-Type: text/html
Content-Length: 7953
Â
<html>
<head>
<title>Directory listing of /ambarella/appweb/web                </title>
<style type="text/css">
body {font-family:courier new,verdana,sans-serif;background-color:#eeeeee;}
table{font-size: 12px; font-weight:bold}
</style>
</head>
<body>
<p/>
<center>
<h2>Directory listing of //drwxr-xr-x</td>
<td>default</td>
<td>default</td>
<td align="right">0</td>
<td>1970-01-01T00:00:00.876Z</td>
<td>1970-01-01T00:00:00.787Z</td>
<td><a href="/">..</a></td>
</tr>Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â <tr>
<td>drwxr-xr-x</td>
<td>default</td>
<td>default</td>
<td align="right">0</td>
<td>1970-01-17T09:47:27.203Z</td>
<td>1970-01-01T00:00:00.787Z</td>
<td><a href="/js">js</a></td>
Cleartext Transmission of Sensitive Information
The Cohu 3960HD is not capable of running the SSL libraries due to processor constraints. The lack of encrypted communications exposes both the HTTP and XMLRPC services to content sniffing and man in the middle attacks.
Missing Authentication for Critical Function
Port 1236/TCP accepts unauthenticated XML SOAP formatted commands. These commands can be used to change IP addresses, user names, and passwords The following configuration parameters can be sent:
CM_CFGIP_ALL,
CM_CFGIP_USEDHCP,
CM_CFGIP_DEVICEIP,
CM_CFGIP_SUBNETMASK,
CM_CFGIP_GATEWAYADDRESS,
CM_CFGIP_HOSTNAME,
CM_CFGIP_USEDNSSERVER,
CM_CFGIP_DOMAIN,
CM_CFGIP_DNSSERVER,
CM_CFGIP_USERNAME,
CM_CFGIP_PASSWORD,
CM_CFGIP_END,
CM_CFGSTREAMING_ALL = 32,
CM_CFGSTREAMING_STREAM1TRANSPORT,
CM_CFGSTREAMING_STREAM1MULTIADDRESS,
CM_CFGSTREAMING_STREAM1MAXPACKETSIZE,
CM_CFGSTREAMING_STREAM2TRANSPORT = 48,
CM_CFGSTREAMING_STREAM2MULTIADDRESS,
CM_CFGSTREAMING_STREAM2MAXPACKETSIZE,
CM_CFGSTREAMING_END,
CM_CFGFORMAT_ALL = 64,
CM_CFGFORMAT_SENSORINPUT,
CM_CFGFORMAT_FRAMERATE,
CM_CFGFORMAT_ENCODING,
CM_CFGFORMAT_STREAM1RESOLUTION,
CM_CFGFORMAT_STREAM1FRAMERATE,
CM_CFGFORMAT_STREAM1BITRATE,
Unrestricted Upload of File with Dangerous Type
As part of the firmware upload process, webupgrade.sh unpacks the tar file and runs postinstall.sh. Any tar file could be uploaded with a malicious postinstall.sh, which the camera would execute with root privileges.
Information Exposure Through Source Code
Due to the directory listing, and the failure of the web server to recognize .esp as server-side code, the web server displays the full source code of .esp web pages. This reveals more information about the system and potential attacks paths and targets. Multiple cases of this exist on the platform.
GET /upgrade.esp HTTP/1.1
Host: cohu_camera_ip
Accept: */*
Accept-Language: en
User-Agent: Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Win64; x64; Trident/5.0)
Connection: close
Referer: http://172.16.0.2//
Cookie: session=--[REDACTED]
HTTP/1.1 200 OK
Date: Thu, 08 Jan 1970 03:36:38 GMT
Last-Modified: Wed, 03 Dec 2014 22:53:19 GMT
Content-Length: 691
Content-Type: text/plain
Date: Thu, 08 Jan 1970 03:36:38 GMT
Server: Cohu Camera
<html>
<head>
<title>Cohu Firmware Upgrade Completed</title>
<META HTTP-EQUIV="Refresh" CONTENT="2;url=/cgi-bin/upgrade.cgi">
<style type="text/css">
body {
color: black; background: #CCCCCC;
margin-left: 10%; margin-right: 10%;
}
h1, h2 { margin-left: -5%; }
hr { color: gray; }
</style>
</head>
<%
if (request["REQUEST_METHOD"] == "POST") {
write("<br/><hr/> <p><br/>File " + files['uploadFile'].CLIENT_FILENAME +
" has been uploaded.</p>");
target = "/tmp/cohuupload";
rename(files['uploadFile'].FILENAME, target);
write ("<p><h3>Please wait as the new image is written on permanent storage...</h3></p> <br/><hr/>");
}
%>
</html>
AND GET /tmp/tmp_root/bin/postinstall.sh
#!/bin/sh
doneFile="/tmp/upgradeweb.done"
lockFile="/tmp/upgradeweb.lock"
status="/tmp/upgradeweb.status"
countDots() {
cnt=`cat $lockFile`
echo "0" > $lockFile
i=0
while [ $i -lt $cnt ]; do
echo -n " ." >> $status
i=`expr $i + 1`
done
echo "" >> $status
}
doneStatus=0
untarDir=`echo $0 | sed -e 's|\(.*\)/bin/.*$|\1|'`
echo "Checking MAC address" >> $status
mac=""
eeprom_out="/tmp/eeprom.out"
if [ ! -f $eeprom_out ]; then
/usr/local/bin/eeprom_read > $eeprom_out
if [ ! -f $eeprom_out ]; then
echo "Failed to read EEPROM: Is it programmed? " >> $status
exit 4
fi
fi
Client Side Enforcement of Server Side Security
Multiple cases of using client-side code to check server-side parameters and configuration changes. Client side code (Javascript) can be manipulated or disabled before being sent back to the server to inject spurious information to the system to cause failure or compromise. Sample (many other instances)
function submit_changes(save) {
var ctl;
var xml = "";
if (!form.Validate()) {
var logMessage = new LogMessage();
logMessage.Header = "Form validation errors!";
for (var i = 0; i < form.ValidationErrors.length; i++) {
logMessage.Lines[logMessage.Lines.length] = form.ValidationErrors[i]
}
document.Logger.LogUserInfo(logMessage);
return;
}
form.ApplyData();
if (!passwordsAreEqual())
return;
try {
//set settings
var xmlRequest = (new SetFTPEmailRequest(form.FTP, form.Email)).ToXml();
document.Logger.LogDebug(xmlRequest);
var info;
if (info = opener.soapRequest("device_service", xmlRequest)) {
var xmlFault = info.getElementsByTagName("Fault");
if (xmlFault.length > 0) {
var fault = new FaultResponse(xmlFault[0]);
document.Logger.LogDebug("Can not set FTP and Email Configuration Settings. ServiceResponse: " + fault.ToString());
}
else {
document.Logger.LogDebug(info.xml);
setAllAsDefault();
}
}
}