Php sql中的引号导致问题

Php sql中的引号导致问题,php,mysql,sql-injection,Php,Mysql,Sql Injection,我有一个非常简单的html输入文本框。此表单的信息表单通过sql字符串传输到mysql数据库 一切都很顺利,除了有人键入“或”之外。我不想限制用户键入什么 在对数据库运行查询之前,是否应该查找并替换字符串 有简单的方法吗 下面是一些代码: <?php session_start(); if (empty($_SESSION['user']) && empty($_REQUEST['form'])) //check this code!!1 { exit; } if

我有一个非常简单的html输入文本框。此表单的信息表单通过sql字符串传输到mysql数据库

一切都很顺利,除了有人键入“或”之外。我不想限制用户键入什么

在对数据库运行查询之前,是否应该查找并替换字符串

有简单的方法吗

下面是一些代码:

<?php
session_start();
if (empty($_SESSION['user']) && empty($_REQUEST['form'])) //check this code!!1
{
    exit;
}
if (isset($_REQUEST['Submit']))
{
    //echo "Let's process this form!";
    include "config.php";
    include "mail.php";
    if ($_REQUEST['form'] == "profile")
    {//public profile
        //print_r($_REQUEST);
        //"UPDATE `tims`.`pending_profile` SET `nickname` = 'I Don''t Have One' WHERE `pending_profile`.`id` = 1;";
        $sql = "INSERT INTO `tims`.`pending_profile`"
                . "(`id`, `nickname`, `location`, `role`, `yog`, `interests`, `favMoment`, `gainThisYr`, `futurePlans`, `bio`) \n"
                . "VALUES ('" . $_SESSION['id'] . "', '" . $_REQUEST['nickname'] . "', '" . $_REQUEST['town'] . "', '" . $_REQUEST['role'] . "', '" . $_REQUEST['yog'] . "', '" . $_REQUEST['interests'] . "', '" . $_REQUEST['fav_moment'] . "', '" . $_REQUEST['gain'] . "', '" . $_REQUEST['future'] . "', '" . $_REQUEST['bio'] . "')\n"
                . "ON DUPLICATE KEY UPDATE nickname ='" . $_REQUEST['nickname'] . "', location='" . $_REQUEST['town'] . "', role= '" . $_REQUEST['role'] . "', yog='" . $_REQUEST['yog'] . "', interests='" . $_REQUEST['interests'] . "', favMoment='" . $_REQUEST['fav_moment'] . "', gainThisYr='" . $_REQUEST['gain'] . "', futurePlans='" .       $_REQUEST['future'] . "', bio='" . $_REQUEST['bio'] . "'\n";  
        $qry = mysql_query($sql) or die(mysql_error());

//@todo overlay this
//http://flowplayer.org/tools/overlay/index.html
        //send mail to moderators
        include "vars.php";
        $to = $captMail;
        $prof = implode("\n", $_REQUEST);
        $subject = "Moderation Needed";
        $body = $_SESSION['fullname'] . " Has just changed their public profile.\n" .
                "Please login here to moderate their changes:\n" .
                //"http://team2648.com/OPIS/login.php?page=manage".
                "http://www." . $sysurl . "/login.php?page=manage\n" .
                "Best,\n" .
                "Blake\n\n\n" .
                "Click here to accept the profile bleow\n\n" .
                "http://www." . $sysurl . "/login.php?page=manage&acceptID=".$_SESSION['id']."\n" .
                $prof;
        mailer($to, $subject, $body);
        $to = $mentorMail;
        mailer($to, $subject, $body);

        echo "<link href=\"../css/styling.css\" rel=\"stylesheet\" type=\"text/css\" media=\"screen\" />";
        echo "<div class =\"widget\" style=\"width:350px\">";
        echo "Your changes have been saved, they will not go live until reviewed by a moderator";
        echo "<br>";
        echo "<a href=\"../\">Click here to continue</a>";
        echo "</div>";
    }
    exit;
}
$sql = "SELECT * FROM `pending_profile` WHERE id ='" . $_SESSION['id'] . "'";
$qry = mysql_query($sql) or die(mysql_error());
$row = mysql_fetch_assoc($qry);
?>
<!--<h3>Use this page to manage your profile information</h3>-->
<h4>Public Profile</h4>
<strong>NOTE:</strong> Fields filled with [NONE] will not show on the website.
<br />
<form id="profile" name="profile" method="get" action="lib/preview.php">
    <input type="hidden" value="profile" name="form">
    <input type="hidden" value="<?php echo $_SESSION['id']; ?>" name="id">
    <table>
        <tr>
            <td><label for="myname">Hello, My name is:</label><td>
            <td><input type="text" readonly="readonly" name="myname" value="<?php echo $_SESSION['firstname']; ?>"/><td>
        </tr>
        <tr>
            <td><label for="nickname">But I like to be called:</label><td>
            <td><input type="text" name="nickname" value="<?php echo $row['nickname']; ?>"/><td>
        </tr>
        <tr>
            <td><label for="town">I live in:</label><td>
            <td><input type="text" name="town" value="<?php echo $row['location']; ?>"/><td>
        </tr>
        <tr>
            <td><label for="role">My role on the team is:</label><td>
            <td><input type="text" name="role" value="<?php echo $row['role']; ?>"/><td>
        </tr>
        <tr>
            <td><label for="yog">I will graduate High School in:</label><td>
            <td><input type="text" name="yog" value="<?php echo $row['yog']; ?>"/><td>
        </tr>
        <tr>
            <td><label for="interests">Some of my interests are:</label><td>
            <td><input type="text" name="interests" value="<?php echo $row['interests']; ?>"/><td>
        </tr>
        <tr>
            <td><label for="fav_moment">One of my favorite team moments:</label><td>
            <td><input type="text" name="fav_moment" value="<?php echo $row['favMoment']; ?>"/><td>
        </tr>
        <tr>
            <td><label for="gain">I would like to gain the following this year:</label><td>
            <td><input type="text" name="gain" value="<?php echo $row['gainThisYr']; ?>"/><td>
        </tr>
        <tr>
            <td><label for="future">My future plans include:</label><td>
            <td><input type="text" name="future" value="<?php echo $row['futurePlans']; ?>"/><td>
        </tr>
        <tr>
            <td><label for="bio">My Bio:</label><td>
            <td><textarea name="bio" ><?php echo $row['bio']; ?></textarea><td>
        </tr>
    </table>
    * All fields are required.
<?php
include "disclaimer.php";
// @todo add js validation of all fields filled in
?>
    <br><input type="submit" name="Submit" value=" I Agree, Preview "/>

</form>

*所有字段都是必填字段。

尝试使用;

在将用户输入放入数据库之前,必须在所有用户输入上使用该功能

例如:

$\u请求['昵称]
更改为
mysql\u real\u escape\u字符串($\u请求['昵称]])

或者使用。

您的代码已被填充。请查看。或至少。不要使用您的代码

还有


不要使用$\u请求。请使用适当的全局$\u POST或$\u GET。GET请求不应更改任何内容,因此应使用$\u POST。

在可以使用引号的值的每个位置使用
添加斜杠($mystringwithquotes)
方法在引号之前添加斜杠

请确保不要在完整的SQL字符串中使用这些内容,因为您仍然希望保留所需的内容

例如,在您的代码中:

$sql = "INSERT INTO `tims`.`pending_profile`" . "(`id`, `nickname`, `location`, `role`, `yog`, `interests`, `favMoment`, `gainThisYr`, `futurePlans`, `bio`) \n" . "VALUES ('" . $_SESSION['id'] . "', '" . $_REQUEST['nickname'] . "', '" . $_REQUEST['town'] . "', '" . $_REQUEST['role'] . "', '" . $_REQUEST['yog'] . "', '" . $_REQUEST['interests'] . "', '" . $_REQUEST['fav_moment'] . "', '" . $_REQUEST['gain'] . "', '" . $_REQUEST['future'] . "', '" . $_REQUEST['bio'] . "')\n" . "ON DUPLICATE KEY UPDATE nickname ='" . $_REQUEST['nickname'] . "', location='" . $_REQUEST['town'] . "', role= '" . $_REQUEST['role'] . "', yog='" . $_REQUEST['yog'] . "', interests='" . $_REQUEST['interests'] . "', favMoment='" . $_REQUEST['fav_moment'] . "', gainThisYr='" . $_REQUEST['gain'] . "', futurePlans='" . $_REQUEST['future'] . "', bio='" . $_REQUEST['bio'] . "'\n"; $qry = mysql_query($sql) or die(mysql_error());
在将变量插入数据库之前,如果没有对表单中的变量进行清理,你会被痛骂一顿

PHP手册中有过滤/消毒的示例

由于您使用的是php和mysql,另一种流行的方法是这样的

$var = mysql_real_escape_string($_POST['var']);
更多信息请点击此处:


希望这会有所帮助。

访问数据库时始终使用参数化查询。在这样做时构造动态SQL语句会引发SQL注入攻击(以及您看到的错误)

在PHP中,执行此操作的代码如下所示

$mysqli = new mysqli('localhost', 'my_user', 'my_password', 'world');
$stmt = $mysqli->prepare("INSERT INTO CountryLanguage VALUES (?, ?, ?, ?)");
$stmt->bind_param('sssd', $code, $language, $official, $percent);
(无耻地摘自PHP手册)。

如果
$\u POST
变量必须是数字,也可以使用
(int)

使用传统的“普通”(非参数化)查询,您必须遵循3条规则

  • 所有字符串(数据的引用部分)都必须转义
  • 所有数字必须显式转换为其类型
  • 所有标识符或运算符都应从先前定义的变量中选择
您还可以使用一些辅助函数自动组合查询

function dbSet($fields,&$source) {
  $set='';
  foreach ($fields as $field) {
    if (isset($source[$field])) {
      $set.="`$field`='".mysql_real_escape_string($source[$field])."', ";
    }
  }
  return substr($set, 0, -2); 
}
但是你的代码太脏了,不能用它来做一个有效的例子。
这是虚拟的一个

$fields = explode(" ","name surname lastname address zip fax phone");
$query  = "INSERT INTO $table SET ".dbSet($fields, $_POST);

正如其他人提到的,您需要处理字符串中的文字引号字符,否则很容易受到攻击

有关更多示例和解决方案,请参见我的演示

使用查询参数是一种有效的防御措施,它实际上更容易编写,并且使代码看起来更漂亮。我建议使用PDO,因为它允许您使用命名参数

还考虑使用PHP来编写SQL代码更简单,而不用担心所有的双引号和级联字符串。

$sql = <<<END_SQL
INSERT INTO `tims`.`pending_profile`
(`id`, `nickname`, `location`, `role`, `yog`, `interests`, `favMoment`,
 `gainThisYr`, `futurePlans`, `bio`)
VALUES (:id, :nickname, :town, :role:, :yog, :interests, :fav_moment, 
 :gain, :future, :bio)
ON DUPLICATE KEY UPDATE
  nickname    = :nickname,
  location    = :town,
  role        = :role,
  yog         = :yog,
  interests   = :interests,
  favMoment   = :fav_moment,
  gainThisYr  = :gain,
  futurePlans = :future,
  bio         = :bio
END_SQL;

$stmt = $pdo->prepare($sql);
$success = $stmt->execute(array(
    ':id'         => (int) $_SESSION['id'],
    ':nickname'   => $_POST['nickname'],
    ':town'       => $_POST['town'],
    ':role'       => $_POST['role'],
    ':yog'        => $_POST['yog'],
    ':interests'  => $_POST['interests'],
    ':fav_moment' => $_POST['fav_moment'],
    ':gain'       => $_POST['gain'],
    ':future'     => $_POST['future'],
    ':bio'        => $_POST['bio'],
));

除了SQL注入风险之外,您的代码还充满了不同类型的安全风险,称为XSS或XSS。当您将用户提供的内容回显到HTML输出时,就会发生这种情况,而不会转义HTML中的特殊字符,例如
,对于未来的人来说,这对我很有用

string addslashes(string$str)

(PHP4、PHP5、PHP7) addslashes-带斜杠的引号字符串

返回需要转义的字符前带有反斜杠的字符串。这些字符是单引号(')、双引号(“)、反斜杠()和NUL(空字节)。


阅读SQL注入:那么,当我将它们从数据库中取出时,如何取消它们的转义呢?另外,如果你想知道如果你不太关心SQL注入会发生什么,请看一下这个,因为妈妈说:哇,“这条线索中所有的幻影否决票是怎么回事?”斯帕雷尔上校——我只是指出,对否决票的解释可能会得到接收者的赞赏。没有必要居高临下。有一个好的。不是“你可以”,“你绝对必须”。愚蠢的“用户输入”再次。似乎不需要在管理输入中转义引号。和愚蠢的“用户输入”而不是字符串。在未加引号的数字上使用这个函数,然后吃掉你的注入。在这里,你可以看到一个新的例子,说明这种愚蠢假设的后果:最好是SQL注入。@delnan:不,你不需要在用户的任何和所有输入上使用它。如果在运行查询之前验证输入,则绝对没有注入的风险@Col:用户输入包括管理员的输入。这与你在网页上的权利无关。@nikic去告诉所有这些家伙吧。管理员输入只是一个数字,它可以是脚本生成的数据或任何东西。为什么要提到愚蠢的用户输入,而查询中的每一个该死的字符串都必须转义,不管它来自何处?至于您的“无需”,验证规则可能会更改。数据验证与数据库级别完全无关。请不要建议使用addslashes进行SQL注入防御。这不是正确的解决方案,因为它不考虑多字节字符集。使用数据库API提供的转义函数:例如mysql_real_escape_string.+1,但我要补充的是,在PDO中使用参数要容易得多。我发现MySQLIAPI更难使用。+1但我发现六次键入同一组字段令人难以置信地无聊。更不用说一个字段被添加到表中的情况了。。。应该有一些帮助函数,使程序员的工作更智能一些。@Col shrapanel:如果您将位置参数与
占位符一起使用,您只需键入三次而不是六次名称。但在这个例子中,在重复密钥更新时插入…必须将每个值传递两次(可以使用
array\u merge()
$sql = <<<END_SQL
INSERT INTO `tims`.`pending_profile`
(`id`, `nickname`, `location`, `role`, `yog`, `interests`, `favMoment`,
 `gainThisYr`, `futurePlans`, `bio`)
VALUES (:id, :nickname, :town, :role:, :yog, :interests, :fav_moment, 
 :gain, :future, :bio)
ON DUPLICATE KEY UPDATE
  nickname    = :nickname,
  location    = :town,
  role        = :role,
  yog         = :yog,
  interests   = :interests,
  favMoment   = :fav_moment,
  gainThisYr  = :gain,
  futurePlans = :future,
  bio         = :bio
END_SQL;

$stmt = $pdo->prepare($sql);
$success = $stmt->execute(array(
    ':id'         => (int) $_SESSION['id'],
    ':nickname'   => $_POST['nickname'],
    ':town'       => $_POST['town'],
    ':role'       => $_POST['role'],
    ':yog'        => $_POST['yog'],
    ':interests'  => $_POST['interests'],
    ':fav_moment' => $_POST['fav_moment'],
    ':gain'       => $_POST['gain'],
    ':future'     => $_POST['future'],
    ':bio'        => $_POST['bio'],
));
$id = (int) $_SESSION['id'];
$sql = "SELECT * FROM `pending_profile` WHERE id = {$id}";
$stmt = $pdo->query($sql);
$row = $stmt->fetch();
<td><input type="text" name="nickname" value="<?php echo htmlentities($row['nickname']); ?>"/><td>
<?php
$str = "Is your name O'Reilly?";

// Outputs: Is your name O\'Reilly?
echo addslashes($str);
?>