#知识点:
1.JavaWeb常见安全及代码逻辑
通过URL信息来对应源码文件。没有代码的情况下很难渗透。
2.目录遍历&身份验证&逻辑&JWT
3.访问控制&安全组件&越权&三方组件
1、JavaWeb-WebGoat8靶场搭建使用
• 下载地址:https://github.com/WebGoat/WebGoat/releases,下载webgoat-server-8.2.2.jar
• 压缩到jar包里面。
• 如何启动:安装jdk,运行 java -jar webgoat-server-8.1.0.jar --server.port=9002
• 访问127.0.0.1:9002/WebGoat/login,注册账号登录就可以了。
WebGoat8.1版本,需求是JDK15
WebGoat8.2版本,需求是JDK17
2、安全问题-目录遍历
【例1】:WebGoat8 - A1- 路径遍历 - 第2关:上传文件时的路径遍历,将文件上传到正常位置之外的位置
实际上传的目录地址:

目标地址:(实际上传地址的前2级目录)

关键代码:
publicAttackResultuploadFileHandler(@RequestParam("uploadedFile")MultipartFilefile,@RequestParam(value="fullName",required=false)StringfullName){
returnsuper.execute(file,fullName);
}
抓包地址:http://127.0.0.1:9002/WebGoat/start.mvc#lesson/AuthBypass.lesson/1
上传图片:

查看代码:

接收两个参数uploadFile赋值给file,fullName赋值给fullName

修改数据包中的“fullName”的值,文件的上传路径也会跟着变化


修改上传数据包为上上一级目录,结尾是test:成功通关


【例2】:A1- 第3关
../被过滤
关键代码:../被替换为空

由于replace只会过滤一次,把fullname修改为:

成功过关。
解决问题:如果当前目录(比如image文件夹)只能上传图片,该文件夹被设置为不能执行可执行文件,所以尝试将执行脚本上传至别的目录(一般上传图片的文件夹会限制不能执行脚本文件,但是根目录不会做限制)


3、安全问题 - 身份认证
【例】:A2-Authentication Bypasses-第2关:绕过身份验证 -绕过安全问题重置密码
代码:


键名---键值,从多个问题中随机选出2个问题来验证:问题和答案相对应
问题s0:你的名字?---刘迪
问题s1:你的出生地?---湖北
给服务器发送数据 s0=xiaodi&s1=湖北 则验证通过
绕过逻辑:
固定接收数据(安全的验证):只接收数据库存在的键名s0、s1,不接收不存在的键名
不固定的接收数据(不安全的验证):键名和键值都接收,数据库存在s0和s1的键名,数据库不存在s3和s4(即s3=null,s4=null),攻击者通过s3=null&s4=null发送数据,因为s3 s4本来就为空,相当于NULL,那么就能进行绕过。

安全验证:
固定的接收数据:如果服务器只接收固定键名,s0和s1,再判断s0和s1的值,就没法绕过
4、安全问题 - JWT Token
使用JSON Web令牌(JWT)进行身份验证(java和python运用较多)
传统token方式和jwt在认证方面有什么差异?
传统token方式:
用户登录成功后,服务端生成一个随机token给用户,并且在服务端(数据库或缓存)中保存一份token,以后用户再来访问时需携带token,服务端接收到token之后,去数据库或缓存中进行校验token的是否超时、是否合法。
jwt方式:
用户登录成功后,服务端通过jwt生成一个随机token给用户(服务端无需保留token),以后用户再来访问时需携带token,服务端接收到token之后,通过jwt对token进行校验是否超时、是否合法。
JWT 令牌由三个部分组成,分别是 标头(Header)、有效载荷(Payload)、签名(Signature),并且由 "." 分割.
类似于 xxxx.yyyy.zzzzz ,也就是 Header.Payload.Signature
如:eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c
jwt解密平台:https://jwt.io/
生成规则如下:
- 第一段HEADER部分,固定包含算法和token类型,对此json进行base64url加密,这就是token的第一段。
{"alg":"HS256","typ":"JWT"}
- 第二段PAYLOAD部分,包含一些数据,对此json进行base64url加密,这就是token的第二段。
{"sub":"1234567890","name":"John Doe","iat": 1516239022...}
- 第三段SIGNATURE部分,把前两段的base密文通过
.拼接起来,然后对其进行HS256加密,再然后对hs256密文进行base64url加密,最终得到token的第三段。
base64url( HMACSHA256( base64UrlEncode(header) + "." + base64UrlEncode(payload), your-256-bit-secret (秘钥加盐) ) )最后将三段字符串通过 .拼接起来就生成了jwt的token。
- 替代 + 及 _ 替代 / 。
【例】:A2-JWT tokens - 第五关:尝试更改令牌,登录管理员用户
① 切换账号为“Tom”(普通用户),抓包发现:Cookie为三段式的,说明是jwt生成的token格式

解密后:Tom非admin用户

JWT的攻击方式:
1.空加密算法(很少见)
2.爆破
3.KID
参考,JWT原理及常见攻击方式:https://www.cnblogs.com/vege/p/14468030.html
1.空加密算法:
因为生成字JWT符串:算法模式+秘钥(缺一不可)
空加密算法的设计初衷是用于调试的,但是如果某天开发人员脑阔瓦特了,在生产环境中开启了空加密算法,缺少签名算法,jwt保证信息不被篡改的功能就失效了。
空加密算法,可以在header中指定alg为None,把签名设置为空(即不添加signature字段),这需要服务器(后端代码)支持不要秘钥签名(空模式加密,即加密方式为None的时候,就不需要签名(密钥))
比如:

找到相对应的代码段发现可以空加密然后用python脚本去写空加密jwt
# -*- coding:utf-8 -*- import jwt import base64 def b64urlencode(data): return base64.b64encode(data).replace(b'+', b'-').replace(b'/', b'_').replace(b'=', b'') print(b64urlencode(b'{"alg":"none"}')+b'.'+b64urlencode(b'{"iat":1573470025,"admin":"true","user":"Tom"}')+b'.')
eyJhbGciOiJub25lIn0.eyJpYXQiOjE1NzM0NzAwMjUsImFkbWluIjoidHJ1ZSIsInVzZXIiOiJUb20ifQ.
//(header+'.'+payload,去掉了'.'+signature字段),没有签名(密钥),就只有2段了,没有第3段
看代码是否支持空模式加密:

2.密钥爆破:
http://127.0.0.1:9091/WebGoat/start.mvc#lesson/JWT.lesson/7
【例】:A2-第8关,通过原JWT拿到密钥,修改用户名为webgoat,生成新的JWT

通过字典爆破,拿到签名,修改用户名为WebGoat,生成新的jwt
从代码中找到密钥:

爆破相关工具:c-jwt-cracker、python脚本

3. 修改KID参数
kid是jwt header中的一个可选参数,全称是key ID,它用于指定加密算法的密钥
{ "alg" : "HS256", "typ" : "jwt", "kid" : "/home/jwt/.ssh/pem"}因为该参数可以由用户输入,所以也可能造成一些安全问题。
(1)任意文件读取
kid参数用于读取密钥文件,但系统并不会知道用户想要读取的到底是不是密钥文件,所以,如果在没有对参数进行过滤的前提下,攻击者是可以读取到系统的任意文件的。
{ "alg" : "HS256", "typ" : "jwt", "kid" : "/etc/passwd"}(2)SQL注入
kid也可以从数据库中提取数据,这时候就有可能造成SQL注入攻击,通过构造SQL语句来获取数据或者是绕过signature的验证
{ "alg" : "HS256", "typ" : "jwt", "kid" : "key11111111' || union select 'secretkey' -- "}(3)命令注入
对kid参数过滤不严也可能会出现命令注入问题,但是利用条件比较苛刻。如果服务器后端使用的是Ruby,在读取密钥文件时使用了open函数,通过构造参数就可能造成命令注入。
"/path/to/key_file|whoami"
对于其他的语言,例如php,如果代码中使用的是exec或者是system来读取密钥文件,那么同样也可以造成命令注入,当然这个可能性就比较小了。
5、安全问题-访问控制&安全组件-第三方组件
【例】:A9-第12关-Vulnerable Components

① 查看代码,发现引用了xstream组件:

百度查找相关漏洞:xstream 1.4.5 CVE-2013-7285
找到这个漏洞的介绍:https://x-stream.github.io/CVE-2013-7285.html 影响版本:XStream <= 1.4.6
找漏洞利用的POC
② 发现log4j组件

6、访问控制
- 隐藏属性:前端页面选择性的展示某些信息(隐藏某些重要的信息)
- 水平越权:同一级别用户权限的查看
【例】:A5-第2关登录后、第3关查看个人信息

①隐藏属性

查看源码:

②水平越权
比如,只要修改“userId”的值,就可以查看其他用户的个人信息。
浙公网安备 33010602011771号