编写SQL时PHP开发人员所犯的5个常见错误

2021-06-19 00:09

阅读:337

标签:

本文和大家分享的主要是编写SQLPHP开发人员常犯的一些错误,一起来看看吧,希望对大家学习php有所帮助。

杜绝使用MySQL API的旧版本

使用PHP开发时有好几种方法可以连接MySQL数据库。最常见的是MySQL APIMySQLi APIPDO API(PHP数据对象)。与MySQL API旧版本相比,后面两种方法支持更多的功能,并且更加安全。如果你使用的是旧的“mysql_”函数,那么你应该马上放下手上的工作,然后开始学习新的PDO API。这些旧的 mysql函数被弃用 ,并且PHP 7.x以后的版本也不会再支持了。

糟糕的实践:

$con = mysql_connect("localhost", "root", "mypass") or

die("Could not connect: " . mysql_error());

mysql_select_db("tutorials");

$result = mysql_query("select * from tutorials");  echo "

Here is a list of the topics:

";  while ($row = mysql_fetch_array($result)) {

 

echo $row[’name’]."
";

}

mysql_close($con);  ?>

优秀的实践:

require_once(’includes/conn.inc.php’);

$sql= "SELECT name, age FROM employees WHERE company_id = 10";

$stmt = $pdo->query($sql);

$row = $stmt->fetch(PDO::FETCH_ASSOC);echo $row[’name’];echo $row[age];

不要使用转义函数处理客户端输入的内容

使用 mysql_real_escape_string 对查询变量进行手工转义是不安全的,原因有两个:

1.

如果经常使用这个方法,你难免会弄错一次。只要有一个漏洞,黑客就可以将代码注入到SQL查询中。

2.

3.

在使用字符串变量时,你应该记住使用引号,很多人都没有这个意识。

4.

mysql_real_escape_string 的替换者就是 prepared statements (参见下面的更多信息)

不要假设预处理在PHP中总是安全的

Prepared statements预处理的目标是将查询与数据分离,以便将数据正确地插入到查询的参数中,而不需要任何操作选项。在大多数情况下,预处理的语句应该是非常安全的,它被认为是为查询注入用户输入参数的最佳实践技巧。

代码样例:

require_once(’includes/conn.inc.php’);

$sql= "SELECT * FROM employees";

$stmt = $pdo->prepare($sql);

$stmt->execute();

$result = $stmt->fetchAll();foreach($result as $row){

echo "

. 

{$row[’employeeName’]}

. 

. 

";

. 

 

}

那么,预处理在PHP中有什么不足呢?在将用户输入的参数值注入到查询语句这种情况下,就会有问题,因为预处理不支持这种注入。例如,MySQL PDO不支持在LIMIT情况中注入参数(使用占位符“?”)。此外,用户输入的内容不能在查询中插入表名或列名。如果你在这些情况下使用预处理,你应该手动地对数据进行人工处理,或者比这更好的方式就是找一个已经测试过的库,自动替你去做这些事。

不要假设ORM框架不会受到SQL注入攻击

使用ORM框架是非常棒的(尽管我敢肯定)。虽然这么说,这并不意味着它不会出现SQL注入攻击的情况。的确,在一个ORM生成的查询中想注入代码是很困难的,但是如果程序员不小心犯了个错误,这将会打开一个漏洞。在大多数情况下,在不使用预处理的情况下,将用户输入的值连接到ORM查询时,被注入的SQL语句就会执行。是的,像Doctrine这样的ORM框架提供了使用预处理的功能,所以使用它。从不将字符串连接到查询,无论是ORM查询还是原始SQL查询。

当然,遵守这些规则是不够的——为了避免给任何SQL注入留有一丝喘息的机会,确保你在编码之后一定要 测试ORM用法 和实现。

糟糕的实践:

在下面的代码示例中,你可以看到从用户输入的一个参数被连接到Doctrine DQL,它将应用程序暴露给SQL注入。

// INSECURE

$dql = "SELECT u

FROM MyProject\\Entity\\User u

WHERE u.status = ’" .  $_GET[’status’] . "’

ORDER BY " . $_GET[’orderField’] . " ASC";

糟糕的实践:

正如推荐给非ORM用户一样,在使用ORM框架(Doctrine)时,推荐使用预处理语句。

$orderFieldWhitelist = array(’email’, ’username’);

$orderField = "email";

if (in_array($_GET[’orderField’], $orderFieldWhitelist)) {

$orderField = $_GET[’orderField’];

}

$dql = "SELECT u

FROM MyProject\\Entity\\User u

WHERE u.status = ?1

ORDER BY u." . $orderField . " ASC";

$query = $entityManager->createQuery($dql);

$query->setParameter(1, $_GET[’status’]);

样例的源码地址: Doctrine文件 

不要低估字符编码的力量

根据OWASP (开放式Web应用程序安全项目),不使用utf8mb4会导致你的应用程序暴露给各种类型的攻击(你可以阅读更多关于encoding bypassing的信息)。另外,你应该经常在PHPMySQL中使用utf8mb4,以获得更好和更标准的多语言支持。

代码样例:

$dsn = ’mysql:host=example.com;dbname=testdb;port=3306;charset=utf8mb4’;

 

 

来源: 极客头条

编写SQL时PHP开发人员所犯的5个常见错误

标签:


评论


亲,登录后才可以留言!