尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

Mongoose 安全审查指南:common_misc 公共工具、文件系统后端与 URL 解析安全面

Mongoose 安全审查指南:common_misc 公共工具、文件系统后端与 URL 解析安全面 嵌入式网络通信物联网【免费下载链接】mongooseEmbedded web server, with TCP/IP network stack, MQTT and Websocket项目地址https://gitcode.com/gh_mirrors/mon/mongoose点击查看免费下载导读本文围绕 Mongoose 嵌入式网络库Embedded web server, with TCP/IP network stack, MQTT and Websocket安全扫描区域规划文档 resources/specs/areas/common_misc.md 展开聚焦其划定的公共杂项安全面字符串/格式化/解析工具、URL 处理、哈希与 Base64 助手、文件系统后端、LittleFS 集成与 Flash 支持。文章以该文档列出的目标文件为骨架结合仓库源码逐层剖析路径遍历防护、路径规范化、URL 解析歧义等关键风险点并给出可落地的审查清单。读完本文你将掌握 Mongoose 公共工具层与文件系统/URL 解析模块的安全模型、已有防护机制及其边界具备对嵌入式 Web 服务端开展针对性安全审查的能力。区域范围common_misc 覆盖哪些安全面根据 resources/specs/areas/common_misc.md本区域的目标是常见工具代码、解析/字符串/格式化助手、URL 处理、哈希/Base64 助手、文件系统后端、LittleFS 集成与 Flash 支持主要文件包括编码与哈希src/base64.c、src/md5.c、src/sha1.c、src/sha256.c格式化与解析src/fmt.c、src/json.c、src/log.c、src/printf.c、src/str.cURL 与路径src/url.c、src/util.c存储层src/fs*.cPOSIX / packed / FAT 等后端、src/lfs.c、src/flash.c该文档还明确了两条审查边界一是仅聚焦这些文件及其安全面src/下其他代码只在需要确认可达性、数据流、状态、校验、缓解或影响时才可查看二是不得审查src/之外的代码或独立展开无关区域。这意味着本文所有源码证据都限定在 src 目录内。文档给出的两条区域专属安全指引Area-Specific Security Guidance构成本文的核心骨架文件系统后端审查打包文件系统与各后端是否存在路径穿越、未授权读写、覆盖或截断检查 POSIX、Windows、嵌入式文件系统、打包文件系统以及自定义mg_fs实现的路径规范化关注尾部斜杠混淆、NUL 字节截断、后端路径处理的大小写敏感性差异。URL 解析审查 scheme、host、port、IPv6 字面量、userinfo、百分号编码、内嵌 NUL、空 host、默认端口、path/query 边界混淆仅在攻击者输入能控制目标主机、协议或网络边界时才评估 SSRF 相关行为仅控制路径不算 SSRF。下文逐条结合源码展开。文件系统后端安全审查mg_fs 抽象一个统一入口多种后端所有文件系统操作都收敛到 src/fs.h 定义的struct mg_fs函数指针表struct mg_fs { int (*st)(const char *path, size_t *size, time_t *mtime); // 返回 MG_FS_* 标志 void (*ls)(const char *path, void (*fn)(const char *, void *), void *); void *(*op)(const char *path, int flags); // 打开文件 void (*cl)(void *fd); size_t (*rd)(void *fd, void *buf, size_t len); size_t (*wr)(void *fd, const void *buf, size_t len); size_t (*sk)(void *fd, size_t offset); bool (*mv)(const char *from, const char *to); // 重命名/移动 bool (*rm)(const char *path); // 删除 bool (*mkd)(const char *path); // 创建目录 };统一标志位MG_FS_READ 1、MG_FS_WRITE 2、MG_FS_DIR 4、MG_FS_EXCL 8src/fs.h。三个内置后端在 src/fs.h 声明mg_fs_posix、mg_fs_packed只读打包文件系统、mg_fs_fat。审查文件系统安全时关键是确认每条路径在到达op()/st()/rm()/mv()之前经历了怎样的校验因为mg_fs本身只是转发器mg_fs_open只是把fd与fs打包成struct mg_fdsrc/fs.c并不做任何路径清洗。因此路径安全完全取决于上层调用点如 HTTP 静态文件服务和后端实现。路径规范化mg_path_is_sane 是核心防线路径穿越的第一道闸门是 src/util.c 的mg_path_is_sane()bool mg_path_is_sane(const struct mg_str path) { const char *s path.buf; size_t n path.len; if (n 0 || path.buf[0] \0) return true; if (s[0] ~) return false; // 以 ~ 开头家目录展开拒绝 if (s[0] . n 1 s[1] .) return false; // 以 .. 开头拒绝 for (; n 0 s[0] ! \0; s, n--) { if ((s[0] / || s[0] \\) n 2 s[1] . n 2 s[2] .) return false; // 任何路径分量以 .. 开头拒绝 } if (n 0) return false; // 内嵌 NUL终止符不计入长度拒绝 return true; }从实现可见它同时防御了四类问题家目录展开~开头路径在类 UNIX 系统会被 shell/fopen展开直接拒绝..穿越既拒绝开头为..的路径也拒绝任意/或\之后紧跟..的路径分量注意它把 Windows 反斜杠与 POSIX 斜杠同等对待防止在 Windows 后端上用\..\绕过内嵌 NUL 截断C 字符串以\0结尾fopen(foo\0bar)实际打开的是foo。该函数在扫描时若遇到提前终止n 0但字符为\0即判定非法——这正是文档指引中NUL 字节截断的对应防护长度边界n 0或首字符为\0的空路径按安全处理由上层逻辑决定是否放行。该函数在 src/util.h 声明被 HTTP 静态服务等关键路径调用见下文uri_to_path2。HTTP 静态文件服务的完整防御链路径穿越的实战防护发生在 src/http.c 的uri_to_path2()其处理顺序本身就是一份教科书式的审查清单根目录拼接把请求 URI 追加到root_dir之后并在拼接前检查长度n 2 path_size直接回 400 Exceeded path size防止栈/堆缓冲溢出百分号解码用mg_url_decode()解码 URI 中 root 前缀之后的部分解码失败回 400 Invalid path。注意先解码再校验避免%2e%2e编码后的..绕过路径合法性对拼好的完整路径调用mg_path_is_sane()不合法回 400尾部斜杠裁剪while (n 1 path[n - 1] /) path[--n] 0;统一目录表示法目录语义目录无尾部斜杠时回 301 重定向Location: %.*s/目录存在时依次探测MG_HTTP_INDEX、index.shtml、index.html.gz目录列表开关MG_ENABLE_DIRLIST开启时才渲染列表页否则回 403src/http.c。此外uri_to_path()src/http.c支持用逗号分隔的前缀目录映射把不同 URI 前缀路由到不同根目录其mg_span逐段解析逻辑同样要纳入审查——恶意前缀配置或匹配歧义可能造成目录逃逸。另一个容易被忽略的点是目录列表页的注入防护listdir()src/http.c在渲染目录名时使用mg_print_html_esc做 HTML 转义src/http.c并以mg_url_decode后的 URI 为标题防止文件名或 URI 中的脚本注入存储型 XSS。审查时应验证所有用户可控字符串在输出前都经过转义。POSIX 后端的平台差异处理src/fs_posix.c 是审查的另一个重点因为它暴露了同一个mg_fs接口在不同平台上的语义差异打开模式POSIX 下MG_FS_READ→rbe带MG_FS_EXCL→wxbe否则 →abesrc/fs_posix.c。默认是追加写模式a而非截断写这本身就是对覆盖/截断风险的一层缓解e标志设置O_CLOEXEC避免句柄泄漏到子进程。Windows 路径转换的双向校验to_wchar()src/fs_posix.c先把 UTF-8 路径转 UTF-16再把转换结果转回 UTF-8 与原串比对不一致如包含 Windows 特殊语义字符则拒绝打开——防止同一字节序列在 UTF-8 与 UTF-16 视图下指向不同文件的规范化绕过。符号链接大小Windows 下stat对符号链接报告 size 为 0后端通过打开文件 seek 到末尾取真实大小src/fs_posix.c审查时需注意该回退逻辑不会把链接目标暴露给路径校验层。目录列表去重p_list()跳过.与..src/fs_posix.c避免无限递归与上级目录暴露。打包文件系统只读设计从根源消除写入风险src/fs_packed.c 实现的mg_fs_packed用于只读地服务内嵌在固件中的文件由pack工具生成到packed_fs.cpacked_open()在flags MG_FS_WRITE时直接返回 NULLsrc/fs_packed.cpacked_write恒返回 0rename/remove/mkdir恒返回 false——写入类操作在接口层即被拒绝不存在覆盖或截断风险文件查找mg_unpack()src/fs_packed.c对mg_mem_files数组做精确字节比较mg_scmp大小写敏感而数组内容是由构建期生成的固定路径字面量因此攻击者无法通过路径操作命中数组之外的数据mg_unpacked()src/fs_packed.c返回指向存储数据的零拷贝mg_strpacked_read()有pos len size的越界钳制src/fs_packed.cpacked_seek把pos钳制到size以内目录语义由is_dir_prefix()src/fs_packed.c判定某路径是任一文件路径的带/边界的前缀即视为目录。审查时注意n 0分支根目录与path[n-1] /的对称处理防止前缀误判导致目录列表泄露非预期条目packed_list()依赖文件列表按字母序排列的假设做去重src/fs_packed.c若构建工具输出顺序变化可能产生重复条目——这是文档指引中打包文件系统审查值得验证的实现细节。mg_fs_packed的完整定义见 src/fs_packed.c其只读语义与mg_fs接口的读写能力形成了明确的能力边界可作为自定义mg_fs实现的安全参考基线。原子写与 Flash/LittleFS 层通用文件写入走 src/fs.c 的mg_file_write()先写临时文件path .. 随机串mg_random_str以MG_FS_WRITE | MG_FS_EXCL独占创建写满后rm旧文件再mv原子替换失败则清理临时文件。这套临时文件 rename机制防止了半写状态下的文件截断与损坏mg_file_printf则在其上提供格式化写src/fs.c。Flash 与 LittleFS 集成方面src/flash.h 定义struct mg_flashstart/size/secsz/alignwrite_fn/swap_fn并通过mg_lfs_init(size)接入 LittleFSmg_ota_flash_begin/write/end组成 OTA 固件写入流水线。该层在MG_OTA或MG_ENABLE_LFS启用时编译。审查重点是分区交换swap_fn的原子性与写入对齐约束以及mg_file_write的临时文件路径是否可能与真实文件冲突。URL 解析安全审查单遍扫描的状态机mg_urlparsesrc/url.c 的urlparse()是全部 URL 能力的地基——它不分配内存只对原始字符串做单遍扫描记录key/user/pass/host/port/uri/end七个偏移量for (i 0; url[i] ! \0; i) { if (url[i] / i 0 u.host 0 url[i - 1] /) { u.host i 1; // 检测 // 定位 host 起点 u.port 0; } else if (url[i] ]) { u.port 0; // IPv6 字面量如 http://[::1]/bar } else if (url[i] : u.port 0 u.uri 0) { u.port i 1; // 端口分隔符 } else if (url[i] u.user 0 u.pass 0 u.uri 0) { u.user u.host; u.pass u.port; u.host i 1; u.port 0; // userinfo } else if (url[i] / u.host u.uri 0) { u.uri i; // 路径起点 } }把这份状态机与文档指引逐条对照可以精确标注每个风险点的处理位置文档关注点处理位置与结论scheme未在urlparse中显式解析由调用方用前缀比较判断如mg_url_is_sslhost 依赖//定位无//的串没有 hosthost / 端口mg_url_host()用port - host - 1或uri - host截取返回的mg_str不 NUL 结尾指向原串视图src/url.h调用方必须按长度使用IPv6 字面量]出现即重置portsrc/url.c支持http://[::1]/bar但未做 IPv6 语法校验userinfo只在user/pass/uri均未设置时生效src/url.cmg_url_user/mg_url_pass按偏移切片src/url.cuser 存在但无 pass 时也能正确截取百分号编码urlparse本身不解码解码发生在消费点HTTP 路径解码见 src/http.c这意味着 URL 各字段携带的编码字符在各消费点语义可能不一致是审查重点内嵌 NUL扫描以\0为终止条件url中的 NUL 会提前截断解析结果后续atoi/比较都只看到截断串——与mg_path_is_sane的 NUL 拒绝形成互补但URL 层本身不拒绝 NUL空 hosthttp:///path这类串host指向非空位置但长度可能为 0mg_url_host返回空mg_str连接层需自行处理默认端口mg_url_port()src/url.c按 scheme 给默认值http/ws→80、https/wss→443、mqtt→1883、mqtts→8883显式端口用atoi解析注意atoi对超范围/畸形数字的行为显式端口优先于默认值path/query 边界该解析器不区分 query 与 fragment/path?x1#f的uri止于第一个/query 被算进 uri 尾部消费端需自行切分——评估路径校验时须意识到 uri 可能带 querySSRF 相关性按文档要求仅在攻击者能控制目标 host/协议/网络边界时才评估 SSRFmg_url_host的输出被用于连接目标凡用户可控 URL 直入mg_url_host的场景如反向代理、连接复用都应列入 SSRF 审查scheme 判定与 TLS 边界mg_url_is_ssl()src/url.c用前缀匹配识别wss:、https:、mqtts:、ssl:、tls:、tcps:。它是 TLS 层选型的依据因此存在前缀混淆审查点例如httpsx://前缀匹配失败不会误判为 TLS但大小写变体HTTPS:同样无法识别——若上层对 URL scheme 做了大小写归一化可能与这里的前缀比较产生不一致。审查时应确认mg_url_is_ssl的判定结果与后续实际建立连接的协议一致。编码解码助手与安全用法URL 相关的编解码助手定义在 src/http.c 附近mg_url_encode只放行字母数字与._-~其余字符转%XXmg_url_decodesrc/http.c在解码时按目标缓冲长度钳制。安全编码实践是所有进入文件系统或数据库的路径参数必须先解码、再走mg_path_is_sane校验、后拼接顺序颠倒即产生%2e%2e类绕过。这正是uri_to_path2的既有顺序解码→校验可作为所有消费点的范式。其余工具面的审查要点文档列出的其余文件构成解析/字符串/格式化/编码哈希辅助层审查要点如下src/base64.cmg_base64_encode/mg_base64_decode被 HTTP Basic Auth 等场景使用如 src/http.c 对Authorization头解码。审查重点解码输出长度是否与目标缓冲匹配、畸形 padding/字符是否报错、解码结果是否被当作可信数据。src/md5.c/src/sha1.c/src/sha256.c纯算法实现。审查重点不是算法本身而是调用点是否把哈希当作认证凭据弱口令、无盐、可预测输入使用。src/printf.c提供mg_snprintf/mg_vmprintf等有界格式化输出。安全基线是格式化串永远不得来自外部输入——这一点与src/fmt.c的%M扩展机制配合使用时尤须注意%M允许回调打印任意内存如mg_print_hex、mg_print_html_esc回调的arg指针若来自攻击者可控偏移可能造成越界读取。src/str.c/src/util.cmg_str系列操作与通用工具。重点审查mg_str长度/终止符假设是否在所有分支成立以及mg_path_is_sane、mg_check_ip_aclsrc/util.c这类校验函数的默认策略ACL 为空时默认放行。src/json.cJSON 解析器重点审查嵌套深度限制、超大 token 计数导致的资源耗尽以及mg_json_get返回指针的生命周期指向原始缓冲。src/log.c日志宏MG_INFO/MG_ERROR/MG_VERBOSE与调试输出。审查重点是敏感信息泄漏——认证头、Cookie、私钥、固件内容不应进入日志MG_VERBOSE级别的路径回显如 src/http.c 的%lu %.*s - %s %d在正式构建中应被编译期关闭。审查清单与验证方法综合文档指引与源码证据对 common_misc 区域的落地审查可收敛为以下清单路径穿越对每个进入mg_fs的路径确认是否经过mg_path_is_sanesrc/util.c用../、..\、%2e%2e、~、/../变体做差分测试确认解码在校验之前。未授权读写确认打包文件系统只读语义packed_open拒绝MG_FS_WRITEPOSIX 后端默认a追加模式mg_file_write的临时文件用MG_FS_EXCL独占创建并原子替换。路径规范化覆盖 POSIX/Windows/嵌入式/打包/自定义mg_fs五种后端Windows 端验证to_wchar双向校验确实拒绝非常规编码src/fs_posix.c。尾部斜杠与目录语义验证目录 301 重定向逻辑、index.html/index.shtml/index.html.gz探测顺序、MG_ENABLE_DIRLIST关闭时的 403 行为。NUL 截断用含\0的路径/URL 做输入确认mg_path_is_sane拒绝路径层且消费点不会把截断结果当作完整输入。URL 歧义对http://[::1]:8080/p、http:///path、user:host、http://host:0/p、/path?q1等边界输入逐一比对mg_url_host/mg_url_port/mg_url_uri/mg_url_user/mg_url_pass的输出src/url.c确认与连接层、认证层的消费语义一致。SSRF 边界仅当用户输入能控制mg_url_host结果并流向连接目标时才评估 SSRF仅控制路径的场景按文档要求不纳入。编码与日志检查%M回调参数来源、Base64 解码缓冲长度、日志内容是否含敏感信息。验证时可在仓库内搜索所有mg_fs_open/mg_fs-op/mg_file_write/mg_url_host的调用点逐条确认其前置校验与后置处理再结合 test 目录中的单元测试与集成测试如 test/unit_test.c观察既有边界用例覆盖情况。结论common_misc 区域看似是杂项工具实则是 Mongoose 安全模型的承重墙文件系统后端决定了路径数据能否越权逃逸URL 解析决定了连接目标的归属而格式化/编码/哈希助手决定了攻击者可控数据能否污染后续处理。从源码看Mongoose 已在关键路径内置了多层防护——mg_path_is_sane的../~/NUL 拒绝、uri_to_path2的先解码后校验、打包文件系统的接口级只读、mg_file_write的原子替换、Windows 路径转换的双向校验——但每层防护都有明确的适用边界URL 层不拒绝 NUL、urlparse不解码百分号、目录前缀判定依赖排序假设、自定义mg_fs的路径安全完全依赖调用方。安全审查的价值正在于确认这些边界在每条可达路径上都被正确衔接。以此为清单结合 resources/specs/areas/common_misc.md 与 src 源码即可对 Mongoose 公共工具层开展完整、可复现的聚焦式安全评估。赞分享嵌入式网络通信物联网【免费下载链接】mongooseEmbedded web server, with TCP/IP network stack, MQTT and Websocket项目地址https://gitcode.com/gh_mirrors/mon/mongoose点击查看免费下载相关推荐freecodecamp.cn后端安全审计全面检查潜在漏洞freecodecamp.cn后端安全审计全面检查潜在漏洞 freecodecamp.cn作为国内领先的免费编程教育平台其后端安全直接关系到数百万学习者的数教育后端前端Dat安全审计终极指南评估P2P文件共享工具的安全性Dat安全审计终极指南评估P2P文件共享工具的安全性 在当今数字化时代数据安全已成为每个用户最关心的问题。Dat作为一款基于Hypercore协议的点对点文数据工程开发工具Lynis安全审计工具全面解析与入门指南Lynis安全审计工具全面解析与入门指南 Lynis是一款专为UNIX类系统设计的开源安全审计工具自2007年由Michael Boelen创建以来已成为网络安全应用安全合规审计漏洞扫描创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表