一道ISCC题引申的PHP正则复习
iscc中的一道web题“试试看”,描述为随意开火
起初看url,以为是一道常规的文件包含题,后面试了很多方法都出不来
最后受到其他师傅的启发才得到payload
这里有两种payload都可以
http://118.190.152.202:8006/show.php?img=php://filter/resource=1.jpg/resource=show.php
http://118.190.152.202:8006/show.php?img=php://filter/resource=show.php|jpg
对这道题目的匹配规则很感兴趣,在本地搭建进行仔细分析,也是对正则以及php函数的复习
在审计代码之前,先复习一下php的preg_match、strpos和file_get_contents等函数
1、preg_match函数用于正则匹配,第一个参数是要匹配的正则规则,第二个参数是被匹配的字符串。后面的可选参数中,$matches是一个数组,用于返回匹配的字符串结果
# preg_match (PHP 4, PHP 5, PHP 7) preg_match — 执行匹配正则表达式 ### 说明 int **preg_match** ( string `$pattern` , string `$subject` [, array `&$matches` [, int `$flags` = 0 [, int`$offset` = 0 ]]] ) 搜索`subject`与`pattern`给定的正则表达式的一个匹配.
2、strpos函数用于字符串查找,如果找到则返回位置,位置从0开始计算。如果没有找到则返回false
# strpos (PHP 4, PHP 5, PHP 7) strpos — 查找字符串首次出现的位置 ### 说明 int **strpos** ( string `$haystack` , [mixed]`$needle` [, int `$offset` = 0 ] ) 返回 `needle` 在 `haystack` 中首次出现的数字位置。 如果提供了参数matches,它将被填充为搜索结果。 $matches[0]将包含完整模式匹配到的文本, $matches[1] 将包含第一个捕获子组匹配到的文本,以此类推。
3、file_get_contents函数用于文本读取,可以获得文件内容,它更强大的地方在于可以通过http协议抓取内容
# file_get_contents (PHP 4 >= 4.3.0, PHP 5, PHP 7) file_get_contents — 将整个文件读入一个字符串 ### 说明 string **file_get_contents** ( string `$filename` [, bool `$use_include_path` = false [, resource`$context` [, int `$offset` = -1 [, int `$maxlen` ]]]] ) 和 file()一样,只除了 **file_get_contents()** 把文件读入一个字符串。将在参数 `offset` 所指定的位置开始读取长度为`maxlen` 的内容。如果失败,**file_get_contents()** 将返回 **`FALSE`**。 **file_get_contents()** 函数是用来将文件的内容读入到一个字符串中的首选方法。如果操作系统支持还会使用内存映射技术来增强性能。 > **Note**: > > 如果要打开有特殊字符的 URL (比如说有空格),就需要使用 [urlencode()]进行 URL 编码。
本题中,经过注释和改造后的主要代码如下
show.php
<?php error_reporting(0); ini_set('display_errors','Off'); include('config.php'); $img = $_GET['img']; if(isset($img) && !empty($img)) { if(strpos($img,'jpg') !== false) { // strpos拿'resource='到$img中查找,如果匹配到了则前者为真;注意这里是全等 // 如果没有匹配到'/resource=.*jpg/i'正则模式则后者为真; if(strpos($img,'resource=') !== false && preg_match('/resource=.*jpg/i',$img) === 0) { //满足上述两种情况,返回找不到文件 die('File not found.'); } // 再次进行正则匹配,如果以php://filter开头,并且字符串中存在resource=加上任意不包含|的字符串 // 对$img进行左右两边空白或者预定符号的删除,最后匹配结果存到$matches数组 preg_match('/^php:\/\/filter.*resource=([^|]*)/i',trim($img),$matches); // $matches[0]将包含完整模式匹配到的文本, $matches[1] 将包含第一个捕获子组匹配到的文本,以此类推。 var_dump($matches); if(isset($matches[1])) { $img = $matches[1]; } echo "<br>"; echo $img; header('Content-Type: image/jpeg'); // 关键函数get_contents,去获得文件内容 $data = get_contents($img); echo $data; } else { die('File not found.'); } } else { ?> <img src="1.jpg"> <?php } ?>
config.php
<?php // 关键函数get_contents,去获得文件内容 function get_contents($img) { // 如果$img中存在'jpg',返回$img文件内容 if(strpos($img,'jpg') !== false) { return file_get_contents($img); } // 否则返回$img的同时,设置返回头为hmtl else { header('Content-Type: text/html'); return file_get_contents($img); } } ?>
这里通过实际payload在执行中的流程,对关键地方进行输出,方便分析和查看结果
0x01
首先分析show.php?img=php://filter/resource=config.php|jpg
逻辑中的第一个涉及preg_match的if语句中,只有在传入的$img中匹配到"resource="的同时,preg_match中$img匹配规则"/resource=.*jpg/i"匹配不到的情况下成立
在这里不会对payload形成影响
关键点在接下来的正则匹配
// 再次进行正则匹配,如果以php://filter开头,并且字符串中存在resource=加上任意不包含|的字符串 // 对$img进行左右两边空白或者预定符号的删除,最后匹配结果存到$matches数组 preg_match('/^php:\/\/filter.*resource=([^|]*)/i',trim($img),$matches); // $matches[0]将包含完整模式匹配到的文本, $matches[1] 将包含第一个捕获子组匹配到的文本,以此类推。 var_dump($matches); if(isset($matches[1])) { $img = $matches[1]; } echo "<br>"; echo $img; // header('Content-Type: image/jpeg'); // 关键函数get_contents,去获得文件内容 $data = get_contents($img); echo $data;
可以看到,匹配规则是要求以php://filter开头,并且字符串中存在resource=加上任意不包含|的字符串
([^|]*)代表的意思就是排除|以外的字符,允许重复零次或多次,圆括号包裹则表示这是一个匹配的文本子组
匹配的结果保存在$matches数组中,并且$img会被覆盖为$matches的第2个元素
这里的关键在于$matches的第二个元素内容,第二个元素内容是圆括号包裹的([^|]*)子组的内容
经过正则后,$img已经被覆盖,内容为config.php
在config.php中,将通过函数
file_get_contents($img)
去获取指定文件内容并且返回 // 如果$img中存在'jpg',返回$img文件内容 if(strpos($img,'jpg') !== false) { return file_get_contents($img); } // 否则返回$img的同时,设置返回头为hmtl else { header('Content-Type: text/html'); return file_get_contents($img); }
0x02
接下来分析show.php?img=php://filter/resource=1.jpg/resource=config.php
其他流程和上面的一样,只要字符串中包含jpg就可以,关键在于
preg_match('/^php:\/\/filter.*resource=([^|]*)/i',trim($img),$matches);
payload进去之后的匹配结果将是后面一个resource=config.php,而不是resource=1.jpg,因此拿到的$matches的第二个元素也是config.php!
低调大师中文资讯倾力打造互联网数据资讯、行业资源、电子商务、移动互联网、网络营销平台。
持续更新报道IT业界、互联网、市场资讯、驱动更新,是最及时权威的产业资讯及硬件资讯报道平台。
转载内容版权归作者及来源网站所有,本站原创内容转载请注明来源。
- 上一篇
Makeblock推出编程教学工具“慧编程”,融入AI和IoT助力老师打造高效课堂
“慧编程”基于青少年编程语言Scratch开发,提供一站式课堂管理平台,以帮助老师节省备课时间、降低编程教学难度。 4月26日,STEAM教育解决方案提供商Makeblock正式推出编程教学软件--慧编程(mBlock5), 同时上线PC端和移动端版本。 慧编程是为教育工作者量身打造的一款功能强大的编程教育工具,基于全球最流行的青少年编程语言Scratch开发,不仅支持软硬件结合,而且可以实现图形化编程到代码编程的转换,让Python教学变得简单有趣。慧编程增加人工智能和物联网等前沿科技,并且引入课堂管理平台,帮助老师一站式提升课堂教学和管理效率,打造高效课堂。 基于Scratch 3.0,打造高效精准的编程教学课堂 慧编程是基于Scratch 3.0 开发的图形化编程软件,支持一键切换现下最流行的Python代码编程,是目前唯一可以用Python操控Scratch舞台角色和机器人的编程教学软件。慧编程延续了Scratch操作简单、所编即所见的设计理念,即使是零基础也可以轻松上手,体验创造带来的乐趣。 此外,慧编程还增加了微软AI认知服务、IoT(物联网)和谷歌深度学习功能,学生可以通...
- 下一篇
甲骨文合作伙伴基于甲骨文云平台不断加速创新并推动客户成功
甲骨文全球大会,美国旧金山,2016年9月19日-企业越来越多地希望通过云来保持竞争力和推动数据中心的转型。但许多企业都缺乏管理复杂的云迁移和长期维护所需的技能和资源,或是他们需要将这些资源转移至战略创新领域。甲骨文合作伙伴网(OPN)今天宣布推出甲骨文云托管服务提供商(MSP)计划,协助客户在合作伙伴和平台的支持下更快地在云端获得成功。 该计划向合作伙伴提供构建、部署、运行和管理甲骨文和非甲骨文工作负载的技能和基础架构,帮助OPN成员为在甲骨文平台即服务(PaaS)和基础架构即服务(IaaS)上运行的工作负载提供全面的托管服务解决方案。 合作伙伴可以根据客户的需求购买Oracle云平台,将他们的MSP服务打包,通过简化的业务模式出售这一集成的解决方案。合作伙伴可在世界级云基础架构上构建服务,而客户可获得优化云计划所需的全面的解决方案,帮助他们降低风险、成本和复杂性。 早期参与本项z计划的合作伙伴包括埃森哲、源讯、凯捷、高知特、德勤管理咨询、达科、富士通、日立咨询、印孚瑟斯、普华永道、塔塔咨询、马恒达科技和威普罗。 甲骨文公司平台产品副总裁桑杰·辛哈(Sanjay Sinha)表示:"...
相关文章
文章评论
共有0条评论来说两句吧...
文章二维码
点击排行
推荐阅读
最新文章
- SpringBoot2整合MyBatis,连接MySql数据库做增删改查操作
- CentOS8,CentOS7,CentOS6编译安装Redis5.0.7
- 设置Eclipse缩进为4个空格,增强代码规范
- CentOS8安装Docker,最新的服务器搭配容器使用
- Docker使用Oracle官方镜像安装(12C,18C,19C)
- CentOS8编译安装MySQL8.0.19
- SpringBoot2整合Redis,开启缓存,提高访问速度
- SpringBoot2配置默认Tomcat设置,开启更多高级功能
- Hadoop3单机部署,实现最简伪集群
- CentOS7,CentOS8安装Elasticsearch6.8.6