最近在测试IOT设备的时候,在逆向之后,找到漏洞,如何攻击就成了一个大问题,发包?怎么发?如何构造?这篇文章就来总结关于IOT设备的攻击路径,我们总得通过一个路径来完成一个攻击,一般情况下有两种方法,第一种是通过无线,另一个就是通过一些物理的手段,拿个榔头(不是)…,通过物理上的接口,这个接口可以是USB,可以是SD卡,这就与目标设备的底座更加相关一些,但是物理接口还是有很大的局限性,毕竟你得接触到设备,而且物理接口也种类繁多,所以这里不介绍,本文更多聚焦于无线这个层面,回到刚刚那个问题,发包?怎么发?如何构造?本文主要是解决这几个问题!

发包?怎么发?

在PWN中通常编写攻击脚本的时候,都是通过remote( )连接,然后send( )来发送攻击的载荷,send( )这么一个操作,其实就是往目标服务器发送一些数据的操作,不用pwntools能发吗?肯定能,毕竟remote( )和send( )函数本质还是socket那一套东西,pwntools只是做了一层封装,只用remote(“IP”,port)一条命令就创建了一个TCP/UDP的socket,然后直接调用socket就可以发送数据了

所以其中一条路径就是socket发包这条路,不管是UDP还是TCP的socket,都是往目标设备所监听的端口上发送数据,这个端口的背后就是二进制程序或者可以说是服务,本质上是一套逻辑,除了socket发,还有另一个方式是requests,笔者的理解它是往HTTP服务端发送数据,背后同样也是有一套逻辑来处理,不过requests发包和socket的发包是有区别的,笔者个人理解有两点:

  • 层次的不同,requests属于应用层中的HTTP的东西,socket属于传输层和网络层之间的东西,很容易知道socket比requests更底层一些,但是再怎么说HTTP层往下也是socket来实现的,只不过也是封了一层,让HTTP协议看起来更简单,一个request,一个respond,只不过requests请求的是一个域名或者说是一个url,然后通过dns解析成对于的IP地址也就是服务器的IP地址,然后再把报头加上数据载荷发过去,不过两者在发的时候都需要加上报头的一些参数的值才能到底漏洞点所在的位置
  • 背后处理的目标问题,requests发包最终会到80口的webserver,webserver会fork一个CGI进程来处理,而socket很大可能就单纯的一个二进制程序,但也不排除它与二进制程序传递参数

知道了有两种发包思路,也就有了两种路径,那在面对真实的设备的时候,如何去确定目标设备的这个漏洞到底是用socket来发,还是用requests来发呢?这里提两种方法:

  • 逆向,回溯整个触发的过程
  • 拿到shell之后查看监听端口背后的服务

对于第一种方法:

只能慢慢的去逆向,看他是通过HTTP来接收它的数据载荷然后处理的,还是通过socket接收来处理的,往往回溯都有一个很明显的特征,比如socket的创建,设置参数等等等

对于第二种方法:

就是去看看监听的端口,用netstat来看看有那些端口正在监听的端口,某个服务确实是在某个端口上监听,那就可以确认它的确是用socket来发的,有时候netstat不能查看对应的进程名,解决的方法通常是:传入一个支持netstat的二进制程序来查看对应进程名的busybox

以DIR-859为例,下面是shell中打印监听端口的信息,IP和端口以及所对应的服务的PID和名称都列出来了:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
# netstat -npl
Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address Foreign Address State PID/Program name
tcp 0 0 192.168.0.1:49152 0.0.0.0:* LISTEN 3959/httpd
tcp 0 0 0.0.0.0:5449 0.0.0.0:* LISTEN 18591/proxyd
tcp 0 0 192.168.0.1:80 0.0.0.0:* LISTEN 3959/httpd
tcp 0 0 127.0.0.1:80 0.0.0.0:* LISTEN 3959/httpd
tcp 0 0 192.168.0.1:45555 0.0.0.0:* LISTEN 2472/hostapd
tcp 0 0 0.0.0.0:53 0.0.0.0:* LISTEN 3369/dnsmasq
tcp 0 0 192.168.0.1:8182 0.0.0.0:* LISTEN 3959/httpd
tcp 0 0 0.0.0.0:63481 0.0.0.0:* LISTEN 689/fakedns
tcp 0 0 192.168.0.1:443 0.0.0.0:* LISTEN 2854/stunnel
tcp 0 0 fe80::e66f:13ff:fe35:bd34:49152 :::* LISTEN 3959/httpd
tcp 0 0 :::9999 :::* LISTEN 12515/telnetd
tcp 0 0 fe80::e66f:13ff:fe35:bd34:80 :::* LISTEN 3959/httpd
tcp 0 0 :::53 :::* LISTEN 3369/dnsmasq
tcp 0 0 fe80::e66f:13ff:fe35:bd34:8182 :::* LISTEN 3959/httpd
tcp 0 0 :::63481 :::* LISTEN 689/fakedns
udp 0 0 0.0.0.0:137 0.0.0.0:* 3982/nameresolv
udp 0 0 0.0.0.0:51342 0.0.0.0:* 807/arpmonitor
udp 0 0 0.0.0.0:53 0.0.0.0:* 3369/dnsmasq
udp 0 0 0.0.0.0:51815 0.0.0.0:* 3285/mDNSResponderP
udp 0 0 0.0.0.0:54760 0.0.0.0:* 2472/hostapd
udp 0 0 0.0.0.0:5353 0.0.0.0:* 3285/mDNSResponderP
udp 0 0 0.0.0.0:5355 0.0.0.0:* 3982/nameresolv
udp 0 0 0.0.0.0:1900 0.0.0.0:* 3959/httpd
udp 0 0 0.0.0.0:1900 0.0.0.0:* 2472/hostapd
udp 0 0 0.0.0.0:49007 0.0.0.0:* 807/arpmonitor
udp 0 0 0.0.0.0:63481 0.0.0.0:* 689/fakedns
udp 0 0 :::36006 :::* 3285/mDNSResponderP
....

上面所讲到的发包模型都是在IP层往上的构包,那想要控制更底层的发包,那就得用scapy这个python的库了,但笔者暂时还没遇到,就姑且放一放好了…

构造报文

按照上面的说法,那就有两种构造报文的思路,一个是socket,另一个即是request,构造起来都不困难,socket的构造和socket的通信十分相似,可参考《网络编程之socket编程》,关键是发送的数据是什么?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
import requests
import socket
from time import sleep

def send_payload(ip,port,pay):
sock=socket.socket(socket.AF_INET,socket.SOCK_DGRAM)
sleep(1)
sock.sendto(pay,(ip, port))
sleep(1)
sock.close()
if __name__ == '__main__':
ip = ""
port =
payload = build_header()
sleep(1)
send_payload(ip,port,payload)
sleep(5)

request的构造也同样简单,只要调用request包,然后发包即可:

1
2
3
4
5
6
7
8
import requests
from pwn import *

payload = " "
url = " "

requests.packages.urllib3.disable_warnings()
requests.post(url, data=payload, verify=False, timeout=1)

总结

写完整个总结下来,对整个攻击的路径也有一定的深入了,以后还有其他的攻击路径还得总结上,总得来说网络层面上面的攻击路径并不新鲜,说来说去还是那几种,但后续有没更底层的打法,只能待后续的跟进与学习了….