[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');
?>

进去直接给出了我们源代码,接下来我会对代码进行一个比较详细的解析。

首先给出了我们两个条件选项,全部绕过才能在eval进行一个漏洞利用。

if(isset($_GET['code'])&&!preg_match('/url|show|high|na|info|dec|oct|pi|log|data:\/\/|filter:\/\/|php:\/\/|phar:\/\//i', $_GET['code']))

第一个条件isset()函数检测我们是否使用get的方式提交code参数,并且!在PHP中用于取反布尔值。所以使用!preg_match()函数来过滤掉部分参数。

if(';' === preg_replace('/[^\W]+\((?R)?\)/', '', $_GET['code']))

第二部分则是使用preg_replace()函数进行一个内容匹配并且替换。

原型是preg_replace($pattern, $replacement, $input);

在 $input中匹配$pattern的内容,匹配到利用$replacement内容替换$pattern内容。

[^\W]+匹配一个或多个字母、数字或下划线。即,匹配字母、数字和下划线的连续序列

\(和\):匹配了()

(?R)?匹配一个递归的子表达式。(?R) 表示递归地应用整个正则表达式。? 表示这是可选的。这意味着模式可以匹配一次或多次,或完全不匹配。

我将在这个例子中,让大家对其有一个初步的了解:

例子:abc(def(ghi))

1.先是匹配 abc 作为 [^\W]+

2.匹配 ()作为\(和\)

3.匹配 def(ghi) 作为递归的内容 ,当匹配完外层的abc(def(ghi))就会再次对def(ghi)再次进行一个关于[^\W]+和\(以及\)进行一个匹配。我理解的意思就是对外面进行匹配后在对()内进行匹配直到完全匹配结束。

 两种方法:

一:使用随机文件读取

payload:

?code=readfile(array_rand(array_flip(scandir(pos(localeconv())))));

localeconv()返回一个包含与本地化设置相关的信息的关联数组,例如货币符号、小数点符号等。

pos() 函数用于返回数组中的第一个元素 。

scandir()函数返回指定目录中的文件和目录列表 。

array_flip() 函数将数组的键和值交换 。

array_rand()函数从数组中随机选择一个键。

readfile()函数读取并输出指定文件的内容。

 

  1. localeconv():

    • 返回一个包含与本地化设置相关的信息的关联数组,例如货币符号、小数点符号等。

  2. pos(localeconv()):

    • pos() 函数用于返回数组中的第一个元素。由于 localeconv() 返回一个数组,pos(localeconv()) 会返回这个数组中的第一个元素。

  3. scandir(pos(localeconv())):

    • scandir() 函数返回指定目录中的文件和目录列表。这里的参数是 pos(localeconv()) 的返回值,也就是 localeconv() 返回数组的第一个元素,因此这个元素应该是一个目录的路径。

  4. array_flip(scandir(pos(localeconv()))):

    • array_flip() 函数将数组的键和值交换。因此,如果 scandir(pos(localeconv())) 返回一个文件和目录的列表,那么 array_flip() 会将这些文件和目录名作为键,原来的索引作为值。

  5. array_rand(array_flip(scandir(pos(localeconv())))):

    • array_rand() 函数从数组中随机选择一个键。这个键是随机选择的文件或目录名,因为我们先将 scandir() 的结果进行了键值翻转。

  6. readfile(array_rand(array_flip(scandir(pos(localeconv()))))):

    • readfile() 函数读取并输出指定文件的内容。由于 array_rand() 随机选择了一个文件名,这个文件名会被传递给 readfile(),所以 readfile() 会输出这个随机选择文件的内容。

总结的内容就是这样。

多几次要出现以下情况就读取到flag了

 flag在源代码中

二: 利用变量

payload:

?code=eval(end(current(get_defined_vars())));&wllm=system(%27cat%20f*%27);

get_defined_vars():来查看当前作用域中所有变量的名称和它们的值

current() 是 PHP 的一个内置函数,用于获取数组中当前元素的值。

end() 函数用于将数组的内部指针移动到数组的最后一个元素,并返回该元素的值

end(current(get_defined_vars()))应该一直返回false。对于这次试题我猜测是因为后台只有一个文件目录,所以才可以使用。

 

  • 16
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值