Guest User

Untitled

a guest
Apr 17th, 2018
228
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 40.76 KB | None | 0 0
  1. #!/bin/sh
  2. # unix-privesc-check - Checks Unix system for simple privilege escalations
  3. # Copyright (C) 2008 [email protected]
  4. # Copyright (C) 2009 [email protected]
  5. #
  6. #
  7. # License
  8. # -------
  9. # This tool may be used for legal purposes only. Users take full responsibility
  10. # for any actions performed using this tool. The author accepts no liability
  11. # for damage caused by this tool. If you do not accept these condition then
  12. # you are prohibited from using this tool.
  13. #
  14. # In all other respects the GPL version 2 applies:
  15. #
  16. # This program is free software; you can redistribute it and/or modify
  17. # it under the terms of the GNU General Public License version 2 as
  18. # published by the Free Software Foundation.
  19. #
  20. # This program is distributed in the hope that it will be useful,
  21. # but WITHOUT ANY WARRANTY; without even the implied warranty of
  22. # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  23. # GNU General Public License for more details.
  24. #
  25. # You should have received a copy of the GNU General Public License along
  26. # with this program; if not, write to the Free Software Foundation, Inc.,
  27. # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  28. #
  29. # You are encouraged to send comments, improvements or suggestions to
  30. #
  31. #
  32. # Description
  33. # -----------
  34. # Auditing tool to check for weak file permissions and other problems that
  35. # may allow local attackers to escalate privileges.
  36. #
  37. # It is intended to be run by security auditors and penetration testers
  38. # against systems they have been engaged to assess, and also by system
  39. # administrators who want to check for "obvious" misconfigurations. It
  40. # can even be run as a cron job so you can check regularly for misconfigurations
  41. # that might be introduced.
  42. #
  43. # Ensure that you have the appropriate legal permission before running it
  44. # someone else's system.
  45. #
  46. # TODO List
  47. # ---------
  48. # There's still plenty that this script doesn't do...
  49. # - Doesn't work for shell scripts! These appear as "/bin/sh my.sh" in the process listing.
  50. # This script only checks the perms of /bin/sh. Not what we're after. :-(
  51. # - Similarly for perl scripts. Probably python, etc. too.
  52. # - Check /proc/pid/cmdline for absolute path names. Check security of these (e.g. /etc/snmp/snmpd.conf)
  53. # - Check everything in root's path - how to find root's path?
  54. # - /proc/pid/maps, smaps are readable and lists some shared objects. We should check these.
  55. # - AIX/Solaris executable stack
  56. # - How about checking for SELinux
  57. # - Is firewall DMA enabled?
  58. # - Loadable kernel modules?
  59. # - /proc/pid/fd contain symlinks to all open files (but you can't see other people FDs)
  60. # - check for trust relationships in /etc/hosts.equiv
  61. # - NFS imports / exports / automounter
  62. # - Insecure stuff in /etc/fstab (e.g. allowing users to mount file systems)
  63. # - Inspecting people's PATH. tricky. maybe read from /proc/pid/environ, .bashrc, /etc/profile, .bash_profile
  64. # - Check if /etc/init.d/* scripts are readable. Advise user to audit them if they are.
  65. # - .exrc? (partial support added)
  66. # - X11 trusts, apache passwd files, mysql trusts?
  67. # - Daemons configured in an insecure way: tftpd, sadmind, rexd
  68. # - World writable dirs aren't as bad if the sticky bit is set. Check for this before reporting vulns.
  69. # - Maybe do a strings of binaries (and their .so's?)
  70. # - Do a better job of parsing cron lines - search for full paths
  71. # - Maybe LDPATHs from /etc/env.d
  72. # - Check if ldd, ld.so.conf changes have broken this script on non-linux systems.
  73. # - ld.so.conf has an equivelent at least on Solaris
  74. # - Avoid check certain paths e.g. /-/_ clearly isn't a real directory.
  75. # - create some sort of readable report
  76. # - indicate when it's likely a result is a false positive and when it's not.
  77. # - Skip pseudo processes e.g. [usb-storage]
  78. # - File permission on kernel modules
  79. # - Replace calls to echo with a my_echo func. Should be passed a string and an "importance" value:
  80. # - my_echo 1 "This is important and should always be printed out"
  81. # - my_echo 2 "This is less important and should only be printed in verbose mode"
  82. # - We check some files / dirs multiple times. Slow. Can we implement a cache?
  83. # - grep for PRIVATE KEY to find private ssh and ssl keys. Where to grep?
  84. # - check SGID programs
  85. # - Get rid of the awk, command-to-parse-output-from | while read parta partb partc is much better
  86. # - HPUX TCB?
  87.  
  88. VERSION="1.5"
  89. HOME_DIR_FILES=".exrc .netrc .ssh/id_rsa .ssh/id_dsa .rhosts .shosts .my.cnf .ssh/authorized_keys .bash_history .sh_history .forward"
  90. CONFIG_FILES="/etc/passwd /etc/group /etc/master.passwd /etc/inittab /etc/inetd.conf /etc/xinetd.con /etc/xinetd.d/* /etc/contab /etc/fstab /etc/profile /etc/sudoers /etc/hosts.equiv /etc/shosts.equiv"
  91. PGDIRS="/usr/local/pgsql/data ~postgres/postgresql/data ~postgres/data ~pgsql/data ~pgsql/pgsql/data /var/lib/postgresql/data /etc/postgresql/8.2/main /var/lib/pgsql/data"
  92.  
  93. get_owner () {
  94. GET_OWNER_FILE=$1
  95. GET_OWNER_RETURN=`ls -lLd "$GET_OWNER_FILE" | awk '{print $3}'`
  96. }
  97.  
  98. get_group () {
  99. GET_GROUP_FILE=$1
  100. GET_GROUP_RETURN=`ls -lLd "$GET_GROUP_FILE" | awk '{print $4}'`
  101. }
  102.  
  103. usage () {
  104. echo "unix-privesc-check v$VERSION ( http://pentestmonkey.net/tools/unix-privesc-check )"
  105. echo
  106. echo "Usage: unix-privesc-check { standard | detailed }"
  107. echo
  108. echo '"standard" mode: Speed-optimised check of lots of security settings.'
  109. echo
  110. echo '"detailed" mode: Same as standard mode, but also checks perms of open file'
  111. echo ' handles and called files (e.g. parsed from shell scripts,'
  112. echo ' linked .so files). This mode is slow and prone to false '
  113. echo ' positives but might help you find more subtle flaws in 3rd'
  114. echo ' party programs.'
  115. echo
  116. echo "This script checks file permissions and other settings that could allow"
  117. echo "local users to escalate privileges."
  118. echo
  119. echo "Use of this script is only permitted on systems which you have been granted"
  120. echo "legal permission to perform a security assessment of. Apart from this "
  121. echo "condition the GPL v2 applies."
  122. echo
  123. echo "Search the output for the word 'WARNING'. If you don't see it then this"
  124. echo "script didn't find any problems."
  125. echo
  126. }
  127.  
  128. banner () {
  129. echo "Starting unix-privesc-check v$VERSION ( http://pentestmonkey.net/tools/unix-privesc-check )"
  130. echo
  131. echo "This script checks file permissions and other settings that could allow"
  132. echo "local users to escalate privileges."
  133. echo
  134. echo "Use of this script is only permitted on systems which you have been granted"
  135. echo "legal permission to perform a security assessment of. Apart from this "
  136. echo "condition the GPL v2 applies."
  137. echo
  138. echo "Search the output below for the word 'WARNING'. If you don't see it then"
  139. echo "this script didn't find any problems."
  140. echo
  141. }
  142.  
  143. MODE=$1
  144.  
  145. if [ ! "$MODE" = "standard" ] && [ ! "$MODE" = "detailed" ]; then
  146. usage
  147. exit 0
  148. fi
  149.  
  150. # Parse any full paths from $1 (config files, progs, dirs).
  151. # Check the permissions on each of these.
  152. check_called_programs () {
  153. CCP_MESSAGE_STACK=$1
  154. CCP_FILE=$2
  155. CCP_USER=$3
  156. CCP_PATH=$4 # optional
  157.  
  158. # Check the perms of the supplied file regardless
  159. # The caller doesn't want to have to call check_perms as well as check_called_programs
  160. check_perms "$CCP_MESSAGE_STACK" "$CCP_FILE" "$CCP_USER" "$CCP_PATH"
  161.  
  162. # Skip the slow check if we're in quick mode
  163. if [ "$MODE" = "standard" ]; then
  164. return 0;
  165. fi
  166.  
  167. # Check if file is text or not
  168. IS_TEXT=`file "$CCP_FILE" | grep -i text`
  169. if [ $OS = "aix" ]; then
  170. IS_DYNBIN=`file "$CCP_FILE" | grep -i 'object module'`
  171. else
  172. IS_DYNBIN=`file "$CCP_FILE" | grep -i 'dynamically linked'`
  173. fi
  174.  
  175. # Process shell scripts (would also work on config files that reference other files)
  176. if [ ! -z "$IS_TEXT" ]; then
  177. # Parse full paths from file - ignoring commented lines
  178. CALLED_FILES=`grep -v '^#' "$CCP_FILE" | sed -e 's/^[^\/]*//' -e 's/["'\'':}$]/\x0a/g' | grep '/' | sed -e 's/[ \*].*//' | grep '^/[a-zA-Z0-9_/-]*$' | sort -u`
  179. for CALLED_FILE in $CALLED_FILES; do
  180. # echo "$CCP_FILE contains a reference to $CALLED_FILE. Checking perms."
  181. check_perms "$CCP_MESSAGE_STACK $CCP_FILE contains the string $CALLED_FILE." "$CALLED_FILE" "$CCP_USER" "$CCP_PATH"
  182. done
  183. else
  184. # Process dynamically linked binaries
  185. if [ ! -z "$IS_DYNBIN" ]; then
  186.  
  187. CALLED_FILES=`ldd "$CCP_FILE" 2>/dev/null | grep '/' | sed 's/[^\/]*\//\//' | cut -f 1 -d ' ' | cut -f 1 -d '('`
  188. for CALLED_FILE in $CALLED_FILES; do
  189. check_perms "$CCP_MESSAGE_STACK $CCP_FILE uses the library $CALLED_FILE." "$CALLED_FILE" "$CCP_USER" "$CCP_PATH"
  190. done
  191.  
  192. # Strings binary to look for hard-coded config files
  193. # or other programs that might be called.
  194. for CALLED_FILE in `strings "$CCP_FILE" | sed -e 's/^[^\/]*//' -e 's/["'\'':}$]/\x0a/g' | grep '/' | sed -e 's/[ \*].*//' | grep '^/[a-zA-Z0-9_/-]*$' | sort -u`; do
  195. check_perms "$CCP_MESSAGE_STACK $CCP_FILE contains the string $CALLED_FILE." "$CALLED_FILE" "$CCP_USER" "$CCP_PATH"
  196. done
  197. fi
  198. fi
  199. }
  200.  
  201. # Parse any full paths from $1 (config files, progs, dirs).
  202. # Check the permissions on each of these.
  203. check_called_programs_suid () {
  204. CCP_FILE=$1
  205. CCP_PATH=$2 # optional
  206.  
  207. get_owner $CCP_FILE; CCP_USER=$GET_OWNER_RETURN
  208. CCP_MESSAGE_STACK="$CCP_FILE is SUID $CCP_USER."
  209. LS=`ls -l $CCP_FILE`
  210. echo "Checking SUID-$CCP_USER program $CCP_FILE: $LS"
  211.  
  212. # Don't check perms of executable itself
  213. # check_perms "$CCP_MESSAGE_STACK" "$CCP_FILE" "$CCP_USER" "$CCP_PATH"
  214.  
  215. # Check if file is text or not
  216. IS_TEXT=`file "$CCP_FILE" | grep -i text`
  217. IS_DYNBIN=`file "$CCP_FILE" | grep -i 'dynamically linked'`
  218.  
  219. # Process shell scripts (would also work on config files that reference other files)
  220. if [ ! -z "$IS_TEXT" ]; then
  221. # Skip the slow check if we're in quick mode
  222. if [ "$MODE" = "standard" ]; then
  223. return 0;
  224. fi
  225.  
  226. # Parse full paths from file - ignoring commented lines
  227. CALLED_FILES=`grep -v '^#' "$CCP_FILE" | sed -e 's/^[^\/]*//' -e 's/["'\'':}$]/\x0a/g' | grep '/' | sed -e 's/[ \*].*//' | grep '^/[a-zA-Z0-9_/-]*$' | sort -u`
  228. for CALLED_FILE in $CALLED_FILES; do
  229. # echo "$CCP_FILE contains a reference to $CALLED_FILE. Checking perms."
  230. check_perms "$CCP_MESSAGE_STACK $CCP_FILE contains the string $CALLED_FILE." "$CALLED_FILE" "$CCP_USER" "$CCP_PATH"
  231. done
  232. else
  233. # Process dynamically linked binaries
  234. if [ ! -z "$IS_DYNBIN" ]; then
  235.  
  236. CALLED_FILES=`ldd "$CCP_FILE" 2>/dev/null | grep '/' | sed 's/[^\/]*\//\//' | cut -f 1 -d ' '`
  237. for CALLED_FILE in $CALLED_FILES; do
  238. check_perms "$CCP_MESSAGE_STACK $CCP_FILE uses the library $CALLED_FILE." "$CALLED_FILE" "$CCP_USER" "$CCP_PATH"
  239. done
  240.  
  241. # Skip the slow check if we're in quick mode
  242. if [ "$MODE" = "standard" ]; then
  243. return 0;
  244. fi
  245.  
  246. # Strings binary to look for hard-coded config files
  247. # or other programs that might be called.
  248. for CALLED_FILE in `strings "$CCP_FILE" | sed -e 's/^[^\/]*//' -e 's/["'\'':}$]/\x0a/g' | grep '/' | sed -e 's/[ \*].*//' | grep '^/[a-zA-Z0-9_/-]*$' | sort -u`; do
  249. check_perms "$CCP_MESSAGE_STACK $CCP_FILE contains the string $CALLED_FILE." "$CALLED_FILE" "$CCP_USER" "$CCP_PATH"
  250. done
  251. fi
  252. fi
  253. }
  254.  
  255. # Check if $1 can be changed by users who are not $2
  256. check_perms () {
  257. CP_MESSAGE_STACK=$1
  258. CHECK_PERMS_FILE=$2
  259. CHECK_PERMS_USER=$3
  260. CHECK_PERMS_PATH=$4 # optional
  261.  
  262. if [ ! -f "$CHECK_PERMS_FILE" ] && [ ! -d "$CHECK_PERMS_FILE" ] && [ ! -b "$CHECK_PERMS_FILE" ]; then
  263. CHECK_PERMS_FOUND=0
  264. if [ ! -z "$CHECK_PERMS_PATH" ]; then
  265. # Look for it in the supplied path
  266. for DIR in `echo "$CHECK_PERMS_PATH" | sed 's/:/ /g'`; do
  267. if [ -f "$DIR/$CHECK_PERMS_FILE" ]; then
  268. CHECK_PERMS_FOUND=1
  269. CHECK_PERMS_FILE="$DIR/$CHECK_PERMS_FILE"
  270. break
  271. fi
  272. done
  273. fi
  274.  
  275. #if [ "$CHECK_PERMS_FOUND" = "0" ]; then
  276. # echo "ERROR: File $CHECK_PERMS_FILE doesn't exist. Checking parent path anyway."
  277. # # return 0
  278. # fi
  279. fi
  280.  
  281. C=`echo "$CHECK_PERMS_FILE" | cut -c 1`
  282. if [ ! "$C" = "/" ]; then
  283. echo "ERROR: Can't find absolute path for $CHECK_PERMS_FILE. Skipping."
  284. return 0
  285. fi
  286.  
  287. echo " Checking if anyone except $CHECK_PERMS_USER can change $CHECK_PERMS_FILE"
  288.  
  289. while [ -n "$CHECK_PERMS_FILE" ]; do
  290. perms_secure "$CP_MESSAGE_STACK" $CHECK_PERMS_FILE $CHECK_PERMS_USER
  291. CHECK_PERMS_FILE=`echo $CHECK_PERMS_FILE | sed 's/\/[^\/]*$//'`
  292. done
  293. }
  294.  
  295. # Check if $1 can be read by users who are not $2
  296. check_read_perms () {
  297. CP_MESSAGE_STACK=$1
  298. CHECK_PERMS_FILE=$2
  299. CHECK_PERMS_USER=$3
  300.  
  301. if [ ! -f "$CHECK_PERMS_FILE" ] && [ ! -b "$CHECK_PERMS_FILE" ]; then
  302. echo "ERROR: File $CHECK_PERMS_FILE doesn't exist"
  303. return 0
  304. fi
  305.  
  306. echo " Checking if anyone except $CHECK_PERMS_USER can read file $CHECK_PERMS_FILE"
  307.  
  308. perms_secure_read "$CP_MESSAGE_STACK" "$CHECK_PERMS_FILE" "$CHECK_PERMS_USER"
  309. }
  310.  
  311. perms_secure_read () {
  312. PS_MESSAGE_STACK=$1
  313. PERMS_SECURE_FILE=$2
  314. PERMS_SECURE_USER=$3
  315.  
  316. if [ ! -b "$PERMS_SECURE_FILE" ] && [ ! -f "$PERMS_SECURE_FILE" ] && [ ! -d "$PERMS_SECURE_FILE" ]; then
  317. echo "ERROR: No such file or directory: $PERMS_SECURE_FILE. Skipping."
  318. return 0
  319. fi
  320.  
  321. # Check if owner is different (but ignore root ownership, that's OK)
  322. only_user_can_read "$PS_MESSAGE_STACK" $PERMS_SECURE_FILE $PERMS_SECURE_USER
  323.  
  324. # Check group read perm (but ignore root group, that's OK)
  325. group_can_read "$PS_MESSAGE_STACK" $PERMS_SECURE_FILE $PERMS_SECURE_USER
  326.  
  327. # Check world read perm
  328. world_can_read "$PS_MESSAGE_STACK" $PERMS_SECURE_FILE
  329. }
  330.  
  331. perms_secure () {
  332. PS_MESSAGE_STACK=$1
  333. PERMS_SECURE_FILE=$2
  334. PERMS_SECURE_USER=$3
  335.  
  336. if [ ! -d "$PERMS_SECURE_FILE" ] && [ ! -f "$PERMS_SECURE_FILE" ] && [ ! -b "$PERMS_SECURE_FILE" ]; then
  337. # echo "ERROR: No such file or directory: $PERMS_SECURE_FILE. Skipping."
  338. return 0
  339. fi
  340.  
  341. # Check if owner is different (but ignore root ownership, that's OK)
  342. only_user_can_write "$PS_MESSAGE_STACK" $PERMS_SECURE_FILE $PERMS_SECURE_USER
  343.  
  344. # Check group write perm (but ignore root group, that's OK)
  345. group_can_write "$PS_MESSAGE_STACK" $PERMS_SECURE_FILE $PERMS_SECURE_USER
  346.  
  347. # Check world write perm
  348. world_can_write "$PS_MESSAGE_STACK" $PERMS_SECURE_FILE
  349. }
  350.  
  351. only_user_can_write () {
  352. O_MESSAGE_STACK=$1
  353. O_FILE=$2
  354. O_USER=$3
  355.  
  356. # We just need to check the owner really as the owner
  357. # can always grant themselves write access
  358. get_owner $O_FILE; O_FILE_USER=$GET_OWNER_RETURN
  359. if [ ! "$O_USER" = "$O_FILE_USER" ] && [ ! "$O_FILE_USER" = "root" ]; then
  360. echo "WARNING: $O_MESSAGE_STACK The user $O_FILE_USER can write to $O_FILE"
  361. fi
  362. }
  363.  
  364. group_can_write () {
  365. O_MESSAGE_STACK=$1
  366. O_FILE=$2
  367. O_USER=$3 # ignore group write access $3 is only member of group
  368.  
  369. get_group $O_FILE; O_FILE_GROUP=$GET_GROUP_RETURN
  370. P=`ls -lLd $O_FILE | cut -c 6`
  371. if [ "$P" = "w" ] && [ ! "$O_GROUP" = "root" ]; then
  372. # check the group actually has some members other than $O_USER
  373. group_has_other_members "$O_FILE_GROUP" "$O_USER"; # sets OTHER_MEMBERS to 1 or 0
  374. if [ "$OTHER_MEMBERS" = "1" ]; then
  375. echo "WARNING: $O_MESSAGE_STACK The group $O_FILE_GROUP can write to $O_FILE"
  376. fi
  377. fi
  378. }
  379.  
  380. group_has_other_members () {
  381. G_GROUP=$1
  382. G_USER=$2
  383.  
  384. # If LDAP/NIS is being used this script can't check group memberships
  385. # we therefore assume the worst.
  386. if [ "$EXT_AUTH" = 1 ]; then
  387. OTHER_MEMBERS=1
  388. return 1
  389. fi
  390.  
  391. GROUP_LINE=`grep "^$G_GROUP:" /etc/group`
  392. MEMBERS=`echo "$GROUP_LINE" | cut -f 4 -d : | sed 's/,/ /g'`
  393.  
  394. GID=`echo "$GROUP_LINE" | cut -f 3 -d :`
  395. EXTRA_MEMBERS=`grep "^[^:]*:[^:]*:[0-9]*:$GID:" /etc/passwd | cut -f 1 -d : | xargs echo`
  396.  
  397. for M in $MEMBERS; do
  398. if [ ! "$M" = "$G_USER" ] && [ ! "$M" = "root" ]; then
  399. OTHER_MEMBERS=1
  400. return 1
  401. fi
  402. done
  403.  
  404. for M in $EXTRA_MEMBERS; do
  405. if [ ! "$M" = "$G_USER" ] && [ ! "$M" = "root" ]; then
  406. OTHER_MEMBERS=1
  407. return 1
  408. fi
  409. done
  410.  
  411. OTHER_MEMBERS=0
  412. return 0
  413. }
  414.  
  415. world_can_write () {
  416. O_MESSAGE_STACK=$1
  417. O_FILE=$2
  418.  
  419. P=`ls -lLd $O_FILE | cut -c 9`
  420. S=`ls -lLd $O_FILE | cut -c 10`
  421.  
  422. if [ "$P" = "w" ]; then
  423. if [ "$S" = "t" ]; then
  424. echo "WARNING: $O_MESSAGE_STACK World write is set for $O_FILE (but sticky bit set)"
  425. else
  426. echo "WARNING: $O_MESSAGE_STACK World write is set for $O_FILE"
  427. fi
  428. fi
  429. }
  430.  
  431. only_user_can_read () {
  432. O_MESSAGE_STACK=$1
  433. O_FILE=$2
  434. O_USER=$3
  435.  
  436. # We just need to check the owner really as the owner
  437. # can always grant themselves read access
  438. get_owner $O_FILE; O_FILE_USER=$GET_OWNER_RETURN
  439. if [ ! "$O_USER" = "$O_FILE_USER" ] && [ ! "$O_FILE_USER" = "root" ]; then
  440. echo "WARNING: $O_MESSAGE_STACK The user $O_FILE_USER can read $O_FILE"
  441. fi
  442. }
  443.  
  444. group_can_read () {
  445. O_MESSAGE_STACK=$1
  446. O_FILE=$2
  447. O_USER=$3
  448.  
  449. get_group $O_FILE; O_FILE_GROUP=$GET_GROUP_RETURN
  450. P=`ls -lLd $O_FILE | cut -c 5`
  451. if [ "$P" = "r" ] && [ ! "$O_GROUP" = "root" ]; then
  452. # check the group actually has some members other than $O_USER
  453. group_has_other_members "$O_FILE_GROUP" "$O_USER"; # sets OTHER_MEMBERS to 1 or 0
  454. if [ "$OTHER_MEMBERS" = "1" ]; then
  455. echo "WARNING: $O_MESSAGE_STACK The group $O_FILE_GROUP can read $O_FILE"
  456. fi
  457. fi
  458. }
  459.  
  460. world_can_read () {
  461. O_MESSAGE_STACK=$1
  462. O_FILE=$2
  463.  
  464. P=`ls -lLd $O_FILE | cut -c 8`
  465.  
  466. if [ "$P" = "w" ]; then
  467. echo "WARNING: $O_MESSAGE_STACK World read is set for $O_FILE"
  468. fi
  469. }
  470.  
  471. section () {
  472. echo
  473. echo '############################################'
  474. echo $1
  475. echo '############################################'
  476. }
  477.  
  478. # Guess OS
  479. if [ -x /usr/bin/showrev ]; then
  480. OS="solaris"
  481. SHADOW="/etc/shadow"
  482. elif [ -x /usr/sbin/sam -o -x /usr/bin/sam ]; then
  483. OS="hpux"
  484. SHADOW="/etc/shadow"
  485. elif [ -f /etc/master.passwd ]; then
  486. OS="bsd"
  487. SHADOW="/etc/master.passwd"
  488. elif [ -f /etc/security/user ]; then
  489. OS="aix"
  490. SHADOW="/etc/security/passwd"
  491. else
  492. OS="linux"
  493. SHADOW="/etc/shadow"
  494. fi
  495. echo "Assuming the OS is: $OS"
  496. CONFIG_FILES="$CONFIG_FILES $SHADOW"
  497.  
  498. # Set path so we can access usual directories. HPUX and some linuxes don't have sbin in the path.
  499. PATH=$PATH:/usr/bin:/bin:/sbin:/usr/sbin; export PATH
  500.  
  501. # Check dependent programs are installed
  502. # Assume "which" is installed!
  503. PROGS="ls awk grep cat mount xargs file ldd strings"
  504. for PROG in $PROGS; do
  505. which $PROG 2>&1 > /dev/null
  506. if [ ! $? = "0" ]; then
  507. echo "ERROR: Dependend program '$PROG' is mising. Can't run. Sorry!"
  508. exit 1
  509. fi
  510. done
  511.  
  512. banner
  513.  
  514. section "Recording hostname"
  515. hostname
  516.  
  517. section "Recording uname"
  518. uname -a
  519.  
  520. section "Recording Interface IP addresses"
  521. if [ $OS = 'hpux' ]; then
  522. for IFACE in `lanscan | grep x | awk '{print $5}' 2>/dev/null`; do
  523. ifconfig $IFACE 2>/dev/null
  524. done
  525. else
  526. ifconfig -a
  527. fi
  528.  
  529. section "Checking if external authentication is allowed in /etc/passwd"
  530. FLAG=`grep '^+:' /etc/passwd`
  531. if [ -n "$FLAG" ]; then
  532. echo "WARNING: /etc/passwd allows external authentcation:"
  533. grep '^+:' /etc/passwd
  534. EXT_AUTH=1
  535. else
  536. echo "No +:... line found in /etc/passwd"
  537. fi
  538.  
  539. section "Checking nsswitch.conf/netsvc.conf for addition authentication methods"
  540. if [ $OS = 'aix' ]; then
  541. if [ -r "/etc/netsvc.conf" ]; then
  542. # ldap_nis Uses LDAP NIS services for resolving names
  543. # nis4 Uses NIS services for resolving only IPv4 addresses
  544. # nis6 Uses NIS services for resolving only IPv6 addresses
  545. # nis+4 Uses NIS plus services for resolving only IPv4 addresses
  546. # nis+6 Uses NIS plus services for resolving only IPv6 addresses
  547. # ldap4 Uses LDAP services for resolving only IPv4 addresses
  548. # ldap6 Uses LDAP services for resolving only IPv6 addresses
  549. # ldap_nis4 Uses NIS LDAP services for resolving only IPv4 addresses
  550. # ldap_nis6 Uses NIS LDAP services for resolving only IPv6 addresses
  551. # ldap Uses LDAP services for resolving names
  552. NIS=`grep '^host' /etc/netsvc.conf | grep 'nis'`
  553. if [ -n "$NIS" ]; then
  554. echo "WARNING: NIS is used for authentication on this system"
  555. EXT_AUTH=1
  556. fi
  557. LDAP=`grep '^host' /etc/netsvc.conf | grep 'ldap'`
  558. if [ -n "$LDAP" ]; then
  559. echo "WARNING: LDAP is used for authentication on this system"
  560. EXT_AUTH=1
  561. fi
  562. else
  563. echo "ERROR: File /etc/netsvc.conf isn't readable. Skipping checks."
  564. fi
  565. else
  566. if [ -r "/etc/nsswitch.conf" ]; then
  567. NIS=`grep '^passwd' /etc/nsswitch.conf | grep 'nis'`
  568. if [ -n "$NIS" ]; then
  569. echo "WARNING: NIS is used for authentication on this system"
  570. EXT_AUTH=1
  571. fi
  572. LDAP=`grep '^passwd' /etc/nsswitch.conf | grep 'ldap'`
  573. if [ -n "$LDAP" ]; then
  574. echo "WARNING: LDAP is used for authentication on this system"
  575. EXT_AUTH=1
  576. fi
  577.  
  578. if [ -z "$NIS" ] && [ -z "$LDAP" ]; then
  579. echo "Neither LDAP nor NIS are used for authentication"
  580. fi
  581. else
  582. echo "ERROR: File /etc/nsswitch.conf isn't readable. Skipping checks."
  583. fi
  584. fi
  585.  
  586. # Check important config files aren't writable
  587. section "Checking for writable config files"
  588. for FILE in $CONFIG_FILES; do
  589. if [ -f "$FILE" ]; then
  590. check_perms "$FILE is a critical config file." "$FILE" root
  591. fi
  592. done
  593.  
  594. section "Checking if $SHADOW is readable"
  595. check_read_perms "$SHADOW holds authentication data" $SHADOW root
  596.  
  597. section "Checking for password hashes in /etc/passwd"
  598. FLAG=`grep -v '^[^:]*:[!x\*]*:' /etc/passwd | grep -v '^#'`
  599. if [ -n "$FLAG" ]; then
  600. echo "WARNING: There seem to be some password hashes in /etc/passwd"
  601. grep -v '^[^:]*:[!x\*]*:' /etc/passwd | grep -v '^#'
  602. EXT_AUTH=1
  603. else
  604. echo "No password hashes found in /etc/passwd"
  605. fi
  606.  
  607. section "Checking account settings"
  608. # Check for something nasty like r00t::0:0::/:/bin/sh in /etc/passwd
  609. # We only need read access to /etc/passwd to be able to check this.
  610. if [ -r "/etc/passwd" ]; then
  611. OPEN=`grep "^[^:][^:]*::" /etc/passwd | cut -f 1 -d ":"`
  612. if [ -n "$OPEN" ]; then
  613. echo "WARNING: The following accounts have no password:"
  614. grep "^[^:][^:]*::" /etc/passwd | cut -f 1 -d ":"
  615. fi
  616. fi
  617. if [ -r "$SHADOW" ]; then
  618. echo "Checking for accounts with no passwords"
  619. if [ "$OS" = "linux" ]; then
  620. passwd -S -a | while read LINE
  621. do
  622. USER=`echo "$LINE" | awk '{print $1}'`
  623. STATUS=`echo "$LINE" | awk '{print $2}'`
  624. if [ "$STATUS" = "NP" ]; then
  625. echo "WARNING: User $USER doesn't have a password"
  626. fi
  627. done
  628. elif [ "$OS" = "solaris" ]; then
  629. passwd -s -a | while read LINE
  630. do
  631. USER=`echo "$LINE" | awk '{print $1}'`
  632. STATUS=`echo "$LINE" | awk '{print $2}'`
  633. if [ "$STATUS" = "NP" ]; then
  634. echo "WARNING: User $USER doesn't have a password"
  635. fi
  636. done
  637. fi
  638. else
  639. echo "File $SHADOW isn't readable. Skipping some checks."
  640. fi
  641.  
  642. section "Checking library directories from /etc/ld.so.conf"
  643. if [ -f "/etc/ld.so.conf" ] && [ -r "/etc/ld.so.conf" ]; then
  644. for DIR in `grep '^/' /etc/ld.so.conf`; do
  645. check_perms "$DIR is in /etc/ld.so.conf." $DIR root
  646. done
  647.  
  648. #FILES=`grep '^include' /etc/ld.so.conf | sed 's/^include *//'`
  649. #if [ ! -z "$FILES" ]; then
  650. # for DIR in `echo $FILES | xargs cat | sort -u`; do
  651. # done
  652. #fi
  653. else
  654. echo "File /etc/ld.so.conf not present. Skipping checks."
  655. fi
  656.  
  657. # Check sudoers if we have permission - needs root normally
  658. section "Checking sudo configuration"
  659. if [ -f "/etc/sudoers" ] && [ -r "/etc/sudoers" ]; then
  660. echo -----------------
  661. echo "Checking if sudo is configured"
  662. SUDO_USERS=`grep -v '^#' /etc/sudoers | grep -v '^[ \t]*$' | grep -v '^[ \t]*Default' | grep =`
  663. if [ ! -z "$SUDO_USERS" ]; then
  664. echo "WARNING: Sudo is configured. Manually check nothing unsafe is allowed:"
  665. grep -v '^#' /etc/sudoers | grep -v '^[ \t]*$' | grep = | grep -v '^[ \t]*Default'
  666. fi
  667.  
  668. echo -----------------
  669. echo "Checking sudo users need a password"
  670. SUDO_NOPASSWD=`grep -v '^#' /etc/sudoers | grep -v '^[ \t]*$' | grep NOPASSWD`
  671. if [ ! -z "$SUDO_NOPASSWD" ]; then
  672. echo "WARNING: Some users can use sudo without a password:"
  673. grep -v '^#' /etc/sudoers | grep -v '^[ \t]*$' | grep NOPASSWD
  674. fi
  675. else
  676. echo "File /etc/sudoers not present. Skipping checks."
  677. fi
  678.  
  679. section "Checking permissions on swap file(s)"
  680. if [ "$OS" != "aix" ]; then
  681. for SWAP in `swapon -s | grep -v '^Filename' | cut -f 1 -d ' '`; do
  682. check_perms "$SWAP is used for swap space." $SWAP root
  683. check_read_perms "$SWAP is used for swap space." $SWAP root
  684. done
  685. fi
  686.  
  687. section "Checking programs run from inittab"
  688. if [ -f "/etc/inittab" ] && [ -r "/etc/inittab" ]; then
  689. for FILE in `cat /etc/inittab | grep : | grep -v '^#' | cut -f 4 -d : | grep '/' | cut -f 1 -d ' ' | sort -u`; do
  690. check_called_programs "$FILE is run from /etc/inittab as root." $FILE root
  691. done
  692. else
  693. echo "File /etc/inittab not present. Skipping checks."
  694. fi
  695.  
  696. section "Checking postgres trust relationships"
  697. for DIR in $PGDIRS; do
  698. if [ -d "$DIR" ] && [ -r "$DIR/pg_hba.conf" ]; then
  699. grep -v '^#' "$DIR/pg_hba.conf" | grep -v '^[ \t]*$' | while read LINE
  700. do
  701. AUTH=`echo "$LINE" | awk '{print $NF}'`
  702. if [ "$AUTH" = "trust" ]; then
  703. PGTRUST=1
  704. echo "WARNING: Postgres trust configured in $DIR/pg_hba.conf: $LINE"
  705. fi
  706. done
  707. fi
  708. done
  709.  
  710. PGVER1=`psql -U postgres template1 -c 'select version()' 2>/dev/null | grep version`
  711.  
  712. if [ -n "$PGVER1" ]; then
  713. PGTRUST=1
  714. echo "WARNING: Can connect to local postgres database as \"postgres\" without a password"
  715. fi
  716.  
  717. PGVER2=`psql -U pgsql template1 -c 'select version()' 2>/dev/null | grep version`
  718.  
  719. if [ -n "$PGVER2" ]; then
  720. PGTRUST=1
  721. echo "WARNING: Can connect to local postgres database as \"pgsql\" without a password"
  722. fi
  723.  
  724. if [ -z "$PGTRUST" ]; then
  725. echo "No postgres trusts detected"
  726. fi
  727.  
  728. # Check device files for mounted file systems are secure
  729. # cat /proc/mounts | while read LINE # Doesn't work so well when LVM is used - need to be root
  730. section "Checking permissions on device files for mounted partitions"
  731. if [ "$OS" = "linux" ]; then
  732. mount | while read LINE
  733. do
  734. DEVICE=`echo "$LINE" | awk '{print $1}'`
  735. FS=`echo "$LINE" | awk '{print $5}'`
  736. if [ "$FS" = "ext2" ] || [ "$FS" = "ext3" ] ||[ "$FS" = "reiserfs" ]; then
  737. echo "Checking device $DEVICE"
  738. check_perms "$DEVICE is a mounted file system." $DEVICE root
  739. fi
  740. done
  741. elif [ "$OS" = "bsd" ]; then
  742. mount | grep ufs | while read LINE
  743. do
  744. DEVICE=`echo "$LINE" | awk '{print $1}'`
  745. echo "Checking device $DEVICE"
  746. check_perms "$DEVICE is a mounted file system." $DEVICE root
  747. done
  748. elif [ "$OS" = "solaris" ]; then
  749. mount | grep xattr | while read LINE
  750. do
  751. DEVICE=`echo "$LINE" | awk '{print $3}'`
  752. if [ ! "$DEVICE" = "swap" ]; then
  753. echo "Checking device $DEVICE"
  754. check_perms "$DEVICE is a mounted file system." $DEVICE root
  755. fi
  756. done
  757. elif [ "$OS" = "hpux" ]; then
  758. mount | while read LINE
  759. do
  760. DEVICE=`echo "$LINE" | awk '{print $3}'`
  761. C=`echo $DEVICE | cut -c 1`
  762. if [ "$C" = "/" ]; then
  763. echo "Checking device $DEVICE"
  764. check_perms "$DEVICE is a mounted file system." $DEVICE root
  765. fi
  766. done
  767.  
  768. NFS=`mount | grep NFS`
  769. if [ -n "$NFS" ]; then
  770. echo "WARNING: This system is an NFS client. Check for nosuid and nodev options."
  771. mount | grep NFS
  772. fi
  773. elif [ "$OS" = "aix" ]; then
  774. mount | grep jfs2 | while read DEVICE LINE
  775. do
  776. echo "Checking device $DEVICE"
  777. check_perms "$DEVICE is a mounted file system." $DEVICE root
  778. done
  779. fi
  780.  
  781. # Check cron jobs if they're readable
  782. # TODO check that cron is actually running
  783. section "Checking cron job programs aren't writable (/etc/crontab)"
  784. CRONDIRS=""
  785. if [ -f "/etc/crontab" ] && [ -r "/etc/crontab" ]; then
  786. MYPATH=`grep '^PATH=' /etc/crontab | cut -f 2 -d = `
  787. echo Crontab path is $MYPATH
  788.  
  789. # Check if /etc/cron.(hourly|daily|weekly|monthly) are being used
  790. CRONDIRS=`grep -v '^#' /etc/crontab | grep -v '^[ \t]*$' | grep '[ \t][^ \t][^ \t]*[ \t][ \t]*' | grep run-crons`
  791.  
  792. # Process run-parts
  793. grep -v '^#' /etc/crontab | grep -v '^[ \t]*$' | grep '[ \t][^ \t][^ \t]*[ \t][ \t]*' | grep run-parts | while read LINE
  794. do
  795. echo "Processing crontab run-parts entry: $LINE"
  796. USER=`echo "$LINE" | awk '{print $6}'`
  797. DIR=`echo "$LINE" | sed 's/.*run-parts[^()&|;\/]*\(\/[^ ]*\).*/\1/'`
  798. check_perms "$DIR holds cron jobs which are run as $USER." "$DIR" "$USER"
  799. if [ -d "$DIR" ]; then
  800. echo " Checking directory: $DIR"
  801. for FILE in $DIR/*; do
  802. FILENAME=`echo "$FILE" | sed 's/.*\///'`
  803. if [ "$FILENAME" = "*" ]; then
  804. echo " No files in this directory."
  805. continue
  806. fi
  807. check_called_programs "$FILE is run by cron as $USER." "$FILE" "$USER"
  808. done
  809. fi
  810. done
  811.  
  812. # TODO bsd'd periodic:
  813. # 1 3 * * * root periodic daily
  814. # 15 4 * * 6 root periodic weekly
  815. # 30 5 1 * * root periodic monthly
  816.  
  817. grep -v '^#' /etc/crontab | grep -v '^[ ]*$' | grep '[ ][^ ][^ ]*[ ][ ]*' | while read LINE
  818. do
  819. echo "Processing crontab entry: $LINE"
  820. USER=`echo "$LINE" | awk '{print $6}'`
  821. PROG=`echo "$LINE" | awk '{print $7}'`
  822. check_called_programs "$PROG is run from crontab as $USER." $PROG $USER $MYPATH
  823. done
  824. else
  825. echo "File /etc/crontab not present. Skipping checks."
  826. fi
  827.  
  828. # Do this if run-crons is run from /etc/crontab
  829. if [ -n "$CRONDIRS" ]; then
  830. USER=`echo "$CRONDIRS" | awk '{print $6}'`
  831. section "Checking /etc/cron.(hourly|daily|weekly|monthly)"
  832. for DIR in hourly daily weekly monthly; do
  833. if [ -d "/etc/cron.$DIR" ]; then
  834. echo " Checking directory: /etc/cron.$DIR"
  835. for FILE in /etc/cron.$DIR/*; do
  836. FILENAME=`echo "$FILE" | sed 's/.*\///'`
  837. if [ "$FILENAME" = "*" ]; then
  838. echo "No files in this directory."
  839. continue
  840. fi
  841. check_called_programs "$FILE is run via cron as $USER." "$FILE" $USER
  842. done
  843. fi
  844. done
  845. fi
  846.  
  847. section "Checking cron job programs aren't writable (/var/spool/cron/crontabs)"
  848. if [ -d "/var/spool/cron/crontabs" ]; then
  849. for FILE in /var/spool/cron/crontabs/*; do
  850. USER=`echo "$FILE" | sed 's/^.*\///'`
  851. if [ "$USER" = "*" ]; then
  852. echo "No user crontabs found in /var/spool/cron/crontabs. Skipping checks."
  853. continue
  854. fi
  855. echo "Processing crontab for $USER: $FILE"
  856. if [ -r "$FILE" ]; then
  857. MYPATH=`grep '^PATH=' "$FILE" | cut -f 2 -d = `
  858. if [ -n "$MYPATH" ]; then
  859. echo Crontab path is $MYPATH
  860. fi
  861. grep -v '^#' "$FILE" | grep -v '^[ \t]*$' | grep '[ \t][^ \t][^ \t]*[ \t][ \t]*' | while read LINE
  862. do
  863. echo "Processing crontab entry: $LINE"
  864. PROG=`echo "$LINE" | awk '{print $6}'`
  865. check_called_programs "$PROG is run via cron as $USER." "$PROG" $USER
  866. done
  867. else
  868. echo "ERROR: Can't read file $FILE"
  869. fi
  870. done
  871. else
  872. echo "Directory /var/spool/cron/crontabs is not present. Skipping checks."
  873. fi
  874.  
  875. section "Checking cron job programs aren't writable (/var/spool/cron/tabs)"
  876. if [ -d "/var/spool/cron/tabs" ]; then
  877. for FILE in /var/spool/cron/tabs/*; do
  878. USER=`echo "$FILE" | sed 's/^.*\///'`
  879. if [ "$USER" = "*" ]; then
  880. echo "No user crontabs found in /var/spool/cron/crontabs. Skipping checks."
  881. continue
  882. fi
  883. echo "Processing crontab for $USER: $FILE"
  884. if [ -r "$FILE" ]; then
  885. MYPATH=`grep '^PATH=' "$FILE" | cut -f 2 -d = `
  886. if [ -n "$MYPATH" ]; then
  887. echo Crontab path is $MYPATH
  888. fi
  889. grep -v '^#' "$FILE" | grep -v '^[ \t]*$' | grep '[ \t][^ \t][^ \t]*[ \t][ \t]*' | while read LINE
  890. do
  891. echo "Processing crontab entry: $LINE"
  892. PROG=`echo "$LINE" | awk '{print $6}'`
  893. check_called_programs "$PROG is run from cron as $USER." $PROG $USER $MYPATH
  894. done
  895. else
  896. echo "ERROR: Can't read file $FILE"
  897. fi
  898. done
  899. else
  900. echo "Directory /var/spool/cron/tabs is not present. Skipping checks."
  901. fi
  902.  
  903. # Check programs run from /etc/inetd.conf have secure permissions
  904. # TODO: check inetd is actually running
  905. section "Checking inetd programs aren't writable"
  906. if [ -f /etc/inetd.conf ] && [ -r /etc/inetd.conf ]; then
  907. grep -v '^#' /etc/inetd.conf | grep -v '^[ \t]*$' | while read LINE
  908. do
  909. USER=`echo $LINE | awk '{print $5}'`
  910. PROG=`echo $LINE | awk '{print $6}'` # could be tcpwappers ...
  911. PROG2=`echo $LINE | awk '{print $7}'` # ... and this is the real prog
  912. if [ -z "$PROG" ] || [ "$PROG" = "internal" ]; then
  913. # Not calling an external program
  914. continue
  915. fi
  916. echo Processing inetd line: $LINE
  917. if [ -f "$PROG" ]; then
  918. check_called_programs "$PROG is run from inetd as $USER." $PROG $USER
  919. fi
  920. if [ -f "$PROG2" ]; then
  921. check_called_programs "$PROG is run from inetd as $USER." $PROG2 $USER
  922. fi
  923. done
  924. else
  925. echo "File /etc/inetd.conf not present. Skipping checks."
  926. fi
  927.  
  928. # Check programs run from /etc/xinetd.d/*
  929. # TODO: check xinetd is actually running
  930. section "Checking xinetd programs aren't writeable"
  931. if [ -d /etc/xinetd.d ]; then
  932. for FILE in `grep 'disable[ \t]*=[ \t]*no' /etc/xinetd.d/* | cut -f 1 -d :`; do
  933. echo Processing xinetd service file: $FILE
  934. PROG=`grep '^[ \t]*server[ \t]*=[ \t]*' $FILE | sed 's/.*server.*=[ \t]*//'`
  935. USER=`grep '^[ \t]*user[ \t]*=[ \t]*' $FILE | sed 's/.*user.*=[ \t]*//'`
  936. check_called_programs "$PROG is run from xinetd as $USER." $PROG $USER
  937. done
  938. else
  939. echo "Directory /etc/xinetd.d not present. Skipping checks."
  940. fi
  941.  
  942. # Check for writable home directories
  943. section "Checking home directories aren't writable"
  944. cat /etc/passwd | grep -v '^#' | while read LINE
  945. do
  946. echo Processing /etc/passwd line: $LINE
  947. USER=`echo $LINE | cut -f 1 -d :`
  948. DIR=`echo $LINE | cut -f 6 -d :`
  949. SHELL=`echo $LINE | cut -f 7 -d :`
  950. if [ "$SHELL" = "/sbin/nologin" ] || [ "$SHELL" = "/bin/false" ]; then
  951. echo " Skipping user $USER. They don't have a shell."
  952. else
  953. if [ "$DIR" = "/dev/null" ]; then
  954. echo " Skipping /dev/null home directory"
  955. else
  956. check_perms "$DIR is the home directory of $USER." $DIR $USER
  957. fi
  958. fi
  959. done
  960.  
  961. # Check for readable files in home directories
  962. section "Checking for readable sensitive files in home directories"
  963. cat /etc/passwd | while read LINE
  964. do
  965. USER=`echo $LINE | cut -f 1 -d :`
  966. DIR=`echo $LINE | cut -f 6 -d :`
  967. SHELL=`echo $LINE | cut -f 7 -d :`
  968. for FILE in $HOME_DIR_FILES; do
  969. if [ -f "$DIR/$FILE" ]; then
  970. check_read_perms "$DIR/$FILE is in the home directory of $USER." "$DIR/$FILE" $USER
  971. fi
  972. done
  973. done
  974.  
  975. section "Checking SUID programs"
  976. if [ "$MODE" = "detailed" ]; then
  977. for FILE in `find / -type f -perm -04000 2>/dev/null`; do
  978. check_called_programs_suid $FILE
  979. done
  980. else
  981. echo "Skipping checks of SUID programs (it's slow!). Run again in 'detailed' mode."
  982. fi
  983.  
  984. # Check for private SSH keys in home directories
  985. section "Checking for Private SSH Keys home directories"
  986. for HOMEDIR in `cut -f 6 -d : /etc/passwd`; do
  987. if [ -d "$HOMEDIR/.ssh" ]; then
  988. PRIV_KEYS=`grep -l 'BEGIN [RD]SA PRIVATE KEY' $HOMEDIR/.ssh/* 2>/dev/null`
  989. if [ -n "$PRIV_KEYS" ]; then
  990. for KEY in $PRIV_KEYS; do
  991. ENC_KEY=`grep -l 'ENCRYPTED' "$KEY" 2>/dev/null`
  992. if [ -n "$ENC_KEY" ]; then
  993. echo "WARNING: Encrypted Private SSH Key Found in $KEY"
  994. else
  995. echo "WARNING: Unencrypted Private SSH Key Found in $KEY"
  996. fi
  997. done
  998. fi
  999. fi
  1000. done
  1001.  
  1002. # Check for public SSH keys in home directories
  1003. section "Checking for Public SSH Keys home directories"
  1004. for HOMEDIR in `cut -f 6 -d : /etc/passwd`; do
  1005. if [ -r "$HOMEDIR/.ssh/authorized_keys" ]; then
  1006. KEYS=`grep '^ssh-' $HOMEDIR/.ssh/authorized_keys 2>/dev/null`
  1007. if [ -n "$KEYS" ]; then
  1008. echo "WARNING: Public SSH Key Found in $HOMEDIR/.ssh/authorized_keys"
  1009. fi
  1010. fi
  1011. done
  1012.  
  1013. # Check for any SSH agents running on the box
  1014. section "Checking for SSH agents"
  1015. AGENTS=`ps -ef | grep ssh-agent | grep -v grep`
  1016. if [ -n "$AGENTS" ]; then
  1017. echo "WARNING: There are SSH agents running on this system:"
  1018. ps -ef | grep ssh-agent | grep -v grep
  1019. # for PID in `ps aux | grep ssh-agent | grep -v grep | awk '{print $2}'`; do
  1020. for SOCK in `ls /tmp/ssh-*/agent.* 2>/dev/null`; do
  1021. SSH_AUTH_SOCK=$SOCK; export SSH_AUTH_SOCK
  1022. AGENT_KEYS=`ssh-add -l | grep -v 'agent has no identities.' 2>/dev/null`
  1023. if [ -n "$AGENT_KEYS" ]; then
  1024. echo "WARNING: SSH Agent has keys loaded [SSH_AUTH_SOCK=$SSH_AUTH_SOCK]"
  1025. ssh-add -l
  1026. fi
  1027. done
  1028. else
  1029. echo "No SSH agents found"
  1030. fi
  1031.  
  1032. # Check for any GPG agents running on the box
  1033. section "Checking for GPG agents"
  1034. AGENTS=`ps -ef | grep gpg-agent | grep -v grep`
  1035. if [ -n "$AGENTS" ]; then
  1036. echo "WARNING: There are GPG agents running on this system:"
  1037. ps aux | grep gpg-agent | grep -v grep
  1038. else
  1039. echo "No GPG agents found"
  1040. fi
  1041.  
  1042. # Check files in /etc/init.d/* can't be modified by non-root users
  1043. section "Checking startup files (init.d / rc.d) aren't writable"
  1044. for DIR in /etc/init.d /etc/rc.d /usr/local/etc/rc.d; do
  1045. if [ -d "$DIR" ]; then
  1046. for FILE in $DIR/*; do
  1047. F=`echo "$FILE" | sed 's/^.*\///'`
  1048. if [ "$F" = "*" ]; then
  1049. echo "No user startup script found in $DIR. Skipping checks."
  1050. continue
  1051. fi
  1052. echo Processing startup script $FILE
  1053. check_called_programs "$FILE is run by root at startup." $FILE root
  1054. done
  1055. fi
  1056. done
  1057.  
  1058. section "Checking if running programs are writable"
  1059. if [ $OS = "solaris" ]; then
  1060. # use the output of ps command
  1061. ps -ef -o user,comm | while read LINE
  1062. do
  1063. USER=`echo "$LINE" | awk '{print $1}'`
  1064. PROG=`echo "$LINE" | awk '{print $2}'`
  1065. check_called_programs "$PROG is currently running as $USER." "$PROG" "$USER"
  1066. done
  1067. elif [ $OS = "aix" ]; then
  1068. # use the output of ps command
  1069. ps -ef -o user,comm | while read LINE
  1070. do
  1071. USER=`echo "$LINE" | awk '{print $1}'`
  1072. PROG=`echo "$LINE" | awk '{print $2}'`
  1073. check_called_programs "`which $PROG` is currently running as $USER." "`which $PROG`" "$USER"
  1074. done
  1075. elif [ $OS = "bsd" ]; then
  1076. # use the output of ps command
  1077. ps aux | while read LINE
  1078. do
  1079. USER=`echo "$LINE" | awk '{print $1}'`
  1080. PROG=`echo "$LINE" | awk '{print $11}'`
  1081. check_called_programs "$PROG is currently running as $USER." "$PROG" "$USER"
  1082. done
  1083. elif [ $OS = "hpux" ]; then
  1084. # use the output of ps command
  1085. ps -ef | while read LINE
  1086. do
  1087. USER=`echo "$LINE" | awk '{print $1}'`
  1088. PROG1=`echo "$LINE" | awk '{print $8}'`
  1089. PROG2=`echo "$LINE" | awk '{print $9}'`
  1090. if [ -f "$PROG1" ]; then
  1091. check_called_programs "$PROG is currently running as $USER." "$PROG1" "$USER"
  1092. fi
  1093. if [ -f "$PROG2" ]; then
  1094. check_called_programs "$PROG is currently running as $USER." "$PROG2" "$USER"
  1095. fi
  1096. done
  1097. elif [ $OS = "linux" ]; then
  1098. # use the /proc file system
  1099. for PROCDIR in /proc/[0-9]*; do
  1100. unset PROGPATH
  1101. PID=`echo $PROCDIR | cut -f 3 -d /`
  1102. echo ------------------------
  1103. echo "PID: $PID"
  1104. if [ -d "$PROCDIR" ]; then
  1105. if [ -r "$PROCDIR/exe" ]; then
  1106. PROGPATH=`ls -l "$PROCDIR/exe" 2>&1 | sed 's/ (deleted)//' | awk '{print $NF}'`
  1107. else
  1108. if [ -r "$PROCDIR/cmdline" ]; then
  1109. P=`cat $PROCDIR/cmdline | tr "\0" = | cut -f 1 -d = | grep '^/'`
  1110. if [ -z "$P" ]; then
  1111. echo "ERROR: Can't find full path of running program: "`cat $PROCDIR/cmdline`
  1112. else
  1113. PROGPATH=$P
  1114. fi
  1115. else
  1116. echo "ERROR: Can't find full path of running program: "`cat $PROCDIR/cmdline`
  1117. continue
  1118. fi
  1119. fi
  1120. get_owner $PROCDIR; OWNER=$GET_OWNER_RETURN
  1121. echo "Owner: $OWNER"
  1122. else
  1123. echo "ERROR: Can't find OWNER. Process has gone."
  1124. continue
  1125. fi
  1126.  
  1127. if [ -n "$PROGPATH" ]; then
  1128. get_owner $PROGPATH; PROGOWNER=$GET_OWNER_RETURN
  1129. echo "Program path: $PROGPATH"
  1130. check_called_programs "$PROGPATH is currently running as $OWNER." $PROGPATH $OWNER
  1131. fi
  1132.  
  1133. if [ "$MODE" == "detailed" ]; then
  1134. for FILE in $PROCDIR/fd/*; do
  1135. F=`echo "$FILE" | sed 's/^.*\///'`
  1136. if [ "$F" = "*" ]; then
  1137. continue
  1138. fi
  1139. check_perms "$FILE is an open file descriptor for process $PID running as $OWNER." $FILE $OWNER
  1140. done
  1141. fi
  1142. done
  1143. fi
  1144.  
  1145. if [ "$MODE" == "detailed" ]; then
  1146. section "Checking exploit mitigation"
  1147. if [ $OS = "linux" ]; then
  1148. ASLR=`sysctl kernel.randomize_va_space | awk '{print $1}'`
  1149. if [ "$ASLR" -eq 0 ]; then
  1150. echo "WARNING: No ASLR"
  1151. elif [ "$ASLR" -eq 1 ]; then
  1152. echo "WARNING: Conservative ASLR"
  1153. fi
  1154.  
  1155. for PROCDIR in /proc/[0-9]*; do
  1156. unset PROGPATH
  1157. PID=`echo $PROCDIR | cut -f 3 -d /`
  1158. echo ------------------------
  1159. echo "PID: $PID"
  1160. if [ -d "$PROCDIR" ]; then
  1161. if [ -r "$PROCDIR/exe" ]; then
  1162. PROGPATH=`ls -l "$PROCDIR/exe" 2>&1 | sed 's/ (deleted)//' | awk '{print $NF}'`
  1163. else
  1164. if [ -r "$PROCDIR/cmdline" ]; then
  1165. P=`cat $PROCDIR/cmdline | tr "\0" = | cut -f 1 -d = | grep '^/'`
  1166. if [ -z "$P" ]; then
  1167. echo "ERROR: Can't find full path of running program: "`cat $PROCDIR/cmdline`
  1168. else
  1169. PROGPATH=$P
  1170. fi
  1171. else
  1172. echo "ERROR: Can't find full path of running program: "`cat $PROCDIR/cmdline`
  1173. continue
  1174. fi
  1175. fi
  1176. else
  1177. echo "ERROR: Can't find full path of running process. Process has gone."
  1178. continue
  1179. fi
  1180. if [ -n "$PROGPATH" ]; then
  1181. echo "Program path: $PROGPATH"
  1182. echo "NX:"
  1183. grep stack $PROCDIR/maps
  1184. echo "SSP:"
  1185. objdump -D $PROCDIR/exe | grep stack_chk
  1186. fi
  1187. done
  1188. find / -perm -u+s -o -perm -g+s | while read PROGPATH
  1189. do
  1190. echo "Program path: $PROGPATH"
  1191. echo "SSP:"
  1192. ls -la $PROGPATH
  1193. objdump -D $PROGPATH | grep stack_chk
  1194. done
  1195. fi
  1196. fi
Advertisement
Add Comment
Please, Sign In to add comment