物理安全密钥(Security Key)是最可靠的

引言 2022年9月底,Uber发生了重大黑客攻击事件,各种云平台管理员权限都被攻破了。黑客主要是通过“社会工程(social engineering)”,也就是钓鱼邮件等等,获得了员工的账号密码。 我听到这个消息大为震撼,Uber这么大的公司,肯定设置了多重身份验证,怎么还能被攻破呢?我于是不务正业地搜索资料,并思索了一番,最后得到以下结论: 在精心设计的钓鱼邮件/短信和虚假网站面前, 短信验证码并不安全。 多重身份验证APP,包括Duo、Authy等等,无论是输入验证码,还是点击“允许登录”的弹窗,安全性也仅仅比短信验证高一点,依然不够安全。 物理的安全密钥,类似USB或者NFC的那一类,比如YubiKey,才是足够安全的。 短信验证码不安全 按照以下步骤: 黑客给用户发送了一则消息,类似“您的账户出现异常,需要您登录检查”,附送一个链接。该链接指向的并不是真实的网页,而是黑客搭建的虚假网页,用户在上面输入的所有信息都会被黑客获取。 用户点击链接,输入账号密码。 黑客使用用户的账号密码登录真实的网页,真实的网页会给用户发送短信验证码,并要求黑客输入验证码。这个时候黑客是没有验证码的。 用户看到虚假网页弹窗:“我们已经给你发送了短信验证码,请输入验证码:”。 用户在虚假的网页上输入收到的短信验证码。 黑客从虚假的网页上获取了短信验证码。验证码是一次性的,但其实用户并未真正使用过,所以依然是有效的。 黑客在真实的网页上输入验证码,黑客登录成功。 多重身份验证APP验证码不安全 这种情况其实和短信验证码没有太大区别。相比起短信验证码,多重身份验证APP的验证码时效更短一些,比如只有20秒。也就是说,用户在虚假网页上提供验证码之后,黑客必须立即使用该验证码登录。这其实对自动脚本并不困难。 多重身份验证APP点击弹窗不安全 比如使用手机软件Duo做多重身份验证,在登录时Duo会推送一个弹窗,要求用户点击允许登录。但其实这没有比验证码安全,甚至简化了步骤。推送的登录IP地址可能让用户起疑心,但是恐怕很多用户都是顺手点开,压根不会关注登录IP地址吧。 按照以下步骤: 黑客给用户发送了一则消息,类似“您的账户出现异常,需要您登录检查”,附送一个链接。该链接指向的并不是真实的网页,而是黑客搭建的虚假网页,用户在上面输入的所有信息都会被黑客获取。 用户点击链接,输入账号密码。 黑客使用用户的账号密码登录真实的网页,此时Duo会给用户手机推送弹窗。 用户看到虚假网页弹窗:“请在手机软件Duo上确认登录”。 用户点击手机弹窗确认登录。 黑客登录成功。 物理安全密钥才是安全的 这种验证方式会需要用户在"登录的设备"上插入安全密钥USB或者扫描NFC来验证登录。 黑客拿不到安全密钥插在自己电脑上,即便诱导用户把安全密钥插在用户的电脑上,也无济于事。只要安全密钥不丢,就是安全的。安全密钥配合密码(有的安全密钥还会配合指纹),并在丢失安全密钥后立即删除权限,在我看来算是足够安全的了。 最后 对于公司而言,指望每一个员工都能对钓鱼邮件免疫,是不太现实的。这么想的话,可能还是用物理安全密钥的好。 网络安全公司Cloudlflare写过一篇blog记录他们遇到的网络钓鱼攻击,内容详实,非常具有启发性,推荐阅读。英文链接,中文链接

October 22, 2022 · Salix

Learning C++ with Docker and Visual Studio Code for Beginners

This blog aims to introduce the minimum efforts to set up a C++ environment with Docker and VS Code.

October 9, 2022 · 4 min · 739 words · Salix

Grow in a Systematic Way

我认为“systematic”是非常重要的思想,其重要程度容易被低估。本文旨在记录我的思考,既是对我个人的提醒,也想和小伙伴们交流。 “systematic”的要素 我搜到的systematic的定义是“done or acting according to a fixed plan or system; methodical”。这个定义太简略了,我个人理解有以下要素: vision and roadmap 首先就是要有发展远景和发展规划。我们拿做研究来举例,好的研究者应该要有心中的蓝图,知道自己多年后要实现的终极目标,每一篇文章,应该是这个终极目标的准备工作或者部分结果。我想需要避免的就是“无助于实现长远研究目标的,ad hoc的工作”。 基于这样的原则,我们就可以产生一些价值判断。比如看起来不够硬核的文章。有一些同学会称之为“灌水”,但是在我看来,如果你清楚地知道这个文章的定位是更高的工作的准备,比如就是帮助自己学习某一个新东西,或者训练低年级学生的研究能力,那么这个文章就是值得的。 当然,vision和roadmap也是不断迭代的,它会随着我们得到新的结果/证据,以及外部环境的变化,而不断更新。重要的是一定要有,并且在其指导下工作。 machinery 我想注重“一整套机器”而非“解决孤立的问题”,我可以举几个例子。 第一个例子是数学中的公理化体系,比如基于测度论的概率论。我们从最基本的东西出发,利用已有的结果,去得到更高的结果,这些结果组成了一个巨大的机器。我们不断利用这个机器去得到新的结果,而这些新的结果又会成为机器的一部分。到最后我们可以得到非常nontrivial的结果,如果不是依靠这个机器,这些结果是绝对不可能达成的。事实上历史上有很多例子,为了解决某一个问题(获得某一个结果)而发明了一整套机器,而这套机器不但可以有条不紊地解决这一个问题,还可以解决别的问题。 第二个例子是DeepMind的一些工作。我发现DeepMind还是很重视搭建machinery的。他们的终极目标是AGI,在对某些问题的研究中,他们觉得relational inductive biases within deep learning architectures是关键要素,因此他们造了一套工具,也就是graph networks,而且做得尽可能general而不是限制在某一个问题。为了方便自己未来的实验,他们写了对应的库。再此之后,他们用graph network的同一套工具做了很多应用性的工作,比如traffic prediction, AlphaFold 2等等,而graph network本身也在各种应用中得到进化,比如引入attention。其实我相信这些应用工作都是他们发展的中间结果,他们想利用这些问题帮助他们建造更好的机器。 我们可以总结一下,machinery强调的是,从某一个小问题出发,抽象出核心要素,搭建一整套机器(而不是把目光局限于这一个问题),用这套机器再去解决更多问题,并在解决问题的过程中不断丰富完善这个机器。 scalability and sustainability 现在的风气非常流行抓住风口赚一波,流行短期效益,而轻视发展的规模化和可持续。 在这方面,我要推荐《Software Engineering at Google》这本书。它一定程度上总结了Google的方法论,试图回答how to scale。不仅仅是在技术层面,也包括文化、管理层面,对非软件工程的从业者也有启发。这本书存在本身,也说明Google真的很强调方法论的总结。 methodology 我想注重“方法论”而非“个人经验或灵感”。如果不能总结成方法论,那么个人的经验和灵感就很难迁移,也就很难有scalability和sustainability。所以一定要有“按照方法论的指导去工作,并不断迭代方法论”的意识。 我想从“方法论”的角度,聊一聊今年全国二卷的作文题,也就是《红楼梦》的那个。事实上,我个人认为这个作文题极好,比我当年高考前后的江苏卷风花雪月不知道高到哪里去了,也比某备受吹捧的欧洲国家作文题的辩经不知道高到哪里去了。因为这个题目讨论的就是关于创新与发展的方法论:移用、化用、独创。它非常务实,又非常general,我无比希望有人能在我18岁的时候教我这种方法论。 第一步,移用,简单说就是抄。要抄得心安理得,要抄得大大方方。哪怕抄得很生硬也没有什么不好,毕竟你啥也不懂,抄就是最好的学习。在抄的过程中积累经验,领悟抄的东西的精髓。 第二步,化用。在对抄的东西不断深入的理解中,知道它的优势和局限性,做一些修改,应用到自己的问题里。 第三步,独创。在不断地化用中,结合自身的实际情况,量变产生质变,最后就有了独创。我们从小被教育要独创,轻视移用和化用,但是哪有无源之水,所有的独创都是能找到脉络的,移用和化用是通往独创的最有效途径。闭门造车,或者在虚空中苦苦思考如何创新,是没有意义的。 个人的学习工作是不是这样的? 企业的技术研发和商业创新是不是这样的? 国家的政治经济文化军事的发展是不是这样的? 这是多么general的方法论啊!所以我要吹爆这个题目! 我打算以后再单独写一篇讨论这个事情。 “systematic”的陷阱 我在这里先罗列一些可能的陷阱,以后有时间再添加。(基于“快速迭代”的原则,我并没有等全部写完再发出来) 1,机械教条与路径依赖,丧失中枢而只剩下无意识的、incremental的优化。这一点我听说Google就有这个倾向。 2,systematic可以帮助、引导思考,但是有些时候也会限制想象。所以我建议two-phase thinking,第一个phase是完全抛弃方法论,天马行空地思考,第二个phase是在框架下思考。两个phase交替进行会比较好。 先到这里了,以后有想法再改。

June 17, 2022 · 1 min · 64 words · Salix

学术界应该从工业界学习什么

简介 2021年夏天,在博士毕业之后,我加入了工业界做智能系统相关的工作。原因有很多,其中之一就是我对AlphaGo、GPT-3等等大型智能系统充满好奇。罗马不是一天建成的,绝不可能有一个人从一开始就设计好了所有的架构与细节,大家按照这样的设计写完代码,在大数据集上训练,一次性成功。 如何组织多人,甚至数十上百人,在一年左右的尺度下,成功开发出大型智能系统? There must be something there. 在工作近一年之后,我渐渐有一些模糊的理解,在这里加以整理记录。对工业界的朋友而言,这些可能是融入血液的常识,但对久处象牙塔的我而言,却是极大的启发。我认为这些是极为重要的“元经验”,是工程开发的“第一性原理”,也是学术界,尤其是应用数学界,应该从工业界学习的东西。 效率的提升 在工作中,始终应该保持"提高工作效率,增加单位时间产出”的意识。这既包括个人工作,也包括团队合作。除了“善用工具、劳逸结合”等等一般意义上的提高效率,软件开发有独特的一面。 有人可能会问,我一个做应用数学的,不是应该更注重灵感吗?解释如下: 应用数学离不开数值实验,灵感也是从信息中来的。快速实验,快速获得反馈。有些实验甚至必须建立在极高的效率之上。 节省时间与脑力,多花在阅读文献,思考,讨论之上。 提高效率不仅仅限于软件开发,比如说教程库与文献库的建设。我个人认为数学和软件工程有非常多的相似性,数学定理的封装与应用,也可以理解成“复用”。 自动化 无聊的工作也会消耗脑力。 尽可能把所有无聊工作自动化,比如一键提交、提醒、处理、下载。会不会浪费时间在工具的搭建呢?不会的,只要我们尽可能复用工具。如下。 复用与基建 复用的动机以及指导原则是: 节省个人和团队的时间。 更重要的,可以逐渐变得更好,最后形成分享的“基建”。 我需要特别解释一下“更好”。这里的更好包括: incrementally更好,比如让某一些代码更加general。 通过封装、嵌套、组合,最后达到指数级的复合增长——这是软件工程的魔法。 不用着急一步到位,一点一点建设,积累下来就是很多工作了。 代码复用 定义好接口 文档(尤其是注释)与范例 尽可能成系统,定期整理 文档复用 比如说,我要给一个人讲一套东西,那我可以写成教程,这样如果有另一个人需要我再讲一遍,我就可以把这个教程给他,而节省了再讲一遍的时间。而如果未来的我,或者另一个人,对这个教程有补充,那就可以变得更好!最后我们可能就有了教程库,甚至一本书。本文就是一个案例。 再比如说,团队一起建设文献库。每一个人记录对新的文献的理解和评价,可以节约文献阅读和搜索的时间。额外的好处是,也加强了沟通。 注意精简而不失信息,以提高信息传递的精度以及阅读效率。关键的地方值得迭代。 项目复用 也就是我下一个项目尽可能是建立在上一个项目的基础之上,我每一个项目也尽可能为后续的项目做好准备。不仅仅是代码复用,文档复用,也有知识与经验的复用。 分布式并行开发 建议所有人学习git。 迭代 这是最有意思的部分。 迭代的动机和指导原则: 在一开始并不知道要做成什么样子,需要依靠对比、反馈来决定后续工作 便于并行开发 提供短期回馈,保持心理健康 测试代码 测试代码可以帮助控制代码质量,同时也是文档和范例(接口是啥,功能是啥,怎么使用)。 标准问题(Benchmark) 我之前低估了benchmark的重要性,毕竟在数学里,好坏是可以推导出来的。但是用标准问题比较好坏,确实要简单快捷很多。更重要的是,便于分布式开发。各个lab一起试图解决某个问题,这不就是分布式开发嘛。 神经网络的迭代 传统的软件开发,可以分模块测试、迭代。神经网络讲究end-to-end,并不容易分模块,那要怎么办呢? 定义小问题 small dataset small batch size small training steps 在小问题上通过快速迭代找到好的神经网络结构和loss function,几轮小迭代之后,就可以在更大的问题上测试,用稍低的频率迭代。最后上超级大问题。 注意记录结果。按照同事的说法,不一定需要grid正交测试,线性测试是可以的。效果不显著的不要留,但如果复合逻辑,可以keep in mind,之后再试试。 调参对个人而言是一个经验活,但是对组织而言,只要有足够快速的迭代(这又回到了效率的问题),总是可以找到好东西的。 这个文档只是我暂时的记录,以后会继续更新。

June 17, 2022 · 1 min · 66 words · Salix