10. 1 개요
1.1 해커의 목표
1.2 취약점의 발생 원인
2 Web Security
2.1 사용자의 입력
2.2 Injection
2.3 파일 관리
2.4 암호화
3 System Security
3.1 해커가 원하는 상황
3.2 Buffer Overflow
4 보안정책
78. POST /foo HTTP/1.1
Host: localhost
User-Agent: ~~ Android ~~
Referer: http://naver.com
Content-Length: 23
Cookie: userid=tunz; admin=1;
param1=val1param2=val2
Virtual Host 조작
Browser/OS 정보 조작
Cookie 조작
이전 페이지 조작
Data 조작
84. 이런 필터링은 단지 1차적인 필터링일 뿐
서버에 직접 데이터를 보내면 된다.
POST /foo HTTP/1.1
Host: example.com
User-Agent: Mozilla/~~
Content-Length: 23
Cookie: userid=tunz; admin=1;
user=tunz!!!pw=123
Server
HTTP Data
115. § 중요한 정보는 사용자가 조작할수 없는곳에 저장하고, 가져오자.
§ Client-Side 에서 Filtering 한 정보는, Server-Side 에서 다시 확인하자.
§ 중요한 페이지명은, 이름을 유추하기 힘들게 변경한다.
if ($_COOKIE[‘admin’] == 1) if ($_SESSION[‘admin’] == 1)
if (!userid.match(/^[0-9a-zA-Z]+$/)) {
alert(‘ID is not alphanumeric’);
return false;
}
if (!preg_match(“/^[0-9a-zA-Z]+$/”, $userid)) {
echo ‘ID is not alphanumeric’;
exit();
}
123. 사용자의 입력으로 새로운 데이터를 만들 경우.
§ SQL injection
§ Command injection
§ XXE (XML External Entity)
§ XSS (Cross Site Scripting)
select * from users where user=‘$id’ and pw=‘$pw’;
system(“echo ‘Hello, $name!‘”);
body
Hello, ?php=$name?!
/body
argsarg1input/arg1/args
132. 사용자의 입력으로 새로운 데이터를 만들 경우.
§ SQL injection
select * from users where user=‘admin’ and pw=‘’ or ‘a’=‘a’;
truefalse or
true
select * from board where bid=‘’ union select idx, uid, uname, pw from
admin –- ’;
응용버전
133.
select * from board where bid=‘tunz’ and substr((select pw from users
where user=‘admin’),1,1)=‘a’ –- ’;
select * from board where bid=‘tunz’ and if(substr((select pw from
users where user=‘admin’),1,1)=‘a’, sleep(1), 0) –- ’;
Union SQL Injection
144. 사용자의 입력으로 새로운 데이터를 만들 경우.
§ SQL injection
select * from users where user=‘tunz’ and pw=‘’ or ‘a’=‘a’;
truefalse or
true
select * from users where user=‘’ union select idx, uid, uname, pw from
admin -- ’ and pw=‘’;
응용버전
145.
select * from users where user=‘tunz’ and substr((select pw from users
where user=‘admin’),1,1)=‘a’ -- ’ and pw=‘’;
select * from users where user=‘tunz’ and if(substr((select pw from
users where user=‘admin’),1,1)=‘a’, sleep(1), 0) -- ’ and pw=‘’;
Union SQL Injection
157. 사용자의 입력으로 새로운 데이터를 만들 경우.
§ SQL injection
§ Command injection
§ XXE (XML External Entity)
§ XSS (Cross Site Scripting)
system(“echo ‘Hello, $name!‘”);
body
Hello, ?php=$name?!
/body
argsarg1input/arg1/args
select * from users where user=‘tunz’ and pw=‘’ or ‘a’=‘a’;
166. 사용자의 입력으로 새로운 데이터를 만들 경우.
§ SQL injection
§ Command injection
§ XXE (XML External Entity)
§ XSS (Cross Site Scripting)
select * from users where user=‘tunz’ and pw=‘’ or ‘a’=‘a’;
system(“echo ‘Hello, ‘; cat index.php; ‘!‘”);
body
Hello, ?php=$name?!
/body
argsarg1input/arg1/args
175. 사용자의 입력으로 새로운 데이터를 만들 경우.
§ SQL injection
§ Command injection
§ XXE (XML External Entity)
§ XSS (Cross Site Scripting)
select * from users where user=‘tunz’ and pw=‘’ or ‘a’=‘a’;
system(“echo ‘Hello, ‘; cat index.php; ‘!‘”);
183. 사용자의 입력으로 새로운 데이터를 만들 경우.
§ SQL injection
§ Command injection
§ XXE (XML External Entity)
§ XSS (Cross Site Scripting)
select * from users where user=‘tunz’ and pw=‘’ or ‘a’=‘a’;
system(“echo ‘Hello, ‘; cat index.php; ‘!‘”);
!DOCTYPE foo [ !ENTITY xxe SYSTEM file:///etc/passwd ]
argsarg1xxe;/arg1/args
body
Hello, ?php=$name?!
/body
184. !DOCTYPE foo [ !ENTITY xxe SYSTEM file:///etc/passwd ]
argsarg1xxe;/arg1/args
body
Hello, ?php=$name?!
/body
사용자의
191. 사용자의 입력으로 새로운 데이터를 만들 경우.
§ SQL injection
§ Command injection
§ XXE (XML External Entity)
§ XSS (Cross Site Scripting)
select * from users where user=‘tunz’ and pw=‘’ or ‘a’=‘a’;
system(“echo ‘Hello, ‘; cat index.php; ‘!‘”);
293. Uploads 폴더에 올려놓고, URL 직접 접근으로 다운받게 하려는 옛날 방법
하지만, 실행 가능한 파일을 업로드 한다면?
$target_file = “uploads/” . basename($_FILES[‘fileToUpload’][‘name’]);
if (move_uploaded_file($_FILES[‘fileToUpload’][‘tmp_name’], $target_file))
echo “The file “ . basename($_FILES[‘fileToUpload’][‘name’] . “ has been uploaded.”;
376. : 사용자 패스워드는 salt 붙여서 hash 하는 것이 좋다. [ 사전식 해독의 방지 ]
sha1(“Naver”.$password.”D2!”)
패스워드는 소중하니까 암호화 해야지 ㅎㅎ
$password = base64_encode($password);
base64는 암호가 아니에요..
암호는 관리자가 몰라도 되는 정보이므로, Hash 를 한다.
if (sha1($password) === $db_password)
asdf.encode('base64')
'YXNkZg==n'
YXNkZg==.decode('base64')
'asdf'
384. 패스워드는 소중하니까 암호화 해서 전송해야지 ㅎㅎ
script
key = “1234567890123456”;
password = AES.encrypt(password, key);
sendToServer(password);
/script
키를 다 보여줘 놓고 암호화 하면 무슨 소용...
Tip
393. 패스워드는 소중하니까 강력하게 한 글자씩 암호화 해야지 ㅎㅎ
$encrypted = “”;
for ($i = 0; $i strlen($password); $i++)
$encrypted .= sha1($password[$i]);
글자가 길어질 뿐.. 경우의수가 256개밖에 안되기 때문에, 금방 뚫린다.
a 86f7e437faa5a7fce15d1ddcb9eaeaea377667b8
b e9d71f5ee7c92d6dc9e92ffdad17b8bd49418f98
C 84a516841ba77a5b4648de2cd0dfcb30ea46dbb4
…
556. 다시 고쳐보자
정확히 size의 길이를 제한했다.
이제 문제 없나?
char *buf[1024];
int size;
read(fd, size, sizeof(int));
if (size – sizeof(int) = 0 || size 1024)
my_error(“ERROR! EXIT”);
read(fd, buf[i], size - sizeof(int));
584. int *buf;
unsigned int size;
read(fd, size, sizeof(unsigned int));
buf = (int *)malloc(size * sizeof(int));
for (i=0; i size; i++)
read(fd, buf[i], sizeof(int));
다른 문제
Size 만큼 메모리 할당을 해주는데 뭐가 문제지?
591. int *buf;
unsigned int size;
read(fd, size, sizeof(unsigned int));
buf = (int *)malloc(size * sizeof(int));
for (i=0; i size; i++)
read(fd, buf[i], sizeof(int));
0x40000004 를 입력으로 넣으면.
메모리 할당은 16바이트만 되었는데, read 는 여전히 0x40000004 만큼 읽는다.
malloc(16)
Overflow!
Buffer Overflow!
size 에 따라 메모리할당이 되더라도, size 에는 제한을 두자.
0x40000004 * 4 = 0x100000010.
595. 사람은 실수를 하기 마련이고,
서비스가 커지면 커질수록 취약점은 반드시 나온다.
그렇다면 공격을 막기 위해서는?
서버 공격 시도만 해도 차단, 고소.
+ 공격 성공 전 미리 차단 가능.
+ 국내 해커의 소극적 공격.
- 취약점들의 존재 가능성은 여전.
- 취약점을 내부에서 모두 찾아야 한다.
취약점 제보 시 보상과 명예를 드높여준다.
+ 수많은 취약점 발견 및 수정 가능.
- 오히려 공격을 유도 할 수 있다.
- 악의적인 공격의 구분 힘들다.
적절히 잘 섞어 보세요...
강하게 너그럽게