evolution / wordpress

Rapidly create, develop, & deploy WordPress across multiple environments.
MIT License
200 stars 18 forks source link

Optionally bypass xml-rpc blocking... #147

Closed EvanK closed 8 years ago

EvanK commented 8 years ago

Evidently, the Jetpack plugin requires remote access to xmlrpc.xml (from wordpress' site), so we need a way around our default behavior of denying all access to it (which we do because it's a gaping security risk).

/cc @ericrasch

EvanK commented 8 years ago

This implements two methods for XML-RPC access, and adds (commented out) examples of both to the group vars file...

Access for all

You can allow unconditional access to Wordpress' XML-RPC:

wordpress__xmlrpc_allow: true

This will generate the following in your virtual host configuration:

    # Enable XML-RPC unconditionally
    <files xmlrpc.php>
        Order allow,deny
        Allow from all
    </files>

Access for some

Alternatively, you can allow conditional XML-RPC access by way of Apache's SetEnvIf directive.

You'd do so by providing a dictionary (key-value hash) in your group vars, where the key is a regular expression match (that must be unique within the whitelist), and the value is an attribute that the expression would successfully match.

For example, this would allow XML-RPC requests from the local host:

wordpress__xmlrpc_whitelist:
  '^127[.]0[.]0[.]1$': 'Remote_Addr'

This will generate the following in your virtual host configuration:

    # Enable XML-RPC for the following SetEnvIf conditions
    SetEnvIf Remote_Addr "^127[.]0[.]0[.]1$" allow_wp_xmlrpc
    <files xmlrpc.php>
        Order deny,allow
        Deny from all
        Allow from env=allow_wp_xmlrpc
    </files>

No access for anyone (continued default behavior)

If neither override variables are provided, or both are falsey values, the established default behavior is maintained and all access is denied to Wordpress' XML-RPC:

    # Disable XML-RPC unconditionally
    <files xmlrpc.php>
        Order allow,deny
        Deny from all
    </files>
ericrasch commented 8 years ago

For the SetEnvIf, would you be able to use a domain name instead of just an IP? Also, what about more than one domain/IP entry?

EvanK commented 8 years ago

@ericrasch No. You could with Remote_Host, but only with HostnameLookups turned on...and it is turned off by default (for performance reasons) in almost all cases

EvanK commented 8 years ago

Furthermore, hostname lookups rely on DNS...meaning a request from wordpress.com servers would only resolve as "wordpress.com" if their outgoing IP matches exactly what's in their DNS records.

I can attest (from our own infrastructure) that this is not always the case

EvanK commented 8 years ago

With that DNS restriction in mind, we could use Apache 2.4's Require directives instead, which would bypass the need for turning on HostnameLookups

ericrasch commented 8 years ago

I'm good with everything proposed here. Is this mergable/deployable?

EvanK commented 8 years ago

I'll update this to use Require directives, and then it should be ready to roll

EvanK commented 8 years ago

Rewritten to use Apache 2.4's Require directives, and explicitly enable the apache modules that might be required...

Access for all

This still allows unconditional access to Wordpress' XML-RPC:

wordpress__xmlrpc_allow: true

But instead generates the following virtual host config:

    # Enable XML-RPC unconditionally
    <files xmlrpc.php>
        Require all granted
    </files>

Access for some

Given a list of strings, this will write a series of Require directives using the raw strings provided.

For example, either of these would allow access from the local host:

wordpress__xmlrpc_whitelist:
  - "local"
  - "ip 127.0.0.0/8"

This will generate the following virtual host config:

    # Enable XML-RPC for only the following Require conditions
    <files xmlrpc.php>
        Require all denied
        Require local
        Require ip 127.0.0.0/8
    </files>

No access for anyone (continued default behavior)

The established default behavior is maintained and all access is denied to Wordpress' XML-RPC:

    # Disable XML-RPC unconditionally
    <files xmlrpc.php>
        Require all denied
    </files>
EvanK commented 8 years ago

For reference, you could whitelist remote hostnames via a double reverse dns lookup with:

wordpress__xmlrpc_whitelist:
  - "host wordpress.org"
EvanK commented 8 years ago

@ericrasch released as v1.4.3