3

For a series of targets (IPs), Id like to determine which SMB shares my account has no access to, which it has read access to, and which it has read/write access to.

Currently I am using smbclient. The command I run first is

smbclient -L [targetIP] -U [user] -p 445

This gives me a list of shares. For example;

        Sharename       Type      Comment
        ---------       ----      -------
        ADMIN$          Disk      Remote Admin
        C$              Disk      Default share
        IPC$            IPC       Remote IPC
        print$          Disk      Printer Drivers
        MySecrets       Disk

I then can connect to a file share with this command

smbclient //[target]/[name_of_share_from_list] -U [user] -p 445

Which results in an SMB prompt. From the prompt I type ls and if I see files I know I have read access. I'm guessing I have to push a file to see if I have write access.

This is tedious. How do I automate this such that for the given list of targets, I get a list of all shares, and the level of access my account has to them?

3 Answers 3

7
+50

You had much of the work already in place. Reading the man page for smbclient would have given you the -c <command> parameter, which can be used to provide one or more commands directly rather than interactively.

#!/bin/bash
username="DOMAIN\\USER"    # Double backslash
password="PASSWORD"        # For demonstration purposes only
hostname="TARGET_HOST"     # SMB hostname of target

cd "${TMPDIR:-/tmp}"
touch tmp_$$.tmp           # Required locally to copy to target

smbclient -L "$hostname" -g -A <( echo "username=$username"; echo "password=$password" ) 2>/dev/null |
    awk -F'|' '$1 == "Disk" {print $2}' |
    while IFS= read -r share
    do
        echo "Checking root of share '$share'"

        if smbclient "//$hostname/$share/" "$password" -U "$username" -c "dir" >/dev/null 2>&1
        then
            status=READ

            # Try uprating to read/write
            if smbclient "//$hostname/$share/" "$password" -U "$username" -c "put tmp_$$.tmp ; rm tmp_$$.tmp" >/dev/null 2>&1
            then
                status=WRITE
            fi
        else
            status=NONE
        fi

        case "$status" in
            READ) echo "Well, $username has read access" ;;
            WRITE) echo "Yes, $username has write access" ;;
            *) echo "No, $username has no access" ;;
        esac
    done

rm -f tmp_$$.tmp
12
  • Ah i was wondering if id have to resort to a bash script like this. I havent written one yet but this may give me a good starting point. Can you edit this to output if i have read access only?
    – n00b
    May 30, 2017 at 15:28
  • In addition to the check for write as well i mean
    – n00b
    May 30, 2017 at 15:29
  • @n00b. You could change the second echo putting the message "$username has read-only access to the root of this share". Unless you are also scanning directories that you have no read access at all...
    – user34720
    May 30, 2017 at 20:16
  • The later is the case. I dont know if I have read access, and would rather have the option to 'try writing' after knowing if I have read access first. In otherwords, tell me if I have read first, then tell me if I have write. Is that possible?
    – n00b
    May 30, 2017 at 21:06
  • 1
    @roaima I did. I saved it in a script.sh file, ran the chmod 755 script.sh command then am trying to execute ./script.sh but it just sits and sits. I added echo 'breadcrumbs' and the echos execute up until the smbclient line
    – n00b
    Jul 5, 2017 at 21:14
3

Maybe SMBmap can help you with this tastk. Its author developed it precisely for that purpose.

$  python smbmap.py -H [targetIP] -u [user] -P 445
[+] Finding open SMB ports....
[+] User SMB session establishd...
[+] IP: 192.168.0.4:445 Name: 192.168.0.4
        Disk                                                    Permissions
        ----                                                    -----------
        ADMIN$                                                  READ, WRITE
        C$                                                      READ, WRITE
        IPC$                                                    NO ACCESS
        TMPSHARE                                                READ, WRITE     

You can use --host-file to pass a list of targets.

Internally, it tries to create a directory with a random name to check if we have write permissions.

0

Same approach as accepted answer but using ansible. This can then be used for mounting as read-only or read-write. (Which then makes other tools such as mergerfs work as expected when a union of filesystems is created)

- name: get available samba shares
  ansible.builtin.shell:
    cmd: "smbclient -L //{{ samba_ip }} -U % -g | grep Disk"
  register: samba_shares_raw

- name: extract samba shares
  ansible.builtin.set_fact:
    samba_shares: "{{ (samba_shares | default([])) + [ ( item | split('|') )[1] ] }}"
  loop: "{{ samba_shares_raw.stdout_lines }}"

- name: send a file to test ro / rw access
  ansible.builtin.file:
    path: "{{ ansible_env.HOME }}/samba_client"
    state: touch

- name: test writeable samba
  ansible.builtin.shell:
    cmd: "smbclient -U % //{{ samba_ip }}/{{ item }} -c 'put samba_client'"
    chdir: "{{ ansible_env.HOME }}"
  register: writeable_raw
  ignore_errors: true
  loop: "{{ samba_shares }}"

- name: extract writeable results
  ansible.builtin.set_fact:
    writeable: "{{ writeable | default({}) | combine({ item.item : not item.failed }) }}"
  loop: "{{ writeable_raw.results }}"
  loop_control:
    label: "{{ item.item }}"

- name: samba mount directories
  ansible.builtin.file:
    state: directory
    recurse: true
    path: "{{ ansible_env.HOME }}/samba/{{ item }}"
  loop: "{{ samba_shares }}"

- name: mount samba shares
  ansible.posix.mount:
    src: "//{{ samba_ip }}/{{ item }}"
    path: "{{ ansible_env.HOME }}/samba/{{ item }}"
    fstype: cifs
    opts: "{{ 'rw' if writeable[item] else 'ro' }},guest,uid=1000,gid=1000"
    state: mounted
  loop: "{{ samba_shares }}"
  become: true

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .