The macosxhints Forums

The macosxhints Forums (http://hintsforums.macworld.com/index.php)
-   UNIX - General (http://hintsforums.macworld.com/forumdisplay.php?f=16)
-   -   looking to clean up unwanted local user accounts (http://hintsforums.macworld.com/showthread.php?t=96402)

tlarkin 12-02-2008 11:32 AM

looking to clean up unwanted local user accounts
 
Everyone,

So, I have a bit of a conundrum. There has been some discussion of unwanted local user accounts and a way to delete them.

So, I am looking at looping a script but my scripting skills are lacking on this one. My local admin accounts are not in /Users, but in other directories so they will be safe. I also have one local account I don't want touched. I know this won't fix every one of my problems but I would like to attempt at doing it.

So, standard users formula has numbers, then it has their abbr. name. The number represents their grad year.

So, I would like to run a script that will exclude any local user account under /Users that starts with a number, and also exclude the one local student account that I have set up. Every other local account it finds is user created and should not be on the machines, and should be deleted.

Please excuse my noob question and if I am unclear. I am on benadryl today and antihistamines make me very loopy. I was thinking of something like this

Code:

#!/bin/sh

for i in /Users

user='<wild card search /Users but leave those that start with a number>

do

if <user does not start with a number>

    then dscl . -delete /Users/$user

fi

done

Any help or point in the right direction would be super awesome. Thanks in advance.

baf 12-02-2008 02:06 PM

Code:

#! /bin/bash

keep="that extra account"

cd /Users

for a in [^0-9]* ; do # only loop over names that doesnt start with a number
    [[ "$a" == "$keep" ]] && continue # skip that extra local account
    dscl ...... $a # do something to it
done

And you will have to checkup on dscl I think it only removes the account not its files.

tlarkin 12-02-2008 03:35 PM

Baf

Thank you so much! Too bad it would be ungodly expensive to fed ex you a beer or I'd do it!

So, I think I was using the wrong looping method, which doesn't shock me. I think I am starting to grasp looping methods

Here is what I came up with, as an example.

Code:

#! /bin/sh

keep="student"

cd /Users

for a in [^0-9]* ; do # only loop over names that doesnt start with a number
    [[ "$a" == "$keep" ]] && continue # skip that extra local account
    /usr/bin/dscl . -delete /Users/$a # do something to it

echo 'removing user files'

/bin/rm -rf /Users/$a

done

I am not sure how drastic that would be ...

So my script, as far as I can tell, will delete every single thing with the exception of what starts with a number or is the 'student' account.

baf 12-02-2008 04:02 PM

Yes that looks pretty good but it contains one bad thing.

On many(most) systems sh really is bash so it doesn't matter which you use on the first line. But if you try to run that on a system where sh really is sh it won't work. [[ is a bashism and only works under bash so I would recommend you to change the first line to:
#! /bin/bash
Then it's clear that the script needs and uses bash.

Also for a "dangerous" script like that I would consider adding a check that the cd really worked. Something like

cd /Users
[[ $(pwd) != "/Users" ]] && echo warning cd failed && exit 2

Would make me feel comfortable. Remember "You can't be to paranoid" and "Even paranoids have enemies"

tlarkin 12-02-2008 04:24 PM

Yes great ideas.

As for the shebang, and I could be wrong on this, but I was told the main difference between using /bin/bash and /bin/sh is that /bin/sh always ran as root. I was told this by an engineer at a training seminar I went to a while ago.

Looking at them in terminal they look almost identical except for a strange difference in permissoins

Code:

tlarkin$ ls -al /bin/sh /bin/bash
-rwxr-xr-x  1 root  wheel  1244928 Mar  4  2008 /bin/bash
-r-xr-xr-x  1 root  wheel  1244960 Mar  4  2008 /bin/sh

Then google tells me that /bin/sh is completely POSIX compliant so it should work on any system that supports POSIX? Then reading through hayne's Unix FAQ and some apple discussion boards it seems if you do a md5 dump on the shells they are indeed different but they reflect the same version?

I am confused:confused:

I agree on the if then clause though, if checks out then proceed if not exit that way nothing drastic happens. Of course I will test it out 40 times on my test machine before I put it out in production.

Thanks again!

baf 12-02-2008 04:46 PM

Quote:

As for the shebang, and I could be wrong on this, but I was told the main difference between using /bin/bash and /bin/sh is that /bin/sh always ran as root. I was told this by an engineer at a training seminar I went to a while ago.
Yes thats completely wrong see proof below.

Code:

baf@pub98-178 ~
$ /bin/sh -c id
uid=501(baf) gid=501(baf) groups=501(baf),98(_lpadmin),80(admin)

baf@pub98-178 ~
$ sudo /bin/sh -c id
uid=0(root) gid=0(wheel) groups=0(wheel),1(daemon),2(kmem),8(procview),29(certusers),3(sys),9(procmod),4(tty),5(operator),80(admin),20(staff)

Quote:

Then google tells me that /bin/sh is completely POSIX compliant so it should work on any system that supports POSIX?
Yes /bin/sh is POSIX compliant which means that it can do everything it must. But that doesnt mean that it can't do more and that another sh might choke on its input. Or in other words "Is your script POSIX compliant?".

The permission diff doesn't matter at all.

And here is proof that /bin/sh really is a bash
Code:

baf@pub98-178 ~
$ /bin/sh -c set
BASH=/bin/sh
BASH_VERSINFO=([0]="3" [1]="2" [2]="17" [3]="1" [4]="release" [5]="i386-apple-darwin9.0")
BASH_VERSION='3.2.17(1)-release'


baf 12-02-2008 05:05 PM

Quote:

Originally Posted by tlarkin (Post 506254)
As for the shebang, and I could be wrong on this, but I was told the main difference between using /bin/bash and /bin/sh is that /bin/sh always ran as root. I was told this by an engineer at a training seminar I went to a while ago.

What he might have meant is that on some system bash is not installed as default or might be somewhere in /usr which might not be available during boot or in single user mode. So the statement works if its "/bin/sh always works for root"

tlarkin 12-02-2008 05:14 PM

OK great stuff

You got any links on advanced scripting tutorials? Should I just go take a Unix programming class? Do they even offer such classes?

What do the double [[ and && stand for? You know I want to know stuff like that.

I get basic scripting but when it gets into more a programming language I kind of start to lose my grasp on everything.

Thanks again!

baf 12-02-2008 05:37 PM

Well now you start with the tough questions.

if you use [ you will use a simpler test mechanism see man test.
if you use [[ you use bash's full inbuilt test which knows more things (I think).
from man bash:
Quote:

[[ expression ]]
Return a status of 0 or 1 depending on the evaluation of the conditional expression expression. Expressions are composed of
the primaries described below under CONDITIONAL EXPRESSIONS. Word splitting and pathname expansion are not performed on the
words between the [[ and ]]; tilde expansion, parameter and variable expansion, arithmetic expansion, command substitution,
process substitution, and quote removal are performed. Conditional operators such as -f must be unquoted to be recognized as
primaries.

for && from man bash
Quote:

The control operators && and || denote AND lists and OR lists, respectively. An AND list has the form

command1 && command2

command2 is executed if, and only if, command1 returns an exit status of zero.
And for advanced scripting I don't really have any good links. Ah I remembered one now "Advanced bash scripting" That one is pretty good. One thing that really helps but can be really boring is to print the bash manual and really read it. You can skip the parts of how to program readline completion and such.

biovizier 12-02-2008 05:37 PM

Shouldn't
Code:

/bin/rm -rf /Users/*
be
Code:

/bin/rm -rf /Users/$a
?

I may be reading it wrong, but I don't think '/Users/*' is what you want to wipe out.

Likewise with the 'dscl', but that one might just error out...

baf 12-02-2008 05:48 PM

Quote:

Originally Posted by biovizier (Post 506264)
Shouldn't
Code:

/bin/rm -rf /Users/*
be
Code:

/bin/rm -rf /Users/$a
?

wups you are completely right.

Hal Itosis 12-02-2008 06:11 PM

Quote:

Originally Posted by baf (Post 506260)
What he might have meant is that on some system bash is not installed as default or might be somewhere in /usr which might not be available during boot or in single user mode. So the statement works if its "/bin/sh always works for root"

Agreed... [ "sh always runs as root" -ne "sh is the default shell for root" ]
Code:

$ dscl . -list /Users UserShell |grep -v false
_uucp                /usr/sbin/uucico
halito                /bin/bash
user2                /bin/bash
user3                /bin/bash
root                /bin/sh


hayne 12-02-2008 06:33 PM

Quote:

Originally Posted by baf
Quote:

Originally Posted by tlarkin (Post 506254)
As for the shebang, and I could be wrong on this, but I was told the main difference between using /bin/bash and /bin/sh is that /bin/sh always ran as root. I was told this by an engineer at a training seminar I went to a while ago.

What he might have meant is that on some system bash is not installed as default or might be somewhere in /usr which might not be available during boot or in single user mode.

No - I think what he meant was "I don't know the difference, but I'll make up something so I don't have to admit that I don't know".

baf 12-02-2008 06:40 PM

Hehe I like that one.

tlarkin 12-02-2008 06:56 PM

Quote:

Originally Posted by biovizier (Post 506264)
Shouldn't
Code:

/bin/rm -rf /Users/*
be
Code:

/bin/rm -rf /Users/$a
?

I may be reading it wrong, but I don't think '/Users/*' is what you want to wipe out.

Likewise with the 'dscl', but that one might just error out...

Hmm, OK, I thought I was wiping everything out, hence the *, but keeping the variables of $a and $keep. Is that not the case?

I modified the script to how you said it should be.

tlarkin 12-02-2008 06:59 PM

Quote:

Originally Posted by hayne (Post 506277)
No - I think what he meant was "I don't know the difference, but I'll make up something so I don't have to admit that I don't know".

Actually, I guess that does make sense now because the training class in particular I was at was with JAMF software. Their binary does run root level stuff at start up before the OS loads and before anyone logs in if you want it to, so their scripts are probably all /bin/sh since no user environment is loaded at that point in time.

I have a policy trigger at start up and it will load when the OS starts up, and the JAMF binary is a launchd item.

I just don't know the differences that well and am pretty much regurgitating what I heard, and I am not even quoting the guy verbatim because that was a long time ago to remember exactly how he explained it.

However, I do know the /bin/bash is the default shell for users in OS X 10.5, but all my scripts I use /bin/sh and have never had a problem.

baf 12-02-2008 07:01 PM

Well $a is the directory under consideration. And it's that user and their home directory you want to remove. Not everything under /Users.

tlarkin 12-02-2008 07:06 PM

Quote:

Originally Posted by baf (Post 506286)
Well $a is the directory under consideration. And it's that user and their home directory you want to remove. Not everything under /Users.

No, it is everything under users but user accounts that start with a number and the one local account we made to put on there. The problem is I am under staffed and have to support 6,000 laptops, 3,000 desktops and like 40 servers and there are literally 5 of us that do the work.

I am trying to consolidate everything to make it more streamlined and simple for all of us. So, I want /Users completely wiped except for any user account that starts with a number (our user formula here at work we use for PHDs) and that one local account just in case a PHD can't sync for whatever reason the user can still log in and use the computer.

I have no idea how many user accounts have been created that are old, not used, named something ridiculous or break AUP contracts. Therefore, I want to kill everything under /Users except for what I know what is suppose to be there.

Local administration accounts are not in /Users so they shouldn't be touched. However, now that I think about it though, they do show up in /Users when using dscl, so this may not work at all.

Like dscl . list /Users lists all users on the computer regardless of where their home directory lives.

tlarkin 12-09-2008 02:59 PM

Well, anyone have any other suggestions. It seems that some users (when an older password was leaked) promoted their accounts to admin accounts and we want to demote them or delete them and have them resync.

Also, before the standardization there were others who created local accounts that we don't want on these machines.

Any thoughts on how I can demote/delete all unwanted accounts on the machines locally?

Baf

Thanks for that link I am going to start going through that stuff this week and I am off for winter break soon and I will probably spend some of it geeking it up and learning some more shell scripting. Everything I do I try to do it in the GUI so I can train everyone else I work with on how to do certain tasks but then things like this come up. I am a scripting neophyte but I am learning as I go. Thanks for your help, it is appreciated.

Hal Itosis 12-09-2008 03:43 PM

Quote:

Originally Posted by tlarkin (Post 507593)
It seems that some users (when an older password was leaked) promoted their accounts to admin accounts and we want to demote them or delete them and have them resync.

For a start on unwanted "promotions", look at the
admin group listing to see if further action is needed:
dscl . -read /Groups/admin GroupMembership

If a lot of usernames show up there which don't belong, and
it's so extensive that manual removal would be too tedious,
then some scripted method could be contrived.

Might also want to check the wheel group:
dscl . -read /Groups/wheel GroupMembership
[its only member should be root]

tlarkin 12-09-2008 04:15 PM

Hal

Thanks for your help, and I was looking into the groupmembership option with dscl actually right after I posted it. I think, I can do something like this, probably loop it out for every account in /Users, since by my design of the OS X image, no admin account should ever exist in /Users

maybe something like this, and granted I am just learning how to code loops

Code:

#!/bin/bash

for -i in /Users

do

dscl . delete /Groups/admin GroupMembership $User

done

I am sure my code is off but I just need to delete the short name from the group membership on that machine locally and it should do the trick. Now, if someone got creative and moved their home directory to a non standard location (which I highly doubt) then I guess they win for now, lol.

baf 12-09-2008 04:31 PM

You must also check every file on every computer for unwanted suid binaries.

something like: (this one only check /usr/bin)
Code:

$ find /usr/bin -perm +7000 -exec ls -l {} \;
-r-sr-xr-x  4 root  wheel  69552 Jul 31 07:51 /usr/bin/at
-r-xr-sr-x  1 root  procview  64368 Jun 27 14:10 /usr/bin/atos
snip...

Dangerous things here are an s in the first triplet and owner root
or an s in the second triplet and group admin. If you don't clean those out then your back on square one again.

So basically you should get a list of those suid commands from a clean machine then compare that with the other machines list. But if your users are savvy enough then thats no help either. Ever heard of a root kit?

tlarkin 12-09-2008 04:48 PM

Everything gets reimaged once a year so I am not worried and my servers are secured and no one has access to those but the few that need access to them.

I highly doubt any user moved their home directory, I could maybe see a root kit, but I doubt that as well. They are mostly concerned with getting video games on the computers than anything else. I walked into an unmanaged iMac lab about a month ago, and saw that every computer had Halo installed. While I could honestly care less what the users do with their computers as long as they don't abuse the machines physically (it is not may job to manage them as people), other people don't want them playing video games.

It all started from the smallest little over sight of my department too, and before we cold contain it, every user knew what was going on. Some standards I did managed to set up this year were as follows

All local admin accounts live in /private/var

All approved local managed accounts start with a number (that formula has been here since before me, but we still use it).

All applications are owned by root and part of the admin group, users can read and execute but not write, everything in /Applications/utiltiies is off limits via WGM group policy

I created nested groups of users and enforce group policy over MCX for lots of things so I don't need to over kill the local policies on the machine.

The only thing I could think of that may be an actual reality is a key logger, and perhaps that is how they snaked some of the passwords in the past. Well, that and there are some people in my department that have written passwords on sticky notes, and I hate that, but I have no power over it.

What I do have power over, and have proved this three times now, is that I can massively change passwords pretty darn fast.

Hal Itosis 12-09-2008 06:01 PM

Quote:

Originally Posted by tlarkin (Post 507620)
#!/bin/bash
for -i in /Users
do
dscl . delete /Groups/admin GroupMembership $User
done

for -i in /Users returns: -bash: `-i': not a valid identifier
for i in /Users returns just: "/Users"

You probably meant to have: for i in /Users/*
[and even that will run "/Users/Shared" through the mill.]

Also... dscl . delete /Groups/admin GroupMembership $User
was probably intended as: dscl . -delete /Groups/admin GroupMembership "$i"

--

Test loops and script lines with harmless things like ls or echo
For testing, we can even have echo entire commands (most times):
Code:

for i in `ls /Users`
do
        [[ $i = Shared ]] ||
        echo dscl . -delete /Groups/admin GroupMembership "$i"
done

...should just echo the "dscl" commands onscreen... not actually call dscl.
[there are limits to that trick, so... fair warning]
Anyway, without the red echo that version might fly.

Nope... needs fixing... hang on.
There... didn't really want full pathnames, just usernames.

--

More fun: running any script as root will turn every ls into ls -A
meaning .DS_Store or .localized or any "dot" files (except . and ..) will also get assigned to $i
<sigh>
Change the first line to
Code:

cd /Users && for i in *
And stop asking so many questions. :D

tlarkin 12-10-2008 05:11 PM

Hal

Thanks man, and well I am asking because I don't know and there are smart people like you to give me answers. :D

I am a bit confused on how the local database for OD on a client machine and the LDAP DB on the server side talk to each other. When I run inventory reports with our Casper Suite it shows users flagged as Admin accounts, which at first I thought they were logging and simply flagging their mobile accounts to admin their computer, which you can do to mobile accounts. Apparently, it will allow a mobile user to admin just that computer and not any other machine, so it should technically flag the local DB that account is in group 20 for staff (everyone is in staff) plus group 80 (admin group) but not an admin from the LDAP.

There is a lot of confusion on my part on how exactly this works. After some testing it seems no matter what local group I put a user in (I can even toss them in wheel) group policy from OD trumps it via MCX. As a test I synchronized a test account of mine that is modeled for a student, same policies. Once I sync'd the account I logged in as local admin and promoted that account to admin of that machine. To verify it was in the admin group I did a dscl . read /Groups/admin and sure enough my test account was listed. When I run the id command on it, it doesn't list the admin group at all, only the staff group and whatever group it is tied to in Open Directory. So all group policy applies. I think the downside is, now that the account is promoted they can probably somehow root the system with their credentials since technically they are listed as a local admin account. They can also drag unapproved apps into the apps folder and run them, which is the main concern from the Administration and Education side, they don't want the users playing video games all day.

So, next thing I did after promoting the account to admin is I tried to delete that user from the /Groups/admin from dscl. After removing it from the /Groups/admin the account could no longer install software with it's credentials when it asked for an admin password. So, in theory all of this works. I was just a bit confused on how Leopard managed local and network/mobile accounts from the client to the server and I had to do some testing today to answer those questions.

Thanks again, this script should come in real handy on cleaning up un wanted local user accounts that exist in /Users. It will also take out any user that has promoted their own account via dscl . delete /Groups/admin GroupMembership <shortname> I appreciate all of you guys helping on this one.

Looks like I am going to have to lock the image down a bit tighter for next school year. Kids are smarter than i thought, well some of them at least.

Hal Itosis 12-11-2008 06:43 PM

Quote:

Originally Posted by tlarkin (Post 507883)
I am a bit confused on how the local database for OD on a client machine and the LDAP DB on the server side talk to each other. When I run inventory reports with our Casper Suite it shows users flagged as Admin accounts, which at first I thought they were logging and simply flagging their mobile accounts to admin their computer, which you can do to mobile accounts. [ . . . ]

I'm not familiar with (any actual hands-on usage of) OD, LDAP or Casper.
As far as those three go, i must bow out to your (and others') experience.

tlarkin 12-12-2008 09:44 AM

Quote:

Originally Posted by Hal Itosis (Post 508109)
I'm not familiar with (any actual hands-on usage of) OD, LDAP or Casper.
As far as those three go, i must bow out to your (and others') experience.

I confirmed from testing that if a mobile account is promoted to admin, MCX and group policy still trump it, since on the directory their user account is only a member of staff. However, their account can authenticate locally to run admin rights on that machine locally since it was promoted to admin via the check box in System Preferences >> Accounts.

So, even though if the user did promote them self via an old user account we were unaware of (from previous people managing them) they are still restricted to group policy, which I have nailed down pretty tight. The only exception is a user who may know a thing or two about terminal commands and could (with admin rights) basically root the machine and/or physically change their particular machine to a different group or many other things that can be done from the command line. 99% of my users don't know the first thing about the command line, however there are a few smart ones out there that have probably done a few things.

As for the Casper Inventory flagging the user twice, once with admin rights no one knows why that is happening and I uploaded my inventory DB to Jamf support so they could look at it.

tlarkin 02-13-2009 11:32 AM

Not to revive an old thread but I thought I'd give an update

I found the cause of the password leaks, and it was totally do to some people using a wrong image that had known passwords on it. I know what account it is and I know what it used to be and I set up a simple casper policy that is on going and hits every machine and deletes that one account.

Then I have a script that removes all users from /Users from the admin group via dscl, since no user in /Users should ever be an admin and we put our hidden local admin accounts in /private/var.

Thanks for everyone's help on this. It took me a while to track it down but when running reports on certain machines I noticed that they didn't have windows installed on them, and all of our clients dual boot. Then that immediately told me it wasn't imaged properly, since our netboot imaging process is automated and if you image any macbook you are getting windows via the automation I set up in the auto run data in Casper.

So, every machine also doesn't have windows installed on it which has that old account on that old image that the users know the password for and use it to gain admin rights. The persons using the wrong image have been told to never use that image (and I don't even know why I kept it around, I SHOULD HAVE DELETED IT, lesson learned). Sort of my fault I suppose.

Now I have a script that detects NTFS partitions and if there isn't one a dummy package is installed via Casper and then I create smart groups of the policy receipts to get a full list of machines that need to be reimaged.

Please everyone who reads this, learn from my mistake. Eradicate all of your old images, especially ones that contain accounts that are known to many people.

tlarkin 08-31-2009 02:33 PM

Man this thread is old but this is how I did it....

Code:

#!/bin/bash

for a in `ls /Users | sed -E` ; do

admincheck=`dscl . read /Groups/admin | grep $a -c`

if [ $admincheck = 1 ]

then echo "$a is in admin group"

else echo "$a is NOT in admin group"

fi

done
exit 0

I changed the echo statements to invoke the dscl commands, but that is proof of the concept of what I used.


All times are GMT -5. The time now is 05:45 PM.

Powered by vBulletin® Version 3.8.7
Copyright ©2000 - 2014, vBulletin Solutions, Inc.
Site design © IDG Consumer & SMB; individuals retain copyright of their postings
but consent to the possible use of their material in other areas of IDG Consumer & SMB.