因此,我已经在php中创建了一些代码,现在我想知道它是否“足够安全”。这是代码:
$amount = $_POST['amount'];
if ($amount < 1) { die("Min amount is 1."); }
if ($amount > 20) { die("Max amount is 20."); }
// More stuff here
例如,是否可以将$amount
设置为50,并且仍然可以使其正常工作?之后,它将发送file_get_contents
到带有数字的网页,例如:https://example.com/amount.php?a=15
。是否有可能在“这里的更多东西”部分将15变为50。
我很好奇,仅此而已。
编辑
这里是html Im正在使用;
<form method="POST">
<input type="number" class="form-control form-control-user" id="amount" name="amount" min="1" max="20" value="1"><br>
<button class="btn btn-success" type="submit">send</button>
</form>
然后这是我的完整php(例如)
if (isset($_POST['amount'])) {
$amount = $_POST['amount'];
if ($amount < 1) { die("Min amount is 1."); }
if ($amount > 20) { die("Max amount is 20."); }
$conn->query("INSERT INTO my_table (amount) VALUES ('$amount')");
file_get_contents("https://example.com/file.php?a=".$amount); // POINT A
}
是否可以在“ POINT A”处发送其他号码?像50
一样?
答案 0 :(得分:4)
您需要:
$amount = (int)$_POST['amount'];
否则用户可以输入以下内容:
3*3
这可能会导致您的file_get_contents( 'https://example.com/amount.php?a=3*3' )
一个真正有问题的场景是该输入:
7&a=8734
它将以file_get_contents( 'https://example.com/amount.php?a=7&a=8734' )
的形式发送请求
第二个a
的值将获胜,因此example.com服务器将解释您的请求,就好像您发送了file_get_contents( 'https://example.com/amount.php?a=8734' )
此“攻击”之所以有效,是因为PHP进行了类型转换,并且出于比较目的,它将7&a=8734
转换为简单的7
,但是您将非转换版本发送到example.com。
这就是为什么$amount = (int)$_POST['amount'];
是正确的解决方案的原因。
答案 1 :(得分:2)
代码有问题的一个示例:
通过发布这样的值:
1'),('50'),('42
用户可以将想要尝试的所有值插入多个my_table
中。
That string is >= 1, and <= 20.
打败客户端验证很简单,甚至根本不需要使用浏览器将值发布到脚本中。
$stmt = $conn->prepare("INSERT INTO my_table (amount) VALUES (?)");
$stmt->execute([$amount]);
您必须使用查询中需要使用的任何值来执行此操作。不要依赖过滤,转义或强制转换。并不是说它们不起作用,只是如果您习惯于直接在查询中使用变量,例如INSERT ... VALUES ('$amount')
,则取决于您能否记住100%进行过滤/转义/广播的能力,而我们只是人类。
答案 2 :(得分:1)
从不信任用户输入
这本身并不安全。用户可以通过检查工具来处理您的表单,也可以与邮递员一起张贴他们想要的任何内容。一种 ! 1 3.5。所有这些都是可行的输入。这还包括XSS,SQL注入等。
那是说您需要先清理输入内容。我建议先使用is_numeric函数,然后在返回false时死掉。之后,您便知道实际上是一个可以检查范围的数字。
<div id="target"></div>
答案 3 :(得分:0)
其他答案很好地解释了为什么它不够用,但是没有答案显示如何正确验证输入,这可以通过filter_var()完成,看起来像:
if (isset($_POST['amount'])) {
$amount = $_POST['amount'];
if(false===($amount=filter_var($amount,FILTER_VALIDATE_FLOAT)){
http_response_code(400); // HTTP 400 Bad Request
die("invalid amount (not a number)"); // show error page
}
// $amount is guaranteed to be a valid floating-point number,
// also filter_var() did the typecast for us,
// so $amount is now a php-native float.
if ($amount < 1) { die("Min amount is 1."); }
if ($amount > 20) { die("Max amount is 20."); }
$conn->query("INSERT INTO my_table (amount) VALUES ('$amount')");
file_get_contents("https://example.com/file.php?a=".$amount); // POINT A
}