在德语键盘中输入 @ 符号

标准的英语键盘大家都很熟悉了,其中的“@”符号在数字“2”的上方,使用 Shift-2 按键组合即可打出。

不幸的是,某一次我把输入法改成了德语,然后我的 Macbook Pro 休眠了,唤醒之后,密码怎么输也不对。碰到这种情况,按公司的传统,我的反应是:

后来仔细想了想,大概是输入法改了的原因。只不过 Mac OS X 在输密码的阶段会锁定输入法,不能切换回英文。好吧,还好我有一个正宗的德语键盘,找一下 @ 字符在哪就可以了。德语键盘长这样:

可以看到数字“2”上面是引号而不是“@”,这就是为什么密码一直不对的原因。而德语键盘中的“@”在“Q”下方,可以通过组合键 AltGr-Q 或者 Ctrl-Alt-Q 打出,其中 AltGr 特指右手边的 Alt 键。

然后我就按了 AltGr-Q,但系统还是说密码不对。

于是,不死心的我又去查了一下德语版的 Macbook 键盘长什么样。

我去,原来苹果把“@”符号设计到了字母“L”那里……

好了,问题解决了,大家洗洗睡吧。

网易所谓的“EAL 3+”证书是个什么东西?

今天一早,乌云上曝出了网易邮箱的安全问题,过亿的用户信息被泄漏。而网易方面也是反应神速,一份宣传稿发到各大媒体,说是自己家的邮箱不仅没问题,而且安全性方面还是全国最牛X的。公告原文如下(摘自新浪):

文中提到了一个 EAL 3+ 的认证,而且号称是国内最高等级。这个到底是什么呢?我们来研究一下。

网易的企业邮箱网站在今年 8 月底发布了一则新闻,说是企业邮箱系统获得了 EAL 3+ 认证,还有一个像模像样的证书。图片就不贴了,大家点链接进去看吧。证书大意是“网易企业级邮箱系统”获得 中国信息安全评测中心信息安全实验室 颁发的 EAL 3+ 证书。

首先,这个系统的名字有歧义,企业级的邮箱系统,不一定只是给企业用的。网易可以说自家的免费邮箱也做到了企业级的安全性。当然网易算是心虚,没有在自己的首页发表这么个新闻,只是在企业邮箱的网站上发了。那我们只能认为只有网易的企业邮箱获得了这个证书,而大众所使用的免费邮箱却没有。而乌云提到的过亿的用户信息,显然不是从企业邮箱来的。网易在公告中宣称的“国内最安全”,只不过是偷换概念罢了。

当然,不能排除网易内部实际上使用的是同一套系统,即企业邮箱和免费邮箱的后台是一样的,只是页面看上去不一样。那么企业邮箱获得了安全认证,免费邮箱也就同样安全。好吧,然后我又去看了一下 EAL 3+ 的实际内容。

EAL(Evaluation Assurance Level)是某个国际组织设立的标准,按它的实际操作来看,每个国家都可以设立自己的评测实验室,对本国的软件进行评测。中国、美国、英国、法国、西班牙等国都有自己的评测实验室。中国的评测由上面提到的 中国信息安全评测中心信息安全实验室 来进行。在中国信息安全评测中心的网站上,可以找到中文版的 EAL 1 - 5 的评测细节,其中这个链接指向的是 EAL 3 的指南(PDF)。文档我稍微看了一下,实际它只有 20 页不到,大约就是一个对文档细节的约束。其中对于测试文档的要求,只有半页,还没我的一篇博文长。摘录如下:

基本上它就是要求了测试文档的完整性,对于要测哪些方面、具体测试的实施以及测试的结果,通通没有要求。也就是说,只要文档写得好,通过 EAL 评测并不难。而做过产品的同学们都知道,文档和最终产品的差距还是相当大的。举个例子:

另外,网易的证书上还提到了评测方法:GB/T 30270-2013 信息技术 安全技术 信息技术安全性评估方法。我搜索了一下,这个《方法》没有电子版,只有纸制书籍出售,当当网的卖价是 103 元。我自然不会为了写博客还去买本破书,因为当当的介绍中提到,这本书只有 200 多页,目录显示它的内容就是 EAL1 到 EAL5 的实际内容,外加一些前言备注什么的。大致可以看到,书中没有额外的内容,具体的评测和上面给出的 PDF 链接没有两样。

所以实际上,网易获得了证书 和 系统的安全性 这两件事并没有直接联系。而即使是网易获得证书的企业邮箱,它的安全性也令人堪忧:

上图中,即使我选择了“全程使用 SSL”,登录页面也没有使用 SSL。在登录页面不使用 SSL 的情况下,即使登录接口使用了 SSL 也是形同虚设的,因为未加密的登录页面可能被劫持,只需要添加一段脚本,就可以神不知鬼不觉得拿到帐号信息。详细的分析我曾经在乌云看过一篇文章,一下子找不到了,等找到了再补上。

对于那些担心自己密码失窃的同学们,我只能建议一句:保护个人信息,远离网易。当然,如果你在其它网站使用了和网易一样的密码,请立即修改。

感谢国家

好久没写文章了,最近这段时间公司事务繁忙,好不容易有点闲暇时间了,就跑过来照顾一下博客。

前几天 StrongVPN 的客服联系了我,问我要 Paypal 的帐号以便付款。他家前段时间升级了代理系统,可能是把我的 Paypal 记录弄丢了,于是我写信回了过去,也顺便去看了一下,我将收到多少钱。

不看没关系,一看吓了一跳,佣金居然有四位数?然后看了一下详细数据,确定了是新系统才有的记录,不是历史数据。敢情在这两个月里网络环境如此地恶劣,大家一起上 VPN 的节奏。

感谢国家,下个月收到佣金可以换个 iPhone 6s 了。

顺便做个广告,StrongVPN 更新了他们的服务,现在更注重隐私,并且提到了无限流量的 VPN,要体验一下的同学点这里

写于博客密码泄露之后

很不幸我的博客密码被盗了,一个不名黑客在半夜入侵了我的主机,植入了菜刀,远程控制了机器。然后他窃取了一些重要资料(比如一些羞羞照),并且把主机变成了一台肉机。我发现的时候,肉机已经偷跑了超过 5000 美元的流量......

在电脑手机前偷笑的各位可以稍微停一下了。以上只是我被害妄想症的一种表现,它实际上并没有发生。

由于对安全的偏执,我假想了各种安全漏洞的情形,然后加以防御。之前讨论过 WordPress 的密码安全性插件安全性,这次来探讨一下密码失窃之后,有哪些亡羊补牢的方法。

假设一名黑客偷取了本博客的管理员密码,(先假设只是博客的密码,而不是主机的管理员权限),那么他能做哪些事情?

一,很明显,他可以操作博客的数据库,新建用户、新建文章、删除文章等。

二,黑客可以在后台直接挂马,然后进行更强大的远程操作。

对于第一条,似乎没有特别好的方法,一旦密码被盗,数据库就只能放弃了。当然,如果你的博客没有任何加密的内容,数据库被盗也没什么好怕的,本来就都是公开的东西。

接下来重点说一下第二条。

PHP 有一个很好用也很危险的特性,就是源代码可以直接执行;而 WordPress 也有一个很好的特性,即可以在后台直接修改插件代码。于是一旦黑客控制了后台,他可以在源代码里嵌入一行如下的语句,然后就可以远程控制了。对,PHP 就是那么强大。

要防止这种情况,最有效的方法是在把所有源代码设置为只读,即 Linux 文件属性 400(或 444),这样可以避免任何人对文件进行修改。但这样做之后,自己真想要修改文件的时候,却是非常麻烦,先要 SSH 登录,把文件属性设为可写(如 755),然后再回到后台改文件。另外,这样做也阻止了 WordPress 的自动更新,一定程度上降低了安全性。

对此, WordPress 提供了一个简单的防御方式,可以 wp-config.php 中添加一行:

这样可以禁用掉 WordPress 中修改源代码的界面,包括插件和主题,同时也禁止了安装新的插件和主题。当然这样同样会有上述的问题,即每次修改文件之前,需要先修改 wp-config.php。为了避免对 wp-config.php 的频繁修改,我们可以加一点小小的逻辑,如下:

它的含义是在不是运行 WP Cron 并且 Session 中没有定义 enable_edit 的时候,才禁用对主题和插件的修改。开启 WP Cron 的原因是它会定期检查并更新 WordPress,而 Session 的定义则可以按需开启修改的界面。

手动启用修改界面,还需要一段代码,写在 functions.php 中:

然后访问 http://你的博客地址/wp-admin/admin-ajax.php?action=temp_enable_edit 即可临时开启对插件和主题的修改,有效期到 Session 过期为止。需要注意的是,并不所有的主机都启用了 Session。如果你的主机把 Session 关了,你可以改成使用 Cookie,效果类似。

这种方法是安全和易用的一个折中,它假设了 WordPress 不会有 Bug,比如 DISALLOW_FILE_MODS 工作正常,并且没有安装可以直接运行 PHP 代码的插件

另外还有一些其它的方法仅供参考:

  • 给 wp-admin/ 文件夹加一个密码,比如 Apache 的 Basic Authentication。我觉得每次登录都需要多输一个密码,实在太麻烦了。
  • 重命名 wp-admin/ 文件夹让别人找不到。根据前几年的讨论贴,这种方法并不能完美工作,也就说是 WordPress 的代码某种程度上依赖于 wp-admin 而不能改名。
  • 创建一个新的域名,只用来访问 wp-admin,而原先的域名供访客浏览。这种方法的前提是你愿意支付双倍的 SSL 证书费用。

这个世界上没有绝对的安全,只不持之以恒的防御。

如何生成 CSR 文件

CSR,Certificate Signing Request,是制作 SSL 证书的必要步骤。一个 CSR 文件中描述了 SSL 证书持有人的信息(如个人姓名或公司名称)、联系地址等,用于验证 SSL 证书和域名是同一个人持有,以确保网站的合法性。

在 Linux 上生成 CSR 文件通常需要用到 OpenSSL 工具,这是一个命令行工具,参数一大堆,对于偶尔用一下的用户来说,可能不太友好。于是 DigiCert 提供了一个在线工具,用于生成 OpenSSL 的命令行,然后再拿去网站主机上运行就可以了。理论上 OpenSSL 一定要在网站所处的主机上运行,即换了主机之后要重新制作一个新的证书,但实践中并不强制这一步骤。

工具截图如下:

示例中我填写了 Google 的信息,请按实际情况修改,各项的含义如下:

  • Common Name: 你的网站域名
    • 如果你购买的是单一域名的 SSL 证名,请填写实际用到的域名,如 leonax.net 或者 www.leonax.net;在 DigiCert 购买的单一域名,填写 www 版本送裸域;
    • 如果购买的是野卡,则填写 *.leonax.net;
  • Organization: 公司名称,如果是个人用户,请填写自己的全名;
  • Department: 部门名称,可不填;
  • City: 所在城市;
  • State / Province: 所在州/省;
  • Country: 所在国家;
  • Key Size: 加密字长,目前常用的是 2048,如果对安全性要求较高,可以选择 4096;

全部填好之后,点击“Generate”即可以生成命令行,把右侧生成出来的一串命令,复制到 Linux 主机上运行即得到一个 CSR 文件。

之后要做的步骤是向 SSL 证书提供商上传这个文件,以获得最终的 SSL 证书,之后再详述。

注:OpenSSL 是一个 Linux 的工具,如果你的主机所用的是 Windows 或其它操作系统,可以在这个页面找到相应的介绍。

HHVM 中的 RepoAuthoritative 模式

HHVM 3.8 中提出了一个 RepoAuthoritative 模式,用于提升 PHP 代码的效率。

PHP 代码是解释型的,也就是每次执行的时候,PHP 引擎都会读取源代码,编译成机器代码之后再执行。这也就是为什么解释型语言比较慢的原因之一,它不能一次编译完成,而是一定要运行到哪里编译到哪里。编译的过程拖慢了整个运行的效率。而这样每次“编译”的过程显得有些多余,因为代码是基本不会变的。于是 PHP-FPM 是提出了 OpCache 来缓存编译的结果,如果代码已经被编译过,且源代码没有改动,则继续使用缓存。

而 HHVM 则更进了一步,在 RepoAuthoritative 开启之后,指定的文件夹会被编译成一个二进制文件,并同时进行优化。官方说法是,这样的优化可以在 HHVM 本身的基础上,再提升 20% 的运行效率。

开启的方法如下,其中 /var/www 是想要编译的文件夹。

关闭的方法如下:

编译的过程使用了 /var/run 做为临时文件夹,实测 WordPress 编译完成之后,要占用 175MB 的空间,如果 /var/run 太小会提示“disk is full”错误。

当然, RepoAuthoritative 也有一定的限制,比如不能使用 eval() 和 create_function() 等动态改变代码的语句。不过 WordPress 中几乎没有用到,说“几乎”是因为实际上有两处用到了,一个是在 wp-includes/pomo/po.php 中,这个文件貌似根本不会被执行到;另一处是在 wp-includes/atomlib.php 中,只要不使用 atom 作为 RSS feed 即可。另外就是编译完成之后,源代码的改动就会“失效”,要再一次编译才会使改动起作用。

然而,由于 HHVM 自身已经相当地高效了,开启 RepoAuthoritative 模式之后没有明显的变化。本站实测下来,TTFB 时间大概减少了 50ms,对于原本只有 700ms 左右的速度来说,看不出效果。我试用了一下之后就把它关闭了。不过至少说明在 WordPress 上使用这个功能是没有问题的。如果你的 WordPress 中有非常慢的功能,不妨试一下 RepoAuthoritative 模式。

在 PHP 中实现 String 的 StartsWith 和 EndsWith

和 Javascript 一样,PHP 中也没有对 String 实现 StartsWith 和 EndsWith 这两个方法。由于这两个方法很常用,我们只好自己来实现一下。

在 PHP 4 中,常见的做法和 Javascript 类似,如下:

上面的方法会使用更多的内存,并且对字符串扫描了两遍,效率不高。这种方法在 PHP 5 中已经过时了,因为 PHP 5 给出了一个 substr_compare 方法,可以直接比较子字符串,如果代码就可以简化成这样:

上述实现的效率至少快了一倍。由于历史遗留的问题,很多现存代码都没有更新,比如 WordPress 的源码中就存在了老版本的实现。如果你已经在使用 PHP 5 或者 HHVM,不妨试试第二种实现。