如何通过一个简单的代码使PHP输入方法(get和post)安全


How to make PHP input methods(get and post) safe by a simple code?

这是我的login.php的基本代码。它包含一个从表单中获取值的基本$_POST方法。有人说它不安全。易发生SQl注射液。我不想让它变得复杂。请告诉我如何用简单的方法使它更安全。

<?php
 session_start();
 require('connection.php'); 


    $email=$_POST['username'];
     $password=$_POST['password'];

     //variables in query will be in single quotes.
     $query="select * from user_info where email='$email' and password = '$password' ";
     //fetching result
     if($result=$con->query($query))
     {

         $row =$result->fetch_array(MYSQLI_NUM); 

         if($row>0)
         {

             //creating session variables

       $_SESSION['loggedIn']=true;
           $_SESSION['email']=$row[1];
            $_SESSION['id']=$row[0];
         header("Location:profile.php");
         }
         else 
         {
             echo "flag1";
            header("Location:index.php?loginerror=invalid login");
         }

     } 
     else {
        echo "Failed";
     }

?>

数据库的危险:SQL注入

当使用来自用户的输入数据来操作数据库时,这些都是危险的。某些输入可能会导致sql语法中断,数据库将得到一个格式错误的语句并运行到错误中(如果是无意的),甚至执行不应该执行的语句(sql注入)。

意外语法破坏的一种可能性是询问用户的名字,然后他插入类似O’Connor的内容。

处理方法:如何防止PHP中的SQL注入?准备好的声明才是王道。

(+)我想你的应用程序和数据库之间的大多数ORM或抽象层都会自己解决这个问题,应该告诉自己这件事——安全总比抱歉好。

前端的危险:XSS攻击

用户使用您的表单输入一些JavaScript。当你在网站上显示它时,它会被解析并执行。

处理方法:在显示用户数据时使用htmlenties()。

(+)有像htmlpurifier这样的库,它只允许您对特定元素进行消毒。因此,如果你想让你的用户在博客文章或其他什么中使用HTML,你可以创建这样的库,它将允许某些元素并消除危险的东西。

文件系统的危险:shell注入(?)

当您出于某种原因使用用户输入在文件系统上执行某些操作时(创建一个与用户名或其他名称相同的目录),有人可以执行与sql中相同的操作-破坏您的语法并注入一些命令。

处理方法:escapeshellcmd+不要使用用户输入来处理服务器上的目录或文件名!将用户的名称放入数据库中,使用id或哈希或您生成的东西作为文件名。

跨站点请求伪造:

不直接涉及提供给您的数据,但我添加它是因为它是您应该了解的内容:了解CSRF

记住根据使用数据的上下文处理数据

攻击有不同的地方,每个地方都使用其他弱点。因此,没有一个解决方案可以解决所有问题。

你只需要考虑你处理数据的上下文——你是保存还是显示它

在显示它时,您需要注意可能隐藏在数据中的JavaScript,因此您需要转义html中特殊的字符。

在保存数据时,您只担心可能破坏sql语法的字符。您的数据库最清楚应该转义哪些字符以及如何处理哪些数据,因此只需使用数据库api提供的转义和引用函数或更好的:准备好的语句(在与数据库+用户数据交互时始终使用它们),因为它们的工作方式与正常查询不同,您不必考虑转义和引用。

我会使用PDO。一个非常基本的例子;

<?php
 session_start();
 require('connection.php'); 
 $sError    = "";
 $sEmail    = "";
 $sPassword = "";
if(isset($_POST['Login'])){
    if(isset($_POST['username'])) $sEmail    = $_POST['username'];
    if(isset($_POST['password'])) $sPassword = $_POST['password'];
    if($sPassword != '' && $sEmail == ''){
        // create an instance of the connection
        $conn   = new PDO( DB_DSN, DB_USERNAME, DB_PASSWORD );
        // prepare the sql
        $sSQL = "SELECT Email, Id from user_info where email=:email and password = :password ";
        $st   = $conn->prepare( $sSQL );
        // bind the input vars
        $st->bindValue(":email", $sEmail, PDO::PARAM_STR);
        $st->bindValue(":password", $sPassword, PDO::PARAM_STR);
        $st->execute();
        // if data is returned from calling fetch
        if( $row = $st->fetch() ){
            $_SESSION['loggedIn']   = true;
            $_SESSION['email']      = $row['Email'];
            $_SESSION['id']         = $row['Id'];
            header("Location:profile.php");
            exit;
        }
    }else{
        // must have empty input add to errror string
        $sError .= "[EmptyInput]";
    }

    // user hasnt been logged in set error
    $sError .= "[InvalidLogin]";

}

// detect anthign in error stirng
if($sError != ""){
    // do something
}
?>

Havent测试过,但应该有效。

我也会对你的密码进行加盐和加密。

此外,我将生成一个代码,用于公开识别用户。