Advertisement
Guest User

Untitled

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