Tuesday, January 19, 2016

Administrator logout flaw in ASUS wireless routers

ASUS wireless routers have an optional feature to log the administrator out after a period of time. That feature was implemented in April 2014, in firmware 3.0.0.4.374_5656, in response to input I gave to their engineering team while correcting a previously reported flaw. Prior to then, if you logged into the router administration UI and did not explicitly log out, your session remained active forever.

While there are scenarios where you might want to keep a logged in session, remaining logged in makes it possible for a malicious hacker to use that session by tricking you into clicking a link. Researcher Bogdan Calin describes this sort of attack in a post he wrote a few years ago. His demo relies on guessing the admin password, but that is not necessary if you are already logged in.

The aforementioned firmware added an optional auto logout feature, so problem solved, right?

Well, not entirely.

This report is one in a series I have written on ASUS wireless router features and vulnerabilities. Others of interest:


The non-technical version


ASUS wireless router models based on the ASUSWRT firmware up to and including the most recent version as of this writing - version 3.0.0.4.378_9460 (dated 2015-12-29) rely on the browser to enforce the auto-logout function. This means if you close the browser window without logging out, or if you run your browser in a high-security mode that disables scripting, your administrative session remains active forever (or at least until the next power outage reboots the router).

The easiest way to be certain your router administrator session is not left active when you don't need it, is to log out when you are finished configuring your router.


The technical version


Models based on the ASUSWRT firmware up to and including the most recent version as of this writing - version 3.0.0.4.378_9460 (dated 2015-12-29) - implement the administrator auto-logout function via JavaScript in the browser. Each web page loads a variety of JavaScript libraries:


<script type="text/javascript" src="/md5.js"></script>
<script type="text/javascript" src="/state.js"></script>
<script type="text/javascript" src="/general.js"></script>
<script type="text/javascript" src="/popup.js"></script>
<script type="text/javascript" src="/disk_functions.js"></script>
<script type="text/javascript" src="/help.js"></script>
<script type="text/javascript" src="/validator.js"></script>
<script language="JavaScript" type="text/javascript" src="/client_function.js"></script>
<script language="JavaScript" type="text/javascript" src="/js/jquery.js"></script>
<script type="text/javascript" src="/switcherplugin/jquery.iphone-switch.js"></script>
<script language="JavaScript" type="text/javascript" src="/form.js"></script>
<script type="text/javascript" src="/jquery.xdomainajax.js"></script>


Relevant to this issue is state.js, which contains the following code that executes upon loading any page in the router's administration interface:


document.getElementById("TopBanner").innerHTML = banner_code;
show_loading_obj();
show_top_status();
updateStatus();


This runs the function updateStatus() to check a counter AUTOLOGOUT_MAX_MINUTE. The counter begins at the number of minutes specified by the administrator in the Auto Logout setting, and is decremented with each iteration of updateStatus(). When the counter reaches 1, the JavaScript module redirects to the logout page.



var AUTOLOGOUT_MAX_MINUTE = parseInt('19') * 20;
function updateStatus(){
if(stopFlag == 1) return false;
if(AUTOLOGOUT_MAX_MINUTE == 1) location = "Logout.asp"; // 0:disable auto logout, 1:trigger auto logout.
require(['/require/modules/makeRequest.js'], function(makeRequest){
if(AUTOLOGOUT_MAX_MINUTE != 0) AUTOLOGOUT_MAX_MINUTE--;
makeRequest.start('/ajax_status.xml', refreshStatus, function(){stopFlag = 1;});
});
}
.
.
.
setTimeout(function(){updateStatus();}, 3000); /* restart ajax */

The last line in this block of code sets a timer to again call the updateStatus() function after 3 seconds. This has the effect of checking for expiration of the logout timer every three seconds.

Keep in mind that this code runs in the client's browser. Ultimately this places control of the autologout in the hands of the client (either the web browser or the person) instead of it being controlled by the server.

This means that if the browser instance closes without the user manually logging out (or if the user has JavaScript disabled in his or her browser), the administrative session can remain logged on indefinitely and potentially be co-opted by an intruder. It's an improvement over not having the feature at all, but better still would be to have the time kept by the router, and have the router log the admin account off after the selected time has elapsed, instead of relying on the client.

If the user has disabled JavaScript, this function is never triggered. Users not in the habit of explicitly logging out of websites may simply close the web UI window, expecting the router to automatically terminate the session after a set time. In both cases, an administrative session remains open on the router without the operator's knowledge.

One simple way this might be exploited is to open the wireless settings panel at [router-address]/Advanced_Wireless_Content.asp and scrape the WPA2 key from the HTML code. With a pre-existing logged-in session on the router, there is no need for the attacker to know credentials.

Lack of an auto-logout function itself is not necessarily a security flaw, but In my opinion an improperly implemented auto-logout feature is a security risk, in that the operator would expect the router to end the session automatically based on the specified timeout.

This line of firmware is used on most modern ASUS wireless routers; I specifically have tested the RT-AC87U and RT-AC66U, but the same code base is used across many other models.

This was first reported to ASUS on December 13, 2014. It was acknowledged but never changed.


What should you do?


The easiest solution is to simply make a point of logging out before closing your browser window. It's slightly inconvenient, and it defeats the purpose of having an auto-logout timer in the first place, but it does the trick.