正则表达式的总结与思考

基础知识
**前言:**最近公司在搞POC和EXP,在看代码的时候发现有的部分已经生疏了,所以又回头总结一下,包括php和Python的具体函数和使用以及漏洞案例

0x01 基础部分

字符:
. 匹配任意字符除了\n
[…] 匹配字符集
\d \D匹配数字/非数字
\s \S 匹配空白/非空白字符
\w \W 匹配单词字符[a-zA-Z0-9]/非单词字符
量词:

  • 匹配前一个字符0次或者无限次
  • 匹配前一个字符1次或者无限次
    ?匹配其哪一个字符0次或者1次
    {m}/{m,n}匹配其哪一个字符m次或者n次
    *?/+? /?? 匹配模式变为非贪婪,尽可能少匹配字符
    ^匹配字符串开头
    $匹配字符串结尾
    \A/\Z指定的字符串匹配必须出现在开头/结尾
0x02 Python

re.findall("",) 使用
re.findall("",)匹配所有
re.search("",)匹配一次

In [1]: import re                                                               

In [2]: a= 'C|Java|Pythonn|Javascript'                                          

In [3]: r =  re.findall("Python",a)
In [5]: r                                                                       
Out[5]: ['Python']

#匹配数字
In [6]: a = 'C54Java433#4564 Python|Java'                                       

In [7]: r = re.findall("\d",a)                                                  

In [8]: r                                                                       
Out[8]: ['5', '4', '4', '3', '3', '4', '5', '6', '4']
In [31]: r = re.findall("\d+",a) 
In [32]: r                                                                      
Out[32]: ['54', '433', '4564']
#匹配非单词字符
In [21]: r = re.findall("\W",a)                                                 

In [22]: r                                                                      
Out[22]: ['#', ' ', '|']

用正则表达式匹配url
图片处’img src="(.*?)"’

In [9]: url = "http://www.xiaohuar.com/2014.html"                               

In [10]: res=req.get(url)                                                       

In [11]: url = re.findall('img src="(.*?)"',res.text)                           

In [12]: url                                                                    
Out[12]: 
['/d/file/20160316/a0bab5b5cc4f695012f4af1d871e7256.jpg',
 'http://www.xiaohuar.com/d/file/20140811101923185.jpg']
 ……
 
 
 
 
 In [13]: for i in url: 
    ...:     if i.startswith('/d'): 
    ...:         i="http://www.xiaohuar.com"+i 
    ...:     print(i) 
    ...:                                                                        
http://www.xiaohuar.com/d/file/20160316/a0bab5b5cc4f695012f4af1d871e7256.jpg
http://www.xiaohuar.com/d/file/20140811101923185.jpg
http://www.xiaohuar.com/d/file/2b903e6d59bd1435a0b9ddfb5b4bd9c5.jpg
http://www.xiaohuar.com/d/file/20190814/5c01302d1d3e7f2fc6cbafbc19becaa8.jpg
http://www.xiaohuar.com/d/file/20161018/5385b7113046ac9ae560da41a44b12af.jpg
http://www.xiaohuar.com/d/file/2ce538e9658af40bc034f5dfaf57826a.jpg
http://www.xiaohuar.com/d/file/20141116030511162.jpg
http://www.xiaohuar.com/d/file/faf429bf24391374472fec693322b178.jpg
http://www.xiaohuar.com/d/file/20151206/f391a2312f448863f36db7d0d9acb84d.jpg
http://www.xiaohuar.com/d/file/7249c06c326a75800fdb9a0e1d4c0df8.jpg
http://www.xiaohuar.com/d/file/20140916055435171.jpg
http://www.xiaohuar.com/d/file/20151109/a6a9f1cd6c721bb3fb1dfe6094a6eeb4.jpg

当然可以使用解析库去解析如bs4

0x03 php

引用W3schoool

<!DOCTYPE html>
<html>
<body>

<?php
echo str_replace("world","Shanghai","Hello world!");
?>
  
</body>
</html>
运行结果
Hello Shanghai! 

preg_match() 函数用于进行正则表达式匹配,成功返回 1 ,否则返回 0 。

语法:
int preg_match( string pattern, string subject [, array matches ] )
看seebug上大佬的某处代码审计案例解析

   public function upload() {

        // 创建图片存储文件夹
        $dir = SYS_UPLOAD_PATH.'/member/'.$this->uid.'/';
        @dr_dir_delete($dir);
        !is_dir($dir) && dr_mkdirs($dir);

        if ($_POST['tx']) {
            $file = str_replace(' ', '+', $_POST['tx']);
            if (preg_match('/^(data:\s*image\/(\w+);base64,)/', $file, $result)){
                $new_file = $dir.'0x0.'.$result[2];
                if (!@file_put_contents($new_file, base64_decode(str_replace($result[1], '', $file)))) {
                    exit(dr_json(0, '目录权限不足或磁盘已满'));
                } else {
                    $this->load->library('image_lib');
                    $config['create_thumb'] = TRUE;
                    $config['thumb_marker'] = '';
                    $config['maintain_ratio'] = FALSE;
                    $config['source_image'] = $new_file;
                    foreach (array(30, 45, 90, 180) as $a) {
                        $config['width'] = $config['height'] = $a;
                        $config['new_image'] = $dir.$a.'x'.$a.'.'.$result[2];
                        $this->image_lib->initialize($config);
                        if (!$this->image_lib->resize()) {
                            exit(dr_json(0, '上传错误:'.$this->image_lib->display_errors()));
                            break;
                        }
                    }
                    list($width, $height, $type, $attr) = getimagesize($dir.'45x45.'.$result[2]);
                    !$type && exit(dr_json(0, '图片字符串不规范'));
                }
            } else {

                exit(dr_json(0, '图片字符串不规范'));
            }
        } else {
            exit(dr_json(0, '图片不存在'));
        }

问题出现preg_match(’/^(data:\s*image/(\w+);base64,)/’, $file, $result)处,正则表达式过滤不严格,导致 $result[2]变量可控制为php,而图片内容也可以是可控制的base64编码的部分,所以可以getshell
通过简单测试:

<?php
$file = "data:image/php;base64,PD9waHAgcGhwaW5mbygpOz8+";
if(preg_match('/^(data:\s*image\/(\w+);base64,)/', $file, $result)){
    print_r($result); 
} else {
    print "A match was not found.";
}
?>
php test.php 运行结果 
Array
(
    [0] => data:image/php;base64,
    [1] => data:image/php;base64,
    [2] => php
)

在php当中,’()'表示匹配的子模式,在代码中的正则用了俩次括号,所以得到数组有十三个
此处正确的正则表达式和代码应该为

<?php
$file = "data:image/jpg;base64,PD9waHAgcGhwaW5mbygpOz8+";
if(preg_match('/^(data:\s*image\/(jpg|png|jpeg);base64,)/', $file, $result)){
    print_r($result); 
} else {
    print "A match was not found.";
}
?>

运行结果:

Array
(
    [0] => data:image/jpg;base64,
    [1] => data:image/jpg;base64,
    [2] => jpg
)

关于php的正则细节可以参考[https://blog.csdn.net/uglyfisher/article/details/79333586]
研究正则表达式,可以严谨代码书写规范,挖掘漏洞

0x03 正则表达式引起的CPU过载

引用一处正则表达式回溯的案例
https://www.jb51.net/article/163520.htm

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值