We launched new forums in March 2019—join us there. In a hurry for help with your website? Get Help Now!
    • 13226
    • 953 Posts
    Hi MODx Users

    I am a fan of eForm and have been using it for quite some time.

    Recently one of my sites was hacked and sadly I cant find out exactly where the entrance was.

    So the following steps were taken:

    STEP 1:
    To pin point the entrance the hackers took, I changed various elements within the site that were possible greyzones and uploaded the site. My changes were sadly not the right ones, as the site was re-hacked within 2 hours of deleteing the server and uploading all the new info.

    STEP 2:
    After speaking to my Hosting Company they kindly carried out an XSS vulnerability test on all of the forms that are in my site - "disaster" the reports came back with massive XSS vulnerabilities within all of the forms.

    STEP 3:
    This step has proven to be the best as of today - the server was completely deleted, all modified files were re-uploaded, and all of the forms have been removed - the site has now been online for 2 days without it going down and there have been no apparant hacks made.

    My dilema is now - no forms.

    I wrote to Ryan directly - which again I would like to apologise for (not the fine English art)

    He kindly replied to my problem and a part of his answer was: "It would seem that it is the way they’re escaping (or not) the inputs"

    Sadly im not a php’er and have very limited knowledge of what I can do to improve the forms validation and security.

    If anyone out there could possibly help in this matter or share a thought or two - then I would be very grateful for any help.

    Kind Regards

    p.s System 0.9.6.3 using eForm 1.4.4

      • 25663 MODX Staff
      • 12,272 Posts
      One thing I forgot to ask was if your host has register_globals set to on. Please say, "No!".
        Ryan Thrash, MODX Co-Founder
        Follow me on Twitter at @rthrash or catch my occasional unofficial thoughts at thrash.me
        • 22851
        • 805 Posts
        As I understand it (and I may be wrong) eForm itself wont do any modification of form data to protect you against XSS attacks. It does provide mechanisms by which you can do so however: Validation of form data before it is submitted including filtering, and modification of form data after it has been submitted but before anything has been done with it. Setting that up is the responsibility of the user.

        Information about validation and word filtering is here: assets/snippets/eform/docs/eform.htm

        An example which shows how to set up an event where you can modify form data before anything is done with it is here: assets/snippets/eform/docs/eform_example_events.htm
        The example adds a job number to the form - but you could equally well use the same approach to validate/escape/clean the data to protect yourself from XSS.

        Hope that helps.
          YAMS: Yet Another Multilingual Solution for MODx
          YAMS Forums | Latest: YAMS 1.1.9 | YAMS Documentation
          Please consider donating if you appreciate the time and effort spent developing and supporting YAMS.
          • 22851
          • 805 Posts
          I reread your initial post and figured that my post might not be that helpful if you don’t know much about PHP.

          If you don’t need to be able to allow people to post html, then a good starting point would be to strip all html and php tags from the submitted form input (like name, description, etc.) You can do this with the PHP strip_tags function. One way of implementing this on its own would be with the following filter:
          #FILTER #EVAL return strip_tags($value);
          


          Another good thing to do would be to apply the php htmlspecialchars function to any form data that will be re-displayed as output (ie; on the thankyou page). This will provide another layer of protection from embedded code.

          You could do both the strip_tags and htmlspecialchars on using the &eFormOnBeforeMailSent event as described on assets/snippets/eform/docs/eform_example_events.htm. The function that you use would need to look something like
          if ( ! function_exists( 'eFormHelpPreventXSS' ) )
          {
          
              function eFormHelpPreventXSS( &$fields )
              {
                global $modx;
                foreach( $fields as $name => $value )
                {
                  switch ( $name )
                  {
                  case 'email':
                  case 'vericode':
                    // Just strip tags. No need to escape.
                    $fields[ $name ] = strip_tags( $value );
                    break;
                  default:
                    $fields[ $name ] = htmlspecialchars( strip_tags( $value ), ENT_QUOTES, $modx->config['etomite_charset'] );
                  }
                }
                return true;
              }
              
          }
          


          Warning: The code is completely untested.

          There must be other eForm users/experts who are protecting themselves against XSS. Perhaps they could comment/share how they go about it?

          EDIT: Just updated the code. It was... the syntax was broken before.
            YAMS: Yet Another Multilingual Solution for MODx
            YAMS Forums | Latest: YAMS 1.1.9 | YAMS Documentation
            Please consider donating if you appreciate the time and effort spent developing and supporting YAMS.
            • 13226
            • 953 Posts
            @Ryan - Yep, the dreaded globals is set to "Off"

            @PMS - Thanks for replying to this post

            It would be great to find somewhat more comprehensive tutorials for eForm.

            As a non php’er its hard to realy understand what is meant with some of the technical specs found in the docs.

            Reading the doc that PMS suggested I have understood to a point how to validate the form(s) before it actually can do any damage. The Badwords, GoodWords etc. jogged my memory - in Jot it can be called directly in the snippet call.

            An example call for Jot:
            [!Jot? &customfields=`name,email` &badwords=`{{Badwords}}` &bw=`2` &debug=`0` &validate=`name,email` &sortby=`createdon:d` &placeholders=`1` &output=`0` &pagination=`5` &captcha=`2`!]
            


            In the code above you can see " &badwords=`{{Badwords}}` " which calls a chunk of words seperated with a comma.

            An example eForm call (at least how I interpret the call):

            [!eForm? &formid=`Test Form` &to=`{{my_mailaddress_chunk}}` &tpl=`testform` &report=`testform_report` &mailselector=`department` &vericode=`1` &sendAsHtml=`0` &allowhtml=`0` &subject=`[+subject+]`!]
            


            In the call there is &amp;allowhtml=`0` which I understand as: When eForm validates the form and finds HTML characters such as <a href, <script etc.. the form is not sent and shows an error message. So if someone is testing a form for XSS vulnerability by using HTML they wont get far.

            The example form would/could be:

            <?php ?>
            <div id="mydiv"> [+validationmessage+]
              <p>All Fields Are Required!</p>
              <form method="post" action="[~[*id*]~]">
                <input type="hidden" name="formid" value="Test Form" />
                <input type="hidden" name="sent_on" id="sent_on" value="<?php echo $modx->runSnippet("DateTime"); ?>" eform="Sent On:string:0"/>
                <fieldset>
                <div>
                  <label for="name">Name:</label>
                  <input type="text" name="name" id="name" eform="Name:string:1:#FILTER #EVAL return myFunction($functionname);"/>
                </div>
                <div>
                  <label for="email">Email:</label>
                  <input type="text" name="email" id="email" eform="Email:string:1:#FILTER #EVAL return myFunction($functionname);"/>
                </div>
                <div>
                  <label for="subject">Subject:</label>
                  <input type="text" name="subject" id="subject" eform="Email:string:1:#FILTER #EVAL return myFunction($functionname);"/>
                </div>
                <div>
                  <label for="message">Message:</label>
                  <textarea name="message" cols="25" rows="6" id="message" eform="Message:string:1:#FILTER #EVAL return myFunction($functionname);"></textarea>
                </div>
                <div><img src="[+verimageurl+]" alt="vericode" /> <input name="vericode" type="text" size="10" /> Enter here</div>
                <div>
                  <input class="button" name="submit" type="submit" value="Submit" />
                </div>
                </fieldset>
              </form>
            </div>
            <?php ?>
            


            Is it possible to call the Badwords function directly in the snippet call in eForm instead of having to add " #FILTER #EVAL return myFunction($functionname); " in each and every input element (as shown above).
              • 13226
              • 953 Posts
              Looking further into XSS I have found this site: http://ha.ckers.org/xss.html

              Is it at all possible to create a function in eForm that can test for the attacks that this site shows or test from a file that lists all known forms of attacks, before the form is processed ??

              I also found the following:

              FireFox Add-on: XSS Me - https://addons.mozilla.org/en-US/firefox/addon/7598

              XSS Me Developers site: http://labs.securitycompass.com/index.php/exploit-me/

              This Add-on is part of SecCom Labs Exploit-Me suite, other tools are: SQL Inject-Me & Access-Me

              From the author:
              Exploit-Me is a suite of Firefox web application security testing tools designed to be lightweight and easy to use.
                • 22851
                • 805 Posts
                iusemodx.

                I just went through the tedious task of testing my contact form against every XSS script apart from one at http://ha.ckers.org/xss.html for one particular setup, using the &eFormOnBeforeMailSent=`eFormHelpPreventXSS` and the function I posted above. The setup was Firefox 3.5.1, HTML 1.0 Strict, page served as application/xhtml+xml; charset=UTF-8. The test I skipped was the following (I wasn’t sure quite what to do with it):

                Event Handlers that can be used in similar XSS attacks to the one above (this is the most comprehensive list on the net, at the time of this writing)....

                The script passed all tests with flying colours. Of course, the test is not comprehensive, since it doesn’t test every single browser and browser version, and may not work if the output is placed within a <script ..> block or sent to flash etc... but it is at least a good starting point for protecting against XSS. The function posted above allows the data to be emailed/displayed even if PHP/HTML/XML had to be removed from it. The following modified function is even stricter since it will output nothing if it detects and attempt to inject html/php/etc:

                <?php
                if ( ! function_exists( 'eFormHelpPreventXSS' ) )
                {
                
                    function eFormHelpPreventXSS( &$fields )
                    {
                      global $modx;
                      $success = TRUE;
                      foreach( $fields as $name => $value )
                      {
                        $stripped = strip_tags( $value );
                        // If there was embedded PHP/HTML/XML etc. then not successful
                        // However, proceed to clean all the fields anyway.
                        if ( $stripped != $value )
                        {
                          $success = FALSE;
                        }
                        switch ( $name )
                        {
                        case 'email':
                        case 'vericode':
                          // Just strip tags. No need to escape.
                          $fields[ $name ] = $stripped;
                          break;
                        default:          
                          $fields[ $name ] = htmlspecialchars( $stripped, ENT_QUOTES, $modx->config['modx_charset'] );
                        }
                      }
                      return $success;
                    }
                    
                }
                ?>
                


                EDIT: Just removed the final param from the htmlspecialchars function for backwards compatibility with older versions of PHP.
                  YAMS: Yet Another Multilingual Solution for MODx
                  YAMS Forums | Latest: YAMS 1.1.9 | YAMS Documentation
                  Please consider donating if you appreciate the time and effort spent developing and supporting YAMS.
                  • 25663 MODX Staff
                  • 12,272 Posts
                  PMS, I updated your code to reference the modx_charset variable. It’s likely that the backwards compatibility is going to be deprecated now that we’re 5 years into it. wink
                    Ryan Thrash, MODX Co-Founder
                    Follow me on Twitter at @rthrash or catch my occasional unofficial thoughts at thrash.me
                    • 22851
                    • 805 Posts
                    Thanks for pointing that out Ryan. I must have picked it up from some old documentation when I first started using MODx and have been using it ever since. I’ll need to make the update to the snippets/plugins/modules/etc. that I have written too.
                      YAMS: Yet Another Multilingual Solution for MODx
                      YAMS Forums | Latest: YAMS 1.1.9 | YAMS Documentation
                      Please consider donating if you appreciate the time and effort spent developing and supporting YAMS.
                      • 13226
                      • 953 Posts
                      @PMS

                      Thanks for your time and help smiley

                      If you have the time, would it be possible to go through your work step for step (idiots guide grin ) e.g

                      Step 1: Create Form (please add an example as an attachment if possible)
                      Step 2: Call eForm in page or template (please create a call string)
                      Step 3: Create function(s) (where are the functions stored and where are they called)

                      This will possibly/probably help many other user’s - following a step for step guide is pretty much fool proof smiley

                      Thanks in advance