luCI 是 Openwrt 开发的 Web 系统,最典型的是自家的 Openwrt ,不少企业基于此系统魔改后成为自家系统(和安卓一个套路),如:水星、TP-LINK 等等。小米在此基础上将 uhttpd 更换为 Nginx 。
这些系统 Web 系统大致都一个样,分析思路、需要重点关注的文件(夹)、二进制程序调用关系、参数传递都是一套系统的,所以来总结一下。
从无 shell 和有 shell 两个大类分别记录。
2.1 无shell
l 网络请求 URL 中带有 stok 字样的 cookie,如下图所示
stok 是用户的 cookie ,是从 /dev/urandom 读取或者由 luci.sys.uniqueid(16) 生成等。
n 只要设备不关机 stok 的值就不会变(摄像头)
n 只要设备不关机、访问者 IP 不变 stok 的值就不会变(企业级设备、家用路由)
l URL 类似于:http://192.168.2.1/cgi-bin/luci/xxxx、http://192.168.2.1/cgi-bin/admin/xxxx,如下图所示。
实际设备中很少出现这种 URL 。厂商会设计一个中转 lua ,文件名常为 dsd.lua、ds.lua。数据以 json 传输 dsd.lua ,再调用其他 lua ,实现将其他 lua 创建的 node 作为 dsd.lua node 的子节点效果,只需要对 dsd node 进行访问权限配置等,子节点即可自动继承,还能缩短 URL 长度,具体在后文页面访问权限。
2.2 有shell
l Web 服务器是uhttpd ,二进制文件存放在 /usr/sbin
l 在/etc 会有 openwrt_release、openwrt_version记录 openwrt 版本文件。
l 在/sbin 、/usr/bin 能找到 lua、uci、luci 执行文件。
l 在/usr/lib/lua/luci 存放网站需要的 lua 脚本。
openwrt web 后台采用的是一个 web 后台进程 + 解析器与 lua + 各种静态资源。
下面分别先对每个部分使用的软件、编程语言、介绍,然后介绍其各自信息以及他们之间的联动关系。
3.1 uhttpd – Web服务器
3.1.1 uhttpd简介
uHTTPd 是一个 OpenWrt/LUCI 开发者从头编写的 Web 服务器。能够与 OpenWrt 的配置框架 (UCI) 整合。默认情况下它被用于 OpenWrt 的 Web 管理接口 LuCI 。支持包括 TLS (SSL)、CGI 以及 Lua 。
uHTTPd 是单线程的,但是支持多个实例 (例如,支持监听多个端口,每个端口都可以使用独立的文档根目录以及其他功能)。
openwrt 官方自建 git 仓库下载,uhttpd 地址:https://git.openwrt.org/?p=project/uhttpd.git
3.1.3 配置文件
配置文件路径:/etc/config/uhttpd
l option home’/www’:定义服务器文档根目录
l optioncgi_prefix ‘/cgi-bin’:定义 CGI 脚本的前缀,相对于 cgi 根目录。如果缺少此选项,则禁用 CGI 支持
l list lua_prefix ‘/cgi-bin/luci=/usr/lib/lua/luci/sgi/uhttpd.lua’:需要分派到嵌入式 Lua 解释器的 http 请求前缀,用于跳转外部程序对应的文件。如果缺少此选项,则禁用 Lua 支持。
需要修改该选项参考这篇文章:https://blog.csdn.net/qq_26202991/article/details/102621184
Web 端访问时,lua 脚本与 URL 对应关系见后文
l listindex_page ‘cgi-bin/luci’:用于目录的索引文件,例如在使用 php 时添加 index.php
3.1.4 在openwrt下互动报文
2022-04-24 报文格式已变化,采用 json
Request 报文首行为: request-line ,其中 type 有 GET、POST、HEAD 三种方式,然后最重要的是 url ,它告诉服务器所请求的资源。
Response 报文首行为: response-line ,其中最重要的是 code ,它告知客户端响应情况( found、redirect、error 等),然后跟一个简单的可读的短语。
两种报文后面具体的内容格式差不多,都是一些 headers (其中冒号前的 str 指明 header 型别),然后以一个空行标识 header 结束,后面是资料。对于 request ,只有 POST 型别的请求需要提交资料,其它型别的是没有资料的。Response 报文的资料就是 url 所指定的资原始档( html、doc、gif 等)。
3.2 lua – 脚本语言
3.2.1 lua简介
lua 是一种轻量小巧的脚本语言,用标准C语言编写并以源代码形式开放。
3.2.2 应用场景
- 游戏开发
- 独立应用脚本
- Web 应用脚本
- 扩展和数据库插件如:MySQL Proxy 和 MySQL WorkBench
- 安全系统,如入侵检测系统
3.3 UCI – 配置文件同一管理系统(工具)
3.3.1 UCI简介
UCI是 Unified ConfigurationInterface(统一配置界面)的缩写,意在OpenWrt整个系统的配置集中化,简单点来说 UCI 是一个配置文件同一管理系统。
各个程序配置文件分散在系统各处,如:/etc/network/interfaces, /etc/exports, /etc/dnsmasq.conf或者 /etc/samba/samba.conf ,且配置文件语法各不相同,在 OpenWrt 中你无需为此烦恼,我们只需更改 UCI 配置文件即可自动化配置路由器。
3.3.2 共同原则
OpenWrt 的所有配置文件皆位于 /etc/config/ 目录下。每个文件大致与它所配置的那部分系统相关。
不管是用文本编辑器、uci 命令行工具、shell 脚本、phpClua 程序,只要能够修改这些配置文件,就能达到控制系统参数的目标。
一些配置文件会因为厂家、设备不同配置文件互相之间存在出入,下面只作为一般情况下的对照参照,除了这些可能还有管理后台账号密码等厂商自定义配置文件。
文件位置 |
描述 |
/etc/config/dhcp |
dnsmasq和DHCP的配置 |
/etc/config/dropbear |
SSH服务端选项 |
/etc/config/firewall |
中央防火墙配置 |
/etc/config/network |
交换,接口和路由配置 |
/etc/config/system |
杂项与系统配置 |
/etc/config/etherwake |
以太网唤醒: etherwake |
/etc/config/httpd |
网页服务器配置选项(Busybox 自带httpd,已被舍弃) |
/etc/config/luci |
基础 LuCI 配置 |
/etc/config/uhttpd |
Web服务器配置(uHTTPd) |
/etc/config/upnpd |
miniupnpd UPnP服务器配置 |
/etc/config/ushare |
uShare UPnP 服务器配置 |
/etc/config/wifitoogle |
使用按钮来开关WiFi的脚本 |
/etc/config/wol |
Wake-on-Lan: wol |
诸如文档语法、uci 命令行工具用法查看官方文档:https://openwrt.org/docs/guide-user/base-system/uci。
3.4 luCI – Web管理界面
3.4.1 luCI简介
luCI 是 lua 与 UCI 两个项目的合体:luCI 是使用 lua 编写的 Web 管理界面,让用户以图形化方式修改 UCI 的配置文件,控制 OpenWrt 系统参数。
3.4.2 luCI目录结构
luCI 存储在 /usr/lib/lua/luci (从存储路径也能看出 luCI 是 lua 模块),分别为几个类别的目录:
l model 对应MVC 中的 M ,后文中 what is model 对这部分详细分析。
l view 对应MVC 中的 V ,后文中 what is view 对这部分详细分析。
l controller 对应MVC 中的 C ,后文中 what is controller 对这部分详细分析。
3.5 MVC运行模式(框架)
3.5.1 简介
MVC 全称 Model View Controller ,是模型(Model)、视图(Model)、控制器(Controller)的缩写,是一种软件设计典范,将业务逻辑、数据、显示界面分离的方法组织代码。
在 luCI 这里被设计为创建 Web 应用程序的模式,简单来说就是OpenWrt Web 后台运作模式。下面分别介绍三个模块的功能细节(三个模块对应 /usr/lib/lua/luci 下同名文件夹)。
l Model 是应用程序中用于处理应用程序数据逻辑的部分。通常Model 对象负责在数据中存取数据。
l View 是应用程序中处理数据显示的部分。通常 View 是依据模板创建页面(html)。
l Controller 是应用程序中处理用户交互部分。通常 Controller 复制从 View 创建的页面读取数据、控制用户输入,并向 Model 发送数据。
3.5.2 what is controller
3.5.2.1定义
Controller(控制器)是应用程序中处理用户交互部分。通常 Controller 负责从 View 创建的页面读取数据、控制用户输入,并向 Model 发送数据。
Controller 默认路径:/usr/lib/lua/luci/controller
3.5.2.2多用户管理
在登录界面用户名的选择很重要,luCI 是一个单用户框架,公用的模块放置在 */luci/controller/ 下面,各个用户的模块放置在 */luci/controller/ 下面用户名对应的文件夹里面,比如 admin 登录,最终的页面只显示 /luci/controller/admin 下面的菜单。
3.5.3 what is model
3.5.3.1定义
Model 是应用程序中用于处理应用程序数据逻辑的部分。通常 Model 对象负责在数据中存取数据。
model 默认路径:/usr/lib/lua/luci/model
3.5.4 what is view
3.5.4.1定义
View 是应用程序中处理数据显示的部分。通常 View 是依据模板创建页面(html)。
对应 controller 里面调用的静态页面文件
View 默认路径:/usr/lib/lua/luci/view
3.5.4.2动态页面生成
l 通过 cbi()/form()方法,它们利用 model 中定义的模板 map ,生成 html 文件
2 通过 template() 方法,利用 view 中定义的 htm(一种类似 html 的文件),直接生成界面。
3.5.4.3小结
controller、model、view 三者结合就构成一个功能页面,或者称为模块。了解一个模块的代码实现,有助于对 openwrt 的逆向分析,诸如:找出页面上功能项目对应的处理 lua 文件;寻找接口地址等等,这部分见后文一个模块的定义。
3.6 Web后台系统总结
使用基于 lua 语言和 UCI 系统编写的 luCI 作为 Web 管理后台,使用 luCI 默认的 Web 服务器 uhttpd
luCI 后台管理系统采用 MVC 模式开发与运行。
原文始发于微信公众号(山石网科安全技术研究院):LuCI系路由系统逆向分析-上篇