Hello Navi

Tech, Security & Personal Notes

Challenge

Network Security Sam has encrypted his password. The encryption system is publically available and can be accessed with this form.

Sam 把他的密码加密了。加密系统是公开的,可以通过页面上的表单访问。

已知加密后的密码:477djk?=

页面提供了一个加密工具,可以输入任意字符串查看加密结果。

Solution

这题需要逆向加密算法。先用加密工具测试几组已知明文,观察规律:

输入 aaaa(4个相同的字符):

1
aaaa → abcd

规律很明显:每个字符的 ASCII 值加上了它的位置索引(从0开始)。

1
2
3
4
a(0) + 0 = a
a(1) + 1 = b
a(2) + 2 = c
a(3) + 3 = d

所以加密公式是:encrypted[i] = chr(ord(plaintext[i]) + i)

解密即为逆操作:plaintext[i] = chr(ord(encrypted[i]) - i)

Python 解密脚本:

1
2
3
4
5
encrypted = "477djk?="
decrypted = ""
for i, c in enumerate(encrypted):
decrypted += chr(ord(c) - i)
print(decrypted) # 465aff96

验证:重新加密 465aff96:

1
2
3
4
5
6
7
8
4 + 0 = 4
6 + 1 = 7
5 + 2 = 7
a + 3 = d
f + 4 = j
f + 5 = k
9 + 6 = ?
6 + 7 = =

结果:477djk?=,与已知密文完全匹配。

自定义加密算法如果有公开的加密 oracle(可以任意加密已知明文),攻击者可以通过 chosen-plaintext attack 推导出算法逻辑,进而解密任意密文。

465aff96

Challenge

Sam has gotten wise to all the people who wrote their own forms to get the password. Rather than actually learn the password, he decided to make his email program a little more secure.

Sam 发现很多人自己写表单来获取密码。他没有去真正学密码,而是让邮件程序变得更安全了一些。

Solution

这题和 Basic 4 基本一样,只是增加了 Referer 验证。服务端会检查请求来源是否来自 /missions/basic/5/ 页面本身。

解决方法完全相同,都是修改隐藏的 to 字段,但必须同时发送正确的 Referer:

1
2
3
4
$ curl -sL -b 'HackThisSite=YOUR_COOKIE' \
-e 'https://www.hackthissite.org/missions/basic/5/' \
-d 'to=YOUR_EMAIL' \
'https://www.hackthissite.org/missions/basic/5/level5.php'

-e 参数设置 Referer header。如果不带 Referer 或 Referer 不匹配,会返回 Invalid Referer 错误。

核心知识点:Referer header 同样可以被伪造。它不是安全机制,不能用来防止跨站请求。唯一可靠的防御是服务端独立验证权限。

92bf24e2

Challenge

This time Sam hardcoded the password into the script. However, the password is long and complex, and Sam is often forgetful. So he wrote a script that would email his password to him automatically in case he forgot.

这次 Sam 把密码硬编码在脚本里了。密码很长很复杂,而 Sam 经常忘,所以他写了一个脚本,会自动把密码发送到他的邮箱。

页面上有两个表单: - 一个"Send password to Sam"按钮 - 一个密码输入框

Solution

查看源代码,发现"Send password to Sam"按钮对应的表单里有一个隐藏字段:

1
2
3
4
<form action="/missions/basic/4/level4.php" method="post">
<input type="hidden" name="to" value="sam@hackthissite.org" />
<input type="submit" value="Send password to Sam" />
</form>

收件人地址 sam@hackthissite.org 是硬编码的。只需将 to 字段的值改为自己的邮箱地址并提交,密码即会发送至该邮箱。

修改方式: 1. 浏览器开发者工具(F12)→ Elements → 直接修改 value="sam@hackthissite.org" 为自己的邮箱 2. 或者用 curl 直接 POST:

1
2
3
4
$ curl -sL -b 'HackThisSite=YOUR_COOKIE' \
-e 'https://www.hackthissite.org/missions/basic/4/' \
-d 'to=YOUR_EMAIL' \
'https://www.hackthissite.org/missions/basic/4/level4.php'

然后去邮箱查收密码。

客户端表单验证毫无意义。任何隐藏字段都可以被修改,任何表单都可以被自定义提交。服务端必须独立验证所有输入。

206a6f9d

Challenge

This time Network Security Sam remembered to upload the password file, but there were deeper problems than that.

这次 Sam 记得上传密码文件了,但问题比这更深层。

页面上有一个密码输入框。查看源代码后发现一个隐藏的表单字段:

1
<input type="hidden" name="file" value="password.php" />

Solution

HTML 表单中的 hidden 类型字段对用户来说完全是可见的:只要查看源代码就能看到。这里隐藏字段暴露了密码文件的路径:password.php。

直接在浏览器中访问这个文件即可获得密码:

1
https://www.hackthissite.org/missions/basic/3/password.php

页面会直接返回密码内容。

e656d2bd

Challenge

Network Security Sam set up a password protection script. He made it load the real password from an unencrypted text file and compare it to the password the user enters. However, he neglected to upload the password file...

Sam 设置了一个密码保护脚本,从一个未加密的文本文件中加载真实密码进行比对。然而他忘了上传密码文件。

Solution

这道题考察的是逻辑思维。脚本从文件加载密码来比对用户输入。如果密码文件不存在,脚本就无法加载任何内容来比对。

提交空密码时,脚本试图将空字符串与一个不存在的文件内容比对;两者都是空值,所以比对通过。

直接在密码框中什么都不输入,点击 submit 即可。

核心知识点:如果密码文件缺失,认证系统可能默认接受任何输入(甚至空输入)。实际部署中应该对文件缺失的情况做防御性处理。

Challenge

This level is what we call "The Idiot Test", if you can't complete it, don't give up on learning all you can, but, don't go begging to someone else for the answer, thats one way to get you hated/made fun of.

这一关被称为"白痴测试",如果你无法完成,别放弃学习,但不要去求别人给你答案。

页面上有一个密码输入框,需要找到密码才能过关。

Solution

最基本的 web 安全入门:查看网页源代码。

右键查看页面源代码(或 Ctrl+U),然后搜索 password,会发现密码直接以 HTML 注释的形式嵌入在源码中:

1
<!-- the first few levels are extremely easy: password is 798ce5a6 -->
798ce5a6

Here's something encrypted, password is required to continue reading.
Read more »

Here's something encrypted, password is required to continue reading.
Read more »

Here's something encrypted, password is required to continue reading.
Read more »