V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
ysy950803
V2EX  ›  PHP

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

  •  
  •   ysy950803 · 38 天前 · 6240 次点击
    这是一个创建于 38 天前的主题,其中的信息可能已经有所发展或是发生改变。

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

    115 条回复    2021-10-28 19:40:12 +08:00
    1  2  
    xmlf
        1
    xmlf   38 天前 via Android
    你可以自己测试一下。
    AoEiuV020
        2
    AoEiuV020   38 天前
    一般是 502,nginx 返回的,
    ysy950803
        3
    ysy950803   38 天前
    @AoEiuV020 不是 Nginx 呢,是 Apache 。
    ysy950803
        4
    ysy950803   38 天前
    @xmlf 哈哈哈害怕关了不会起了,不太熟,对 PHP 服务。
    InDom
        5
    InDom   38 天前
    有可能会,但绝大多数配置正确的情况下并不会。

    以 Nginx 来举例,如果你把 .php 配置到了 php-fpm 后,如果 fpm 挂了,它会尝试连接 fpm 失败后直接报错。

    而不是把 php 文件作为文本来输出,如果你 .php 文件没有在 Nginx 内正确处理,就算 fpm 没挂也会作为文本输出。

    综上,在 Nginx 作为 WebServer 的情况下,是否可能输出 php 文件源代码和 fpm 挂没挂基本没有直接关系,只和 Nginx 本身的配置是否有关。
    ysy950803
        6
    ysy950803   38 天前
    @InDom 感谢解答。那这么说.php 文件放在网站目录还是有一定的安全风险。
    demoshengxw
        7
    demoshengxw   38 天前 via Android   ❤️ 1
    并不能,因为 php 部署只会开放入口文件。而且 nginx 会转发给 fpm,fpm 挂了那 nginx 收不到正确响应,就会吐给浏览器 5xx 错误
    hxy100
        8
    hxy100   38 天前
    并不会,了解下什么叫 MIME type,只要你 MIME type 配置正确(通常情况下以文件后缀名作为区分),无论服务怎么挂,是不会暴露源码的,除非你把.php 后缀的文件配置成 txt 形式( text/plain )加载,这样无论服务挂不挂都会暴露源码。
    eason1874
        9
    eason1874   38 天前
    php-fpm 挂了,nginx 就得不到 php-fpm 的响应,不会返回 php 文件内容,会报网关错误。

    另外,机密信息不要硬编码在代码文件里,设置到环境变量,让代码读取
    void1900
        10
    void1900   38 天前
    @hxy100 和 mime 没关系兄弟,你配成其他的 下下来一样打开就看见了,要转发给 fpm 才能避免
    Rache1
        11
    Rache1   37 天前
    Apache 跟 Nginx 不一样,Apache 是使用的 php_module,这里没有 fpm 。
    elevioux
        12
    elevioux   37 天前
    能查看与否和 php 本身无关,跟 web 服务器的设置有关。
    正常的情况下,设置正确的 web 服务器遇到 php 文件都会交由 php-fpm 来处理。如果 php-fpm 挂了的话,nginx 直接报网关错误 502 。
    不过,如果 web 服务本身就没有设置好,确实有可能把 php 直接打印出来,不过这种情况下,网站本身就不能正常打开。
    dosgo
        13
    dosgo   37 天前
    跟 web 服务器配置有关,当然现在可以在网站根目录留一个入口文件 index.php,剩下的可以不丢 web 目录
    hxy100
        14
    hxy100   37 天前
    @void1900 和 MIME 当然有关系,你说的这种情况就是没有给该拓展名的文件指定特定的 mime,默认的 mime 类型就是 application/octet-stream,这本质也是一种 MIME,所以 http 访问就当成附件让用户下载下来了。
    hxy100
        15
    hxy100   37 天前
    @void1900 另外,Apache,Nginx,php-fpm 解析文件时要么根据 MIME (后缀名也算),要么根据路径来判定。无论怎么绕,底层逻辑都离不开 MIME 。
    void1900
        16
    void1900   36 天前
    @hxy100 年轻人 那我问你 mime 怎么配置能防止被下下来?
    markgor
        17
    markgor   36 天前
    @void1900
    常规场景下他说的没错,
    apache 太久没碰不确认,但依稀记得是通过 AddType 添加 PHP 的 mime 进去的
    nginx 的话就是看配置.php 后缀然后转发 php-fpm

    当然也有场景是 php 直接监听端口,nginx 按目录请求转发到端口,这种就和 mime 没关系。


    回到 LZ 的问题,
    Nginx 通过 phpfpm 转发的话 fpm 挂了,那么会产生 5XX 错误,不会反回源码;
    一般反回源码的情况是 Nginx/Httpd 没配置好的时候(即没把解析 PHP 配置好),就会出现反回源码。
    void1900
        18
    void1900   35 天前
    @markgor 所以都是要转发给 fpm 或者其他服务,mime 其实只影响,响应的 header 里的 content-type ,不要混淆了
    markgor
        19
    markgor   34 天前
    @void1900
    换种说法可能更容易理解;
    nginx/httpd 如何知道这个文件需要转发给 phpfpm 还是直接读取返回呢?
    这时候一般就几种方式;
    1 、根据后缀来判断是否 php 文件;(其实就是#15 说的“解析文件时要么根据 MIME (后缀名也算)”
    2 、根据目录转发请求;这种就和你所说的,和 mime 毫无关联
    3 、全部请求转发,相当于 nginx 进行反代或均衡或缓存等;如 webman 框架,框架自身自带处理静态文件,上级的 nginx 做负载。
    hxy100
        20
    hxy100   34 天前
    @void1900 配置一个任意的已知解析逻辑处理程序即可(强调,这些操作都是 MIME Type 强相关,而不是不相关),php-fpm 算是其中一种,还有其他 cgi 模式的程序也可以作为后端处理,比如,你把 hello.php 写满 Python 代码交给 python.exe 去执行也是 OK 的,或者把图片的二进制代码放到 hello.php 里面,Apache 或 Nginx 设置 MIME 为图片类型输出处理也可以,不过这种情况服务器端要输出一个图片类型的 http Header 来告诉浏览器这是一张图片,浏览器端就能正确渲染。对于不认识或者不知道怎么处理的文件形式( MIME Type ),Apache 和 Nginx 的默认行为都是 Raw 形式直接输出,除非你做了限制和特殊配置。
    hxy100
        21
    hxy100   34 天前
    @void1900 你甚至还可以自己修改 Apache 或者 Nginx 的源码,做一个特殊的服务器 daemon ,对于未知的 MiME Type 的类型,服务端不做任何处理,对于已知的类型,才做相对应的解析。如果你还是不能理解,你去温习一下看看 Windows 下 IIS 配置 PHP 解析又是怎么做的,逻辑上是不是根据 MIME Type 来的,看看 GUI 界面上的那几个大字跟 MIME Type 有没有什么关系。
    hxy100
        22
    hxy100   34 天前   ❤️ 1
    @void1900 一句话总结,MIME type 中文名叫,“文件类型,文件扩展”;并不是只有浏览器上你看到的 Content-type 才叫 MIME type ,服务端也有 MIME type 的概念,如果你不知道这个,或者不知道服务器的 Nginx/Apache 软件配置跟 MIME type 有关系,那你该补补课了,基础不扎实。
    void1900
        23
    void1900   34 天前
    @hxy100 你这么硬掰真的就有点搞笑

    搞来搞去都是要转发给其他服务处理,mime 真的没你说的那么高级,还看看 iis....

    都是靠规则匹配文件 转发给其他服务

    -----------
    MIME
    ```媒体类型(通常称为 Multipurpose Internet Mail Extensions 或 MIME 类型 )是一种标准,用来表示文档、文件或字节流的性质和格式。它在 IETF RFC 6838 中进行了定义和标准化。```

    https://datatracker.ietf.org/doc/html/rfc2045
    https://www.iana.org/assignments/media-types/media-types.xhtml

    看看,就只是用来表示文件类型的。甚至可以和扩展名都不相关。

    其实主要是给浏览器用的。

    说白了他是 HTTP 协议的一部分,和你解析服务器文件没多少关系。
    void1900
        24
    void1900   34 天前
    不再回复了,被拉到同一水平线击败也挺可耻的 :doge:
    jindeq
        25
    jindeq   34 天前
    有没有朋友鉴定一下楼上两位水平孰优孰劣?

    我这个吃瓜群众就想看到别人吵架的结果。
    hxy100
        26
    hxy100   34 天前
    @void1900 我就问你,你平时是怎么配的 PHP ,不管是 Apache ,Nginx 还是其他的 Web 服务器,通常做法是不是把所有.php 的后缀的文件交给某个后端( etc:Nginx & php-fpm )或者某个模块处理( etc:Apache Load PHP Module ),这个过程,本身就是区别对待不同文件 MIME Type 的过程(绝大多数情况下后缀名识别是约定速成的形式,你也可以配置成不使用常规的后缀名)。回到题主本身的问题来,题主问 PHP 应用如果后端服务服务挂了,源码会不会暴露出来,我回答正确配置 MIME Type 就行,不会出现题主担心的问题。这个回答并没有毛病,你配置后端解析的时候,就是把这个 MiME Type 的文件指定一个程序去解析,张三是一个 MIME Type ,你指定张三去 3 号窗口领盒饭,它找不到 3 号窗口就会僵在那,不会发生意外之外的情况跑去 4,5 号窗口,你叫李四挂个牌子叫他张三也可以,也是一样的道理,挂牌子的过程,本身就是指定 MIME Type ,你指定的 MIME Type 解析过程如果配置有误,或者没指定,那么不管后端 php-fpm 挂不挂,题主都会发现问题。然后就会去找原因解决问题,然后就不会有如此疑问了。题主之所以有此问题,原因在于不理解服务器端是怎么识别不同类型的文件的处理逻辑,所以,回答这个问题,MIME Type 是核心,你所说的配置 php-fpm 后端解析巴拉巴拉都对,但也都是围绕 MIME Type 来的, 这个问题归根结底,在于理解 MIME Type 对于 Web 服务器的作用。苦口婆心说了这么多,希望你能听进去。
    hxy100
        27
    hxy100   34 天前
    @void1900 另外你说的浏览器标头里面的 Content-Type ,也是 Web 服务器告诉浏览器的,不是浏览器自己去探测的,那么 Web 服务器是怎么判断什么时候该输出 jpg 图片标头,什么时候该输出 png 标头,什么时候又该输出 html ,js 标头的呢,你考虑过这个问题没有?还有 Apache 配置文件 httpd.conf 里边一堆 AddType AddHandler 是干嘛使的呢,是不是作者脑袋抽抽了胡乱加的,“说白了他是 HTTP 协议的一部分,和你解析服务器文件没多少关系。”这是你的原话,你再好好推敲一下。
    https://imgur.com/LIdAUhd
    void1900
        28
    void1900   34 天前
    @hxy100

    等你理解什么是 MIME 再来和我说吧小老弟。

    你把.php 配置成任何类型都没有用,最终还是要去配转发,通常用规则(扩展名)。

    Apache 也只是借用 mime 类型转发罢了,最终还是要转发才能避免,懂了吗?

    就如你说的,php 如果配置了 mime types ,为什么访问的适合不是直接输出 php 的类型,而是 php 自由可以输出图片?因为转发给 cgi 或者其他服务之后,这个 mime 配置就无效了。

    混淆了就混淆了,不懂也别装懂。

    还说 `只要你 MIME type 配置正确(通常情况下以文件后缀名作为区分),无论服务怎么挂,是不会暴露源码的`,是想坑人?

    你单单 MIME 配置一个 .php -> text/x-php 还是 配置个 .php -> text/plain ,还是配个 php -> application/x-httpd-php ? 再或者配个 php -> newbie/flower ?能起什么作用,浏览器打开是显示文本还是下载文件的区别罢了?

    重点是要配置转发

    别在这误人子弟了,真的。
    void1900
        29
    void1900   34 天前
    @jindeq 哈哈哈 还不明显吗?
    void1900
        30
    void1900   34 天前
    @hxy100
    还说什么 `你配置后端解析的时候,就是把这个 MiME Type 的文件指定一个程序去解析` 我问你 .txt 、.jpg 、.css 、.js 给那个程序解析?……

    好好再去理解理解吧,没事别把底层挂嘴上,真的懂得越多你才越知道自己肤浅,你的底层再别人眼里可能只是个笑话
    hxy100
        31
    hxy100   34 天前
    @void1900 你不要避重就轻,管你转发不转发,Web 服务器就是靠 MIME Type 来识别要后端解析 Code 还是输出文件的 RAW 数据。比如人类普遍凭 X 器官区分性别一样,这是不争的事实,就题主的问题而言,靠 MIME Type 识别这个究竟是 PHP 文件需要解析,还是你这位 V 站 void1900 大神直接输出,题主问题在于就是不懂这个东西,所以才来提的问题。我只是一针见血指出题主的疑惑所在,至于你扯的这些东西,浮于表面,扯了一堆有的没的,还是没说到问题根本,如果你一口咬定所谓的转发跟 MIME Type 没关系。MIME Type 跟 Web Server 没关系,建议去 Google 和 Stackoverflow 搜索相关权威内容。
    我随便贴几个链接:
    https://stackoverflow.com/questions/20668886/nginx-and-fastcgi-downloads-php-files-instead-of-processing-them
    https://serverfault.com/questions/315224/why-are-the-php-files-downloaded-instead-of-processed-by-nginx
    https://stackoverflow.com/questions/20093069/set-mime-type-after-php-interpreting
    希望你不要对既定事实视而不见,不服的话请去怼老外。

    这是我最后一次回复,跟掩耳盗铃的人较真真的很累。
    void1900
        32
    void1900   33 天前 via iPhone   ❤️ 1
    @hxy100 哈哈哈哈 算了算了,年轻人 你就继续怎么呆下去吧。

    mime 就只是一个文件类型标识,不是你所谓的后端解析

    我说的是和 php 文件的处理没有关系,不是和 web server 没有关系,年轻人语文也不行,唉。

    还管你转不转发,还权威内容,nginx php 需要配置 mime types ?不配 mime types 一样能处理。

    但是你不配 fastcgi_pass 试试?

    apache 配置 php 方法有几种,说直白点就是 apache 把你误导了,懂了吧,你自己再学习学习吧。

    apache 你单单配置 addtype 有用?


    还 一针见血 哈哈哈哈哈哈哈哈哈

    你这个一针见血怕是扎针到别人飚血了

    你找多几个人问问吧 真的
    ysc3839
        33
    ysc3839   33 天前 via Android
    @hxy100
    > Web 服务器就是靠 MIME Type 来识别要后端解析 Code 还是输出文件的 RAW 数据

    这句话可以很轻易地证伪。使用 Unix shell 配合 FIFO 和 netcat 可以实现一个很简单的 Web 服务器,比如这个例子 https://www.linuxquestions.org/questions/linux-newbie-8/how-to-write-a-http-server-using-bash-script-644921/#post3180848
    其中就不涉及到 MIME type ,而是直接根据文件名后缀选择处理流程。

    你可以说某个 Web 服务器的内部处理逻辑用到了 MIME type ,但绝对不是所有 Web 服务器的处理逻辑都涉及 MIME type 。
    void1900
        34
    void1900   33 天前
    @hxy100 看看吧,来了个明白人了
    hxy100
        35
    hxy100   33 天前
    @ysc3839 你没完整看完我的回答,另外你也不懂,后缀名也是识别 MIME Type 的方式之一,谁说后缀名跟 MIME Type 没关系的,计算机判断一个文件是什么文件,通常有两种方式,其一是通过后缀名粗暴判断(绝大多数的情况),其二是根据一些常见的已知的文件类型的二进制数据流头几个字节来判断(专业术语叫:File Magic Number )。
    hxy100
        36
    hxy100   33 天前
    @void1900

    “mime 就只是一个文件类型标识,不是你所谓的后端解析”
    ——是你语文不行,我的意思就是,MIME Type 用以 Web Server 识别同一类文件,Web 服务就是把这写不同 Type 的文件区分来用不种方式处理的,该输出还是该后端解析,后缀名属于确认 MIME Type 的一种极其常见方式。

    “我说的是和 php 文件的处理没有关系,不是和 web server 没有关系,年轻人语文也不行,唉。”
    ——题主的疑问爆不爆源码跟 php 本身没关系,跟 WebServer 配置有关系。

    “还管你转不转发,还权威内容,nginx php 需要配置 mime types ?不配 mime types 一样能处理。”
    ——Nginx 本身内置了 mime type ,但是默认定义的都是用于处理静态文件,但你配置 proxy_pass 是通常要指定的 location ~ *.php {...},你只要用了后缀名做区分,本质上也是用了 MIME Type ,别以为后缀名就不是 MIME Type 了

    “apache 配置 php 方法有几种,说直白点就是 apache 把你误导了,懂了吧,你自己再学习学习吧。”
    ——不管几种,而且不管哪一种,内部逻辑都需要 MIME Type 把不同的文件区分归类,然后做不同的处理

    “apache 你单单配置 addtype 有用?”
    ——这是你说的,我没说
    void1900
        37
    void1900   33 天前
    @hxy100

    哈哈哈 好一个用到 扩展名就是 mime 哈哈哈哈哈哈哈哈

    谁能叫醒他 ,

    我 nginx 可以不加 mime types 一样解析 php ,apache 可以不加 AddType 一样解析 php ,这是 mime ?哈哈哈

    我 mime 配置 .php -> newbie/flower 一样可以解析 哈哈哈

    mime 是 http 协议的一部分,扩展名是啥,mime 的第三个 M 是啥? Mail !还在这硬扯 webserver 。

    还内部逻辑 ...
    hxy100
        38
    hxy100   33 天前
    @void1900 我当然知道 MIME Type 的全程是啥,你可以不叫它 MIME Type ,你可以不用这个名称,直接就叫“文件类型”即可,但是和 MIME Type 就是一个意思,服务器端都要靠文件类型来区别对待不同的文件。如果你非要狭义认为只有静态资源才配有 MIME Type ,或者 MIME Type 一定要用在浏览器上才叫 MIME Type ,那好,你赢了,我认输。可能你真的认定叫一个人的名字是专人专用,小名和大名也不能混,二狗和王二狗不是同一个人吧。你赢了,你是对的,我不用 MIME Type 这个名字了,让给你,暂且叫它 V2EX Type 吧!
    void1900
        39
    void1900   33 天前   ❤️ 1
    @hxy100

    混淆了就混淆了,不丢脸,世界还很大,这和叫啥没有关系

    mime 配置就单单是 扩展名 对应 mime types ,不能说配了 mime 就可以了,重点是要转发给其他服务处理。

    别犟,也别杠
    ysc3839
        40
    ysc3839   33 天前   ❤️ 1
    @hxy100 我看了。你一边强行把 MIME Type 和文件后缀名绑定成一个概念,另一边又毫无依据地强调“Web 服务器就是靠 MIME Type 来识别”。

    按照我的理解,MIME Type 和文件后缀名以及文件内容没有强关联。HTTP 使用 MIME Type 也正是因为文件后缀名和文件内容没有必然联系,所以引入了 MIME Type 来让服务器告诉浏览器,应该把数据当作什么文件类型来处理,不然按照后缀名去推测的话,PHP 这种脚本语言该对应什么类型?没有后缀的文件名该怎么处理?
    本来 MIME Type 的概念就只是在几个互联网协议中使用的,根本没有被各种软件、系统广泛使用,硬要把 MIME Type 和文件后缀名绑定在一起是站不住脚的。

    对于你说的“看看 Windows 下 IIS 配置 PHP 解析又是怎么做的”,请你去看看微软官方的文档 https://docs.microsoft.com/en-us/iis/application-frameworks/scenario-build-a-php-website-on-iis/configuring-step-1-install-iis-and-php 里面是怎么写的:
    11. In Request path, type *.php.
    再看看 PHP 官方的文档 https://www.php.net/manual/en/install.windows.manual.php:
    [name='PHP_via_FastCGI',path='*.php',verb='*',modules='FastCgiModule',scriptProcessor='%phppath%\php-cgi.exe',resourceType='Unspecified']
    fkdtz
        41
    fkdtz   33 天前   ❤️ 4
    楼主你惹祸了
    hxy100
        42
    hxy100   33 天前
    @ysc3839 你的这个说法我认同,而且我知道你这个回答是看了我帖子的其他回复给出的答案,我确实是做了强关联,我接受,这是我的狭隘之处,我也知道,后缀名!=文件类型!=MIME type (我上面的其中一个回复里面举例时也提到了这一点),但绝大多数时候,我们如果没有特殊需求,往往就是采用开宗明义的做法,以后缀名区分文件类型,然后再以不同的文件类型作为标识输出给浏览器 [MIME Type] ,这种情况下,后缀名间接对应 MIME Type ,PHP 同样也有,大概总结就是 Web 服务把不同后缀的文件类型区分,该读取的读取,该由第三方解析的解析,然后统一回复客户端,不仅仅是静态资源文件有,有的 Web Server 会明示某种动态脚本后缀的文件为某个 MIME Type (比如 Apache 定义 PHP 为 application/x-httpd-php ),有的 Web Server 不明示,但不代表内部的这种 Type 区分不存在。我上面要强调的是仅仅是不同文件类型的区分,在任何一个流行的 Web Server ( Nginx ,Apache ,IIS ,LightHttpd 等等)都是存在的,不管你看不看得见。配置 PHP 时正确配置这个 Type ,不管后端接盘的 php-fpm 还是其他的何方神圣,都不会暴露源码。

    -----

    综上,我认为我的表述过于狭隘,或者说不应该把服务端的这种区别文件类型的做法叫 MIME Type ,MIME Type 严格的描述应该是 xxx/xxxxx 这样的形式,至于其余的逻辑没问题,我理解 Web Server 是怎么处理各种文件的。你的这条回答很中肯。我也虚心接受,不像 @void1900 一顿乱杠,自己的逻辑里面很多东西都是错的。
    void1900
        43
    void1900   33 天前
    @hxy100 还在杠

    不管我文件名是不是.php ,mime type 配不配 application/x-httpd-php

    我都能让他走 php cgi 解析,这种情况配对了吗?

    我起名叫 .nb , mime types 配置 text/nb ,

    我只要配置了 nginx 的 proxy_pass 或者 apache 的 SetHandler ,就能解析,这种怎么解释,你还能扯扩展名和 mime type 吗?

    还我一顿乱杠,666
    hxy100
        44
    hxy100   33 天前
    @void1900 我不回复你了,只有楼上这位仁兄 @ysc3839 认真看了我的答案,你的话就只顾自说自话,我不知道你是从来不看别人这么说,还是我答得太长了,你有点晕看不懂,你不会正视自己的问题,就只想证明别人是错的,你再从头把我的每一个回复看一遍,我什么时候说过只要 inlcude mime.types 和 AddType 就行了,就能正确解析了,这完全是你自己说的,我说的是所有 PHP 文件默认是一个 Type ,你给找个 Type 指定合适的规则,就完全不用担心爆不爆源码的文件。爆不爆源码与后端服务的死活无关,只与 Web 服务器本身有关,Web 服务器就是靠这个 Type 来区分文件的,这个 Type 可以是.php ,也可以是.abc ,web 服务器认得就是这个 Type ,你可以把 .php .123 .abc 这三个后缀的文件合并成一组交给后端解析,组名也就是这个 Type ,我之前叫这个叫 MIME Type 可能有误,直接就叫文件类型标识好了。
    void1900
        45
    void1900   33 天前 via iPhone
    @hxy100 我都和你说了,和 mime type 也好 扩展名也好都没有关系,还在这硬扯 type 。

    你的第一个回答就是 “只要你 MIME type 配置正确”
    void1900
        46
    void1900   33 天前
    @hxy100

    还说 "除非你把.php 后缀的文件配置成 txt 形式( text/plain )加载,这样无论服务挂不挂都会暴露源码。"

    我就算这样设置,吧文件转发给 cgi 一样不暴露。能理解吗?

    还在硬扛
    hxy100
        47
    hxy100   33 天前
    @void1900 我说的有什么问题,我说的“配置正确”范围很宽泛,不管你配置转发到后端也好,或者配置权限控制也好(密码访问,IP 限制等),哪怕是 Nginx 你这么写 location ~ *.php {deny alll;},我都都算配置正确。我说的“配置正确”意思就是叫你对这类文件的预期行为进行设置,如果你设置有误,设置成纯文本模式读取的形式( text/plain,text/css 等),或者没设置设置成未知的类型,那 MIME Type 默认就是 application/octet-stream ,这样 http 访问就会被当成一个附件下载下来了,不管 HTTP header 输不输出这个 Content-type 头,只要 Web 服务器认为这个文件不需要被处理,需要输出原始流,都会导致源码暴露。你才是硬杠,我提这个的东西最初衷的目的就是让题主去了解服务器分文件类型解析和输出结果的过程,然后题主就不会有这样的疑问了,因为 php 这个文件类型已经被约定行为了。你可以说 PHP 文件在 Web 服务器内部不能叫 MIME Type ,我叫错了,但你无法证明我的思路和阐述是错误的,就这样子。
    void1900
        48
    void1900   33 天前
    @hxy100 对你说的都对
    hxy100
        49
    hxy100   33 天前
    @void1900 很好,结贴
    liuxu
        50
    liuxu   33 天前   ❤️ 1
    @jindeq
    @void1900
    @hxy100

    直接用 nginx 源码讲话。


    首先说明 nginx 的默认配置 mime.types ,内容如:
    types {
    text/html html htm shtml;
    text/css css;
    text/xml xml;
    ...

    存储在 nginx 内存中方存放的方式为:
    [
    'html' => 'text/html',
    'htm' => 'text/html',
    'shtml' => 'text/html',
    'css' => 'text/css',
    'xml' => 'text/xml',
    ...
    ]
    也就是['ext' => 'mime']这种格式,从这里就很清楚了,mime 和文件后缀可以互相替代,但是 mime 不是文件后缀,你完全可以在这个文件里添加一条
    text/html v2ex;

    此后后缀为".v2ex"的文件 nginx 返回时 response 的 Content-type 就会设置成 text/html

    [email protected]:/etc/nginx$ cat mime.types | grep v2ex
    text/html v2ex;

    [email protected]:/etc/nginx$ ls -l /var/www/html/
    total 12
    -rw-r--r-- 1 root root 612 10 月 26 21:47 index.nginx-debian.html
    -rw-r--r-- 1 root root 11 10 月 26 23:34 test.v2ex

    [email protected]:/etc/nginx$ file /var/www/html/index.nginx-debian.html
    /var/www/html/index.nginx-debian.html: HTML document, ASCII text

    [email protected]:/etc/nginx$ file /var/www/html/test.v2ex
    /var/www/html/test.v2ex: ASCII text

    [email protected]:/etc/nginx$ cat /var/www/html/test.v2ex
    I'm liuxu.

    [email protected]:/etc/nginx$ curl -v http://127.0.0.1/test.v2ex
    * Trying 127.0.0.1:80...
    * TCP_NODELAY set
    * Connected to 127.0.0.1 (127.0.0.1) port 80 (#0)
    > GET /test.v2ex HTTP/1.1
    > Host: 127.0.0.1
    > User-Agent: curl/7.68.0
    > Accept: */*
    >
    * Mark bundle as not supporting multiuse
    < HTTP/1.1 200 OK
    < Server: nginx/1.18.0 (Ubuntu)
    < Date: Tue, 26 Oct 2021 15:35:53 GMT
    < Content-Type: text/html
    < Content-Length: 11
    < Last-Modified: Tue, 26 Oct 2021 15:34:36 GMT
    < Connection: keep-alive
    < ETag: "6178200c-b"
    < Accept-Ranges: bytes
    <
    I'm liuxu.
    * Connection #0 to host 127.0.0.1 left intact



    在有了以上说明后,下面从 nginx 源码说话:

    1. nginx 不设置 default_type 时,response 的 Content-Type 默认是 text/plain ,而不是 application/octet-stream 。也就是说单独一个 nginx 运行,root 目录为 /var/www/html/时,把 test.php 放入 /var/www/html/下,会直接打印代码。

    https://github.com/nginx/nginx/blob/41a241b3ef74dbbe3d82ab2ebbe682919e4a0b90/src/http/ngx_http_core_module.c#L3693

    2. nginx 设置了 default_type 为 application/octet-stream ,按 1 的配置,浏览器访问 1.php ,Content-Type 因为是 application/octet-stream 所以会下载该文件。当然也不止 application/octet-stream ,还有如果有 Content-Disposition 的话也会调用下载任务。
    https://en.wikipedia.org/wiki/MIME

    3. nginx 引入了自己的默认配置文件 mime.types 后,ngx_http_set_content_type()首先走到 1606 行判断有没有文件后缀,如果有后缀,则会走到 1633 ,从后缀中搜索 type ,也就是前面说的在 nginx 内存结构中的 mime.types:
    type = ngx_hash_find(&clcf->types_hash, hash,
    r->exten.data, r->exten.len)
    if (type) {
    r->headers_out.content_type_len = type->len;
    r->headers_out.content_type = *type;

    return NGX_OK;
    }
    但是由于 mime.types 中没有 php 相关的配置,也就是不存在一个"type/xxx php"这样的配置,所以如果没有设置 location ~ \.php${...}这类配置,php 文件就会被下载。

    以下是返回 response 的代码:
    https://github.com/nginx/nginx/blob/41a241b3ef74dbbe3d82ab2ebbe682919e4a0b90/src/http/ngx_http_core_module.c#L1593



    所以 nginx 并没有通过 mime 来区分返回 response ,而是通过文件后缀查询到了对应的 mime ,然后设置了到 Content-type 然后返回。

    最后说一下 location ~ \.php${...}中,.php 是不是后缀匹配。从人为理解来说是匹配.php 后缀文件,但是从 nginx 的角度来看,它就是一个正则字符串,并没有在内部 mime 列表中查出一个['php'=>'type/php']这种东西。
    void1900
        51
    void1900   33 天前 via iPhone
    @liuxu 你就别刺激他了
    lap510200
        52
    lap510200   32 天前
    nginx 本身无法执行 php, 如果没有配置 php 解析或模块,php 文件又可读,是会返回源码的。如果配置了解析,nginx 碰到 php 文件会去找 fpm, 此时 fpm 挂了 ,nginx 返回是 5xx 错误。 同理对于代理转发的也是,代理的端口服务挂了也是 5xx
    hxy100
        53
    hxy100   32 天前
    @liuxu 你的这个回答恰恰说明了 php 会不会暴露源码跟 MIME Type 高度相关,而不是不相关,打了不少人的脸,@void1900 首当其冲,脸都被打肿了。先不讨论你回答的正确性(因为我懒得验证),根据你的回答,我阐述有问题的地方仅有两个:
    一. 不是所有的 Web 服务器默认 MIME Type 都是 application/octet-stream ;
    二。不能把 Nginx 通过 location 配置 PHP 解析的方式统一叫成后缀名或 MIME Type 识别,它可能仅仅就是一个 URL 路径的正则匹配。

    ----
    当然,现在的我仍然坚持后缀名≈MIME Type 的观点,我不是说他们概念和定义相等,是说他们对 Web 服务器的影响差不多,前后端搭配,不仅是浏览器需要 Content-Type ,Web 服务器本身也需要区分哪些文件需要处理,哪些文件是直接输出。

    你说的“但是从 nginx 的角度来看,它就是一个正则字符串,并没有在内部 mime 列表中查出一个['php'=>'type/php']这种东西。”这个问题我上面的回复说过了,不需要输出给浏览器特殊标头( Content-Type )的文件,并不需要显式定义,因为不管是 php ,还是 jsp 他们最终呈现给浏览器都是 text/html 而已,但不意味着在 Web 服务器内部没有一个标识来把这些 php 文件统一归类,有可能这个东西不能叫 MIME Type (你可以叫 proxy file group1 ,proxy file group2 或其他),但绝对存在这样一个标识,Nginx 这样的代理服务器也不例外。

    综上,结论就是 PHP 爆不爆源码还真的跟 MIME Type 有关系。别吵了。
    hxy100
        54
    hxy100   32 天前
    @liuxu 另外说一下,关于第二个问题,Nginx 使用 location 配置 php 时,实际上已经在正则表达式里边传递 php 的后缀名了,所以说成是后缀名匹配也无大的错误。
    void1900
        55
    void1900   32 天前
    @hxy100

    都懒得理你了,你还说打我脸,怎么看都是打你脸,还高度相关,哥么别出来秀了,丢脸了
    hxy100
        56
    hxy100   32 天前
    @void1900 你就继续掩耳盗铃吧。你再好好读读楼上那位兄弟的回答,假如你能理解的话。要是读不懂,那我就送你三个字:“你赢了!”,散会
    hxy100
        57
    hxy100   32 天前
    @void1900 还有指明一点,别人的回答你都不仔细看,甚至没弄明白别人说的是什么就率先站出来反对,你看看我在这个帖子下的所有的回复,哪一个兄弟的回复的答案我没看?并且是有人给出自己观点,我都会对照自己的表述一一回应,错了就错了,概念错误,还是逻辑错误,又或者是意思没表达清楚,我都大方承认,就你光在这自说自话,压根不管别人说的是啥,这是一个学习者该有的态度吗?
    -----
    顺便说一句,V2 发帖的好处是无法删帖无法修改,究竟打了谁的脸,就留给观众老爷们评判吧,让时间说话。
    void1900
        58
    void1900   32 天前
    @hxy100

    哈哈哈哈哈 楼上多少位都和你说了 和 mime 没关系,就算你扯上扩展名也没用。

    和扩展名也没有关系,真的懒得和你说了,井底之蛙应该就是说你这种人了。

    还我不理解,你语文真的也不行,哥么,你找个人帮你读读。

    人家结尾都说了 “并没有在内部 mime 列表中查出一个['php'=>'type/php']这种东西。”。

    写正则用的是扩展名,那假如我将整个目录都 proxy_pass 给 fpm 呢?你还怎么扯你的扩展名?

    还整天一个劲的总结,“就这样”,“别吵了”,看得出你很想赢。

    可是技术逻辑就是那么严谨,你怎么掰扯都没有用啊,说越多越显得你可笑
    void1900
        59
    void1900   32 天前
    @liuxu 你写太长了,你就和 @hxy100 说结论吧,他语文不太好。
    miencun
        60
    miencun   32 天前
    Apache 模块:只能 AddType application/x-httpd-php .php ,结论:有关
    CGI 模式:所谓的 Mime 可以任意起名,结论:无关
    反代:不需要 Mime
    void1900
        61
    void1900   32 天前
    @hxy100
    你的回答我真的看了,帮你总结下.

    1. 就是不完全懂什么是 MIME
    2. 然后和扩展名分不清楚
    3. 被 apache 误导
    4. 还有就是语文也不好。
    5. 还有可能是忘了自己一开始的回答,通篇强调 MIME ,然后还说一个“配置正确”很多含义,服气,给你点个赞。

    “并不会,了解下什么叫 MIME type ,只要你 MIME type 配置正确(通常情况下以文件后缀名作为区分),无论服务怎么挂,是不会暴露源码的,除非你把.php 后缀的文件配置成 txt 形式( text/plain )加载,这样无论服务挂不挂都会暴露源码。”
    void1900
        62
    void1900   32 天前
    @miencun apache 可以 SetHandle proxy: 一样转发给 cgi ,一样可以不配 mime
    miencun
        63
    miencun   32 天前
    @void1900 这不就是反代吗?
    void1900
        64
    void1900   32 天前
    @miencun 也是,apache module 确实算是强相关
    hxy100
        65
    hxy100   32 天前
    你是不是傻,来,我来一一回复你:

    “人家结尾都说了 “并没有在内部 mime 列表中查出一个['php'=>'type/php']这种东西。”。”

    ——请把我这个帖子的回复连贯起来看,我上面的回复里面说了,并不是要明示“'php'=>'type/php'”这样的东西才叫 php 有 MIME Type ,没定义不代表就没有,MIME Type 是 HTTP 类应用在区分不同文件类型的时候引入的概念,但不是说这类东西只能跟浏览器挂钩,Web 服务也是需要的,比如 Apache 里面是定义了 PHP 的 MIME Type 类型是 application/x-httpd-php ,你可以不加这个名字,叫 application/x-abc 也行,总之是为了区分不同类型的文件; Nginx 默认只定义了所有常见的静态资源类型的 MIME Type ,没去定义任何的动态类语言的 MIME Type ( php ,jsp 等等),是因为 Nginx 常用做前端负载均衡代理服务使用,你要给他一个 PHP 的 MIME 定义,他也没错,Nginx 对不同的文件类型,也同样有自己 MIME Type 概念,其实严格一点说,所有具有后缀名的文件都有 MIME Type ,只要我们需要了,我们就可以给这一类文件定义一个 MIME Type ,Web Server 靠这个东西区分不同的文件类型该做什么样处理。你的问题在于陷入了一个误区,认为只有浏览器的 Content-Type 跟 MIME Type 有关系,其他的地方都没关系。

    ---

    “写正则用的是扩展名,那假如我将整个目录都 proxy_pass 给 fpm 呢?你还怎么扯你的扩展名?”

    ——你当然可以这样设置,但你这是正常和常规的做法吗?万一你这个路径下边有子目录呢,子目录里面有图片,js
    ,css 文件呢,你是不是要不管三七二十一统统交给后端去解析,还是说你把所有的子目录一个个分开来设置,不管嵌套几层,统统分开设置,反正就是打死不用后缀名来匹配。顺便建议你,平时在服务器上配置 Nginx 和 PHP 也采用你说的做法,打死不要用 php 后缀名来做正则匹配哦,我会为你鼓掌,你要偷偷用了你就是小狗。
    hxy100
        66
    hxy100   32 天前
    忘记艾特你了,请看上一楼,专门回复你的。 @void1900
    void1900
        67
    void1900   32 天前
    @hxy100 等你搞懂了再来吧哥么
    hxy100
        68
    hxy100   32 天前
    @miencun CGI 你也得用相应的规则配置去匹配.php 这一类后缀的文件,这还叫没关系。虽然 MIME Type 不全等于文件拓展名(这一点我上面的回复说了,就算我强行关联吧),但 MIME Type 就是为了让 HTTP 服务 C/S 两端前后呼应,用来区分不同文件类型的,想想你用 Niginx 配置代理 PHP 时候怎么写的 location 来匹配呢,用了 php 的拓展名没有?
    hxy100
        69
    hxy100   32 天前
    @void1900 语文不好的是你,理解能力差,所以一开始才看不懂别人的回复里面已经约定了很多东西,你视而不见,需要一遍又一遍跟你解释,我说了不急,只要 V2 这站还活着,让时间给你答案。
    miencun
        70
    miencun   32 天前
    @hxy100
    1. 不利用任何 Mime 判断,现在都反代,Mime 唯一的用途只是让服务器输出 Content-Type ,以供浏览器参考如何加载文件。
    2. 扩展名和 Mime 毛关系都没有,你以为 php 叫 application/x-httpd-php ,谁定义的?浏览器为什么会暴源码,因为浏览器不认识 application/x-httpd-php !
    void1900
        71
    void1900   32 天前
    @hxy100
    你强关联就已经错了

    其次即使是 apache ,重点也不是 MIME 配置,重点也是 SetHandler ,也并不是 “MIME 配置”,只是 SetHandler 用到了 php 的 MIME type ,懂了吗?

    重点根本不是 “MIME type 配置”,MIME 配置是 AddType ,搞不懂就先去搞懂他,我累了,这届新人真难带
    void1900
        72
    void1900   32 天前
    @miencun 他根本就不懂这个东西,和他掰扯真的很累
    void1900
        73
    void1900   32 天前
    @hxy100

    另外跟你说吧,“application/x-httpd-php” 是 PHP 定义的,不是 apache 定义的
    hxy100
        74
    hxy100   32 天前
    @void1900 对牛弹琴,说了那么多白说了。如果你要好好说话,你可以说 MIME Type 不能和拓展名相关联,只能做描述文件类型用,那这个问题本身就有争议,我可以考虑接受。尽管这个问题有争议,回复了那么多,你也应该知道我要说的 MIME Type 就是 Web Server 根据不同拓展名来处理不同类型文件的意思。而不是杠子眼,为什么我说有争议,是因为这个问题你在 Google 和 Stackoverflow 上都有两个版本,普遍认为 Apache ,IIS 这样的关联比较强(直接写在配置文件里或者配置界面上),Nginx 等代理性质的服务器关联比较弱,但不是代表没关系。

    第二个,关于你说的 SetHandle ,那你觉得 Apache 是凭什么东西找到它要 Handle 的对象的呢?
    void1900
        75
    void1900   32 天前
    @hxy100 大神你说的都对,加油!
    hxy100
        76
    hxy100   32 天前
    @miencun 又来一个搞笑的。你的两个观点都大错特错。你甚至还不如他 @void1900
    引用你的话:
    “扩展名和 Mime 毛关系都没有,你以为 php 叫 application/x-httpd-php ,谁定义的?浏览器为什么会暴源码,因为浏览器不认识 application/x-httpd-php ”
    ----
    解答:
    1 、扩展名和 Mime 是一一对应的关系,当然了,也可以一对多,一个 MIME 对应多个拓展名。
    2 、浏览器暴露源码是因为 Web 服务器处理失误输出了源文件的原始数据( RAW DATA ),跟你浏览器收到什么 Content-type 没有关系,这个东西很好证明,你可以不用浏览器啊,Linux 有现成的 curl 命令,Web 服务器端配置有问题的话,你用 curl http://xxx 不一样能得到服务器返回的源码吗?跟 Content-Type 有什么关系呢?只跟你服务器输出了什么东西有关系,不止是 Content-Type ,绝大多数的 HTTP 头部信息其实都是可以忽略的,不影响结果输出,绝大部分的头部信息都属于冗余信息,需要用到的时候才拿出来用。
    void1900
        77
    void1900   32 天前
    @hxy100

    哈哈哈哈哈 大神干的漂亮,求你别 @我了,我真的知道错了


    让我静静的观蛙吧,哈哈哈哈哈哈哈哈哈哈哈 (笑倒在了井口)
    InDom
        78
    InDom   32 天前
    弱弱的补上一刀

    ```Nginx.conf
    location ~ \.(php|html?|svg|jpg)$ {
    fastcgi_pass php74:9000;
    fastcgi_index index.php;
    include fastcgi.conf;
    fastcgi_param PATH_INFO $fastcgi_path_info;
    fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
    }
    ```

    以上配置是可以正常执行的,如果内部有 html 代码,也是可以执行的...(似乎)
    miencun
        79
    miencun   32 天前
    @void1900 你别走,我们俩都被他纠住衣领了,你还想跑?
    void1900
        80
    void1900   32 天前
    @InDom 你看到你 location 里的 php 了吗,那就是 mime 配置,还说和 MIME 没关系。
    sarices
        81
    sarices   32 天前
    我怀疑楼主是来钓鱼的,不过我没证据
    void1900
        82
    void1900   32 天前
    @miencun 我已经服输了,他应该已经放过我了
    void1900
        83
    void1900   32 天前
    @sarices 钓蛙
    ccreater222
        84
    ccreater222   32 天前
    正常情况下不会。非正常情况就是你配置了处理 upstream 无响应的配置,中间件的漏洞
    wonderfulcxm
        85
    wonderfulcxm   32 天前 via iPhone
    跟 mine-type 没关系啊,服务器 nginx 也不是靠 mine-type 转发给 php 处理的,浏览器 conten-type 跟 mine-type 也没关系。比如用 php ,jsp 也可以输出 content-type 不是 text/html 内容,比如验证码图片。
    watcher
        86
    watcher   32 天前
    微信加好友 单扣吧
    hxy100
        87
    hxy100   32 天前
    突然想起来一个老梗:
    如何让一群程序员马上争论起来?
    ——“PHP 是世界上最好的语言”

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

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


    散了,我克制一点。干正事要紧。
    eason1874
        88
    eason1874   32 天前   ❤️ 2
    @hxy100 #8 “除非你把.php 后缀的文件配置成 txt 形式( text/plain )加载,这样无论服务挂不挂都会暴露源码”

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

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

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

    你赢了。
    void1900
        93
    void1900   32 天前
    @eason1874

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

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


    @InternetExplorer

    你杠啥杠,大佬说了,MIME 的应用和含义很广泛,你都 <?php 了,就是 mime application/x-httpd-php
    hxy100
        94
    hxy100   32 天前
    @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
        95
    hxy100   32 天前
    @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
        96
    rekulas   32 天前
    @hxy100
    恕我直言,这跟 mime type 确实没啥关系,举个例子,一个 mp3 文件,你改成 php 后缀,那么你认为它的 mime type 是啥呢,如果你觉得是 php 那显然违背了 mime type 的定义,如果你觉得是 mp3 ,那自然就是承认自己错了。mime type 本身就存储在文件头中,web 服务器决定某个文件交给哪个服务去处理的时候,根本不会去读取内容,怎么可能判断 mime type 呢,你如果敢用 mime type 来判断转发服务,那你可能是还没被社会教训惨
    现在别说 web 服务,各大平台读取文件判断类型都从来不会考虑 mime type 了-毕竟这是一种可以随意篡改的不安全的数据
    新手一般喜欢用 mime type ,但是错了就是错了,痛痛快快的别强钻牛角尖
    liuxu
        97
    liuxu   32 天前   ❤️ 6
    首先我忘了回复楼主。
    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
        98
    liuxu   32 天前
    #97 s/不会暴露密码 /不会暴露代码 /
    ji39
        99
    ji39   32 天前
    asp 站转 php 站,没删除的 asp 文件就暴露源码了,想当年专门搜索这样的
    Hardrain
        100
    Hardrain   32 天前 via Android
    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 错误吧
    }
    1  2  
    关于   ·   帮助文档   ·   API   ·   FAQ   ·   我们的愿景   ·   广告投放   ·   感谢   ·   实用小工具   ·   1592 人在线   最高记录 5497   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 31ms · UTC 00:14 · PVG 08:14 · LAX 16:14 · JFK 19:14
    ♥ Do have faith in what you're doing.