首页 / PHP / php – 切换到准备好的语句
php – 切换到准备好的语句
内容导读
互联网集市收集整理的这篇技术教程文章主要介绍了php – 切换到准备好的语句,小编现在分享给大家,供广大互联网技能从业者学习和参考。文章包含5304字,纯文字阅读大概需要8分钟。
内容图文
![php – 切换到准备好的语句](/upload/InfoBanner/zyjiaocheng/820/cd03f193d5914d03a4bb02e7e5f24c37.jpg)
我刚刚开始研究我的第一个项目(为了好玩).我正在学习PHP和MySQL,并完成了我的第一个工作应用程序.它有效,但我现在正在学习如何保护我的应用程序,从而防止SQL注入.
我有大约50个PHP文件来管理与MySQL数据库的交互.他们都看起来像这样:
<?php
$inputvalues = $_POST;
$errors = false;
$result = false;
session_start();
$uid = $_SESSION['usr_id'];
$mysqli = new mysqli('localhost', "root", "", "testdb");
if (mysqli_connect_errno()) {
printf("Connect failed: %s\n", mysqli_connect_error());
exit();
}
foreach ($inputvalues as $key => $value) {
if(isset($value) && !empty($value)) {
$inputvalues[$key] = $mysqli->real_escape_string( $value );
} else {
$errors[$key] = 'The field '.$key.' is empty';
}
}
if( !$errors ) {
$addresult = "
SELECT a.firstnames, a.surname, a.schoolrole, a.datejoined FROM teachers a LEFT JOIN schools b ON a.schoolid = b.id WHERE b.id = '".$inputvalues['schoolid']."'
";
if( $result = $mysqli->query($addresult) ) {
while($row = $result->fetch_all())
{
$returnResult = $row;
}
}
}
mysqli_close($mysqli);
echo json_encode(['result' => $returnResult, 'errors' => $errors]);
exit;
?>
这是我在整个应用程序中用于向/从数据库读取和写入数据的格式.如果我需要将它们更改为准备好的语句,我没有插入任何信息而只是检索它们,我将如何处理它?
另外,如果我没有向数据库输入任何数据,它是否仍然容易受到注入?
你能不能给我一个关于如何使我的当前代码适应预备语句的例子,我真的很感激.
解决方法:
我一直处于同样的境地.我也在使用连接语句,然后将应用程序切换到预处理语句.
坏消息是你要改变通过将客户端数据连接到SQL语句而构建的每个SQL语句,这几乎就是你的50个源文件中的每个SQL语句.
好消息是,转换为准备好的报表所获得的收益是无价的,例如:
1 – 你永远不会担心所谓的“SQL注入攻击”
php manual说
If an application exclusively uses
prepared statements, the developer can be sure that no SQL injection
will occur (however, if other portions of the query are being built up
with unescaped input, SQL injection is still possible).
对我来说,这个原因 – 思想的和平 – 足以支付更改源代码的成本. ,现在您的客户可以输入表格名称字段robert; DROP表学生; – ;)你觉得安全,没有任何事情会发生
2-您不再需要转义客户端参数.您可以直接在SQL语句中使用它们,例如:
$query = "SELECT FROM user WHERE id = ?";
$vars[] = $_POST['id'];
代替
$id = $mysqli->real_escape_string($_POST['id']);
$query = "SELECT FROM user WHERE id = $id";
这是你在使用准备好的陈述之前必须做的事情,这使你有可能忘记逃避一个参数作为普通人.并且攻击者破坏你的系统只需要1个未转义的参数.
改变守则
通常更改源文件总是有风险并且很痛苦,特别是如果您的软件设计很糟糕并且您没有明显的测试计划.但我会告诉你我做了什么让它变得更容易.
我创建了一个每个数据库交互代码都会使用的函数,所以你可以在以后的某个地方改变你想要的东西 – 这个函数 – 你可以做这样的事情
class SystemModel
{
/**
* @param string $query
* @param string $types
* @param array $vars
* @param \mysqli $conn
* @return boolean|$stmt
*/
public function preparedQuery($query,$types, array $vars, $conn)
{
if (count($vars) > 0) {
$hasVars = true;
}
array_unshift($vars, $types);
$stmt = $conn->prepare($query);
if (! $stmt) {
return false;
}
if (isset($hasVars)) {
if (! call_user_func_array(array( $stmt, 'bind_param'), $this->refValues($vars))) {
return false;
}
}
$stmt->execute();
return $stmt;
}
/* used only inside preparedQuery */
/* code taken from: https://stackoverflow.com/a/13572647/5407848 */
protected function refValues($arr)
{
if (strnatcmp(phpversion(), '5.3') >= 0) {
$refs = array();
foreach ($arr as $key => $value)
$refs[$key] = &$arr[$key];
return $refs;
}
return $arr;
}
}
现在,您可以在源文件中的任何位置使用此接口,例如,让我们更改您在问题中提供的当前SQL语句.让我们改变这一点
$mysqli = new mysqli('localhost', "root", "", "testdb");
$addresult = "
SELECT a.firstnames, a.surname, a.schoolrole, a.datejoined
FROM teachers a LEFT JOIN schools b ON a.schoolid = b.id
WHERE b.id = '".$inputvalues['schoolid']."'";
if( $result = $mysqli->query($addresult) ) {
while($row = $result->fetch_all())
{
$returnResult = $row;
}
}
进入这个
$mysqli = new mysqli('localhost', "root", "", "testdb");
$sysModel = new SystemModel();
$addresult = "
SELECT a.firstnames, a.surname, a.schoolrole, a.datejoined
FROM teachers a LEFT JOIN schools b ON a.schoolid = b.id
WHERE b.id = ?";
$types = "i"; // for more information on paramters types, please check :
//https://php.net/manual/en/mysqli-stmt.bind-param.php
$vars = [];
$vars[] = $inputvalues['schoolid'];
$stmt = $sysModel->preparedQuery($addresult, $types, $vars, $mysqli);
if (!$stmt || $stmt->errno) {
die('error'); // TODO: change later for a better illustrative output
}
$result = $stmt->get_result();
$returnResult = [];
while ($row = $result->fetch_array(MYSQLI_ASSOC)) {
$returnResult[] = $row;
}
Also, If I am not entering any data to the DB, is it still vulnerable to injection?
是的,通过将错误的字符串连接到您的SQL语句来应用Sql Injection攻击.它是INSERT,SELECT,DELETE,UPDATE.例如
$query = "SELECT * FROM user WHERE name = '{$_GET['name']}' AND password = '{$_GET['pass']}'"
类似的东西可以被利用
// exmaple.com?name=me&pass=1' OR 1=1; --
这将导致SQL语句
$query = "SELECT * FROM user WHERE name = 'me' AND password = '1' OR 1=1; -- '"
//executing the SQL statement and getting the result
if($result->num_rows){
//user is authentic
}else{
//wrong password
}
// that SQL will always get results from the table which will be considered a correct password
将您的软件转换为准备好的语句,祝您好运,并记住,您知道无论发生什么事情,您都可以安心地从SQL注入攻击中获取安全性,这是值得更改源文件的成本
内容总结
以上是互联网集市为您收集整理的php – 切换到准备好的语句全部内容,希望文章能够帮你解决php – 切换到准备好的语句所遇到的程序开发问题。 如果觉得互联网集市技术教程内容还不错,欢迎将互联网集市网站推荐给程序员好友。
内容备注
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 gblab@vip.qq.com 举报,一经查实,本站将立刻删除。
内容手机端
扫描二维码推送至手机访问。