Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Adding A10:2020 SSRF exercise #608

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ Disclaimer: You are about to install vulnerable apps in your machine! 🔥
| A7 - Identity and Authentication Failures | Golang | [Insecure go project](owasp-top10-2021-apps/a7/insecure-go-project) |
| A8 - Software and Data Integrity Failures | Python | [Amarelo Designs](owasp-top10-2021-apps/a8/amarelo-designs) |
| A9 - Security Logging and Monitoring Failures | Python | [GamesIrados.com](owasp-top10-2021-apps/a9/games-irados) |
| A10 - Server-Side Request Forgery | Go | [Doryl Site Check](owasp-top10-2021-apps/a10/doryl-site-check) |

## OWASP Top 10 (2016) Mobile apps: 📲

Expand Down
39 changes: 39 additions & 0 deletions owasp-top10-2021-apps/a10/doryl-site-check/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
.SILENT:
.DEFAULT_GOAL := help

COLOR_RESET = \033[0m
COLOR_COMMAND = \033[36m
COLOR_YELLOW = \033[33m
COLOR_GREEN = \033[32m
COLOR_RED = \033[31m


## Installs a development environment
install: compose msg

## Composes project using docker-compose
compose: compose-down
docker-compose -f deployments/docker-compose.yml -p secdevlabs up -d --build --force-recreate

## Down project using docker-compose
compose-down:
docker-compose -f deployments/docker-compose.yml -p secdevlabs down -v --remove-orphans

## Prints initialization message after compose phase
msg:
chmod +x deployments/check-init.sh
./deployments/check-init.sh

## Prints help message
help:
printf "\n${COLOR_YELLOW}${PROJECT}\n------\n${COLOR_RESET}"
awk '/^[a-zA-Z\-\_0-9\.%]+:/ { \
helpMessage = match(lastLine, /^## (.*)/); \
if (helpMessage) { \
helpCommand = substr($$1, 0, index($$1, ":")); \
helpMessage = substr(lastLine, RSTART + 3, RLENGTH); \
printf "${COLOR_COMMAND}$$ make %s${COLOR_RESET} %s\n", helpCommand, helpMessage; \
} \
} \
{ lastLine = $$0 }' $(MAKEFILE_LIST) | sort
printf "\n"
16 changes: 16 additions & 0 deletions owasp-top10-2021-apps/a10/doryl-site-check/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
# Doryl site-check
![image](images/doryl-site-check.png)
This is a simple Golang webapp that contains an example of a SSRF(Server Side Request Forgery) vulnerability and its main goal is to describe how a malicious user could exploit it.

## What is SSRF?
*from ![PortSwigger Academy](https://portswigger.net/web-security/ssrf).*

Server-side request forgery (also known as SSRF) is a web security vulnerability that allows an attacker to induce the server-side application to make requests to an unintended location.

In a typical SSRF attack, the attacker might cause the server to make a connection to internal-only services within the organization's infrastructure. In other cases, they may be able to force the server to connect to arbitrary external systems, potentially leaking sensitive data such as authorization credentials.

## What is the impact of SSRF attacks?

A successful SSRF attack can often result in unauthorized actions or access to data within the organization, either in the vulnerable application itself or on other back-end systems that the application can communicate with. In some situations, the SSRF vulnerability might allow an attacker to perform arbitrary command execution.

An SSRF exploit that causes connections to external third-party systems might result in malicious onward attacks that appear to originate from the organization hosting the vulnerable application.
120 changes: 120 additions & 0 deletions owasp-top10-2021-apps/a10/doryl-site-check/app/api/services.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
package api

import (
"fmt"
"io"
"net"
"net/http"
"net/url"
"strings"

"github.com/labstack/echo"
)

type missingSecurityHeaders struct {
ContentSecurityPolicy bool
XFrameOptions bool
XContentTypeOptions bool
ReferrerPolicy bool
PermissionsPolicy bool
}

// Index renders the home page.
func Index(c echo.Context) error {
return c.Render(http.StatusOK, "index.html", map[string]interface{}{})
}

// SiteCheckPage renders page with results about headers check.
func SiteCheckPage(c echo.Context) error {
target := c.FormValue("target")
if !strings.Contains(target, "http") {
target = "http://" + target
}

domain, ips := lookupIPDomain(target)
headers, missing, body := httpGet(target)
return c.Render(http.StatusOK, "check.html", map[string]interface{}{
"target": target,
"domain": domain,
"ips": ips,
"headers": headers,
"secHeaders": missing,
"body": body,
})
}

func lookupIPDomain(target string) (string, string) {
domain, err := url.Parse(target)
if err != nil {
fmt.Println("URL parser error:", err)
}

iprecords, err := net.LookupIP(domain.Hostname())
if err != nil {
fmt.Println("LookupIP error:", err)
}

var ips string
for i, ip := range iprecords {
if i != 0 {
ips = ips + ", "
}
ips = ips + ip.String()
}

return domain.Hostname(), ips
}

func verifySecurityHeaders(rawHeaders map[string]string) missingSecurityHeaders {
var missing missingSecurityHeaders

if _, ok := rawHeaders["Content-Security-Policy"]; !ok {
missing.ContentSecurityPolicy = true
}

if _, ok := rawHeaders["X-Frame-Options"]; !ok {
missing.XFrameOptions = true
}

if _, ok := rawHeaders["X-Content-Type-Options"]; !ok {
missing.XContentTypeOptions = true
}

if _, ok := rawHeaders["Referrer-Policy"]; !ok {
missing.ReferrerPolicy = true
}

if _, ok := rawHeaders["Permissions-Policy"]; !ok {
missing.PermissionsPolicy = true
}

return missing
}

func httpGet(url string) (map[string]string, missingSecurityHeaders, string) {
rawHeader := make(map[string]string)

res, err := http.Get(url)

Check failure

Code scanning / CodeQL

Uncontrolled data used in network request

The [URL](1) of this request depends on a [user-provided value](2).
if err != nil {
fmt.Println("HTTP: HTTP GET request error:", err)
return nil, missingSecurityHeaders{}, ""
}
defer res.Body.Close()

if res.StatusCode != 200 {
fmt.Println("HTTP: Unexpect response status:", res.Status)
}

for k, v := range res.Header {
rawHeader[k] = strings.Join(v, ", ")
}

missing := verifySecurityHeaders(rawHeader)

bodyBytes, err := io.ReadAll(res.Body)
if err != nil {
fmt.Println("HTTP: Read body error:", err)
}

return rawHeader, missing, string(bodyBytes)
}