前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >PHP代码审计05之正则使用不当

PHP代码审计05之正则使用不当

作者头像
雪痕@
发布于 2020-12-31 03:05:27
发布于 2020-12-31 03:05:27
61700
代码可运行
举报
文章被收录于专栏:代码审计代码审计
运行总次数:0
代码可运行

前言

根据红日安全写的文章,学习PHP代码审计的第五节内容,题目均来自PHP SECURITY CALENDAR 2017,讲完题目会用一道CTF的题目和实例来加深巩固。这是之前写的,有兴趣可以去看看:

PHP代码审计01之in_array()函数缺陷

PHP代码审计02之filter_var()函数缺陷

PHP代码审计03之实例化任意对象漏洞

PHP代码审计04之strpos函数使用不当

漏洞分析

下面看题目,代码如下:

题目漏洞是正则使用不严谨导致任意文件删除的漏洞,现在来具体分析,引起漏洞的地方在上面代码的21行,这里用到了preg_replace()函数,我们打开PHP手册来看看对这个函数的定义如下:

了解了函数的用法,看上面代码,^a-z.-_ 表示匹配除了 a 字符到 z 字符和. 字符到 _ 字符之间的所有字符,但是没有考虑到目录路径字符。这就直接可以任意删除文件,例如构造如下参数:

action=delete&data=../../config.php

将删除config.php文件。

CTF练习

通过上面的讲解,来用一道CTF题目来练习一下,也是关于正则的问题,先看代码:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
//index.php
<?php
include 'flag.php';
if  ("POST" == $_SERVER['REQUEST_METHOD'])
{
    $password = $_POST['password'];
    if (0 >= preg_match('/^[[:graph:]]{12,}$/', $password))
    {
        echo 'Wrong Format';
        exit;
    }
    while (TRUE)
    {
        $reg = '/([[:punct:]]+|[[:digit:]]+|[[:upper:]]+|[[:lower:]]+)/';
        if (6 > preg_match_all($reg, $password, $arr))
            break;
        $c = 0;
        $ps = array('punct', 'digit', 'upper', 'lower');
        foreach ($ps as $pt)
        {
            if (preg_match("/[[:$pt:]]+/", $password))
            $c += 1;
        }
        if ($c < 3) break;
        if ("42" == $password) echo $flag;
        else echo 'Wrong password';
        exit;
    }
}
highlight_file(__FILE__);
?>
//flag.php
<?php $flag = "HRCTF{Pr3g_R3plac3_1s_Int3r3sting}";?>

这道题目考察了是否熟悉PHP正则表达的字符类,大体是下面这个表格:

| alnum | 字母和数字 |

| alpha | 字母 |

| ascii | 0 - 127的ascii字符 |

| blank | 空格和水平制表符 |

| cntrl | 控制字符 |

| digit | 十进制数(same as \d) |

| graph | 打印字符, 不包括空格 |

| lower | 小写字母 |

| print | 打印字符,包含空格 |

| punct | 打印字符, 不包括字母和数字 |

| space | 空白字符 (比\s多垂直制表符) |

| upper | 大写字母 |

| word | 单词字符(same as \w) |

| xdigit | 十六进制数字 |

想要更加详细的了解,建议翻阅PHP手册,了解了字符类,下面来分析代码,上面一共三处正则表达,第一处如下:

if (0 >= preg_match('/^[:graph:]{12,}

它表示的含义是匹配到可打印字符12往上包含12,^表示必须某类字符开头,$表示必须某类字符结尾。

第二处正则如下:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
 $reg = '/([[:punct:]]+|[[:digit:]]+|[[:upper:]]+|[[:lower:]]+)/';
if (6 > preg_match_all($reg, $password, $arr))
break;

它表示的含义是,把连续的字符,数字,大写,小写作为一段,最少分成六段,比如Test+0He 会分为T est + 0 H e六段。

下面看第三处正则:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
$ps = array('punct', 'digit', 'upper', 'lower');
 foreach ($ps as $pt)
{
if (preg_match("/[[:$pt:]]+/", $password))
$c += 1;
}
if ($c < 3) break;
if ("42" == $password) echo $flag;

这里的含义是输入的字符必须包含字符,数字,大写,小写其中的三种往上。最后与42进行弱类型比较,都符合就输出flag,现在都解读清楚了,让咱们构造payload结果如下:

实例分析

通过例题和CTF题目的讲解,是不是感觉棒棒的,现在咱们来分析实例吧,实例是LvyeCMS3.1,是基于ThinkPHP3.2.3框架。这个实例存在的漏洞也是函数使用不规范被绕过,导致任意文件删除。下面来具体分析:

先查看入口文件index.php

可以看到公共目录,应用目录等一些信息。接下来再看看目录结构:

而漏洞在Application/Template/Controller/StyleController.class.php文件中,具体如下:

看代码第117行,这里是获取目录路径,参数也是我们可以控制的,再向后看,用到了str_replace()函数,它是个字符串替换函数,具体说明如下:

再这里起到的作用就是将'..\', '../', './', '.\'替换为空。但是这里是可以绕过的,如果我们输入.....///呢,会发生什么?是不是正好构造成了../,举个小例子会更清楚,如下:

构造出../我们就可以穿越目录了,现在访问install.php文件会提示已安装,如下图:

然后尝试删除lvyecms/Application/Install/目录下的 install.lock 文件,构造payload如下:

http://www.xxx.com/index.php?g=Template&m=Style&a=delete&dir=.....///Application/Install/&file=install.lock

现在访问install.php,发现确实删除了,如下图:

小结

通过这篇文章的学习与讲解,是不是对PHP的正则了解的更多了呢,下一篇文章会对parse_str函数缺陷进行学习和讲解。一起加油吧!

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2020-12-29 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
java8 Streams API 详解(下)-- 详解 Stream 操作
上一篇文章中,我们介绍了 Streams API 是如何使用的,以及列出了 java8 中 Streams API 包含的所有操作。
用户3147702
2022/06/27
7750
java8 Streams API 详解(下)-- 详解 Stream 操作
Java8中的Stream API详解
在传统的J2EE应用中,Java代码经常不得不依赖于关系型数据库的聚合操作来完成诸如:
用户4396583
2024/08/03
1640
Java 8 中的 Streams API 详解
Stream 作为 Java 8 的一大亮点,它与 java.io 包里的 InputStream 和 OutputStream 是完全不同的概念。它也不同于 StAX 对 XML 解析的 Stream,也不是 Amazon Kinesis 对大数据实时处理的 Stream。Java 8 中的 Stream 是对集合(Collection)对象功能的增强,它专注于对集合对象进行各种非常便利、高效的聚合操作(aggregate operation),或者大批量数据操作 (bulk data operation)。Stream API 借助于同样新出现的 Lambda 表达式,极大的提高编程效率和程序可读性。同时它提供串行和并行两种模式进行汇聚操作,并发模式能够充分利用多核处理器的优势,使用 fork/join 并行方式来拆分任务和加速处理过程。通常编写并行代码很难而且容易出错, 但使用 Stream API 无需编写一行多线程的代码,就可以很方便地写出高性能的并发程序。所以说,Java 8 中首次出现的 java.util.stream 是一个函数式语言+多核时代综合影响的产物。
编程十年
2019/09/17
1.2K0
Java8 Stream api 入门
Stream 作为 Java 8 的一大亮点,它与 java.io 包里的 InputStream 和 OutputStream 是完全不同的概念。它也不同于 StAX 对 XML 解析的 Stream,也不是 Amazon Kinesis 对大数据实时处理的 Stream。
呼延十
2019/07/01
7330
Java8---Stream的介绍和相关概念(1)
        Stream 作为 Java 8 的一大亮点,它与 java.io 包里的 InputStream 和 OutputStream 是完全不同的概念。它也不同于 StAX 对 XML 解析的 Stream,也不是 Amazon Kinesis 对大数据实时处理的 Stream。Java 8 中的 Stream 是对集合(Collection)对象功能的增强,它专注于对集合对象进行各种非常便利、高效的聚合操作(aggregate operation),或者大批量数据操作 (bulk data operation)。
IT云清
2019/01/22
5440
Java 基础概念·Java Stream
Stream 和其它集合类的区别在于:其它集合类主要关注与有限数量的数据的访问和有效管理(增删改),而 Stream 并没有提供访问和管理元素的方式,而是通过声明数据源的方式,利用可计算的操作在数据源上执行。
数媒派
2022/12/01
1.1K0
JDK8系列之Stream API入门教程和示例
在前面的章节的学习中,我们学习了jdk8的新特性,lambada表达式、方法引用、函数式接口等等,接着本博客继续JDK8的一个比较重要的特性,JDK8 Stream API
SmileNicky
2021/07/21
7290
Java 8 Stream 从入门到进阶——像SQL一样玩转集合
所以有没有这样一种方式可以让我们不再使用一遍又一遍的循环去处理集合,而是能够便捷地操作集合?
翊君
2022/03/08
6680
Java 8 Stream 从入门到进阶——像SQL一样玩转集合
Java8函数式编程
最近使用lambda表达式,感觉使用起来非常舒服,箭头函数极大增强了代码的表达能力。于是决心花点时间深入地去研究一下java8的函数式。
全栈程序员站长
2022/07/21
6570
Java8函数式编程
Java8 Stream的总结
Stream是Java 8新增的接口,Stream可以认为是一个高级版本的 Iterator。它代表着数据流,流中的数据元素的数量可以是有限的,也可以是无限的。
fengzhizi715
2018/08/24
3920
Java8 Stream的总结
2021最新 JDK17 之 JAVA基础 Stream 流
Java 8之前的集合类库主要依赖于 外部迭代(external iteration)。 Collection实现 Iterable接口,从而使得用户可以依次遍历集合的元素。比如我们需要把一个集合中的形状都设置成红色,那么可以这么写:
猫头虎
2024/04/07
2210
2021最新 JDK17 之 JAVA基础 Stream 流
Java8特性接口的改变LambaStream时间API
函数式接口,该接口中只能由一个抽象方法,可以使用@FunctionalInterface注解修饰某个接口有且仅有一个抽象方法。
spilledyear
2018/10/09
4350
一次性实战java8 新特性(全)—— Lambda、Optional、stream、DateTime
本篇博客你将学到: 1.Lambda表达式 2.Optional类,告别空指针异常 3.Stream流式处理 4.时间处理LocalDate、LocalTime、LocalDateTime、ZonedDateTime、Clock、Duration 5.重复注解 6.扩展注释 7.更好的类型推荐机制 8.参数名字保存在字节码中 9.异步调用 CompletableFuture
源码之路
2020/09/03
2.6K0
【小家java】java8新特性之---Stream API 详解 (Map-reduce、Collectors收集器、并行流、groupby多字段分组)
Stream 作为 Java 8 的一大亮点,它与 java.io 包里的 InputStream 和 OutputStream 是完全不同的概念。
YourBatman
2019/09/03
3.3K0
【小家java】java8新特性之---Stream API 详解  (Map-reduce、Collectors收集器、并行流、groupby多字段分组)
Java8新特性之Stream流(基础篇)
对于流的处理,主要有三种关键性操作:分别是流的创建、中间操作(intermediate operation)以及最终操作(terminal operation)。
Remember_Ray
2020/08/03
1.9K1
Java8学习之Stream(流)
本文讲述.stream()的内容,需要一些Lambda表达式的基础,之前也推送过关于Lambda表达式和Stream的相关内容,就看哪盘菜味道更好!
用户5927304
2019/07/31
1.1K0
还看不懂同事的代码?超强的 Stream 流操作姿势还不学习一下
我们都知道 Lambda 和 Stream 是 Java 8 的两大亮点功能,在前面的文章里已经介绍过 Lambda 相关知识,这次介绍下 Java 8 的 Stream 流操作。它完全不同于 java.io 包的 Input/Output Stream ,也不是大数据实时处理的 Stream 流。这个 Stream 流操作是 Java 8 对集合操作功能的增强,专注于对集合的各种高效、便利、优雅的聚合操作。借助于 Lambda 表达式,显著的提高编程效率和可读性。且 Stream 提供了并行计算模式,可以简洁的编写出并行代码,能充分发挥如今计算机的多核处理优势。
未读代码
2019/11/25
5560
Java8 Stream流
关注公众号(CoderBuff)回复“stream”获取《Java8 Stream编码实战》PDF完整版。
用户1148394
2020/03/25
1.4K0
【Java8新特性】03 Stream流式数据处理
【Java8新特性】02 函数式接口和Lambda表达式实战练习:环绕执行模式使行为参数化
爱笑的架构师
2020/09/24
1.4K0
【Java8新特性】03 Stream流式数据处理
Stream使用这么久,它是如何提高遍历集合效率?
对于List 集合类,我想大家肯定很了解了,那我想一定也知道集合的顶端接口 Collection。在 Java8 中,Collection 新增了两个流方法,分别是 Stream() 和 parallelStream()
码农架构
2020/10/26
9090
Stream使用这么久,它是如何提高遍历集合效率?
推荐阅读
相关推荐
java8 Streams API 详解(下)-- 详解 Stream 操作
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档