
curl--path-as-is详解按原样保留 URL 路径中的../与./序列【免费下载链接】curlA command line tool and library for transferring data with URL syntax, supporting DICT, FILE, FTP, FTPS, GOPHER, GOPHERS, HTTP, HTTPS, IMAP, IMAPS, LDAP, LDAPS, MQTT, MQTTS, POP3, POP3S, RTSP, SCP, SFTP, SMB, SMBS, SMTP, SMTPS, TELNET, TFTP, WS and WSS. libcurl offers a myriad of powerful features项目地址: https://gitcode.com/GitHub_Trending/cu/curl--path-as-is是 curl 命令行工具提供的一个布尔开关用于关闭 curl 对 URL 路径中/../与/./序列的默认合并squash处理让请求按用户输入的原始路径原样发送。它在调试路径穿越类安全问题时尤其有用同时 libcurl 用户也可通过CURLOPT_PATH_AS_IS选项在编程接口中获得相同行为。读完本文你将掌握curl 默认如何规范化 URL 路径、--path-as-is的触发与生效范围含重定向场景、libcurl 侧对应的 API 用法以及底层dedotdotify()实现与单元测试证据。选项速览属性值长选项--path-as-is帮助文本Do not squash..sequences in URL path引入版本7.42.0见 docs/cmdline-opts/path-as-is.md分类curl取值布尔开关Multi: boolean可在命令行中与--no-path-as-is配对使用相关选项--request-targetSee-also 指定用于自定义请求目标官方示例--path-as-is https://example.com/../../etc/passwd该选项在 curl 工具的参数表中注册为布尔类型见 src/tool_getparam.c 中的{path-as-is, ARG_BOOL, , C_PATH_AS_IS}解析后存入 src/tool_cfgable.h 的BIT(path_as_is)标志位src/config2setopts.c在生成curl_easy_setopt调用时会根据该标志输出对应的设置代码。curl 默认行为按 RFC 3986 规范化路径正常情况下curl 会“squash压平或 merge合并”URL 路径中的/../与/./序列这一行为遵循 RFC 3986 的规范化规则。也就是说即使你在命令行里显式写入了../curl 在解析 URL 阶段也会把它们消除后再发起请求# 默认行为../ 与 ./ 会被按规范合并 curl https://example.com/../../etc/passwd curl https://example.com/a/./b/../c上述命令实际请求的目标会被规范化例如/../../etc/passwd被合并为/etc/passwd/a/./b/../c被合并为/a/c等。这种默认处理符合大多数场景的预期但当你需要调试路径相关的安全问题、或希望请求字面上携带这些点序列时就需要关闭它。--path-as-is按原样保留路径设置--path-as-is后curl 不再对 URL 路径中的/../与/./做任何合并处理而是把用户给定的路径原样as-is用于请求# 关闭路径规范化路径中的点序列原样保留 curl --path-as-is https://example.com/../../etc/passwd curl --path-as-is https://example.com/a/./b/../c这与文档中的官方示例一致见 docs/cmdline-opts/path-as-is.md。一个典型的实际用途是验证目标服务器如何处理带有路径穿越特征的请求如测试反向代理、Web 应用防火墙或后端框架的路径解析差异此时必须在请求行中原样携带这些序列。底层原理CURLU_PATH_AS_IS标志与dedotdotify()标志定义libcurl 的 URL API 层通过CURLU_PATH_AS_IS标志位控制是否执行点序列移除定义于 include/curl/urlapi.h#define CURLU_PATH_AS_IS (1 4) /* leave dot sequences */注释“leave dot sequences”直白地说明了该标志的语义保留点序列。路径解析入口URL 解析器在handle_path()中根据该标志决定是否规范化路径见 lib/urlapi.cif(!(flags CURLU_PATH_AS_IS)) { /* remove ../ and ./ sequences according to RFC3986 */ char *dedot; int err dedotdotify(path, pathlen, dedot); if(err) return CURLUE_OUT_OF_MEMORY; if(dedot) { curlx_free(u-path); u-path dedot; } }可以看到当标志位未设置时路径会交给dedotdotify()按 RFC 3986 第 5.2.4 节规则移除../与./当标志位被设置时整个规范化步骤被跳过路径保持原样。标志值会透传到内部接口见 lib/urlapi-int.h 的U_CURLU_PATH_AS_IS映射。dedotdotify()的实现细节dedotdotify()是路径规范化的核心函数定义于 lib/urlapi.c其算法完全按 RFC 3986 5.2.4 节实现先通过needs_dedotdot()快速判断路径中是否真的存在需要处理的点序列若没有则直接返回避免无谓开销见 lib/urlapi.c移除路径开头的../、./前缀以及仅由.或..构成的整段路径lib/urlapi.c循环处理路径中的每个段遇到/./或结尾的/.时替换为/遇到/../或结尾的/..时用memrchr找到输出缓冲区中最后一个/并截断即“删掉上一段及其前置斜杠”lib/urlapi.c其余普通段按原样拷贝到输出缓冲区lib/urlapi.c。该函数是UNITTEST标记的单元测试目标unittest 1395配套测试见 tests/unit/unit1395.c其中覆盖了大量边界用例例如/a/b/c/./../../g→/a/g/hello/../moo→/moo/../../moo→/moo开头多余的..直接丢弃/a/%2e/g→/a/gURL 编码的.同样被识别处理/1..→/1..1..不是独立的.段原样保留///moo.→///moo.、/.config/../ssh→/ssh等注意一个细节dedotdotify对百分号编码形式的点%2e、%2E同样执行规范化因此默认模式下编码的%2e%2e也逃不掉合并而--path-as-is会连同这些编码序列一起原样保留。在 curl 请求流程中的生效位置--path-as-is并非在发送阶段临时修改路径而是在URL 解析阶段就把标志传给curl_url_set()从而影响整个请求后续使用的规范化 URL。主请求create_conn阶段的 URL 解析在建立连接前的 URL 规范化处lib/url.cpath_as_is被折算为CURLU_PATH_AS_IS标志参与解析uc curl_url_set(uh, CURLUPART_URL, Curl_bufref_ptr(data-state.url), (unsigned int)(CURLU_GUESS_SCHEME | CURLU_NON_SUPPORT_SCHEME | (data-set.disallow_username_in_url ? CURLU_DISALLOW_USER : 0) | (data-set.path_as_is ? CURLU_PATH_AS_IS : 0)));重定向场景--path-as-is对Location重定向目标同样生效在 lib/http.c 的重定向处理逻辑中解析重定向 URL 时同样带入了CURLU_PATH_AS_IS标志因此跟随重定向后路径中的点序列也保持原样。其他依赖 URL 重写的场景见 lib/http1.c 等也会引用该标志保持行为一致。libcurl 编程接口CURLOPT_PATH_AS_IS对于使用 libcurl 的开发者命令行选项对应的是CURLOPT_PATH_AS_IS定义于 include/curl/curl.hCURLOPT(CURLOPT_PATH_AS_IS, CURLOPTTYPE_LONG, 234),其 setopt 处理位于 lib/setopt.c直接将传入值写入连接数据中的path_as_is字段case CURLOPT_PATH_AS_IS: s-path_as_is enabled; break;使用方式curl_easy_setopt(curl, CURLOPT_PATH_AS_IS, 1L);此外URL API 的CURLU_PATH_AS_IS标志见 include/curl/urlapi.h也可直接用于curl_url_set()对单个 URL 句柄进行精细控制这在需要“同一个程序里一部分 URL 规范化、一部分保留原样”时更加灵活。典型使用场景与注意事项安全研究与调试验证服务器、代理或 WAF 对../路径穿越请求的实际响应--path-as-is可确保请求行中的路径与命令行输入完全一致兼容特定后端少数后端要求请求路径字面包含点序列默认规范化会破坏这类请求重定向链路排查由于该选项对重定向同样生效见 lib/http.c可用于复现多跳重定向中的路径细节问题与--request-target的关系文档的 See-also 指向--request-target见 docs/cmdline-opts/request-target.md后者用于直接指定请求行中的目标字符串两者都能干预“实际发出的请求目标”但机制不同——--path-as-is影响 URL 解析阶段的路径规范化--request-target则整体改写请求目标版本前提该选项自 curl 7.42.0 起可用CURLOPT_PATH_AS_IS同步在 libcurl 中提供使用前可用curl --version确认版本。小结curl 默认按 RFC 3986 将 URL 路径中的/../、/./序列合并--path-as-is则让路径“原样通行”底层由 URL API 的CURLU_PATH_AS_IS标志跳过dedotdotify()规范化实现lib/urlapi.c。该行为在主请求创建lib/url.c与重定向解析lib/http.c两处统一生效并有 tests/unit/unit1395.c 的单元测试作为行为佐证。无论是命令行排障还是 libcurl 编程理解这一开关都能帮你精确控制发送到服务器的请求路径。【免费下载链接】curlA command line tool and library for transferring data with URL syntax, supporting DICT, FILE, FTP, FTPS, GOPHER, GOPHERS, HTTP, HTTPS, IMAP, IMAPS, LDAP, LDAPS, MQTT, MQTTS, POP3, POP3S, RTSP, SCP, SFTP, SMB, SMBS, SMTP, SMTPS, TELNET, TFTP, WS and WSS. libcurl offers a myriad of powerful features项目地址: https://gitcode.com/GitHub_Trending/cu/curl创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考