Program: CWE-78
Project: CVE-2022-24796
Buggy source:
#!/bin/sh
# shellcheck shell=dash disable=SC2169,SC2034,SC2154

echo -ne "Content-Type: text/html; charset=iso-8859-1\r\n\r\n"

# fake read boundary+disposition, etc.
read -r boundary
read -r disposition
read -r ctype
read -r junk

# get length
a=${#boundary}
b=${#disposition}
c=${#ctype}
d=0

# Due to \n\r line breaks we have 2 extra bytes per line read,
# 6 + 2 newlines == 10 junk bytes
a=$((a*2+b+c+d+10))

# extract all params from QUERY_STRING
# shellcheck disable=SC2046,SC2116,SC2086
eval $(echo ${QUERY_STRING//&/;})

# calculate the expected content length using
# HTTP_CONTENT_LENGTH or CONTENT_LENGTH
if [ -z "${HTTP_CONTENT_LENGTH}" ]; then
  HTTP_CONTENT_LENGTH=${CONTENT_LENGTH}
fi
SIZE=$((HTTP_CONTENT_LENGTH-a))

# write out the data
filename=$(mktemp -p /usr/local/tmp)
if ! /usr/bin/head -q -c ${SIZE} >"${filename}"; then
  echo "ERROR (head)"
fi

echo "<html>"
echo " <head>"
echo "  <script>"
echo "   <!--- Hide script from browsers that don't understand JavaScript"
echo "   var url = '${url}?sid=${sid}';"
echo "   var dlgPopup = parent.top.dlgPopup;"
echo "   if (dlgPopup === undefined) {"
echo "     dlgPopup = window.open('', 'ccu-main-window').dlgPopup;"
echo "   }"
echo "   if (dlgPopup !== undefined) {"
echo "     dlgPopup.hide();"
echo "     dlgPopup.setWidth(450);"
if [[ -n "${downloadOnly}" ]]; then
  echo "     dlgPopup.downloadOnly=${downloadOnly};"
fi
echo "     dlgPopup.LoadFromFile(url, 'action=${action}&filename=${filename}');"
echo "   }"
echo "   // End hiding -->"
echo "  </script>"
echo " </head>"
echo "</html>"

exit 0


Fixed version (ground truth):
#!/bin/sh
# shellcheck shell=dash disable=SC3036,SC3010,SC2034,SC3060,SC2116,SC3045 source=/dev/null

echo -ne "Content-Type: text/html; charset=iso-8859-1\r\n\r\n"

# allow only POST requests
if [[ "${REQUEST_METHOD}" != "POST" ]]; then
  echo "ERROR: no POST request"
  exit 1
fi

# fake read boundary+disposition, etc.
read -r boundary
read -r disposition
read -r ctype
read -r junk

# get length
a=${#boundary}
b=${#disposition}
c=${#ctype}
d=0

# Due to \n\r line breaks we have 2 extra bytes per line read,
# 6 + 2 newlines == 10 junk bytes
a=$((a*2+b+c+d+10))

# calculate the expected content length using
# HTTP_CONTENT_LENGTH or CONTENT_LENGTH
if [[ -z "${HTTP_CONTENT_LENGTH}" ]]; then
  HTTP_CONTENT_LENGTH=${CONTENT_LENGTH}
fi
SIZE=$((HTTP_CONTENT_LENGTH-a))

# continue only if SIZE > 0
if [[ "${SIZE}" -le 0 ]]; then
  echo "ERROR: POST size <= 0"
  exit 1
fi

# extract known params from QUERY_STRING only
while IFS= read -r -d '&' KEYVAL && [[ -n "$KEYVAL" ]]; do
  case ${KEYVAL%%=*} in
    url) url=${KEYVAL#*=} ;;
    sid) sid=${KEYVAL#*=} ;;
    action) action=${KEYVAL#*=} ;;
    downloadOnly) downloadOnly=${KEYVAL#*=} ;;
  esac
done <<END
$(echo "${QUERY_STRING}&")
END

# check for url and action parameter
if [[ -z "${url}" ]] || [[ -z "${action}" ]]; then
  echo "ERROR: missing required URL parameters"
  exit 1
fi

# check for a valid ADMIN session id
if [[ "${#sid}" -eq 12 ]]; then
  # parse the current version
  [[ -r /VERSION ]] && . /VERSION

  # use CCU.getVersion which is allowed only for Admins
  RES=$(/usr/bin/curl http://127.0.0.1/api/homematic.cgi \
                      -H 'Content-Type: application/json' \
                      -d "{\"method\":\"CCU.getVersion\",\"params\":{\"_session_id_\": \"${sid//@}\"}}")

  # check the curl result contains the current
  # version number or not
  if ! echo "${RES}" | grep -q "${VERSION}"; then
    echo "ERROR: no valid admin session id"
    exit 1
  fi
else
  echo "ERROR: invalid session id"
  exit 1
fi

# write out the data
filename=$(mktemp -p /usr/local/tmp)
if ! /usr/bin/head -q -c ${SIZE} >"${filename}"; then
  echo "ERROR: head failure"
  exit 1
fi

echo "<html>"
echo " <head>"
echo "  <script>"
echo "   <!--- Hide script from browsers that don't understand JavaScript"
echo "   var url = '${url}?sid=${sid}';"
echo "   var dlgPopup = parent.top.dlgPopup;"
echo "   if (dlgPopup === undefined) {"
echo "     dlgPopup = window.open('', 'ccu-main-window').dlgPopup;"
echo "   }"
echo "   if (dlgPopup !== undefined) {"
echo "     dlgPopup.hide();"
echo "     dlgPopup.setWidth(450);"
if [[ -n "${downloadOnly}" ]]; then
  echo "     dlgPopup.downloadOnly=${downloadOnly};"
fi
echo "     dlgPopup.LoadFromFile(url, 'action=${action}&filename=${filename}');"
echo "   }"
echo "   // End hiding -->"
echo "  </script>"
echo " </head>"
echo "</html>"

exit 0