MENU

安全学习-02-正则表达式

August 25, 2021 • 网络安全

正则表达式

正则表达式:

  • ^ 匹配行首(以什么开头;
  • $ 匹配行尾(以什么结尾;
  • [ ] 集合,匹配集合中的任意单个字符;
  • 1 对集合取反;
  • . 匹配任意单个字符;
  • * 匹配前一个字符任意次数(需配合使用);
  • .* 可以是空也可以是任意字符无数次;
  • {n,m} 匹配前一个字符n到m次(匹配前一个字符排列在一起几次到几次)
  • {n} 匹配前一个字符n次
  • {n,} 匹配前一个字符n次以上
  • () 保留 (复制)

使用 Linux系统中 grep命令举例:

  • grep "^ro" /etc/passwd
  • grep "sh$" /etc/passwd
  • grep "[abc]" /etc/passwd
  • grep "[^abc]" /etc/passwd #匹配不含a或b或c的行
  • grep "r." /etc/passwd #匹配r与任意字符组合的行
  • grep "a*" /etc/passwd #搜索a出现任意次数的行,0次也包括
  • grep "..." /etc/passwd #搜索任意三个字符出现的行
  • grep ".* " #可匹配任意行 包括空行

扩展正则表达式:

  • + 最少匹配一次;
  • ? 最多匹配一次;
  • () 组合为整体,保留(相当于 复制)
  • | 或者
  • b 单次边界 \< >\

问题代码:

<?php  
$key='flag{********************************}'; 
$Regular= preg_match("/zkaq.*key.{2,9}:\/.*\/(key*key)/i", trim($_GET["id"]), $match); 
if( $Regular ){  
  die('key: '.$key); 
}
?>

分析:

<1>、函数解析;

preg_match( )

preg_match() 函数可以根据正则表达式对字符串进行搜索匹配,函数的语法格式如下:

preg_match ( $pattern , $subject , $matches )

搜索subject与pattern给定的正则表达式的一个匹配.

参数 :

pattern : 要搜索的模式,字符串类型(正则表达式)。
subject : 输入的字符串。
matches :(可有可无)如果提供了参数matches,它将被填充为搜索结果。 $matches[0]将包含完整模式匹配到的文本, $matches[1] 将包含第一个捕获子组匹配到的文本,以此类推。

返回值 :

preg_match()返回 pattern 的匹配次数。 它的值将是0次(不匹配)或1次,因为preg_match()在第一次匹配后 将会停止搜索。preg_match_all()不同于此,它会一直搜索subject 直到到达结尾。 如果发生错误preg_match()返回 FALSE。


trip( )

trim() 函数移除字符串两侧的空白字符或其他预定义字符.

相关函数:

  • ltrim() - 移除字符串左侧的空白字符或其他预定义字符。
  • rtrim() - 移除字符串右侧的空白字符或其他预定义字符。
 trim(string,charlist) 
参数描述
string必需。规定要检查的字符串。
charlist可选。规定从字符串中删除哪些字符。如果省略该参数,则移除下列所有字符:1."0" - NULL; 2."t" - 制表符; 3."n" - 换行; 4."x0B" - 垂直制表符; 5."r" - 回车; 6." " - 空格
<2>、配合代码解析;

最主要的一行就在于此:

$Regular= preg_match("/zkaq.*key.{2,9}:\/.*\/(key*key)/i", trim($_GET["id"]), $match);
  1. 其中trim()参数并未设置charlist,所以只是去除GET传参中两榜的特殊符号,并未设计具体字符移除,不用考虑;
  2. 主要考虑preg_match(),其中/zkaq.*key.{2,9}:\/.*\/(key*key)/i

    • //双斜杠中的才为具体匹配的内容;
    • 后一个斜杠后的 i 表示不区分大小写;
  3. 得到更具体的进行匹配的字段zkaq.*key.{2,9}:\/.*\/(key*key)

由上述给到的正则匹配规则,一一进行解析:

  • zkaq == zkaq # 确定的字符串无法变动
  • .* == # 通配符,任意字符串
  • key == key # 确定的字符串无法变动
  • .{2,9} == aa # 匹配前一个字符n到m次
  • : == : # 确定的字符串无法变动
  • / == / # 为转义符,使得/无特殊意义
  • .* == a # 通配符,任意字符串
  • / == / # 为转义符,使得/无特殊意义
  • (key*key) == keykeykeykey #()为了组合为一个整体,但是第一个key后面又一个*表示任意次,所以这里我去了3次,后一个key为确定的字符无法变动

最终我给到的结果为: zkaqkeyaa:/a/keykeykeykey

提示:

当然提示的一点是前面我们给到的i不区分大小写并未使用,所以字符串中字母的大小写可以任意,而且.*所匹配的任意字符串可以随意填写,以及后续的字符出现次数也可以随意。

<3>、验证;

将GET传参的 id 改为所得出的结果:

2.正则表达式

最终flag:

key: flag{regular_god_code}