😇
牛牛的安全 Odin
  • 个人介绍
  • 数据安全
  • 工控安全
    • 工控概念
  • 车联网安全合规
    • R155
    • CSMS\VTA
    • GDPR认证
  • 车联网安全
    • 漏洞订阅
    • 汽车攻击时间轴
    • 汽车信息安全研究
      • 车厂安全需求 Custom Requirement
      • 安全威胁
      • 参考文章
      • Who’s Behind the Wheel?
      • 安全研究基础
      • 智能网联汽车安全渗透指标
      • 智能网联汽车软件安全测试关键技术研究
      • 基于硬件在环的整车控制器功能安全测试技术研究
      • 智能网联汽车信息安全解决方案
      • 自动驾驶汽车的安全性-识别挑战
    • ECU逆向案例
      • 特斯拉攻击链
      • 汽车动力系统ECU固件逆向工程初探
  • 物联网安全
    • IoT 技术和协议
    • 智能设备常规测试思路总结
    • 各种调试接口(SWD、JTAG、Jlink、Ulink、STlink)的区别
    • QEMU 系统仿真
      • 如何“用 QEMU 模拟它”
      • 处理加密的路由器固件
    • 自动分析Automated Approach
    • IOT渗透测试(一)
    • 物联网安全目录
  • 固件分析案例
    • 智能门锁、手环
      • MCU固件反汇编
      • 云丁鹿客门锁中bootloader和FreeRTOS的分析
      • 云丁鹿客门锁BLE通信的分析(下)
      • 云丁鹿客门锁BLE通信的分析(中)
      • 云丁鹿客门锁BLE通信的分析(上)
      • 华为智联旗下小豚AI摄像头的完整分析(下)
      • 华为智联旗下小豚AI摄像头的完整分析(上)
      • 海康萤石智能门锁的网关分析(4)
      • 海康萤石智能门锁的网关分析(3)
      • 海康萤石智能门锁的网关分析(2)
      • 海康萤石智能门锁的网关分析(1)
      • idapython编写和调试
      • 果加智能门锁的全面分析(下)
      • 果加智能门锁的全面分析(中)
      • 果加智能门锁的全面分析(上)
      • BLE智能手环
      • 耶鲁智能门锁的简单测试(下)
      • 耶鲁智能门锁的简单测试(上)
      • 耶鲁门锁漏洞
      • 对一款BLE灯泡的分析
      • BLE协议栈与Android BLE接口简介
    • 在IoT设备中查找端口对应进程的四种方法
    • 路由器命令执行
    • 对基于Philips TriMedia CPU的网络摄像机进行逆向工程
    • 从Microsoft Band以及 Hello Sense 设备中提取自己的历史数据
    • CVE-2021-22909- 深入研究 UBIQUITI 固件更新错误
    • 复现|摄像头固件重打包
    • Dlink_DWR-932B路由器固件分析
    • 针对小米九号平衡车的无接触式攻击
    • 记一次智能印章设备的漏洞挖掘
  • APP 逆向
    • Go二进制文件逆向分析从基础到进阶——综述
    • Switch APP逆向分析
  • 传统静态代码分析
    • 静态分析案例
      • ELF恶意软件的静态分析原理和方法(上)
      • ELF恶意软件的静态分析原理和方法(下)
    • 静态代码分析工具清单
    • 企业级静态代码分析工具清单
  • 应用安全测试
    • DAST、SAST、IAST
    • IAST 工具初探
  • 芯片架构
    • ARM指令集概念
    • ARM指令集
    • 冯·诺伊曼结构
    • 指令集
    • 处理器架构、指令集和汇编语言,三者有何关系?
  • 病毒分析
    • 熊猫烧香
  • 编程知识
    • REST API 教程
  • 流量分析工具
    • 卡巴斯基开源的智能手机流量劫持工具
    • 利用 Burp Suite 劫持 Android App 的流量(二)
    • 利用 Burp Suite 劫持 Android App 的流量(一)
  • 区块链安全
    • 安全多方计算
    • Chainalysis 团队从区块链的角度分析发现 2020 年最大的 4 起勒索软件攻击实现存在关联
  • 攻击案例
    • 特斯拉Powerwall网关可能受到黑客攻击
  • 移动应用
    • Mac上使用Charles抓包
    • 手机抓包工具汇总
    • APP渗透测试流程和技巧大全
    • 加壳和脱壳
    • 浅谈 Android Dex 文件
    • 移动应用漏洞分析样例分享
    • 移动应用常见漏洞分析
    • 移动应用漏洞分析工具介绍
    • 渗透测试流程详解 及 移动APP安全测试要点
    • Frida Android hook
  • 安全设计
    • 【软件安全设计】安全开发生命周期(SDL)
Powered by GitBook
On this page
  1. 固件分析案例

CVE-2021-22909- 深入研究 UBIQUITI 固件更新错误

https://www.zerodayinitiative.com/blog/2021/5/24/cve-2021-22909-digging-into-a-ubiquiti-firmware-update-bug

Previous从Microsoft Band以及 Hello Sense 设备中提取自己的历史数据Next复现|摄像头固件重打包

Last updated 3 years ago

早在二月份,Ubiquiti 发布了 Ubiquiti EdgeRouter 的新固件更新,修复了。该漏洞存在于固件更新过程中,允许中间人 (MiTM) 攻击者在系统执行自动固件更新时提供恶意固件映像,从而以 root 身份在设备上执行代码。该漏洞是由名为 awxylitol 的研究人员发现并报告给 ZDI 程序的。

这个漏洞听起来可能是人为的。坏人给设备提供坏固件,坏事就会发生。然而,不安全的下载漏洞自成立以来一直是路由器类别中多个 条目的支柱。此漏洞的影响非常微妙,值得进一步讨论。

路由器究竟如何执行固件更新?

根据,新的模板化操作命令add system image可用于通过命令行界面 (CLI) 更新路由器的固件。模板化的操作命令允许用户快速修改路由器的操作状态,而无需摆弄复杂的命令行参数。这简化了日常操作的过程并最大限度地减少了用户错误。我相信我们都听说过系统管理员不小心删除了关键文件、将自己锁在远离文明的设备之外等等的恐怖故事。模板化命令试图缓解这些问题。

Ubiquiti EdgeRouter 使用的模板系统由包提供。命令add system image在/opt/vyatta/share/vyatta-op/templates/add/system/image/node.def文件中定义。

$ cat node.def 
help:  Add a new image to the system 
 
run: sudo /usr/sbin/ubnt-fw-latest --upgrade

hosted with ❤ by

通过运行此操作命令,用户可以有效地调用ubnt-fw-latest带有--upgrade选项的脚本。此选项会导致ubnt-fw-latest脚本运行该upgrade_firmware()功能,该功能将检查以获取有关最新固件版本的信息,包括固件下载 URL。

#!/bin/bash 
 
 
#------------------------------------------------------------------------------- 
STATUS_FILE="/var/run/fw-latest-status" 
UPGRADING_FILE="/var/run/upgrading" 
REBOOT_NEEDED_FILE="/var/run/needsareboot" 
DOWNLOADING_FILE="/var/run/downloading" 
URL="https://fw-update.ubnt.com/api/firmware-latest" 
ACTION="refresh" 
CHANNEL="release" 
DEFAULT_URL="https://localhost/eat/my/shorts.tar" 
 
 
#------------------------------------------------------------------------------- 
while [[ $# -gt 0 ]] 
do 
    key="$1" 
    case $key in 
        -r|--refresh)           # Refresh status of latest firmware by 
        ACTION="refresh"        # fetching it from fw-update.ubnt.com 
        shift 
        ;; 
        -s|--status)            # Read latest firmware status from cache 
        ACTION="status" 
        shift 
        ;; 
        -u|--upgrade)           # Upgrade to latest firmware 
        ACTION="upgrade" 
        shift 
        ;; 
        -c|--channel)           # Target channel (release or public-beta) 
        CHANNEL="$2" 
        shift 
        shift 
        ;; 
        *)                      # Ignore unknown arguments 
        shift 
        ;; 
esac 
done 
# ... 
upgrade_firmware() {                                                                                   
    # Fetch version number of latest firmware                                                                       
    echo -n "Fetching version number of latest firmware... "                                             
    refresh_status_file @> /dev/null                                                                     
                                              
    # Parse status file                                                   
    local fw_version=`cat $STATUS_FILE | jq -r .version 2> /dev/null` || fw_version="" 
    local fw_url=`cat $STATUS_FILE | jq -r .url 2> /dev/null` || fw_version="" 
    local fw_md5=`cat $STATUS_FILE | jq -r .md5 2> /dev/null` || fw_version=""                       
    local fw_state=`cat $STATUS_FILE | jq -r .state 2> /dev/null` || fw_version="" 
    if [ -z "$fw_version" ] || [ "$fw_url" = "$DEFAULT_URL" ]; then 
        echo "failed"                                                            
        exit 42                                                                  
    else                
        echo "ok"                                                                
        echo " > version : $fw_version"                                                                
        echo " > url     : $fw_url"                                                        
        echo " > md5     : $fw_md5"                                    
        echo " > state   : $fw_state"                                 
        echo                                                                     
    fi                            
                                                                                 
    if [ "$fw_state" == "can-upgrade" ]; then                                    
        echo "New firmware $fw_version is available"                                                     
        echo                               
        sudo /usr/bin/ubnt-upgrade --upgrade-force-prompt "$fw_url"                  
                                                                                 
    elif [ "$fw_state" == "up-to-date" ]; then 
        echo "Current firmware is already up-to-date (!!!)" 
        echo                                                              
        sudo /usr/bin/ubnt-upgrade --upgrade-force-prompt "$fw_url"                                      
                                           
    elif [ "$fw_state" == "reboot-needed" ]; then                                
        echo "Reboot is needed before upgrading to version $fw_version" 
                                                           
    else                    
        echo "Upgrade is already in progress" 
    fi                                                                                 
}                                                                              
                                                                                 
#-------------------------------------------------------------------------------   
if [ "$ACTION" == "refresh" ]; then                                 
    refresh_status_file                                       
                                   
elif [ "$ACTION" == "status" ]; then 
    read_status_file                                                             
                                                                                 
elif [ "$ACTION" == "upgrade" ]; then                                                      
    upgrade_firmware                  
fi

该函数继续解析服务器的结果并将其与当前固件版本进行比较。如果有可用更新,脚本将调用ubnt-upgrade以从fw-download.ubnt.com升级服务器提供的域中获取固件。然后它将执行实际的固件升级。

错误 - ZDI-21-601

问题在于/usr/bin/ubnt-upgradebash 脚本下载固件的方式。该get_tar_by_url()函数使用该curl命令来执行提取。但是,开发人员指定了 -k 选项(也称为–insecure选项),该选项禁用了 TLS 连接的证书验证。

get_tar_by_url () 
{ 
    mkdir $TMP_DIR 
    if [ "$NOPROMPT" -eq 0 ]; then 
        echo "Trying to get upgrade file from $TAR" 
    fi 
  
    if [ -n "$USERNAME" ]; then 
        auth="-u $USERNAME:$PASSWORD" 
    else 
        auth="" 
    fi 
  
    filename="${TMP_DIR}/${TAR##*/}" 
    if [ "$NOPROMPT" -eq 0 ]; then 
        curl -k $auth -f -L -o $filename $TAR      # <-----  
    else 
        curl -k $auth -f -s -L -o $filename $TAR   # <----- 
    fi 
    if [ $? -ne 0 ]; then 
        echo "Unable to get upgrade file from $TAR" 
        rm -f $filename 
        rm -f $DOWNLOADING 
        exit 1 
    fi 
  
    if [ ! -e $filename ]; then 
        echo "Download of $TAR failed" 
        rm -f $DOWNLOADING 
        exit 1 
    fi 
  
    if [ "$NOPROMPT" -eq 0 ]; then 
        echo "Download succeeded" 
    fi 
  
    TAR=$filename 
}

由于/usr/sbin/ubnt-upgrade不检查证书的有效性,攻击者可以使用自签名证书来欺骗fw-download.ubnt.com域,而不会在设备上触发任何警告或投诉来提醒用户。此漏洞显着降低了发起成功攻击所需的技能障碍。

要利用此漏洞,攻击者可以修改现有的 EdgeRouter 固件映像并修复文件中包含的校验和。在提交的概念验证中,研究人员修改了rc.local文件以使用反向 shell 连接回攻击者。重新启动是升级过程的一部分,会触发rc.local脚本。

结论

如果攻击者将自己作为 MiTM 插入,他们就可以冒充 Ubiquiti 控制的“fw-download.ubnt.com”域。但是,要成功地从该域中提供恶意固件,攻击者通常需要获取带有域私钥的有效证书。要继续进行,攻击者可能需要侵入 Ubiquiti 或说服受信任的证书颁发机构 (CA) 为攻击者颁发 Ubiquiti 域的证书,这绝非易事。但是,由于此错误,无需获取证书。

还应该注意校验和不是加密签名的替代品。校验和可以帮助检测传输中的随机错误,但不能提供数据真实性的硬证明。

脚注

谨慎的 EdgeRouter 用户寻求如何正确升级设备的建议,应避免使用自动升级功能进行此更新。他们可能希望从浏览器手动下载固件文件,并在通过 Web 界面将固件文件上传到设备执行手动升级之前验证固件的哈希值。

hosted with ❤ by

hosted with ❤ by

问题的核心是固件二进制文件缺乏身份验证。安全通信通道的功能是提供机密性、完整性和身份验证。在 TLS 中,加密提供机密性,消息摘要(或TLS 1.3 中的)提供完整性,证书验证提供身份验证。如果没有验证证书,客户端将在通信通道中进行身份验证。在这种情况下,客户端可能会“安全地”与恶意行为者对话。

最后一个考虑因素是。在这种情况下,固件及其关联的哈希值都可能被恶意版本替换。这种情况只能通过对固件文件本身应用加密签名来缓解。也许 Ubiquity 会转而使用加密方式签署固件二进制文件,这将提高其客户的整体安全性。

Ubiquity 在其安全更新中通过从模板化命令中删除-k( --insecure) 标志来解决此错误。

CVE-2021-22909/ZDI-21-601
Pwn2Own
获奖
Ubiquiti 文档
vyatta-op
view raw
CVE-2021-22909-snippet-1.console
GitHub
Ubiquiti 更新服务器
view raw
CVE-2021-22909-snippet-2.bash
GitHub
view raw
CVE-2021-22909-snippet-3.bash
GitHub
AEAD
供应商的网站可能会受到损害
v2.0.9-hotfix.1