-
2021-03-23 11:31:54
PHP crypt()函数可以完成基本的加密功能:
string crypt (string input_string [, string salt])
这一函数完成被称作单向加密的功能,也就是说,它可以加密一些明码,但不能够将密码转换为原来的明码。单向加密的口令一旦落入第三方人的手里,由于不能被还原为明文,因此也没有什么大用处。在验证用户输入的口令时,用户的输入采用的也是单向算法,如果输入与存储的经加密后的口令相匹配,则输入的口令一定是正确的。
这个函数的input_string参数是需要加密的字符串,第二个参数salt是一个位字串,它能够影响加密的暗码,进一步地排除被称作预计算攻击的可能性。缺省情况下,PHP使用一个2个字符的DES干扰串,如果你的系统使用的是MD5 ,它会使用一个12个字符的干扰串。我们可以通过执行下面的命令发现系统将要使用的干扰串的长度:
print "系统使用的干扰串的长度是:". CRYPT_SALT_LENGTH;
crypt()支持四种算法,下面是它支持的算法和相应的salt参数的长度:
[注:以下用表格]
算法 Salt长度
CRYPT_STD_DES 2-character (默认)
CRYPT_EXT_DES 9-character
CRYPT_MD5 12-character beginning with $1$
CRYPT_BLOWFISH 16-character beginning with $2$
如何将PHP的数据加密功能应用于用户验证?
我们用crypt()实现用户身份验证。比如我们用一段PHP程序限制对一个目录的访问,只允许注册用户访问这一目录。我们把资料存储MySQL数据库的一个表(这个数据表名为members)中:
复制代码 代码如下:
mysql>CREATE TABLE members (
->username CHAR(14) NOT NULL,
->password CHAR(32) NOT NULL,
->PRIMARY KEY(username)
->);
然后,我们可以输入用户的数据到该表中:
用户名 密码
Tom keloD1C377lKE
John ba1T7vnz9AWgk
Bill paLUvRWsRLZ4U
这些加密的口令对应的明码分别是Tom、John和Bill。我们将根据口令的前二个字母创建干扰串:
复制代码 代码如下:
<?php
$enteredPassword.
$salt = substr($enteredPassword, 0, 2);
$userPswd = crypt($enteredPassword, $salt);
// $userPswd然后就和用户名一起存储在MySQL 中
crypt()和Apache的口令-应答验证系统的应用
$host = "localhost"; //主机
$username = "Tom"; //用户名
$passwd = "Hello world"; //密码
$db = "users"; //数据库名
// 设置是否通过验证标志,默认为否
$authorization = 0;
// 提示用户输入帐号和密码
if (isset($PHP_AUTH_USER) && isset($PHP_AUTH_PW)){
mysql_pconnect($host, $username, $passwd) or die("不能连接到MySQL服务器!");
mysql_select_db($db) or die("不能选择数据库!");
// 进行加密
$salt = substr($PHP_AUTH_PW, 0, 2);
$encrypted_pswd = crypt($PHP_AUTH_PW, $salt);
//SQL查询语句
$query = "SELECT username FROM members WHERE username = \'$PHP_AUTH_USER\' AND password = \'$encrypted_pswd\'";
// 执行查询
if (mysql_numrows(mysql_query($query)) == 1) {
$authorization = 1;
}
}
if (! $authorization){
header(\'WWW-Authenticate: Basic realm="用户验证"\');
header(\'HTTP/1.0 401 Unauthorized\');
print "无法通过验证";
exit;
}else {
print "已经加密";
}
?>
在缺省状态下使用的 crypt()并不是最安全的,所以如果需要较高的安全性能,就需要其他更好的算法,比如md5(),这一函数使用MD5散列算法。
如何通过MD5方式进行加密?
PHP中通过MD5方式加密的函数有md5(),它的一个作用是混编。
一个混编函数可以将一个可变长度的信息变换为具有固定长度被混编过的输出,也被称作"信息文摘",这是十分有用的,因为 一个固定长度的字符串可以用来检查文件的完整性和验证数字签名与用户身份。PHP内置的md5()混编函数将把一个可变长度的信息转换为128位(32个字符)的信息文摘。混编的一个有趣的特点是:不能通过分析混编后的信息得到原来的明码,因为混编后的结果 与原来的明码内容没有依赖关系。即便只改变一个字符串中的一个字符,也将使得MD5混编算法计算出二个截然不同的结果。我们首先来看下表的内容及其相应的结果:
使用md5()混编字符串
复制代码 代码如下:
<php
$input = "Hello,PHP world!";
$output = md5($input);
print "输出: $output ";
?>
结果:
输出: 7996b5e0804042fd531907a4900f190e
注意,结果的长度为32个字符。我们把$input的值稍微改变一下:
使用md5()对一个稍微变化的字符串进行混编
复制代码 代码如下:
<?php
$input = "Hello,PHP World!";
$output = md5($input);
print "输出: $output ";
?>
结果:
hash2: f0456d48ed06a5c35b1e42561fa7a016
可以发现,尽管二个结果的长度都是32个字符,但明文中一点微小的变化使得结果发生了很大的变化,我们可以利用这个特点来检查数据中微小变化。
更多相关内容 -
Android md5加密与php md5加密一致详解
2021-01-04 21:36:43在Android开发过程中加密密码常常采用md5加密方式,然而如果服务器端采用PHP开发(php采用md5加密很简单,直接md5($str)),很可能与Java的md5加密不一致。以下方法是md5加密与php一致的源码: import java.math.... -
php结合md5实现的加密解密方法
2020-10-22 22:32:26主要介绍了php结合md5实现的加密解密方法,涉及PHP字符串操作及加密解密算法实现技巧,需要的朋友可以参考下 -
php实现MD5加密16位(不要默认的32位)
2020-12-18 19:57:02使用substr函数截取: 复制代码 代码如下:substr(md5(“admin”),8,16);... 您可能感兴趣的文章:Android md5加密与php md5加密一致详解node.JS md5加密中文与php结果不一致的解决方法php进行md5加密简单实例方法 -
CTF:PHP MD5函数0E绕过漏洞
2021-06-01 18:02:49CTF:PHP MD5函数0E绕过漏洞 作者:高玉涵 博客:blog.csdn.net/cg_i 时间:2021.6.1 8:43 背景 昨天参加了一场CTF线上赛,面对行业内的安全强队,比赛成绩相差巨大。通过这次比赛,找到了差距,找到了不足,...CTF:PHP MD5函数0E绕过漏洞
作者:高玉涵
博客:blog.csdn.net/cg_i
时间:2021.6.1 8:43
背景
昨天参加了一场CTF线上赛,面对行业内的安全强队,比赛成绩相差巨大。通过这次比赛,找到了差距,找到了不足,更增长了知识。子曰:“学而不思则罔,思而不学则殆。”计划将经后每次比赛,解题过程中的困惑、思路、整理后分享出来,以达起到巩固知识,也便于帮助有需要的人。因个人能力所限,文中难免会有错误,不妥之处还请批评指正。
赛题源码
本职工作极少接触CTF相关知识,初看此题直接是懵的。代码清晰而简单这里不表,唯一让我困惑的是if($c == md5($c))这一条语句,分析可知当$c==md5($c) 即可拿到Flag。心中诧异:这怎么可能!加密前后的值要相等?逻辑上不通啊!难道要用到md5撞库?这种概率也太小了,假设真的存在这种可能,即使不考虑其巨大的计算量,稍微对加密原理有些常识的人就应知道,世上根本不会存在“加密前后的值要相等”(这还算得上加密码?)我走进了知识盲区,走进了思维的死胡同。
在长时间的懵圈后,我逐渐冷静下来并断定,主办方不可能出道需耗时100年(我电脑的计算力)才能得出的答案的题。直觉告诉我突破口应是md5()这个函数,它可能存在我不知道的漏洞,确定方向后接下来就是对它发起进攻。
MD5算法
首先还是说一下什么是MD5算法,MD5全名消息摘要算法(Message-Digest Algorithm 5),是一种密码散列函数,可以产生一个128位(16字节)的哈希值(hash value),用于确保信息传输的完整一致性,它的基础原理就是将数据预算变为另一固定长度的值。
MD5的特点
长度一致性:任意长度的数据,计算出来的哈希值长度都是固定的128位。
不对称性:从原数据计算哈希值十分容易,但是知道哈希值去碰撞原数据十分困难。
MD5算法的基本原理
这里采用网上一个大佬绘制的图。
MD5算法的安全问题
其实不仅是MD5,任何一个hash函数,都有被碰撞的可能,所谓碰撞,就是输入不同的值Value和Value得到相同的hash值,这其实不难证明,MD5生成的hash值是由128位组成的,而它必然是一个有限集合,而我们的输入数据是一个无限集,一个无限集映射到有限集上,必然存在两个或多个无限集中的元素映射到同一有限集元素的情况。
PHP MD5中的安全问题
相等操作符:用来比较两个值,测试其相等性。
PHP中有两个相等操作符“==”和“===”。$a == $b,如果类型转换后$a和$b相等,则输出true。$a === $b,如果$a和$b相等,并且类型也相同,则输出true。
PHP是弱类型语言,所以有时会根据引用变量时所处的环境,将变量自动转换为最适合的类型。下面给出例子:
$total = “45 fire engines”; $incoming = 10; $total = $incoming + $total; // $total = 55
因为最前面的$total字符串以整数值开头,所以计算中就使用了这个值。如果数学计算中用到包含e或E(表示科学计数法)的字符串,这个字符串将作为浮点数进行计算。
有了上述知识我们就可以通过构造特别参数,将原本不相等的if判断相等。原理:在进行“==”判断的时候,会先将字符串类型转化成相同再比较。转换的规则为,若该字符串以合法的数值开始,则使用该值,否则其值为0。因此,根据这一点,可以遍历出一个字符串,其MD5加密前后都是'0e'开头且后面纯数字,这样就能保证值是相等。
Python写的暴库代码(注:2020.6.4修改,原我写的多进程代码存在BUG,这里引用了网上的一段代码)
import hashlib def md5_enc(s): m = hashlib.md5() m.update(str(s).encode('utf-8')) return m.hexdigest() if __name__ == '__main__': result = [] for i in range(0, 9999999999): i = '0e' + str(i) enc = md5_enc(i) print(i+" md5 is "+enc) # md5值前两位为0e if enc[:2] == "0e": # md5值0e后为纯数字 if enc[2:].isdigit(): result.append(i) print("Got Result:"+i) break
跑了40分钟得到一个值:0e215962017
MD5 == 0e291242476940776845150308577824
构造URL:http://1.1.1.1/2.php?a=1&b=0&c=0e215962017,成功取得FLAG。如下图。
CTF意义所在
CTF题都是由业内专家命题,往往凝聚着他们多年积累出来的技能,是信息安全基本概念、攻防技术、技巧浓缩和提炼。能够给不能层次的人在技术上带来提高。除此之外,高质量得CTF题都没法直接使用现成工具解出,一般需要在理解基本原理的基础上,自己编写代码来求解,这个过程会加深和巩固计算机基础知识,通过CTF大赛和国内外强队比拼,增长了知识,开阔了视野,提升了能力。
-
解决.net 调用php 接口 md5加密不一致问题
2018-07-13 15:15:00解决.net 调用php 接口时生成签名用到 md5加密,net与PHP生成密文不一致问题 -
php代码-php md5 运算
2021-07-16 14:51:36php代码-php md5 运算 -
php md5下16位和32位的实现代码
2020-10-30 12:11:24PHP里MD5加密的16位和32位实现代码,在网上一搜也有不少人有这方面的困惑,后来找到一个解决办法,是正确的,就记录下来 -
PHP实现的MD5结合RSA签名算法实例
2021-01-20 01:35:10本文实例讲述了PHP实现的MD5结合RSA签名算法。分享给大家供大家参考,具体如下: <?php class Md5RSA{ /** * 利用约定数据和私钥生成数字签名 * @param $data 待签数据 * @return String 返回签名 */ ... -
解决java md5和php md5 结果不一致问题
2018-11-22 16:32:39java md5的输出结果和php md5的输出结果不一致。 二、解决代码 java import java.security.MessageDigest; public class md5Test { /** * @param input 输入 * @return 返回16个字节 * @throws Exception ...一、遇到问题
java md5的输出结果和php md5的输出结果不一致。
二、解决代码
java
import java.security.MessageDigest; public class md5Test { /** * @param input 输入 * @return 返回16个字节 * @throws Exception */ public static byte[] originMD5(byte[] input) throws Exception { MessageDigest md5 = MessageDigest.getInstance("MD5"); byte[] out = md5.digest(input); return out; } /** * @param input 输入 * @return 返回16个字节 * @throws Exception */ public static byte[] MD5(byte[] input) throws Exception { String str = new String(input, 0, input.length); //创建MD5加密对象 MessageDigest md5 = MessageDigest.getInstance("MD5"); // 进行加密 md5.update(str.getBytes()); //获取加密后的字节数组 byte[] md5Bytes = md5.digest(); String res = ""; for (int i = 0; i < md5Bytes.length; i++) { int temp = md5Bytes[i] & 0xFF; // 转化成十六进制不够两位,前面加零 if (temp <= 0XF) { res += "0"; } res += Integer.toHexString(temp); } return res.getBytes(); } public static void main(String[] args) throws Exception { byte[] data = {0x4C, 0x2B, 0x3E, 0x5A, 0x26, 0x3A, 0x3C, 0x18}; byte[] md5Data = MD5(data); String strMd5Key = new String(md5Data, 0, md5Data.length); System.out.println(strMd5Key); } }
php
<?php /** * Created by PhpStorm. * User: xianbin * Date: 2018/11/20 * Time: 18:52 */ class testhexstring { public function arr2Form($arr){ $tempStr = ""; foreach ($arr as $key=>$value){ $tempStr .=$key."=".$value."&"; } return substr($tempStr, 0, strlen($tempStr) -1); } public function form2Arr($str){ $arr = array(); $array=explode('&', $str); foreach ($array as $key){ $tempInfo=explode('=', $key); $arr[$tempInfo[0]] = $tempInfo[1]; } return $arr; } /** * 将字节数组转化为String类型的数据 * @param $bytes 字节数组 * @param $str 目标字符串 * @return 一个String类型的数据 */ public function toStr($bytes) { $str = ''; foreach($bytes as $ch) { $str .= chr($ch); } return $str; } /** * 转换一个string字符串为byte数组 * @param $str 需要转换的字符串 * @param $bytes 目标byte数组 */ public function getbytes($str) { $len = strlen($str); $bytes = array(); for($i=0;$i<$len;$i++) { if(ord($str[$i]) >= 128){ $byte = ord($str[$i]) - 256; }else{ $byte = ord($str[$i]); } $bytes[] = $byte ; } return $bytes; } } $test = new testhexstring(); $data = array(0x4C, 0x2B, 0x3E, 0x5A, 0x26, 0x3A, 0x3C, 0x18); $strData = $test->toStr($data); $md5Data = md5($strData); echo 'md5 origin is: ',$md5Data,PHP_EOL; ?>
结果:
-
php md5加密 php md5加密
2010-11-16 10:13:09php md5加密php md5加密php md5加密php md5加密 -
PHP md5和JS hex_md5与特殊字符的结果不匹配
2019-03-27 06:07:44<p>I have tried hashing a string in PHP7 using MD5 and the same in Javascript, but the results are different.. can someone explain me how to get this matched? <pre class="lang-php prettyprint-... -
MD5withRSA签名和验证签名(php>5.5)
2017-12-06 23:50:10MD5withRSA签名和验证签名(php>5.5)MD5withRSA签名和验证签名(php>5.5) -
php结合md5的加密解密算法实例
2020-10-21 09:58:44主要介绍了php结合md5的加密解密算法,结合实例形式分析了php结合md5实现自定义密钥的加密解密算法相关实现技巧,需要的朋友可以参考下 -
PHP中MD5函数使用实例代码
2020-10-30 10:36:23PHP中有着丰富的函数,MD5加密函数就是其中之一。 -
PHP中md5()函数的用法讲解
2020-10-17 05:50:32今天小编就为大家分享一篇关于PHP中md5()函数的用法讲解,小编觉得内容挺不错的,现在分享给大家,具有很好的参考价值,需要的朋友一起跟随小编来看看吧 -
php进行md5加密简单实例方法
2020-10-16 08:48:25在本文里小编给大家整理了一篇非常实用的php如何进行md5加密知识点内容,有需要的朋友们可以参考下。 -
node.JS md5加密中文与php结果不一致的解决方法
2021-01-20 07:21:32因项目需要,需要Node.js与PHP做接口调用,发现node.js对中文使用md5加密与php对中文md5加密的结果不同。 PHP <?php $str = '程序员'; echo $str.' md5:'.md5($str); ?> 输出: 程序员 md5:72d9adf4944f23e5... -
php md5()漏洞
2017-08-10 16:21:40md5()漏洞题目描述
一个网页,不妨设URL为
http://haha.com
,打开之后是这样的if (isset($_GET['a']) and isset($_GET['b'])) { if ($_GET['a'] != $_GET['b']) { if (md5($_GET['a']) === md5($_GET['b'])) { echo ('Flag: '.$flag); }else { echo 'Wrong.'; } } }
根据这段代码,可以看出;
- 使用GET方式提交参数,可以直接在URL里面改,不用写POST请求
- GET里面必须包含a,b两个参数
- a!=b,这里的不等是严格的value上的不等,而不是
!==
引用上的不等 - a和b的md5必须相等
- 这段代码是无论如何都要返回的,如果答案错误,先返回wrong,再返回这段代码。
如果提交
http://haha.com?a=3&b=2
,返回wrong
如果提交http://haha.com?a=3&b=3
,跟没带参数一样,因为没有进入到那层判断中去
问,怎么提交才能得到flag预备知识
PHP在处理哈希字符串时,会利用”!=”或”==”来对哈希值进行比较,它把每一个以”0E”开头的哈希值都解释为0,所以如果两个不同的密码经过哈希以后,其哈希值都是以”0E”开头的,那么PHP将会认为他们相同,都是0。
常见的payload有QNKCDZO 240610708 s878926199a s155964671a s214587387a s214587387a sha1(str) sha1('aaroZmOk') sha1('aaK1STfY') sha1('aaO8zKZF') sha1('aa3OFF9m')
同时MD5不能处理数组,若有以下判断则可用数组绕过
if(@md5($_GET['a']) == @md5($_GET['b'])) { echo "yes"; } //http://127.0.0.1/1.php?a[]=1&b[]=2
题解
URL可以传递数组参数,形式是
http://haha.com?x[]=1&x[]=2&x[]=3
,这样就提交了一个x[]={1,2,3}的数组。
在PHP中,MD5是不能处理数组的,md5(数组)会返回null,所以md5(a[])==null,md5(b[])==null,md5(a[])=md5(b[])=null,这样就得到答案了。http://butian.secbox.cn/flag.php?a[]=1&b[]=2
返回结果Flag: flag{1bc29b36f623ba82aaf6724fd3b16718} if (isset($_GET['a']) and isset($_GET['b'])) { if ($_GET['a'] != $_GET['b']) { if (md5($_GET['a']) === md5($_GET['b'])) { echo ('Flag: '.$flag); }else { echo 'Wrong.'; } } }
我说
一开始我还以为要找到两个md5相同的字符串,百度一番不曾找到。只找到一个fastcoll.exe文件碰撞器,内容都是二进制的,不是字符串。
直接搜索PHP、MD5,就发现原来这题跟密码学半毛钱关系没有,只是简简单单的PHP语言漏洞。
于是余有叹焉,PHP是地球上最垃圾的语言,一方面养活着一大群抱残守缺的程序员,另一方面也养活着一批PHP安全方面的专家。程序员这不是自娱自乐吗?用Java哪来的这么多奇葩问题,强类型的安全性自然而然,一切都是确定的,弱类型带来了太多的可能性。脚本写起来虽然方便,却最好只在本地使用而不要放在易受攻击的地方。参考资料
-
C#与PHP的md5计算结果不同的解决方法
2020-08-31 22:20:07今天在用C#接入我的登录api发现了一个问题,登陆的时候无论如何都会出现用户名和密码错误的问题,后来通过查找排除找的了问题的原因是因为C#与PHP的md5计算结果不同导致的,下面就来看看如何解决这个问题吧。 -
解决c# md5与php md5加密不一致的问题(md5(unicode))
2019-04-15 23:03:00首先是登陆,客户直接添加的用户密码采用了md5加密方式,我在app登陆的时候取出数据进行验证,验证密码的时候,一直提示密码不正确,于是我打印出php md5('123456') :md5: e10adc3949ba59abbe56e057f20f883e .... -
android md5加密与php md5加密一致
2017-02-24 14:13:35在Android开发过程中加密密码常常采用md5加密方式,然而如果服务器端采用php开发(php采用md5加密很简单,直接md5($str)),很可能与java的md5加密不一致。以下方法是md5加密与php一致的源码: import java.math.... -
对接php md5输出byte数组问题
2019-08-07 14:13:06今天由于业务需求和php同学对接了... global_secretKey=new SecretKeySpec(MD5.getMD5Byte(Key), KEY_ALGORITHM); global_cipher = Cipher.getInstance(CIPHER_ALGORITHM_ECB); global_cipher.init(Cipher....