WebGoat

WebGoat

WebGoat是一个基于java应用的开源漏洞环境

安装

  1. 要确保虚拟机中装有Java环境

  2. 下载webgoat-server/webwolf文件

  3. 在虚拟机中执行以下命令

    java -jar webgoat-server文件名 --server.address=0.0.0.0
    java -jar webwolf文件名 --server.address=0.0.0.0
  4. Web页面测试是否安装成功,访问http://本机ip:8080/WebGoat,出现以下页面则表明安装成功

1 认证机制

攻击方式

  • 通过html隐藏的input标签值
  • 通过移除/修改提交的参数来确认程序的响应
  • 通过猜测或暴力破解强制访问站点的某些url

1.1 绕过认证(Authentication Bypasses)

1.1.1 实践

修改上述http消息主体的参数为secQuestion2/3

成功绕过该验证机制

1.1.2 源代码

 public boolean verifyAccount(Integer userId, HashMap<String, String> submittedQuestions) {
        //short circuit if no questions are submitted
        if (submittedQuestions.entrySet().size() != secQuestionStore.get(verifyUserId).size()) {
            return false;
        }
        if (submittedQuestions.containsKey("secQuestion0") && !submittedQuestions.get("secQuestion0").equals(secQuestionStore.get(verifyUserId).get("secQuestion0"))) {
            return false;
        }
        if (submittedQuestions.containsKey("secQuestion1") && !submittedQuestions.get("secQuestion1").equals(secQuestionStore.get(verifyUserId).get("secQuestion1"))) {
            return false;
        }
        // else
        return true;
    }
}

由上述代码可知,身份认证中只对变量名为secQuestion0/1的变量进行了检验,安全设置只局限在secQuestion0/1变量上,如果修改变量名为secQuestion3/4,就可以绕过该限制,从而成功实施攻击。该漏洞代码的缺陷:

  • 没有对传入的变量进行限制

1.2 JWT

1.2.1 概述

JWT(Json Web Tokens),JWT与Web服务器交互

在此流程中,可以看到用户使用用户名和密码登录服务器后返回的成功身份验证。服务器创建一个新令牌并将其返回给客户端。当客户端对服务器进行连续调用时,它将新令牌附加在“授权”标头中。服务器读取令牌,并在成功验证后首先验证签名,然后服务器使用令牌中的信息来识别用户。

JWT签名

每个JWT令牌至少应在发送给客户端之前进行签名,如果未签名,则客户端应用程序将能够更改令牌的内容。

1.2.2 token的组成

令牌是base64-url编码的,由三部分组成:header.claims.signature

JWT的内容以Base64URL进行了编码,base64加解码网站:https://jwt.io/#encoded-jwt

header头部

以上图中的JWT为例,头部解码后为:


{
  "alg":"HS256",
  "typ":"JWT"
}
  • alg:是说明这个JWT的签名使用的算法的参数,常见值用HS256(默认),HS512等,也可以为None。HS256表示HMAC SHA256。
  • typ:说明这个token的类型为JWT
claims声明

上图JWT的claims解码后为:

{
  "exp": 1416471934,
  "user_name": "user",
  "scope": [
    "read",
    "write"
  ],
  "authorities": [
    "ROLE_ADMIN",
    "ROLE_USER"
  ],
  "jti": "9bc92a44-0b1a-4c5e-be70-da52075b9a84",
  "client_id": "my-client-with-secret"
}

其中有些字段是JWT的固定参数,有特定的含义;而另一些是服务器自定义的参数,用来表示通话信息等。

signature签名

服务器有一个不会发送给客户端的密码(secret),用头部中指定的算法对header和claims的内容用此密码进行加密,生成的字符串就是JWT的签名。

HMACSHA256(
  base64UrlEncode(header) + "." +
  base64UrlEncode(payload),  
your-256-bit-secret
)

注:在HTTP传输过程中,Base64编码中的”=”,”+”,”/“等特殊符号通过URL解码通常容易产生歧义,因此产生了与URL兼容的Base64 URL编码。在Base64 URL编码中,”+”会变成”-“,”/“会变成”_”,”=”会被去掉,以此达到url safe的目的。

1.2.3 实践4

尝试更改收到的令牌并通过更改令牌成为管理员用户,一旦成为管理员,就重置投票

先切换用户,然后点击重置密码,并使用BP进行抓包:

对上述token进行解码:

此处我们将admin字段修改为true,一旦内容改变,token的签名也随之改变,所以此处我们可以将alg设为none,即没有加密算法来进行绕过。

头部
{
   "alg":"none"
}

编码后:

ewogICAiYWxnIjoibm9uZSIKfQ==
声明
{
  "iat": 1596437866,
  "admin": "true",
  "user": "Tom"
}

编码后:

ewogICJpYXQiOiAxNTk2NDM3ODY2LAogICJhZG1pbiI6ICJ0cnVlIiwKICAidXNlciI6ICJUb20iCn0=
最终token
ewogICAiYWxnIjoibm9uZSIKfQ.ewogICJpYXQiOiAxNTk2NDM3ODY2LAogICJhZG1pbiI6ICJ0cnVlIiwKICAidXNlciI6ICJUb20iCn0.

注:要把末尾的=去掉,一定要加上.

转发之后,服务器返回的响应如下:

此时我们就可以利用管理员token冒充管理员执行操作

源代码解析

从http请求中解析token的代码如下:

encodedHeader = TextCodec.BASE64URL.encode(jsonHeader);
            encodedPayload = TextCodec.BASE64URL.encode(jsonPayload);
            if (jsonHeader.toLowerCase().contains("none")) {
                encodedSignature="";
            } else {
                encodedSignature = TextCodec.BASE64URL.encode(getJWTSignature(jsonHeader, encodedHeader, encodedPayload, jsonSecret));
            }

从上述代码中可知,如果头部指定的算法字段为none,则签名可以为空,此代码就给篡改token有机可趁。

1.2.4 实践7

让他人代付

查看题目给出的token日志:

对token进行解码:

其中claims中的exp字段是token过期时间,将鼠标放上去JWT会自动解析时间,我们只需直接在上面修改数字查看时间,只要时间在当前时间之后就可以。同时把头部的alg置为None:

声明
{
  "iat": 1526131411,
  "exp": 1629217911,
  "admin": "false",
  "user": "Tom"
}

编码后:

ewogICJpYXQiOiAxNTI2MTMxNDExLAogICJleHAiOiAxNjI5MjE3OTExLAogICJhZG1pbiI6ICJmYWxzZSIsCiAgInVzZXIiOiAiVG9tIgp9
最终token
ewogICAiYWxnIjoibm9uZSIKfQ.ewogICJpYXQiOiAxNTI2MTMxNDExLAogICJleHAiOiAxNjI5MjE3OTExLAogICJhZG1pbiI6ICJmYWxzZSIsCiAgInVzZXIiOiAiVG9tIgp9.

修改http请求authorization的值为token

2. 不安全的对象直接引用

直接使用用户输入去访问数据和对象会造成不安全的对象直接引用。

2.1 XXE

2.1.1 XML实体

XML(EXtensible Markup Language),可扩展标记语言,是一种用于标记电子文件,使其具有结构性的标记语言,可以用来标记数据,定义数据类型。与HTML不同:HTML被设计来显示数据,XML被设计来传输数据。XML实体定义解析XML文档时被特定内容替换的标签,通常有三种类型的实体:

  • 内部实体
  • 外部实体
  • 参数实体
    一个实体必须由DTD(Document Type Definition)创造,如下图所示

    一旦上述XML文档被解析(绿框中的内容),定义的实体js就会被替换成“John Smith”。在java应用中,XML可以用于从客户端获取数据发送到服务器端。
实体

实体都以&开头,以;结束,上图中&js;就是实体

内部实体

创建内部实体的格式:

<!ENTITY {实体名} "{用来替代实体的文本}">
<!ENTITY js "This is text"

调用格式

&{实体名};
&js;
外部实体

外部实体引用的是来自外部的文件:

<?xml version="1.0"?>
  <!DOCTYPE test [
    <!ENTITY bbb SYSTEM "1.xml">
  ]>
&bbb;

外部实体中的SYSTEM表示引用系统外的文件。

2.2 XXE注入

XXE(XML External Entity,XML外部实体)攻击是一种破坏应用解析XML输入的攻击。XML输入中包含一个被易受攻击的XML解析器解析的外部实体的引用就会诱发此种攻击。

2.3 XXE攻击分类

  • Classic:一个外部实体包含在本地DTD语言中
  • Blind: 在响应中不会显示输出或错误
  • Error: 尝试从错误信息中获取资源内容

2.4 实践

XXE-4

响应中返回file:/c的文件

XXE-7

服务器可能能够接受其他的数据格式。因此,这可能导致JSON端点容易受到XXE攻击。

源代码:

 public AttackResult createNewUser(@RequestBody String commentStr, @RequestHeader("Content-Type") String contentType) throws Exception {
        AttackResult attackResult = failed(this).build();

        if (APPLICATION_JSON_VALUE.equals(contentType)) {
            comments.parseJson(commentStr).ifPresent(c -> comments.addComment(c, true));
            attackResult = failed(this).feedback("xxe.content.type.feedback.json").build();
        }
        if (null != contentType && contentType.contains(MediaType.APPLICATION_XML_VALUE)) {
            String error = "";
            try {
                Comment comment = comments.parseXml(commentStr);
                comments.addComment(comment, false);
                if (checkSolution(comment)) {
                    attackResult = success(this).build();
                }
            } catch (Exception e) {
                error = org.apache.commons.lang.exception.ExceptionUtils.getFullStackTrace(e);
                attackResult = failed(this).feedback("xxe.content.type.feedback.xml").output(error).build();
            }
        }
        return attackResult;
    }

由上可知服务器端对json/xml格式的数据都进行了解析处理,所以可以将json数据改为xml数据,进而实施xxe攻击。

3.XSS

3.1 实践

3.1.1 XSS-7

点击UpdateCart,下方显示card number,可知可能存在XSS漏洞,尝试构建payload:

<script>alert("XSS Test")</script>


   转载规则


《WebGoat》 fightingtree 采用 知识共享署名 4.0 国际许可协议 进行许可。
  目录