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()
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()
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()
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()
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()
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()
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()
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()
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()
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()
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()
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()
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()
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()
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()
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()
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()
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()