Fork me on GitHub
Suzf  Blog

Tag PHP

密码散列安全

节选自 PHP manual

相关链接  Wooyun

本部分解释使用散列函数对密码进行安全处理背后的原因, 以及如何有效的进行密码散列处理。

  1. 为什么需要把应用程序中用户的密码进行散列化?
  2. 为何诸如 md5 和 sha1 这样的常见散列函数不适合用在密码保护场景?
  3. 如果不建议使用常用散列函数保护密码, 那么我应该如何对密码进行散列处理?
  4. “盐”是什么?
  5. 我应该如何保存“盐”?

为什么需要把应用程序中用户的密码进行散列化?

当设计一个需要接受用户密码的应用时, 对密码进行散列是最基本的,也是必需的安全考虑。 如果不对密码进行散列处理,那么一旦应用的数据库受到攻击, 那么用户的密码将被窃取。 同时,窃取者也可以使用用户账号和密码去尝试其他的应用, 如果用户没有为每个应用单独设置密码,那么将面临风险。

通过对密码进行散列处理,然后再保存到数据库中, 这样就使得攻击者无法直接获取原始密码, 同时还可以保证你的应用可以对原始密码进行相同的散列处理, 然后比对散列结果。

需要着重提醒的是,密码散列只能保护密码 不会被从数据库中直接窃取, 但是无法保证注入到应用中的 恶意代码拦截到原始密码。

为何诸如 md5()sha1() 这样的常见散列函数不适合用在密码保护场景?

MD5,SHA1 以及 SHA256 这样的散列算法是面向快速、高效 进行散列处理而设计的。随着技术进步和计算机硬件的提升, 破解者可以使用“暴力”方式来寻找散列码 所对应的原始数据。

因为现代化计算机可以快速的“反转”上述散列算法的散列值, 所以很多安全专家都强烈建议 不要在密码散列中使用这些散列算法。

如果不建议使用常用散列函数保护密码, 那么我应该如何对密码进行散列处理?

当进行密码散列处理的时候,有两个必须考虑的因素: 计算量以及“盐”。 散列算法的计算量越大, 暴力破解所需的时间就越长。

PHP 5.5 提供了 一个原生密码散列 API, 它提供一种安全的方式来完成密码 散列验证。 PHP 5.3.7 及后续版本中都提供了一个 » 纯 PHP 的兼容库

PHP 5.3 及后续版本中,还可以使用 crypt() 函数, 它支持多种散列算法。 针对每种受支持的散列算法,PHP 都提供了对应的原生实现, 所以在使用此函数的时候, 你需要保证所选的散列算法是你的系统所能够支持的。

当对密码进行散列处理的时候,建议采用 Blowfish 算法, 这是密码散列 API 的默认算法。 相比 MD5 或者 SHA1,这个算法提供了更高的计算量, 同时还有具有良好的伸缩性。

如果使用 crypt() 函数来进行密码验证, 那么你需要选择一种耗时恒定的字符串比较算法来避免时序攻击。 (译注:就是说,字符串比较所消耗的时间恒定, 不随输入数据的多少变化而变化) PHP 中的 == 和 === 操作符strcmp() 函数都不是耗时恒定的字符串比较, 但是 password_verify() 可以帮你完成这项工作。 我们鼓励你尽可能的使用 原生密码散列 API

“盐”是什么?

加解密领域中的“盐”是指在进行散列处理的过程中 加入的一些数据,用来避免从已计算的散列值表 (被称作“彩虹表”)中 对比输出数据从而获取明文密码的风险。

简单而言,“盐”就是为了提高散列值被破解的难度 而加入的少量数据。 现在有很多在线服务都能够提供 计算后的散列值以及其对应的原始输入的清单, 并且数据量极其庞大。 通过加“盐”就可以避免直接从清单中查找到对应明文的风险。

如果不提供“盐”,password_hash() 函数会随机生成“盐”。 非常简单,行之有效。

我应该如何保存“盐”?

当使用 password_hash() 或者 crypt() 函数时, “盐”会被作为生成的散列值的一部分返回。 你可以直接把完整的返回值存储到数据库中, 因为这个返回值中已经包含了足够的信息, 可以直接用在 password_verify()crypt() 函数来进行密码验证。

下图展示了 crypt()password_hash() 函数返回值的结构。 如你所见,算法的信息以及“盐”都已经包含在返回值中, 在后续的密码验证中将会用到这些信息。

crypt-text-rendered

 

date(): It is not safe to rely on the system's timezone settings

date(): It is not safe to rely on the system's timezone settings. You are *required* to use the date.timezone setting or the date_default_timezone_set() function. In case you used any of those methods and you are still getting this warning, you most likely misspelled the timezone identifier. We selected the timezone 'UTC' for now, but please set date.timezone to select your timezone. PHP 5.3 +  需要在 php.ini 文件中配置 timezone, 或在调用 date() 函数之前使用 date_default_timezone_set() 方法设置 timezone

Deprecated: mysql_connect(): The mysql extension is deprecated and will be removed in the future

昨天刚把 php 的错误日志打开,今天看自己以前写的 监控网站访问量的 demo 就一片空白了 一片空白了 一片空白了。
手动执行了下 数据采集的 data_access.php 发现有一个警告信息输出:
Deprecated: mysql_connect(): The mysql extension is deprecated and will be removed in the future: use mysqli or PDO instead
这个警告把原本的数据结构给打乱了,所以会出现 demo 的空白。
从提示很明显可以看出  mysql 扩展模块将在将来弃用,可以使用 mysqli 和 PDO 来代替。

Case A:
将 mysql 替换为 mysqli

-$conn = mysql_connect("db-hostname","dnuser","password","dbname");
+$conn = mysqli_connect("db-hostname","dbuer","password","dbname");
 
-if (!$conn) {
-  die('Could not connect: ' . mysql_error());
+/* check connection */
+if (mysqli_connect_errno()) {
+    printf("Connect failed: %s\n", mysqli_connect_error());
+    exit();
 }

官方文档  http://www.php.net/manual/zh/mysqli.query.php

Case B:
将错误日志关闭
display_errors = On
改为
display_errors = Off

Case C:
在php程序代码里面设置报警级别
error_reporting(E_ALL ^ E_DEPRECATED);

这样 Deprecated 这个问题就解决了。 不过还是推荐 使用 mysqli 或是 PDO 替代老旧的 mysql. 毕竟是趋势嘛。

 

PHP 获取的时间和系统的时间不一致

问题描述:
最近发现自动发送工作日报的那个脚本出现了问题, 发送是大昨天的内容.
可能是系统时间或是服务器时间配置不正确,下面开始逐步排查.

^_^[11:04:26][[email protected] ~]#date
Thu Oct 22 11:05:33 CST 2015
^_^[11:05:33][[email protected] ~]#cat /etc/sysconfig/clock
ZONE="Asia/Shanghai"
#UTC=true
#ARC=false

<?php
//date_default_timezone_set('UTC');
date_default_timezone_set('CST/8.0');

$today = date('Y-m-d H:i:s');
$yesterday = date('Y-m-d H:i:s',time()-86400);
echo "$today\n";
echo "$yesterday";
?>


^_^[11:06:09][[email protected] ~]#php test.php
2015-10-21 23:06:16
2015-10-20 23:06:16

^_^[11:07:35][[email protected] ~]#date -R
Thu, 22 Oct 2015 11:10:14 +0800


奇le个怪le, 系统区时的时间是对的,为啥时间不对呢?
再来看一下php 的 timezone

咔咔,居然错误在这里

[Date]
; Defines the default timezone used by the date functions
; http://www.php.net/manual/en/datetime.configuration.php#ini.date.timezone
date.timezone = 'Asia/Shanghai'
date.timezone = 'America/New_York'

将第二个注释掉再来看,这下对了O(∩_∩)O哈!

^_^[11:15:06][[email protected] ~]#php test.php
2015-10-22 11:15:12
2015-10-21 11:15:12

reference:
发现时区确实错误,进行修改
/bin/cp /etc/localtime{,.old}
/bin/cp /usr/share/zoneinfo/Asia/Shanghai      /etc/localtime

命令行修改时区
tzselect

一些概念:

1、硬件时钟(也叫BIOS时钟、CMOS时钟)
和CPU和系统无关的,单独由一个电池和晶振运行的时钟,即使关机也会走。
硬件时钟只有当系统启动的时候才会读取。
hwclock --show # 显示硬件时间
hwclock -s     # 系统时钟和硬件时钟同步

2、系统时间
Linux内核启动以后的时间,保持一个时间中断,用1970年1月1日00:00:00开始的秒数计数。这是我们平时看到时间。

3、时区
在某个时刻,世界各地的人,看到的时间都不同的。比如你同样适用gmail,大陆的人看到是 20:00,北美的人,可能是07:00.时刻还是一样的,但是由于时区不同,看到的时间显示就不同。
同样,我们机器里,可以系统时间一样的,但是不同的用户,可以设置不同的时区,看到的时间也不同。当然,系统本身有一个缺省时区。
在Redhat或者CentOS下,是使用  /etc/sysconfig/clock里的 ZONE="Asia/Shanghai" 选项配置的

4、UTC/GMT还是本地时间
系统启动的时候,使用/sbin/hwclock 从硬件时钟读取时间,关机的时候,会回写硬件时钟。
这里就有一个问题,读取和回写的时候,采用什么标准,是UTC还是本地时间?
一般情况下,都使用UTC/GMT,这样可以自动处理夏令时间(中国地方太大,已经作废)。
使用UTC的唯一坏处,是当你的计算机是多系统时,如果启动Windows,会导致时间不对。

5、时间同步
一般使用 ntp 协议进行同步,可以保持毫秒级的时差。

http://php.net/manual/zh/function.date.php
http://bbs.csdn.net/topics/390023846

How-to: 使用 highcharts + MySQL 构建自己的简易网站监控系统

Highcharts 是一个用纯JavaScript编写的一个图表库。

Highcharts 能够很简单便捷的在web网站或是web应用程序添加有交互性的图表

Highcharts 免费提供给个人学习、个人网站和非商业用途使用。

HighCharts 特性

  • 兼容性 - 支持所有主流浏览器和移动平台(android、iOS等)。
  • 多设备 - 支持多种设备,如手持设备 iPhone/iPad、平板等。
  • 免费使用 - 开源免费。
  • 轻量 - highcharts.js 内核库大小只有 35KB 左右。
  • 配置简单 - 使用 json 格式配置
  • 动态 - 可以在图表生成后修改。
  • 多维 - 支持多维图表
  • 配置提示工具 - 鼠标移动到图表的某一点上有提示信息。
  • 时间轴 - 可以精确到毫秒。
  • 导出 - 表格可导出为 PDF/ PNG/ JPG / SVG 格式
  • 输出 - 网页输出图表。
  • 可变焦 - 选中图表部分放大,近距离观察图表;
  • 外部数据 - 从服务器载入动态数据。
  • 文字旋转 - 支持在任意方向的标签旋转。