【问题标题】:Is my code safe for injection?我的代码可以安全注入吗?
【发布时间】:2012-05-26 11:03:22
【问题描述】:

我之前使用 MySQL,被告知它不安全,所以现在我在 PDO 中重新编写了我的管理员登录面板,这里和其他论坛的用户说不能注入。但是黑客还在进来……我登录后编辑了页面,告诉被黑客告诉我我在上面放了什么,黑客告诉我……

我需要知道我的代码是否安全。他告诉我他正在通过 SQL 进入。

所以首先我将他们的 IP 存储在一个会话中,因此如果他们的 IP 发生更改,它将注销他们(或用户名)

if ( isset($_SESSION['last_ip']) == false )
{
    $_SESSION['last_ip'] = $_SERVER['REMOTE_ADDR'];
}
if ( $_SESSION['last_ip'] !== $_SERVER['REMOTE_ADDR'] )
{
    session_unset();
    session_destroy();
}

然后这是我的登录信息:

session_start();
include 'functions/functions.php';  
$db = mysqlconnect();
$password = md5($_POST['mypassword']);
$mod = 1; 
$statement = $db->prepare("SELECT * FROM users WHERE username = ? AND password = ?");
$statement->execute(array($_POST['myusername'],$password));
$result = $statement->fetchObject()->mod;
$count = $statement->rowCount();
if ( $result == 1 ) {
    $db = mysqlconnect();
    // Register $myusername, $mypassword and redirect to file "login_success.php"
    $_SESSION['user'] = $_POST['myusername'] ;
    //Test if it is a shared client
    if ( !empty($_SERVER['HTTP_CLIENT_IP']) ) {
        $ip=$_SERVER['HTTP_CLIENT_IP'];
        //Is it a proxy address
    } elseif ( !empty($_SERVER['HTTP_X_FORWARDED_FOR']) ) {
        $ip=$_SERVER['HTTP_X_FORWARDED_FOR'];
    } else {
        $ip=$_SERVER['REMOTE_ADDR'];
    }
    $sqll = "UPDATE users SET lastip=? WHERE username=?";
    $q = $db->prepare($sqll);
    $q->execute(array($ip,$_SESSION['username']));
    $_SESSION['user'] = $_POST['myusername'] ;
    $sqlll = "INSERT INTO user_log (username,ip) VALUES (?, ?)";
    $qq = $db->prepare($sqlll);
    $qq->execute(array($_SESSION['username'],$ip));
    header("Location: home.php");
} else {
    echo "Wrong Username or Password";
}

代码可以注入吗?

这是我的 home.php 页面,它阻止用户查看它。

/// My conenct is here                    
$sql = "SELECT * FROM users WHERE username='$_SESSION[user]'";
$result = mysql_query($sql) or die(mysql_error());
$values = mysql_fetch_array($result);


if( isset($_SESSION['user']) ) {

} else {
    echo "Bye Bye";
    die;
}

if ( $values['mod'] == 1 ) {    
    echo "welcome";  
} else {
    echo"Your account has been reported for hacking";
    die;
}

【问题讨论】:

  • 在 SQL 中使用 $_POST['myusername'] 之前,您应该验证其格式是否正确。一个简单的preg_match() 就足够了,或者您可以将其转义到另一个变量,然后搜索该变量。还有,$_SERVER['HTTP_CLIENT_IP'] 是从哪里来的?
  • 我认为在 pdo 中你不需要格式化变量??
  • 黑客在做什么?为什么说“他进来了”,为什么会认为是 SQL 注入?
  • 如果黑客已经进去了,你怎么知道这是实际执行的代码?
  • 您不应该信任代理/转发的 $_SERVER 变量。这些是客户提供的数据,伪造起来很简单。唯一可靠的客户端 IP 值是$_SERVER['REMOTE_ADDR'],它由 php 确定,而不是用户。

标签: php mysql sql pdo


【解决方案1】:

假设您显示的查询是您使用的唯一查询,那么黑客如何使用您认为会阻止他的代码,这很有趣。 在 IT 世界中,前门通常是三重锁着的,而后门是开着的。 在这种情况下,它不是后门,而是门上的小窗户,用于查看您是否向骗子敞开大门。

对所有查询使用准备好的语句和变量绑定。

这是一般规则。您只是忘记了“所有查询”中的“全部”。

您的陈述:

$sql = "SELECT * FROM users WHERE username='$_SESSION[user]'";

是你打开的窗口。 很明显,您的黑客在会话数据中欺骗了用户名。简单的解决方案是:

  1. 验证用户名或您从外部收到的任何数据($_SESSION、$_POST、一些 $_SERVER 和其他),然后再对它进行任何操作。当然是在您执行任何数据库交互之前。
  2. 像在其他查询中一样使用变量绑定。

在这种情况下,删除标签或使用 mysql_real_escape_string 的价值较小,因为在没有任何不可存储的字符的情况下完全可以破解。

顺便说一句,您实际上并不需要使用 PDO 来使用变量绑定。在mysql中也是完全可能的。

$verbLok = mysqli_connect(Iam, not, gonna, tellyou);
$result = array();
if (($stmtLok = $verbLok->prepare( "SELECT * FROM users WHERE username = ?  limit 1")))
{        
    $stmtLok->bind_param("s", $_SESSION[user]);
    $stmtLok->execute();
    $result = $stmtLok->get_result();
    $stmtLok->close();
}
mysqli_close($verbLok);

应该为您解决问题。 $result 将保存一个结果行数组。我对常规查询不太熟悉了,但据我所知,它与您的代码相似。

可以在on this page 找到有关如何对您的查询进行 SQL 代码注入攻击的有趣阅读。

【讨论】:

    【解决方案2】:

    一个好的 SQL 注入预防措施是转义任何和所有可用于在计算过程中终止 SQL 命令以启动新命令的文本。

    为此,您应该对输入中的任何引号进行转义,并使用更好的 SQL — 在字段和表名周围使用反引号,使用引号包裹任何非代码文本等。

    SELECT * FROM `users` WHERE `id` = '1'
    

    然后用mysql_real_escape_string 转义所有引号,或者用#039 手动替换;等,还要确保转义任何 HTML 以确保它不会弄乱其他东西,请使用 htmlentities 等。

    【讨论】:

    • PDO 的重点是您不必这样做。您使用 placeholders 编写查询,准备它,然后使用传入的数据执行它,这些数据由 PDO 驱动程序自动转义。
    • 如果您只使用 mysql_real_escape_string、` 和 ' 以及对您期望的数据进行一些类型检查,则不需要使用 pdo。在查询的某些部分周围使用方括号 ( ) 也会有所帮助。检查返回的结果是不是你想要的,如果不是,die()
    • 在我自己的 SQL 框架上,我只是在使用大约 3-4 种不同的方法将数据放入数据库之前对数据进行转义。我总是检查我的网站是否存在 SQL 注入,但它们从不工作。
    • 不需要使用 3-4 种不同的方法进行转义。要么使用 mysql API 提供的方法进行转义,要么使用参数。不需要其他逃生方法。
    • 占位符更容易、更高效,并且实际上正在维护中。
    猜你喜欢
    • 2023-04-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-10-12
    • 1970-01-01
    • 2010-12-25
    • 1970-01-01
    相关资源
    最近更新 更多