Splunk 검색 명령어
데이터 나열, 변환 | table, rename, fields, dedup |
통계 계산 | stats, top, rare, len(x) |
차트 시각화 | timechart, chart |
비교분석 | eval, case, cidrmatch, if, like, match |
다중문자열과 시간 | mvindex, split, substr, round, ruldecode, strftime, strptime, now |
차트 시각화 명령어는 로그들이 텍스트로 되어 있기 때문에, visual 하게 보는 것이 로그에 대한 이해도를 높일 수 있기에 사용하는 명령어로, 보고서 쓸 때나 대시보드 구성할 때 많이 사용함
Splunk 검색 실습
검색하려고 할 때, 먼저 시간을 체크(전체시간으로 설정)
검색창에 필드명을 정확히 모를땐 키워드만 입력해도 충분히 찾을 수 있음
검색 > category*
검색 > 400
=> 데이터 길이가 400이거나, 오류코드가 400인 경우 등 400이 있는 것은 모두 찾음
=> 오류코드가 400인 경우를 원한다면 status=400(필드명과 필드값)을 입력해줘야함
검색 > status=400 categoryId=Null
=> status와 categoryId 사에에 and, && 연산자가 있는 것임
=> 두 개의 조건 모두 만족해야 검색됨
=> 클라이언트가 값을 넣을 때 categoryId를 설정하지 않아서 400 오류가 발생했음을 파악
=> 하나의 문장을 검색하고 싶을 때, access denied 같은 경우, "access denied"로 검색해야 함
큰따옴표를 사용하지 않으면 access && denied 가 검색되는 것임
검색 > 401 OR 402 OR 403
=> 만약 401나 402나 403을 검색하고 싶을 때, 401 OR 402 OR 403을 검색하면 됨(연산자 사용 시 대문자 사용)
=> 관계연산자가 소문자인 경우 검색결과 X
=> 우선순위의 경우 괄호 사용 가능
[검색 정리]
● 키워드로 검색 시 대소문자 구별 하지 않음
- error / ERROR 모두 가능
● 문자열을 검색하기 위해서는 큰따옴표 사용
- "access denied"
● 연산자 사용 시 반드시 대문자 사용
- 401 or 402 (X)
- 401 OR 402 (O)
- 연속하여 작성하면 AND 연산자가 생략된 것(401 402 403)
● 괄호를 이용하여 우선순위 지정 가능
- 401 AND (402 OR 403)
● 시간 점검 필수!!
● 자동완성기능 사용 추천!!
table
- 검색 결과를 테이블 형태로 보여주는 것
- 필드명은 대소문자를 구분해야 함
- 여러 개의 필드는 쉼표 또는 띄어쓰기로 구분
검색 > index=main sourcetype=access_combined_wcookie | table clientip, method, productId, status
=> 저장소를 인덱스라고 하는데, 저장소 이름 중에 main이라는 것이 있음.
=> main에서 sourcetype 중에서 access_combined_wcookie를 검색
=> 검색결과를 테이블 형태로 확인, 그때 clientip와 method, productID, status를 출력
rename
- 필드명을 다른 이름으로 변경
- 필드명을 띄어쓰기로 구분하고 싶으면 원하는 필드명을 따옴표로 표시
검색 > index=main sourcetype=access_combined_wcookie | table clientip, action, productId, status | rename action AS "Customer Action", productId AS ProductID, status AS "HTTP Status"
sort
- 검색 결과를 정렬
- 필드명을 띄어쓰기로 구분하고 싶으면 원하는 필드명을 따옴표로 표시
검색 > index=main sourcetype=access_combined_wcookie | table clientip, action, productId, status | sort action, -productId
=> action에 대해서 오름차순, productId에 대해서는 내림차순
=> +action / action 모두 오름차순(+ 생략 가능)
=> 기본 action으로 오름차순이고, 중복이 되는 데이터에 대해서는 productId를 기준으로 내림차순 정렬
dedup
- 검색 결과에서 중복값 제거
- 지정한 필드 기준으로 실행
- 두 개 이상 필드에서 중복을 제거하려면 쉼표로 구분
- 해당 필드에 존재하는 값을 확인하고 싶을 때 사용
검색 > index=main sourcetype=access_combined_wcookie status=404
검색 > index=main sourcetype=access_combined_wcookie status=404 | dedup host
=> 이 컴퓨터에는 404 코드가 잡힘
=> 몇 건이 있었어가 아니라 그냥 그런 일이 있었어
stats
- 통계함수를 이용하여 데이터 계산
함수명 | 설명 |
count(X) | 개수를 반환 |
dc(X) | 중복을 제거한 개수 반환 |
sum(X) | 총합 반환 |
avg(X) | 평균 반환 |
list(X) | 목록으로 만들어 반환 |
values(X) | 중복을 제거한 목록 반환 |
max(X), median(X), min(X) | 최대, 중앙, 최소값 반환 |
var(X) | 분산값 반환 |
stdev(X) | 표준편자 반환 |
검색 > index=main sourcetype="access_combined_wcookie"
=> 1665가 의미하는 게 뭘까?
=> > 이 부분 눌러서 확인하면 bytes 값임을 확인할 수 있음
검색 > index=main sourcetype="access_combined_wcookie" | stats sum(bytes), avg(bytes), max(bytes), median(bytes), min(bytes) by clientip
=> clientip를 기준으로 합계, 평균, 최댓값, 중간값, 최솟값을 검색
=> 통계치 구하기
=> 이 ip는 bytes가 왜 이렇게 많지? 이벤트보기로 해당 ip만 볼 수 있음
=> clientip들이 평균 얼마만큼의 데이터를 송수신하고 있는지 확인
top
- 지정한 필드에서 가장 많이 나오는 값을 보여주는 명령어
- 검색 결과를 파이프로 입력받아 계산한 후 결과 반환
- showperc와 showcount의 기본값이 T이므로 지정하지 않더라도 비율과 개수를 보여줌
limit | - 반환되는 결과 개수를 지정 - 숫자를 지정하지 않으면 기본적으로 10개로 설정 - 전체 값을 모두 보려면 limit=0 설정 |
showperc | - 해당 값이 차이하는 비율을 보여줌 - 기본값 T |
showcount | - 해당 값의 개수를 보여줌 - 기본값 T |
useother | Top10 외 다른 숫자의 크기를 알고 싶다면 T 입력 |
rare
- top과 반대의 결과인 빈도가 적은 값의 순서를 추출
- 희귀한 사이트로 가는 것, 빈도수가 낮은 사이트 방문, 얘는 왜 이 사이트를 방문했는가?
검색 > * | top useother=T clientip by method
검색 > * | rare useother=T clientip by method
=> top과 rare 결과의 차이!!
=> top 결과를 보면 method를 기준으로 clientip가 count 만큼 사용함을 확인(count가 많음)
=> rare 결과를 보면 많이 안 쓴 것들을 보여줌(ex. GET 메소드를 59개 사용, POST는 30개)
차트시각화
- 원본 로그 데이터로 차트 그리기는 불가능
- 데이터를 차트로 만들려면 먼저 관련 데이터 추출
- 시각화 원본 데이터를 통계 테이블로 변환
timechart
- 시간에 따른 통계 테이블 생성
- 시간 필드가 X축, 실제 데이터가 Y축에 표시되는 차트 시각화 형식으로 출력
- 시간에 따른 통계의 추세를 표시할 때 사용
- Span : 시간 계산 단위 설정
- Count : 전체 개수를 계산하는데 12시간 단위로 총 숫자를 구하여 보여줌
검색 > index=main sourcetype="access_combined_wcookie" | timechart span=12h count(clientip) as "Access Count"
=> 테이블로 만들어 놓은 것을 차트화 시킬 수 있음
=> 차트 모양도 바꿀 수 있고, 형식, 격자 레이아웃도 사용할 수 있음
[사내망의 로그들에 대해서]
HTTP 로그를 분석하여 이상징후를 탐색
DNS 로그를 분석하여 이상징후를 탐색
EndPoint 로그를 분석하여 이상징후를 탐색
=> 비교분석 명령어와 다중문자열과 시간 명령어를 엄청 많이 쓰게 됨
eval
- 검사 결과 값의 변환, 검증을 수행하며 함수 실행 결괏값을 반환
ex) eval status_code=if(status==200, "OK", "Error")
=> if 조건문(status가 200이면 OK 출력, 아니면 Error status_code에 저장)
ex) eval list="mozilla"
=> list(필드명X, 변수명O)
=> 변수명 앞에는 eval이 있음
case(X,"Y", ...)
- 여러 개 조건을 검증할 때 사용
- 두 개의 인자가 한 그룹으로 동작
ex) eval description=case(error==404, "Not found", error==500, "internal Server Error")
=> error가 404면 Not found를, 500이면 Internal Server Error를 descripsion 변수에 넣음
ex) eval quarter=case(date_month==“January”, “1Q”, date_month==“April”, “2Q”)
=> date_month가 January이면 1Q를, April이면 2Q를 quarter 변수에 넣음
cidrmatch("X",Y)
- Y가 네트워크 범위 X에 존재하는지 확인
- 반환값은 참/거짓
ex) eval local=cidrmatch(“10.0.0.0/8”, “10.10.0.100”)
=> 10.10.0.100이 10.0.0.0/8 대역에 포함되므로 True 반환
ex) | where (cidrmatch(“10.0.0.0/8”, ip) OR (cidrmatch(“172.16.0.0/12”, ip) OR (cidrmatch(“192.16.0.0/16”, ip)
=> ip가 주어지진 않았지만 ip가 X 범위에 포함된다면 True 반환, 3가지 값을 OR 연산을 해서 최종 참/거짓 반환
if(X,Y,Z)
- X가 참이면 Y, 거짓이면 Z 실행
ex) | eval ip1="10.10.0.100", ip2="100.10.0.100" | eval network1=if(cidrmatch("10.10.0.0/24", ip1),"local", "external"), network2=if(cidrmatch("10.10.0.0/24", ip2),"local", "external") | table ip1, network1, ip2, network2
=> 변수에 값 저장
=> cidrmatch는 참/거짓 반환하므로 network1에는 local 저장
=> cidrmatch는 참/거짓 반환하므로 network2에는 external 저장
like(X,"Y")
- X필드에서 일부 문자열 Y를 검색
- X에서 Y찾기
- like 함수의 와일드 카드는 %
ex) …| where like(field, “addr%”)
=> 변수 field가 addr로 시작하는지 검색
match(X,"Y")
- like 함수는 일부가 맞으면 참을 반환하지만 match는 함수명과 정확히 일치하는지를 비교
ex) match(filename, “malicious.exe”)
=> filename이 malicious.exe이면 참, 아니면 거짓 반환
=> 문자열 비교에 대소문자 구분 X
ex) match(filename, “(.jpg|.gif|.png)$”)
=> $ 앞의 문자로 끝난다는 의미
=> | 다중 선택 의미
=> filename이 .jpg, .gif, .png로 끝나는지 확인 (or)
=> 확장자 검사
ex) match(method, "(GET|POST|-)")
=> method가 GET, POST, - 인지 확인 (or)
split(X,"Y")
- 구분자 Y를 이용해서 X를 분할해 다중값 형식으로 변환
- 구분자로 분리한 문자열은 여러 개의 토큰이 발생하므로 주로 mvindex()에서 사용
- 이벤트에서 특정 값을 추출할 때 사용
ex) split(uri,"/")
/data/utility/tool/GoogleToolbar.exe
=> data utility tool GoogleToolbar.exe
=> [0] [1] [2] [3]
mvindex(X,Y,Z)
- 필드 X에 있는 Y번째 값을 반환 (Z생략 가능)
- Y : 0(첫번째 값), -1(인덱스 뒤부터 시작), -2(끝에서 두번째)
- Z는 선택, Z를 지정하면 함수는 Y부터 Z까지 값을 반환
ex) mvindex(split(uri,"/"),-1)
/data/utility/tool/GoogleToolbar.exe
=> data utility tool GoogleToolbar.exe
=> [0] [1] [2] [3]
=> 0 -2 -1 : Y
=> 분할되는 개수가 유동적이기 때문에 인덱싱 값을 유추하기 어려움
=> 그래서 첫번째(0) 또는 가장 마지막 위치(-1) 또는 마지막에서 2번째 위치(-2) 이렇게 원하는 위치를 뽑을 수 있음
substr(X,Y,Z)
- 세번째 인자 Z가 없다면 필드 X의 Y부터 문자열 끝까지 반환
- Z가 주어지면 Y부터 Z개의 문자열 반환
ex) *| eval passwd_str="lightdm:x:107:117:Light Display M a n a g e r :/var/lib/lightdm:/bin/false"
| eval uid=mvindex(split(passwd_str,":"),0)
| eval subuid1=substr(uid,2)
| eval subuid2=substr(uid,2,4)
| table uid, subuid1, subuid2
=> passwd_str를 : 를 기준으로 분할하여 첫번째 것을 uid에 저장
lightdm x 107 117 Light Display M a n a g e r /var/lib/lightdm /bin/false
uid = lightdm
=> uid에서 2번째부터 문자열 끝까지 subuid1에 저장
subuid1 = ightdm
=> uid에서 2번째부터 4개의 문자열을 subuid2에 저장
subuid2 = ight
round(X,Y)
- X를 Y자릿수 기준으로 반올림
- 나누기 계산을 할 경우 소수점 자리가 급격히 늘어나는 것을 방지
strftime(X,Y)
- 유닉스 타임을 일반시간으로 변환
- 유닉스타임 X를 지정한 Y형식으로 출력
- 유닉스 타임(에포크 타임) 계산법은 1970년 1월 1일 0시를 기준으로 초 계산
striptime(X,Y)
- 일반시간을 유닉스 타임으로 변환
- Y 형식으로 된 X 시간 문자열을 입력받아 유닉스 타임을 반환