The find command is one of the more useful tools when working in the CLI-Interface of Linux. It is used for searching data and folders distributed across the file system. It is invaluable for solving ctf-challenges.
The find command uses the simple syntax:
find [where to look] [what to find]
We first tell the system to search, then where to search and then, right at the end, what to search.
The “find” command uses the following flags to specify the “where” and the “what”. Both specifications (where & what) are allowing the usage of wildcards (*)!
Where to look:
Without specifying a search location, find always searches in the current working directory (in the current pwd!). Furthermore, it always searches recursively (It does include subfolders!).
Simply insert the path of a folder if you know where to look for. If you want to search the whole filesystem you can simply use the “/”-option.
NOTE: If you´re searching the whole filesystem you´ll most likely get a ton of error-messages. Especially in ctf´s when you don´t have the necessary permissions to conduct a full search.
What to find:
-type – This comes with two parameters: f specifies that were looking for a file, d specifies that were looking for a directory
-name – This Tag allows us to specify the pattern we´re looking for. ATTENTION: The searching pattern specified right behind this Tag has to be in “quotation marks”! Otherwise the search won’t work. The search is case-sensitive.
-iname – This Tag works like the Tag -name above, -iname is case-insensitive though.
Example: Find all files with the extension “.xml” on your computer:
$ find / -type f -name "*.xml"
The above covers already the most common things to know about find. It´ll be sufficient for the most usecases, even though find is more versatile than that.
More tags, and refined searching queries:
Sometimes it is not enough just to know the name and the type of a file. One can search for the following:
The Owner of a file – this is specified by using the “-user” flag, followed by the Name of the desired User.
The File size – this is specified by using “-size”, accompanied by the numbers corresponding to the file size. This differentiaties between +n, -n and n – with “n” being an integer.
+n –> the value / file size is bigger than n ;
-n –> the value / file size is smaller than n ;
n –> the file size is exactly n .
This operation also needs a suffix to tell “find” which size-unit we`re specifying inside our search query!
c is the suffix for bytes
k is the suffix for KiB
m is the suffix for MiB.
This sounds complicated first. But the following example will clarify:
A file smaller than 30 bytes is searched for with “-size -30 c
“.
A file bigger than 20 MiB is searched for with “size +20m
“
File Permissions – this is specified by using “-perm“.
Can be specified either by using the octal numbers’s (e.g. 644), or with the corresponding permission characters.
f.e.: -perm u=r
(looking for files with user permission = read)
The characters for the owner and group permissions are as following: uid = u, gid = g, others= o, all = a
The characters for the file permissions are: Reading permission = r, Writing permission = w, executable = x, suid-bit set = s
But the above query only returns the files or directories that exactly matches the specified permissions. To change that you can conduct a less specific search operation by using the “-“ or “/” operators.
So, the “–” operator will return all files for which we have AT LEAST the specified permission set. (f.e. “-perm -444
” will also return files that match the “-perm 777
“-query as 777 means that everyone can read/write/execute a file).
The “/” operator on the other hand returns all files for which at least one permission matches our search criterion. –> /666 returns all files where at least one permission allows reading and writing. No matter if it is allowed for the user, a group, or others.
If you have problems with permissions i recommend you to have a look at this webpage as i found it to be really understandable: https://linuxize.com/post/what-does-chmod-777-mean/
The last time a File was Accessed / Modified – Unlike above, the keyword for this searching operation does vary – depending on what youre looking for. It consists of two components:
A word and a prefix. –> the words are “min” for Minutes and “time” for Days.
The prefixes are a, m and c for: When were the files were last accessed (a), modified (m) or status-changed (c). For the values we´re setting here the same rules apply as with the file size above +, – and exactly on the point (At least we don´t have a suffix here!).
Examples: To indicate that a searched file was last accessed more than 30 minutes ago our search term is: -amin +30
To indicate that the last change was less than 7 days ago we would use instead: -mtime -7
(Note: If a file has been modified within the last 24 hours we use -mtime 0
. It has been edited within the last day).
The last term you need to know is: -exec
-exec allows us to execute other commands directly after our search – f.e. -exec whoami \;
Finally, you should know that you can use the redirect operator (>) together with find. This way you can save your search results and make them more readable by redirecting error messages to nirvana. You can block the stderr by putting 2> /dev/null at the end of the search query. –> This way you don’t see any error messages for directories you can’t access.
Thats it. You need another example? 🙂
$ find / -type f -a ( -perm -u+s -o -perm -g+s ) -exec ls -l {} \; 2> /dev/null
The above command is one to keep. It´s looking for files with the suid-bit set. Very handy if you are looking for Privilege Escalation Vectors.