Php 我是否在避免sql注入?
我这样做对吗?这有助于避免sql注入吗Php 我是否在避免sql注入?,php,mysql,sql-injection,Php,Mysql,Sql Injection,我这样做对吗?这有助于避免sql注入吗 $deleteid = htmlspecialchars(strip_tags(mysql_real_escape_string($_POST['listid']))); mysql_send("DELETE FROM stage where listid='$deleteid'"); 是的,在MySQL语句中的字符串声明中使用on值将阻止SQL注入。这正是这个函数的目的 但您不需要其他两个函数和。因为这些函数分别用于删除(HTML)标记和用字符引用替
$deleteid = htmlspecialchars(strip_tags(mysql_real_escape_string($_POST['listid'])));
mysql_send("DELETE FROM stage where listid='$deleteid'");
是的,在MySQL语句中的字符串声明中使用on值将阻止SQL注入。这正是这个函数的目的
但您不需要其他两个函数和。因为这些函数分别用于删除(HTML)标记和用字符引用替换HTML特殊字符。它们不是为了保护您免受SQL注入的影响
事实上,在
mysql\u real\u escape\u string
之后使用strip\u标记和/或htmlspecialchars
可能会在某些情况下中断转义(例如,在使用非美国ASCII字符集时,另请参见)。因此,请确保在将其返回值插入SQL语句之前使用该函数
除了使用mysql\u real\u escape\u string
对输出进行编码外,还可以使用以下方法验证输入:
此验证确保查询中只使用不需要转义的(正)整数值。否
您应该只调用mysql\u real\u escape\u string
htmlspecialchars
和strip\u标签
函数用于对要显示为HTML的字符串进行编码。
它们不应该与SQL一起使用,因为它可以防止SQL注入攻击,但这是一种糟糕的方法。改用
既然你的评论说你正在系统地改变你的整个网站,那就用更好的方法吧。如果您以后想切换到另一个后端,那么您可能需要移动到一个非MySQL特定的数据库API。除了上述建议(只有MySQL\u real\u escape\u string
但更好的是准备好的语句),我想补充一点,准确分析您试图清理/确保安全的价值总是很有用的
如果您的ID应该是一个整数,我只需使用intval($\u POST['listid'])
来确保结果是一个整数,并为字符串保留mysql\u real\u escape\u string
(尽管我个人会使用预处理语句/PDO)。使用存储过程,只向您的app db用户授予执行权限(再加上存储过程带来的无数其他好处)我总是在我的所有项目上使用数据库助手类。这样我就不必使用mysql\u real\u escape\u string
保持代码干净易读如果你忘记使用它,你就不会被注射
下面是我使用的一个例子
<?php
final class DatabaseException extends Exception {
function __construct($strErrMessage, $intErrCode) {
parent::__construct($strErrMessage, $intErrCode);
}
}
class Database {
protected $host = ""; //database server
protected $user = ""; //database login name
protected $pass = ""; //database login password
protected $database = ""; //database name
protected $prefix = ""; //table prefix
protected $connected = false;
protected $db = null;
protected $record = array();
protected $error = "";
protected $errno = 0;
//table name affected by SQL query
protected $field_table= "";
//number of rows affected by SQL query
protected $affected_rows = 0;
protected $link_id = 0;
protected $query_id = array();
function __construct($server, $user, $pass, $database, $pre='') {
$this->connected = false;
$this->host = $server;
$this->user = $user;
$this->pass = $pass;
$this->database = $database;
$this->prefix = $pre;
$this->connect();
}
function __destruct() {
//mysql_close($this->link_id);
}
public function connect() {
if ($this->link_id > 0 && $this->connected && mysql_ping($this->link_id)) { return; }
$this->link_id = mysql_pconnect($this->host, $this->user, $this->pass);
if (!$this->link_id) { //open failed
throw new DatabaseException("mysql_pconnect failed",0);
}
if(!@mysql_select_db($this->database, $this->link_id)) {//no database
throw new DatabaseException("mysql_select_db failed",0);
}
$this->server='';
$this->user='';
$this->pass='';
$this->database='';
$this->connected = true;
$this->query("SET time_zone = '".Settings::get('db.timezone_offset')."';",TRUE);
}
public function escape($string) {
if(get_magic_quotes_gpc())
$string = stripslashes($string);
return mysql_real_escape_string($string);
}
public function insert($table,$data,$tbl_key='id') {
$v='';
$n='';
foreach($data as $key=>$val) {
$n.="`$key`, ";
if(strtolower($val)=='null')
$v.="NULL, ";
elseif(strtolower($val)=='now()')
$v.="NOW(), ";
elseif(strcmp(substr($val,0,7),'**ESC**') == 0)
$v .= str_replace('**ESC**','',$val);
else
$v.= "'".$this->escape($val)."', ";
}
if ($v=='' || $n=='')
return false;
$q = "INSERT INTO `".$this->prefix.$table."` ";
$q .= "(". rtrim($n, ', ') .") VALUES (". rtrim($v, ', ') .");";
if($this->query($q)){
$id=mysql_insert_id();
if ($id === 0) { // The ID generated for an AUTO_INCREMENT column by the previous INSERT query on success,
// 0 if the previous query does not generate an AUTO_INCREMENT value, or FALSE if no MySQL
// connection was established.
return TRUE;
}
return $id;
}
else {
return false;
}
}
public function replace($table,$data,$tbl_key='id') {
$v='';
$n='';
foreach($data as $key=>$val) {
$n.="`$key`, ";
if(strtolower($val)=='null')
$v.="NULL, ";
elseif(strtolower($val)=='now()')
$v.="NOW(), ";
elseif(strcmp(substr($val,0,7),'**ESC**') == 0)
$v .= str_replace('**ESC**','',$val);
else
$v.= "'".$this->escape($val)."', ";
}
if ($v=='' || $n=='')
return false;
$q = "REPLACE INTO `".$this->prefix.$table."` ";
$q .= "(". rtrim($n, ', ') .") VALUES (". rtrim($v, ', ') .");";
if($this->query($q)){
$id=mysql_insert_id();
if ($id === 0) { // The ID generated for an AUTO_INCREMENT column by the previous INSERT query on success,
// 0 if the previous query does not generate an AUTO_INCREMENT value, or FALSE if no MySQL
// connection was established.
return TRUE;
}
return $id;
}
else {
return false;
}
}
public function update($table,$data,$where='1') {
$q = "UPDATE `".$this->prefix.$table."` SET ";
foreach($data as $key=>$val) {
if(strtolower($val)=='null') $q .= "`$key` = NULL, ";
elseif(strtolower($val)=='now()') $q .= "`$key` = NOW(), ";
elseif(strcmp(substr($val,0,7),'**ESC**') == 0) $q .= "`$key` = ".str_replace('**ESC**','',$val);
else $q.= "`$key`='".$this->escape($val)."', ";
}
$q = rtrim($q, ', ') . ' WHERE '.$where.';';
$result = $this->query($q);
if ($result) {
}
return $result;
}
public function search($table, $field, $value, $exact=FALSE)
{
$value = escape($value);
if (!$exact) {
$q = "select * from $table where $field like '%$value%';";
} else {
$q = "select * from $table where $field = '$value';";
}
return $this->query($q);
}
public function delete($table,$where='1') {
$q = "DELETE FROM `".$this->prefix.$table."` ";
$q .= " WHERE ".$where.";";
$result = $this->query($q);
if ($result) {
}
}
public function query($sql,$reset=FALSE) {
//echo "<pre>$sql</pre>";
$this->connect();
$command = strtok(trim($sql)," \n\t");
switch (strtoupper(trim($command))) {
case "SELECT":
case "SHOW":
case "DESCRIBE":
case "EXPLAIN":
if (isset($this->query_id[md5($sql)]) && $reset==FALSE) {
$row = mysql_fetch_array($this->query_id[md5($sql)], MYSQL_ASSOC);
if ($row == FALSE) {
unset($this->query_id[md5($sql)]);
return FALSE;
} else {
return $row;
}
} else {
$this->query_id[md5($sql)] = @mysql_query($sql, $this->link_id);
if (!$this->query_id[md5($sql)]) {
throw new DatabaseException(mysql_error($this->link_id),mysql_errno($this->link_id));
}
}
$row = mysql_fetch_array($this->query_id[md5($sql)], MYSQL_ASSOC);
if ($row == FALSE) {
unset($this->query_id[md5($sql)]);
return FALSE;
} else {
return $row;
}
break;
default:
return @mysql_query($sql, $this->link_id);
break;
}
}
}
?>
如果所有表单元素的名称都与表字段的名称相同,那么将数据从$\u POST
获取到数据库中是非常简单的。例如:
mysql_query("DELETE FROM stage WHERE listid=".intval($_POST['listid']));
在这种情况下
完整参考资料:因此,在我将其应用于站点的其余部分之前,上面的代码是100%没有问题的??也就是说,在实际降低系统安全性之后,放置strip\u标记和htmlspecialchars
。mysql\u real\u escape\u字符串函数的确切目的是引用分隔符,而不是其他内容。它非常cOmon不相信这个函数是与SQL inj.相关的。我只是一组语法规则的一部分。应该独立于SQL注入的可能性使用。当然。它不能保护任何东西,只能保护带引号的字符串。我发现这个术语更适合于数字转换。+1…好吧,或者,或者至少使mysql\u real\u escape\u string
最外层的调用…@user:只需删除strip_标记
和htmlspecialchars
$deleteid=mysql_real_escape_string($\u POST['listid'];mysql_send(“DELETE FROM stage where listid='deleteid');mysql_real_escape_string($\u POST['listid']))
应该足够了。或者如果你想使用htmlspecialchars
和strip\u标记(或任何其他函数),你应该转义它们的返回值:mysql\u real\u escape\u string(htmlspecialchars(strip\u标记($\u POST['listid'))
没错……mysql_real_escape_string应该可以做到这一点。htmlspecialchars和strip_标记有助于防止XSS,而XSS不适用于您在这里展示的示例。但是编写糟糕的存储过程仍然会被注入,因为您可以通过字符串连接构建查询……所以这不是一个简单的“做到这一点,完成”过程…-1传播存储过程是防止SQL注入的神奇证据这一神话。请看你引用的一个WTF示例loolStored过程不会阻止注入,而且引用的WTF示例在这种情况下完全有意义。编写糟糕的WTF类型的存储过程不会阻止注入,因此如果可能的话,你可以避免编写任何-errrm,嗯。这就是我所说的“我在计算机科学课上是第一名,但什么都不懂”。如果所有表单元素的名称都与表字段的名称相同,那么将数据从$\u POST获取到数据库是非常简单的,并且如果您运行一个通用查询,只需使用escape($value)即可直接进入SQL注入,如果您的服务器运行的是较旧版本的PHP,这也可以保护您。哦,您是否也转义字段名?@Col.Shrapnel,不确定您的意思..update()转义$\u POST中的值在我的示例中,如果类有问题,请告诉我不,我不建议使用转义()在字段名上,这将毫无帮助。唯一可能的方法是显式枚举所有字段名。使用允许的字段名创建一个数组,并对照它检查POST输入。是的,这看起来很无聊,但这是唯一安全的方法
$db = new Database("db.host","db.user","db.pass","db.database");
$data = $_POST;
$ok = $db->update('mytable', $data, 'something = something_else'); //$ok will be false if something went wrong
mysql_query("DELETE FROM stage WHERE listid=".intval($_POST['listid']));