PHP源码分析之parse_url()的2个小trick
Posted ChaMd5安全团队
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了PHP源码分析之parse_url()的2个小trick相关的知识,希望对你有一定的参考价值。
前言:
之前从phithon师傅的代码审计小密圈看到pupiles师傅发过一篇文章,讲了parse_url()的很多小tricks,可惜只是给出了tricks的利用方法,并没有从底层原理上进行分析,正好我最近也在研究php源码,于是就给分析了一波。
本文测试使用的PHP版本为7.0.30
pupiles师傅的原文链接:
http://pupiles.com/%E8%B0%88%E8%B0%88parse_url.html
函数分析:
parse_url()定义在extstandardurl.c中第337行
第334行调用zend_parse_parameters()对参数进行解析,第一参数就是传入的URL字符串,第二个参数是可选的我们暂时不做研究。
第348行,调用php_url_parse_ex()对URL字符串进行解析,返回值保存在resource中,resource定义在341行,是一个php_url类型的结构体:
跟入php_url_parse_ex()
这个函数接收两个参数,分别是URL字符串和其长度
第100行声明了一个ret指针并为其分配了一个php_url结构,用于保存返回值
之后初始化s指向字符串开头,ue指向字符串结尾
第一个trick:
此时我们传入的字符串为 /pupiles.com:80
第107行把e指向了字符“:”所在的位置
第109行把s赋值给p
此时的指针结构入如下:
112行的if中有四个条件:
1.*p非字符
2.*p非数字
3.*p != ‘+’
4.*p != ‘-’
很明显,p指向的第一个字符是’/’,满足上述条件
113行再次进行判断,其中两个条件:
1. e + 1 < ue,由上图知e + 2 == ue,故条件满足
2. e < s + strcspn(s,"?#"), 由于字符串s中没有出现字符?和#,因此strcspn()返回s的长度15,e < s + 15,满足条件
114行 goto parse_port;
parse_port在第177行:
执行到第179行时指针结构如下:
181行的循环之后:
185行中if条件满足
187行中,因为pp - p == 2,所以把从指针p开始的两个字符复制到port_buf中,port_buf定义在99行:
188行追加一个空字符终止字符串,此时port_buf的值为: 80
189行从port_buf解析出port并在191行赋值给ret结构体的port成员
至此port解析完成,进入到215行的parse_host:
217行把ue赋值给e:
218行把p指向了字符’/’的位置:
219行把p赋值给e:
此时 e == s,故不会进入229行的if
继续向下:
246行的if不满足,进入到251行的else中
找到zend_memrchr()的定义:
传入的参数n即(e-s),由于e == s,即e - s == 0,可知n == 0
在zend_memrchr()的第189行,可知n <= 0时返回NULL
因此p == NULL,不会进入255行的if,而是进入到281行的else中:
281行把e赋值给p,还是和之前一样:
286行由于p == s,因此(p-s) < 1成立,291行return NULL,函数返回
自己写一个PHP文件测试一下:
<?php
$url = $_GET['url'];
var_dump(parse_url($url));
第二个trick:
实测一下:
在端口号之后加一个字符就会被当做path解析了,神奇!
继续分析一波:
这个字符串的解析过程和上述基本一致,不同发生在了parse_port中:
在185行时各指针如下:
由于此时185行的if不满足因此会进入到207行,跳转到just_path中:
305行把ue赋值给e:
由于字符串中不存在字符’#’和’?’
因此306和316行的if都不满足
326行s < e为真,之后设置了ret结构的path成员
331行返回结构体ret
后记:
本人不才,看C看的好心累,只分析了前两个trick,剩下的trick有兴趣的师傅欢迎投稿分享~!
ChaMd5安全招聘~
美团点评集团
移动安全专家(协议分析、安全审计方向)
http://www.chamd5.org/jobdetail.aspx?id=487
移动安全专家(产品研发方向)
http://www.chamd5.org/jobdetail.aspx?id=488
百度安全实验室
AI安全产品研发工程师
http://www.chamd5.org/jobdetail.aspx?id=482
AI安全研究员
http://www.chamd5.org/jobdetail.aspx?id=483
北京天际友盟信息技术有限公司
安全开发工程师
http://www.chamd5.org/jobdetail.aspx?id=474
情报/数据分析师
http://www.chamd5.org/jobdetail.aspx?id=475
Python爬虫工程师
http://www.chamd5.org/jobdetail.aspx?id=476
用户体验设计师
http://www.chamd5.org/jobdetail.aspx?id=477
JAVA工程师
http://www.chamd5.org/jobdetail.aspx?id=478
Web前端工程师
http://www.chamd5.org/jobdetail.aspx?id=479
售前工程师
http://www.chamd5.org/jobdetail.aspx?id=480
华东区销售总监
http://www.chamd5.org/jobdetail.aspx?id=481
西安讯蜂科技有限公司
前端开发工程师
http://www.chamd5.org/jobdetail.aspx?id=493
安全工程师
http://www.chamd5.org/jobdetail.aspx?id=492
安全研究员
http://www.chamd5.org/jobdetail.aspx?id=491
人工智能研究员
http://www.chamd5.org/jobdetail.aspx?id=490
数据分析研究员
http://www.chamd5.org/jobdetail.aspx?id=489
销售经理
http://www.chamd5.org/jobdetail.aspx?id=488
以上是关于PHP源码分析之parse_url()的2个小trick的主要内容,如果未能解决你的问题,请参考以下文章