此代码对于最小和最大int是否足够安全?

时间:2019-06-21 19:28:38

标签: php

因此,我已经在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一样?

4 个答案:

答案 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.

打败客户端验证很简单,甚至根本不需要使用浏览器将值发布到脚本中。

You need to bind that value to a prepared statement instead of including it directly in the SQL string to prevent this type of mischief.

$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
}
  • 如果$ amount只能是整数,不能是浮点数,则使用FILTER_VALIDATE_INT代替FILTER_VALIDATE_FLOAT