web security

박정빈·2024년 11월 28일

정보보호

목록 보기
12/14

Web Shell
Cookie
Session management
XSS
CSRF
SQL Injection
OWASP Top10
OAuth

개요

웹의 첫 시작은 물리학자가 열었다. 초기 웹은 하이퍼텍스트를 누르면 다른 웹을 불러오는, stateless 한 상태였다. 하지만 웹이 발전이 되고 상업적으로 사용하기 시작하면서 statefull 한 상태가 개발되었고, 이에 따라 여러 문제가 발생하게 되었다. 특히 보안쪽은 전혀 염두에 두지 않고 개발되었기에 초기에는 보안 취약점들이 굉장히 많았다.

웹 클라이언트와 서버가 소통을 할때는 아래의 request,response 메세지를 주고 받으면서 한다.

기본적으로는 이런 메세지를 stateless 한 상태에서 날리게 된다.

web shell

shell 이라고 하면 리눅스 쉘이 떠오른다.
내가 어드민 권한으로 리눅스에서 쉘을 띄울 수 있다는 것은 그 시스템에 대해서 모든 것을 할 수 있다는 것이다.

웹쉘은 웹서버에 접속을 할 때, 브라우저로 하는게 아니라 브라우저에 쉘을 띄워서 그 시스템을 컨트롤하겠다라는 것이다.

MITRE(마이터)는 미국에 있는 보안관련 비영리기관이다.
공격,취약점을 어떻게 부를 것인가에 대한 정의를 내린다.
이름을 붙여서 표준처럼 만든다.

웹쉘은 CWE-434 라고 부른다.

웹쉘은 웹서버가 실행파일이 업로드 됬을때 발생하는 취약점이다.
내가 올린 파일이 서버의 어디에 저장되는지 알 수 있다면,
URL에 그 경로를 넣고 GET 하면 정보를 탈취할 수 있게된다.

쉘파일(예~.exe,~.php)을 업로드 했다고 하자, 그 디렉토리를 알고 있다면, 그 실행파일을 실행시켜서 쉘을 작동시킬 수 있다.

방어방법?
1. 파일업로드를 막아라 -> 말이 안됨 업로드를 하긴 해야함
2. 파일 확장자를 막아라 -> pdf 만 받는 사이트
3. size 체크
4. 저장되는 디렉토리의 파일 권한을 잘 설정을 해라 rwe 권한
5. 웹서버를 root 권한으로 돌리지 마라. 웹서버를 root 권한으로 돌리지 마라

우리나라는 시큐어코딩을 따라야한다는 것이 법에 박혀있다.
한국인터넷진흥원진흥원

statefull을 하고 싶다! 그게 뭐냐? 다시 웹사이트에 접속했을때 내가 누군지 웹이 알고 있어야한다.
클라이언트가 출입증같은 것을 제시해서 나를 증명하는 것이다.
짧은 text 이다.
인증, 선호도, 장바구니 등을 저장해놓을 수 있다.
유효기간, 어떤 도메인,path에서 유효한지에 대한 정보가 들어있다.
키,밸류로
쿠키에 민감한 정보가 있다면 다 유출, 변조될 수 있다. TLS,SSL에 의해 보호가 되어야함

클라이언트가 쿠키를 변조할 수 있다는 사실은 서버에게 위협이다.
서버는 값을 클라이언트에게 내려줄때, 자기만 알고 있는 키값K를 전달한다.M과 K를 HMAC해서 변조유무를 판단한다.

Session

세션 또한 웹을 statefull하게 해준다.
Referer 필드: 직전에 어떤 사이트를 갖다왔는지
session hijacking: tcp session 을 가로채는 것 -> 그 사람인양 할 수 있다.

예측가능한 토큰을 쓰면 안된다. (장바구니 값 , 계좌번호 등을 랜덤 값으로 바꿔야 함을 랜덤 값으로 바꿔야 함)

strong session token을 만들기 위해서
HMAC , SID=[userID, exp.time , client ip]
client ip 로만 보안을 설정하면 취약한 것
기존의 보안 규칙에 client ip 를 더하는 것은 좋은 것

XSS

(CWE-79) 웹페이지가 생성되는 동안에 input 값의 부적절한 중립화

  • persistent XSS(stored)

예전에는 글을 작성할때 글에 자바스크립트 태그를 넣으면 자바스크립트를 실행시킬 수 있었다.
이 스크립트에 공격코드를 넣으면? 예를 들어 쿠키값을 볼 수 있게하면 세션하이제킹을 할 수 있다.

공격한 글이 서버에 계속 저장되기에 persistent,stored 라고 한다.

해결책
1. 태그로 인식될 수 있는 꺽쇠 < > 를 < > 로 표현한다.
2. 스크립트를 못쓰게 한다.

  • non-persistent XSS (reflected)

동작 방식:
악성 스크립트 삽입: 공격자가 URL에 악성 JavaScript 코드를 삽입하거나 폼에 악성 스크립트를 제출합니다.
서버의 반응: 웹 서버는 사용자로부터 입력받은 값을 검증 없이 그대로 페이지에 반영합니다. 이 과정에서 입력된 스크립트가 웹 페이지의 HTML에 삽입됩니다.
클라이언트에서 실행: 클라이언트(사용자의 브라우저)는 페이지를 렌더링하면서 악성 스크립트를 실행하게 됩니다.

예시:
공격자가 URL 파라미터를 악용하는 경우를 가정해 봅시다. 예를 들어, 사용자가 검색어를 입력하고 그 결과를 웹 페이지에 출력하는 사이트에서, 검색어를 입력한 URL이 다음과 같을 수 있습니다.

https://example.com/search?query=<script>alert('XSS')</script>

웹 서버가 query 파라미터의 값을 적절히 검증하지 않으면, alert('XSS') 스크립트가 해당 페이지에 삽입되어 브라우저에서 실행됩니다.

워터링홀

워터링홀(Watering Hole) 공격은 특정 그룹이나 조직을 타겟으로, 그들이 자주 방문하는 웹사이트를 악성 코드로 감염시켜 해당 그룹에 속한 사용자들을 공격하는 방식의 사이버 공격입니다.

이름은 야생 동물들이 물을 마시기 위해 특정 물웅덩이에 모이는 습성을 이용해 포식자가 매복하는 방식에서 유래되었습니다. 비슷하게 공격자는 특정 목표 그룹이 자주 방문하는 웹사이트를 감염시켜, 이를 통해 목표를 감염시키려 합니다.

lateral movement 횡적이동 
서버에서 옆에 있는 서버를 이동할때는 보통 방화벽이 없기 때문에 공격탐지가 쉽지 않다.

CSRF

Cross-Site Request Forgery(CSRF)
one click attack , session riding
CWE-352

XSS는 유저가 피해자 특정 사이트를 믿었는데 악용당했다.
CSRF는 서버,사이트가 유저를 믿었는데 악용당했다.

패스워드 변경시 이미 로그인 되어있는데도 패스워드를 입력하게 하는 것이 CSRF에 대한 방어책을 세운 사이트이다.

웹 서버가 관리자 계정의 새 비밀번호를 설정할 때 현재 비밀번호를 요구하지 않는다고 가정해보자, 공격자는 관리자의 다음 요청으로 비밀번호를 재설정할 것이라는 사실을 알고 있다 이때, 공격자는 XSS를 사용하여 관리자가 이를 실행하도록 만든다.

/changepasswd.jsp?newpassword=[new pwd]&confirmpassword=[new pwd confirmed]

해결책
1. 세션관리 타임아웃을 해놓지 않으면 공격할 기회가 늘어나는 것이다.
2. HTTP Referrer 헤더 확인
3. GET 및 POST 매개변수뿐만 아니라 쿠키에서도 인증 요구
4. 인증 쿠키의 수명 제한
5. POST 요청을 처리할 때 GET 매개변수 무시
6. 모든 폼 제출에 사용자별 비밀 토큰 요구

SQL Injection

CWE-89
SQL 쿼리에 값이 들어올때 안좋은 데이터를 처리하지 못하는 것

code injection 의 한 종류

$sql = "select * from members where id='$id' and password='$password';"

만약 위 쿼리의 $id'or'1=1'-- 를 넣는다면?

$sql = "select * from users where id = '' or '1=1' -- and password = '123123' ";

-- 뒤는 주석 처리가 되고 '' or '1=1'true 가 돼서 모든 사용자의 정보를 가져오게 된다.

만약 ′ ; DROP TABLE members -- 같은 값이 들어온다면, DB값이 다 지워질 것이다.

해결법
1. 사용자가 전달한 입력 매개변수를 절대 신뢰하지 않기
2. 폼 입력에서 ' " / \ ; 등 특수 문자를 필터링하기
3. 에러 메시지를 노출하지 않기 (공격자에게 정보를 알려주지 않는다)
4. 데이터베이스 계정의 권한을 낮추기

Insecure Direct Object Reference

열어놓은 곳 만 접속해야하는데 URI를 추측해서 직접 접속하는 방법
아래와 같은 주소들은 추측하기 쉽다.

http://onepiece-spoilers.blogspot.com/2009/08/one-piece-554-english.html
http://www.site.com/adm
http://www.site.com/admin_login.cgi
http://www.site.com/admin
http://www.site.com/webadmin
http://www.site.com/rhksflwk
http://www.site.com/manager
http://admin.site.com
http://manager.site.com
http://adm.site.com 
hardning CISCO router , hardening web server
config 설정같은 것을 강화해서 hardning을 잘 해야한다.

OAuth

역할

내가 웹개발자면 client를 개발할 것이다. 이때 우리 application 을 사용하는 사용자에게 OAuth 인증을 할 수 있는 서비스를 만들자
Google Calander 나 Kakao Login 과 같은 서비스를 사용할 수 있게 하려면 OAuth 인증절차를 거치게 해야한다.
사용자는 구글이나 카카오 계정을 이미 가지고 있다. 이 사용자를 resource owner라고 하자, 그렇다면 구글이나 카카오 서버는 resource server이다.

client resource owner resource server 이 삼자관계가 중요하다.

등록

일단 웹개발자인 나는 clientresource server에 등록시켜야한다. 서버마다 등록절차가 다르겠지만, Client ID , Client Secret , Authorized Redirect URIs를 공통적으로 등록하게 된다.
Client ID는 application을 식별할 수 있게하는 식별자 ,
Client Secret은 ID에 대한 비밀번호,
Authorized Redirect URIs는 정보전달을 위한 약속장소이다.

이 과정에서 clientresource serverClient ID , Client Secret , Authorized Redirect URIs 를 공유하게된다.

owner 승인

resource server가 가지고 있는 정보를 모두 얻고싶은게 아니라면, 모든 정보에 대한 승인을 할 필요가 없을 것이다.

예를 들어, 카카오 로그인을 할 때 성별,이름등은 얻고싶지 않고, 닉네임,프로필사진만 얻고 싶다면 해당 항목에 대한 승인만 받으면 된다.

clientresource owner에게 인증을 거쳐야한다는 화면을 보여준다. 카카오 로그인 버튼과 같은 것이다.
그러면 resource owner는 버튼을 통해 https://resource server uri/?client_id=1&scope=닉네임,프로필사진&redirect_uri=https://callback uri 로 이동할 수 있게 된다.
이 주소를 통해 resource server로 접속하게되고, 로그인이 필요하다면 로그인을 진행한다. 그러면 서버는 Client ID Authorized Redirect URI를 대조해서 맞는지 확인한다.
맞다면 serverscope=닉네임,프로필사진 에 대한 권한을 줄것인지 확인하는 UI를 보여줘서 확인을 하게하고 서버에 해당 user_idscope에 대한 권한에 동의했다는 정보를 저장한다.

서버owner에게 권한에 대한 동의를 구한 것이다.

server 승인

resource owner에게 인증을 받았으니, resource server에게도 인증을 받아야한다. 이때 사용되는 것이 authotization code이다. 서버는 오너에게 응답할때 헤더에 location:https://callback?code=3 을 포함해 보내고, 오너의 브라우저는 해당 위치로 이동하게 된다. 그렇게 되면 clientauthotization code를 알게 된다.

이제 client는 모든 값을 알고있다. 따라서 서버에 직접
https://resource server uri/token?grant_type=authorization_code&code=3&redirect_uri=https//callback&client_id=1&client_secret=2 이런 값들을 보낼 수 있게 된다.
서버는 자신이 알고 있는 값과 client가 보낸 값들을 비교해서 같다면,
authorization_code를 삭제하고, access token을 발급한다.

access token

서버는 발급한 access tokenclient에게 전달한다.
client는 해당 토큰을 사용하여 서버에게 인증을 하면,
해당 토큰은 user_id , scope등이 정해져 있으므로 어떤 유저의 어떤 권한을 줘야하는지 서버가 알 수 있게 한다.

API 호출

토큰을 발급한 서버는 미리 정해놓은 API들을 가지고 있다.
client는 API를 호출하며 토큰을 쿼리 파라미터나 Authorization : Bearer를 헤더로 전송하면 ,
인증을 하고, API의 기대되는 응답을 받을 수 있다.

reflesh token

access token은 유효 기간이 있다. 따라서 시간이 지나면 토큰은 만료되며,
토큰을 헤더에 담아 서버에 API요청을 보내면 거절된다.
access token을 새로 발급받아 요청을 해야하는데, 앞의 과정을 다시 거치기에는 굉장히 수고스럽다.
보통 access token을 발급받을때 reflesh token을 같이 받는다.
만약 access token이 만료되면, reflesh token을 보내서 access token을 새로 발급받고, 다시 요청을 진행한다.

0개의 댓글