NotionNext 博客上锁文章的强制访问
太长不看
- 所有的前端加密都是不安全、可破解的;
- NotionNext 这个框架采用的是基础的
md5
加密,送入加密器的内容是文章地址 + 密码
,
如article/example-2
+123456
,这里的+
表示字符串连接; md5
加密不可能(高效)从密文获取到原文;- 修改
js
需要指定一个保存修改后文件的本地文件夹。
序
最近看到了一位学长的博客,许多花里胡哨的特效,连鼠标右键的菜单都不满意,要自己用一些 Live2D 之类的库生成一个。
我对这些特效不太感冒,我也尊重其他人的选择,毕竟是自己的博客,想怎样设计都好。不过,我的底线就是,不要影响鼠标右键的基本菜单。因为作为一个对前端比较熟悉的人,我喜欢对着页面上的一些元素点来点去,看看是怎样实现的。
我记得一个让我很郁闷的博客是,直接劫持了鼠标右键,不让复制。这种问题很好解决,改一下 event 就好了,没什么难度。有时候我就喜欢对着干,要是本来没什么限制,我也想不起来要用一些技术手段来突破。
话说回来,为什么要写这篇文章呢?是因为我这位学长有一篇保研记录的文章,居然加密了,无法直接观看。这我就有些赞叹,哇,居然在前端加密?前端加密,能防谁呢?我对文章的内容倒不是很感兴趣,我就想看看这前端的加密到底是怎么做的。
我曾经也破解过学校对密码的前端 AES 加密,就是一些函数罢了,破解的关键就是厘清整个状态进行的流程。毕竟,前端嘛,所有的逻辑都摆在明面上了。无非就是,代码经过混淆过,人类不方便阅读。但一些关键的地方,库的名字之类的,还是能看出来端倪。毕竟,加密的就那几个库呀。
所以说,为了看看这前端加密到底是怎么一回事,写了这篇文章。
初步探索
先确定一下这密码是前端加密的,嗯,确实是。按下提交密码按钮后,Network 部分没有给后端的请求。
一开始,我的思路还是按照经验来,找找按下按钮的事件。但这并不顺利,因为这位学长的博客特效太多(烟花、缎带…),按下右键后,直接进入到了框架统一的事件处理入口,并没有进入到处理密码的部分。
所以后来我就想,毕竟博客是用某个框架来搭建的,所以,看看这框架是怎样实现的吧。所以找到了这篇文章:
这篇文章是官方的一个使用示例,所以我从它入手。一开始还不是很顺利,因为定位不到关键的函数入口。所以我放弃了从事件开始,按时间顺序观察函数执行流程的思路,而是改用关键词搜索,检索所有 js 文件。
找到了一个负责 md5
加密的 js
文件,问了问 AI,回答是:就是一个很基本的 md5
加密,没有加盐之类的。那还不错。
但是,密码哪里来呢?发现 html
中会存储每个文档的信息,password
属性就是 md5
处理后的哈希值。
所以,整体的密码验证逻辑是,用户在输入框输入密码,送到 md5
加密函数,得到输出。把输出和文章的哈希值比对,如果一致,则文章解锁。
而且我注意到,文章解锁是永久的。因为写过一些网页,所以一下子就想到,应该是密码存放到了 LocalStorage 中。一看,果然。
key
形如 password_/article/example-2
,value
就是明文的密码,比如 123456
。等到再次访问解锁过的博客,先看看 LocalStorage 中有没有存过密码,如果有,直接拿这个验证。
修改 js
现在已经明白了大概的验证流程。那么,有一件事就可以清楚了:不可能获得明文密码来解锁文章。因为 md5
加密是不可逆的,就算知道了加密后的哈希,除非跑彩虹表,否则很难知道原始的密码是什么。
那么,接下来的思路就改成,修改前端的验证逻辑,不管输入的密码是什么,都能够验证成功。
这里,LocalStorage 的部分对我帮助很大。因为如果验证通过,密码会被保存到本地。反过来想,密码保存到本地的前提是,密码被验证了。也就是说,验证密码的部分和保存密码的部分应该离得很近。
确实是这样,以 _password
为关键词搜索,找到了负责这部分功能的 js
文件。鼠标悬停到一些变量上面,看到了变量的值,嗯,就是文章的哈希。所以,只需要在这个位置打断点,就能找到文章的密码哈希,完全不用在 html
中一个个检索文章的链接来定位。
不过,修改 js
,我确实没做过,一开始 Chrome 提示做的修改没有保存到文件系统。后来是这样做的,在 Sources
中找到要修改的文件,点 Override Content
,会提示选定一个本地的保存文件夹。选定后,做出的修改就会被保存。
对 js
的修改很简单,我选的是其中一种比较直白的修改方法,那就是把待比对的变量直接设置为文章密码的哈希。刷新一下页面,就达成了目的。