"I am {MyName},he is {HisName}".format(MyName="aa",HisName="bb")
这个语句的输出是I am aa,he is bb,这种语句可以在format函数的参数通过key来赋值。
"I am {},he is {}".format("a","b")
这个语句的输出是I am a,he is b,这样的用法会让大括号与format的参数一一对应。
当大括号与format的参数不能一一对应的时候便会报错,例如:
"I am {0},he is also {0}".format('a')"I am {0},he is also {1}".format('a')
前者会输出I am a,he is also a,而后者会报错tuple index out of range。
这些format函数的基本用法并不是导致格式化字符串漏洞的根源,查看下列代码:
"first {0[1]}, second {0}".format(['a','b'])
输出为first b, second ['a', 'b'],可见当format函数的参数是一个列表时,可以通过用方括号添加索引的方式来获取列表的值。同样的,这种用法也可以用在类的属性上,比如以下代码会输出字符串a的内置属性__class__:
print("{0.__class__}".format('a'))
输出结果是
一般利用
python的格式化字符串的利用与沙盒逃逸或者python SSTI很相似,但format与后两者的区别在于它只能读取属性而不能执行方法,这就限制了格式化字符串的利用与攻击链的构造。举个例子,python SSTI中可以通过'a'.__class__.__base__.__subclasses__()[12]来获取任意类,但是由于format函数无法执行__subclasses__()这样的方法,直接把这种payload套进格式化字符串的利用中会报错type object 'object' has no attribute '__subclasses__()'。
在与队友讨论时我们用的测试代码简化如下:
from secret.secret import secret classAppendStr(object):def__init__(self, message = 'test'): self.message = message def__str__(self):return self.message deftest(): s = input("test\n") t = s + " by the way {0}" print(t.format(AppendStr())) while(1): test()
from django.http import HttpResponse defindex(request): template = 'Hello {user}, This is your email: ' + request.GET.get('email')return HttpResponse(template.format(user=request.user))