PHP 服务挂了之后是不是就能查看. PHP 文件源码了?

2021-10-21 18:15:20 +08:00
 ysy950803

问个小白问题,有这么一个场景,假如我把.php 文件放在网站目录下,和 index.html 同目录,可通过浏览器访问的那种。 比如有一个 test.php 文件,里面有一些 PHP 代码,不渲染任何东西,当服务正常的时候,浏览器显示空白,这是正常情况。但如果 fpm 等相关服务挂掉了,是不是再访问就直接视为普通文本文件返回给浏览器了?这样就能看见源码了?

8795 次点击
所在节点    PHP
115 条回复
sarices
2021-10-27 16:06:41 +08:00
我怀疑楼主是来钓鱼的,不过我没证据
void1900
2021-10-27 16:07:27 +08:00
@miencun 我已经服输了,他应该已经放过我了
void1900
2021-10-27 16:07:48 +08:00
@sarices 钓蛙
ccreater222
2021-10-27 16:08:10 +08:00
正常情况下不会。非正常情况就是你配置了处理 upstream 无响应的配置,中间件的漏洞
wonderfulcxm
2021-10-27 16:15:46 +08:00
跟 mine-type 没关系啊,服务器 nginx 也不是靠 mine-type 转发给 php 处理的,浏览器 conten-type 跟 mine-type 也没关系。比如用 php ,jsp 也可以输出 content-type 不是 text/html 内容,比如验证码图片。
watcher
2021-10-27 16:22:46 +08:00
微信加好友 单扣吧
hxy100
2021-10-27 16:39:04 +08:00
突然想起来一个老梗:
如何让一群程序员马上争论起来?
——“PHP 是世界上最好的语言”

-------------

万万没想到,有一天我也变成了这种人,终究还是没躲过。


散了,我克制一点。干正事要紧。
eason1874
2021-10-27 16:41:21 +08:00
@hxy100 #8 “除非你把.php 后缀的文件配置成 txt 形式( text/plain )加载,这样无论服务挂不挂都会暴露源码”

你发一个已经转发给 php-fpm 但因为媒体类型是 text/plain 所以暴露源码的配置来看看。
InternetExplorer
2021-10-27 16:57:36 +08:00
一个冷知识,PHP 代码不需要文件名作为标识,你可以放在任何文件中,PHP 程序只会解析 <?php 或者 <? 开头的部分,其他内容只会原样输出,所以跟什么后缀,mine-type 都是没有关系的。
网页地址的文件后缀是 .php 只是一种习惯而已。
ipwx
2021-10-27 17:06:27 +08:00
这。。。tm 杠精啊。
hxy100
2021-10-27 17:07:04 +08:00
@eason1874 又来一个在这杠,我再强调一次,MIME Type 的应用很广泛,客户端和服务端都有,不是你在浏览器看到的那个 Content-Type 才叫 MIME Type ,你在配置转发的时候,已经认定 PHP 这个类型的 MIME 包括的这一类文件需要后端解析了,居然都解析过了,自然看不到原始数据了。一群人狭隘地认为浏览器里面那个“Content-Type”才叫 MIME Type
miencun
2021-10-27 17:14:28 +08:00
@hxy100

你整一大堆专业名词,什么冗余啦、原始数据啦、Header 啦,现在又拿梗说事了,吹拉弹唱样样精通,你是唱戏的还是写代码的。

一看,哦原来是 Stack Overflow 爱好者,那我无话可说。

你赢了。
void1900
2021-10-27 17:15:30 +08:00
@eason1874

你杠啥杠,大佬说了,“配置正确”范围很宽泛,你懂不懂

------------


@InternetExplorer

你杠啥杠,大佬说了,MIME 的应用和含义很广泛,你都 <?php 了,就是 mime application/x-httpd-php
hxy100
2021-10-27 17:24:42 +08:00
@InternetExplorer 是的,你这个表述大部分是对的,但对于 MIME Type 的理解还是限制在了 Content-Type 上,这也不算冷知识了,大家都知道, 早期 PHP 源文件为了区分不同的版本,甚至还使用.php4 和.php5 这样的后缀名呢,这都不影响,MIME-Type 用来指代和归类一类文件,比如 .php4 .php5 .php 都可以统一归为一种 MIME Type ,至于叫什么名字无所谓,你甚至可以把它叫做 application/my-php-file, xxx/xxx 这样的名字也只是一种约定速成的形式。为了 HTTP 统一接口,统一调用而已。

PHP 本身跟 mime 没关系,但是服务器软件要解析和处理 PHP ,就少不了 MIME Type 的掺和了。

不管是什么 Web 服务器( Apache ,Nginx ,IIS 等)在以文件后缀名作为区别对请求进行分流的时候,Web 服务器内部就已经是通过不同的文件类型来分别做不同的处理了。多个不同的后缀名文件也可以设置归到一个 MIME Type 下,用一种方式统一处理(比如上面举的例子,多个不同的 php 文件的后缀名实质都是 PHP )。然后,已知的图片类型加图片类型的 Content-type ,文本类型加 text 这一类的头部,经过动态解析的页面,统一都使用 text/html ,接口调用的根据需要显示 json 头部或者 xml 的头部标识。

要注意一点,浏览器的 Content-Type 只是 MIME Type 的应用之一,而不是全部。MIME Type 的存在让 HTTP 类应用各种文件类型前后呼应,功不可没。C/S 架构,B/S 架构少了任何一端配合都不行。
hxy100
2021-10-27 17:34:07 +08:00
@InternetExplorer 再补充一点,如果你是在命令行直接调用 php 文件(比如 php hello.php, php hello2.123 <---后缀名不相关,可以任意),那这种情况就跟 MIME Type 没有关系,他就是直接读取源码然后解析<?php ?>包含的代码,只要你把 PHP 文件放到任意的 Web Server 里边,要通过 HTTP/HTTPS 访问,那 MIME Type 就是绕不过去的了,别管你看没看到 Content-Type ,看到的 Content-Type 是啥,Web 服务器在发送结果之前,都按自己内部定义的或者默认的 MIME Type 进行了分析和处理。
rekulas
2021-10-27 17:36:38 +08:00
@hxy100
恕我直言,这跟 mime type 确实没啥关系,举个例子,一个 mp3 文件,你改成 php 后缀,那么你认为它的 mime type 是啥呢,如果你觉得是 php 那显然违背了 mime type 的定义,如果你觉得是 mp3 ,那自然就是承认自己错了。mime type 本身就存储在文件头中,web 服务器决定某个文件交给哪个服务去处理的时候,根本不会去读取内容,怎么可能判断 mime type 呢,你如果敢用 mime type 来判断转发服务,那你可能是还没被社会教训惨
现在别说 web 服务,各大平台读取文件判断类型都从来不会考虑 mime type 了-毕竟这是一种可以随意篡改的不安全的数据
新手一般喜欢用 mime type ,但是错了就是错了,痛痛快快的别强钻牛角尖
liuxu
2021-10-27 21:11:14 +08:00
首先我忘了回复楼主。
1. 如果 php 文件和 index.html 同目录,但是 nginx 配置文件配置了请求 php 路径的 location ,不会暴露密码。
2. 如果 test.php 不渲染任何东西,但是 nginx 通过 fastcgi 访问 fpm ,fpm 运行 test.php 后实际上会返回 http 200 OK ,nginx 会把这个返回给浏览器,所以浏览器显示空白是正常情况,但是你如果观察 header ,是有对应的 header 头的。显示空白只是 http 的 content 是空的而已。
3. 如果满足 1 的配置要求,fpm 挂了,nginx 一般是抛出 502 错误页。
4. 只有没有按 1 的要求配置,才会返回 php 代码文件。



@void1900
@hxy100

我不是想打谁的脸,我回复的目的主要是为 25 楼这样的小兄弟解答,以及其他看到这个帖子的新人。
我看各位的注册年限都好几年,工作经验起码 3-5 年以上了,也正是因为这个原因,你们对技术比较专业的讨论,如果没有正确的回复,会非常误导人。

下面的回复不是针对谁,我就是给其他刚入行的小兄弟看的。

问:后缀是不是 MIME media type ?
答:不是。
原因:
1. 从理论角度来分析,MIME 是有 RFC 的,但是 RFC 中并没有任何有关后缀和 media type 的关系定义。
image/png 中,image 是 type ,png 是 subtype ,中间用 /分开,为一个 MIME media type 。而.png 没有任何定义。
https://en.wikipedia.org/wiki/MIME

2. MIME media type 的列表是 IANA 定制的,而且大部分也说明了 MIME media type 对应的文件后缀,下面以 text/html 为例,见“File extension”部分。
https://www.iana.org/assignments/media-types/text/html

那么从以上两点可以知道 MIME 是 MIME ,文件后缀是文件后缀。




说到这里我想扩展一下。

1. 一个软件(nginx, file)识别一个文件的 MIME 有 2 中方法。
a. 像 nginx 一样提供一个 mime.types 这样的有 mime 和文件后缀对应的列表。
b. 像 linux 命令 file 一样分析文件内容。

按 a 的话效率很高,毕竟分析文件内容会导致 nginx 消耗额外资源,而且只要配置列表齐全,就不会出现不识别问题。
而 file 是按 b ,所以 file 判断一个文件 test.php 文件的时候,把文件名改成 test ,也就是删掉.php ,也可以识别正确。原理是看文件是不是"<?php"开头。

$ cat test.php
<?php

t$ file --mime test.php
test.php: text/x-php; charset=us-ascii

$ mv test.php test

$ file --mime test
test: text/x-php; charset=us-ascii

但是这个是有缺陷的, 因为 php 可以 html 和 php 代码混合。
$ cat test
<!DOCTYPE html>
<html>
<body>
<?php
echo "I'm liuxu.\n";
?>
</html>

$ php test
<!DOCTYPE html>
<html>
<body>
I'm liuxu.
</html>

$ file --mime test
test: text/html; charset=us-ascii

可以看到明明是 php 文件,但是 file 却说文件是 text/html ,因为 file 读取文件开头是"<!DOCTYPE html>",所以判断这个文件是 html 文件。
同时也可以看见即使没有.php 后缀,文件也可以识别执行。原因是 php 读取文件就是单纯的 fopen()。


问:那么我用 php 执行一个单纯的 html 会怎样,甚至是一个 txt 会怎样。
答:会原样输出文件内容。
$ cat test.html
<!DOCTYPE html>
<html>
<body>
</html>

$ php test.html
<!DOCTYPE html>
<html>
<body>
</html>




2. nginx+php-fpm 的原理,我就以 nginx 官方配置说明为例。
server {
location / {
fastcgi_pass localhost:9000;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
fastcgi_param QUERY_STRING $query_string;
}

location ~ \.(gif|jpg|png)$ {
root /data/images;
}
}

首先这个配置没有匹配.php 后缀,而是匹配所有请求。如果请求时.gif .jpg .png 结尾,则会去 /data/images/加上请求路径拼接查找对应文件,也就是请求 /test/a.jpg ,会查找 /data/images/test/a.jpg 。然后如果找到了文件,会根据后缀.jpg 在 mime.types 查找到 mime 设置到 Content-Type ,然后返回。

但是如果不是上面的请求后缀,则转发到后端 php-fpm 。转发整个过程是:
a. 匹配请求路径,如 /test1.html ,/test2.php 。
b. 设置 fastcgi_param SCRIPT_FILENAME ,设置的值为 root 目录加请求路径,也就是 root 是 /data/project/,请求是 /test2.php 的话,SCRIPT_FILENAME 为 /data/project/test2.php 。然后把这个路径发送给 php-fpm 。php-fpm 使用 fopen()打开这个文件,由于是绝对路径,所以 php-fpm 不会读取到错误的工作目录。然后 php 执行 test.php ,得到输出返回给 nginx ,包含 header ,最后 nginx 做一些其他操作后将 php-fpm 的返回值返回给浏览器。

所以从 b 的的解析来看,即使你请求"/test3",也就是没有后缀,那么假如 /data/project/test3 问一个 php 内容的文件,php-fpm 一样会执行返回。




3. 然后我普及下十几年前 asp/php 当道的年代,一个人尽皆知的 webshell 攻击手法,也是和 mime 有关。
a. 首先网站有个上传图片功能,php 验证文件的方式是读取文件的 mime ,也就是看是不是 image/jpeg 或者 image/png 。
b. 攻击者上传 muma.php ,由于这个会上传时 Content-type 不是 image/jpeg ,所以使用工具劫持请求,然后更改上传文件的 Content-type 为 image/jpeg 后发送请求。然后 php 会验证通过,将文件存放到磁盘上。最后攻击者访问这个文件的链接就拿到了 webshell ,所以现在 php 验证一般是验证文件后缀。这也是说明 mime 和文件后缀虽然有联系,但是要区分对待。



4. 最后我想说一下 php 的 mime 问题,有点意思。从我查询有限的信息来看,php 是有 mime 的,但是还没有被 IANA 收录。
首先 IANA 定义的 MIME media type 叫官方 MIME ,然后还有一些 subtype 为 x-开头的,叫非官方定义,为的是以后官方定义避免名字冲突所以加上了 x-。
现在就有一个有趣的事情,我看前面有人说 apache 中 php 的 mime 要设置成 application/x-httpd-php ,实际上 linux 都有一个文件,叫 /etc/mime.types ,里面有 IANA 定义的 MIME 列表,但是 php 相关是注释掉的。
$ cat /etc/mime.types | grep php
#application/x-httpd-php phtml pht php
#application/x-httpd-php-source phps
#application/x-httpd-php3 php3
#application/x-httpd-php3-preprocessed php3p
#application/x-httpd-php4 php4
#application/x-httpd-php5 php5

然后用 file 看 php 文件的 mime 是 text/x-php 。

$ file -i test.php
test.php: text/x-php; charset=us-ascii

这个其实很有趣,原因是命名规范问题。

首先有官方定义 application/javascript 和 text/html ,原因是 js 是程序代码,html 是 html 文本。但是 php 很特殊,因为 php 可以是单纯的<?php 开头的 php 文件,也可以是 html+php 混合文件。如果是混合文件,那么开头就是<!DOCTYPE html>或者<html>,这样读取分析文件会是 text/html ,明显是错的。然后有人说 application/x-httpd-php 这个是有问题的,因为 php 和 html 一样是可读文本,所以 type 应该是 text ,mime 应该是 text/x-php 。所以 IANA 应该是考虑到这个问题,就把 php 相关的 mime 去掉的。但是 apahce 现在还在用,linux 命令 file 或者 php 自己的方法 mime_content_type()返回 php 文件的 mime 都是 text/x-php 。
liuxu
2021-10-27 21:21:46 +08:00
#97 s/不会暴露密码 /不会暴露代码 /
ji39
2021-10-27 21:42:00 +08:00
asp 站转 php 站,没删除的 asp 文件就暴露源码了,想当年专门搜索这样的
Hardrain
2021-10-27 21:47:35 +08:00
switch (SAPI) {
case 'fpm': 你大概会看到 502 或 503 错误 因为 HTTP 服务器无法连接到 fpm 提供的 fcgi 后端
case 'apache2': 根本不会有这种情况,因为此时 PHP 是 Apache 的模块,PHP 挂了就意味着 Apache 也挂了
case 'cli': 比如 roadrunner amphp 或 swoole ,大概也会看到 502 或 503 因为 HTTP 服务器无法连接到后端的 application server
case 'cgi': 这种还有人用吗?不过如果 CGI 程序不能运行,大概也会是 5xx 错误吧
}

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/809602

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX