当前位置: 首页 > 知识库问答 >
问题:

如何在以下PHP mysql_*代码上执行SQL注入?

岳卓君
2023-03-14

我有一个现有的应用程序,它使用不推荐的mysql函数来执行数据库查询。此后,我将大多数数据库访问(以及所有有用户输入的)更改为PDO,因此我相信我相对不会受到注入攻击。然而,我想知道如何在前面的代码上执行注入攻击,以便在需要时演示它是多么不安全。

我有以下格式的链接:

http://localhost/api/view.php?id=

然后未经过滤地将其传递到下面的选择函数中:

$db->select('invitations','Replied, Response, Registered',null,"Id = '".$id."'");
$res = $db->getResult();

然后执行var\u dump()以查看结果。

我试过这样的方法:

>

  • http://localhost/api/view.php?id=

    http://localhost/api/view.php?id=

    但这些类型的查询似乎不会成功。理想情况下,我希望能够做一些严肃的事情。我希望有类似于”的东西;删除表用户-- ,但我似乎无法让这种事情发生。

    以下是完整的select功能:

    public function select($table, $rows = '*', $join = null, $where = null, $order = null, $limit = null){
        // Create query from the variables passed to the function
        $q = 'SELECT '.$rows.' FROM '.$table;
        if($join != null){
            $q .= ' JOIN '.$join;
        }
        if($where != null){
            if (is_array($where)) {
                $filter = $where;
                $where = " 0 = 0 ";
                $qs = "";
                for ($i=0;$i<count($filter);$i++){
                    switch($filter[$i]['data']['type']){
                        case 'string' : $qs .= " AND ".$filter[$i]['field']." LIKE '%".$filter[$i]['data']['value']."%'"; Break;
                        case 'list' :
                            if (strstr($filter[$i]['data']['value'],',')){
                                $fi = explode(',',$filter[$i]['data']['value']);
                                for ($q=0;$q<count($fi);$q++){
                                    $fi[$q] = "'".$fi[$q]."'";
                                }
                                $filter[$i]['data']['value'] = implode(',',$fi);
                                $qs .= " AND ".$filter[$i]['field']." IN (".$filter[$i]['data']['value'].")";
                            }else{
                                $qs .= " AND ".$filter[$i]['field']." = '".$filter[$i]['data']['value']."'";
                            }
                            Break;
                        case 'boolean' : $qs .= " AND ".$filter[$i]['field']." = ".($filter[$i]['data']['value']); Break;
                        case 'numeric' :
                            switch ($filter[$i]['data']['comparison']) {
                                case 'eq' : $qs .= " AND ".$filter[$i]['field']." = ".$filter[$i]['data']['value']; Break;
                                case 'lt' : $qs .= " AND ".$filter[$i]['field']." < ".$filter[$i]['data']['value']; Break;
                                case 'gt' : $qs .= " AND ".$filter[$i]['field']." > ".$filter[$i]['data']['value']; Break;
                            }
                            Break;
                        case 'date' :
                            switch ($filter[$i]['data']['comparison']) {
                                case 'eq' : $qs .= " AND ".$filter[$i]['field']." = '".date('Y-m-d',strtotime($filter[$i]['data']['value']))."'"; Break;
                                case 'lt' : $qs .= " AND ".$filter[$i]['field']." < '".date('Y-m-d',strtotime($filter[$i]['data']['value']))."'"; Break;
                                case 'gt' : $qs .= " AND ".$filter[$i]['field']." > '".date('Y-m-d',strtotime($filter[$i]['data']['value']))."'"; Break;
                            }
                            Break;
                    }
                }
                $where .= $qs;
            }
            $q .= ' WHERE '.$where;
        }
        if($order != null){
            $q .= ' ORDER BY '.$order;
        }
        if($limit != null){
            $q .= ' LIMIT '.$limit;
        }
        // Check to see if the table exists
        if($this->tableExists($table)){
            // The table exists, run the query
            $query = @mysql_query($q);
            if($query){
                // If the query returns >= 1 assign the number of rows to numResults
                $this->numResults = mysql_num_rows($query);
                // Loop through the query results by the number of rows returned
                for($i = 0; $i < $this->numResults; $i++){
                    $r = mysql_fetch_array($query);
                    $key = array_keys($r);
                    for($x = 0; $x < count($key); $x++){
                        // Sanitizes keys so only alphavalues are allowed
                        if(!is_int($key[$x])){
                            if(mysql_num_rows($query) > 1){
                                $this->result[$i][$key[$x]] = $r[$key[$x]];
                            }else if(mysql_num_rows($query) < 1){
                                $this->result = null;
                            }else{
                                $this->result[$key[$x]] = $r[$key[$x]];
                            }
                        }
                    }
                }
                return true; // Query was successful
            }else{
                array_push($this->result,mysql_error());
                return false; // No rows where returned
            }
        }else{
            return false; // Table does not exist
        }
    }
    

    如何执行SQL注入?

    编辑:

    使用$\u GET['id']通过浏览器接收该值。事实上,还有第二个值没有在SQL查询中使用,而是在switch语句中使用。因此,完整请求如下所示:

    http://localhost/api/view.php?rsvp=<status>&id=<id>
    

    这可能会有所帮助。

    编辑2:

    可能需要提到的是,所讨论的id实际上是GUID,而不是数值。到目前为止,我用一个正确的ID运行了评论中的所有查询。以下是一些结果:

    >

    http://localhost/api/view.php?id=62FD23D8-B6C0-03F1-D45A-C9AC33C91774';从邀请中选择* =

    以下几行是使用$id的全部代码:

    // ...
    if(isset($_GET['id'])) {
        $id = $_GET['id'];
        $db->select('invitations','Replied, Response, Registered',null,"Id = '".$id."'");
        $res = $db->getResult();
    // ...
    }
    

  • 共有1个答案

    段干博明
    2023-03-14

    仅仅是一些特定的输入导致MySQL语法错误这一事实就证明了用户输入对SQL语法有一些意外的影响,这意味着SQL注入是可能的。

    但是,利用这种SQL注入是另一章。MySQL,或者更准确地说是PHP的MySQL扩展,默认情况下不支持使用MySQL\u query执行多条语句:

    mysql_query()发送一个唯一的查询(不支持多个查询)[…]

    因此,删除表的经典示例将不起作用,并且您仅限于当前语句的功能和从注入点开始允许的语法元素。

    在您的特定示例中,SELECT将您限制为

    • 从MySQL用户有权访问的数据库中读取任意数据
    • 使用LOAD_FILE功能读取文件
    • 使用语法将文件写入…语法

    对于读取任意数据,最好选择联合,因为结果似乎会反馈给用户。您只需确保生成的SQL是有效的,这意味着您的联合必须有三列(即回复、响应和从现有选择中注册):

    ' UNION SELECT '1','2','3
    

    然后,生成的语句看起来像:

    SELECT Replied, Response, Registered FROM invitations WHERE Id = '' UNION SELECT '1','2','3'
    

    现在,您可以用自己的表达式(包括LOAD_FILE)或子查询替换额外选择的值。

     类似资料:
    • 本文向大家介绍以下代码的执行顺序?相关面试题,主要包含被问及以下代码的执行顺序?时的应答技巧和注意事项,需要的朋友参考一下 参考回答: //输出2,6,5,3,4,1 为什么呢?具体请参考我的文章: 从promise、process.nextTick、setTimeout出发,谈谈Event Loop中的Job queue

    • 问题内容: 我有一个.sql文件,其中包含一堆要在heroku上的postgres数据库上执行的插入命令。但我不知道该怎么做: 如果我有权访问postgres控制台,请输入以下内容: 但似乎heroku不支持此命令。我尝试过 但这不能让我输入文件。 还有其他选择吗? 问题答案: 对于种子数据库之类的事情,我推荐理查德·布朗(Richard Brown)的答案:可以说,最好使用Rails种子机制之类

    • 问题内容: 我正在开发应用程序(用C ++编写),该应用程序在运行时会生成一些机器代码(现在是Linux,x86-64,但我计划在ARM上迁移)。接下来,它将生成的代码存储在内存中,并通过跳转到内存位置来执行它。长期以来,我在分配可执行内存方面遇到问题,但最终我使用以下方法解决了问题: 到目前为止,它是可行的,但是我不确定这是否是执行此类操作的优雅方法。我想知道可执行加载程序是如何做到的? 问题答

    • 我能够使用Jsch连接shell通道,然后我必须执行后续命令,我已经阅读了下面的帖子通过Jsch Shell执行多个命令 我已经试过了,如下所示 但是cmd1是UNIX服务器登录脚本,所以即使我用putty给出下面的命令 我无法在一个实例中执行所有三个,只有cmd1正在执行,因此也不能使用Jsch。 因为cmd1是用于登录的,所以通常我会在puty中执行cmd1,然后一旦登录到unix服务器,我就

    • 问题内容: 到目前为止,我已经看到了这些问题的答案2,)建议使用GCD的这样: 输出: 等一下 是一个变量,因此我可以轻松做到这一点: 输出: 所以,是没有用的,如果我们我可以改变的价值!转换成常量并非易事,因为它需要类型化。 那么我们应该放弃Swift吗?有没有一种安全的方法可以只执行一次代码? 问题答案: 由闭包初始化的静态属性是延迟运行的,最多只能运行一次,因此尽管被调用了两次,但它仅打印一

    • 问题内容: 我如何强制Spark执行对map的调用,即使它认为由于其惰性求值而无需执行该调用? 我已经尝试过使用map调用了,但是仍然不能解决问题。我的地图方法实际上将结果上传到HDFS。因此,它不是无用的,但Spark认为是。 问题答案: 简短答案: 要强制Spark执行转换,您需要要求一个结果。有时,一个简单的动作就足够了。 TL; DR: 好的,让我们回顾一下 操作。 支持两种类型的操作: