취약한 패스워드 해시 알고리즘을 사용하는 계정 찾는 방법

uncools·2023년 6월 12일
0

패스워드 방식 인증을 잘 사용하지 않는데?

오늘날 많은 리눅스 시스템은 SSH 키 방식으로 시스템을 접속한다.
패스워드 방식으로 사용하여 인증을 하는 시스템을 보기가 어려워졌다.

패스워드 방식을 사용하지 않으므로 패스워드 해시 알고리즘을 볼 경우도 없다.
root 계정이외 다른 계정에 패스워드가 존재하는 계정을 본 것도 오래 되었다.

그러나 간간히? 어쩌면? 정말? 정말? 지나가다가.. 일부 시스템에 패스워드 방식 인증을 사용 하고 있는 경우가 확인된다.

이러한 시스템 중 일부는 여전히 취약한 패스워드 해시 알고리즘 으로 사용하고 있다.

어떻게 확인?

  • /etc/shadow 파일을 열어서 각 사용자 계정에 대한 해시 값을 확인한다.
  • 계정명 다음의 $ 가 해시 알고리즘 이다.
no구분해시 알고리즘
1$1MD5
2$2aBlowfish
3$5SHA-256
4$6SHA-512
  • 이런 형식이다.
root@buddy01:~:# vim /etc/shadow

.. 생략 ..
jackson:$1$mh8p2Qat$NkobYtLOHl3.ry

어떤 것이 취약?

  • MD5 가 존재한다면 취약한 계정이다. 다 아는 말이다.
  • 요즘 OS, 아니 단종된 OS가 아니라면, 기본값을 MD5 를 사용하는 경우가 없다.

이제는 MD5 해시가 보인다면 의도적으로 MD5 로 생성 한 것인가? 를 고민해보는 것이 빠르다.
무언가 자동화 스크립트, 세팅 스크립트를 사용 하였다면, 그 스크립트에 그렇게 되어 있을 확률이 있다.

무엇을 조치 해야 하는가?

  • MD5 해시 알고리즘은 복원하거나 패스워드 크래킹 공격에 취약할 수 있다.
  • 따라서 SHA-512 등으로 변경해서 사용해야 한다. >> 맞는 말이다.
    그러나 강조하고 싶은 부분은 어디에 MD5 해시를 가진 패스워드가 생성 되어 있는가? 이다.

사용자의 패스워드가 세팅이 되는 경우는, root 가 사용자가 계정을 생성 하고 (useadd)
패스워드를 설정할때 (만들어낼때) 거기에서 MD5 해시로 패스워드를 저장한다.
이 포인트 또는 계정의 패스워드를 설정 하는 부분을 확인하여, 거기를 조치해야 한다.

패스워드를 만들어 내는 부분이 있다면, 거기를 잘 살펴 보자.
mkpasswd 또는 openssl 명령어를 이용하여 패스워드를 생성 하면서 MD5 해시 알고리즘을 고정 해두었을 수 있다.
(예시) 아래와 같은 커맨드를 사용하여, 자동으로 패스워드를 생성 한다.

예시- Using mkpasswd

root@ansible-controller:~/# mkpasswd -m sha-512
Password:
$6$KU2P9m78xF3n$noEN/CV.0R4qMLdDh/TloUplmJ0DLnqi6/cP7hHgfwUu.D0hMaD2sAfxDT3eHP5BQ3HdgDkKuIk8zBh0mDLzO1

Other Options -
root@ansible-controller:~/# mkpasswd — help
Usage: mkpasswd [OPTIONS]… [PASSWORD [SALT]]
Crypts the PASSWORD using crypt(3).
-m, — method=TYPE select method TYPE
-5 like — method=md5
-S, — salt=SALT use the specified SALT
-R, — rounds=NUMBER use the specified NUMBER of rounds
-P, — password-fd=NUM read the password from file descriptor NUM
instead of /dev/tty
-s, — stdin like — password-fd=0
-h, — help display this help and exit
-V, — version output version information and exit
If PASSWORD is missing then it is asked interactively.
If no SALT is specified, a random one is generated.
If TYPE is ‘help’, available methods are printed.

예시- Using openssl

root@ansible-controller:~/# openssl passwd -6
Password:
Verifying — Password:
$6$SX8O9xVd1d/WX2hm$vh9RI2WCnh1BKwmHU2QHX5/ZMwH45zLpVe5v7EykPvjtiNGeYqje9GH2l/dZruVP0kYyPecJRGz1XfYpLERHh0

Other options -
root@ansible-controller:~/# openssl passwd — help
Usage: passwd [options]
Valid options are:
-help Display this summary
-in infile Read passwords from file
-noverify Never verify when reading password from terminal
-quiet No warnings
-table Format output as table
-reverse Switch table columns
-salt val Use provided salt
-stdin Read passwords from stdin
-6 SHA512-based password algorithm
-5 SHA256-based password algorithm
-apr1 MD5-based password algorithm, Apache variant
-1 MD5-based password algorithm
-aixmd5 AIX MD5-based password algorithm
-crypt Standard Unix password algorithm (default)
-rand val Load the file(s) into the random number generator
-writerand outfile Write random data to the specified file

결론

  • MD5 로 된 계정은 패스워드를 변경해야 한다. 무엇으로? SHA-512 로 하면 된다.
  • 아래는 /etc/passwd 파일을 확인 > 리스트업 > MD5 해시 알고리즘을 찾는 간단한 코드이다.
#!/bin/bash


#
#################
# Colors
#################
#
    NORMAL="\e[39m"
    WARNING="\e[33m"  # Bad (red)
    SECTION="\e[33m"  # Section (yellow)
    NOTICE="\e[33m"   # Notice (yellow)
    OK="\e[32m"       # Ok (green)
    BAD="\e[31m"      # Bad (red)
    NA="\e[33m"       # Na  (Brown)

    # Real color names
    YELLOW="\e[33m"  
    WHITE="\e[37m"   
    GREEN="\e[32m"    
    RED="\e[31m"      
    PURPLE="\e[35m"
    MAGENTA="\e[35m"
    BROWN="\e[33m"
    CYAN="\e[36m"
    BLUE="\e[34m"

Logo()
{
    echo -e "${GREEN}"
    echo "===================================================="
    echo -e "${NORMAL}"
}


check_if_vulnerable_password_hash_users_exists()
{
    local DESC="(*) 취약한 패스워드 해시 알고리즘을 사용하는 계정을 확인 합니다.\n - Check for using weak password hashing algorithm accounts."
    local CHECK_RESULT=""
    local n=1

    echo -e   "$DESC"
    echo "----------------------------------------------------"

    while IFS=: read -r username password uid gid full_name home_dir shell; do
      excluded_shells=("false" "nologin" "null" "halt" "sync" "shutdown")
      
      if [[ -n "$shell" && ! "${excluded_shells[*]}" =~ (^| )"$shell"( |$) ]]; then
          password_hash_entry=$(grep "^$username:" /etc/shadow | cut -d: -f2)
          hash_type=$(echo "$password_hash_entry" | cut -d'$' -f2)

          case $hash_type in
            1)
              hash_type_info="MD5"
              ;;
            2a)
              hash_type_info="Blowfish"
              ;;
            5)
              hash_type_info="SHA-256"
              ;;
            6)
              hash_type_info="SHA-512"
              ;;
            *)
              hash_type_info="No-password"
              hash_type="None"
              ;;
          esac

          if [[ $hash_type == "6" ]]; then
              RESULT_DATA=$RESULT_DATA
              echo -e "$n. [${OK}Ok${NORMAL}] $username : ${YELLOW}$hash_type_info${NORMAL} $shell"
          elif [[ $hash_type == "None" ]]; then
              RESULT_DATA=$RESULT_DATA
              echo -e "$n. [${OK}Ok${NORMAL}] $username : ${WHITE}$hash_type_info${NORMAL} $shell"
          else
              CHECK_RESULT=$CHECK_RESULT"Vulnerable\n"
              echo -e "$n. [${BAD}BAD${NORMAL}] $username : ${RED}$hash_type_info${NORMAL} $shell"
          fi

          ((n++))
      fi
    done < /etc/passwd

    echo ""
    if [ `echo -e $CHECK_RESULT | grep "Vulnerable" | wc -l` -ge 1 ]; then
        echo -e ">> 점검 결과: ${BAD}취약${NORMAL}"
    else
        echo -e ">> 점검 결과: ${OK}양호${NORMAL}"
    fi

}


START()
{
    Logo

    check_if_vulnerable_password_hash_users_exists

    echo "[+]["`date +%y-%m-%d-%H%M%s`"]"
}

START
profile
가이드, 팁, 코드 조각의 기록과 공유

0개의 댓글