红队打靶:Prime1详细打靶提权思路之OpenSSL解密(vulnhub)

目录

写在开头

第一步:enc查找与破解

第二步:md5格式生成

第三步:OpenSSL解密参数确定

第四步:OpenSSL解密(bash脚本)

第五步:提权

总结与思考

写在开头

 本篇博客是根据红队笔记大佬的视频进行打靶,本次靶机依然是vulnhub上的prime,本文详述了提权的思路,从获得初始立足点www-data的shell开始,最终提权为root的过程。本文核心利用了OpenSSL的解密过程。前述的模糊测试及wfuzz工具的使用、文件包含漏洞利用、wordpress CMS代码执行的过程见我的上一篇博客:

红队打靶:Prime1详细打靶思路之模糊测试+内核提权(vulnhub)

上一篇博客的提权使用了内核提权。利用了老版本linux内核的漏洞,虽然提权过程并不复杂,但这种方式并不“优雅”,并不推荐大家作为首选。利用内核提权是很暴力的,容易导致系统服务的中断/重启,被系统管理员发现。因此,本文使用其他方式,涉及知识点包括find命令寻找备份、md5哈希生成、OpenSSL加解密的参数设定、bash脚本的编写等。详细思路见红队比较大佬的视频:

「红队笔记」靶机精讲:Prime1 - 提权的另一种解法,彻底搞懂OpenSSL解密渗透提权,超强思路版。_哔哩哔哩_bilibili

prime是vulnhub中的一台用于OSCP考试练习的的靶机,链接见:

Prime: 1 ~ VulnHub

靶机下载链接见:

https://download.vulnhub.com/prime/Prime_Series_Level-1.rar

 特别注意,本文是从拿到www-data的shell开始的:

 下面我们就开始提权的过程。

第一步:enc查找与破解

拿到www-data的shell之后,应该先查看自身权限:

sudo –l

发现www-data能够以root权限执行/home/saket/enc这个东西,那么我们cd /home/saket之后,看看enc是个啥 

cd /home/saket
ls -liah

 果然有个enc,而且是个可执行文件,既然他说能够在无密码的前提下以root权限运行,那我们在此目录sudo执行试试。

sudo ./enc

 发现需要输入密码,那我们随便输入一个aaa试试,如上图,应该是失败了。此处应该是需要寻找密码,因此我们在整个系统中查找有没有备份信息,可能会泄露enc的密码信息。这也是打靶的常规思路,当发现登录或执行命令时需要密码,而我们此时不知道密码,可以在系统中寻找是否有信息泄露的位置,从而得到密码。根据经验,存放密码的地方可能是系统的备份,也可能管理员直接起名为password/passwd这样类似的名称,我们先在根目录开始寻找名称中存在backup字符的文件,命令如下:

find / -name "*backup*"

 其中/表示从根目录开始搜索,-name表示以文件名作为匹配,"*backup*"表示匹配字符串中包含backup的文件。运行结果如下:

 信息非常多,而且有好多都报错Permission denied(权限不允许),这种信息是没意义的,干脆把他丢弃掉,用2>/dev/null过滤:

find / -name "*backup*" 2>/dev/null

 结果依旧有很多,我们应当选择最有可能泄露密码的位置。搜索结果中有很多在/usr/share/help目录下,help是帮助,应该不会泄露这些密码,另外有关内核的.ko文件也不会是。使用此命令发现第一个查找的结果就是/var/backups,感觉很有可能,那我们试试看。进入目录/var/backups,看看里面有什么:

 里面还真有两个文件passwd.bak和shadow.bak。我们试试能不能查看,结果很可惜,权限不够,没法读:

 那说不定其他目录也有备份,再找找吧。回看刚才find命令的找到的文件,最底下有个/opt/backup,那我们再看看:

 进入目录/opt/backup,经过一系列的翻找,发现server_database目录下有个名为backup_pass的文件:

 那我们查看backup_pass试试:

cat backup_pass

 你说巧不巧,找到了!告诉我们enc的密码就是backup_password ,再回到/home/saket执行enc试试,输入密码backup_password 结果如下:

 成功了!enc执行之后显示了一个good。

第二步:md5格式生成

 就这?我辛辛苦苦找到了enc的密码,就是为了听你夸我一句good?那他肯定是干了点啥东西。先看看当前目录/home/saket有啥变化:

原来是运行enc之后,会吐出两个文件,enc.txt和key.txt,我们分别看看,先看enc.txt 

nzE+iKr82Kh8BOQg0k/LViTZJup+9DReAsXd/PCtFZP5FHM7WtJ9Nz1NmqMi9G0i7rGIvhK2jRcGnFyWDT9MLoJvY1gZKI2xsUuS3nJ/n3T1Pe//4kKId+B3wfDW/TgqX6Hg/kUj8JO08wGe9JxtOEJ6XJA3cO/cSna9v3YVf/ssHTbXkb+bFgY7WLdHJyvF6lD/wfpY2ZnA1787ajtm+/aWWVMxDOwKuqIT1ZZ0Nw4=

 感觉像一串乱码,也可能是一段密文。另外由于这个密文很长,估计是使用了某种方式对字符串进行了加密,并不是将较短的密码使用加密算法加密成定长的密文。再看看key.txt

I know you are the fan of ippsec.

So convert string "ippsec" into md5 hash and use it to gain yourself in your real form.

 结果就两句话,直译:我知道你说ippsec的粉丝,那就将ippsec转换为md5的哈希,以获得你自己的真实形式。什么是自己的真实形式?先不管了,总之先把这个ippsec转化为md5哈希,命令为:

echo –n 'ippsec' | md5sum

 加密结果为:

366a74cb3c959de17d61db30591c39d1

 使用-n是为了去掉结尾的换行符,意思就是,如果不使用-n,那么相当于对”ippsec/n”进行了md5哈希(不是我们本意),这是完全不同的结果,如下图:

 这个可以用指令man echo查看帮助,可以看到-n的作用就是不输出结尾换行符

  我们已经得到了hash值,是366a74cb3c959de17d61db30591c39d1。当然,也可以更优雅的直接得到:

echo -n 'ippsec' | md5sum | awk -F ' ' '{print $1;}'

 awk是对字符串进行处理的一个工具,awk -F ' ' '{print $1;}'意思是以空格为分割,打印其中第一个部分,这样就会只输出366a74cb3c959de17d61db30591c39d1 后面的‘-’不会输出。

 这样我们就得到了密钥366a74cb3c959de17d61db30591c39d1

第三步:OpenSSL解密参数确定

 接下来综合enc,key.txt的信息,可以推断出,这是要我们对密文enc.txt使用密钥OpenSSL进行解密。这是经验。我们可以看一下openssl的帮助

openssl –h

 这有一大堆标准命令和加密方式,标准命令中有enc,如果要想解密,我们必须要知道加密方式才行。这里我们采用的命令应该就是enc了,那么加密方式是啥呢?又有哪些参数呢?我们先看看enc命令的相关参数吧:

openssl enc –h

 这里关于OpenSSL有一大堆参数,我们这里要解密,要用到-d,另外enc.txt看起来相似base64编码的,那么我们还有使用-a,当然用-base64也行,还要使用密钥key,参数-K,可是有个问题,-K后参数的说明他写到,需要Raw key,in hex 意思是需要16进制的格式,我们刚才得到的md5应该没有转换为这个形式,因此需要转化为16进制形式。

 转换为16进制格式需要使用工具od,我们查看帮助od --help。 

 首先是输出格式-A,默认会输出片偏移offset的长度,这里我们不需要,因此选择None,参数为-A n。然后是16进制格式,我们要指定单字节单位十六进制数,参数为-t x1,具体情况可查看帮助,我就不在博客中赘述了。将ippsec的md5值转换为单字节单位的十六进制格式命令如下:

echo -n 'ippsec' | md5sum | awk -F ' ' '{print $1;}' |od -A n -t x1

 od前面的语句是用于生成没有空格的'ippsec'的md5值,然后使用od 进行16进制转换。这样生成的结果如下:

 使用此命令输出结果最后还有一个由换行符转换而来的空字符0a,我们不想要这个,干脆前面就把换行符干掉使用tr –d  ‘\n’去掉换行符(-d是删除delete的意思):

echo -n 'ippsec' | md5sum | awk -F ' ' '{print $1;}' | tr -d '\n' | od -A n -t x1

 继续进行处理,我们想把这个结果放在一行显示,同时去掉空格,再用tr –d 依次干掉换行和空格就好了,命令为:

echo -n 'ippsec' | md5sum | awk -F ' ' '{print $1;}' | tr -d '\n' | od -A n -t x1| tr -d '\n' | tr -d ' '

 最终结果为3336366137346362336339353964653137643631646233303539316333396431。这就是openssl解密过程中-K后面的参数,即密钥的16进制形式。下面我们就可以构造对enc.txt进行OpenSSL解密的命令,完整命令为:

echo "nzE+iKr82Kh8BOQg0k/LViTZJup+9DReAsXd/PCtFZP5FHM7WtJ9Nz1NmqMi9G0i7rGIvhK2jRcGnFyWDT9MLoJvY1gZKI2xsUuS3nJ/n3T1Pe//4kKId+B3wfDW/TgqX6Hg/kUj8JO08wGe9JxtOEJ6XJA3cO/cSna9v3YVf/ssHTbXkb+bFgY7WLdHJyvF6lD/wfpY2ZnA1787ajtm+/aWWVMxDOwKuqIT1ZZ0Nw4=" | openssl enc -d -a -cipher -K 3336366137346362336339353964653137643631646233303539316333396431

这一段参数非常长,echo后面引号内的内容就是enc.txt中的密文,使用OpenSSL enc进行解密,-d是进行解密,-a意思是base64解码(也可以直接用-base64),-K后面接参数密钥raw的16进制hex形式,关键就在于-cipher应该替换为解密的算法,前面我们查看openssl enc的帮助的时候。我们看到了许多加密算法:

 这么多可能的加密方式,我怎么知道这个OpenSSL是用哪个方式进行加密的呢?如果对密文的形式有了解的话,或许可以将加解密方式的范围缩小。但是对于我这种啥也不会的小白,似乎只能一个一个去尝试,把-cipher的位置依次换成这么多加解密方式。不过手工去尝试费时费力,不如想办法使用脚本。

第四步:OpenSSL解密(bash脚本)

 上一步说我们要想办法枚举所有的加密方式的可能。那么最好就是写一个bash脚本,依次遍历每个加密方式,带入OpenSSL的解密命令执行,看看哪个能成功解密出明文。既然要使用脚本进行遍历,我们首先要创建一个文件,把这个openssl –h的内容关于加密算法的内容复制到一个文件中。干脆起名为CipherTypeRaw(之后要对这个文件进行遍历),去掉其中无关的行,结果如下(就是vim和复制操作,不赘述了):

 有这么多种可能,我们对CypherTypeRaw进行处理,保证每个字符串独占一行,这样方便遍历。首先把所有空格替换为换行符,这样就可以保证每一项字符串独占一行,使用gsub()函数用于将空格替换为换行符,完整命令如下:

awk '{gsub(" ","\n");print}' CypherTypeRaw

 由于空格非常多,因此替换后的换行符也特别多,我们最好是把这些换行符都去掉,最简便的方法就是先排序sort,保证所有非空行聚集在一起再使用uniq,直接过滤掉重复的行,这样处理之后只剩一个空行了:

awk '{gsub(" ","\n");print}' CypherTypeRaw | sort | uniq

 我们把这个结果输入到文件,起名为CipherTypes,这就是处理好的文件,命令如下:

awk '{gsub(" ","\n");print}' CypherTypeRaw | sort | uniq > CypherTypes

 最后这个CypherTypes文件有99行,含第一行空行和98种加密方式。回到刚刚的OpenSSL解密命令中,现在我们可以构造bash脚本,写一个for循环,将CipherTypes中的每一行替换为上述命令中的-cipher,bash脚本如下:

for cipher in $(cat CypherTypes); do echo "nzE+iKr82Kh8BOQg0k/LViTZJup+9DReAsXd/PCtFZP5FHM7WtJ9Nz1NmqMi9G0i7rGIvhK2jRcGnFyWDT9MLoJvY1gZKI2xsUuS3nJ/n3T1Pe//4kKId+B3wfDW/TgqX6Hg/kUj8JO08wGe9JxtOEJ6XJA3cO/cSna9v3YVf/ssHTbXkb+bFgY7WLdHJyvF6lD/wfpY2ZnA1787ajtm+/aWWVMxDOwKuqIT1ZZ0Nw4=" | openssl enc -d -a -$cipher -K 3336366137346362336339353964653137643631646233303539316333396431 ;done

运行结果:

 确实看到了几行文字,到这里其实已经解密完成了,但我们还是想知道到底是哪一种解密方式成功解密,因此我们重新构造命令输出每次遍历的字符串(即解密方式)。由于使用其他解密方式都会报错,我们将报错信息丢弃2>/dev/null ,完整的命令为:

for cipher in $(cat CypherTypes); do echo "nzE+iKr82Kh8BOQg0k/LViTZJup+9DReAsXd/PCtFZP5FHM7WtJ9Nz1NmqMi9G0i7rGIvhK2jRcGnFyWDT9MLoJvY1gZKI2xsUuS3nJ/n3T1Pe//4kKId+B3wfDW/TgqX6Hg/kUj8JO08wGe9JxtOEJ6XJA3cO/cSna9v3YVf/ssHTbXkb+bFgY7WLdHJyvF6lD/wfpY2ZnA1787ajtm+/aWWVMxDOwKuqIT1ZZ0Nw4=" | openssl enc -d -a -$cipher -K 3336366137346362336339353964653137643631646233303539316333396431 2>/dev/null;echo $cipher;done

 可以更清晰的看到,可以用于解密的字符串,即加密方式为aes-256-ecb,因此,我们只要执行如下命令即可得到单纯的解密结果:

echo "nzE+iKr82Kh8BOQg0k/LViTZJup+9DReAsXd/PCtFZP5FHM7WtJ9Nz1NmqMi9G0i7rGIvhK2jRcGnFyWDT9MLoJvY1gZKI2xsUuS3nJ/n3T1Pe//4kKId+B3wfDW/TgqX6Hg/kUj8JO08wGe9JxtOEJ6XJA3cO/cSna9v3YVf/ssHTbXkb+bFgY7WLdHJyvF6lD/wfpY2ZnA1787ajtm+/aWWVMxDOwKuqIT1ZZ0Nw4=" | openssl enc -d -a -aes-256-ecb -K 3336366137346362336339353964653137643631646233303539316333396431

 这句话意思就是我们得到了saket的密码为tribute_to_ippsec,很可能就是saket账户ssh登录的密码。同时还有一个名为Victor的落款,不知道能不能用上。

第五步:提权

用ssh登录saket账户,并输入密码tribute_to_ippsec

 登录成功了,我们还是用看看自己是谁:

 果然是saket,ip地址也没问题,这个shell交互性差,还是用python拿到交互性更好的shell,先用dpkg -l | grep python看看有没有python,发现有,然后可以用如下命令拿到交互性更好的shell:

python -c "import pty;pty.spawn('/bin/bash')"

 既然想提权,那我们就先知道自己当前是啥权限:

sudo -l

提示我们,可以无密码的形式以root运行/home/victor/undefeated_victor,那咱就运行试试:

sudo /home/victor/undefeated_victor

 结果说,找不到/tmp/challenge这个文件,还给了一句提示:如果你能够打败我,就先挑战站在你面前的你。这啥意思啊?挑衅呢?既然他说找不到/tmp/challenge这个文件,那咱们就去tmp目录下看看:

 确实是没有名为challenge的文件呀,以root运行/home/victor/undefeated_victor会去运行/tmp/challenge,如果challenge中包含提权的指令,那么一旦运行就可以提权了,现在既然没有这个challenge文件,那咱就创建一个。尝试了一下,没有vim,那咱们就用echo的方式创建challenge并追加命令:

echo '#!/bin/bash' > challenge
echo '/bin/bash' >> challenge

 好了,challenge的提权文件已经创建好,接下来我们只要执行/home/victor/undefeated_victor应该就可以提权了:

 是我得意忘形了,提示没有权限,应该是刚创建的challenge文件没有执行权限。现在给challenge这个文件添加执行权限:

chmod +x challenge

 这样应该就可以执行了,再次执行/home/victor/undefeated_victor,即可提权成功

sudo /home/victor/undefeated_victor

成功拿到了root权限,在/root目录下可以看到root.txt,这个就是flag。至此打靶完成。 

总结与思考

 本文涉及知识点包括find命令寻找备份、md5哈希生成、OpenSSL加解密的参数设定、bash脚本的编写等。真是没想到,仅提权一个思路就可以总结这么多过程,不过本文篇幅较长还是因为对bash脚本已经一些字符串处理工具awk/od/tr等进行了详述。如果熟悉这个过程的话,渗透测试的过程应该不会很长。本文主要总结了OpenSSL解密的过程,至于为什么想到OpenSSL,主要还是根据enc和key.txt的提示,需要一定的经验才可。

 本文的思路相比于上一篇博客总结使用内核漏洞提权的方式,更为优雅,不容易造成系统的崩溃和服务的终止,是更推荐的思路。最后总结一下OpenSSL解密和提权全过程的思路:

enc查找与破解:拿到www-data权限后,提示我们去寻找enc,结果发现要执行enc需要密码,使用find命令查找备份,最后成功找到了enc的密码,执行后生成key.txt和enc.txt

md5格式生成:key.txt文档中提示我们生成ippsec的md5值,使用md5sum进行生成即可。

OpenSSL解密参数的确定:查看OpenSSL enc -h帮助可知,我们需要使用的参数包括-d解密,-a使用base64解码,-K [16进制单字节密钥],-解密方式。其中的解密方式我们无法确定。

OpenSSL解密:构造CipherTypes文件,每个解密方式独占一行,构造bash脚本通过for循环遍历CipherTypes判断解密方式,并成功解密,获得saket的ssh密码。

提权:常规思路,寻找以root权限执行的文件challenge,在对应的文件中加入获得shell的指令,执行即可提权。

 有关prime靶场的打靶就总结完毕了,没想到总结的篇幅还挺长的。虽然没有多少读者看这个红队打靶的专栏,但我还是想记录记录自己学习渗透测试的历程,也希望对得起未来的自己的。如果有读到这里的读者恳请多多点赞支持。有关打靶的问题也可以在评论区指出。后续我可能会继续打靶,也可能会总结一些渗透测试的技巧等等,希望读者多多支持。

猜你喜欢

转载自blog.csdn.net/Bossfrank/article/details/131235993