openwrt-rpcd服务ACL配置错误风险分析

前言

openwrt 是一个用于的 路由器 的开源系统。

其他类似的路由器系统相比它的更新速度非常的快,可以看看 github 的更新速度

https://github.com/openwrt/openwrt

感觉以后用到 openwrt 的路由器会越来越多,而且 openwrt 可以直接用 vmware 来运行,也减少了学习的成本。

本文介绍一下 openwrtubus 机制 以及怎么利用 rpcd 通过 http 来访问 openwrt 里面的 ubus. 最后以一个 cve 为例介绍 rpcd 配置过程失误导致的安全问题。

Openwrt Helloworld

编译

首先安装好需要的包

sudo apt-get update
sudo  apt-get  install  subversion  git-core
sudo  apt-get install  gcc g++ binutils patch bzip2 flex bison make autoconf gettext textinfo unzip sharutils gawk  ncurses-term zliblg-dev libncurses5-dev

然后去 github 下载源码包 (比较大,建议挂 ss 下载)

git clone git://git.openwrt.org/openwrt.git

更新编译依赖的包

scripts/feeds update -a
scripts/feeds install –a

然后通过

make menuconfig

配置一下编译参数,使他生成 vmdk 镜像文件

Tartget Images
    [*] Build VMware image files (VMDK)
    [*] ext4  ---> 

然后编译即可

make -j4 V=99

最后会在 bin/targets/x86/generic/ 目录下生成编译好的文件

我们使用 openwrt-x86-generic-combined-ext4.vmdk 即可。

挂载到vmware

然后新建一个 虚拟机, 选择目标操作系统为 其他 linux 64 位 的即可,然后后面选择硬盘时,使用刚刚生成的硬盘。

然后开机启动即可。

添加了那么多个网卡的原因是我这里前面几个网卡都是不能正常联网的,后面的就可以正常了~~~

这时不出意外,应该可以进入 shell 了。

基本配置

首先修改一下 root 的密码,方便 ssh 访问

passwd root

然后安装一个 web 界面,用来方便的管理路由器

opkg update
opkg install luci

然后启动 uhttpd

/etc/init.d/uhttpd start
/etc/init.d/uhttpd enable

这时由于防火墙的原因可能无法访问,由于是虚拟机,这里直接清空了 防火墙的规则

iptables -F

然后在浏览器上访问

http://server_ip/

ubus

介绍

ubusopenwrt 引入的一个消息总线,主要作用是实现不同应用程序之间的信息交互。

ubus 启动后会在后台运行 ubusd 进程,该进程监听一个 unix 套接字用于与其他应用程序通信。

其他应用程序可基于 libubox 提供的接口(或自己实现)与其通信。

用户可以使用 ubus 的命令行工具和 ubus 总线进行通信, 也可以使用 libubus.so 里面的 api 来和 ubus总线交互, 利用 uhttpd 的模块 和 rpcd 还可以实现通过 http 来访问 ubus 总线

如下图所示:

使用命令行工具与ubus交互

命令行工具的命令就是 ubus , 列举一下常用的选项

list

不加参数的话会列举出总线上所有的可用的命名空间。

[email protected]:~# ubus list
dhcp
dnsmasq
foo
log
network
network.device
network.interface
network.interface.lan
network.interface.loopback
network.interface.wan
network.interface.wan6
network.rrdns
network.wireless
service
session
system
uci

使用 -v 选项可以列举出 命名空间内方法的详细信息

[email protected]:~# ubus -v list
‘dhcp‘ @f236b80a
    "ipv4leases":{}
    "ipv6leases":{}
‘dnsmasq‘ @a7e0fefe
‘foo‘ @224fa516
    "bar":{"arg1":"Boolean","arg2":"Integer","arg3":"String"}
    "toto":{}
‘log‘ @fb3f988f
    "read":{"lines":"Integer","stream":"Boolean","oneshot":"Boolean"}
    "write":{"event":"String"}
‘network‘ @58aebe07
    "restart":{}
    "reload":{}
    "add_host_route":{"target":"String","v6":"Boolean","interface":"String"}
    "get_proto_handlers":{}
    "add_dynamic":{"name":"String"}
...............................................................
...............................................................
...............................................................

后面还可以加上命名空间的名字,使得只打印该命名空间内部的方法信息

[email protected]:~# ubus -v list network.device
‘network.device‘ @61cffe58
    "status":{"name":"String"}
    "set_alias":{"alias":"Array","device":"String"}
    "set_state":{"name":"String","defer":"Boolean"}

这里打印了 network.device 命名空间内的方法的信息。可以看到它有三个方法可以被调用。

call

使用 call 选项就可以调用指定命名空间的方法了。

[email protected]:~# ubus call  network.device status ‘{"name":"eth1"}‘
{
    "external": false,
    "present": true,
    "type": "Network device",
    "up": true,
    "carrier": true,
    "link-advertising": [

调用 network.devicestatus 方法,参数通过 json 数据格式传递,name 指定设备名 ,这里的作用就是获取 eth1 的设备信息。

一些 openwrt 内置的命名空间以及他们的参数说明信息 , 可以看 openwrt 的官方 wiki, 其他更多的命令信息也可以查看这个 wiki

https://wiki.openwrt.org/zh-cn/doc/techref/ubus?s[]=ubus

通过http与ubus交互

配置 uhttpd

首先需要修改 uhttpd 的配置文件, 使得 uhttpd 支持 ubus_prefix

修改 /etc/init.d/uhttpd

start_instance() {
...
 append_arg "$cfg" ubus_prefix "-u"
...
} 

修改 /etc/config/uhttpd

...
    option ubus_prefix /ubus
...

然后重启一下 uhttpd

/etc/init.d/uhttpd restart

之后可以通过

http://server_ip/ubus 

ubus 交互(使用 post 请求)

rpcd配置

通过 http 来与 ubus 总线进行交互是通过 rpcd 进行的。

rpcd 是有访问控制措施的。

其中访问控制配置文件位于 /usr/share/rpcd/acl.d 目录下

[email protected]:/usr/share/rpcd/acl.d# ls
hac425.json           luci-base.json        unauthenticated.json

hac425.json 是我后面新建的,内容为

{
        "hac425": {
                "description": "acl for hac425",
                "read": {
                        "ubus": {
                                "file": [ "*" ],
                                "log": [ "*" ],
                                "service": [ "*" ],
                        },
                },
                "write": {
                        "ubus": {
                                "file": [ "*" ],
                                "log": [ "*" ],
                                "service": [ "*" ],
                        },
                }
        }
}

这个定义就是允许 hac425 使用 file, log, service 命名空间下的所有方法。

需要为其他用户增加 ACL ,可以根据官方提供的配置文件 demo 进行修改。

这个目录下的文件名是没有作用的,起作用的是 json 文件里面的顶层元素,用于定义 访问控制针对的用户的用户名

unauthenticated.json 为例

{
    "unauthenticated": {
        "description": "Access controls for unauthenticated requests",
        "read": {
            "ubus": {
                "session": [
                    "access",
                    "login"
                ]
            }
        }
    }
}

这个文件定义了没有登录的用户(就是所有人)都可以使用的方法是

session 命名空间里面的 access, login 方法

调用 login 进行登录后会获得一个 ubus_rpc_session, 用于后面的 ubus 调用

curl -d ‘{ "jsonrpc": "2.0", "id": 1, "method": "call", "params": [ "00000000000000000000000000000000", "session", "login", { "username": "hac425", "password": "123"  } ] }‘  http://192.168.31.111/ubus

如果用户名密码正确的话会返回 (默认的用户名和密码是 root 的用户名和密码, 后面介绍怎么修改)

{
    "jsonrpc":"2.0",
    "id":1,
    "result":[
        0,
        {
            "ubus_rpc_session":"749e6006d3be1149e8ef23c7dd6cb7ac",
            "timeout":300,
            "expires":300,
            "acls":{
                "access-group":{
                    "hac425":[
                        "read",
                        "write"
                    ],
                    "uci-access":[
                        "read",
                        "write"
                    ],
                    "unauthenticated":[
                        "read"
                    ]
                },
                "ubus":{
                    "file":[
                        "*"
                    ],
                    "log":[
                        "*"
                    ],
                    "service":[
                        "*"
                    ],
                    "session":[
                        "access",
                        "login"
                    ]
                },
                "uci":{
                    "*":[
                        "read",
                        "write"
                    ]
                }
            },
            "data":{
                "username":"hac425"
            }
        }
    ]
}

里面会有一个 ubus_rpc_session 用于调用那些需要登录后才能调用的方法, 同时会显示所有可以通过 http 调用的方法。

用于 rpcd 认证的用户名和密码在 /etc/config/rpcd 设置

[email protected]:~# cat /etc/config/rpcd 

config login
  option username ‘hac425‘
  option password ‘$p$hac425‘
  list read ‘*‘
  list write ‘*‘
config login
        option username ‘test‘
        option password ‘$p$test‘
        list read ‘*‘
        list write ‘*‘

$p$test 表示使用用户名为 test 的系统用户的密码作为 rpc 认证的密码

所以需要增加一个用户,只需新建一个系统用户,然后增加一个 表项即可

config login
        option username ‘xxxxx‘
        option password ‘$p$xxxxx‘
        list read ‘*‘
        list write ‘*‘

获取到 ubus_rpc_session 后,就可以调用在 /usr/share/rpcd/acl.d 目录下设置好的允许调用的方法了。调用方法时用到的 json 数据的格式如下

{
  "jsonrpc": "2.0",
  "id": <unique-id-to-identify-request>,
  "method": "call",
  "params": [
             <ubus_rpc_session>, <ubus_object>, <ubus_method>,
             { <ubus_arguments> }
            ]
}

首先使用 list 显示方法的详细信息

 curl -d ‘{"jsonrpc":"2.0","method":"list","params":["749e6006d3be1149e8ef23c7dd6cb7ac","*"],"id":1}‘  http://192.168.31.111/ubus

返回结果比较多,截个图看看

打印了方法的参数信息。

接下来可以调用需要的方法,比如调用 file 命名空间内的 read 方法 读取 /etc/passwd 的文件内容

07:36 [email protected]:~ $ curl -d ‘{ "jsonrpc": "2.0", "id": 1, "method": "call", "params": [ "749e6006d3be1149e8ef23c7dd6cb7ac", "file", "read", { "path": "/etc/passwd" } ] }‘  http://192.168.31.111/ubus
{"jsonrpc":"2.0","id":1,"result":[0,{"data":"root:x:0:0:root:\/root:\/bin\/ash\ndaemon:*:1:1:daemon:\/var:\/bin\/false\nftp:*:55:55:ftp:\/home\/ftp:\/bin\/false\nnetwork:*:101:101:network:\/var:\/bin\/false\nnobody:*:65534:65534:nobody:\/var:\/bin\/false\ndnsmasq:x:453:453:dnsmasq:\/var\/run\/dnsmasq:\/bin\/false\nhac425:x:1000:1000::\/home\/hac425:\ntest:x:1001:1001::\/home\/test:\n"}]}

安全风险

ACL配置问题简述

rpcd 用于 rpc 调用,那么访问控制就非常重要。

rpcd 的配置就有个很大的坑,使用 官网 wiki 上的配置,来配置用户的 ACL ,就会发现 ACL 不成功的情况,而且也没找到可以正常 配置 ACL 的方法 ~_~....

以上面的例子为例, hac425 设置了 ACL ,允许其调用 很多方法

test 用户没有配置 ACL 那么他应该只能调用非常有限的方法比如(session 中的 login

但是实际测试发现 , test 也可以调用 允许 hac425 调用的方法,比如 file 命名空间内的 read 方法。

由于一些错误配置,就会导致很多不该提供给用户调用的 方法被暴露出来,可能会造成一些问题(比如暴露 file 命名空间,就可能造成文件泄露等)。

CVE-2017-11361分析

这个漏洞是由于 对 rpcd 的错误配置(感觉是使用了官方的配置导致配置失效),导致管理 web 界面的普通用户可以通过 rpcd 暴露的大量方法,实现代码执行。(由于最新版的 juci 已经不使用 rpcd ,所以没有搭建复现环境)

下面根据漏洞作者的博客,简述下漏洞发现流程。

首先通过抓包,发现有 rpc 调用的登录包

{"jsonrpc":"2.0","method":"call","params":["00000000000000000000000000000000","session","login",{"username":"user","password":"testing"}],"id":0}

然后返回了大量的可以被调用的方法。

<{"jsonrpc":"2.0","id":0,"result":[0,{"ubus_rpc_session":"eb3bd8e7beb01338b21533a89b678971","timeout":300,"expires":299,"acls":{"access-group":{"core":["read"],"juci-broadcom-dsl":["read"],"juci-broadcom-dsl-admin":["write"],"juci-broadcom-ethernet":["read","write"],"juci-broadcom-iptv":["read","write"],"juci-broadcom-vlan":["read"],"juci-broadcom-vlan-admin":["write"],"juci-ddns":["read","write"],"juci-diagnostics":["read","write"],"juci-dnsmasq-dhcp":["read","write"],"juci-dropbear":["read","write"],"juci-ethernet":["read"],"juci-event":["read"],"juci-firewall-fw3":["read","write"],"juci-igmpinfo":["read"],"juci-inteno-backup":["read","write"],"juci-inteno-provisioning":["read","write"],"juci-inteno-qos":["read","write"],"juci-inteno-voice-client":["read","write"],"juci-minidlna":["read","write"],"juci-mod-status":["read"],"juci-mod-system":["read","write"],"juci-natalie-dect":["read","write"],"juci-netmode":["read","write"],"juci-network-netifd":["read","write"],"juci-owsd":["read","write"],"juci-printer":["read","write"],"juci-realtime-graphs":["read"],"juci-samba":["read","write"],"juci-snmpd":["rea...............................

其中有可以用于文件读写的 readwrite 方法,以及可以增加 ssh_keyrouter.dropbear:add_ssh_key 方法,组合起来就可以写 ssh_key , 然后 ssh 连过去。

CVE-2018-10123 分析

这个漏洞利用的是 p910nd 打印服务对配置文件信息没做校验,利用 rpcd 暴露的 uci 命名空间内的方法来写配置文件 get root shell

首先看看 p910nd 打印机服务,官网 wiki

安装

opkg update
opkg install p910nd

此时默认配置文件内容为

[email protected]:/usr/share/rpcd/acl.d# uci show p910nd
[email protected][0]=p910nd
[email protected][0].device=‘/dev/usb/lp0‘
[email protected][0].port=‘0‘
[email protected][0].bidirectional=‘1‘
[email protected][0].enabled=‘0‘
[email protected]:/usr/share/rpcd/acl.d#

然后设置 enabled 选项为 1, 开启 p910nd 服务

[email protected]:/usr/share/rpcd/acl.d# uci set [email protected][0].enabled=1
[email protected]:/usr/share/rpcd/acl.d# uci show p910nd
[email protected][0]=p910nd
[email protected][0].device=‘/dev/usb/lp0‘
[email protected][0].port=‘0‘
[email protected][0].bidirectional=‘1‘
[email protected][0].enabled=‘1‘
[email protected]:/usr/share/rpcd/acl.d# /etc/init.d/p910nd restart
[email protected]:/usr/share/rpcd/acl.d# netstat -an| grep 9100
tcp        0      0 0.0.0.0:9100            0.0.0.0:*               LISTEN  

此时可以用 nc 连接 9100 端口和 打印机通信。

如果我们修改 [email protected][0].device 为 一个文件的路径,我们在 nc 连过去的时候就可以获取文件的内容,同时在文件末尾追加内容。

openwrt 新建一个文件做测试,同时设置 device 指向它,并重启服务,使修改生效

[email protected]:/usr/share/rpcd/acl.d# echo this_line_1 >/tmp/xx
[email protected]:/usr/share/rpcd/acl.d# cat /tmp/xx
this_line_1
[email protected]:/usr/share/rpcd/acl.d# uci set [email protected][0].device=/tmp/xx
[email protected]:/usr/share/rpcd/acl.d# uci show p910nd
[email protected][0]=p910nd
[email protected][0].port=‘0‘
[email protected][0].bidirectional=‘1‘
[email protected][0].enabled=‘1‘
[email protected][0].device=‘/tmp/xx‘
[email protected]:/usr/share/rpcd/acl.d# /etc/init.d/p910nd restart
[email protected]:/usr/share/rpcd/acl.d# netstat -an| grep 9100
tcp        0      0 0.0.0.0:9100            0.0.0.0:*               LISTEN
[email protected]:/usr/share/rpcd/acl.d# 

然后 nc 过去就可以获取 /tmp/xx 文件的内容,此时再输入内容,然后终止连接,输入内容就会写入输入的数据到文件末尾.

输入内容

05:36 [email protected]:~ $ nc 192.168.31.111 9100
this_line_1
line2_writed_by_nc
^C
06:25 [email protected]:~ $ 

查看修改,可以看到内容成功被修改

[email protected]:/usr/share/rpcd/acl.d# cat /tmp/xx
this_line_1
line2_writed_by_nc

这个 cve 是由于在用户登录后可以开启 p910nd 服务, 同时 我们可以访问 uci 命名空间中的一些方法,然后利用 rpcd 服务修改配置文件,就可以实现任意文件读写。

最后的利用方式是在 /etc/init.d/p910nd 追加了一句写 ssh key 的代码,然后在以后执行 /etc/init.d/p910nd 时就可以写入 ssh_key.

总结

对于 rpcd 要严格限制暴露出来的方法, 避免出现严重的问题

总结

对于 rpcd 要限制暴露出来的方法, 避免出现严重的问题

参考

http://www.cnblogs.com/nicephil/p/6768381.html#e4bdbfe794a8e696b9e6b395_2

https://neonsea.uk/blog/2017/07/17/cve-2017-11361.html

https://neonsea.uk/blog/2018/04/15/pwn910nd.html

原文地址:https://www.cnblogs.com/hac425/p/9416854.html

时间: 2024-08-01 14:52:17

openwrt-rpcd服务ACL配置错误风险分析的相关文章

IIS中遇到无法预览的问题(HTTP 错误 401.3 - Unauthorized 由于 Web 服务器上此资源的访问控制列表(ACL)配置或加密设置,您无权查看此目录或页面。)

在IIS中  依次执行如下操作: 网站--编辑权限--共享(为了方便可以直接将分享对象设置为everyone)--安全(直接勾选 everyone )--应用--确定. IIS中遇到无法预览的问题(HTTP 错误 401.3 - Unauthorized 由于 Web 服务器上此资源的访问控制列表(ACL)配置或加密设置,您无权查看此目录或页面.)

httpd服务的配置

httpd2.2安装 yum安装 # yum install httpd-2.2.15-26.el6.centos.x86_64 配置文档:编辑之前复制一份 vim /etc/httpd/conf/httpd.conf 1.ServerRoot "/etc/httpd"   服务器运行目录 配置文件.错误文档.日志的保持目录 2.端口 Listen [IP] PORT Listen 80 Listen 8080 这样,http://192.168.1.31:8080 就可以访问主页面了

Rsyslog日志服务安装配置

rsyslog服务端配置  centos6.4 x64系统  系统自带rsyslog 5.8版本 rsyslog 是一个 syslogd 的多线程增强版. 现在Fedora和Ubuntu, rhel6默认的日志系统都是rsyslog了 rsyslog负责写入日志, logrotate负责备份和删除旧日志, 以及更新日志文件 ################################### #首先部署好lamp环境,详情见lamp安装文档 #更新系统时间   rsyslog-mysql是rs

MVC扩展Filter,通过继承HandleErrorAttribute,使用log4net或ELMAH组件记录服务端500错误、HttpException、Ajax异常等

□ 接口 public interface IExceptionFilter{    void OnException(ExceptionContext filterContext);} ExceptionContext继承于ControllerContext,从中可以获得路由数据route data.HttpContext. □ 的HandleErrorAttribute是对IExceptionFilter的实现,默认是启用的 public static void RegisterGlobal

sshd服务基本配置和使用(201610改)

一.基于密钥认证的服务端基本安全设置:1.修改/etc/ssh/sshd_config,具体如下:Protocol 2  #只支持SSH2协议Port <端口号>  #修改默认端口号MaxStartups 5    #同时允许5个尚未登录的SSH联机MaxAuthTries 3 #最大登录尝试次数为3 GSSAPIAuthentication no #关闭GSSAPI认证ServerKeyBits 1024 #将ServerKey强度改为1024比特PermitEmptyPasswords n

openwrt l7过滤qos配置

openwrt l7过滤qos配置     电梯直达 1# 本帖最后由 木鸟 于 2010-7-27 10:22 编辑 openwrt的qos基于hsfc.提供了分类标记,流量控制等功能,可能还有整形实际使用下来效果很不错.像是基于优先级的公平队列. openwrt默认提供了四个队列级别Class          Packets          字节           Priority         17172         1666639         (1.6 MiB)Expre

LINUX服务部分配置【带图的可以在csdn上找 hanbim520账号下载,我做成的是PDF】

REDHAT 5 常用服务配置实例 适用于初学者的朋友 测试时候注意防火墙和selinux哦!! 生活其实很精彩--本文版权保留,任何人不得利用本文获取利益!!! [email protected],欢迎交流,交流才能进步!! 一.YUM服务的配置 1.为什么要首先配置YUM服务器 答:我们都知道,安装软件在装机的时候会加长装机时间,也可能造成物理存储空间的浪费,有些软件在后来 中不一定会用到.然后配置YUM服务器后会非常的方便,一旦需要什么软件(必须是光盘里面自带或者您自 行下载后放入软件库)

hadoop配置错误

经过上一周的郁闷期(拖延症引发的郁闷),今天终于开始步入正轨了.今天主要是解决hadoop配置的错误以及网络时断时续的问题. 首先说明一下之前按照这篇文章的方法配置完全没有问题,但是等我配置好了发现hadoop的版本和我的需求有点不一样,于是重新安装低版本的hadoop,结果就遇到问题了. 一,Hadoop错误 1. dataNode总是启动不了?  no datanode to stop 怎么解决的呢.不需要hadoop namenode -format:把 dfs/data 删除即可,res

iOS xmpp协议实现聊天之openfire的服务端配置(二)

本篇主要说一下如何利用命令行来正确配置MySql. 首先打开终端: 1.为mysql起一个别名 alias mysql=/usr/local/mysql/bin/mysql 2.创建mysql的管理员  admin(后期登陆用到) alias mysqladmin=/usr/local/mysql/bin/mysqladmin 3.设置root账号密码 mysqladmin -u root password 初始密码 4.连接数据库 mysql -u root -p  (提示输入刚才的密码) 5