92 lines
2.3 KiB
C
92 lines
2.3 KiB
C
|
/*
|
||
|
* =====================================================================================
|
||
|
*
|
||
|
* 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 <vbatts@hashbangbash.com>
|
||
|
*
|
||
|
* =====================================================================================
|
||
|
*/
|
||
|
|
||
|
#define _XOPEN_SOURCE 500
|
||
|
#include <ftw.h>
|
||
|
|
||
|
#include <linux/limits.h>
|
||
|
#include <stdlib.h>
|
||
|
#include <stdint.h>
|
||
|
#include <stdio.h>
|
||
|
#include <string.h>
|
||
|
#include <sys/stat.h>
|
||
|
#include <sys/types.h>
|
||
|
#include <unistd.h>
|
||
|
#include <limits.h>
|
||
|
|
||
|
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;
|
||
|
}
|