我有一个简单的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>
答案 0 :(得分:11)
您的代码中填充了sql injection opportunities。使用PDO查看prepared statements。或至少mysql_real_escape_string。不要使用你的代码。
也...
不要使用$ _REQUEST。使用适当的全局$ _POST或$ _GET。 GET请求不应该更改任何内容,因此您应该使用$ _POST。
答案 1 :(得分:5)
在将用户输入的所有输入数据库之前,必须使用mysql_real_escape_string功能。
例如:
将$_REQUEST['nickname']
更改为mysql_real_escape_string($_REQUEST['nickname'])
或者使用prepared statements。
答案 2 :(得分:5)
访问数据库时始终使用参数化查询。正如您所做的那样构建动态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手册中获取)。
答案 3 :(得分:4)
正如其他人所提到的,你需要处理字符串中的字面引号字符,否则你很容易受到SQL injection攻击。
有关更多示例和解决方案,请参阅我的演示文稿SQL Injection Myths and Fallacies。
使用查询参数是一种有效的防御,它实际上更容易编写并使您的代码看起来更好。我建议使用PDO,因为它允许您使用命名参数。
还考虑使用PHP的heredoc syntax来简化编写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'],
));
注意:我将$ _REQUEST更改为$ _POST,因为您永远不应该使用修改数据的GET请求。搜索引擎会跟踪链接,因此您可能会发现Google抓取您的网站并无意中修改了您的数据库。当操作要存储或修改某些内容时,始终使用POST请求。
对于简单的情况,你甚至不必使用参数,如果你可以将你的变量强制转换成可以安全使用的东西,比如一个普通的整数:
$id = (int) $_SESSION['id'];
$sql = "SELECT * FROM `pending_profile` WHERE id = {$id}";
$stmt = $pdo->query($sql);
$row = $stmt->fetch();
除了SQL注入风险之外,您的代码还充满了不同类型的安全风险,称为Cross-Site Scripting或XSS。当您将用户提供的内容回显到HTML输出时,会发生这种情况,而不会转义HTML中特殊的字符,例如<
或&
。攻击者可以输入他们的名字,包括javascript代码,从而导致恶作剧。
XSS的修复基本上是对你回应的任何内容使用htmlentities()
,如果它可能来自用户输入或任何其他不受信任的来源(如从数据库或文件或Web服务中读取)
<td><input type="text" name="nickname" value="<?php echo htmlentities($row['nickname']); ?>"/><td>
如果您为网络编写代码,您确实需要研究这些安全漏洞。它们是互联网上很多麻烦的来源。请参阅OWASP或SANS Top 25 Most Dangerous Software Errors。
答案 4 :(得分:3)
答案 5 :(得分:3)
在将表单中的变量插入数据库之前,您不会因为没有清理表单中的变量而受到打击。
PHP手册中有过滤/消毒的示例....
http://php.net/manual/en/filter.filters.sanitize.php
自从使用php和mysql以来,另一种流行的方法是这样的......
$var = mysql_real_escape_string($_POST['var']);
更多信息:
http://php.net/manual/en/function.mysql-real-escape-string.php
希望有所帮助。
答案 6 :(得分:2)
如果(int)
变量必须是数字,您也可以使用$_POST
。
答案 7 :(得分:1)
使用带引号的值的每个位置都使用addslashes($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());
您希望将其置于addslashes($_SESSION['id'])
,addslashes($_SESSION['nickname'])
等值,但不是
$sql = "INSERT INTO `tims`.`pending_profile`"
答案 8 :(得分:0)
使用传统的“普通”(非参数化)查询,您必须遵循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);
答案 9 :(得分:0)
对于未来的人来说,这对我有用
string addslashes ( string $str )
(PHP 4,PHP 5,PHP 7) addslashes - 使用斜杠引用字符串
在需要转义的字符之前返回带反斜杠的字符串。这些字符是单引号('),双引号(“),反斜杠()和NUL(NULL字节)。 Read more
<?php
$str = "Is your name O'Reilly?";
// Outputs: Is your name O\'Reilly?
echo addslashes($str);
?>