【发布时间】:2013-10-15 20:17:44
【问题描述】:
我知道黄金法则,永远不要相信用户提供的文件名。不过我想打破这个规则。下面的方案有什么不安全的地方吗?
$name = $_POST['name'];
$id = intval($_GET['id']);
$sanitized_name = preg_replace('/[^0-9a-zA-Z]/','',$name);
$fp = fopen("/path/to/".$id."/".$sanitized_name.".jpg",'w');
如果我用 '' 替换不是 0-9 或 a-z 或 A-Z 的所有内容,那么任何人都可以注入 '.' 绝对有 0% 的变化。创建自己的扩展名(使用 NULL 字节的组合)或遍历目录。这似乎很安全。我只是想通过 SO 运行它。
此外,由于 ID 被强制为 int,任何时髦的东西都会简单地变成 0。
【问题讨论】:
-
为什么你们是 HTML 编码文件名?!
-
这只是我复制和粘贴的例行清理。没关系,因为任何 HTML 字符都会被条纹化。它不是必需的和多余的。像“cat”这样的普通名称将保留为“cat”。 '>cat' 会变成 '>cat' 会变成 'gtcat'。没关系,因为它刚刚被剥离。
-
“安全”不是你可以像撒盐一样撒在代码上并期望它神奇地变得更好/更美味的东西。 您的安全要求是什么?也许您允许多个用户上传文件并且只希望他们访问自己的文件。在这种情况下,这段代码是无用的,因为文件为
z.txt的用户A 可以修改文件名并访问属于用户B 的y.txt。“哎呀”。 -
不要盲目地把货物崇拜扔进与主题无关的函数中。 HTML 编码在这里绝对没有价值。
-
@MarcB 这符合我的要求。我会简单地检查 if($sanitized_name == SOMETHING_ELSE_IN_DIRECTORY) 然后错误,否则继续