弱密码主要是由于系统或用户的密码没有达到一定的复杂程度的密码或使用较弱的加密算法产生的密码,恶意攻击者可以通过猜测、彩虹表、cookie、配置文件、注册表、网络截获等手段可以破解的密码。
CWE-261对应该类缺陷,对应OWASP 2004年十大类别A8-不安全存储,SFP二级集群的弱密码学。这些涉及到凭证管理、不受保护的凭证存储、配置文件中的空密码、使用硬编码密码、配置文件中的密码、权限和访问控制、最低权限违规、授权不当、证书验证、加密问题、使用不充分的随机值等、使用简单编码隐藏的Miami不会保护密码。当密码以纯文本形式存储在应用程序的属性或配置文件中时,会出现密码管理问题。程序员可以通过使用编码功能(例如base 64编码)来模糊密码来尝试解决密码管理问题,但这种努力不能充分保护密码。“crypt”系列函数使用弱加密算法(MD5、SHA-1),应该避免使用。它可能存在于某些项目中以实现兼容性。
(1)网络抓包
如果应用程序不使用安全通道(如SSL)来交换敏感信息,则可以访问网络流量的攻击者从连接中嗅探数据包并发现数据。通过Fiddler、Wireshark、tcpdump等攻击就可以抓取http报文,得到敏感信息。需要物理访问敏感数据传输到的网络的某些部分。此访问通常位于用户连接到网络的位置附近(例如公司网络上的同事),但可以位于从用户到终端服务器的路径的任何位置。
(2)保存在cookie
此代码将用户的登录信息写入cookie,以便用户以后不必再次登录。
示例1,语言: PHP
function persistLogin($ username,$ password){
$ data = array(“username”=> $ username,“password”=> $ password);
setcookie(“userdata”,$ data);
}
代码将用户的用户名和密码以明文形式存储在用户计算机上的cookie中。如果用户的计算机被攻击者攻陷,则会显示用户的登录信息。即使用户的计算机没有受到攻击,这种弱点与跨站点脚本相结合也可能允许攻击者远程复制cookie。
示例2,语言:Java
Java示例代码:
<%
String[] cookies = request.getParameterValues("isUseCookie");//values这里是获取一串数据
if(cookies!=null&&cookies.length>0)//如果数组不为空且大于0,说明被选中了
{
String username= request.getParameter("username");
String password = request.getParameter("password");
Cookie name = new Cookie("username", username);
Cookie pwd = new Cookie("password", password);//将index页面文本框的值存入cookie对象
name.setMaxAge(86400);
pwd.setMaxAge(86400);//设置生效时间,单位是秒 86400秒为1天
response.addCookie(name);
response.addCookie(pwd);//返回cookie对象
//System.out.println(username);
}
(3)存储在缓冲区
以下代码尝试建立连接,读入密码,然后将其存储到缓冲区。
示例3,语言: C
server.sin_family = AF_INET; hp = gethostbyname(argv[1]);
if (hp==NULL) error("Unknown host");
memcpy( (char *)&server.sin_addr,(char *)hp->h_addr,hp->h_length);
if (argc < 3) port = 80;
else port = (unsigned short)atoi(argv[3]);
server.sin_port = htons(port);
if (connect(sock, (struct sockaddr *)&server, sizeof server) < 0) error("Connecting");
...
while ((n=read(sock,buffer,BUFSIZE-1))!=-1) {
write(dfd,password_buffer,n);
...
虽然连接成功,但连接未加密,发送到服务器或从服务器接收的所有敏感数据都可能被恶意者截获。
(4)属性文件中存储用户名和密码
示例4,语言:Java
...
属性prop = new Properties();
prop.load(new FileInputStream(“config.properties”));
String password = Base64.decode(prop.getProperty(“password”));
DriverManager.getConnection(url,usr,password);
...
这段代码可以运行,但是任何有权限访问config.properties的人都可以读取密码,并轻易确定是否为base64位编码。如果是内部员工,则可以使用这个密码进入系统。
(5)从注册表中读取密码,并使用密码创建新的网络凭证
示例5,语言:C#
...
string value = regKey.GetValue(passKey).ToString();
byte [] decVal = Convert.FromBase64String(value);
NetworkCredential netCred = newNetworkCredential(username,decVal.toString(),domain);
...
此代码将成功运行,但有权访问用于存储密码的注册表项的任何人都可以读取密码的值。如果一个具有敌意的员工可以访问这些信息,他们可以使用它来进入系统。
缓解措施:密码应该至少128位长度的秘钥加密,以全包足够的安全。
(完)