python jinja2初见

吸取了长城杯的教训,学习python-web迫在眉睫。

正常难度的python_template_injection,由于现在没学面向对象,理解原理比较困难,所以先使用简单版复现;并附上正常版的常用payload。

part1:操作

  服务端代码:

  

   测试payload1:

 

   效果:

      网页回显无意义。

  测试payload2:

   效果:

      网页回显无意义。

  测试payload3:

 网页无回显。

 

 

网页无回显。

 本地回显同上;同样的回显也出现在网页。

 

part2:浅层原理

   name=request.args.get('name','guest')获取名为name的get参数;若无该参数,则将name赋值为'guest'(可能不准确,但测试的是这个效果)

    jinja2是一个灵活的模板系统;模板可以理解为渲染。(反正我都不知道是啥)

      在jinja2中,控制结构需要以{% %}包裹,变量取值需要以 {{}}包裹。

      所以,我们在payload加入这些语法后,jinja2就不会把这些东西渲染为简单的字符串,而是去执行。

      要想在jinja2模板中执行python代码,需要在模板环境中注册函数。上述代码中,为降低难度,已经将os模块注册(t.globals['os']=os)

        os.system()将字符串转化成命令在服务器运行。

        字符串传入时,会被url编码,但测试发现&符号不会被编码;故需要用%26替代。(测了好久才发现问题在这o(╥﹏╥)o)

        每个system语句执行时均会创建一个子进程,system语句之间不具有连续性。若想连续执行,需要用【;】分割字符串

   

  在网上查阅资料知,system返回值是状态码0,1,2;popen可以返回输出内容。

  但实际测试的时候,system返回过256、512;popen还报错。

    最后通过os.popen().read()解决了问题。

  

一般的,服务端代码不会import os。

故需构造payload:【任意命令执行】

{{__class__.__mro__[x(须获得object类)].__subclasses__()[71].__init__.__globals__['os'].popen('任意系统命令').read()}}

 

参考:https://xuanxuanblingbling.github.io/ctf/web/2019/01/02/python/

posted @ 2021-09-23 10:44  hiddener  阅读(135)  评论(0编辑  收藏  举报