Server Message Block (SMB) v2
Files and Directories management with an SMB server. Supports SMB2 and SMB3 protocols.
Utilities · Server Message Block (SMB)
Details
| ID | Server Message Block (SMB) v2 |
|---|---|
| Provider | Microsoft |
| Category | Utilities |
| From Version | 5.0.0 |
| Docker Image | demisto/smbprotocol:1.0.0.9067966 |
| Supported Modules | Agentix Cloud Runtime Security Cloud Posture Security XSIAM EDR Cortex Cloud |
README
Files and Directories management with an SMB server. Supports SMB2 and SMB3 protocols.
Configure Server Message Block (SMB) v2 in Cortex
| Parameter | Description | Required |
|---|---|---|
| Server IP / Hostname (e.g. 1.2.3.4) | False | |
| Port | False | |
| Domain Controller | The domain controller hostname. This is useful for environments with DFS servers as it is used to identify the DFS domain information automatically. | False |
| Username | False | |
| Client GUID | The client machine name to identify the client to the server on a new connection. | False |
| Force Encryption | Force encryption on the connection, requires SMBv3 or newer on the remote server. Default is “false”. | False |
| Secure Dialect Negotiation | Validate the negotiation info when connecting to a share. More information can be found on https://docs.microsoft.com/en-us/archive/blogs/openspecification/smb3-secure-dialect-negotiation | False |
Commands
You can execute these commands from the CLI, as part of an automation, or in a playbook.
After you successfully execute a command, a DBot message appears in the War Room with the command details.
smb-download
Downloads a file from the server.
Base Command
smb-download
Input
| Argument Name | Description | Required |
|---|---|---|
| file_path | The path to the file, starting from the share, for example: Share/Folder/File. This field is case-insensitive. | Required |
| hostname | Server IP address / hostname. If empty, the hostname from the instance configuration is used. | Optional |
| username | The username to use when creating a new SMB session. If empty, the username from the instance configuration is used. | Optional |
| password | The password to use for authentication. If empty, the password from the instance configuration is used. | Optional |
Context Output
| Path | Type | Description |
|---|---|---|
| File.Size | number | File size. |
| File.SHA1 | string | SHA1 hash of the file. |
| File.SHA256 | string | SHA256 hash of the file. |
| File.Name | string | File name. |
| File.SSDeep | string | SSDeep hash of the file. |
| File.EntryID | string | File entry ID. |
| File.Info | string | Information about the file. |
| File.Type | string | File type. |
| File.MD5 | string | MD5 hash of the file. |
Command Example
!smb-download file_path=Shared/Tests/Test.txt
Context Example
{
"File": {
"EntryID": "2837@51c113de-6213-4aea-8beb-d4b88551f7f8",
"Extension": "txt",
"Info": "text/plain; charset=utf-8",
"MD5": "ce114e4501d2f4e2dcea3e17b546f339",
"Name": "Test.txt",
"SHA1": "a54d88e06612d820bc3be72877c74f257b561b19",
"SHA256": "c7be1ed902fb8dd4d48997c6452f5d7e509fbcdbe2808b16bcf4edce4c07d14e",
"SHA512": "a028d4f74b602ba45eb0a93c9a4677240dcf281a1a9322f183bd32f0bed82ec72de9c3957b2f4c9a1ccf7ed14f85d73498df38017e703d47ebb9f0b3bf116f69",
"SSDeep": "3:hMCEpn:hup",
"Size": 14,
"Type": "ASCII text, with no line terminators"
}
}
Human Readable Output
smb-upload
Uploads a file to the server.
Base Command
smb-upload
Input
| Argument Name | Description | Required |
|---|---|---|
| file_path | The path to the file, starting from the share, for example: Share/Folder/File. This field is case-insensitive. | Required |
| hostname | Server IP address / hostname. If empty, the hostname from the instance configuration is used. | Optional |
| username | The username to use when creating a new SMB session. If empty, the username from the instance configuration is used. | Optional |
| password | The password to use for authentication. If empty, the password from the instance configuration is used. | Optional |
| entryID | EntryID of the file to send to the share. | Optional |
| content | File content to send to the share. Ignored if EntryID argument is specified. | Optional |
Context Output
There is no context output for this command.
Command Example
!smb-upload file_path=Shared/Tests/Test.txt content="This is a test"
Human Readable Output
File Test.txt was uploaded successfully
smb-directory-list
Returns a list containing the names of the entries in the directory given by path.
Base Command
smb-directory-list
Input
| Argument Name | Description | Required |
|---|---|---|
| path | The path to the directory, starting from the share, for example: Share/Folder. This field is case-insensitive. | Required |
| hostname | Server IP address / hostname. If empty, the hostname from the instance configuration is used. | Optional |
| username | The username to use when creating a new SMB session. If empty, the username from the instance configuration is used. | Optional |
| password | The password to use for authentication. If empty, the password from the instance configuration is used. | Optional |
Context Output
| Path | Type | Description |
|---|---|---|
| SMB.Path.SharedFolder | String | The full path of the shared folder. |
| SMB.Path.Files | Unknown | List of files under the shared folder. |
| SMB.Path.Directories | Unknown | List of directories under the shared folder. |
Command Example
!smb-directory-list path=Shared
Context Example
{
"SMB": {
"Path": {
"Directories": [
"Tests"
],
"Files": [
"123.txt",
"test.jpg"
],
"SharedFolder": "127.0.0.1/Shared"
}
}
}
Human Readable Output
List Of Entries for 127.0.0.1/Shared
Directories Files SharedFolder Tests 123.txt,
test.jpg127.0.0.1/Shared
smb-file-remove
Removes a file from the server.
Base Command
smb-file-remove
Input
| Argument Name | Description | Required |
|---|---|---|
| file_path | The path to the file, starting from the share, for example: Share/Folder/File. This field is case-insensitive. | Required |
| hostname | Server IP address / hostname. If empty, the hostname from the instance configuration is used. | Optional |
| username | The username to use when creating a new SMB session. If empty, the username from the instance configuration is used. | Optional |
| password | The password to use for authentication. If empty, the password from the instance configuration is used. | Optional |
Context Output
There is no context output for this command.
Command Example
!smb-file-remove file_path=Shared/Tests/Test.txt
Human Readable Output
File Test.txt was deleted successfully
smb-directory-create
Creates a new directory under the given path.
Base Command
smb-directory-create
Input
| Argument Name | Description | Required |
|---|---|---|
| path | The path to the directory, starting from the share, for example: Share/NewFolder. This field is case-insensitive. | Required |
| hostname | Server IP address / hostname. If empty, the hostname from the instance configuration is used. | Optional |
| username | The username to use when creating a new SMB session. If empty, the username from the instance configuration is used. | Optional |
| password | The password to use for authentication. If empty, the password from the instance configuration is used. | Optional |
Context Output
There is no context output for this command.
Command Example
!smb-directory-create path=Shared/Tests
Human Readable Output
Directory: 127.0.0.1/Shared/Tests was created successfully
smb-directory-remove
Removes a directory from the given path.
Base Command
smb-directory-remove
Input
| Argument Name | Description | Required |
|---|---|---|
| path | The path to the directory, starting from the share, for example: Share/NewFolder. This field is case-insensitive. | Required |
| hostname | Server IP address / hostname. If empty, the hostname from the instance configuration is used. | Optional |
| username | The username to use when creating a new SMB session. If empty, the username from the instance configuration is used. | Optional |
| password | The password to use for authentication. If empty, the password from the instance configuration is used. | Optional |
Context Output
There is no context output for this command.
Command Example
!smb-directory-remove path=Shared/Tests
Human Readable Output
Directory: 127.0.0.1/Shared/Tests was removed successfully
Configuration parameters
hostname— Server IP / Hostname (e.g. 1.2.3.4)port— Portdc— Domain Controllercredentials— Usernameclient_guid— Client GUIDencrypt— Force Encryptionrequire_secure_negotiate— Secure Dialect Negotiation
Commands (6)
-
smb-directory-createCreates a new directory under the given path.
-
smb-directory-listReturns a list containing the names of the entries in the directory given by path.
-
smb-directory-removeRemoves a directory from the given path.
-
smb-downloadDownloads a file from the server.
-
smb-file-removeRemoves a file from the server.
-
smb-uploadUploads a file to the server.
import uuid import demistomock as demisto # noqa: F401 from CommonServerPython import * # noqa: F401 """ IMPORTS """ import smbclient from smbclient import ( mkdir, open_file, register_session, remove, rmdir, scandir, ) def get_file_name(path): delimiter = "/" if "/" in path else "\\" return path.split(delimiter)[-1] def handle_path(path): """ Stripping the '\\' and '/' characters from a given path. Examples: \\Shared\\123.txt\\ ---> Shared\\123.txt /Shared/123.txt/ ---> Shared/123.txt \\Shared\\123.txt/\\ ---> Shared\\123.txt """ return path.strip("\\/") def create_share_path(hostname, path): r""" Create a path to the shared folder according to the smbprotocol convention: '\\server\share'. For reference see https://github.com/jborean93/smbprotocol/blob/master/examples/high-level/directory-management.py """ return rf"\\{hostname}\{path}" class SMBClient: def __init__(self, hostname, user, password, encrypt, port): self.hostname = hostname self._user = user self._password = password self._encrypt = encrypt self._port = port def create_session( self, hostname: str = None, user: str = None, password: str = None, encrypt: bool = False, port: int = None ): register_session( server=hostname or self.hostname, username=user or self._user, password=password or self._password, port=port or self._port, encrypt=encrypt or self._encrypt, auth_protocol="ntlm", ) def test_module(client: SMBClient): client.create_session() return "ok" def smb_upload(client: SMBClient, args: dict): hostname = args.get("hostname") path = handle_path(args.get("file_path")) path = create_share_path(hostname or client.hostname, path) username = args.get("username") password = args.get("password") entryID = args.get("entryID") content = args.get("content") if not entryID and not content: raise DemistoException("You must provide a content to upload using one of the following arguments: content, entryID.") client.create_session(hostname, username, password) # For the content argument - the input is text. writing_mode = "w" if entryID: file = demisto.getFilePath(entryID) filePath = file["path"] writing_mode = "wb" with open(filePath, mode="rb") as f: content = f.read() with open_file(rf"{path}", mode=writing_mode) as file_obj: file_obj.write(content) return f"File {get_file_name(path)} was uploaded successfully" def smb_download(client: SMBClient, args: dict): hostname = args.get("hostname") path = handle_path(args.get("file_path")) path = create_share_path(hostname or client.hostname, path) username = args.get("username") password = args.get("password") client.create_session(hostname, username, password) with open_file(rf"{path}", mode="rb") as fd: file_contents = fd.read() file_name = get_file_name(path) return fileResult(file_name, file_contents) def smb_remove_file(client: SMBClient, args: dict): hostname = args.get("hostname") path = handle_path(args.get("file_path")) path = create_share_path(hostname or client.hostname, path) username = args.get("username") password = args.get("password") client.create_session(hostname, username, password) remove(path) file_name = get_file_name(path) return f"File {file_name} was deleted successfully" def list_dir(client: SMBClient, args: dict): hostname = args.get("hostname") username = args.get("username") password = args.get("password") path = handle_path(args.get("path")) path = create_share_path(hostname or client.hostname, path) client.create_session(hostname, username, password) entries = list(scandir(path)) files = [] dirs = [] for entry in entries: if entry.is_file(): files.append(entry.name) if entry.is_dir(): dirs.append(entry.name) context = { "SharedFolder": path, "Files": files, "Directories": dirs, } return CommandResults( outputs_prefix="SMB.Path", outputs_key_field="SharedFolder", outputs=context, readable_output=tableToMarkdown(f"List Of Entries for {path}", context), ) def smb_mkdir(client: SMBClient, args: dict): hostname = args.get("hostname") username = args.get("username") password = args.get("password") path = handle_path(args.get("path")) path = create_share_path(hostname or client.hostname, path) client.create_session(hostname, username, password) mkdir(path) return f"Directory: {path} was created successfully" def smb_rmdir(client: SMBClient, args: dict): hostname = args.get("hostname") username = args.get("username") password = args.get("password") path = handle_path(args.get("path")) path = create_share_path(hostname or client.hostname, path) client.create_session(hostname, username, password) rmdir(path) return f"Directory: {path} was removed successfully" def main(): params = demisto.params() hostname = params["hostname"] port = int(params.get("port", "445")) user = params["credentials"]["identifier"] password = params["credentials"]["password"] encrypt = params.get("encrypt", False) dc = params.get("dc", None) verify = params.get("require_secure_negotiate", True) client_guid = params.get("client_guid", None) # Temporary workaround to an issue in the smbprotocol package. # Git issue: https://github.com/jborean93/smbprotocol/issues/109 config = smbclient.ClientConfig(username=user, password=password, require_secure_negotiate=verify) config.domain_controller = dc if client_guid: try: client_guid = uuid.UUID(client_guid) config.client_guid = client_guid except ValueError: demisto.info(f"Failed to convert {client_guid} to a valid UUID string. Using a random generated UUID instead") client = SMBClient(hostname=hostname, user=user, password=password, encrypt=encrypt, port=port) demisto.info(f"Command being called is {demisto.command()}") try: if demisto.command() == "test-module": return_results(test_module(client)) elif demisto.command() == "smb-download": return_results(smb_download(client, demisto.args())) elif demisto.command() == "smb-upload": return_results(smb_upload(client, demisto.args())) elif demisto.command() == "smb-directory-list": return_results(list_dir(client, demisto.args())) elif demisto.command() == "smb-file-remove": return_results(smb_remove_file(client, demisto.args())) elif demisto.command() == "smb-directory-create": return_results(smb_mkdir(client, demisto.args())) elif demisto.command() == "smb-directory-remove": return_results(smb_rmdir(client, demisto.args())) except Exception as e: return_error(f"Failed to execute {demisto.command()} command. Error: {e!s}") finally: smbclient.reset_connection_cache() if __name__ in ("__main__", "__builtin__", "builtins"): main()