从sql注入学sql

sql注入原理

数据库针对我们的输入会进行查询

一般来说,数据库的查询可以是:

SELECT * FROM users WHERE name = 'skulle' 

那么如果我们输入

skulle' OR 1=1; #

对于数据库而言,就会有这样一条命令

SELECT * FROM users WHERE name = 'skulle' OR 1=1; #

但是显然,不会这么简单,因为这种方法大家都知道了,因此才有了绕过

从数据库思路考虑绕过

数据库为了防止sql注入会采取一些措施,下面列举一下

  1. 过滤特殊字符:过滤用户输入中的特殊字符,如` ' " ; () #等,避免这些字符影响SQL语句的解析。

    这是最常用的,最简单的就是双写绕过,使用编码、注释符等绕过。例如:SELECT * FROM users WHERE name = '1'; # 中使用注释符绕过对单引号的过滤。

  2. 参数化查询:使用参数化查询语句或者预编译语句,并且参数只接受基本类型,不直接拼接用户输入到SQL语句中。
    例如:

     stmt = "SELECT * FROM users WHERE name = ?"
     stmt_prepared = db.prepare(stmt)
     stmt_executed = stmt_prepared.execute(input_name)
    

    可以尝试修改参数类型为字符串,或使用EXECUTE IMMEDIATE执行非参数化查询。例如:

     stmt = "SELECT * FROM users WHERE name = ?" 
     stmt_prepared = db.prepare(stmt)
     input_name = "1' OR 1=1;"   # 将参数改为字符串
     stmt_executed = stmt_prepared.execute(str(input_name)) 
    
  3. 限制数据库权限:不赋予用户过高的权限,避免执行Drop Table、Shutdown之类的危险操作。通常只赋予Select、Insert、Update的权限。

    尝试当前用户可利用的所有权限,或通过读取数据字典获取高权限账户密码登录

  4. 显示友好错误信息:不要直接将数据库的报错信息显示到用户界面,以免泄露过多信息。

     尝试不同的注入语句,或在报错位置插入注入语句导致报错并回显信息。
    
  5. SQL注入检测:对用户输入的数据执行SQL注入检测,检测可能存在的注入语句或 payload 并拦截。

    使用编码、注释及较为隐蔽的语法等来绕过检测。例如:

    SELECT * FROM users WHERE name = char(49); # 使用CHAR()编码绕过

  6. 安全编码:对用户数据在存储和显示的过程中,避免直接使用,转义或编码来减小SQL注入的风险。例如:

     name = request.get['name']
     name = mysql.escape_string(name)  # 转义特殊字符
     <p><?php echo htmlspecialchars($name) ?></p> # HTML编码
    

    对应的也使用解码函数来解码,再执行注入。例如:

     SELECT * FROM users WHERE name = unhex(&#39;3D&#39;) OR 1 = 1;   # 使用UNHEX()解码16进制
    
  7. WAF:使用Web应用防火墙来检测和阻挡常见的SQL注入语句,以防止注入攻击发生。

  8. 其他: 使用存储过程而不是直接拼接SQL语句,对注入检测结果记录日志以便追踪等。
    综上,数据库主要是通过过滤特殊字符、参数化查询、权限管理、显示友好错误信息等方法来防范SQL注入。同时开发人员也需要遵循安全编码规范,增强安全意识来减小注入风险。

sql注入思路

  1. sql注入要先找可供用户输入的地方,进行payload,在这之后还要考虑回显,sqlmap也是个不错的选择,但是一般情况下都会拿sqlmap试试吧

  2. 常见的注入方式有:拼接SQL语句、非法字符控制符注入(如;'--)、宽字节注入等

  3. 注入的查询语句中,信息是通过union select来获取的,用于抓取表名、列名、数据等信息

  4. 常用的过滤与绕过方式:

  • 使用过滤掉'--'等字符:可使用#、/.../等代替
  • 过滤空格:使用/**/代替
  • 过滤关键字:使用大小写混合、编码等绕过
  • 使用whitelist过滤:or 1=1--+绕过
  • 过滤非数字:使用unicode字符如ffff代替

学习mysql

  1. SELECT - 从数据库表中获取数据

     SELECT * FROM users;  //获取users表所有数据
     SELECT name, age FROM users; //获取users表的name和age字段
    
  2. UNION - 合并两个查询结果

     SELECT * FROM users WHERE name='john' UNION SELECT * FROM info;
    
  3. WHERE - 用于过滤记录

     SELECT * FROM users WHERE age=30; //获取age=30的用户
     SELECT * FROM users WHERE name LIKE '%mary%'; //获取名称包含mary的用户
    
  4. OR - 获取满足任一条件的记录

     SELECT * FROM users WHERE name='john' OR age=30;
    
  5. ORDER BY - 对查询结果排序

     SELECT * FROM users ORDER BY age DESC; //根据age降序排序
    

sql注入判断

来判断注入类型和网站漏洞情况:

  1. OR 1=1# - 如果该输入可以登录成功,那么很可能是数值型的布尔盲注入。
  2. ' OR 1=1# - 如果该输入可以登录成功,那么可能是字符型的布尔盲注入。
  3. OR SLEEP(5)# - 如果页面响应被延迟5秒,那么存在基于时间的盲注入。
  4. UNION SELECT 1,2,3# - 如果该输入可以登录成功并在页面上显示1 2 3,那么可能存在联合查询注入。
  5. OR '1'='1'# - 在MySQL下,如果该输入可以登录成功,那么可能存在字符回显注入。
  6. OR 1=1/* - 如果页面显示出错信息中包含SQL关键词,那么可能存在报错注入。
  7. a' AND (SELECT * FROM users WHERE username='admin') - 如果可以登录成功,那么存在提取数据的注入,并且admin账户存在。
  8. a' AND (SELECT * FROM users LIMIT 0,1)# - 如果每次重新输入会显示不同的用户名,那么存在基于查询结构的数据遍历注入。
posted @ 2023-04-28 13:03  逆世混沌  阅读(35)  评论(0)    收藏  举报