웹 애플리케이션을 개발하고 운영한다면 보안은 중요한 요소중에 하나입니다.

OWASP 는 3년마다 가장 중요한 취약점을 정리해서 발표하고 있는데 2020 년에 발표된 10대 취약점에 대해 정리했습니다.


Injection(인젝션)


인젝션은 공격자가 web application 에 신뢰할 수 없는 데이타를 보내서 내부 데이타에 접근하는 공격이며 제일 유명하고 일반적인 공격으로는 SQL Injection 이 있습니다.


개발자가 아래와 같이 client 가 보낸 데이터를 검증없이 사용하도록 코딩할 수 있습니다.

SQL Injection

String query = “SELECT * FROM accounts WHERE custID = ‘” + request.getParameter(“id”) + “‘”;
JAVA


이럴 경우 공격자가 아래처럼 parameter 를 전송할 경우 accounts 테이블 데이타에 바로 접근할 수 있습니다.

 http://example.com/app/accountView?id=’ or ‘1’=’1
CODE


Injection 을 막으려면 다음과 같은 기술이 필요합니다.


Client 가 보낸 데이터를 신뢰하지 않기

선량한 대다수의 client 에 소수의 공격자가 섞여 있을수 있으므로 client 의 데이터는 서버단에서 검증 및 SQL 의 특수 문자등을 소독해서 사용해야 합니다..


SQL 에 동적 쿼리 대신 parameter bind 사용


위와 같이 SQL 구문을 동적으로 생성하지 말고 Parameter 를 binding 해서 사용해야 합니다. 

SQL Injection

String query = “SELECT * FROM accounts WHERE custID = ? ”;

PreparedStatement statement = connection.prepareStatement(query );
statement.setInt(1, request.getParameter(“id”));
JAVA


쿼리 결과 갯수 제한

LIMIT 등을 적용해서 SQL Injection 이 되어도 레코드가 대량 유출되지 않도록 쿼리를 작성합니다. 쿼리 건수 제한은 서버의 응답 성능 개선과 안정성에도 중요한 용소입니다.


Broken Authentication(취약한 인증)

취약한 인증은 공격자가 수동 및 자동화된 방법으로 시스템에서 원하는 계정을 제어할 수 있는 취약점입니다.


예로 로그인 페이지에 대해 brute force 공격을 허용하거나 취약한 비밀번호와 암호 알고리즘을 사용하거나 세션 관리를 제대로 하지 않는 경우가 있습니다.


이 취약점을 방지하려면 다음과 같은 작업을 수행해야 합니다.


관리자 로그인 기능 제한

Wordpress 등은 웹 기반 설치를 위해 wp-admin URL 에서 관리자로 로그인 할 수 있습니다.


설치가 끝났다면 URL 을 삭제하고 whitelist 기반의 IP 접근 제어를 걸어서 관리자 기능은 정해진 곳에서만 접근가능하게 해야 합니다.


유추 가능한 관리자 이름 사용 안 하기

root, admin, sysadm 같은 유추 가능한 관리자 이름을 사용하지 않아야 합니다.


brute force 방지

일정 횟수 이상의 login 실패시 계정이 잠기거나 정해진 시간이후에 시도 가능한 login throttling 기능등을 적용해야 합니다.


Sensitive Data Exposure(민감 데이타 유출)


안전하게 보호해야 할 민감 데이타들은 다음과 같습니다.

  • 신용 정보
  • 신용카드 번호
  • 주민/외국인 번호
  • 의료 정보
  • 생체등 개인 식별 정보(Personally identifiable information (PII)
  • 그외 개인 정보


특히 유럽의 개인정보 보호법인 GDPR 은 민감한 정보를 제대로 안 다루어 보안 사고가 발생했을 경우 사업자에게 엄청난 과징금을 매기고 있으니 특히 주의해야 합니다.


데이타는 DBMS 등에 저장되는 "저장 데이타(stored data)" 와 브라우저나 클라이언트등에 전송하는 "전송 데이타(Transmitted data)" 2가지 유형이 있습니다.


OWASP 에서 제시하고 있는 예제 공격 시나리오는 다음과 같습니다.


시나리오 #1: 

application 은 신용 카드 번호를 DBMs 에 저장시 자동으로 암호 알고리즘을 사용해서 저장합니다. 하지만 DBMS 에서 정보를 가져올 때 자동으로 복호화하므로 SQL injection 공격으로 신용 카드 번호를 가져올 수 있습니다.


시나리오 #2: 

사이트가 모든 페이지에서 TLS 를 사용하지 않거나 약한 암호화 알고리즘을 사용할 경우 공격자는 네트워크 트래픽을 모니터링하고 중간자 공격을 통해 HTTPS 를 HTTP 로 전환하여 사용자의 요청을 가로채고 세션 쿠키를 훔칠수 있습니다.

공격자는 쿠키를 전송해서 사용자의 세션을 가로 채고 사용자 개인 데이터에 엑세스 하거나 수정할 수 있습니다.


시나리오 #3: 

비밀번호를 저장소 hash 에 salt 를 추가하지 않았다면 레인보우 테이블을 사용해서 비밀번호를 알아 낼 수 있습니다.

또 강력한 알고리즘으로 암호화하지 않았다면 salt 가 있더라도 GPU 연산으로 크랙할 수 있습니다.

전송 데이타 보호

전송 데이타를 보호하려면 SSL/TLS 같은 End to End 암호화 방식을 사용해서 전송 구간을 보호해야 합니다.

특히 SSL/TLS 는 중간자 공격이 가능하므로 HSTS(http strict transport security)를 사용해서 중간자 공격을 차단해야 합니다.


데이타 유출을 방지하려면

  • 먼저 데이타를 분류하고 민감 정보를 식별한 후에 정보의 중요성에 맞게 보호 조치를 강화합니다.
  • 특히 민감 데이타는 사업상 필요가 없다면 아예 보관하지 않는게 좋습니다.
  • 모든 민감 데이터는 강력한 표준 알고리즘을 사용해서 암호화하고 암호화 키는 HSM 등의 별도의 하드웨어나 AWS Key Management Service 나 Azure의 key Vault 같은 안전한 보관소를 통해 관리해야 합니다.
  • 사용자의 암호는 argon2, scrypt, bcypt, PBKDF2 같은 강력한 단방향 암호화 알고리즘을 사용하고 적당한 salt 와 지연 요소를 가진 알고리즘을 사용해야 합니다. (Argon2 추천)


XML External Entities (XXE)

XXE 는 일부 오래된 XML 파서가 외부 엔터티의 검증을 철저하게 하지 않는 점을 악용한 취약점 공격 방법입니다.


공격자는 취약점이 있는 XML 을 upload 해서 서버에서 이를 처리하게 해서 데이터를 유출하게 하거나 특정 명령을 실행하게 합니다.


OWASP 에서 제시하고 있는 예제 공격 시나리오는 다음과 같습니다.


시나리오 #1: 서버의 passwd 파일 유출 시도

passwd 파일 유출

<?xml version="1.0" encoding="ISO-8859-1"?>
<!DOCTYPE foo [
<!ELEMENT foo ANY >
<!ENTITY xxe SYSTEM "file:///etc/passwd" >]>
<foo>&xxe;</foo>
XML


시나리오 #2:  서버의 private network 환경 정보 유출

<!ENTITY xxe SYSTEM "https://192.168.1.1/private" >]>
XML


시나리오 #3: 서버의 random 디바이스를 활용해서 DOS 공격 시도

passwd 파일 유출

<!ENTITY xxe SYSTEM "file:///dev/random" >]>
XML

Broken Access control(취약한 접근 제어)

인증된 사용자가 수행할 수 있는 권한과 페이지에 대한 제한이 제대로 구현되어 있지 않다면 공격자는 이를 악용하여 관리자 권한에 접근하거나 사용자는 제약이 있는 비즈니스 로직을 수행하거나, 데이터 수정/삭제등 비즈니스의 안정성에 영향을 미치는 여러 행위를 할 수 있습니다.


접근 제어 탐지는 일반적으로 자동화된 테스팅으로 감지하기가 어려우므로 매뉴얼 테스팅이 이런 문제를 찾아 내는대 더 효과적입니다.


OWASP 에서 제시하고 있는 예제 공격 시나리오는 다음과 같습니다.


시나리오 #1: 다른 사용자로 전환 시도


아래와 같이 파라미터를 통해 account 권한을 설정하고 있는 코드를 작성했으면 

pstmt.setString(1,request.getParameter(“acct”)); 
ResultSetresults =pstmt.executeQuery( );
JAVA


공격자는 URL 에 파라미터를 넣어서 관리자 권한을 획득할 수 있습니다.

http://example.com/app/accountInfo?acct=root
CODE


시나리오 #2: 강제 브라우징(force browsing)


제대로 된 접근 제어가 되지 않을 경우 공격자는 특정 권한으로 볼 수 있는 URL 을 강제로 입력해서 데이타를 보거나 권한을 획득할 수 있습니다.

http://example.com/app/admin_getappInfo
CODE


공격을 방지하려면 다음과 같은 예방이 필요합니다.


  • 모든 퍼블릭 리소스는 deny 를 기본 정책으로 설정
  • Model 에 대한 접근 제어는 레코드의 소유자만 가능하도록 강제합니다. 예로 "John" 이란 사용자는 CRUD 권한을 본인 소유인 model 에 대해서만 수행할 수 있도록 강제합니다.
  • web server 가 file metadata 에 대해 직접 엑세스 하는 것을 차단합니다. 예로 .git 이나 .svn 같은 폴더에 엑세스하게 하면 app 의 소스를 모두 볼수가 있으니 접근을 차단합니다.
  • access control 이 실패한 내역을 로그로 남기고 정기적으로 내역을 분석하고 IP 차단등의 후속 조치를 취합니다.
  • API 와 Controller 를 호출할 때 호출 건수등의 제약을 겁니다.
  • logout 후에 JWT 토큰을 서버에서 무효화합니다.


Security misconfigurations


Cross Site Scripting (XSS)


Insecure Deserialization


Using Components with known vulnerabilities


Insufficient logging and monitoring



Ref