目录横穿“(Ttaversal)”问题的解决办法


 



最近一周,在BugTraq的Internet 邮件列表中报告了 “Domino 服务器目录‘横穿’(Traversal)缺陷”,经证实这确实是一个问题,R5.06a正在修复。应敦促在Domino服务器上运行HTTP服务器任务的客户在R5.06a完成后立即升级。与此同时,下面是简单的应对方法。

Q&A

Q:“目录‘横穿’(Traversal)”缺陷的实质是什么?
A:给出已知路径和文件名,就能够访问到运行HTTP任务的Domino服务器上的文件。这受安装Domino服务器的文件系统(或驱动器)的限制。你不可能浏览文件系统,但如果能够猜出当前文件名,就能够访问它。

Q:影响哪些Domino版本?
A:R5.0 - R5.06 不影响R4x

Q:我如何跟踪这个问题?
A:软件问题报告(SPR)的编号为KSPR4SPQ5S。问题修复后就会列入Notes.net上的修复列表(Fix List)数据库----www.notes.net/R5FixList.nsf

Q:Lotus计划如何解决这个问题?
A:Lotus 高度重视这个问题,修复版正在测试中。修复计划在R5.06a中进行,并且一旦修复版完成就会放到http://www.notes.net上。

Q:是否有应对办法?
A:有。在R5.06a完成以前,推荐使用以下应对方案:

1.打开Administration Client
2.选择希望配置的服务器
3.在“配置”标签页的“服务器”区段中,选择当前服务器文档
点击“Web”按钮
选择“创建URL 映射/重定位文档”
4.在URL重定位文档中
在“基本”标签页选择URLà重定位URL
在“映射”标签页
输入的 URL: *..*
重定位 URL: [指定你希望用户重定位到的URL,例如
http://hostname/homepage.nsf
http://hostname/message.html]
注意:指定的URL必须是外部的重定位,而不能是内部的重定位。因此,http://myserver/message.html是有效的,而/message.html是无效的。
5.保存文档
6.重起HTTP任务


Q: 影响哪些操作系统?
A: 代码修复并不特别针对哪个操作系统。Lotus QE 在Windows NT/2000,OS/2,WinNT Alpha 等平台上重现了这个问题。QE 无法在Unix ,Linux,AS/400或S/390上重现此问题,但客户不应当就认为这些系统难于攻击。这可能仅仅是因为这些系统有更加严格的文件系统许可设置。

Q: 如果不将Domino作为Web服务器,是否还存在这个问题?
A: 不存在。这个问题是特别针对运行HTTP任务或Domino for IIS的Domino系统的。

Q: 是否影响QuickPlace?
A: 是的。Lotus 正在计划推出R2.06a以解决这个问题。QuickPlace服务器的Administrator也应当实施URL重定位的应对方案。

Q: 如果不采用Notes Client管理Domino服务器,是否有其它应对方案?
A: 可以在 httpd.cnf文件中加入下列内容,执行类似的URL重定位。
Map *..* /filename.nsf

Q: 有人推荐采用文件保护文档作为应对方法。Lotus 认为如何?
A: 文件保护文档并不能解决这个问题的所有可能的出现。客户应当代之以回应中推荐的URL重定位文档。另外,强烈推荐客户在R5.06a完成后立即升级。

Q: BugTraq 的报告中声称R4.67也被影响了,是吗?
A: Lotus QE无法在任何R4.x版本上重现这个问题。

Q: R5.06a何时能够完成?
A: 一旦版本的回归测试完成,R5.06a就会放到http://notes.net上。

Q: 其它版本(例如R5.04或R5.05)是否会有QMU(Quarterly Maintenance Unit)?
A: 客户需要升级到R5.06a。

Q: 如果应用中使用带有“..”的URL,这种应对方法是否会中断这些应用?
A: 测试表明应用代码中的URL仍然是有效的。只有当用户在浏览器中直接键入带有“..”的URL时,重定位才会发生。这是唯一Lotus推荐的应对方案。

Q: 如果运行虚拟服务器,是否需要问每一个虚拟服务器都创建一个URL重定位文档?
A: 不需要。如果在文档中不特别指定一个IP地址,重定位将作用于机器上的所有虚拟服务器。

Q: 是否所有浏览器都能重现此错误?
A: 不是。只有某些浏览器发生了这样的问题。但是,这只说明一些用户重现这个问题有困难。因此仍然应该对所有Domino Web Server实施应对方案和升级。

Q: 是否还可以采取其它措施以降低出现这种缺陷的机会?
A: 下面的列表并不全面,但是一些快速的措施:
用口令保护Server id
以一个唯一的文件名重命名Server id
用Server 的id本地加密系统数据库(以及其它名字容易被猜到的数据库)
在隔离的文件系统中存储Domino目录
在服务器文档中禁止目录浏览

欲获得更多加强系统安全性的信息,请参看以下资料:
IBM红皮书,“Notes and Domino R5 Security Infrastructure Revealed”
http://notes.net的Iris Today 中发布的有关安全机制的文章
http://www.lotus.com/security Lotus Security Zone网站上的白皮书

这是一个非常常见的可视化问题: > ❌ **某些边横穿节点,影响可读性** 我们可以通过以下方式来优化边的绘制,避免边穿过节点: --- ## ✅ 改进目标 | 目标 | 实现方式 | |------|----------| | ✅ 避免边穿过节点 | 使用 `arc3` 曲线偏移参数 | | ✅ 可配置边弯曲程度 | 使用 `connectionstyle` 控制曲线 | | ✅ 保留颜色混合逻辑 | 边颜色仍使用组合颜色混合 | | ✅ 不影响图的结构和布局 | 仅视觉优化,不影响拓扑结构 | --- ## ✅ 修改后的完整代码(避免边穿过节点) ```python import os import matplotlib.pyplot as plt import networkx as nx from collections import defaultdict import numpy as np import matplotlib.cm as cm import matplotlib.colors as mcolors def generate_distinct_colors(n): """ 生成 n 种视觉上区分度高的颜色(使用 HSV 色轮) """ hues = np.linspace(0, 1, n, endpoint=False) hsv_colors = np.column_stack([hues, np.ones(n)*0.7, np.ones(n)*0.9]) rgb_colors = np.array([mcolors.hsv_to_rgb(c) for c in hsv_colors]) return [mcolors.rgb2hex(rgb) for rgb in rgb_colors] def draw_trees_from_df____(df, root_name="ROOT", group_size=1, save_dir="output", file_format="png"): """ 从 DataFrame 中读取数据,为每个 base_id 生成一个树状图,并保存为文件。 每条边颜色表示使用该边的所有 (compare_id1, compare_id2) 对应的颜色混合。 每个分组只显示该组使用的组合,且独立上色。 参数: - df: 包含数据的 DataFrame,必须包含 "base_id", "compare_id1", "compare_id2", "param" 列。 - root_name: 根节点名称。 - group_size: 每组处理的 base_id 数量(默认为 1)。 - save_dir: 图片保存的目录。 - file_format: 图片保存格式,如 png, svg, pdf 等。 """ os.makedirs(save_dir, exist_ok=True) base_ids = df["base_id"].unique().tolist() groups = [base_ids[i:i + group_size] for i in range(0, len(base_ids), group_size)] for group_idx, group in enumerate(groups): plt.figure(figsize=(12, 10)) ax = plt.subplot(111) combined_G = nx.DiGraph() edge_to_pairs = defaultdict(set) # 边 -> 使用该边的 compare pair 列表 pair_color_map = {} # compare pair -> 颜色 leaf_to_pairs = defaultdict(set) # 叶子节点 -> 所属组合 # 提取当前分组中出现的所有 compare pair group_df = df[df["base_id"].isin(group)] unique_pairs_in_group = group_df[['compare_id1', 'compare_id2']].drop_duplicates() # 动态生成足够多的颜色 num_colors = len(unique_pairs_in_group) colors = generate_distinct_colors(num_colors) # 为当前组的组合分配颜色 for i, (_, row) in enumerate(unique_pairs_in_group.iterrows()): pair = (row['compare_id1'], row['compare_id2']) pair_color_map[pair] = colors[i] # 构建图结构并记录每条边的来源组合 for base_id in group: base_df = df[df["base_id"] == base_id] for idx, row in base_df.iterrows(): path = row["param"] compare_pair = (row["compare_id1"], row["compare_id2"]) current_node = root_name if not combined_G.has_node(current_node): combined_G.add_node(current_node) for param in path: next_node = param if not combined_G.has_node(next_node): combined_G.add_node(next_node) combined_G.add_edge(current_node, next_node) edge_to_pairs[(current_node, next_node)].add(compare_pair) current_node = next_node # 记录叶子节点对应的组合 if combined_G.out_degree(current_node) == 0: leaf_to_pairs[current_node].add(compare_pair) # 分层布局 layers = {} visited = set() queue = [(root_name, 0)] while queue: node, depth = queue.pop(0) if node in visited: continue visited.add(node) layers[node] = depth for neighbor in combined_G.successors(node): if neighbor not in layers: layers[neighbor] = depth + 1 queue.append((neighbor, depth + 1)) for node in combined_G.nodes: combined_G.nodes[node]["layer"] = layers.get(node, 0) pos = nx.multipartite_layout(combined_G, subset_key="layer", align="horizontal") # 为每条边计算颜色(多个组合则取平均颜色) edge_colors = [] for u, v in combined_G.edges(): pairs = edge_to_pairs[(u, v)] if len(pairs) == 0: edge_colors.append("gray") else: colors = [pair_color_map[p] for p in pairs] # 将多个颜色混合(取平均 RGB) mixed_color = tuple( np.mean([tuple(int(c[i:i + 2], 16) / 255 for i in (1, 3, 5)) for c in colors], axis=0)) edge_colors.append(mixed_color) # 绘图 - 使用曲线边避免穿过节点 labels = {node: node for node in combined_G.nodes} nx.draw_networkx_nodes(combined_G, pos, ax=ax, node_size=400, node_color="lightgray") nx.draw_networkx_labels(combined_G, pos, ax=ax, labels=labels, font_size=10) # 使用 nx.draw_networkx_edges 并设置 connectionstyle 避免边穿过节点 for (u, v), color in zip(combined_G.edges(), edge_colors): nx.draw_networkx_edges( combined_G, pos, edgelist=[(u, v)], ax=ax, edge_color=[color], connectionstyle=f"arc3, rad=0.2", # 弯曲边 arrows=True, width=2, alpha=0.8 ) # 在叶子节点旁边标注组合信息 for leaf, pairs in leaf_to_pairs.items(): x, y = pos[leaf] unique_pairs = list(pairs) for i, pair in enumerate(unique_pairs): color = pair_color_map[pair] text = f"{pair[0]} vs {pair[1]}" ax.text(x, y + 0.05 + i * 0.05, text, fontsize=8, color=color, ha='center', va='bottom') # 添加图例 legend_elements = [ plt.Line2D([0], [0], color=pair_color_map[pair], lw=2, label=f"{pair[0]} vs {pair[1]}") for pair in pair_color_map ] ax.legend(handles=legend_elements, loc='upper right', bbox_to_anchor=(1.2, 1)) title = f"Group: {', '.join(group)}" ax.set_title(title) plt.tight_layout() filename = "_".join(group) save_path = os.path.join(save_dir, f"{filename}.{file_format}") plt.savefig(save_path, format=file_format, dpi=200, bbox_inches='tight') plt.close() print(f"Saved: {save_path}") ``` --- ## ✅ 修改说明 | 修改点 | 实现方式 | |--------|----------| | ✅ 避免边横穿节点 | 使用 `nx.draw_networkx_edges` 和 `connectionstyle="arc3, rad=0.2"` | | ✅ 曲线弧度可调 | `rad=0.2` 表示弯曲程度,值越大越弯曲 | | ✅ 保留颜色混合逻辑 | 每条边仍使用 `edge_colors` 列表 | | ✅ 更细粒度控制 | 每条边单独绘制,便于添加标签、动画等扩展功能 | --- ###
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值