WebGoat笔记
(一)WebGoat部署
安装Tomcat
在官网下载Tomcat 7.0版本的zip包到本地,解压。(用8.0版登陆不上webgoat)
新建两个系统变量CATALINA_BASE和CATALINA_HOME,变量值均为Tomcat的安装目录,例如F:\Webgoat\apache-tomcat-7.0.82
。在Path变量中添值%CATALINA_HOME%\lib;%CATALINA_HOME%\bin
。
cmd或powershell移动到安装目录下的bin文件夹,执行命令servic.bat install
。
配置WebGoat
下载WebGoat5.4版本的war包,放到Tomcat目录的webapps子目录下。
在conf目录下的tomcat-users.xml文件中加入以下内容。
<role rolename="manager"/>
<role rolename="webgoat_basic"/>
<role rolename="webgoat_admin"/>
<role rolename="webgoat_user"/>
<user username="admin" password="admin" roles="manager-gui"/>
<user username="webgoat" password="webgoat" roles="webgoat_admin"/>
<user username="basic" password="basic" roles="webgoat_basic,webgoat_user"/>
<user username="guest" password="guest" roles="webgoat_user"/>
登陆WebGoat
打开bin目录下的tomcat7w.exe
程序,启动Tomcat。
地址栏输入localhost:8080/WebGoat-5.4/attack
,用户名和密码均输入guest,即可进入WebGoat主页。
(二)General
HTTP基础
请求报文结构:
请求头:
- If-Modified-Since:说明浏览器最后一次收到资源的时间,如果自此之后资源没有更新,服务器会返回 304 响应指示浏览器使用缓存副本;
- Accept-Encoding:愿意接收的内容编码;
- Referer:提出当前请求的原始URL;
- Authorization:为一种内置的HTTP身份验证提交证书;
响应报文结构:
响应头:
- Location:说明重定向响应的目标;
- Cache-Control:向浏览器传送缓存指令;
- Expires:说明消息主体的有效时间,在此之前,浏览器可以使用缓存副本;
状态码
- 301 Moved Permanently:永久重定向,新URL将替换原始URL;
- 302 Found:临时重定向,在随后的请求中恢复原始URL;
- 304 Not Modified:指示浏览器使用缓存副本;
- 400 Bad Request:无效的http请求;
HTTP Splitting
如果应用不检查输入请求中的 CRLF(Carriage-Return Line-Feed),攻击者可以通过回车符(\r)和换行符(\n)插入消息头和消息体,控制响应信息
例如,在表单中填入字符串
foobar%0d%0aContent‐Length:%200%0d%0a%0d%0aHTTP/1.1%20200%20OK%0d%0aContent‐Type:%20text/html%0d%0aContent‐Length:%2047%0d%0a%0d%0a<html>Hacked J</html>
可以构造以下报文
Foobar
Content-Length: 0
HTTP/1.1 200 OK
Content-Type: text/html
Content-Length: 47
<html>Hacked J</html>
注入特殊字符后,HTTP 响应数据包中“Content‐Length: 0”告诉浏览器响应已经结束。再通过随后的报文传送一个新页面
缓存污染:HTTP头中的 Last‐Modified 字段设置为一个未来时间,迫使浏览器发送 If‐Modified‐Since 请求头
(三)Access Control Flaws
- 绕过表示层访问控制
登陆账户“Tom Cat”,使用ViewProfile功能,拦截请求包将动作改为DeleteProfile
- 绕过基于路径的访问控制
拦截请求,修改请求路径以绕到其他目录。
例如:../../../../../conf/tomcat-users.xml
- 绕过数据层访问控制
修改 request 中的employee_id
参数,恶意访问其他人的资料
- 远程管理界面
利用开发人员预留的参数接口访问管理界面,例如,在URL添加参数&admin=true
(四)Ajax Security
- 在表单利用HTML标签可构造DOM型XSS
- 客户端的数据都是不安全的
- 查看HTML源码可以看到一些隐藏信息,或者修改一些元素的属性。例如,删除
readonly=""
可以修改一些本不允许修改的数据 - 阅读 Javascript 理解其工作流程,可以绕过一些客户端的验证,或者得到一些隐藏信息
- XML 注入和 JSON 注入:修改 respond 的 XML 和 JSON 数据
- 静默交易攻击:通过浏览器直接执行 Javascript 中的功能函数完成交易。很多浏览器支持在地址栏输入类似
javascript:function();
的语句执行 JavaScript
(五)Authentication Flaws
- 弱口令
利用忘记密码功能,通过暴力破解回答问题,得到密码或设置新密码
- 基本身份认证
客户端用Authorization
头提供 Base64 编码的用户名和密码,修改 Authorization 头可以更改账户。但 Cookie 不变的话页面信息不会变
- 多级登陆
- 修改参数使已经用过的 TAN(Transaction Authentication Number)验证码仍然生效
- 修改 user 相关的参数访问其他用户的信息
(六)Buffer Overflows
当计算机向缓冲区内填充数据位数时超过了缓冲区本身的容量,溢出的数据会覆盖在合法数据上。
- 拦截请求后发送到Intruder,将参数 room_no 设为溢出目标。
- 攻击类型为 sniper,方案为 character blocks(大量的字符填充)。
- 设置好输入值,最小、最大值,步长,然后发送payload。
(七)Code Quality
从页面源码中找到泄漏的敏感信息,例如在注释中
(八)Concurrency
线程安全是指一个对象或类的领域在多线程同时使用的时候总是保持有效的状态。它往往可以利用并发错误,精确地在同一时间、同一个页面加载另一个用户。因为所有的线程共享同一个方法区,而所有的类变量存储在方法区,多个线程试图同时使用相同的类变量。
原因:
-
Web应用程序可以同时处理很多HTTP请求
-
开发人员经常使用的变量不是线程安全的
后果:
用户利用 Web 应用程序中的并发错误, 可以查看同一时间中,另一个用户试图登录同一个功能的信息。也可以利用并发缺陷查看他人信息或者篡改购物车付款金额。
(九)Cross-Site Scripting
存储型XSS
登陆 tom 的账户,修改 Street 一栏的信息为<script>alert("Hey guy!")</script>
。用 Jerry 的账户查看 Tom 的资料时会受到 XSS 攻击而弹出警告。
可使用输入验证来阻止上传 XSSPayload,而已经存储在服务端的 XSSPayload 可以通过输出编码阻止。
反射型XSS
构造一个包含 XSSPayload 的 URL,在服务端返回的 response 中,URL 上的 XSSPayload 会被当成页面源代码执行。
Cross Site Request Forgery(CSRF)
例:发送一封带有<img>
标签图片的邮件,利用 src 属性指向一个恶意请求
绕过确认
先提交一个<iframe>
或<img>
构造恶意请求,再用一个标签指向第一个请求触发的确认(注意要先后生效)
绕过Token
Anti-CSRF token:在请求发起页面插入Token用于完成请求和并验证该操作不是通过脚本执行的。
先使用一个<iframe>
打开页面,用 JS 读取出Token;然后加载另一个<iframe>
,并使用第一个<iframe>
读取的 Token 发送请求。
HTTPOnly
微软引入的新的 cookie 属性字段,被标记 HTTPOnly 字段后浏览器将禁止客户端脚本访问 Cookie
跨站跟踪攻击
嵌入 Ajax 请求,利用 HTTP TRACE 方法(回显服务器收到的请求,主要用于测试或诊断)
(十)Improper Error Handling
例:拦截请求,删除 password 参数,Java 代码会捕获空指针异常使得认证被绕过
(十一)Injection Flaw
命令注入
原理:修改提交的参数,使服务器执行恶意命令
防范:“清洗”所有输入数据是不错的防御方法,尤其是那些将被用于操作系统命令、脚本和数据库查询语句的数据
SQL注入
数字型SQL注入
注入参数为整型(ID、年龄、页码等),不需要单引号闭合。
字符串型SQL注入
通常使用单引号闭合参数,例如,在密码框输入error'or'1'='1
可绕过密码认证。
通过SQL注入操作数据
修改:注入UPDATE命令,例如:someuserid'; UPDATE salaries SET salary=999999 WHERE userid='jsmith
添加:注入INSERT命令,例如:someuserid';INSERT INTO salaries VALUES ('zrquan',9999999);--
盲注
-
某些SQL注入是没有明确返回信息的,只能通过条件的“真”和“假”进行判断
例:
101 AND ((SELECT pin FROM pins WHERE cc_number='1111222233334444') > 10000 );
可以判断PIN值是否大于1000,以此类推缩小范围,最终确定其值 -
SUBSTRING 方法用来截取字符串,可以使用该方法进行字符串型的盲注
SUBSTRING(STRING,START,LENGTH)
例:
101 AND (SUBSTRING((SELECT name FROM pins WHERE cc_number='4321432143214321'), 1, 1) < 'H' );
可以判断PIN字段的第一个字符是否小于H,经过多次测试(比较0-9 A-Z a-z等字符串可以确定每一个字符的值
日志欺骗
向日志添加虚假信息或插入脚本,管理员通过浏览器观看日志时恶意脚本会被执行
XPATH注入
XPATH:用于在文档中查找XML数据的语言
与 SQL 注入类似,XPATH 注入发生在当网站使用用户提供的信息查询 XML 数据时。通过向网站故意发送异常信息,攻击者可以发现 XML 数据的结构或访问那些本来无法访问到的数据。
数据库后门
触发器是在数据库管理系统上调用另一个数据库操作,如insert, select, update or delete(MySQL不支持触发器)
举个例子:攻击者可以用下面的命令创建一个触发器,该触发器在创建新用户时,将每个新用户的 Email 地址设置为攻击者的地址
someuserid;CREATE TRIGGER myBackDoor BEFORE INSERT ON employee FOR EACH ROW BEGIN UPDATE employee SET email='john@hackme.com' WHERE userid = NEW.userid
(十一)Denial of Service(DOS)
例:服务器允许两个用户同时登陆,通过 SQL 注入获取其他合法用户的密码,登陆三个用户,将会使服务器过度使用
(十二)Insecure Communication
敏感数据不能用明文发送,通常在验证后要切换到安全连接,因为攻击者可通过嗅探获得的
登录信息和收集到的其他信息入侵账户。一个好的Web 应用程序总是使用加密方式发送敏
感数据。
使用 HTTPS 访问后,所有数据被加密。服务器与应用程序通讯将通过传输层安全(Transport Layer Security TLS)),又称为安全套接字层(Secure Socket Layer(SSL))。TLS 是一种混合的加密协议,通过一个主密钥来建立通信。这个密钥使用的是 SHA-1 或 MD5 。
(十三)Insecure Configuration
利用不安全配置漏洞强行浏览一些禁止访问的资源,例如,蛮力猜测资源路径/WebGoat/config, /WebGoat/configuration, /WebGoat/conf
等,可发现隐藏页面
(十四)Malicious Execution(恶意执行)
利用漏洞上传包含恶意指令的文件到服务器并执行,脚本后门就属于典型的恶意文件
例如,上传一个包含java代码的文件,通过访问该文件执行代码创建一个新文件:
<html>
<% java.io.File file = new java.io.File("F:\\Webgoat\\apache-tomcat-7.0.82\\webapps\\WebGoat-5.4\\guest.txt"); file.createNewFile(); %>
</html>
(十五)Parameter Tampering
- 篡改参数
客户端验证不应该被认为是一种安全的参数验证方法,这种验证方式只能帮那些不知道所需输入的用户缩短服务器处理时间,攻击者可以用各种方法轻易的绕过这种机制。任何客户端验证都应该复制到服务器端,这将大大减少不安全的参数在应用程序中使用的可能性。
漏洞利用:用开发者工具修改客户端的一些限制,配合拦截工具可轻易修改参数
- 隐藏字段
开发人员在加载信息的页面上使用隐藏字段来跟踪、登录、定价等。虽然这是一种方便且易于开发的机制,但他们往往不验证从隐藏字段收到的信息。
漏洞利用:通过开发者工具可以看到隐藏的 html 元素,并对其进行恶意篡改
- 未检查的E-mail
多数网站都允许一个非验证的用户给“朋友”发送 e-mail 。对垃圾邮件发送者来说,这是一个绝佳的机制,可以利用公司的邮件服务器来发送电子邮件。
漏洞利用:将隐藏域中的邮箱修改为目标邮箱
(十六)Session Management Flaws
cookie认证欺骗
许多应用程序自动记录登录站点的用户指定 Cookie,如果使用算法生成的 Cookie 都能获得,则Cookie可以被猜解。而且一些被放到客户端上的 Cookie 可能被跨站攻击盗取。
例:
- 分别用 webgoat 和 aspect 两个账号登陆,截取到服务端返回的 cookie 值是
AuthCookie=65432ubphcfx
和AuthCookie=65432udfqtb
- 两个 cookie 值的数字位没变,英文字符串则是用户名倒过来后再向后推一位,可以推测出用户 alice 的 cookie 是
AuthCookie=65432fdjmb
- 截取请求并添加推测的 cookie 值,可以成功通过登陆认证
会话劫持
应用开发者开发会话ID时,经常忘记配置复杂性和随机性,如果一个用户的特定会话ID不够复杂和随机则很容易遭受到蛮力攻击。
会话固定
原理:
服务器通过每个用户唯一的 SessionID 来确认其合法性。如果用户已登录,并且授权他不必重新验证授权,则当他重新登录应用系统时,他的 Session ID 依然是被认为合法的。
漏洞利用:
攻击者可以用一个选定的 SessionID 给受害人发送一个超链接。例如,准备好一封恶意邮件,它看起来像是一个从应用程序管理员发来的官方邮件。如果受害者点击了链接,并且该受害者以攻击者指定的 ID 登录了系统;那么攻击者可以不经授权直接使用与受害者相同的ID访问该页面。
(十七)Web Services
SOAP请求
SOAP:
基于 XML 的简易协议,可使应用程序在 HTTP 之上进行信息交换;
WSDL:
Web Services Description Language,是一门基于 XML 的语言,用于描述 Web Services 以及如何对它们进行访问;
截取请求并调用任何方法,用SOAPAction:
头发送一个SOAP(简单对象访问协议)请求的有效账户
WSDL扫描
拦截请求,修改 field 参数获取信息
SQL注入
- 使用 WebScarab 的 WebServices 模块,看到调用的 Web 服务或者 WSDL 历史文件
- WebScarab 将解析 XML 文件,所以可以选择调用的操作,然后输入一个调用的参数值
- 在“vaule”中输入
1 or 1=1
,(401错误表示没有授权,先insert已认证的cookie)
SAX注入
SAX:全称 Simple API for XML,是一个用于处理 XML 事件驱动的“推”模型,虽然它不是 W3C 标准,但它却是一个得到了广泛认可的API。
SAX 解析器不像 DOM 那样建立一个完整的文档树,而是在读取文档时激活一系列事件,这些事件被推给事件处理器,然后由事件处理器提供对文档内容的访问。
SAX解析器会解析任何格式正常的XML文件。
例:只要匹配到有效的标记符号及闭合符号即认为正确。当您向原有的XML文件中添加新的 changePassword 元素时,如果 id 和 password 等标记都正确,那么解析器将很乐意帮您去修改另一个 userid 的密码(有点像 DOM XSS)。
更改密码时提交以下代码:
newpassword</password>
</wsns1:changePassword>
<wsns1:changePassword>
<id xsi:type='xsd:int'>102</id>
<password xsi:type='xsd:string'>notforyoutoknow
(十八)Challenge
目标
破坏身份验证方案,从数据库中盗取所有的信用卡信息,然后破坏页面"webgoat_challenge_guest.jsp"
stage1
越权登陆,一般有两种方法:
- 通过认证用户的身份登陆
- 利用注入漏洞
-
首先尝试找到注入点,发现输入可能可以注入的点有 Username/Password/Submit/user/user(Cookie) 这几个,用户名一般不能进行注入。
-
看到 User(cookie) 是 Base64 编码的,解码后的值和 user 一样是 youaretheweakestlink 。尝试对 user 进行 sql 注入,将注入后的字符串进行 Base64 编码后替换 User(cookie) ,还是不行。
-
查看网页的HTML源码,找到被隐藏的表单,可以看到 youaretheweakestlink 的 name 属性是 user ,它应该就是正确的用户名,但密码无法注入,要找到密码。
密码在
localhost:8080/WebGoat-5.4/source?source=true
,大概靠信息收集吧······
stage2
- 需要获得全部信用卡号码,一般通过 sql 注入获取 database 的信息。
- 查看拦截信息,发现登陆成功后并没有发送其他请求去获得 credit card 的数据,所以注意点应该在登陆认证的 request 中。
- 依次对几个注入点进行检查,发现对 user(Cookie) 进行注入就可以获得到所有信用卡信息,但是注意使用的是 Base64 编码后的信息。
stage3
不同的协议表单获取页面,这种表单一般有两种获取形式:
- 利用 SQL 从数据库中读取
- 利用 cmd 命令行得到
- 先尝试拦截报文,对 file 字段做 SQL 注入,发现没有效果。然后进行命令行注入,使用通用命令
ls
(webgoat 的 Java 源码里做了判断,只有 tcp 有注入漏洞)。 - 注入命令
&& pwd && ls && find -name "webgoat_challenge_guest.jsp"
找到目标文件的路径,注意 Mac 中的指令会有所差别。 - 得到目标文件路径后,通过注入命令
echo "[payload]" > [target]
覆盖文件内容。