因为几年没打过CTF了,这次是赶鸭子上架。玄武组的比赛,这道题其实也不是我做出来的,我主要是做pwn和Reversa。
这个题我做了2/3的环节,最后一个环节是队友搞的,觉得蛮有意思的,于是就模拟了一个docker环境来复刻一下。
这是一道web题,其实我觉得根本不应该算一道web题,web的作用也仅仅是有一个reboot.txt文件,然后给出了ssh的用户名密码和一个wbStego4.bmp文件名称,bmp文件直接可以下载。
但是ssh只能通过私钥连接,直接下载wbStego4.bmp文件。通过wbStego4直接解密得到一个文本文件。
这一看就是一个ssh的公钥啊,base64解码header也是ssh-rsa。
好玩的地方来了,我开始也想过,直接枚举私钥,但是都失败了。最后想想,rsa非对称加密嘛,先把n和e提取出来,看看能不能分解n。
于是写了个小脚本如下:
import base64
import struct
from Crypto.Util.number import bytes_to_long
import gmpy2
def parse_ssh_pubkey(key_data):
try:
# 解码 base64 数据
binary_data = base64.b64decode(key_data)
# 读取键类型长度
length = struct.unpack('>I', binary_data[:4])[0]
# 跳过键类型
rest = binary_data[4+length:]
# 读取 e 的长度和值
e_length = struct.unpack('>I', rest[:4])[0]
e_bytes = rest[4:4+e_length]
e = bytes_to_long(e_bytes)
# 读取 n 的长度和值
rest = rest[4+e_length:]
n_length = struct.unpack('>I', rest[:4])[0]
n_bytes = rest[4:4+n_length]
n = bytes_to_long(n_bytes)
return n, e
except Exception as ex:
print(f"解析SSH公钥时出错: {str(ex)}")
return None, None
def main():
# SSH格式的公钥
pub_key_b64 = "AAAAB3NzaC1yc2EAAAADAQABAAABAHqSISYfkwuFeX20KTtyDhpG/nmyMK5MrmjKILUbLxpEtgw+4i0sIR4sWtNpGSVAMLZ4YO8EY6p7FBw0z4u0ALo2qC8I763lfKlNXH1WHWexRHd72MEpxpOzt79ukabEr7OWpRdDEISj3MyEalVNYGTKMt/TQWR/dnFd+TsDB2aRDBQQq9VfQhZ9Z864huQ4Du8PKg42plzfRPJsEhe4JpE0GW5QRap9ZNHM/4fSSHJlwqbBqGdeIjw+U7zY/RokxK979+f7SN6qMc9FzAUTnbwFGLpZe4ohz4pPJNrmRKfERTSKDoXw1krdDZuEZzCgiprpR8WqLvGoDXhYstcrgWU="
n, e = parse_ssh_pubkey(pub_key_b64)
if n is not None and e is not None:
print(f"成功提取公钥参数:")
print(f"n = {n}")
print(f"e = {e}")
print(f"n十六进制格式:")
print(f"n (hex) = {hex(n)}")
print(f"e (hex) = {hex(e)}")
# 如果成功找到p和q,可以计算d
# 假设已经找到p和q
'''
p = # 这里填入找到的p值
q = # 这里填入找到的q值
phi = (p-1) * (q-1)
d = int(gmpy2.invert(e, phi))
print(f"n私钥d = {d}")
'''
else:
print("未能成功提取公钥参数")
if __name__ == "__main__":
main()
执行成功得到n和e
其实到这一步我去在线分解n,没有结果,我也想过枚举爆破,但是都不现实,然后发挥优良作风,交给队友。
说一下,这个地方是让我觉得比较有意思的,因为比赛结束了,所以只能搭建一个docker环境来复现。
dockerfile文件如下:
FROM ubuntu:20.04
# 安装SSH服务器
RUN apt-get update &&
apt-get install -y openssh-server &&
mkdir /var/run/sshd &&
mkdir /root/.ssh
# 设置root密码(可选)
RUN echo 'root:password' | chpasswd
# 允许root用户SSH登录
RUN sed -i 's/#PermitRootLogin prohibit-password/PermitRootLogin yes/' /etc/ssh/sshd_config
# 添加公钥
RUN echo "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAHqSISYfkwuFeX20KTtyDhpG/nmyMK5MrmjKILUbLxpEtgw+4i0sIR4sWtNpGSVAMLZ4YO8EY6p7FBw0z4u0ALo2qC8I763lfKlNXH1WHWexRHd72MEpxpOzt79ukabEr7OWpRdDEISj3MyEalVNYGTKMt/TQWR/dnFd+TsDB2aRDBQQq9VfQhZ9Z864huQ4Du8PKg42plzfRPJsEhe4JpE0GW5QRap9ZNHM/4fSSHJlwqbBqGdeIjw+U7zY/RokxK979+f7SN6qMc9FzAUTnbwFGLpZe4ohz4pPJNrmRKfERTSKDoXw1krdDZuEZzCgiprpR8WqLvGoDXhYstcrgWU=" > /root/.ssh/authorized_keys
# 设置正确的权限
RUN chmod 700 /root/.ssh &&
chmod 600 /root/.ssh/authorized_keys
# 暴露SSH端口
EXPOSE 22
# 启动SSH服务
CMD ["/usr/sbin/sshd", "-D"]
部署好之后,我们要构建自己的私钥,这里直接用了 RsaCtfTool这个工具,我没仔细读代码,但是这个吊毛脚本就给出私钥了。原理我觉得事后我要去好好研究一下,蛮好玩的,毕竟几年没打CTF了,就跟个新手一样......
python3 RsaCtfTool.py -n "15473132342055954558780743503377112628799304584198645895267270016124133490922098456166112042641326832865833651985277530457678074443980433108579830298962133947433527712865590585431566632983430843501946695655887372383479716038917317269141215074859439934216381040714018271595168426357226026198765176618021081022415221237337044775954393916497106899407589200453955923849063288526403725531781699959251467756397025462984686365248488495366710314704482655593149707807258497477652225445069994376526985310824804739194259812224359792816573562797784525943054303945261131087499235482603191504292886444952159639040155783760580411749" -e "65537" –private
私钥就直接出来了[无语.gif]
好吧,启动docker环境测试一下
就是这个私钥~~~~~~
挺好玩的,rsa算法ssh这块算是贫道孤陋寡闻了,但是既然知道了,一定要追根溯源把原理弄得明明白白~~~~~~
wbStego4.bmp及环境下载,关注公众号回复 wbStego4 即可。
原文始发于微信公众号(蓝极战队):「CTF」网鼎杯玄武挺好玩的一道题,事后自建环境分享一下
- 左青龙
- 微信扫一扫
- 右白虎
- 微信扫一扫
评论