skip to Main Content

Good day,

I’m trying to create a docker environment where one can exercise stored XSS.

The XSS happens in the comment section and sends the document.cookie content to the attacker. The login cookie is not sent. That is only possible if HTTPOnly tag in the cookie is set to false.

Here’s my docker-compose file

version: "3.8"
services:
  wordpress:
    image: wordpress:4.1
    environment:
      WORDPRESS_DB_HOST: db
      WORDPRESS_DB_USER: dbuser
      WORDPRESS_DB_PASSWORD: dbpassword 
      WORDPRESS_DB_NAME: exampledb
    links:
        - db:mysql  
    volumes:
      - ./wordpress:/var/www/html
    ports:
      - 8080:80
  db:
    image: mysql:5.7
    restart: always
    environment:
      MYSQL_DATABASE: exampledb
      MYSQL_USER: dbuser
      MYSQL_PASSWORD: dbpassword
      MYSQL_RANDOM_ROOT_PASSWORD: '1'         
    ports:
      - 3306:3306  
    volumes:
      - ./db:/var/lib/mysql
volumes:
  wordpress:
  db:

I tried the following:

in wp-config.php

@ini_set('session.cookie_httponly', false); 
@ini_set('session.cookie_secure', false); 
@ini_set('session.use_only_cookies', false);

modifying the setcookie function in wp-login.php in all occurences (setting the httponly parameter to false)

setcookie( $rp_cookie, ' ', time() - YEAR_IN_SECONDS, $rp_path, COOKIE_DOMAIN, is_ssl(), false );

without any success.
I appreciate any help possible.

2

Answers


  1. You should edit ‘wp-includes/pluggable.php’ file. Change last true parameter to false.

    Enable HttpOnly:

    setcookie( $auth_cookie_name, $auth_cookie, $expire, PLUGINS_COOKIE_PATH, COOKIE_DOMAIN, $secure, true );
    setcookie( $auth_cookie_name, $auth_cookie, $expire, ADMIN_COOKIE_PATH, COOKIE_DOMAIN, $secure, true );
    setcookie( LOGGED_IN_COOKIE, $logged_in_cookie, $expire, COOKIEPATH, COOKIE_DOMAIN, $secure_logged_in_cookie, true );
    setcookie( LOGGED_IN_COOKIE, $logged_in_cookie, $expire, SITECOOKIEPATH, COOKIE_DOMAIN, $secure_logged_in_cookie, true );
    

    Disable HttpOnly:

    setcookie( $auth_cookie_name, $auth_cookie, $expire, PLUGINS_COOKIE_PATH, COOKIE_DOMAIN, $secure, false );
    setcookie( $auth_cookie_name, $auth_cookie, $expire, ADMIN_COOKIE_PATH, COOKIE_DOMAIN, $secure, false );
    setcookie( LOGGED_IN_COOKIE, $logged_in_cookie, $expire, COOKIEPATH, COOKIE_DOMAIN, $secure_logged_in_cookie, false );
    setcookie( LOGGED_IN_COOKIE, $logged_in_cookie, $expire, SITECOOKIEPATH, COOKIE_DOMAIN, $secure_logged_in_cookie, false );
    
    Login or Signup to reply.
  2. I had a similar issue a while ago, and wordpress being wordpress caused it to be a bit of a nightmare, especially with other plugins also acting like they have free reign to change whatever they want on the box

    This was the class I ended up using for messing around with cookies as wp was setting them, with hooks for login and auth cookies

    <?php
    /**
     * Enforces The Cookie Parameters Needed
     *
     * @author yourname
     * @version $Id$
     * @package default
     */
    
    namespace mypluginEnforce_Cookie_Params;
    
    class Enforce_Cookie_Params {
        public static $instance;
    
        public static function get_instance() {
            if ( ! isset( self::$instance ) ) {
                self::$instance = new self();
            }
    
            return self::$instance;
        }
    
        public function __construct() {
            $this->set_up_hooks();
        }
    
        public function set_up_hooks() {
            add_action( 'set_logged_in_cookie', array( $this, 'plugin_set_logged_in_cookie' ), 10, 6 );
            add_action( 'set_auth_cookie', array( $this, 'plugin_set_auth_cookie' ), 10, 5 );
            add_filter( 'send_auth_cookies', array( $this, 'plugin_send_auth_cookies' ), 10, 4 );
        }
    
        public function plugin_set_logged_in_cookie( $logged_in_cookie, $expire, $expiration, $user_id, $scheme, $token ) {
    
            $base_options = array(
                'expires'  => $expire,
                'domain'   => COOKIE_DOMAIN,
                'httponly' => true,
                'samesite' => 'None',
                'secure'   => is_ssl(),
            ); // httponly is added at samesite_setcookie();
    
            samesite_setcookie(
                LOGGED_IN_COOKIE,
                $logged_in_cookie,
                $base_options + array(
                    'secure' => $secure_logged_in_cookie,
                    'path'   => COOKIEPATH,
                )
            );
            if ( COOKIEPATH != SITECOOKIEPATH ) {
                samesite_setcookie(
                    LOGGED_IN_COOKIE,
                    $logged_in_cookie,
                    $base_options + array(
                        'secure' => $secure_logged_in_cookie,
                        'path'   => SITECOOKIEPATH,
                    )
                );
            }
        }
    
    
        function plugin_set_auth_cookie( $auth_cookie_value, $expire, $expiration, $user_id, $scheme ) {
            $auth_cookie_name = SECURE_AUTH_COOKIE;
            $secure           = is_ssl();
    
            $base_options = array(
                'expires'  => $expire,
                'domain'   => COOKIE_DOMAIN,
                'httponly' => true,
                'samesite' => 'None',
            ); // httponly is added at samesite_setcookie();
    
            samesite_setcookie(
                $auth_cookie_name,
                $auth_cookie_value,
                $base_options + array(
                    'secure' => $secure,
                    'path'   => PLUGINS_COOKIE_PATH,
                )
            );
            samesite_setcookie(
                $auth_cookie_name,
                $auth_cookie_value,
                $base_options + array(
                    'secure' => $secure,
                    'path'   => ADMIN_COOKIE_PATH,
                )
            );
        }
    
        function plugin_send_auth_cookies( $send ) {
            // header( 'Refresh: 0;' );
            $send = false;
            return $send;
        }
    
    
        /**
         * @internal Function to mimic setcookie() function behaviour without PHP 7.3 as
         *  as a requirement to set SameSite flag. This function does not handle exceptional
         *  cases well (to keep its functionality minimal); Do not use for any other purpose.
         * @param $name
         * @param $value
         * @param array $options
         */
        function samesite_setcookie( $name, $value, array $options ) {
            $header  = 'Set-Cookie:';
            $header .= rawurlencode( $name ) . '=' . rawurlencode( $value ) . ';';
            $header .= 'expires=' . gmdate( 'D, d-M-Y H:i:s T', $options['expires'] ) . ';';
            $header .= 'Max-Age=' . max( 0, (int) ( $options['expires'] - time() ) ) . ';';
            $header .= 'path=' . rawurlencode( $options['path'] ) . ';';
            $header .= 'domain=' . rawurlencode( $options['domain'] ) . ';';
    
            if ( ! empty( $options['secure'] ) ) {
                $header .= 'secure;';
            }
            $header .= 'httponly;';
            $header .= 'SameSite=' . rawurlencode( $options['samesite'] );
    
            $ret = setcookie(
                $name,
                $value,
                $options,
            );
    
            ob_clean();
            header( $header, false );
            $_COOKIE[ $name ] = $value;
        }
    }
    

    that being said, if you just want to change those headers and you are running apache just bind-mount/find another way of getting a .htaccess into your docker machine and write a regex to strip it, I have used itto increase security but i imagine it would work in reverse as well, if this turns it on

    Header edit Set-Cookie ^(.*)$ $1;HttpOnly;SameSite=strict
    

    something like this could be used to turn it off by dropping everything after the first ‘;’

    Set-Cookie:s+(?<cookie>[^=]+=[^;]+)
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search