diff --git a/README.md b/README.md
index 3204409c6..d273811e2 100644
--- a/README.md
+++ b/README.md
@@ -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: 📲
diff --git a/owasp-top10-2021-apps/a10/doryl-site-check/Makefile b/owasp-top10-2021-apps/a10/doryl-site-check/Makefile
new file mode 100644
index 000000000..f15ce2704
--- /dev/null
+++ b/owasp-top10-2021-apps/a10/doryl-site-check/Makefile
@@ -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"
diff --git a/owasp-top10-2021-apps/a10/doryl-site-check/README.md b/owasp-top10-2021-apps/a10/doryl-site-check/README.md
new file mode 100644
index 000000000..7dabfefb2
--- /dev/null
+++ b/owasp-top10-2021-apps/a10/doryl-site-check/README.md
@@ -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.
diff --git a/owasp-top10-2021-apps/a10/doryl-site-check/app/api/services.go b/owasp-top10-2021-apps/a10/doryl-site-check/app/api/services.go
new file mode 100644
index 000000000..3902ca87a
--- /dev/null
+++ b/owasp-top10-2021-apps/a10/doryl-site-check/app/api/services.go
@@ -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)
+ 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)
+}
diff --git a/owasp-top10-2021-apps/a10/doryl-site-check/app/corp-server/admin/employers.html b/owasp-top10-2021-apps/a10/doryl-site-check/app/corp-server/admin/employers.html
new file mode 100644
index 000000000..5c5c3a4d3
--- /dev/null
+++ b/owasp-top10-2021-apps/a10/doryl-site-check/app/corp-server/admin/employers.html
@@ -0,0 +1,398 @@
+
+
+
+
+
+
+ Employers Directory
+
+
+
+
+
+
+
+
+
diff --git a/owasp-top10-2021-apps/a10/doryl-site-check/app/corp-server/admin/logins.txt b/owasp-top10-2021-apps/a10/doryl-site-check/app/corp-server/admin/logins.txt
new file mode 100644
index 000000000..002e5156c
--- /dev/null
+++ b/owasp-top10-2021-apps/a10/doryl-site-check/app/corp-server/admin/logins.txt
@@ -0,0 +1,18 @@
+// Super sensitive information
+
+// WiFi
+id: Doryl
+password: 2022doryl@*
+
+// Guest WiFi
+id: Doryl-Guest
+password: dorylguest2022
+
+// Intranet
+login: admin
+password: Adminqwert2022
+
+// Ginpass
+login: dorylAdmin
+password: ginAndOrange
+
diff --git a/owasp-top10-2021-apps/a10/doryl-site-check/app/go.mod b/owasp-top10-2021-apps/a10/doryl-site-check/app/go.mod
new file mode 100644
index 000000000..c4bf035e1
--- /dev/null
+++ b/owasp-top10-2021-apps/a10/doryl-site-check/app/go.mod
@@ -0,0 +1,19 @@
+module github.com/fguisso/doryl-site-check
+
+go 1.17
+
+require github.com/labstack/echo v3.3.10+incompatible
+
+require (
+ github.com/dgrijalva/jwt-go v3.2.0+incompatible // indirect
+ github.com/labstack/gommon v0.3.1 // indirect
+ github.com/mattn/go-colorable v0.1.11 // indirect
+ github.com/mattn/go-isatty v0.0.14 // indirect
+ github.com/stretchr/testify v1.7.1 // indirect
+ github.com/valyala/bytebufferpool v1.0.0 // indirect
+ github.com/valyala/fasttemplate v1.2.1 // indirect
+ golang.org/x/crypto v0.0.0-20220321153916-2c7772ba3064 // indirect
+ golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2 // indirect
+ golang.org/x/sys v0.0.0-20211103235746-7861aae1554b // indirect
+ golang.org/x/text v0.3.6 // indirect
+)
diff --git a/owasp-top10-2021-apps/a10/doryl-site-check/app/go.sum b/owasp-top10-2021-apps/a10/doryl-site-check/app/go.sum
new file mode 100644
index 000000000..87ca0ef0f
--- /dev/null
+++ b/owasp-top10-2021-apps/a10/doryl-site-check/app/go.sum
@@ -0,0 +1,42 @@
+github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
+github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
+github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
+github.com/dgrijalva/jwt-go v3.2.0+incompatible h1:7qlOGliEKZXTDg6OTjfoBKDXWrumCAMpl/TFQ4/5kLM=
+github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ=
+github.com/labstack/echo v3.3.10+incompatible h1:pGRcYk231ExFAyoAjAfD85kQzRJCRI8bbnE7CX5OEgg=
+github.com/labstack/echo v3.3.10+incompatible/go.mod h1:0INS7j/VjnFxD4E2wkz67b8cVwCLbBmJyDaka6Cmk1s=
+github.com/labstack/gommon v0.3.1 h1:OomWaJXm7xR6L1HmEtGyQf26TEn7V6X88mktX9kee9o=
+github.com/labstack/gommon v0.3.1/go.mod h1:uW6kP17uPlLJsD3ijUYn3/M5bAxtlZhMI6m3MFxTMTM=
+github.com/mattn/go-colorable v0.1.11 h1:nQ+aFkoE2TMGc0b68U2OKSexC+eq46+XwZzWXHRmPYs=
+github.com/mattn/go-colorable v0.1.11/go.mod h1:u5H1YNBxpqRaxsYJYSkiCWKzEfiAb1Gb520KVy5xxl4=
+github.com/mattn/go-isatty v0.0.14 h1:yVuAays6BHfxijgZPzw+3Zlu5yQgKGP2/hcQbHb7S9Y=
+github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94=
+github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
+github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
+github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
+github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
+github.com/stretchr/testify v1.7.1 h1:5TQK59W5E3v0r2duFAb7P95B6hEeOyEnHRa8MjYSMTY=
+github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
+github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw=
+github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc=
+github.com/valyala/fasttemplate v1.2.1 h1:TVEnxayobAdVkhQfrfes2IzOB6o+z4roRkPF52WA1u4=
+github.com/valyala/fasttemplate v1.2.1/go.mod h1:KHLXt3tVN2HBp8eijSv/kGJopbvo7S+qRAEEKiv+SiQ=
+golang.org/x/crypto v0.0.0-20220321153916-2c7772ba3064 h1:S25/rfnfsMVgORT4/J61MJ7rdyseOZOyvLIrZEZ7s6s=
+golang.org/x/crypto v0.0.0-20220321153916-2c7772ba3064/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
+golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2 h1:CIJ76btIcR3eFI5EgSo6k1qKw9KJexJuRLI9G7Hp5wE=
+golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
+golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.0.0-20211103235746-7861aae1554b h1:1VkfZQv42XQlA/jchYumAnv1UPo6RgF9rJFkTgZIxO4=
+golang.org/x/sys v0.0.0-20211103235746-7861aae1554b/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
+golang.org/x/text v0.3.6 h1:aRYxNxv6iGQlyVaZmk6ZgYEDa+Jg18DxebPSrd6bg1M=
+golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
+golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
+gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
+gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
+gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b h1:h8qDotaEPuJATrMmW04NCwg7v22aHH28wwpauUhK9Oo=
+gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
diff --git a/owasp-top10-2021-apps/a10/doryl-site-check/app/main.go b/owasp-top10-2021-apps/a10/doryl-site-check/app/main.go
new file mode 100644
index 000000000..c858d88df
--- /dev/null
+++ b/owasp-top10-2021-apps/a10/doryl-site-check/app/main.go
@@ -0,0 +1,48 @@
+package main
+
+import (
+ "errors"
+ "html/template"
+ "io"
+ "os"
+
+ "github.com/fguisso/doryl-site-check/api"
+ "github.com/labstack/echo"
+ "github.com/labstack/echo/middleware"
+)
+
+// TemplateRegistry defines the template registry struct.
+type TemplateRegistry struct {
+ templates map[string]*template.Template
+}
+
+// Render implement e.Renderer interface.
+func (t *TemplateRegistry) Render(w io.Writer, name string, data interface{}, c echo.Context) error {
+ tmpl, ok := t.templates[name]
+ if !ok {
+ err := errors.New("This template is not found: " + name)
+ return err
+ }
+ return tmpl.ExecuteTemplate(w, "base.html", data)
+}
+
+func main() {
+ e := echo.New()
+ e.HideBanner = true
+
+ e.Use(middleware.Logger())
+ e.Use(middleware.Recover())
+ e.Use(middleware.RequestID())
+
+ templates := make(map[string]*template.Template)
+ templates["index.html"] = template.Must(template.ParseFiles("templates/home.html", "templates/base.html"))
+ templates["check.html"] = template.Must(template.ParseFiles("templates/check.html", "templates/base.html"))
+
+ e.Renderer = &TemplateRegistry{
+ templates: templates,
+ }
+ e.GET("/", api.Index)
+ e.POST("/check", api.SiteCheckPage)
+
+ e.Logger.Fatal(e.Start("0.0.0.0:" + os.Getenv("PORT")))
+}
diff --git a/owasp-top10-2021-apps/a10/doryl-site-check/app/templates/base.html b/owasp-top10-2021-apps/a10/doryl-site-check/app/templates/base.html
new file mode 100644
index 000000000..96db0b5ef
--- /dev/null
+++ b/owasp-top10-2021-apps/a10/doryl-site-check/app/templates/base.html
@@ -0,0 +1,88 @@
+{{define "base.html"}}
+
+
+
+
+
+
+ Doryl Site Check
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Check your website now!
+
+
+ No more headaches with security headers and another http information leaks, test your website now to be part of most security projects in the World Wide Web.
+
+
+
+
+
+
+
+ {{ template "body" .}}
+
+
+{{ end }}
diff --git a/owasp-top10-2021-apps/a10/doryl-site-check/app/templates/check.html b/owasp-top10-2021-apps/a10/doryl-site-check/app/templates/check.html
new file mode 100644
index 000000000..9a6df51c9
--- /dev/null
+++ b/owasp-top10-2021-apps/a10/doryl-site-check/app/templates/check.html
@@ -0,0 +1,132 @@
+{{ define "body" }}
+
+
+
+
+
+
+
+
+ Site
+ {{ index . "domain" }}
+
+
+ IP Address
+ {{ index . "ips" }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ if .secHeaders.ContentSecurityPolicy }}
+
+ Content-Security-Policy
+ Content Security Policy is an added layer of security that helps to detect and mitigate certain types of attacks, including Cross-Site Scripting (XSS) and data injection attacks.
+
+ {{ end }}
+
+ {{ if .secHeaders.XFrameOptions }}
+
+ X-Frame-Options
+ The X-Frame-Options The X-Frame-Options HTTP response header can be used to indicate whether or not a browser should be allowed to render a page in a frame , iframe , embed or object . Sites can use this to avoid click-jacking attacks, by ensuring that their content is not embedded into other sites.
+
+ {{ end }}
+
+ {{ if .secHeaders.XContentTypeOptions }}
+
+ X-Content-Type-Options
+ The X-Content-Type-Options response HTTP header is a marker used by the server to indicate that the MIME types advertised in the Content-Type headers should be followed and not be changed. The header allows you to avoid MIME type sniffing by saying that the MIME types are deliberately configured.
+
+ {{ end }}
+
+ {{ if .secHeaders.ReferrerPolicy }}
+
+ Referrer-Policy
+ The Referrer-Policy HTTP header controls how much referrer information (sent with the Referer header) should be included with requests. Aside from the HTTP header, you can set this policy in HTML.
+
+ {{ end }}
+
+ {{ if .secHeaders.PermissionsPolicy }}
+
+ Permissions-Policy
+ Permissions-Policy is a new header that allows a site to control which features and APIs can be used in the browser.
+
+ {{ end }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ range $key, $value := .headers }}
+
+ {{ $key }}
+ {{ $value}}
+
+ {{ end }}
+
+
+
+
+
+
+
+
+
+
+
+GET {{ .target }}
+{{ range $key, $value := .headers }}{{ $key }}: {{ $value }} {{ end }}
+{{ .body }}
+
+
+
+
+
+
+
+{{ end }}
diff --git a/owasp-top10-2021-apps/a10/doryl-site-check/app/templates/home.html b/owasp-top10-2021-apps/a10/doryl-site-check/app/templates/home.html
new file mode 100644
index 000000000..48fea2d83
--- /dev/null
+++ b/owasp-top10-2021-apps/a10/doryl-site-check/app/templates/home.html
@@ -0,0 +1,3 @@
+{{ define "body" }}
+
+{{ end }}
diff --git a/owasp-top10-2021-apps/a10/doryl-site-check/deployments/check-init.sh b/owasp-top10-2021-apps/a10/doryl-site-check/deployments/check-init.sh
new file mode 100755
index 000000000..8070d0f35
--- /dev/null
+++ b/owasp-top10-2021-apps/a10/doryl-site-check/deployments/check-init.sh
@@ -0,0 +1,72 @@
+#!/bin/bash
+#
+# This script verifies if SecDevLabs app has properly start-up.
+#
+
+COLOR_RED='\033[31m'
+COLOR_YELLOW='\033[33m'
+COLOR_GREEN='\033[32m'
+COLOR_BLUE='\033[1;34m'
+COLOR_RESET='\033[0m'
+
+PROJECT='A10 - Doryl Site Check'
+PORT=10010
+TRIES=480
+LOADING=0
+
+printf "${COLOR_YELLOW}SecDevLabs: 👀 Your app is starting!\n${COLOR_RESET}"
+
+while : ; do
+ `curl -s -f http://localhost:$PORT > /dev/null`
+ if [ $? == 0 ] ; then
+ break
+ fi
+ if [ $TRIES == 0 ] ; then
+ break
+ fi
+ TRIES=$((TRIES-1))
+ sleep 0.25
+
+ # Loading animation
+ if [ $LOADING == 14 ]; then
+ LOADING=0
+ fi
+ if [ $LOADING == 0 ]; then
+ printf "\r${COLOR_YELLOW}SecDevLabs: 👀 Your app is still starting... (*-------) ${COLOR_RESET}"
+ elif [ $LOADING == 1 ]; then
+ printf "\r${COLOR_YELLOW}SecDevLabs: 👀 Your app is still starting... (-*------) ${COLOR_RESET}"
+ elif [ $LOADING == 2 ]; then
+ printf "\r${COLOR_YELLOW}SecDevLabs: 👀 Your app is still starting... (--*-----) ${COLOR_RESET}"
+ elif [ $LOADING == 3 ]; then
+ printf "\r${COLOR_YELLOW}SecDevLabs: 👀 Your app is still starting... (---*----) ${COLOR_RESET}"
+ elif [ $LOADING == 4 ]; then
+ printf "\r${COLOR_YELLOW}SecDevLabs: 👀 Your app is still starting... (----*---) ${COLOR_RESET}"
+ elif [ $LOADING == 5 ]; then
+ printf "\r${COLOR_YELLOW}SecDevLabs: 👀 Your app is still starting... (-----*--) ${COLOR_RESET}"
+ elif [ $LOADING == 6 ]; then
+ printf "\r${COLOR_YELLOW}SecDevLabs: 👀 Your app is still starting... (------*-) ${COLOR_RESET}"
+ elif [ $LOADING == 7 ]; then
+ printf "\r${COLOR_YELLOW}SecDevLabs: 👀 Your app is still starting... (-------*) ${COLOR_RESET}"
+ elif [ $LOADING == 8 ]; then
+ printf "\r${COLOR_YELLOW}SecDevLabs: 👀 Your app is still starting... (------*-) ${COLOR_RESET}"
+ elif [ $LOADING == 9 ]; then
+ printf "\r${COLOR_YELLOW}SecDevLabs: 👀 Your app is still starting... (-----*--) ${COLOR_RESET}"
+ elif [ $LOADING == 10 ]; then
+ printf "\r${COLOR_YELLOW}SecDevLabs: 👀 Your app is still starting... (----*---) ${COLOR_RESET}"
+ elif [ $LOADING == 11 ]; then
+ printf "\r${COLOR_YELLOW}SecDevLabs: 👀 Your app is still starting... (---*----) ${COLOR_RESET}"
+ elif [ $LOADING == 12 ]; then
+ printf "\r${COLOR_YELLOW}SecDevLabs: 👀 Your app is still starting... (--*-----) ${COLOR_RESET}"
+ elif [ $LOADING == 13 ]; then
+ printf "\r${COLOR_YELLOW}SecDevLabs: 👀 Your app is still starting... (-*------) ${COLOR_RESET}"
+ fi
+ LOADING=$((LOADING+1))
+ # End of loading animation
+
+done
+
+if [ $TRIES == 0 ]; then
+ printf "\n${COLOR_RED}SecDevLabs: Ooops! Something went wrong, please check api details for more information!\n${COLOR_RESET}"
+else
+ printf "\n${COLOR_GREEN}SecDevLabs: 🔥 ${PROJECT} is now running at ${COLOR_RESET}${COLOR_BLUE}http://localhost:$PORT${COLOR_RESET}\n"
+fi
diff --git a/owasp-top10-2021-apps/a10/doryl-site-check/deployments/corp-server.Dockerfile b/owasp-top10-2021-apps/a10/doryl-site-check/deployments/corp-server.Dockerfile
new file mode 100644
index 000000000..9d1872bd3
--- /dev/null
+++ b/owasp-top10-2021-apps/a10/doryl-site-check/deployments/corp-server.Dockerfile
@@ -0,0 +1,7 @@
+FROM python:3
+
+WORKDIR /www/
+
+COPY app/corp-server/ /www/
+
+CMD python3 -m http.server 8080
diff --git a/owasp-top10-2021-apps/a10/doryl-site-check/deployments/docker-compose.yml b/owasp-top10-2021-apps/a10/doryl-site-check/deployments/docker-compose.yml
new file mode 100644
index 000000000..727e76519
--- /dev/null
+++ b/owasp-top10-2021-apps/a10/doryl-site-check/deployments/docker-compose.yml
@@ -0,0 +1,25 @@
+version: '3'
+
+networks:
+ doryl_corp_net:
+
+services:
+ doryl:
+ container_name: doryl-site-check
+ build:
+ context: ../
+ dockerfile: deployments/doryl.Dockerfile
+ environment:
+ PORT: "10010"
+ ports:
+ - "10010:10010"
+ networks:
+ - doryl_corp_net
+
+ corp_server:
+ container_name: corp-server
+ build:
+ context: ../
+ dockerfile: deployments/corp-server.Dockerfile
+ networks:
+ - doryl_corp_net
diff --git a/owasp-top10-2021-apps/a10/doryl-site-check/deployments/doryl.Dockerfile b/owasp-top10-2021-apps/a10/doryl-site-check/deployments/doryl.Dockerfile
new file mode 100644
index 000000000..c5615291d
--- /dev/null
+++ b/owasp-top10-2021-apps/a10/doryl-site-check/deployments/doryl.Dockerfile
@@ -0,0 +1,10 @@
+FROM golang:1.17.7-alpine AS build
+
+WORKDIR /doryl-site-check
+
+COPY app/ .
+RUN go mod download
+
+RUN go build -o /doryld
+
+ENTRYPOINT ["/doryld"]
diff --git a/owasp-top10-2021-apps/a10/doryl-site-check/images/doryl-site-check.png b/owasp-top10-2021-apps/a10/doryl-site-check/images/doryl-site-check.png
new file mode 100644
index 000000000..fa8965df4
Binary files /dev/null and b/owasp-top10-2021-apps/a10/doryl-site-check/images/doryl-site-check.png differ