0x00 Weak Session IDs
一般密码、证书等认证方式只用于登录的时候,或者需要付款等敏感操作时,平时访问网站的页面不可能每次都要输入密码认证。所以在登录完成以后,需要用别的方法来确认登录状态。
可以使用cookie,但cookie是保存在客户端的,也就是可以被篡改利用,非常不安全。
使用Session ID则是保存在服务端,一般会设置一定时效,并以cookie的形式发给用户,用户在Session ID时效内,携带对应的Session ID值去访问,就相当于该用户登录状态的正常页面访问。
但是当Session ID设置不合理,很容易破解,那么黑客就可以利用规律,在Session ID有效期内,携带受害者的Session ID去访问,即可以受害者的身份登录访问,而不需要账号密码。
DVWA中只是涉及弱Session ID的计算方式,并没有做Session ID判断错误时有什么反馈,不涉及利用Session ID去攻击。所以练习的时候只研究其生成原理并分析为何是弱Session ID。
0x01 Low
源码分析
<?php
$html = "";
if ($_SERVER['REQUEST_METHOD'] == "POST") {
if (!isset ($_SESSION['last_session_id'])) {
$_SESSION['last_session_id'] = 0;
}
$_SESSION['last_session_id']++;
$cookie_value = $_SESSION['last_session_id'];
setcookie("dvwaSession", $cookie_value);
}
?>
源码中的Session ID是从0开始发送的,并且每次请求检查后追加1,这样我们只需要按照规律在访问的时候按顺序累加1,即可与服务器存储的Session ID值对应上,从而通过认证。
解题思路
首先点击generate,此时便生成了Session ID,然后接下来开始Burpsuite拦截,可以看到HTTP头如下:
POST /dvwa/vulnerabilities/weak_id/ HTTP/1.1
Host: 127.0.0.1:9000
User-Agent: Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:79.0) Gecko/20100101 Firefox/79.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
Accept-Language: zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2
Accept-Encoding: gzip, deflate
Content-Type: application/x-www-form-urlencoded
Content-Length: 0
Origin: http://127.0.0.1:9000
Connection: close
Referer: http://127.0.0.1:9000/dvwa/vulnerabilities/weak_id/
Cookie: dvwaSession=1; security=low; PHPSESSID=q9vdhmprkt3dtd8ttlrlfd0i3d
Upgrade-Insecure-Requests: 1
其中dvwaSession=1即为Session ID,在服务器保存着的值也是为1,就算自己手动修改为100,再发送,依旧是以服务器端的Session ID为主,继续自加1返回,也就是会在收到HTTP响应中dvwaSession=2。
我们也可以利用burpsuite的Sequencer进行分析,抓包发送到Sequencer模块,点击Start live capture,等待持续抓包,也可以手动Stop中断,然后Analyze now。
分析完成就可以看到Summary框下Overall result的结果中显示
The overall quality of randomness within the sample is estimated to be:extremely poor.
poor表示Session ID设置得比较弱,容易被破解。
0x02 Medium
源码分析
<?php
$html = "";
if ($_SERVER['REQUEST_METHOD'] == "POST") {
$cookie_value = time();
setcookie("dvwaSession", $cookie_value);
}
?>
源码中直接用时间作为Session ID,看起来会稍微复杂一点,但经过连续的收集就可以发现其中的规律了,所以也是弱Session ID。
解题思路
依旧是Generate生成Session ID后,然后用Burpsuite拦截,再次点击Generate,转到Repeater模块发送,可以看到响应包HTTP头中携带了dvwaSession=1605957581,看着是没有规律的字符串,实际上就是时间戳,也是可以用python转化成时间
import time
time_tuple = time.localtime(1605957581)
result = time.strftime("%Y-%m-%d %H:%M%S", time_tuple)
即可得到结果为:
"2020-11-21 19:19:41"
Sequencer模块分析结果依旧是poor。
0x03 High
源码分析
<?php
$html = "";
if ($_SERVER['REQUEST_METHOD'] == "POST") {
if (!isset ($_SESSION['last_session_id_high'])) {
$_SESSION['last_session_id_high'] = 0;
}
$_SESSION['last_session_id_high']++;
$cookie_value = md5($_SESSION['last_session_id_high']);
setcookie("dvwaSession", $cookie_value, time()+3600, "/vulnerabilities/weak_id/", $_SERVER['HTTP_HOST'], false, false);
}
?>
这里用到了md5哈希,将哈希结果作为Session ID,并且设置了有效期为1小时(3600s),规定cookie路径为/vulnerabilities/weak_id/,规定cookie只能在访问当前服务器的主机时使用,最后两个false是指关闭secure和httponly。
看起来很那破解,但用于哈希的数是非常简单的从0开始累加1,很容易就被md5碰撞破解,所以也不是最安全的。
解题思路
点击Generate生成Session ID后,设置Burpsuite代理拦截,转到Repeater模块发送,可以看到响应包中cookie携带dvwaSession=c4ca4238a0b923820dcc509a6f75849b,就是Session ID值,是数字1的哈希值。
可以直接将md5值拿到md5破解网站去破解,即可得到原来的md5之前的值为1。 md5破解网站如: https://www.sojson.com/encrypt_md5.html
用Sequencer模块分析可以看到是Excellent,表示还是比较强的,但对有经验的攻击者还是可能被破解。
0x04 Impossible
源码分析
<?php
$html = "";
if ($_SERVER['REQUEST_METHOD'] == "POST") {
$cookie_value = sha1(mt_rand() . time() . "Impossible");
setcookie("dvwaSession", $cookie_value, time()+3600, "/vulnerabilities/weak_id/", $_SERVER['HTTP_HOST'], true, true);
}
?>
源码中用mt_rand()函数生成随机种子(一串字符串),与时间戳、盐(字符串“Impossible”)拼接,使用更难破解的sha1哈希算法对拼接字符串进行哈希,然后设置有效期、规定cookie使用路径、规定使用服务器主机范围,并且打开cookie的secure属性(限定只能https协议访问,不能http)、httponly属性(js脚本不能读取cookie)。
这已经是很难破解的了,复杂的Session ID生成规则和较难撞库的算法,限制cookie有效期和使用范围,并且打开secure和httponly属性,很难造成xss攻击。
解题思路
sequencer模块分析也是Excellent,难以破解。
0x05 小结
防御方法:
- 使用随机的Session ID。
- 可以是sha1等复杂的哈希算法。
- 待哈希的值可以是时间戳、随机种子、加盐的字符串拼接组合。
- 限定cookie使用范围,包括有效期、能访问的域名或主机、能访问的网站路径。
- 打开secure、httponly属性,防止XSS攻击。