When managing Linux systems, administrators often need to identify files accessible to specific users. The core challenge involves:
- Evaluating all permission combinations (user/group/other)
- Accounting for both explicit and inherited permissions
- Handling special cases like sticky bits and ACLs
Here's the most efficient one-liner to locate writable items for user username
under /path/to/directory
:
find /path/to/directory -exec \
sh -c 'test -w "$1" -o \
$(stat -c "%U" "$1") = "username" -o \
$(stat -c "%G" "$1") = "$(id -gn username)"' \
sh {} \; -print
The command works by:
- Using
find
to traverse the directory tree - Checking three possible write conditions via
test -w
andstat
:- Direct write permission via
-w
flag - Ownership match (
%U
) - Group membership (
%G
compared with user's primary group)
- Direct write permission via
For more complex scenarios:
1. Check non-writable files
find /path -exec \
sh -c '! test -w "$1" && \
[ "$(stat -c "%U" "$1")" != "username" ] && \
[ "$(stat -c "%G" "$1")" != "$(id -gn username)" ]' \
sh {} \; -print
2. Include ACL permissions
find /path -exec \
sh -c 'getfacl "$1" | grep -q "user:username:rw"' \
sh {} \; -print
For large directory trees, consider these optimizations:
- Add
-xdev
to prevent crossing filesystem boundaries - Use
-mount
instead of-xdev
for broader compatibility - Limit depth with
-maxdepth
where appropriate
Finding web directory files writable by www-data
:
find /var/www -exec \
sh -c 'test -w "$1" || \
[ "$(stat -c "%U" "$1")" = "www-data" ] || \
[ "$(stat -c "%G" "$1")" = "$(id -gn www-data)" ]' \
sh {} \; -print -ls
The -ls
flag provides detailed permission output for verification.
When managing Linux systems, a common administrative task is identifying filesystem objects accessible to specific users. The complexity arises because Linux permissions involve multiple layers:
- Direct user ownership (user is owner and has write bit)
- Group membership (user in group with write permission)
- World writable (others permission)
- Special cases (ACLs, capabilities, etc.)
Here's the most precise one-liner to solve this:
find /target/directory -type f -exec bash -c 'sudo -u target_user [ -w "$0" ] && echo "$0"' {} \;
For directories:
find /target/directory -type d -exec bash -c 'sudo -u target_user [ -w "$0" ] && echo "$0"' {} \;
For cases where sudo isn't available, we can analyze permissions directly:
find /target/directory $-perm -u=w -user target_user$ -o \
\( -perm -g=w -group $(id -gn target_user) \) -o \
$-perm -o=w$ -ls
Let's say we need to check which files user "deploy" can modify in /var/www:
#!/bin/bash
TARGET_USER="deploy"
SEARCH_DIR="/var/www"
echo "[+] Checking writable files for $TARGET_USER"
find "$SEARCH_DIR" -type f -exec bash -c \
'if sudo -u '"$TARGET_USER"' [ -w "$0" ]; then
ls -la "$0";
fi' {} \;
For comprehensive checks including ACLs:
getfacl -R /target/directory | grep -E "user:${TARGET_USER}:..w|group:.*:..w"
The sudo-based method is accurate but slow for large directories. For faster results:
find /target/directory -printf "%u:%g:%m %p\n" | awk -F: -v user="$TARGET_USER" \
'$1 == user && ($3 ~ /[2-7][0-7][2-7]/) || \
$2 == "'"$(id -gn "$TARGET_USER")"'" && ($3 ~ /[0-7][2-7][0-7]/) || \
$3 ~ /[0-7][0-7][2-7]/ {print $0}'