1#!/bin/sh 2 3################################################################################# 4# 5# Lynis 6# ------------------ 7# 8# Copyright 2007-2013, Michael Boelen 9# Copyright 2007-2021, CISOfy 10# 11# Website : https://cisofy.com 12# Blog : http://linux-audit.com 13# GitHub : https://github.com/CISOfy/lynis 14# 15# Lynis comes with ABSOLUTELY NO WARRANTY. This is free software, and you are 16# welcome to redistribute it under the terms of the GNU General Public License. 17# See LICENSE file for usage of this software. 18# 19###################################################################### 20# 21# Helper program to share details 22# 23###################################################################### 24# 25# How to use: 26# ------------ 27# Run: lynis show <option> 28# 29###################################################################### 30 31COMMANDS="audit configure generate show update upload-only" 32HELPERS="audit configure show update" 33OPTIONS="--auditor\n--cronjob (--cron)\n--debug\n--developer\n--devops\n--forensics\n--help (-h)\n--log-file\n--manpage (--man)\n--no-colors\n--no-log\n--no-plugins\n--pentest\n--profile\n--plugin-dir\n--quick (-Q)\n--quiet (-q)\n--report-file\n--reverse-colors\n--tests\n--tests-from-category\n--tests-from-group\n--usecwd\n--upload\n--verbose\n--version (-V)\n--wait\n--warnings-only" 34 35SHOW_ARGS="categories changelog commands dbdir details environment eol groups help hostids includedir language license logfile man options os pidfile plugindir profiles release releasedate report settings tests version workdir" 36SHOW_HELP="lynis show ${BROWN}categories${NORMAL} (display test categories) 37lynis show ${BROWN}changelog${NORMAL} ${GRAY}[version]${NORMAL} (release details) 38lynis show ${BROWN}commands${NORMAL} (all available commands) 39lynis show ${BROWN}dbdir${NORMAL} (database directory) 40lynis show ${BROWN}details${NORMAL} (display test details from log file) 41lynis show ${BROWN}environment${NORMAL} (hardware, virtual machine, or container type) 42lynis show ${BROWN}eol${NORMAL} (OS end-of-life status) 43lynis show ${BROWN}groups${NORMAL} (test groups) 44lynis show ${BROWN}help${NORMAL} (detailed information about arguments) 45lynis show ${BROWN}hostids${NORMAL} (unique IDs for this system) 46lynis show ${BROWN}includedir${NORMAL} (include directory for tests and functions) 47lynis show ${BROWN}language${NORMAL} (configured or detected language) 48lynis show ${BROWN}license${NORMAL} (license details) 49lynis show ${BROWN}logfile${NORMAL} (location of logfile) 50lynis show ${BROWN}man${NORMAL} (show help) 51lynis show ${BROWN}options${NORMAL} (available flags and options) 52lynis show ${BROWN}os${NORMAL} (operating system and version) 53lynis show ${BROWN}pidfile${NORMAL} (active file to stored process ID) 54lynis show ${BROWN}plugindir${NORMAL} (directory with plugins) 55lynis show ${BROWN}profiles${NORMAL} (discovered profiles) 56lynis show ${BROWN}release${NORMAL} (version) 57lynis show ${BROWN}releasedate${NORMAL} (date of release) 58lynis show ${BROWN}report${NORMAL} (location of report data) 59lynis show ${BROWN}settings${NORMAL} (display configured settings, ${WHITE}options:${NORMAL} ${CYAN}--brief --nocolors${NORMAL}) 60lynis show ${BROWN}tests${NORMAL} ${GRAY}[test]${NORMAL} (display information about one or more tests) 61lynis show ${BROWN}tests skipped${NORMAL} (which tests to skip according profile) 62lynis show ${BROWN}version${NORMAL} (${PROGRAM_NAME} version) 63lynis show ${BROWN}workdir${NORMAL} (work directory)" 64 65AUDIT_ARGS="( dockerfile | system )" 66AUDIT_HELP=" 67 ${WHITE}lynis audit <target>${NORMAL} 68 69 ${CYAN}audit dockerfile ${BROWN}<file>${NORMAL} 70 71 Perform security audit on a Docker build file 72 ${GRAY}Example:${NORMAL} 73 lynis audit dockerfile Dockerfile 74 75 76 ${CYAN}audit system ${GRAY}[options]${NORMAL} 77 78 Perform security system audit 79 80 ${GRAY}Examples:${NORMAL} 81 lynis audit system 82 lynis audit system --cronjob 83 lynis audit system --profile developer.prf 84 lynis audit system --quick 85 86 87 ${CYAN}audit system remote ${BROWN}<target> ${GRAY}[options]${NORMAL} 88 89 Perform security system audit on a remote target 90 91 ${GRAY}Examples:${NORMAL} 92 lynis audit system remote 192.168.1.100 93 lynis audit system remote 192.168.1.100 --no-colors 94 95" 96 97GENERATE_ARGS="( --save )" 98GENERATE_HELP=" 99 Generate random value for hostid and hostid2 100 ${WHITE}lynis generate hostids${NORMAL} 101 102 Generate and save values 103 ${WHITE}lynis generate hostids --save${NORMAL} 104 105 Generate systemd units to run Lynis on a schedule (e.g. daily) 106 ${WHITE}lynis generate systemd-units${NORMAL} 107 108" 109 110 111UPDATE_ARGS="check | info" 112UPDATE_HELP=" 113 ${CYAN}update info${NORMAL} 114 115 Check and show version information 116 117 ${CYAN}update check${NORMAL} 118 119 Just check if version is up-to-date 120 121" 122 123UPLOAD_ONLY_HELP=" 124 ${CYAN}update-only${NORMAL} 125 126 Perform just a data upload 127 128" 129 130SHOW_SETTINGS_ARGS="--brief --configured-only --nocolors" 131SHOW_TESTS_ARGS="skipped" 132 133COMMANDS_AUDIT_SYSTEM_USAGE="Usage: lynis audit system" 134COMMANDS_AUDIT_SYSTEM_FUNCTION="Function: performs a security audit of the system" 135 136if [ $# -gt 0 ]; then 137 case $1 in 138 "categories") 139 ViewCategories 140 ;; 141 "changelog") 142 # Allow providing a version 143 if [ $# -gt 1 ]; then 144 shift; SEARCH_VERSION="$1" 145 fi 146 PROGRAM_NAME_LOWER=$( echo ${PROGRAM_NAME} | tr '[:upper:]' '[:lower:]') 147 CHANGELOG_PATHS="/usr/share/doc/${PROGRAM_NAME} /usr/share/doc/${PROGRAM_NAME}-${PROGRAM_VERSION} /usr/share/doc/${PROGRAM_NAME_LOWER} ." 148 CHANGELOG="" 149 if [ -z "${SEARCH_VERSION}" ]; then SEARCH_VERSION="${PROGRAM_VERSION}"; fi 150 STARTED=0 151 for FILEPATH in ${CHANGELOG_PATHS}; do 152 if [ -f ${FILEPATH}/CHANGELOG.md ]; then 153 CHANGELOG="${FILEPATH}/CHANGELOG.md" 154 # Check also for gzipped changelog 155 elif [ -f ${FILEPATH}/changelog.gz ]; then 156 ZCAT=$(which zcat 2> /dev/null | grep -v "no [^ ]* in ") 157 if [ -n "${ZCAT}" ]; then 158 CreateTempFile 159 CHANGELOG="${TEMP_FILE}" 160 LogText "Result: found gzipped changelog in ${FILEPATH}" 161 LogText "Action: Creating temporary file to store text" 162 ${ZCAT} ${FILEPATH}/changelog.gz > ${CHANGELOG} 163 else 164 DisplayError "Could not find zcat utility to use on gzipped changelog" 165 fi 166 fi 167 if [ -n "${CHANGELOG}" ]; then LogText "Result: found changelog file: ${CHANGELOG}"; break; fi 168 done 169 if [ -n "${CHANGELOG}" ]; then 170 SEARCH=$(sed 's/^## //' ${CHANGELOG} | grep -E "^${PROGRAM_NAME} ${SEARCH_VERSION}") 171 if [ $? -eq 0 ]; then 172 while read -r LINE; do 173 if [ ${STARTED} -eq 0 ]; then 174 SEARCH=$(echo ${LINE} | sed 's/^## //' | grep -E "^${PROGRAM_NAME} ${SEARCH_VERSION}") 175 if [ $? -eq 0 ]; then STARTED=1; ${ECHOCMD} "${BOLD}${LINE}${NORMAL}"; fi 176 else 177 # Stop if we find the next Lynis version 178 SEARCH=$(echo ${LINE} | sed 's/^## //' | grep -E "^${PROGRAM_NAME} [0-9]\.[0-9]\.[0-9]") 179 if [ $? -eq 0 ]; then 180 break 181 else 182 ${ECHOCMD} "${LINE}" 183 fi 184 fi 185 done < ${CHANGELOG} 186 else 187 DisplayError "Could not find this version in the changelog" 188 ${ECHOCMD} "" 189 ${ECHOCMD} "${HEADER}Usage:${NORMAL}" 190 ${ECHOCMD} "$0 lynis show changelog [version]" 191 ${ECHOCMD} "" 192 ${ECHOCMD} "${HEADER}${PROGRAM_NAME} versions:${NORMAL}" 193 SEARCH=$(sed 's/^## //' ${CHANGELOG} | grep -E "^Lynis [0-9]\.[0-9]\.[0-9] " | awk '{print $2}' | sort -n) 194 ${ECHOCMD} ${SEARCH} 195 ExitFatal 196 fi 197 else 198 DisplayError "Could not find the changelog file (searched in ${CHANGELOG_PATHS})" 199 ExitFatal 200 fi 201 ;; 202 "commands") 203 if [ $# -eq 1 ]; then 204 ${ECHOCMD} "\n${WHITE}Commands:${NORMAL}" 205 for ITEM in ${COMMANDS}; do 206 ${ECHOCMD} "lynis ${CYAN}${ITEM}${NORMAL}" 207 done 208 ${ECHOCMD} "" 209 else 210 shift 211 if [ $# -eq 1 ]; then 212 case $1 in 213 "audit") ${ECHOCMD} "${AUDIT_HELP}" ;; 214 "configure") ${ECHOCMD} "No help available yet" ;; 215 "generate") ${ECHOCMD} "${GENERATE_HELP}" ;; 216 "show") ${ECHOCMD} "${SHOW_HELP}" ;; 217 "update") ${ECHOCMD} "${UPDATE_HELP}" ;; 218 "upload-only") ${ECHOCMD} "${UPLOAD_ONLY_HELP}" ;; 219 *) DisplayError "Unknown argument for 'commands'" 220 esac 221 else 222 shift 223 case $1 in 224 "dockerfile") 225 ${ECHOCMD} "Usage: lynis audit dockerfile <file>" 226 ;; 227 "system") 228 ${ECHOCMD} "${COMMANDS_AUDIT_SYSTEM_USAGE}\n${COMMANDS_AUDIT_SYSTEM_FUNCTION}\n" 229 ;; 230 *) 231 DisplayError "Unknown argument '$1' for commands" 232 ;; 233 esac 234 fi 235 fi 236 ;; 237 "dbdir") 238 ${ECHOCMD} "${DBDIR}" 239 ;; 240 "details") 241 if [ -z "${LOGFILE}" ]; then DisplayError "Could not find log file to parse"; fi 242 if [ $# -eq 1 ]; then 243 DisplayError "This command needs a test ID (e.g. CORE-1000) to search for. This command is used after a scan (lynis audit system). Run 'lynis show tests' to see all available tests." 244 else 245 shift 246 if [ $# -eq 1 ]; then 247 TESTID="$1" 248 awk -v search="Performing test ID $TESTID" '$0 ~ search {++f;p=1}p&&f==1;/====/{p=0}' ${LOGFILE} 249 fi 250 fi 251 ;; 252 "environment") 253 if [ -z "${CONTAINER_TYPE}" ]; then 254 ${ECHOCMD} "container=0" 255 else 256 ${ECHOCMD} "container=1" 257 ${ECHOCMD} "container-type=${CONTAINER_TYPE}" 258 fi 259 if [ ${ISVIRTUALMACHINE} -eq 1 ]; then 260 ${ECHOCMD} "virtual-machine=1" 261 ${ECHOCMD} "virtual-machine-type=${VMTYPE}" 262 else 263 ${ECHOCMD} "hardware=1" 264 ${ECHOCMD} "virtual-machine=0" 265 fi 266 ;; 267 "eol") 268 ${ECHOCMD} "Operating-system=${OS_FULLNAME}" 269 if [ ${EOL} -eq 0 ]; then 270 ${ECHOCMD} "End-of-life=No" 271 elif [ ${EOL} -eq 1 ]; then 272 ${ECHOCMD} "End-of-life=Yes" 273 elif [ ${EOL} -eq 255 ]; then 274 ${ECHOCMD} "End-of-life=Not tested" 275 else 276 ${ECHOCMD} "End-of-life=Unknown" 277 fi 278 ;; 279 "groups") 280 ViewGroups 281 ;; 282 "help" | "--help" | "-h") 283 if [ $# -eq 1 ]; then 284 ${ECHOCMD} "${PROGRAM_NAME} ${PROGRAM_VERSION} - Help" 285 ${ECHOCMD} "==========================" 286 ${ECHOCMD} "" 287 ${ECHOCMD} "${WHITE}Commands${NORMAL}:" 288 for ITEM in ${COMMANDS}; do 289 ${ECHOCMD} "${CYAN}${ITEM}${NORMAL}" 290 done 291 ${ECHOCMD} "" 292 ${ECHOCMD} "Use 'lynis show help ${CYAN}<command>${NORMAL}' to see details" 293 ${ECHOCMD} ""; ${ECHOCMD} "" 294 ${ECHOCMD} "${WHITE}Options${NORMAL}:\n${GRAY}${OPTIONS}${NORMAL}" 295 else 296 shift 297 case $1 in 298 "audit") ${ECHOCMD} "${AUDIT_HELP}" ;; 299 "configure") ${ECHOCMD} "No help available yet" ;; 300 "generate") ${ECHOCMD} "${GENERATE_HELP}" ;; 301 "show") ${ECHOCMD} "${SHOW_HELP}" ;; 302 "update") ${ECHOCMD} "${UPDATE_HELP}" ;; 303 "upload-only") ${ECHOCMD} "${UPLOAD_ONLY_HELP}" ;; 304 "?") ${ECHOCMD} "${SHOW_ARGS}" ;; 305 *) ${ECHOCMD} "Unknown argument provided for lynis show help" ;; 306 esac 307 fi 308 ;; 309 "helpers") for ITEM in ${HELPERS}; do ${ECHOCMD} ${ITEM}; done ;; 310 "hostids" | "hostid") 311 ${ECHOCMD} "hostid=${HOSTID}" 312 ${ECHOCMD} "hostid2=${HOSTID2}" 313 ${ECHOCMD} "machineid=${MACHINEID}" 314 ;; 315 "includedir") 316 ${ECHOCMD} "${INCLUDEDIR}" 317 ;; 318 "language") ${ECHOCMD} "${LANGUAGE}" ;; 319 "license") ${ECHOCMD} "${PROGRAM_LICENSE}" ;; 320 "logfile") ${ECHOCMD} "${LOGFILE}" ;; 321 "man") ${ECHOCMD} "Use ./lynis --man or man lynis" ;; 322 "options") ${ECHOCMD} "${OPTIONS}" ;; 323 "os") 324 ${ECHOCMD} "OS=${OS}" 325 ${ECHOCMD} "OS_NAME=${OS_NAME}" 326 ${ECHOCMD} "OS_FULLNAME=${OS_FULLNAME}" 327 ${ECHOCMD} "OS_VERSION=${OS_VERSION}" 328 ;; 329 "pidfile") ${ECHOCMD} "${PIDFILE}" ;; 330 "profile" | "profiles") for ITEM in ${PROFILES}; do ${ECHOCMD} ${ITEM}; done ;; 331 "profiledir") ${ECHOCMD} "${PROFILEDIR}" ;; 332 "plugindir") ${ECHOCMD} "${PLUGINDIR}" ;; 333 "release") ${ECHOCMD} "${PROGRAM_VERSION}-${PROGRAM_RELEASE_TYPE}" ;; 334 "releasedate") ${ECHOCMD} "${PROGRAM_RELEASE_DATE}" ;; 335 "report") ${ECHOCMD} "${REPORTFILE}" ;; 336 "settings") 337 BRIEF_OUTPUT=0 338 COLORED_OUTPUT=1 339 CONFIGURED_ONLY_OUTPUT=0 340 while [ $# -gt 1 ]; do 341 shift 342 case $1 in 343 "--brief" | "--br") BRIEF_OUTPUT=1 ;; 344 "--configured-only" | "--co") CONFIGURED_ONLY_OUTPUT=1 ;; 345 "--nocolors" | "--no-colors" | "--nc") COLORED_OUTPUT=0; COLORS=0 ;; 346 *) 347 ${ECHOCMD} "${RED}Error${NORMAL}: Invalid argument provided to 'lynis show settings'\n\n" 348 ${ECHOCMD} "Suggestions:" 349 for ITEM in ${SHOW_SETTINGS_ARGS}; do ${ECHOCMD} "lynis show settings ${ITEM}"; done 350 ExitFatal 351 ;; 352 esac 353 done 354 if [ ${COLORED_OUTPUT} -eq 0 ]; then RemoveColors; fi 355 # Sort all settings and display them 356 SETTINGS=$(sort ${SETTINGS_FILE} | sed 's/ /:space:/g') 357 for LINE in ${SETTINGS}; do 358 SETTING=$(echo ${LINE} | awk -F';' '{print $1}') 359 VALUE=$(echo ${LINE} | awk -F';' '{print $2}') 360 DESCRIPTION=$(echo ${LINE} | awk -F';' '{print $3}' | sed 's/:space:/ /g') 361 if [ -z "${VALUE}" -a ${CONFIGURED_ONLY_OUTPUT} -eq 0 ]; then VALUE="${GRAY}[not configured]${NORMAL}"; fi 362 if [ -n "${VALUE}" ]; then 363 if [ ${BRIEF_OUTPUT} -eq 0 ]; then ${ECHOCMD} "${GRAY}# ${DESCRIPTION}${NORMAL}"; fi 364 ${ECHOCMD} "${WHITE}${SETTING}${NORMAL}=${CYAN}${VALUE}${NORMAL}" 365 if [ ${BRIEF_OUTPUT} -eq 0 ]; then ${ECHOCMD} ""; fi 366 fi 367 done 368 if [ ${BRIEF_OUTPUT} -eq 0 -a ${CONFIGURED_ONLY_OUTPUT} -eq 0 -a ${COLORED_OUTPUT} -eq 1 ]; then 369 if [ ${COLORS} -eq 1 ]; then 370 ${ECHOCMD} "# Add --brief to hide descriptions, --configured-only to show configured items only, or --nocolors to remove colors" 371 else 372 ${ECHOCMD} "# Add --brief to hide descriptions, --configured-only to show configured items only" 373 fi 374 fi 375 376 ;; 377 "tests") 378 if [ $# -gt 1 ]; then 379 shift 380 case $1 in 381 "skipped") 382 if [ -z "${SKIP_TESTS}" ]; then 383 ${ECHOCMD} "# ${CYAN}No tests are skipped (according profile)${NORMAL}" 384 else 385 ${ECHOCMD} "# Skipped tests (according profile)" 386 ${ECHOCMD} "${SKIP_TESTS}" 387 fi 388 ;; 389 *) 390 if [ -f ${DBDIR}/tests.db ]; then 391 SEARCH="$1" 392 FIND=$(grep "^${SEARCH}" ${DBDIR}/tests.db | sed "s/ /:space:/g") 393 if [ -z "${FIND}" ]; then 394 ${ECHOCMD} "${WARNING}Error${NORMAL}: ${BOLD}Could not find this test in the database${NORMAL}\n\n" 395 ExitFatal 396 else 397 for ITEM in ${FIND}; do 398 TEST_DESCRIPTION=$(echo ${ITEM} | sed "s/:space:/ /g" | awk -F: '{print $6}') 399 TEST=$(echo ${ITEM} | awk -F: '{print $1}') 400 TEST_TYPE=$(echo ${ITEM} | awk -F: '{print $2}') 401 TEST_CATEGORY=$(echo ${ITEM} | awk -F: '{print $3}') 402 TEST_GROUP=$(echo ${ITEM} | awk -F: '{print $4}') 403 TEST_OS=$(echo ${ITEM} | awk -F: '{print $5}') 404 TEST_SKIPPED=0 405 ${ECHOCMD} "${CYAN}${TEST}${NORMAL}" 406 ${ECHOCMD} "===================================" 407 ${ECHOCMD} "" 408 ${ECHOCMD} "${WHITE}Type:${NORMAL} ${TEST_TYPE}" 409 ${ECHOCMD} "" 410 ${ECHOCMD} "${WHITE}Description:${NORMAL}" 411 ${ECHOCMD} "${TEST_DESCRIPTION}" 412 ${ECHOCMD} "" 413 ${ECHOCMD} "${WHITE}Category:${NORMAL} ${TEST_CATEGORY}, ${WHITE}Group:${NORMAL} ${TEST_GROUP}" 414 ${ECHOCMD} "" 415 ${ECHOCMD} "${WHITE}Test Execution:${NORMAL}" 416 if [ "${TEST_OS}" = "" ]; then 417 ${ECHOCMD} " Operating System: ${GREEN}Yes${NORMAL} (all systems)" 418 elif [ "${TEST_OS}" = "${OS}" ]; then 419 ${ECHOCMD} " Operating System: ${GREEN}Yes${NORMAL} (${TEST_OS} only)" 420 else 421 ${ECHOCMD} " Operating System: ${RED}No${NORMAL} (${TEST_OS} only)" 422 TEST_SKIPPED=1 423 fi 424 if [ -z "${SKIP_TESTS}" ]; then 425 ${ECHOCMD} " Profile: ${GREEN}Yes${NORMAL} (not configured)" 426 else 427 FIND=$(echo ${SKIP_TESTS} | grep -E "${TEST}") 428 if [ -z "${FIND}" ]; then 429 ${ECHOCMD} " Profile: ${GREEN}Yes${NORMAL} (test not marked to be skipped)" 430 else 431 ${ECHOCMD} " Profile: ${RED}No${NORMAL} (marked test as to be skipped)" 432 TEST_SKIPPED=1 433 fi 434 fi 435 if [ ${TEST_SKIPPED} -eq 1 ]; then ${ECHOCMD} ""; ${ECHOCMD} " This test will NOT be performed on this system"; fi 436 437 ${ECHOCMD} "" 438 ${ECHOCMD} "" 439 440 done 441 fi 442 else 443 ShowError "Can not find tests database" 444 ${ECHOCMD} "The changelog might not be installed on your system. Details can be found at ${PROGRAM_SOURCE}." 445 ExitFatal 446 fi 447 ;; 448 esac 449 else 450 if [ -f ${DBDIR}/tests.db ]; then 451 ${ECHOCMD} "# Test OS Description" 452 ${ECHOCMD} "# ======================================================================================" 453 awk -F: '{ if ($1 !~ /^#/) printf("%-10s %-10s %s (%s)\n",$1,$5,$6,$3)}' ${DBDIR}/tests.db 454 else 455 ShowError "Can not find tests database" 456 ${ECHOCMD} "The changelog might not be installed on your system. Details can be found at ${PROGRAM_SOURCE}." 457 ExitFatal 458 fi 459 fi 460 ;; 461 "version") ${ECHOCMD} "${PROGRAM_VERSION}" ;; 462 "workdir") ${ECHOCMD} "${WORKDIR}" ;; 463 "?") ${ECHOCMD} "${SHOW_ARGS}" ;; 464 *) ${ECHOCMD} "Unknown argument '${RED}$1${NORMAL}' for lynis show" ;; 465 esac 466else 467 ${ECHOCMD} "\n ${WHITE}Provide an additional argument${NORMAL}\n\n" 468 for ITEM in ${SHOW_ARGS}; do 469 ${ECHOCMD} " lynis show ${BROWN}${ITEM}${NORMAL}" 470 done 471 ${ECHOCMD} "\n" 472 ${ECHOCMD} "" 473 ${ECHOCMD} "Extended help about the show command can be provided with: $0 show commands show" 474fi 475 476 477ExitClean 478 479# More additions: 480# - categories 481# - workdir 482 483# The End 484