admin[hctf 2018]

y4ny4n

unicode欺骗、flask session伪造、条件竞争

对源文件的分析学习

code.py

random.sample

多用于截取列表的指定长度的随机数,但是不会改变列表本身的排序:

1
2
3
4
5
6
7
list = [0,1,2,3,4]
rs = random.sample(list, 2)
print(rs)
print(list)

》》》[2, 4] #此数组随着不同的执行,里面的元素随机,但都是两个
》》》[0, 1, 2, 3, 4]

string.digits

digits方法的作用是生成字符串,包括0-9

string.ascii_letters

a-z A-Z

原来验证码是这样生成的(好神奇

1
2
3
def gene_text():
'''生成4位验证码'''
return ''.join(random.sample(string.ascii_letters+string.digits, 4))

PIL库使用

PIL.image

1)新建图片对象

im = Image.new(‘RGB’,(width, height),’white’)

如果不给color变量赋值,图像内容被设置为0,为黑色

2)预览

im.show()

PIL.ImageDraw

1)新建draw对象

draw=ImageDraw.Draw(im)

2)绘制字符串

draw.text((5+random.randint(-3,3)+23*item, 5+random.randint(-3,3)),

​ text=code[item], fill=rndColor(),font=font )

第一个参数为绘制开始坐标,第二个参数为需要绘制的文字内容,第三个参数为颜色

高斯模糊

对图像进行模糊处理 使用ImageFilter类

ImageFilter:Python中的图像滤波,主要对图像进行平滑、锐化、边界增强等滤波处理。

im = im.filter(ImageFilter.GaussianBlur(radius=1.5))

高斯模糊 GaussianBlur(radius=2)

Image.save

1
img.save(img_name, quality=95)

有些时候往往需要图片的大小不能变化太大或不能太小。所以在使用此方式时可以加入参数。quality参数: 保存图像的质量,值的范围从1(最差)到95(最佳)。 默认值为75,使用中应尽量避免高于95的值; 100会禁用部分JPEG压缩算法,并导致大文件图像质量几乎没有任何增益。

routes.py

and/or

学习出处:https://www.cnblogs.com/yonyong/p/9166067.html

and和or比较的结果不是布尔值,而是比较值之一

and

从左到右演算表达式,如果比较的值都为真,and返回最后一个值

如果某个值为假,and返回第一个假值

or

使用 or 时,在布尔上下文中从左到右演算值,就像 and 一样。如果有一个值为真,or 立刻返回该值 如果所有的值都为假,or 返回最后一个假值 注意 or 在布尔上下文中会一直进行表达式演算直到找到第一个真值,然后就会忽略剩余的比较值

故config.py中

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

如果环境变量为空,那么key值将成为’ckj123’

BytesIO

Python在内存中读写数据,用到的模块是StringIO和BytesIO

os.environ.get()

os.environ.get()是python中os模块获取环境变量的一个方法

nodeprep.prepare

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),版本差距过大可以判断有漏洞(原来如此

学习出处:https://hu3sky.github.io/2019/02/07/hctf/

nodeprep.prepare()
这个函数会把大写转换为小写 并且nodeprep.prepare()会做如下转换
假如有一个字符 第一次调用函数时会造成ᴬ->A,第二次调用时会A->a

解题

学习出处:

https://www.cnblogs.com/wangtanzhi/p/11861820.html

https://blog.csdn.net/weixin_44677409/article/details/100733581

1.unicode欺骗

注册一个ᴬdmin账号 此时第一次调用nodeprep.prepare()账号变为
Admin() 此时进行登录,再次调用nodeprep.prepare(),页面显示Hello Admin,此时应已变成admin,修改密码再次调用,修改admin密码 再进行登录

2.flask session伪造

学习出处:https://www.leavesongs.com/PENETRATION/client-session-security.html

通过这个工具(https://github.com/noraj/flask-session-cookie-manager)可以加密解密flask中session,大概看了一下具体的原理(因为太菜了,还没太看懂呜呜呜呜

大概分为这几步:

  1. json.dumps 将对象转换成json字符串,作为数据
  2. 如果数据压缩后长度更短,则用zlib库进行压缩
  3. 将数据用base64编码
  4. 通过hmac算法计算数据的签名,将签名附在数据后,用“.”分割

这里还有师傅写的解密的脚本,都记录一下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
#!/usr/bin/env python3
import sys
import zlib
from base64 import b64decode
from flask.sessions import session_json_serializer
from itsdangerous import base64_decode

def decryption(payload):
payload, sig = payload.rsplit(b'.', 1)
payload, timestamp = payload.rsplit(b'.', 1)

decompress = False
if payload.startswith(b'.'):
payload = payload[1:]
decompress = True

try:
payload = base64_decode(payload)
except Exception as e:
raise Exception('Could not base64 decode the payload because of '
'an exception')

if decompress:
try:
payload = zlib.decompress(payload)
except Exception as e:
raise Exception('Could not zlib decompress the payload before '
'decoding the payload')

return session_json_serializer.loads(payload)

if __name__ == '__main__':
print(decryption(sys.argv[1].encode()))

拿到secret_key以后,伪造session重发即可拿到flag

还根据师傅的博客学习到利用解密session绕过验证码, 不过这道题里的session直接给了验证码hh

3.条件竞争

threading.Thread类

创建线程thread=threading.Thread(target=function_name, args=(function_parameter1, function_parameterN))

function_name: 需要线程去执行的方法名

args: 线程执行方法接收的参数,该属性是一个元组,如果只有一个参数也需要在末尾加逗号。

启动创建的线程thread.start()

requests模块

不带参数get请求r=requests.get('')

带参数的get请求r=requests.get('',params=url_params)

其中字典传递参数url_params={‘key’:’value’}

post请求r=requests.post('')

带参数的post请求r=requests.post(url,data=params)

params同样为字典传递参数

r=requests.post(url,data=params)

img

r.text输出结果:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
{
"args": {},
"data": "",
"files": {},
"form": {
"key1": "value1",
"key2": "value2"
},
"headers": {
"Accept": "*/*",
"Accept-Encoding": "gzip, deflate",
"Connection": "close",
"Content-Length": "23",
"Content-Type": "application/x-www-form-urlencoded",
"Host": "httpbin.org",
"User-Agent": "python-requests/2.18.1"
},
"json": null,
"origin": "183.14.133.88",
"url": "http://httpbin.org/post"
}
  • 本文标题:admin[hctf 2018]
  • 本文作者:y4ny4n
  • 创建时间:2020-09-16 21:20:45
  • 本文链接:https://y4ny4n.cn/2020/09/16/2018/
  • 版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!