前言

根据红日安全写的文章,学习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题目来练习一下,也是关于正则的问题,先看代码:

//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 字母和数字 header
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('/[1]{12,}$/', $password))

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

第二处正则如下:

$reg = '/([[:punct:]]+|[[:digit:]]+|[[:upper:]]+|[[:lower:]]+)/';

if (6 > preg_match_all($reg, $password, $arr))

break;

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

下面看第三处正则:

$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函数缺陷进行学习和讲解。一起加油吧!


  1. [:graph:]

PHP代码审计05之正则使用不当的更多相关文章

  1. ThinkPHP 3.1,3.2中对IN和BETWEEN正则匹配不当导致的一个SQLi

    // where子单元分析 protected function parseWhereItem($key,$val) { $whereStr = ''; if(is_array($val)) { if ...

  2. 【python正则】工作中常用的python正则代码

    工作中常用的一些正则代码: 01.用户名正则 import re # 4到16位(字母,数字,下划线,减号)if re.match(r'^[a-zA-Z0-9_-]{4,16}$', "ab ...

  3. PHP代码审计分段讲解(3)

    05 ereg正则%00截断 放上源代码 <?php $flag = "flag"; if (isset ($_GET['password'])) { if (ereg (& ...

  4. 航遇项目react踩坑

    1.iconfont应用: a.正常用法如下 <span className='iconfont' > iconfont的代码,例如: </span> b.react不能动态 ...

  5. JS正则表达式完整教程

    JS正则表达式完整教程(略长) 引言 亲爱的读者朋友,如果你点开了这篇文章,说明你对正则很感兴趣. 想必你也了解正则的重要性,在我看来正则表达式是衡量程序员水平的一个侧面标准. 关于正则表达式的教程, ...

  6. CTF-WEB-XTCTF-Web_php_unserialize

    题目来源 XTCTF-Web_php_unserialize 题目考点:PHP代码审计.PHP正则.PHP序列化与反序列化 解题思路 题目源码 <?php class Demo { privat ...

  7. MySQL Crash Course #05# Chapter 9. 10. 11. 12 正则.函数. API

    索引 正则表达式:MySQL only supports a small subset of what is supported in most regular expression implemen ...

  8. 代码审计-ereg正则%00截断

    <?php $flag = "xxx"; if (isset ($_GET['password'])) { if (ereg ("^[a-zA-Z0-9]+$&qu ...

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

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

随机推荐

  1. moviepy音视频剪辑:使用rotate函数实现视频变换处理以及参数expand取值为True时的花屏问题解决方案

    ☞ ░ 前往老猿Python博文目录 ░ 一.rotate函数功能介绍 moviepy的rotate函数用于将剪辑逆时针旋转指定的角度或弧度. 调用语法:rotate(clip, angle, uni ...

  2. PyQt学习随笔:QTableWidget的selectedRanges、setRangeSelected访问选中矩形范围的方法

    老猿Python博文目录 专栏:使用PyQt开发图形界面Python应用 老猿Python博客地址 在QTableWidget对项的操作支持选中多个项的情况下,可以通过方法selectedRanges ...

  3. 第15.19节 PyQt(Python+Qt)入门学习:自定义信号与槽连接

    老猿Python博文目录 专栏:使用PyQt开发图形界面Python应用 老猿Python博客地址 一.引言 本文利用中介绍了PyQt中的信号和槽机制,除了使用PyQt组件的已有信号外,PyQt和Qt ...

  4. PyQt(Python+Qt)学习随笔:QAbstractItemView的alternatingRowColors属性

    老猿Python博文目录 老猿Python博客地址 alternatingRowColors属性用于控制视图中不同行记录背景色是否使用交替不同的颜色. 如果此属性为True,则将使用QPalette. ...

  5. Linux里的几种不同的压缩命令小记

    第一个是 .gz的压缩格式 我们使用gzip来对文件进行压缩,使用gunzip(或者是gzip -d)来对文件进行解压缩 但是gzip的缺点在于不能够压缩目录,压缩的时候也不能够保留源文件 第二个是 ...

  6. 归并排序(c++,递归)

    放上c++代码模板(但是该版本中,还可以再进一步优化成原地算法,即不开辟新的空间:本代码中空间复杂度为n,不是1) 1 #include <iostream> 2 #include< ...

  7. 【Dotnet9-01】从0开始搭建开源项目-lqclass.com

    行文目录 一. 前言 1.1 我的现有网站 1.2 想法:新开发一个网站 1.3 目前开发计划 二. 行动了 2.1 Github创建项目 2.2 使用 WTM 搭建后台框架 2.3 项目演示 2.4 ...

  8. 一种不错的 BFF Microservice GraphQL/REST API 层的开发方式

    云原生(Cloud Native)Node JS Express Reactive 微服务模板 (REST/GraphQL) 这个项目提供了完整的基于 Node JS / Typescript 的微服 ...

  9. bootstrap table 控制checkbox在某些状态不显示

    首先columns:[{field:'column',checkbox:true}];然后设置$("#tableName").bootstrapTable('hideColumn' ...

  10. 【题解】G.Graph(2015-2016 ACM-ICPC, NEERC, Northern Subregional Contest)

    题目链接G题 题意 序列 \(a_1,a_2,⋯,a_n\) 是一个排列, 当且仅当它含有 1 到 n 的所有整数. 排列 \(a_1,a_2,⋯,a_n\) 是一个有向图的拓扑排序,当且仅当对于每条 ...