Exemple #1
0
def U52():
    report = pm.openReport('U-52.txt')
    pm.printTitle(report, '[U-52] 동일한 UID 금지')

    f = open('/etc/passwd', 'r')
    existUID = []
    isSafe = True

    for line in f:
        splitLine = line.split(':')
        uid = splitLine[2]
        if uid in existUID:
            isSafe = False
            pm.printWarning(report, '여러 계정이 동일한 UID: ' + uid + '를 가집니다.')
        existUID.append(uid)

    if isSafe:
        pm.printSafe(report)
    else:
        pm.printNotsafe(report)
        pm.printSolution(report, '[U-52] 조치 방법')
        pm.printSolution(report, '\t동일한 UID를 가진 사용자 계정의 UID를 변경하세요.')
        pm.printSolution(report, '\t\t#usermod -u <변경할 UID> <user_name>\n')

    report.close()
Exemple #2
0
def U03():
    report = pm.openReport('U-03.txt')
    pm.printTitle(report, '[U-03] 계정 잠금 임계값 설정')

    isSafe = False
    isSet = False
    # pam_tally2로 수정
    tocheck = 'auth required pam_tally2.so'
    tocheck = ''.join(tocheck.split())
    # KISA 매뉴얼에는 system-auth로 되어 있음
    # 우분투는 common-auth
    f = open('/etc/pam.d/common-auth', 'r')
    for line in f:
        line = ''.join(line.split())  # 공백 제거
        if tocheck in line:
            # 주석인지 확인
            if '#' in line:
                continue

            index = line.find('deny=')
            if index < 0:
                continue
            index += len('deny=')
            limit = ''
            while line[index] > '0' and line[index] < '9':
                limit = limit.join(line[index])
                index += 1
            if int(limit) > 5:
                pm.printWarning(report, '계정 잠금 임계값이 5 초과입니다.')
                pm.printWarning(report, '현재 임계값은 ' + limit + ' 입니다.')
                isSet = True
            else:
                pm.printNotice(report, '현재 임계값은 ' + limit + ' 입니다.')
                isSet = True
                isSafe = True
    f.close()

    if not isSet:
        pm.printWarning(report, '계정 잠금 임계값이 설정되어 있지 않습니다.')

    if isSafe:
        pm.printSafe(report)
    else:
        pm.printNotsafe(report)
        pm.printSolution(report, '[U-03] 조치 방법')
        pm.printSolution(report, '\t계정 잠금 임계값을 5이하로 설정하세요.')
        pm.printSolution(
            report, '\t\t텍스트 에디터를 이용하여 \"/etc/pam.d/common-auth\" 파일을 엽니다.')
        pm.printSolution(report, '\t\t아래의 내용을 수정 또는 추가하세요.')
        pm.printSolution(report, '\t\t순서가 중요하므로 수행문 최상단에 입력해.')
        pm.printSolution(report, '\t\tauth  required  pam_tally2.so ')
        pm.printSolution(
            report, '\t\t\tonerr=fail deny=5 unlock_time=120 no_magic_root')
        pm.printSolution(report,
                         '\t\t  no_magic_root : root에게는 패스워드 잠금 설정을 적용하지 않음')
        pm.printSolution(report, '\t\t  deny=5        : 5회 입력 실패 시 계정 잠금')
        pm.printSolution(
            report, '\t\t  unlock_time   : 계정 잠김 후 설정 시간이 지나면 잠김 해제 (단위: 초)\n')

    report.close()
Exemple #3
0
def U07():
    report = pm.openReport('U-07.txt')
    pm.printTitle(report, '[U-07] /etc/passwd 파일 소유자 및 권한 설정')

    status = stat('/etc/passwd')

    isRightOwner = False
    owner = status.st_uid
    if owner == 0:
        isRightOwner = True
        pm.printNotice(report, '/etc/passwd 파일의 소유자가 root 입니다.')
    else:
        pm.printWarning(report, '/etc/passwd 파일의 소유자가 root가 아닙니다.')

    isRightPerm = False
    perm = int(oct(status.st_mode)[-3:])
    if perm <= 644:
        isRightPerm = True
        pm.printNotice(report, '/etc/passwd 파일의 권한이 644 이하입니다.')
    else:
        pm.printWarning(report, '/etc/passwd 파일의 권한이 644 이하가 아닙니다.')

    if isRightOwner and isRightPerm:
        pm.printSafe(report)
    else:
        pm.printNotsafe(report)
        pm.printSolution(report, '[U-07] 조치 방법')
        pm.printSolution(report,
                         '\t/etc/passwd 파일의 소유자를 root로 권한을 644로 변경하세요.')
        pm.printSolution(report, '\t\t#chown root /etc/passwd')
        pm.printSolution(report, '\t\t#chmod 644 /etc/passwd\n')

    report.close()
Exemple #4
0
def U09():
    report = pm.openReport('U-09.txt')
    pm.printTitle(report, '[U-09] /etc/hosts 파일 소유자 및 권한 설정')

    status = stat('/etc/hosts')

    isRightOwner = False
    owner = status.st_uid
    if owner == 0:
        isRightOwner = True
        pm.printNotice(report, '/etc/hosts 파일의 소유자가 root 입니다.')
    else:
        pm.printWarning(report, '/etc/hosts 파일의 소유자가 root가 아닙니다.')

    isRightPerm = False
    perm = int(oct(status.st_mode)[-3:])
    if perm == 600:
        isRightPerm = True
        pm.printNotice(report, '/etc/hosts 파일의 권한이 600 입니다.')
    else:
        pm.printWarning(report, '/etc/hosts 파일의 권한이 600이 아닙니다.')

    if isRightOwner and isRightPerm:
        pm.printSafe(report)
    else:
        pm.printNotsafe(report)
        pm.printSolution(report, '[U-09] 조치 방법')
        pm.printSolution(report,
                         '\t/etc/hosts 파일의 소유자를 root로 권한을 600으로 변경하세요.')
        pm.printSolution(report, '\t\t#chown root /etc/hosts')
        pm.printSolution(report, '\t\t#chmod 600 /etc/hosts\n')

    report.close()
Exemple #5
0
def U04():
    report = pm.openReport('U-04.txt')
    pm.printTitle(report, '[U-04] 패스워드 파일 보호')

    isShadow = path.isfile("/etc/shadow")
    if not isShadow:
        pm.printWarning('/etc/shadow 파일이 없습니다.')

    isCrypto = False
    if isShadow:
        f = open('/etc/passwd', 'r')
        line = f.readline().split(':')
        if line[1] == 'x':
            isCrypto = True
        else:
            isCrypto = False
            pm.printWarning(report, '패스워드가 shadow를 통해 암호화가 되어있지 않습니다.')
        f.close()

    if isShadow and isCrypto:
        pm.printSafe(report)
    else:
        pm.printNotsafe(report)
        pm.printSolution(report, '[U-04] 조치 방법')
        pm.printSolution(report, '\tshadow 패스워드를 사용하거나 패스워드를 암호화하여 저장하세요.')
        pm.printSolution(report, '\t\t#pwconv\n')

    report.close()
Exemple #6
0
def U05():
    report = pm.openReport('U-05.txt')
    pm.printTitle(report, '[U-05] root 홈, 패스 디렉터리 권한 및 패스 설정')
    pm.printNotice(report, 'U-05의 점검은 현재 계정의 PATH만을 점검합니다.')

    envList = subprocess.check_output('echo $PATH', shell=True)
    envList = str(envList)
    isNotDot = False
    if '.' in envList:
        pm.printNotsafe(report, 'PATH에 \".\"이 포함되어 있습니다.')
    else:
        isNotDot = True
    isNotColon = False
    if '::' in envList:
        pm.printNotsafe(report, 'PATH에 \":\"이 포함되어 있습니다.')
    else:
        isNotColon = True

    if isNotDot and isNotColon:
        pm.printSafe(report)
    else:
        pm.printNotsafe(report)
        pm.printSolution(report, '[U-05] 조치 방법')
        pm.printSolution(report, '\t환경 설정 파일을 확인 및 수정하세요.')
        pm.printSolution(report, '\t\t점검이 필요한 파일들')
        pm.printSolution(report, '\t\t/etc/environment')
        pm.printSolution(report, '\t\t/etc/profile')
        pm.printSolution(report, '\t\t/etc/profile.d/*.sh')
        pm.printSolution(report, '\t\t~/.profile')
        pm.printSolution(report, '\t\t~/.bashrc')
        #pm.printSolution(report, '\t(수정 전) PATH=\".:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games\"\n')
        #pm.printSolution(report, '\t(수정 후) PATH=\"/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games\"\n')
        pm.printSolution(report, '\t\".\" 혹은 \":\"을 제거\n')

    report.close()
Exemple #7
0
def U44():
    report = pm.openReport('U-44.txt')
    pm.printTitle(report, '[U-44] root 이외의 UID가 \'0\' 금지')

    f = open('/etc/passwd', 'r')
    isSafe = True

    for line in f:
        splitLine = line.split(':')
        name = splitLine[0]
        uid = splitLine[2]
        if (name != 'root') and (uid == '0'):
            isSafe = False
            pm.printWarning(report, name + '의 UID가 \'0\'입니다.')

    if isSafe:
        pm.printSafe(report)
    else:
        pm.printNotsafe(report)
        pm.printSolution(report, '[U-44] 조치 방법')
        # KISA 매뉴얼은 500 이상
        pm.printSolution(report, '\tUID가 0인 일반 계정의 UID를 1000 이상으로 수정하세요.')
        pm.printSolution(report, '\t\t#usermod -u <변경할 UID> <user_name>\n')

    report.close()
Exemple #8
0
def U10():
    report = pm.openReport('U-10.txt')
    pm.printTitle(report, '[U-10] /etc/(x)inetd.conf 파일 소유자 및 권한 설정')

    filename = ''

    isInetd = path.isfile('/etc/inetd.conf')
    if not isInetd:
        pm.printNotice(report, '/etc/inetd.conf 파일이 없습니다.\n')
    else:
        filename = '/etc/inetd.conf'

    isXinetd = path.isfile('/etc/xinetd.conf')
    if not isXinetd:
        pm.printNotice(report, '/etc/xinetd.conf 파일이 없습니다.\n')
    else:
        filename = '/etc/xinetd.conf'

    if (not isInetd) or (not isXinetd):
        report.close()
        return

    status = stat(filename)

    isRightOwner = False
    owner = status.st_uid
    if owner == 0:
        isRightOwner = True
        pm.printNotice(report, filename + ' 파일의 소유자가 root 입니다.')
    else:
        pm.printWarning(report, filename + ' 파일의 소유자가 root가 아닙니다.')

    isRightPerm = False
    perm = int(oct(status.st_mode)[-3:])
    if perm == 600:
        isRightPerm = True
        pm.printNotice(report, filename + ' 파일의 권한이 600 입니다.')
    else:
        pm.printWarning(report, filename + ' 파일의 권한이 600이 아닙니다.')

    if isRightOwner and isRightPerm:
        pm.printSafe(report)
    else:
        pm.printNotsafe(report)
        pm.printSolution(report, '[U-10] 조치 방법')
        pm.printSolution(report,
                         '\t' + filename + ' 파일의 소유자를 root로 권한을 600으로 변경하세요.')
        pm.printSolution(report, '\t\t#chown root ' + filename)
        pm.printSolution(report, '\t\t#chmod 600 ' + filename)

    # xinetd.d 의 하위도 검사하도록 수정 필요
    if isXinetd:
        pm.printSolution(report,
                         '\t/etc/xinetd.d 디렉터리 하위의 취약한 파일도 동일한 방법으로 조치하세요.')

    report.close()
Exemple #9
0
def U49():
    report = pm.openReport('U-49.txt')
    pm.printTitle(report, '[U-49] 불필요한 계정 제거')
    pm.printNotice(report, 'U-49의 점검은 U-49.txt를 참고하여 관리자가 직접 수행바랍니다.\n')

    pm.printSolution(report, '[U-49] 조치 방법')
    pm.printSolution(report, '\t"/etc/passwd\" 파일을 확인하여')
    pm.printSolution(report, '\t미사용 계정, 의심스러운 계정, 사용하지 않지만')
    pm.printSolution(report, '\t기본적으로 생성되는 계정들을 확인합니다.')
    pm.printSolution(report, '\t불필요한 사용자 계정은 제거합니다.')
    pm.printSolution(report, '\t\t# userdel <user_name>\n')

    report.close()
Exemple #10
0
def U51():
    report = pm.openReport('U-51.txt')
    pm.printTitle(report, '[U-51] 계정이 존재하지 않는 GID 금지')
    pm.printNotice(report, 'U-51의 점검 및 조치는 시스템 관리자와 검토하여야 합니다.')
    pm.printNotice(report, 'U-51.txt를 참고하여 관리자와 사용자가 직접 수행바랍니다.')

    pm.printSolution(report, '[U-51] 조치 방법\n')
    pm.printSolution(report, '\t계정이 존재하지 않고 시스템 운영에 사용되지 않는 그룹 등')
    pm.printSolution(report, '\t불필요한 그룹이 존재하는 경우 해당 그룹을 제거하세요.')
    pm.printSolution(report, '\t\t\"/etc/group\" 파일과 \"/etc/passwd\" 파일을 같이 확인하여')
    pm.printSolution(report, '\t\t불필요한 그룹을 확인')
    pm.printSolution(report, '\t\t# groupdel <group_name>\n')

    report.close()
Exemple #11
0
def U53():
    report = pm.openReport('U-53.txt')
    pm.printTitle(report, '[U-53] 사용자 shell 점검')

    names = ['daemon',   \
             'bin',      \
             'sys',      \
             'adm',      \
             'games',    \
             'listen',   \
             'nobody',   \
             'nobody4',  \
             'noaccess', \
             'diag',     \
             'operator', \
             'gopher']

    f = open('/etc/passwd', 'r')
    isNologin = True

    for line in f:
        splitLine = line.split(':')
        name = splitLine[0]
        if name in names:
            shell = splitLine[6]
            # KISA 매뉴얼에는 /sbin/nologin 이지만 우분투는 /usr/sbin/nologin 이다.
            if  ( shell.find('/usr/sbin/nologin') < 0 )  \
            and ( shell.find('/bin/false') < 0 )         \
            and ( shell.find('/sbin/nologin') < 0 ):
                isNologin = False
                pm.printWarning(report, name + ' 계정의 로그인이 가능합니다.')

    pm.printNotice(
        report,
        '일반적으로 UID 1000 미만 60000 이상의\n\t       시스템 계정(sync 제외)의 확인이 필요합니다.')

    if isNologin:
        pm.printSafe(report)
    else:
        pm.printNotsafe(report)
        pm.printSolution(report, '[U-53] 조치 방법')
        pm.printSolution(report, '\t로그인이 필요하지 않은 계정에 대해 nologin 쉘로 변경하세요.')
        pm.printSolution(report, '\t\t텍스트 에디터를 이용하여 \"/etc/passwd\" 파일을 엽니다.')
        pm.printSolution(report, '\t\t해당 계정의 항목의 맨 마지막 필드인 로그인 쉘을.')
        pm.printSolution(report,
                         '\t\t우분투 기준으로 \"/usr/sbin/nologin\"으로 변경하세요.\n')

    report.close()
Exemple #12
0
def U13():
    report = pm.openReport('U-13.txt')
    pm.printTitle(report, '[U-13] SUID, SGID, sticky bit 설정 및 권한 설정')

    SUID = 0o4000
    SGID = 0o2000

    isSafe = True

    # 불필요한 SUID/SGID 목록
    files = ['/sbin/dump',        \
             '/sbin/restore',     \
             '/sbin/unix_chkpwd', \
             '/usr/bin/at',       \
             '/usr/bin/lpq',      \
             '/usr/bin/lpq-lpd',  \
             '/usr/bin/lprm',     \
             '/usr/bin/lprm-lpd', \
             '/usr/bin/newgrp',   \
             '/usr/sbin/lpc',     \
             '/usr/sbin/lpc-lpd', \
             '/usr/sbin/traceroute']

    for file in files:
        if not path.isfile(file):
            continue

        status = stat(file)
        perm = int(oct(status.st_mode)[-4:])

        if perm & SUID:
            pm.printWarning(report, file + ' 파일에 SUID가 설정되어 있습니다.')
            isSafe = False
        if perm & SGID:
            pm.printWarning(report, file + ' 파일에 SGID가 설정되어 있습니다.')
            isSafe = False

    if isSafe:
        pm.printSafe(report)
    else:
        pm.printNotsafe(report)
        pm.printSolution(report, '[U-13] 조치 방법')
        pm.printSolution(report, '\t주요 파일에 불필요한 SUID/SGID가 설정된 경우 SUID/SGID를 제거하세요.')
        pm.printSolution(report, '\t제거 시 OS 및 응용 프로그램 등 서비스가 정상작동 하는지 확인이 필요합니다.')
        pm.printSolution(report, '\t\t#chmod -s <file_name>\n')

    report.close()
Exemple #13
0
def U06():
    report = pm.openReport('U-06.txt')
    pm.printTitle(report, '[U-06] 파일 및 디렉터리 소유자 설정')
    pm.printNotice(report, 'U-06의 점검은 모든 파일을 검사하므로 상당한 시간이 소요됩니다.')
    pm.printNotice(report, '조치 방법을 참고하여 사용자가 직접 수행바랍니다.\n')

    pm.printSolution(report, '[U-06] 조치 방법')
    pm.printSolution(report, '\t소유자가 존재하지 않는 파일 및 디렉터리를 삭제하거나 소유자를 변경하세요.')
    pm.printSolution(report, '\t수정이 필요한 파일을 아래의 명령어로 검색합니다.')
    pm.printSolution(report, '\t\t# find / -nouser -print')
    pm.printSolution(report, '\t\t# find / -nogroup -print')
    pm.printSolution(report, '\tfind 뒤의 최상위 디렉터리 \"/\" 대신 필요한 경로를 입력하셔도 됩니다.')
    pm.printSolution(report, '\t대상 파일 혹은 디렉터리가 불필요할 경우에는 삭제합니다.')
    pm.printSolution(report, '\t필요한 경우에는 chown으로 소유자를 변경합니다.')
    pm.printSolution(report, '\t\t# chown <user_name> <file_name>\n')

    report.close()
Exemple #14
0
def U46():
    report = pm.openReport('U-46.txt')
    pm.printTitle(report, '[U-46] 패스워드 최소 길이 설정')

    isSafe = False
    isSet = False
    f = open('/etc/login.defs', 'r')
    for line in f:
        line = ''.join(line.split())
        index = line.find('PASS_MIN_LEN')
        if index >= 0:
            # 주석인지 확인
            if '#' in line[0:index]:
                continue

            passLen = line[index + len('PASS_MIN_LEN'):]
            if passLen == '':
                continue
            elif int(passLen) < 8:
                pm.printWarning(report, '패스워드 최소 길이가 8자 미만입니다.')
                pm.printWarning(report, '현재 최소 길이는 ' + passLen + '자 입니다.')
                isSet = True
            else:
                pm.printNotice(report, '현재 패스워드 최소 길이는 ' + passLen + '자 입니다.')
                isSet = True
                isSafe = True
    f.close()

    if not isSet:
        pm.printWarning(report, '패스워드 최소 길이가 설정되어 있지 않습니다.')

    if isSafe:
        pm.printSafe(report)
    else:
        pm.printNotsafe(report)
        pm.printSolution(report, '[U-46] 조치 방법')
        pm.printSolution(report, '\t패스워드 최소 길이를 8자 이상으로 설정하세요.')
        pm.printSolution(report, '\t공공기관인 경우 9자 이상으로 설정하세요.')
        pm.printSolution(report,
                         '\t\t텍스트 에디터를 이용하여 \"/etc/login.defs\" 파일을 엽니다.')
        pm.printSolution(report, '\t\t아래의 내용을 수정 또는 추가하세요.')
        pm.printSolution(report, '\t\t  PASS_MIN_LEN 8\n')

    report.close()
Exemple #15
0
def U50():
    report = pm.openReport('U-50.txt')
    pm.printTitle(report, '[U-50] 관리자 그룹에 최소한의 계정 포함')

    isSafe = True
    f = open('/etc/group', 'r')
    for line in f:
        splitLine = line.split(':')
        group = splitLine[0]
        # KISA 매뉴얼에는 root 그룹만 검사함
        # 난 sudo 그룹도 추가하였다.
        if group == 'root':
            users = splitLine[3].split(',')
            numOfUsers = len(users)
            if '\n' in users:
                numOfUsers -= 1
            if 'root' in users:
                numOfUsers -= 1
            if numOfUsers > 0:
                pm.printWarning(report, 'root 그룹에 불필요한 계정이 존재합니다.')
                isSafe = False
        elif group == 'sudo':
            users = splitLine[3].split(',')
            numOfUsers = len(users)
            if '\n' in users:
                numOfUsers -= 1
            if 'sudo' in users:
                numOfUsers -= 1
            if numOfUsers > 0:
                pm.printNotice(report,
                               'sudo 그룹에 ' + str(numOfUsers) + '개의 계정이 존재합니다.')
                pm.printNotice(report, '사용자가 직접 계정 현황 확인 후 조치 바랍니다.')
    f.close

    if isSafe:
        pm.printSafe(report)
    else:
        pm.printNotsafe(report)
        pm.printSolution(report, '[U-50] 조치 방법')
        pm.printSolution(report, '\t관리자 그룹에 불필요한 계정은 제거하세요.')
        pm.printSolution(report, '\t\t# deluser <user_name> root\n')

    report.close()
Exemple #16
0
def U48():
    report = pm.openReport('U-48.txt')
    pm.printTitle(report, '[U-48] 패스워드 최소 사용기간 설정')

    isSafe = False
    isSet = False
    f = open('/etc/login.defs', 'r')
    for line in f:
        line = ''.join(line.split())
        index = line.find('PASS_MIN_DAYS')
        if index >= 0:
            # 주석인지 확인
            if '#' in line[0:index]:
                continue

            days = line[index + len('PASS_MIN_DAYS'):]
            if days == '':
                continue
            elif int(days) < 1:
                pm.printWarning(report, '패스워드 최소 사용기간이 1일 미만 입니다.')
                pm.printWarning(report, '현재 최소 사용기간은 ' + days + '일 입니다.')
                isSet = True
            else:
                pm.printNotice(report, '현재 패스워드 최소 사용기간은 ' + days + '일 입니다.')
                isSet = True
                isSafe = True
    f.close()

    if not isSet:
        pm.printWarning(report, '패스워드 최소 사용기간이 설정되어 있지 않습니다.')

    if isSafe:
        pm.printSafe(report)
    else:
        pm.printNotsafe(report)
        pm.printSolution(report, '[U-48] 조치 방법')
        pm.printSolution(report, '\t패스워드 최소 사용기간을 1일로 설정하세요.')
        pm.printSolution(report,
                         '\t\t텍스트 에디터를 이용하여 \"/etc/login.defs\" 파일을 엽니다.')
        pm.printSolution(report, '\t\t아래의 내용을 수정 또는 추가하세요.')
        pm.printSolution(report, '\t\t  PASS_MIN_DAYS 1 (단위: 일)\n')

    report.close()
Exemple #17
0
def U54():
    report = pm.openReport('U-54.txt')
    pm.printTitle(report, '[U-54] Session Timeout 설정')

    # check bash
    shell = subprocess.check_output('echo $SHELL', shell=True)
    shell = str(shell)
    if not ('bash' in shell):
        pm.printNotice(report, 'bash shell이 아닙니다.')
        report.close()
        return

    echoRst = subprocess.check_output('echo $TMOUT', shell=True)
    echoRst = str(echoRst)
    startIdx = echoRst.find('\'')
    endIdx = echoRst.find('\\n')
    time = echoRst[startIdx + 1:endIdx]

    isTimeout = False
    if time == '':
        pm.printWarning(report, 'Session Timeout이 설정되어 있지 않습니다.')
    elif int(time) > 600:
        pm.printWarning(report, 'Session Timeout이 10분 이상으로 설정되어 있습니다.')
    else:
        isTimeout = True

    if isTimeout:
        pm.printSafe(report)
    else:
        pm.printNotsafe(report)
        pm.printSolution(report, '[U-54] 조치 방법')
        pm.printSolution(report, '\tSession Timeout을 10분 이하로 설정하세요.')
        pm.printSolution(report, '\t\t텍스트 에디터를 이용하여 \"~/.bashrc\" 파일을 엽니다.')
        pm.printSolution(report, '\t\t아래의 내용을 수정 또는 추가하세요.')
        pm.printSolution(report, '\t\t  TMOUT=600')
        pm.printSolution(report, '\t\t  export TMOUT\n')

    report.close()
Exemple #18
0
def U08():
    report = pm.openReport('U-08.txt')
    pm.printTitle(report, '[U-08] /etc/shadow 파일 소유자 및 권한 설정')

    isShadow = path.isfile('/etc/shadow')
    if not isShadow:
        pm.printNotice(report, '/etc/shadow 파일이 없습니다.')
        report.closed()
        return

    status = stat('/etc/shadow')

    isRightOwner = False
    owner = status.st_uid
    if owner == 0:
        isRightOwner = True
        pm.printNotice(report, '/etc/shadow 파일의 소유자가 root 입니다.')
    else:
        pm.printWarning(report, '/etc/shadow 파일의 소유자가 root가 아닙니다.')

    isRightPerm = False
    perm = int(oct(status.st_mode)[-3:])
    if perm == 400:
        isRightPerm = True
        pm.printNotice(report, '/etc/shadow 파일의 권한이 400 입니다.')
    else:
        pm.printWarning(report, '/etc/shadow 파일의 권한이 400이 아닙니다.')

    if isRightOwner and isRightPerm:
        pm.printSafe(report)
    else:
        pm.printNotsafe(report)
        pm.printSolution(report, '[U-08] 조치 방법')
        pm.printSolution(report, '\t/etc/shadow 파일의 소유자를 root로 권한을 400으로 변경하세요.')
        pm.printSolution(report, '\t\t#chown root /etc/shadow')
        pm.printSolution(report, '\t\t#chmod 400 /etc/shadow\n')

    report.close()
Exemple #19
0
def U45():
    report = pm.openReport('U-45.txt')
    pm.printTitle(report, '[U-45] root 계정 su 제한')

    isSafe = False
    tocheck = 'auth required pam_wheel.so'
    tocheck = ''.join(tocheck.split())
    f = open('/etc/pam.d/su', 'r')
    for line in f:
        line = ''.join(line.split())
        if tocheck in line:
            # 주석인지 확인
            if not ('#' in line):
                isSafe = True
    f.close()

    if isSafe:
        pm.printNotice(report, '특정 그룹만 su 명령어를 사용할 수 있습니다.')
        pm.printSafe(report)
    else:
        pm.printWarning(report, '모든 사용자가 su 명령어를 사용할 수 있습니다.')
        pm.printNotsafe(report)
        pm.printSolution(report, '[U-45] 조치 방법')
        pm.printSolution(report, '\t특정 그룹의 사용자만 su 명령어를 사용하도록 제한시키세요.')
        pm.printSolution(report, '\t\twheel 그룹이 존재하지 않을 시 wheel 그룹을 생성하세요.')
        pm.printSolution(report, '\t\t  # groupadd wheel')
        pm.printSolution(report, '\t\twheel 그룹에 su 명령어를 사용할 사용자를 추가하세요.')
        pm.printSolution(report, '\t\t  usermod -G wheel <user_name>')
        pm.printSolution(report,
                         '\t\t텍스트 에디터를 이용하여 \"/etc/pam.d/su\" 파일을 엽니다.')
        pm.printSolution(report, '\t\t아래와 같이 주석을 제거하거나 설정하세요.')
        pm.printSolution(report, '\t\t  auth  sufficient  pam_rootok.so')
        pm.printSolution(
            report,
            '\t\t  auth  required    pam_wheel.so  debug group=wheel\n')

    report.close()
Exemple #20
0
def U01():
    report = pm.openReport('U-01.txt')
    pm.printTitle(report, '[U-01] root 계정 원격 접속 제한')

    isSafeLogin = False
    tocheck = 'pam_securetty.so'
    f = open('/etc/pam.d/login', 'r')
    for line in f:
        if tocheck in line:
            index = line.find(tocheck)
            # 주석인지 확인
            if '#' in line[:index]:
                continue
            else:
                isSafeLogin = True
    f.close()
    if not isSafeLogin:
        pm.printWarning(report, '\"/etc/pam.d/login\" 파일 내용의 확인이 필요합니다.')

    # securetty 파일이 없는 경우도 있었음
    isSafeSecuretty = True
    if path.isfile('/etc/securetty'):
        tocheck = 'pts'
        f = open('/etc/securetty', 'r')
        for line in f:
            if tocheck in line:
                index = line.find(tocheck)
                # 주석인지 확인
                if '#' in line[:index]:
                    continue
                else:
                    isSafeSecuretty = False
        f.close()
        if not isSafeSecuretty:
            pm.printWarning(report, '\"/etc/securetty\" 파일에 pts 관련 내용이 있습니다.')

    # KISA 매뉴얼과 별개로 sshd_config 파일도 검사
    isSafeSshd = True
    if path.isfile('/etc/ssh/sshd_config'):
        tocheck = 'PermitRootLogin'
        f = open('/etc/ssh/sshd_config', 'r')
        for line in f:
            if tocheck in line:
                index = line.find(tocheck)
                # 주석인지 확인
                if '#' in line[:index]:
                    continue
                else:
                    isSafeSshd = False
        f.close()
        if not isSafeSshd:
            pm.printWarning(
                report,
                '\"/etc/ssh/sshd_config\" 파일에 PermitRootLogin 관련 내용이 있습니다.')

    if isSafeLogin and isSafeSecuretty and isSafeSshd:
        pm.printSafe(report)
    else:
        pm.printNotsafe(report)
        pm.printSolution(report, '[U-01] 조치 방법')
        pm.printSolution(report, '\troot 계정의 원격 접속을 차단하세요.')
        pm.printSolution(report,
                         '\t\t텍스트 에디터를 이용하여 \"/etc/pam.d/login\" 파일을 엽니다.')
        pm.printSolution(report, '\t\t아래의 내용을 수정 또는 추가하세요.')
        pm.printSolution(report, '\t\tauth required pam_securetty.so')
        pm.printSolution(report,
                         '\t\t텍스트 에디터를 이용하여 \"/etc/securetty\" 파일을 엽니다.')
        pm.printSolution(report, '\t\tpts 관련 내용을 제거하세요.')
        pm.printSolution(report, '\tssh를 사용 중이라면 ssh를 통한 root 접속을 차단하세요.')
        pm.printSolution(
            report, '\t\t텍스트 에디터를 이용하여 \"/etc/ssh/sshd_config\" 파일을 엽니다.')
        pm.printSolution(report, '\t\tPermitRootLogin 내용을 제거하세요.\n')

    report.close()
Exemple #21
0
def U02():
    report = pm.openReport('U-02.txt')
    pm.printTitle(report, '[U-02] 패스워드 복잡성 설정')
    pm.printNotice(report, '기존에 설정 되어 있는 패스워드에 대해서는 점검할 수 없습니다.')

    isSafe = False
    output = subprocess.getoutput('dpkg -l | grep libpam-pwquality')
    if not ('libpam-pwquality' in output):
        pm.printWarning(report, 'pwquality.conf 파일이 존재하지 않습니다.')
        pm.printWarning(report, 'libpam-pwquality를 설치해 주세요.')
        pm.printWarning(report, '# apt install libpam-pwquality')

    else:
        # pam_pwquality로 수정
        tocheck = 'password requisite pam_pwquality.so'
        tocheck = ''.join(tocheck.split())
        f = open('/etc/pam.d/common-password', 'r')
        for line in f:
            line = ''.join(line.split())  # 공백 제거
            if tocheck in line:
                # 주석인지 확인
                if '#' in line:
                    continue

                isSafe = True
                # minlen
                index = line.find('minlen=')
                if index < 0:
                    pm.printWarning(report, '최소 길이가 설정되어 있지 않습니다.')
                else:
                    index += len('minlen=')
                    minlen = ''
                    while line[index] > '0' and line[index] < '9':
                        minlen = minlen.join(line[index])
                        index += 1
                    if int(minlen) < 8:
                        pm.printWarning(report, '최소 패스워드 길이가 8 미만입니다.')
                        pm.printWarning(report,
                                        '현재 최소 길이는 ' + minlen + ' 입니다.')
                        isSafe = False
                    else:
                        pm.printNotice(report, '현재 최소 길이는 ' + minlen + ' 입니다.')

                # lcredit
                index = line.find('lcredit=-1')
                if index < 0:
                    pm.printWarning(report, '소문자 요구가 설정되어 있지 않습니다.')
                    isSafe = False
                else:
                    pm.printNotice(report, '소문자 요구가 설정되어 있습니다.')
                # ucredit
                index = line.find('ucredit=-1')
                if index < 0:
                    pm.printWarning(report, '대문자 요구가 설정되어 있지 않습니다.')
                    isSafe = False
                else:
                    pm.printNotice(report, '대문자 요구가 설정되어 있습니다.')
                # dcredit
                index = line.find('ucredit=-1')
                if index < 0:
                    pm.printWarning(report, '숫자 요구가 설정되어 있지 않습니다.')
                    isSafe = False
                else:
                    pm.printNotice(report, '숫자 요구가 설정되어 있습니다.')
                # ocredit
                index = line.find('ucredit=-1')
                if index < 0:
                    pm.printWarning(report, '특수문자 요구가 설정되어 있지 않습니다.')
                    isSafe = False
                else:
                    pm.printNotice(report, '특수문자 요구가 설정되어 있습니다.')
        f.close()

    if isSafe:
        pm.printSafe(report)
    else:
        pm.printNotsafe(report)
        pm.printSolution(report, '[U-02] 조치 방법')
        pm.printSolution(report, '\tlibpam-pwquality 패키지를 설치하세요.')
        pm.printSolution(report, '\t\t# apt install libpam-pwquality')
        pm.printSolution(report, '\t패스워드 복잡성 설정 파일의 내용을 내부 정책에 맞도록 수정하세요.')
        pm.printSolution(
            report,
            '\t\t텍스트 에디터를 이용하여 \"/etc/pam.d/common-password\" 파일을 엽니다.')
        pm.printSolution(report, '\t\t아래의 내용으로 수정하세요.')
        pm.printSolution(
            report,
            '\t\tpassword requisite pam_pwquality.so retry=3 minlen=8 ')
        pm.printSolution(report,
                         '\t\t\tlcredit=-1 ucredit=-1 dcredit=-1 ocredit=-1')
        pm.printSolution(report, '\t\t  lcredit=-1 : 소문자 최소 1자 이상 요구')
        pm.printSolution(report, '\t\t  ucredit=-1 : 대문자 최소 1자 이상 요구')
        pm.printSolution(report, '\t\t  dcredit=-1 : 숫자 최소 1자 이상 요구')
        pm.printSolution(report, '\t\t  ocredit=-1 : 특수문자 최소 1자 이상 요구')
        pm.printSolution(report, '\t\t  minlen=8   : 최소 8자리 이상 요구')
        pm.printSolution(report, '\t\t  retry=3    : 3번 재입력 가능\n')

    report.close()