1. Getting Started
      1. Video Quick-Start Series
      2. Server Requirements
        1. MySQL 5.0.51 Issues
      3. Installation
        1. Basic Installation
          1. MODx Revolution on Debian
          2. Problems with WAMPServer 2.0i
          3. Lighttpd Guide
          4. Installation on a server running ModSecurity
          5. MODX and Suhosin
          6. Nginx Server Config
        2. Successful Installation, Now What Do I Do?
        3. Successful Installation, Now What Do I Do?
        4. Advanced Installation
        5. Git Installation
        6. Command Line Installation
          1. The Setup Config Xml File
        7. Troubleshooting Installation
        8. Using MODx Revolution from SVN
      4. An Overview of MODX
        1. Glossary of Revolution Terms
          1. Explanation of Directory Structure
        2. Roadmap
        3. MODX Revolution Framework Structure Ideology
        4. What's New in 2.3
    2. FAQs & Troubleshooting
      1. CMP Development FAQs & Troubleshooting
    3. Making Sites with MODx
      1. Structuring Your Site
        1. Resources
          1. Content Types
          2. Named Anchor
          3. Static Resource
          4. Symlink
            1. Using Resource Symlinks
          5. Weblink
        2. Templates
        3. Chunks
        4. Using Snippets
      2. Tag Syntax
      3. Customizing Content
        1. Template Variables
          1. Creating a Template Variable
          2. Adding a Custom TV Type - MODX 2.2
          3. Bindings
            1. CHUNK Binding
            2. DIRECTORY Binding
            3. EVAL Binding
            4. FILE Binding
            5. INHERIT Binding
            6. RESOURCE Binding
            7. SELECT Binding
          4. Template Variable Input Types
          5. Template Variable Output Types
            1. Date TV Output Type
            2. Delimiter TV Output Type
            3. HTML Tag TV Output Type
            4. Image TV Output Type
            5. URL TV Output Type
          6. Adding a Custom TV Input Type
          7. Adding a Custom TV Output Type
          8. Creating a multi-select box for related pages in your template
          9. Accessing Template Variable Values via the API
        2. Properties and Property Sets
        3. Input and Output Filters (Output Modifiers)
          1. Custom Output Filter Examples
      4. Commonly Used Template Tags
        1. Date Formats
    4. Administering Your Site
      1. Settings
        1. System Settings
          1. access_category_enabled
          2. date_timezone
          3. access_context_enabled
          4. access_resource_group_enabled
          5. allow_duplicate_alias
          6. allow_forward_across_contexts
          7. allow_multiple_emails
          8. allow_tags_in_post
          9. archive_with
          10. automatic_alias
          11. auto_check_pkg_updates
          12. auto_check_pkg_updates_cache_expire
          13. auto_menuindex
          14. base_help_url
          15. blocked_minutes
          16. cache_action_map
          17. cache_context_settings
          18. cache_db
          19. cache_db_expires
          20. cache_db_session
          21. cache_default
          22. cache_disabled
          23. cache_format
          24. cache_handler
          25. cache_json
          26. cache_json_expires
          27. cache_lang_js
          28. cache_lexicon_topics
          29. cache_noncore_lexicon_topics
          30. cache_resource
          31. cache_resource_expires
          32. cache_scripts
          33. cache_system_settings
          34. clear_cache_refresh_trees
          35. compress_css
          36. compress_js
          37. concat_js
          38. container_suffix
          39. cultureKey
          40. custom_resource_classes
          41. default_per_page
          42. default_template
          43. editor_css_path
          44. editor_css_selectors
          45. emailsender
          46. emailsubject
          47. enable_dragdrop
          48. error_page
          49. extension_packages
          50. failed_login_attempts
          51. feed_modx_news
          52. feed_modx_news_enabled
          53. feed_modx_security
          54. feed_modx_security_enabled
          55. fe_editor_lang
          56. filemanager_path
          57. filemanager_path_relative
          58. filemanager_url
          59. filemanager_url_relative
          60. forgot_login_email
          61. friendly_alias_lowercase_only
          62. forward_merge_excludes
          63. friendly_alias_max_length
          64. friendly_alias_restrict_chars
          65. friendly_alias_restrict_chars_pattern
          66. friendly_alias_strip_element_tags
          67. friendly_alias_translit
          68. friendly_alias_translit_class
          69. friendly_alias_translit_class_path
          70. friendly_alias_trim_chars
          71. friendly_alias_urls
          72. friendly_alias_word_delimiter
          73. friendly_alias_word_delimiters
          74. friendly_urls
          75. friendly_url_prefix
          76. friendly_url_suffix
          77. global_duplicate_uri_check
          78. hidemenu_default
          79. link_tag_scheme
          80. mail_charset
          81. mail_encoding
          82. mail_smtp_auth
          83. mail_smtp_helo
          84. mail_smtp_hosts
          85. mail_smtp_keepalive
          86. mail_smtp_pass
          87. mail_smtp_port
          88. mail_smtp_prefix
          89. mail_smtp_single_to
          90. mail_smtp_timeout
          91. mail_smtp_user
          92. mail_use_smtp
          93. manager_date_format
          94. manager_direction
          95. manager_favicon_url
          96. manager_language
          97. manager_lang_attribute
          98. manager_theme
          99. manager_time_format
          100. context_tree_sort
          101. context_tree_sortby
          102. context_tree_sortdir
          103. session_enabled
          104. modx_charset
          105. new_file_permissions
          106. new_folder_permissions
          107. password_generated_length
          108. password_min_length
          109. phpthumb_allow_src_above_docroot
          110. phpthumb_cache_maxage
          111. phpthumb_cache_maxfiles
          112. phpthumb_cache_maxsize
          113. phpthumb_cache_source_enabled
          114. phpthumb_document_root
          115. phpthumb_error_bgcolor
          116. phpthumb_error_fontsize
          117. phpthumb_error_textcolor
          118. phpthumb_far
          119. phpthumb_imagemagick_path
          120. phpthumb_nohotlink_enabled
          121. phpthumb_nohotlink_erase_image
          122. phpthumb_nohotlink_text_message
          123. phpthumb_nohotlink_valid_domains
          124. phpthumb_nooffsitelink_enabled
          125. phpthumb_nooffsitelink_erase_image
          126. phpthumb_nooffsitelink_require_refer
          127. phpthumb_nooffsitelink_text_message
          128. phpthumb_nooffsitelink_valid_domains
          129. phpthumb_nooffsitelink_watermark_src
          130. phpthumb_zoomcrop
          131. principal_targets
          132. proxy_auth_type
          133. proxy_host
          134. proxy_password
          135. proxy_port
          136. proxy_username
          137. publish_default
          138. rb_base_dir
          139. rb_base_url
          140. request_controller
          141. request_param_alias
          142. request_param_id
          143. resource_tree_node_name
          144. resource_tree_node_tooltip
          145. richtext_default
          146. search_default
          147. server_offset_time
          148. server_protocol
          149. session_cookie_domain
          150. session_cookie_lifetime
          151. session_cookie_path
          152. session_cookie_secure
          153. session_handler_class
          154. session_name
          155. settings_version
          156. signupemail_message
          157. site_name
          158. site_start
          159. site_status
          160. site_unavailable_message
          161. site_unavailable_page
          162. strip_image_paths
          163. symlink_merge_fields
          164. tree_default_sort
          165. tree_root_id
          166. tvs_below_content
          167. udperms_allowroot
          168. ui_debug_mode
          169. unauthorized_page
          170. upload_maxsize
          171. use_alias_path
          172. use_browser
          173. use_editor
          174. use_multibyte
          175. welcome_screen
          176. which_editor
          177. which_element_editor
          178. xhtml_urls
      2. Using Friendly URLs
      3. Contexts
        1. Creating a Subdomain from a Folder using Virtual Hosts
        2. Using One Gateway Plugin to Manage Multiple Domains
      4. Customizing the Manager
        1. Customizing the Manager via Plugins
        2. Form Customization Profiles
        3. Form Customization Sets
          1. Customizing Tabs via Form Customization
          2. MODX GitHub Contributor's Guide
        4. Manager Templates and Themes
      5. MODX GitHub Integrator's Guide
      6. Security
        1. Hardening MODX Revolution
        2. Policies
          1. ACLs
          2. Permissions
            1. Permissions - Administrator Policy
            2. Permissions - Resource Policy
          3. PolicyTemplates
        3. Resource Groups
        4. Roles
        5. Security Standards
        6. Security Tutorials
          1. More on the Anonymous User Group
          2. Creating a Second Super Admin User
          3. Giving a User Manager Access
          4. Making Member-Only Pages
          5. Restricting an Element from Users
        7. Troubleshooting Security
          1. Resetting a User Password Manually
        8. User Groups
        9. Users
      7. Installing a Package
        1. Troubleshooting Package Management
      8. Upgrading MODX
        1. Upgrading to Revolution 2.0.5
        2. Upgrading from 2.0.x to 2.1.x
        3. Upgrading from Versions Earlier than 2.0.5
        4. Upgrading to 2.2.x
        5. Upgrading to Revolution 2.0.0-rc-2
        6. Troubleshooting Upgrades
        7. Upgrading from MODx Evolution
          1. Functional Changes from Evolution
      9. Moving Your Site to a New Server, or to Root from Subfolder
      10. Media Sources
        1. Adding a Media Source
        2. Assigning Media Sources to TVs
        3. Media Source Types
          1. Media Source Type - File System
          2. Media Source Type - S3
        4. Securing a Media Source
          1. Creating a Media Source for Clients Tutorial
      11. Dashboards
        1. Assigning a Dashboard to a User Group
        2. Creating a Dashboard Widget
        3. Dashboard Widget Types
          1. Dashboard Widget Type - File
          2. Dashboard Widget Type - HTML
          3. Dashboard Widget Type - Inline PHP
          4. Dashboard Widget Type - Snippet
        4. Managing Your Dashboard
    5. Developing in MODx
      1. Code Standards
      2. Overview of MODx Development
        1. Developer Introduction
          1. Getting Started Developing
        2. Extras Directories
        3. Setting up a Development Environment
      3. Basic Development
        1. Plugins
          1. System Events
            1. OnMODXInit
            2. OnBeforeCacheUpdate
            3. OnBeforeChunkFormDelete
            4. OnBeforeChunkFormSave
            5. OnBeforeDocFormDelete
            6. OnBeforeDocFormSave
            7. OnBeforeEmptyTrash
            8. OnBeforeManagerLogin
            9. OnBeforeManagerLogout
            10. OnBeforeManagerPageInit
            11. OnBeforePluginFormDelete
            12. OnBeforePluginFormSave
            13. OnBeforeSaveWebPageCache
            14. OnBeforeSnipFormDelete
            15. OnBeforeSnipFormSave
            16. OnBeforeTempFormDelete
            17. OnBeforeTempFormSave
            18. OnBeforeTVFormDelete
            19. OnBeforeTVFormSave
            20. OnBeforeUserActivate
            21. OnBeforeUserFormDelete
            22. OnBeforeUserFormSave
            23. OnBeforeWebLogin
            24. OnBeforeWebLogout
            25. OnCacheUpdate
            26. OnCategoryBeforeRemove
            27. OnCategoryBeforeSave
            28. OnCategoryRemove
            29. OnCategorySave
            30. OnChunkBeforeRemove
            31. OnChunkBeforeSave
            32. OnChunkFormDelete
            33. OnChunkFormPrerender
            34. OnChunkFormRender
            35. OnChunkFormSave
            36. OnChunkRemove
            37. OnChunkSave
            38. OnContextBeforeRemove
            39. OnContextBeforeSave
            40. OnContextFormPrerender
            41. OnContextFormRender
            42. OnContextRemove
            43. OnContextSave
            44. OnDocFormDelete
            45. OnDocFormPrerender
            46. OnDocFormRender
            47. OnDocFormSave
            48. OnDocPublished
            49. OnDocUnPublished
            50. OnEmptyTrash
            51. OnFileManagerUpload
            52. OnHandleRequest
            53. OnInitCulture
            54. OnLoadWebDocument
            55. OnLoadWebPageCache
            56. OnManagerAuthentication
            57. OnManagerLogin
            58. OnManagerLoginFormPrerender
            59. OnManagerLoginFormRender
            60. OnManagerLogout
            61. OnManagerPageAfterRender
            62. OnManagerPageBeforeRender
            63. OnManagerPageInit
            64. OnPageNotFound
            65. OnPageUnauthorized
            66. OnParseDocument
            67. OnPluginBeforeRemove
            68. OnPluginBeforeSave
            69. OnPluginEventRemove
            70. OnPluginFormDelete
            71. OnPluginFormPrerender
            72. OnPluginFormRender
            73. OnPluginFormSave
            74. OnPluginRemove
            75. OnPluginSave
            76. OnPropertySetBeforeRemove
            77. OnPropertySetBeforeSave
            78. OnPropertySetRemove
            79. OnPropertySetSave
            80. OnResourceGroupBeforeRemove
            81. OnResourceGroupBeforeSave
            82. OnResourceGroupRemove
            83. OnResourceGroupSave
            84. OnRichTextBrowserInit
            85. OnRichTextEditorInit
            86. OnRichTextEditorRegister
            87. OnSiteRefresh
            88. OnSiteSettingsRender
            89. OnTemplateVarBeforeRemove
            90. OnTemplateVarBeforeSave
            91. OnTemplateVarRemove
            92. OnTemplateVarSave
            93. OnUserActivate
            94. OnUserBeforeRemove
            95. OnUserBeforeSave
            96. OnUserChangePassword
            97. OnUserFormDelete
            98. OnUserFormSave
            99. OnUserNotFound
            100. OnUserRemove
            101. OnUserSave
            102. OnWebAuthentication
            103. OnWebLogin
            104. OnWebLogout
            105. OnWebPageComplete
            106. OnWebPageInit
            107. OnWebPagePrerender
        2. Snippets
          1. Adding CSS and JS to Your Pages Through Snippets
          2. How to Write a Good Chunk
          3. How to Write a Good Snippet
          4. Templating Your Snippets
        3. xPDO
      4. Advanced Development
        1. Caching
          1. Setting up Memcache in MODX
        2. Custom Manager Pages
          1. Custom Manager Pages in 2.3
          2. Actions and Menus
            1. Action List
          3. Custom Manager Pages Tutorial
          4. MODExt
            1. MODx.combo.ComboBox
            2. MODx.Console
            3. MODx.FormPanel
            4. MODx.grid.Grid
            5. MODx.grid.LocalGrid
            6. MODx.msg
            7. MODx.tree.Tree
            8. MODx.Window
            9. MODExt Tutorials
              1. 1. Ext JS Tutorial - Message Boxes
              2. 2. Ext JS Tutorial - Ajax Include
              3. 3. Ext JS Tutorial - Animation
              4. 4. Ext JS Tutorial - Manipulating Nodes
              5. 5. Ext JS Tutorial - Panels
              6. 7. Ext JS Tutoral - Advanced Grid
              7. 8. Ext JS Tutorial - Inside a CMP
            10. MODExt MODx Object
        3. Custom Resource Classes
          1. Creating a Resource Class
            1. Creating a Resource Class - Step 2
            2. Creating a Resource Class - Step 3
            3. Creating a Resource Class - Step 4
        4. Extending modUser
        5. From the Command Line (CLI)
        6. Internationalization
          1. Adding a Translation
        7. MODx Services
          1. modFileHandler
          2. modMail
          3. modRegistry
        8. Namespaces
        9. Package Management
          1. Creating a 3rd Party Component Build Script
          2. Providers
          3. Transport Packages
        10. Using runProcessor
        11. Validating Requests: Tokens and Nonces
        12. Developing RESTful APIs
      5. Other Development Resources
        1. Summary of Legacy Code Removed in 2.1
        2. API Reference
        3. Class Reference
          1. modResource
            1. modResource.isMember
          2. modChunk
            1. modChunk.getContent
            2. modChunk.setContent
          3. modUser
            1. modUser.addSessionContext
            2. modUser.changePassword
            3. modUser.endSession
            4. modUser.getSessionContexts
            5. modUser.getSettings
            6. modUser.hasSessionContext
            7. modUser.isAuthenticated
            8. modUser.isMember
            9. modUser.loadAttributes
            10. modUser.removeSessionContext
            11. modUser.removeSessionContextVars
            12. modUser.removeSessionCookie
          4. modX
            1. modX.addEventListener
            2. modX.checkForLocks
            3. modX.checkSession
            4. modX.executeProcessor
            5. modX.getAuthenticatedUser
            6. modX.getCacheManager
            7. modX.getChildIds
            8. modX.getChunk
            9. modX.getConfig
            10. modX.getContext
            11. modX.getEventMap
            12. modX.getLoginUserID
            13. modX.getLoginUserName
            14. modX.getParentIds
            15. modX.getParser
            16. modX.getPlaceholder
            17. modX.getRegisteredClientScripts
            18. modX.getRegisteredClientStartupScripts
            19. modX.getRequest
            20. modX.getResponse
            21. modX.getService
            22. modX.getSessionState
            23. modX.getTree
            24. modX.getUser
            25. modX.getVersionData
            26. modX.handleRequest
            27. modX.hasPermission
            28. modX.initialize
            29. modX.invokeEvent
            30. modX.lexicon
            31. modX.makeUrl
            32. modX.parseChunk
            33. modX.regClientCSS
            34. modX.regClientHTMLBlock
            35. modX.regClientScript
            36. modX.regClientStartupHTMLBlock
            37. modX.regClientStartupScript
            38. modX.reloadConfig
            39. modX.removeAllEventListener
            40. modX.removeEventListener
            41. modX.runProcessor
            42. modX.runSnippet
            43. modX.sendError
            44. modX.sendErrorPage
            45. modX.sendForward
            46. modX.sendRedirect
            47. modX.sendUnauthorizedPage
            48. modX.setDebug
            49. modX.setPlaceholder
            50. modX.setPlaceholders
            51. modX.switchContext
            52. modX.toPlaceholder
            53. modX.toPlaceholders
            54. modX.unsetPlaceholder
            55. modX.unsetPlaceholders
        4. Loading MODx Externally
        5. Reserved Parameters
    6. Case Studies and Tutorials
      1. Developing an Extra in MODX Revolution
        1. Developing an Extra in MODX Revolution, Part II
        2. Developing an Extra in MODX Revolution, Part III
      2. Developing an Extra in MODX Revolution - MODX 2.1 and Earlier
        1. Developing an Extra in MODX Revolution, Part II - MODX 2.1 and Earlier
        2. Developing an Extra in MODX Revolution, Part III - MODX 2.1 and Earlier
      3. PHP Coding in MODx Revolution, Pt. I
        1. PHP Coding in MODx Revolution, Pt. II
        2. PHP Coding in MODx Revolution, Pt. III
      4. Using Custom Database Tables in your 3rd Party Components
      5. Creating a Blog in MODx Revolution
      6. Loading Pages in the Front-End via AJAX and jQuery Tabs
      7. Reverse Engineer xPDO Classes from Existing Database Table
      8. Integrating a Template into MODX Tutorial
      9. Quick and Easy MODX Tutorials
        1. Automated Server-Side Image Editing
      10. Adding Custom Fields to Manager Forms
      11. Create a Multilingual Website with migxMultiLang
      12. Managing Resources and Elements via SVN
    7. MODX Community Information
      1. Becoming a Core Contributor
      2. Filing Bug Reports
      3. Getting a MODx Account
      4. Using GitHub

Hardening MODX Revolution

Overview

Hardening any web application, including MODx Revolution, involves auditing all layers of your site, including your server, all of its services, and the application itself. Make no mistake: it's a war out there. If you're not afraid, then you aren't paying attention. The simple act of having a website on-line will ensure that you will be targeted by hacks. Their motives vary, but the weakest link will be sought out and exploited.

Hardening is a huge topic, so this page seeks to help you identify what might be the most common attack vectors on your site and help you close them.

Everything but MODX

There are many aspects to hardening that have nothing to do with MODX. We make perfunctory mention of them here, but this page is focused specifically on how to harden MODX. A thorough security audit will focus on the entire environment, so do not neglect to consider the following aspects:

Your Computer

Using any version of Windows prior to Windows Vista is almost a death-wish. This isn't just indiscriminate Microsoft bashing, it's because it literally took MicroSoft twenty-some years to finally build a system whose security policy was "default-deny" instead of "default-permit" (read more here), and Windows still does not include a secure shell (SSH). Hardening older Windows systems is a herculean effort and unless you are extremely skilled and vigilant, your pre-Vista computer will likely contain severe security holes.

But don't be fooled: ANY operating system can be hacked. Don't think you're impervious if you're on a Mac or pushing the Penguin. Run as a user with limited permissions and keep your system patched and run dynamic intrusion detection software to protect you from key-loggers or screen-capture viruses. Never save your passwords or other login info as plain text, use secure software like LastPass to store your passwords.

NEVER use a public computer: for all you know, that computer is logging every username and password you type.

Your Connection

If possible, use only wired connections (no Wifi). Never use public Wifi, and never use a wireless connection that uses anything less than WPA2 encryption. It's far too easy to intercept packets as they travel across a router. With only modest hacking skills, someone can read your usernames and passwords as they travel get beamed around the coffeeshop.

Your Server

No matter how secure all other elements are, it amounts to nothing if your server is not adequately secure. If your FTP password is cracked, then there's nothing you can do to guarantee the integrity of your site. Turn off all unnecessary services and if possible, turn off FTP entirely in favor of SFTP. Consider turning off password authentication entirely in favor of SSH keyed logins, and if you use an SSH key, make sure you use a complex passphrase.

Make sure that your server has a good firewall installed and some form of intrusion detection that dynamically detects hacking attempts. ModSecurity is a security module for Apache, and it helps deter any number of malicious attacks.

Update your server and its technologies often! If any weak link is discovered in any part of your server, it could be the crack in the dam that floods your entire site with a world of hurt. Keep your server patched!

Passwords and Logins

Choose long, randomly generated passwords and update them regularly. Longer passwords are usually more mathematically complex than shorter passwords, even if your passwords use special characters. Salting your passwords with a easily-remembered phrase to increase the password length is a good technique to reduce the odds of a brute-force attack succeeding. Again, you MUST store your passwords securely, in some sort of encrypted format. It's far better to write your passwords in a notebook that you keep in a locked filing cabinet than it is to keep them in a plaintext file on your computer.

Very important: never use the same password twice. Frequently hacks succeed because one service is compromised and the password deciphered, and a user has ignorantly or lazily used the same password for other sites or services. DO NOT BE LAZY!!!

Keep it Clean

Delete anything unnecessary from your site. Delete any unused images or javascript files. Especially bad are any lingering PHP scripts or god-forbid, any backups or zip files inside of your document root. Think of your site as a sinking airship: if you don't need it, throw it out before you crash and burn. If you're not using a particular Plugin, Snippet, or template, for example, then delete its files from your server. Just because it's not activated doesn't mean it can't be exploited!

Backups

One of the most important things you can do for your web site is to set up incremental, off-site backups. There is never a guarantee that you won't get hacked, so the best thing you can do is to ensure that at a minimum, you have backups to restore your site if and when it gets nuked.

Social Engineering

Many hacks involve some plain old trickery: someone calling or emailing you and asking for information under false pretexts. Don't be fooled! Are you SURE it's your client asking you for their password? Or is it someone who got into their email account? For a good read, check out Kevin Mitnick's Ghost in the Wires: he was able to get the source code from many LARGE companies merely by placing believable phone-calls to the right person.

Locking down MODX

You'll notice that this is only one small section of the hardening process. Remember: MODX is only one aspect of your environment, so do not neglect the previous section!

Changing Default Paths

Unlike Evolution, MODX Revolution makes it fairly easy to change the names of its various folders and move the core outside the web root. Note that only the core can (and should) be moved outside the web root because the other directories must be accessible via the web. Changing the directory names is critical if you want to avoid your site being fingerprinted and ending up on the speed-dial list of every hacker-bot out there.

The Advanced Distribution allows you to specify the names and locations of the various directories during the install, but it won't install successfully on some hosts.

Before you do any of this, make a backup of your site and your database!

core

This is perhaps the most important path to change. Move your core directory out of the web server's document root. You don't want anyone poking around in there via a browser and exploiting any potential weaknesses. One simple place to put it is simply one folder above your document root, i.e. /core/ instead of /public_html/core/. Once you move it, you'll have to update the following configuration details:

  • core/config/config.inc.php (change the $modx_core_path variable)
  • /config.core.php (at the site root)
  • /connectors/config.core.php
  • /manager/config.core.php
  • The modx_workspaces database table – this is best done by re-running the setup as you might do when moving your site

You'll probably want to go ahead and update the other paths, but just keep in mind that once you're done, you'll have to run the setup to ensure that all your paths are clean.

manager

The manager is arguably the second most important path to change. After all, if someone sees that you've got a nice MODX login page at http://yoursite.com/manager/ it won't take a genius to figure out that you're running MODX and the brute-force hacking attempts can begin.

Choose a randomly generated alphanumeric bit of text to use as your new manager folder. For maximum compatibility, it should use only lowercase letters. Then update the core/config/config.inc.php file to something like the following:

$modx_manager_path = '/home/youruser/public_html/r4nd0m/';
$modx_manager_url = '/r4nd0m/';

Moving the manager will avoid the fingerprinting bots from easily sniffing your site out as a MODX site, but it's still possible that someone could eventually find your new manager directory (not easy, but entirely possible). For an even more thorough solution, you could put the manager URL on a completely different domain, e.g. $modx_manager_url = 'http://othersite.com/r4nd0m/'; This would require that you have multiple domains on your server, but the advantage here is that it would really throw off attempts to hack your site because it wouldn't be clear that the 2 domains are related, but it would require far more sysadmin work to make this type of setup work.

You can also lock down access to the manager by configuring your server and/or its firewall to allow access to the manager url from specific IP addresses. E.g. if your site is only accessed by workers in an office, you could configure your server to deny requests from outside the office's IP addresses. Another tactic would be to put an .htaccess password on the manager directory. This would mean that users would have to enter 2 separate passwords before entering the MODX manager. Perhaps that's not convenient, but it is more secure.

connectors

Just as with the manager directory, choose a random alphanumeric name for your connectors directory, and then update your core/config/config.inc.php to reflect the new location, e.g.

$modx_connectors_path = '/home/youruser/public_html/0therp4th/';
$modx_connectors_url = '/0therp4th/';

As with the manager, this could also potentially live on a separate domain.

assets

The assets URL can be changed, but this is the lowest priority change because anyone visiting your site will be able to examine the source HTML and see the paths to this directory. But it's good to change anyway, simply to confuse any efforts at fingerprinting.

$modx_assets_path = '/home/youruser/public_html/4ssetsh3r3/';
$modx_assets_url = '/4ssetsh3r3/';

Again, this could potentially live on another domain (e.g. one optimized to serve up static content).

Path Followup

After changing all these paths, save the new locations in a secure place (as with your passwords), and then re-run the MODX setup utility to ensure that everything was set correctly.

Doing this will make your site more secure, but updating your site will become more complex: you will have to merge the various component directories one at a time for each MODX update.

Change your Login Page

Ideally, you should also mask your manager login page so it's not obvious that you're running MODX. At a minimum, you should remove any MODX branding from your manager login form. See the page on Manager Templates for more information.

Changing Default Database Prefixes

This is best done when you first install MODX, but it's always a good habit to avoid the defaults and choose a custom database prefix for your tables instead of the default modx_ prefix. If a hacker is somehow able to issue arbitrary SQL commands via a SQL injection attack, using custom table prefixes will make the attack just that much more difficult.

Use a unique name for the Admin User

If your admin username is hard to guess, it will slow down any attempt at a brute-force hack. A randomly generated series of characters would make for the most secure username. Never use a name that is easy to guess (do not use a username like admin, manager, or a name that matches the site's name – they're too easy to guess). Remember that a big part of hacking is social engineering – you want to make it virtually impossible for someone to guess your admin user name.

Force a Password Policy

Delete any stagnant users from your site (e.g. if you created a login for a developer when you first setup the site, be sure to deactivate that user once his/her work is done). Ensure that each user is using a complex password.

Set up a dedicated 404 page

Don't just point your 404 page to your homepage. Set up a dedicated 404 page. We don't want our site to get any undue attention because a scanner thinks that you have a page on your site that you do not. E.g. if scanner looks for a known vulnerability at http://yoursite.com/malicious/hack, and the request comes back as an HTTP 200, then the scanner might think that you actually have that vulnerable file on your site, and it will attract other hacks or scans. You can use the FireFox "Web Developer" add-on (or several others) to view page headers and verify that 404s are actually 404s.

Forcing SFTP Access

The kosher dictum here is "NEVER USE FTP." If your server doesn't support SFTP, find a different host. Period. Even shared hosts will have a shared certificate that you can use to access your sites securely.

Adding an SSL Certificate to your Manager

Sending usernames and passwords via plaintext is silly: any fool hacker with an ounce of dedication can intercept them. If security is a priority, you should always access your MODX manager via a secure connection (i.e. via HTTPS).

Using a shared Certificate

Just like with FTP, if your site is on a shared host, you can often piggyback on your host's shared certificate. That makes for ugly URLs, but please ladies and gentlemen: do not be so superficial as to put URL aesthetics above your security.

Talk to your web host for specific instructions here, but to give you an idea, sometimes, you can use a URL that features your host's name or IP and your username, e.g.

https://myhost.com/~myuser/manager
https://127.0.0.1/~myuser/manager

127.0.0.1 is just an example IP address, and surely you've already changed your default "manager" URL, no?

Using a self-signed Certificate

The piggy-back option works in a pinch, but for any serious site, you'll want to install your own SSL certificate, so then we have to talk about IP addresses: you must have a unique IP address to install an SSL certificate. You can create your own self-signed certificate so long as you have a unique IP address. Multiple non-secure HTTP connections can be shared across a single IP address, but a secure HTTPS connection requires its own dedicated IP address. Most hosting providers will offer a unique IP address for an additional fee (usually an extra couple dollars per month).

Once you have a dedicated IP address (and only then), you can install an SSL certificate. But now you face another dilemma: what kind?

The cheapest option is to use your own self-signed certificate. Technically, it's every bit as secure as the ones you pay for, but due to the nature of "trust" and how internet browsers are programmed, your self-signed certificates will throw warnings in browsers:

Why? Because nobody knows who you are. And who are you to sign your own certificate? The technology in place is the same no matter who signs your certificate, but the fact that you are not one of the trusted few entities that sign certificates, your browser will curse at you, and for good reason. Remember the Arab Spring? In Syria, the government issued fake SSL certificates in order to spy on protesters' Facebook accounts. The morale of the story: if your browser says the certificate might be forged, run away. But if you know that YOU signed this certificate, then you can trust yourself. And if your clients trust you, you can instruct them to ignore that browser message.

Do you understand what you're up against? It's a legitimate solution in certain situations. If it's just you on this hobby-horse, load up! Install a self-signed certificate! The exact instructions here depend on your server, but here's a tutorial for Open SSL: click here.

Install a "Real" Certificate

If the browser warnings are not acceptable for you or your clients, you need to be willing to spend a little money. Prices on SSL certificates vary wildly (really, really crazy here), so shop around. Seriously, the difference here are jaw-dropping, and the practical differences are hard to distinguish, so here's some links to get you started:

Whether you generate a .crt file yourself or you buy one, you'll have to install install it on your server, but that's the gold at the end of the rainbow: one way or another, that makes your connection encrypted. Once you can access your site via a secure connection, you must configure the manager to force secure connections.

Forcing SSL connections to the Manager

Once you've got your site hooked up to use HTTPS, you need to force the manager to use SSL. First, you should confirm that both http://yoursite.com/ AND https://yoursite.com/ both work (browser warnings depending on what kind of certificate you've installed).

Once you've verified that HTTPS works, you can now modify your .htaccess file to force all connections to the manager to occur over port 443 (i.e. over a secure connection).

Inside your manager's folder (which you've changed by now from the default /manager/ directory), you should edit your /manager/.htaccess file to force a secure connection.

Here is a sample .htaccess file to put inside your manager directory:

RewriteEngine On
RewriteBase /
RewriteCond %{SERVER_PORT} 80
RewriteRule ^(.*)$ https://yoursite.com/manager/$1

Test this by trying to navigate to the non-secure url, e.g. http://yoursite.com/manager – if it doesn't redirect to HTTPS, you'll have to tweak the .htaccess.

Monitoring your Site and Server

Once you've locked down your site and server, you'll benefit from regular monitoring of it. There are some free services available. The best ones will monitor specific files and report any changes made to them. If your index.php suddenly changed, then that might indicate that somebody maliciously modified it.

Changing the Manager Templates as per the documentation is a nice way to customize your login page!

Suggest an edit to this page on GitHub (Requires GitHub account. Opens a new window/tab).