- The Guide to Finding and Reporting Web Vulnerabilities
- About the Author
- About the Tech Reviewer
- Foreword
- Introduction
- Who This Book Is For
- What Is In This Book
- Happy Hacking!
- 1 Picking a Bug Bounty Program
- 2 Sustaining Your Success
- 3 How the Internet Works
- 4 Environmental Setup and Traffic Interception
- 5 Web Hacking Reconnaissance
- 6 Cross-Site Scripting
- 7 Open Redirects
- 8 Clickjacking
- 9 Cross-Site Request Forgery
- 10 Insecure Direct Object References
- 11 SQL Injection
- 12 Race Conditions
- 13 Server-Side Request Forgery
- 14 Insecure Deserialization
- 15 XML External Entity
- 16 Template Injection
- 17 Application Logic Errors and Broken Access Control
- 18 Remote Code Execution
- 19 Same-Origin Policy Vulnerabilities
- 20 Single-Sign-On Security Issues
- 21 Information Disclosure
- 22 Conducting Code Reviews
- 23 Hacking Android Apps
- 24 API Hacking
- 25 Automatic Vulnerability Discovery Using Fuzzers
Exercise: Spot the Vulnerabilities
Some of these tips may seem abstract, so let’s walk through an example program, written in Python, that will help you practice the tricks introduced in this chapter. Ultimately, reviewing source code is a skill to be practiced. The more you look at vulnerable code, the more adept you will become at spotting bugs.
这些技巧中有些可能看起来比较抽象,因此我们来介绍一个用 Python 写的示例程序,帮助你实践本章节中介绍的技巧。最终,检视源代码是需要实践的技能。你查看越多漏洞代码,就会越熟悉在代码中发现错误的技巧。
The following program has multiple issues. See how many you can find:
以下程序有多个问题。看看你能找出多少个问题:
import requests
import urllib.parse as urlparse
from urllib.parse import parse_qs
api_path = "https://api.example.com/new_password"
user_data = {"new_password":"", "csrf_token":""}
def get_data_from_input(current_url):
# get the URL parameters
# todo: we might want to stop putting user passwords 1
# and tokens in the URL! This is really not secure.
# todo: we need to ask for the user's current password
# before they can change it!
url_object = urlparse.urlparse(current_url)
query_string = parse_qs(url_object.query)
try:
user_data["new_password"] = query_string["new_password"][0]
user_data["csrf_token"] = query_string["csrf_token"][0]
except: pass
def new_password_request(path, user_data):
if user_data["csrf_token"]: 2
validate_token(user_data["csrf_token"])
resp = requests.Response()
try:
resp = requests.post(url=path, headers=headers, timeout=15, verify=False, data=user_data)
print("Your new password is set!")
except: pass
def validate_token(csrf_token):
if (csrf_token == session.csrf_token):
pass
else:
raise Exception("CSRF token incorrect. Request rejected.")
def validate_referer(): 3
# todo: implement actual referer check! Now the function is a placeholder. 4
if self.request.referer:
return True
else:
throw_error("Referer incorrect. Request rejected.")
if __name__ == "__main__":
validate_referer()
get_data_from_input(self.request.url)
new_password_request(api_path, user_data)
Let’s begin by considering how this program works. It’s supposed to take a new_password
URL parameter to set a new password for the user. It parses the URL parameters for new_password
and csrf_token
. Then, it validates the CSRF token and performs the POST request to change the user’s password.
让我们开始考虑这个程序是如何工作的。它应该接收一个 new_password 的 URL 参数来为用户设置新密码。它会解析 URL 参数以获取 new_password 和 csrf_token。然后,它会验证 CSRF 令牌并执行 POST 请求以更改用户的密码。
This program has multiple issues. First, it contains several revealing developer comments 1 . It points out that the request to change the user’s password is initiated by a GET request, and both the user’s new password and CSRF token are communicated in the URL. Transmitting secrets in URLs is bad practice because they may be made available to browser histories, browser extensions, and traffic analytics providers. This creates the possibility of attackers stealing these secrets. Next, another development comment points out that the user’s current password isn’t needed to change to a new password! A third revealing comment points out to the attacker that the CSRF referer check functionality is incomplete 4 .
该程序存在多个问题。首先,它包含多个暴露开发者注释的部分。1.它指出更改用户密码的请求是通过 GET 请求发起的,并且用户的新密码和 CSRF 令牌都在 URL 中进行通信。在 URL 中传输密钥是不好的做法,因为它们可能会被浏览器历史记录、浏览器扩展和流量分析提供者公开。这会导致攻击者窃取这些秘密的可能性。其次,另一个开发注释指出,不需要用户当前的密码就可以更改新密码!第三个显露性评论指出,CSRF referrer 检查功能不完整。
You can see for yourself that the program employs two types of CSRF protection, both of which are incomplete. The referer check function checks only if the referer is present, not whether the referer URL is from a legitimate site 3 . Next, the site implements incomplete CSRF token validation. It checks that the CSRF token is valid only if the csrf_token
parameter is provided in the URL 2 . Attackers will be able to execute the CSRF to change users’ passwords by simply providing them with a URL that doesn’t have the csrf_token
parameter, or contains a blank csrf_token
, as in these examples:
你可以自己看到这个程序使用了两种 CSRF 保护,但它们都不完整。Referer 检查函数只检查 Referer 是否存在,而不检查 Referer URL 是否来自合法站点 3。此外,该站点实现的 CSRF 令牌验证也不完整。它只会检查 CSRF 令牌是否有效,仅当 URL 中提供了 csrf_token 参数时才会进行检查 2。攻击者可以通过提供没有 csrf_token 参数或包含空白 csrf_token 的 URL 来执行 CSRF,从而更改用户密码,例如:
https://example.com/change_password?new_password=abc&csrf_token=
https://example.com/change_password?new_password=abc
Code review is an effective way of finding vulnerabilities, so if you can extract source code at any point during your hacking process, dive into the source code and see what you can find. Manual code review can be time-consuming. Using static analysis security testing (SAST) tools is a great way to automate the process. Many open source and commercial SAST tools with different capabilities exist, so if you are interested in code analysis and participating in many source code programs, you might want to look into using a SAST tool that you like.
代码审查是找到漏洞的有效方式,因此,如果您在黑客过程中的任何时候可以提取源代码,请深入研究源代码,并查找您可以找到的内容。手动代码审查可能会花费很长时间。使用静态分析安全测试(SAST)工具是自动化过程的好方法。存在许多具有不同能力的开源和商业 SAST 工具,因此,如果您对代码分析感兴趣并参与许多源代码项目,则可能希望考虑使用您喜欢的 SAST 工具。
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论