/* * ===================================================================================== * * Filename: app.c * * Description: playing with finding writable files or directories on the host * * Version: 1.0 * Created: 10/20/2023 06:41:29 PM * Revision: none * Compiler: gcc * * Author: Vincent Batts * * ===================================================================================== */ #define _XOPEN_SOURCE 500 #include #include #include #include #include #include #include #include #include #include uid_t uid; gid_t gid; int ngroups; gid_t groups[NGROUPS_MAX]; int check_dir(const char *fpath, const struct stat *sb, int typeflag, struct FTW *ftwbuf) { int finding = 0; if (sb->st_uid != uid && sb->st_mode & S_IWOTH) finding |= 1; if (sb->st_uid != uid && sb->st_gid == gid && sb->st_mode & S_IWGRP) finding |= 2; for (int i = 0; i < ngroups; i++) { if (sb->st_uid != uid && sb->st_gid == groups[i] && sb->st_mode & S_IWGRP) finding |= 4; } if (typeflag == FTW_SLN || typeflag == FTW_SL) return 0; if (finding != 0) { printf("--> %s (m: %jo; t: %s; uid: %d; gid: %d)\n", fpath, (uintmax_t) sb->st_mode, (typeflag == FTW_D) ? "d" : (typeflag == FTW_F) ? "f" : (typeflag == FTW_SL) ? "sl" : (typeflag == FTW_SLN) ? "sln" : "???", sb->st_uid, sb->st_gid); if (finding&1) printf(" owned by another user and is world writable\n"); if (finding&2) printf(" owned by another user and is group writable by our group\n"); if (finding&4) printf(" owned by another user and is group writable by a group we are a member of\n"); } return EXIT_SUCCESS; } int main(int argc, char** argv) { uid = geteuid(); gid = getegid(); ngroups = getgroups(NGROUPS_MAX, groups); int flags = 0; flags |= FTW_PHYS; // don't follow symlinks for (int i = 1; i < argc; i++) { printf("arg[%d] %s\n", i, argv[i]); int ret; ret = nftw(argv[i], &check_dir, 1024, flags); if (ret != EXIT_SUCCESS) { printf("FAILURE walking %s\n", argv[i]); } } return EXIT_SUCCESS; }