Bandit 是wargame 系列挑战中的第一个系列,也是最基础的一个,可以用来巩固一些命令行基础知识,所有的挑战都通过终端直接 ssh 连接远程主机即可。我在两周前打完了 Bandit,所以写下这篇博客来做一个总结。
Level 0
目标
使用 ssh 连接到目标主机 bandit.labs.overthewire.org 。用户名为bandit0,密码为bandit0。
可能会用到的命令
ssh
非常简单,直接连进去可以得到下一关的密码。
1 | sshpass -p `natas0` ssh natas0@bandit.labs.overthewire.org -p 2220 |
这里用到了 sshpass 命令,这个命令允许你进行 ssh 连接时直接输入密码,而不需要再标准输入中输入,非常方便,之后的连接我都是使用的这个命令。可以通过该页面 查看安装如何安装
Level 0 → 1
目标
下一关的密码保存在用户目录下的 readme文件中。无论什么时候得到了下一关的密码,使用 ssh 登入下一关并继续挑战。
可能会用到的命令
ls, cd, cat, file, du, find
使用ls 查看用户目录并用cat查看文件内容。
1 | cat readme |
Level 1→ 2
目标
下一关的密码保存在用户目录下的”-“文件中。
可能会用到的命令
ls, cd, cat, file, du, find
使用 ls 查看目录并使用 cat 查看文件内容。然而在使用 cat 命令时会出现一直空等的情况。因为文件名”-“是一个特殊字符,它会告诉 Shell 用户想从标准输入输入数据,所以 Shell 就会空等。解决办法就是带上文件路径。
1 | cat ~/- |
Level 2→3
目标
下一关的密码保存在用户目录下的 space in this filename文件中。
可能会用到的命令
ls, cd, cat, file, du, find
这一关考察的是转义符的应用。如果直接在 Shell 中打出文件命令的话,Shell 会将输入理解为多个参数,而不是一个文件名,因此需要用转义符’\‘来对空格进行转义。
1 | cat "spaces in this filename" |
Level 3→4
目标
下一关的密码保存在 inhere 文件夹下的隐藏文件中。
可能会用到的命令
ls, cd, cat, file, du, find
主要熟悉 ls 命令,加上 -a 参数后就可以看到当前文件夹下包括隐藏文件在内的所有文件。
1 | cd inhere |
Level 4→ 5
目标
下一关的密码保存在 inhere 文件夹下唯一可读的文件中。
可能会用到的命令
ls, cd, cat, file, du, find
在 inhere 有很多文件,但只有一个是可读的。使用 file 命令可以查看所有文件的文件类型,发现只有一个文件是 ASCII 格式的,那就是我们需要的!
1 | cd inhere |
level 5→6
目标
下一关的密码保存在 inhere 文件夹的某个文件中,它有下列特征:可读的;1033字节;不可执行。
可能会用到的命令
ls, cd, cat, file, du, find
这一关用到 find 命令。参数 -size 可以用来指定文件的大小,在数字后加 ‘c’用字节表示,加’k’用 kb 表示,加’M’用 MB 表示。参数 -type 用来指定文件的类型,’f’表示普通文件,’I’表示链接文件,’d’表示目录。
1 | cd inhere |
Level 6→7
目标
和上一关类似,这一关的文件在服务器中,没有告诉我们具体位置。这一关的文件有以下特征:属于用户 bandit7;属于组 bandit6;33字节。
可能会用到的命令
ls, cd, cat, file, du, find, grep
这一关还是要用到 find命令。我们已经知道了使用 -size 33c来寻找长33字节的文件。参数 -group bandit6 将会寻找属于组 bandit6 的文件。参数 -user bandit7 将会寻找属于用户 bandit7 的文件。因为该文件在服务器的某处,所以我们要从根目录开始找。执行命令后将会产生许多拒绝访问的报错信息。为了过滤掉这些没用的信息,我们使用 (2>/dev/null)。
小贴士:
‘>’操作符重定向输出到文件或设备。也可以使用’>>’来附加(’>’会覆盖源文件,如果有的话)。
> file : 重定向标准输出到文件
1>file : 重定向标准输出到文件
2>file : 重定向标准错误到文件
&>file : 重定向标准输出和错误到文件
/dev/null 是空设备,任何定向到它的数据都会被删除,可以用来压缩任何输出。
1 | find / -size 33c -user bandit7 -group bandit6 2>/dev/null |
Level 7→8
目标
下一关的密码保存在 data.txt 文件中的单词 millionth 后面。
可能会用到的命令
grep, sort, uniq, strings, base64, tr, tar, gzip, bzip2, xxd
这一关很简单,直接用 grep 就好。
1 | grep "millionth" data.txt |
Level 8→9
目标
下一关的密码保存在文件 data.txt中并且仅有一行只出现一次。
可能会用到的命令
grep, sort, uniq, strings, base64, tr, tar, gzip, bzip2, xxd
因为下一关的密码是唯一的一行,我们需要使用uniq -u命令来从 data.txt中获取。然而,uniq 只能从输入中过滤相邻匹配的行,所以我们需要在使用uniq前排序。因此,我们需要sort data.txt 并使用管道传递给uniq -u。
1 | sort data.txt | uniq -u |
Level 9→10
###目标
下一关的密码保存在 data.txt 文件中,只有少部分以’=’ 开头的字符串是可读的。
可能用到的命令
grep, sort, uniq, strings, base64, tr, tar, gzip, bzip2, xxd
使用 strings命令打印出文件中所有可打印的字符,然后用管道将其传递给 grep = 来查找所有的’=’。 输出的所有行将会包含’=’,其中之一会有密码。如果使用’==’来替代’=’,你会发现仅有4行结果。
1 | strings data.txt | grep == |
Level 10→11
###目标
下一关的密码保存在 data.txt文件中,它包含 base64 编码的数据。
可能用到的命令
grep, sort, uniq, strings, base64, tr, tar, gzip, bzip2, xxd
提示在于 base64 编码的数据。我们需要将 base64 编码的数据解码来获取下一关的密码。
1 | base64 -d data.txt |
Level 11→12
目标
下一关的密码保存在 data.txt 中,所有的小写(a-z)和大写(A-Z)字母都经过了13位翻转。
可能用到的命令
grep, sort, uniq, strings, base64, tr, tar, gzip, bzip2, xxd
从命令列表中发现,tr 命令用于变换或删除字符。使用方式:tr [OPTION] … SET1 [SET2]。SETs可以被表示为 CHAR1-CHAR2,其中所有的字符是以升序从 CHAR1 到 CHAR2。ROT13是翻转 a 到 n,b 到 o, c 到 p … z 到 m,大写字母类似。我们可以写出完整的列表或者简化版本。首先,我们需要通过管道将 data.txt 作为输入传给 tr。
1 | cat data.txt | tr abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ nopqrstuvwxyzabcdefghijklmNOPQRSTUVWXYZABCDEFGHIJKLM |
Level 12→13
###目标
下一关的密码保存在文件 data.txt 中,它是一个被重复压缩的 hexdump 文件。在这一关中,使用 mkdir 命令在 /tmp 目录下创建一个可以工作的目录是非常有用的。例如:mkdir /tmp/myname123。之后用 cp 复制 data.txt 文件并用 mv重命名。
可能用到的命令
grep, sort, uniq, strings, base64, tr, tar, gzip, bzip2, xxd, mkdir, cp, mv
从列出的命令来看,xxd 用来生成 hexdump 或者进行逆向。应该是会用到的。另外,这个文件被重复压缩了,所以我们也会需要gzip 和bzip2。就像目标中提及的,这需要进行几次迭代和一个临时的工作目录。
首先,我们将 hexdump文件逆向成二进制文件。使用 file 命令,我们可以查看文件的压缩格式。使用man gzip命令,我们可以查到解压的参数是-d 。如果我们现在使用gzip -d data2,这将会报未知后缀的错误。因此,我们需要在解压前重命名文件为.gz 后缀
1 | xxd -r data.txt data2 |
现在一个新的文件 data 已经在目录中了。再次使用 file 来查看文件的类型。data 是一个 bzip2 压缩文件。使用 bzip2 -d data 来解压。它会抱怨源文件名并添加一个 .out 后缀。
1 | file data |
重复类似的操作,可以得到下一关的密码。
1 | file data.out |
Level 13→14
目标
下一关的密码保存在 /etc/bandit_pass/bandit14 中,并且只能被用户 bandit14 读。在这一关中,你无法获得下一关的密码,但是你可以获得用于登录下一关的 SSH 私钥。注意:localhost 是你正在工作的机器的主机名。
可能用到的命令
ssh, telnet, nc, openssl, s_client, nmap
线索来自目标。首先一个 SSH 私钥已经在 bandit13 的用户目录下了。
1 | sshkey.private |
我们必须以 bandit14 的身份使用私钥进行登录。
1 | ssh -i sshkey.private bandit14@localhost |
在我们以 bandit14 的身份登录后,我们需要做的就是拿到下一关的密码。
1 | cat /etc/bandit_pass/bandit14 |
Level 14→15
目标
可以通过提交本关的密码到 localhost 上的 30000 端口来获取下一关的密码。
可能用到的命令
ssh, telnet, nc, openssl, s_client, nmap
1 | nc localhost 30000 < /etc/bandit_pass/bandit14 |
Level 15→16
###目标
可以使用 SSL 加密提交本关的密码到 Localhost 上的端口 30001来获取下一关的密码。
可能用到的命令
ssh, telnet, nc, openssl, s_client, nmap
在 openssl 的帮助页面上,s_client 命令实现了一个通用的 SSL/TLS客户端。用它来完成本关的挑战。
1 | openssl s_client -connect localhost:30001 -quiet < /etc/bandit_pass/bandit15 |
Level 16→17
目标
提交当前关的密码到 localhost 上范围31000-32000的一个端口上来获取下一关的密码。首先找到哪些端口正被服务器监听。之后找到哪些支持SSL,哪些不支持。仅有一个端口会返回下一关的密码,其它的则是返回你发送的数据。
可能用到的命令
ssh, telnet, nc, openssl, s_client, nmap
查看一下提供的命令,nmap 看起来是我们需要的。参数 -p 可用来指定扫描端口的范围。
1 | nmap -p 31000-32000 localhost |
有5个在扫描范围内开放的端口。我们可以检查每一个端口,发现 31790 是我们想要的。另外,我们可以写一个脚本,创建一个 /tmp/key 文件夹并将密钥保存在这。
1 | cat /etc/bandit_pass/bandit16 | openssl s_client -connect localhost:31790 -quiet > /tmp/key/b16pkey |
如果你这样使用密钥,是非常不安全的,因为每个人都可以看到它。原因在于该文件的读写权限对所有人都是开放的。我们需要改变它的读写权限让它仅对拥有者开放。
1 | chmod 600 /tmp/key/b16pkey |
之后我们就可以用它登录了。
1 | ssh -i /tmp/key/b16pkey bandit17@localhost |
下一关的密码在同样的位置。
1 | cat /etc/bandit_pass/bandit17 |
Level 17→18
目标
用户目录下有两个文件:passwords.old 和 passwords.new 。下一关的密码在 password.new 中,并且在新密码和旧密码中仅有一行不同。
可能用到的命令
cat, grep, ls
diff 命令会输出两个文件中所有不同的行。
1 | diff passwords.new passwords.old |
Level 18→19
###目标
下一关的密码保存在用户目录下的 readme 文件夹下。不幸的是,在你使用 SSH 登录的时候,某个人已经修改了 .bashrc 文件来将你登出。
可能用到的命令
ssh, ls, cat
从 ssh 的帮助文档中,我们可以在登录之后执行一个命令。因为我们已经知道密码保存在哪,我们可以在被登出前查看它。
1 | ssh bandit18@bandit.labs.overthewire.org cat readme |
Level 19→20
目标
为了进入下一关,你应该使用用户目录下的 setuid 二进制文件。在没有参数的情况下执行它来探索如何使用。在你正确使用了它后,下一关的密码可以在(/etc/bandit_pass)中找到。
查看用户目录,我们可以看到由bandit20创建的 bandit20-do文件,可以被bandit19访问。该文件的权限设置是 rws。s 权限意味着当该文件被执行时,它会在所有者的权限下运行。
1 | -rwsr-x--- 1 bandit20 bandit19 7237 Jun 6 2013 bandit20-do |
因为所有者是 bandit20,我们可以尝试运行它,并使用提升的权限来查看下一关的密码。
1 | ./bandit20-do |
让我们查看密码文件并获取下一关的密码。
1 | ./bandit20-do cat /etc/bandit_pass/bandit20 |
Level 20→21
目标
用户目录下有一个 setuid 二进制文件,它做下列事情:建立一个到 localhost 某一端口的连接,该连接可由你通过命令行参数指定。它之后会从连接处读入一行文本并和上一关(bandit20)的密码比较。如果密码是正确的,它将传回下一关的密码(bandit21)。
注意:为了通过这关,你需要登录两次:一次运行 setuid 命令,一次启动 setuid 将会连接的网络服务。
注意 2:尝试连接你自己的网络服务来查看是否如你想象的那样工作。
可以看到 suconnect 需要执行,让我们看看执行的结果。
1 | ./suconnect |
就像注意中所提示的,我们需要两个实例,一个用来监听端口,另一个读入和返回下一关的密码。我们使用 nc来监听我们选择的端口并发送这关的密码到该端口。
1 | nc -l 32123 < /etc/bandit_pass/bandit20 |
在另一个 ssh 会话中,我们在同一个端口启动 suconnect ,马上得到了回应。
1 | ./suconnect 32123 |
此时查看第一个会话,发现下一关的密码就在其中。
1 | gE269g2h3mw3pwgrj0Ha9Uoqen1c9DGr |
Level 21→22
目标
一个程序通过 cron 在规律的中断下自动运行,基于时间的作业调度。查看 /etc/cron.d 的配置来查看什么命令被执行了。
可能用到的命令
cron, crontab, crontab(5) (use “man 5 crontab” to access this)
从目标来看,我们可以访问 /etc/cron.d 并查找一些文件。名为 cronjob_bandit22 的文件看起来是我们感兴趣的。它展示了 cron_job_bandit22.sh 脚本的位置。我们来看看这个脚本。
1 | cat cronjob_bandit22 |
某人将 bandit22 的密码放入了临时文件中。我们再一次查看临时文件,找到下一关的密码。
1 | cat /tmp/t7O6lds9S0RqQh9aMcz6ShpAoZKF7fgv |
Level 22→23
目标
一个程序通过 cron 在规律的中断下自动运行,基于时间的作业调度。查看 /etc/cron.d 的配置来查看什么命令被执行了。
可能用到的命令
cron, crontab, crontab(5) (use “man 5 crontab” to access this)
和上一关做一样的事情,我们发现了下面这个脚本
1 | cat cronjob_bandit23 |
我们注意到 whoami 返回当前用户,也就是 bandit22。所以我们应该改变它,先运行一下这个脚本看看会发生什么。
1 | /usr/bin/cronjob_bandit23.sh |
所以我们将 bandit22 换成 bandit23,我们将会获得一个包含下一关密码的文件。长文件名是 mytarget 的 mds hash。我们得到这个长字符串并查看该文件的内容,即为我们下一关的密码。
1 | echo I am user bandit23 | md5sum | cut -d ' ' -f 1 |
Level 23→24
目标:
一个程序通过 cron 在规律的中断下自动运行,基于时间的作业调度。查看 /etc/cron.d 的配置来查看什么命令被执行了。
注意:这一关需要你自己创建自己的第一个 shell 脚本。这是一个非常大的进步。
1 | cat cronjob_bandit24 |
从脚本的描述来看,它将执行 $myname 文件夹下的所有脚本。我们在 /var/spool 目录下发现了 bandit24 文件夹。因此,让我们写一个脚本复制密码到临时文件夹中。
1 | mkdir /tmp/b23abc |
我们能复制文件到 /var/spool/bandit24 ,但是记住执行前必须设置权限。
1 | chmod 777 /tmp/b23abc/getpass.sh |
然而,在几分钟后,我们并没有在文件夹中获得 pass.txt 。我们忘记设置文件夹的权限,使得文件能被写入。完成后,我们就可以得到下一关的密码。
1 | chmod 777 /tmp/b23ac/ |
Level 24→25
目标
一个服务正在监听 30002 端口,如果将本关的密码和一个4位的 pincode 给它,它就会给你下一关的密码,我们没有办法获取这个 Pincode ,只能遍历 10000种组合,也就是暴力破解。
再一次,我在 /tmp 中创建一个文件夹,确保所有新创建的文件夹和所有和本关相关联的文件都有合适的权限。
1 | #!/bin/bash |
我选择使用 netcat(nc) 命令。pincode 通过一个 for 循环遍历生成。 ‘>>’将输出补充到 result 文件中。’&’让命令在后台进行,让它可以开始下一次迭代。
使用同样的策略来从文件中找到唯一的行,我们就可以看到下一关的密码了。
1 | $ sort result | uniq -u |