我穿越到了1994年,终于发现了现在80%的网站都用PHP的原因!

昨天晚上写代码到深夜,一头扎到床上,沉沉睡去。

第二天睁开眼睛,我发现自己居然坐在一个咖啡馆里,旁边的墙上贴着最新的英文电影海报《阿甘正传》、《肖申克的救赎》

c3b382162e3ddda3e042abffff0749b3.png

这都是1994年的经典电影,我意识到,自己穿越到了1994年的美国!

对面坐着一个帅哥,一边操作电脑,一边在不停地赞叹。

我探过头去,发现他正在看这个东西:

1f6b599cf632e394cb647c53a8e7c649.png

3e483bc03cac24f11488eb7a40e8551c.png

我说:“哥们儿,这不是安德森开发的Mosaic浏览器吗?这么丑,你怎么不用网景?”

“网景?那是什么东西?不过兄弟不简单啊,我在咖啡馆喝了这么多天的咖啡,你是第一个识货的,还知道安德森,肯定也是个程序员吧,要不一起干吧!”

“干什么啊?”

“浏览器绝对是互联网的未来,现在很多公司都在狂热地拥抱它, 他们就使用 Microsoft Word写文档,然后将文档保存为 HTML,通过 FTP 将它们放到网上,这里边有商业机会啊。”

“写个HTML会有什么商业机会?”

“静态的网站是枯燥的,这些公司很快就会发现,可以和用户交互的、动态的网站才有商业价值。我准备专门提供这样的咨询服务,为他们开发各种动态的Web应用程序。对了,忘了自我介绍了,我叫Rasmus Lerdorf。”

这个人名怎么这么熟悉?

我想既然穿越而来,那就看看1994年的动态网站是怎么开发的吧。

我说:“我叫张大胖,主要用Java编程。”

“Java?那是什么语言?” 他两眼立刻放光了!

我意识到说漏嘴了,Java这时候还没诞生呢!

“其实叫C++--,一个小众语言。”

“和C语言相关,那就好,我们得用C语言写CGI脚本。”

我和他合伙开了个咨询公司,专门接开发动态网站的活儿。

但是开发一开始,我就崩溃了:没有前后端分离,没有Java,没有JSP,ASP, 真的全靠在C语言!

给大家看看:

void main(int argc, char *argv[]) {
  char *params, *data, *dest, *s, *tmp;
  char *name, *age;


  puts("Content-type: text/html\r\n");
  puts("<HTML><HEAD><TITLE>Form Example</TITLE></HEAD>");
  puts("<BODY><H1>My Example Form</H1>");
  puts("<FORM action=\"form.cgi\" method=\"GET\">");
  puts("Name: <INPUT type=\"text\" name=\"name\">");
  puts("Age: <INPUT type=\"text\" name=\"age\">");
  puts("<BR><INPUT type=\"submit\">");
  puts("</FORM>");


  data = getenv("QUERY_STRING");
  if(data && *data) {
    params = data; dest = data;
      while(*data) {
      if(*data=='+') *dest=' ';
      else if(*data == '%' && ishex(*(data+1))&&ishex(*(data+2))) {
        *dest = (char) htoi(data + 1);
        data+=2;
      } else *dest = *data;
      data++;
      dest++;
    }
    *dest = '\0';
    s = strtok(params,"&");
    do {
      tmp = strchr(s,'=');
      if(tmp) {
        *tmp = '\0';
        if(!strcmp(s,"name")) name = tmp+1;
        else if(!strcmp(s,"age")) age = tmp+1;
      }
    } while(s=strtok(NULL,"&"));


    printf("Hi %s, you are %s years old\n",name,age);
  }
  puts("</BODY></HTML>");
}

用一句话来说那就是:在C语言当中输出HTML代码。

这是人干的活吗?我都快写吐了!

Rasmus:“没办法啊,C语言编写CGI脚本,实现动态网页,可不就得这样嘛?对了,你会用Perl吗?”

“就是那个写出来以后代码谁都不认识的语言?我不想用!”

时间长了,Rasmus 也受不了了:“这些CGI 脚本无外乎就是处理表单, Post数据,过滤等,重复代码太多了,怎么样才能提高效率呢?”

他有空就琢磨这件事情,有一天,他想到了一招,把这些常用的功能都包装到一个C语言库中,它“植入”NCSA Web 服务器中(这是Apache之前最流行的服务器),然后在上面添加了一个模板系统,可以轻松地调用他们。

于是代码就是变成这个样子:

<html><head><title>Form Example</title></head>
<body><h1>My Example Form</h1>
<form action="form.phtml" method="POST">
Name: <input type="text" name="name">
Age: <input type="text" name="age">
<br><input type="submit">
</form>
<?if($name):?>
Hi <?echo $name?>, you are <?echo $age?> years old
<?endif?>
</body></html>

换句话说:就是在HTML中“混入”代码。

和CGI对比,这种方式对程序员来说非常友好,我们的工作效率一下子提高了很多。

说实话,我早就知道这种方式,就是ASP,JSP嘛,但是自己没那技术实力,实现不了啊!

Rasmus 很快就找到了一个新客户,用新工具为他们开发Web程序,连接到数据库,满足他们各种各样的需求。

随着客户的增多, 客户的需求也略有不同,于是,Rasmus 就不断地扩展它的工具箱, 从简单的解析器慢慢发展为包含条件标签,然后是循环标签、函数等各种复杂的东西,这已经是一门语言了。 

Rasmus 把它们称为Personal Home Page,简称PHP。

我这才意识到,原来遇到了PHP之父!

很快就有其他程序员找上门来, 问我们:Rasmus, 你们怎么开发得这么快!

Rasmus说:我有个人工具箱啊!

“那我能不能用?”

Rasmus说:“可以啊,工具只是我的锤子,每个人都可以用我的锤子。”

我赶忙阻止他:“Rasmus, 你把锤子给别人, 那咱们靠什么赚钱?”

“我不靠锤子赚钱,我卖的是解决问题的服务。”

我心想他真是傻瓜,为什么不靠卖他的工具来赚钱呢?学学Bill Gates,过几年上市!

让我没想到的是,神奇的事情发生了。

使用PHP的人开始给Rasmus发送补丁了 ——他们发现了Rasmus都没有发现的Bug!

于是Rasmus到客户那里说:我又升级了一个新版本,改了这个,改了那个。

客户非常满意,他们认为我们的工作效率非常高,不但能快速完成功能,还能快速修复Bug。

我突然意识到:这不就是开源吗?

当然,这是1994、1995年,开源这个词还没有出现,当时只有RMS提倡的自由软件。

随着越来越多的人提交补丁,PHP逐渐完善,1995年,Rasmus看到时机成熟,正式宣布了 PHP 1.0的诞生。

4be3003d3933cca9a8c04239ddfed9d9.png

4bbfeee436dafc829c49ad106bb72b7d.png

原来PHP就是这么起步的啊!

Rasmus展示出了一个领袖的大度和风范,他放弃了对PHP的独家控制权。

通过把项目的所有权分给其他人,这样大家都可以投入,PHP成了大家的项目,而不是Rasmus一个人的项目。

当时,PHP源码放在CVS中,我想让Rasmus把PHP源码放到GitHub, 可是那个时候连Git都没有,哪而来的Hub?

在这里没有管理,大家是自我组织的小群体,可以围绕自己感兴趣的东西,自我组织。

任人唯贤, 代码说话。

这真正地改变了PHP的本质。

有一个周末,我又和Rasmus来咖啡馆喝咖啡,我说:“我觉得你得给PHP添加一些高级的特性了!”

“比如泛型,注解,面向函数编程,Lambda之类。”

“不不,我希望 把进入PHP的门槛控制在很低的水平,无论是使用它还是向他做贡献。任何想解决Web问题的人通常会通过PHP找到非常直接的解决方案,许多声称可以解决 Web 问题的替代方案太复杂了,想想看,你需要在周五之前完成工作,但是得翻阅800页的手册,这让人崩溃。”

“你有没有想过,将来PHP会统治Web?”

“哈哈, 有这种可能吗?”

当年的Rasmus并不知道,PHP将在互联网大潮中野蛮生长,和Linux, MySQL , Apache联姻, 不断攻城略地。

W3Tech的统计显示,PHP统治了Web, 接近80%的网站在使用PHP!

599b9e4173d847068c35809d559815e2.png

23fb78c3f309ea54926bf7ab98c6851e.png

“如果让你总结一下,如何才能创建一个成功的开源项目,你会怎么说?”

聊到这个话题,Rasmus突然就滔滔不绝起来,因为他从0到1发展起一个项目,简直太有发言权了!

“如果你只有一个很酷的想法, 没有人会加入你的项目,每个人都有很酷的想法。

如果你创建的东西是半生不熟的,那么人们可能对你做的事情不屑一顾,他们会用自己的方式来解决问题。

只有你构建了足够有用的东西,大家才会来到你的身边,他们会更容易接受你的代码,然后稍微扩展来解决他们自己的问题,这样雪球才能滚动起来。

所以,要开始一个开源项目,你必须解决一个困扰你一段时间的问题,这可能会花费数月的时间才能找到真正的问题并解决掉,然后你必须接受早期采用这的建议,尽最大努力让工具对更广泛的受众有用。

最后可以考虑放弃控制权,让其他人和你一起努力,当人们用你的代码做他们任何想做的事情的时候,你的开源项目就成功了!”

“太棒了,我希望我的读者们都能看到这段话。”

“你的读者?”

“是的,码农翻身公众号,我不能说太多了,天机不可泄露,我得走了。”

说完,我就消失了。

后记:这次尝试了一个新的写法,让张大胖穿越到了1994年,以旁观者的身份讲解了PHP的起步历程。最精华的部分就是末尾关于“如何创建一个成功的开源项目”。

有人可能要问,哪些情节是真的?这个要卖个关子,只要在公众号回复“PHP之父”就能得到答案。

(完)

我的新书《半小时漫画计算机》京东、当当热销中,五折优惠,不容错过,长按二维码即可购买

009ffbad7a180deb9449798f687ba552.png

另外,没有看过第一本《码农翻身》的小伙伴可以考虑下,也是5折,点击阅读原文即可购买。

<think>好的,我现在需要处理用户关于PHP中目录穿越漏洞的原理及防护方法的提问。首先,我得先理解目录穿越漏洞的基本概念。目录穿越漏洞,也叫做路径遍历漏洞,攻击者通过构造特殊的输入来访问本不应该被公开的文件或目录。比如,用户提交的路径参数中包含“../”这样的字符,可能导致服务器解析路径时跳出限制目录,访问到系统敏感文件。 接下来,我需要结合用户提供的引用内容。用户给出了三个引用,其中引用[1]提到了Voyager管理面板中的漏洞处理,代码中使用str_replace替换'../'和'./',但可能处理不够彻底。引用[2]是Apache Tomcat的漏洞链接,可能相关其他服务器的类似问题。引用[3]涉及开发自定义漏洞利用脚本,说明攻击者可能利用这种漏洞进行后续攻击。 首先,我需要解释漏洞的原理。比如,用户提供的路径参数未正确过滤,导致攻击者可以输入类似“../../etc/passwd”的路径,访问系统文件。PHP中如果直接使用用户输入的路径去读取文件,而没有做足够的过滤,就会产生这个问题。例如,用户提供的代码示例中,使用urldecode处理路径,再替换掉'../'和'./',但可能没有考虑到多重编码的情况,比如%2e%2e%2f代表../,或者使用斜杠的不同表示方式。 然后,防护方法部分需要详细说明如何正确过滤用户输入。比如,使用realpath函数来解析绝对路径,并检查是否在允许的目录内。另外,要提到白名单验证,限制允许访问的文件类型或目录。还要注意编码问题,比如进行多次urldecode处理,防止攻击者绕过替换。此外,设置PHP的open_basedir限制,确保文件操作只能在指定目录内进行。 还要参考用户提供的例子,指出替换'../'可能不够,比如如果攻击者使用“.../”或者“..\”等变种,可能需要更面的过滤。同时,使用basename函数来获取文件名,避免路径中的跳转字符。 最后,生成相关问题,考虑用户可能进一步想知道如何测试这种漏洞,其他常见PHP漏洞,或者具体框架如Laravel中的防护方法。需要确保问题覆盖漏洞的不同方面,帮助用户面理解。 总结起来,回答的结构应该是:原理、示例代码分析、防护方法(多个措施)、相关引用,然后生成相关问题。要确保使用正确的中文表达,行内公式用$...$,独立公式用$$...$$,不过这个问题可能不需要数学公式,但要注意LaTeX格式。同时检查是否有需要引用的地方,比如引用[1]中的代码示例,说明处理不足的情况,需要指出正确的做法。</think>### PHP目录穿越漏洞原理与防护方法 #### 一、漏洞原理 目录穿越漏洞(Directory Traversal)源于未对用户输入的路径参数进行严格过滤,攻击者通过构造包含特殊字符(如$../$、$./$)的路径,绕过系统限制访问非授权文件。例如: ```php // 漏洞示例代码 $user_input = $_GET['file']; $file_path = '/var/www/uploads/' . $user_input; readfile($file_path); ``` 若用户输入为`../../etc/passwd`,最终路径会解析为`/var/www/uploads/../../etc/passwd`,从而泄露系统敏感文件[^1]。 #### 二、漏洞触发条件 1. **未过滤用户输入**:直接拼接用户输入的路径参数。 2. **多重编码绕过**:攻击者可能使用URL编码(如`%2e%2e%2f`表示`../`)或双重编码(如`%252e%252e%252f`)。 3. **操作系统差异**:Windows系统可能允许反斜杠`..\`作为路径分隔符。 #### 三、防护方法 1. **路径规范化与校验** ```php $user_input = $_GET['file']; $base_dir = '/var/www/uploads/'; // 解析绝对路径并检查是否在基目录下 $real_path = realpath($base_dir . $user_input); if (strpos($real_path, $base_dir) !== 0) { die("非法路径"); } ``` 2. **白名单限制文件类型** ```php $allowed_extensions = ['jpg', 'png']; $file_name = basename($user_input); // 去除路径跳转字符 $extension = pathinfo($file_name, PATHINFO_EXTENSION); if (!in_array($extension, $allowed_extensions)) { die("文件类型不允许"); } ``` 3. **输入过滤与解码处理** ```php $user_input = urldecode($user_input); $user_input = str_replace(['../', '..\\'], '', $user_input); // 过滤所有路径跳转符 ``` 4. **配置PHP参数** ```ini ; php.ini配置 open_basedir = /var/www/uploads/ disable_functions = realpath,shell_exec ``` #### 四、实际案例 在Voyager管理面板的漏洞代码中,虽然尝试通过`str_replace`过滤`../`和`./`,但未处理多重编码或反斜杠,导致仍存在绕过风险。正确做法应结合`realpath`和基目录校验。 ---
评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值