티스토리 뷰

개요

 

Slack slash command 메시지를 보내올때에, 그것이 Slack 에서 보내온 것인지 검증해보자.

링크: https://api.slack.com/docs/verifying-requests-from-slack

 

(참고) 현재까지 관련 포스팅 모음

- Golang: Github - Travis-CI - Heroku: https://jusths.tistory.com/69

- Slack slash command + Golang server: https://jusths.tistory.com/72

- slack slash command 는 무얼 보내주는 걸까: https://jusths.tistory.com/73

 

 

Signing secret

 

Slack 앱을 등록하면 Slack unique string Signing secret 생성해준다.

우리는 Signing secret 이용하여 Vefification 수행한다.

, Golang 서버가 Slack 에서 보냈다는 HTTP POST message 받으면, 정말 Slack 에서 보냈는지를 검증한다.

 

https://api.slack.com 에서 App Basic Information 보면  Signing secret 정보를 확인할 있다.

 


 

 

프로세스는 다음과 같다.

 

Slack 설정에 등록된 우리의 Golang 서버에 다음과 같이 signature 붙여서 HTTP POST request 보낸다.

 

1) Slack (당연히) 앱의 Signing secret 가지고 있고, Golang 서버 역시 동일한 정보를 알고 있도록 한다. (환경변수 등등)

2) Slack Signing secret 전송하려는 body HMAC 이용하여 signature 만든다.

- HMAC 참고: standard HMAC-SHA256 keyed hash

3) Slack 보내는 HTTP POST header X-Slack-Signature 바로 이렇게 만든 signature 들어간다.

- 보내려는 내용인 body

- Signing secret 으로 서명 작업을 하면 나오는 것이

- 바로 body signature 것이다.

그래서 body 마다 고유의 signature 가지게 된다.

 

그러면 HTTP POST 받은 Golang server 다음과 같은 작업을 하게 된다.

 

1) Golang server Slack 똑같은 Sigining secret 가지고 있다.

2) Signing secret 받은 HTTP POST body HMAC 이용하여 signature 만든다.

3) 이렇게 Golang server 만든 singature HTTP POST header X-Slack-Signature (= Slack 만든 signature) 값이 같은지를 확인한다. 똑같다면 verified!

 

이렇게 하면 다음과 같은 강점을 가지게 된다.

 

1) request 마다 body 바뀌니 매번 unique signature 생성된다.

2) Slack Golang server 공유한 Signing secret 정보는 HTTP POST request 들어가지 않는다.

 

(참고) Go 말고 다른 언어들 - Node, Python SDK 있음

- https://api.slack.com/docs/verifying-requests-from-slack#sdk_support

 

 

Golang server 에서 signature 만들기

 

필요한 재로는 다음과 같다.

 

1) Slack 에서 HTTP POST request

2) signing 사용될 Signing secret (슬랙이 생성해서 앱에 공유해준거)

3) 사용할 프로그래밍 언어 - 우리는 Golang

 

* 파이썬 구현 참고: https://goo.gl/9Ttqci

 


 

파이썬의 구현코드를 참고하여 프로세스를 정리해보면 다음과 같다.

 

1) Slack HTTP POST request 에서 X-Slack-Request-Timestamp body 가져온다.

2) version number + timestamp + body basestrintg 으로 concatenate 해준다.

- ex) v0:123456789:command=/weather&text=94070

3) 위의 basestring , Server 가지고 있는 Signing secret key 하여,

4) 프로그래밍 언어가 제공하는 HMAC SHA256 이용해 signing 한다.

5) Request Header X-Slack-Signature 값과 생성한 값이 같으면 verify

 

 

Step-by-step 으로 알아보자

 

1) Signing secret

 

- https://api.slack.com 에서 App Basic Information 보면  Signing secret 정보를 확인할 있다.

- utf-8 포맷의 string 이라 생각하자.

- ex) 8f742231b10e8888abcd99yyyzzz85a5

 

 

2) Request body 추출

 

- HTTP POST request Parsing 하면 아래와 같은 body 값을 얻을 있다.

 

token=xyzz0WbapA4vBCDEFasx0q6G&team_id=T1DC2JH3J&team_domain=testteamnow&channel_id=G8PSS9T3V&channel_name=foobar&user_id=U2CERLKJA&user_name=roadrunner&command=%2Fwebhook-collect&text=&response_url=https%3A%2F%2Fhooks.slack.com%2Fcommands%2FT1DC2JH3J%2F397700885554%2F96rGlfmibIGlgcZRskXaIFfN&trigger_id=398738663015.47445629121.803a0bc887a14d10d2c447fce8b6703c

 

3) Timestamp 주출

 

- 마찬가지로 다음과 같은 포맷의 timestamp 얻을 있다 (UNIX time): 1531420618

Timestamp 는 replay attack 대비로 의미가 있다.

replay attack 체크로 현재시간보다  5분이상 지난건 버려버리는 것도 좋다.

 

4) 합체 (Concatenate)

 

- 버전:타임스탬프:바디 합체

- delimiter colon, ":" 이다.

 

5) signing secret 으로 합체 스트링을 hash 해준다.

 

- 그리고 hash 결과인 string 앞에 "v0=" 을 붙여준다.

예를 들어

- hash 결과: a2114d57b48eac39b9ad189dd8316235a7b4a8d21a10bd27519666489c69b503

- "v0=" 붙여주기: v0=a2114d57b48eac39b9ad189dd8316235a7b4a8d21a10bd27519666489c69b503

 

6) 비교

 

위 결과와 Request header 의 signature 를 비교해서 같으면 OK

 

기타등등

 

- Signing secret 유출되었다면 울지말고 새로 생성하면 .

- JSON 이나 다른 것으로 deserialize 되기전의 raw request body 사용할


반응형
반응형
잡학툰 뱃지
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
«   2024/11   »
1 2
3 4 5 6 7 8 9
10 11 12 13 14 15 16
17 18 19 20 21 22 23
24 25 26 27 28 29 30
글 보관함