Bash CGI Scripts Request Method: POST /w JSON


Example

Using Request Method POST in combination with SSL makes datatransfer more secure.

In addition...

  • Most of the encoding and decoding is not needed any more
  • The URL will be visible to any one and needs to be url encoded.
    The data will be send separately and therefor should be secured via SSL
  • The size of the data is almost unlitmited
  • Still needs protection against Cross-Side-Scripting (XSS)

To keep this showcase simple we want to receive JSON Data
and communication should be over Cross-Origin Resource Sharing (CORS).

The following script will also demonstrate two different Content-Types.

#!/bin/bash

exec 2>/dev/null    # We dont want any error messages be printed to stdout
trap "response_with_html && exit 0" ERR    # response with an html message when an error occurred and close the script

function response_with_html(){    
    echo "Content-type: text/html"
    echo ""
    echo "<!DOCTYPE html>"
    echo "<html><head>"
    echo "<title>456</title>"
    echo "</head><body>"
    echo "<h1>456</h1>"
    echo "<p>Attempt to communicate with the server went wrong.</p>"
    echo "<hr>"
    echo "$SERVER_SIGNATURE"
    echo "</body></html>"
}
        
function response_with_json(){
    echo "Content-type: application/json"
    echo ""
    echo "{\"message\": \"Hello World!\"}"
}

if [ "$REQUEST_METHOD" = "POST" ]; then
   
    # The environment variabe $CONTENT_TYPE describes the data-type received
    case "$CONTENT_TYPE" in
    application/json)
        # The environment variabe $CONTENT_LENGTH describes the size of the data
        read -n "$CONTENT_LENGTH" QUERY_STRING_POST        # read datastream 

        # The following lines will prevent XSS and check for valide JSON-Data.
        # But these Symbols need to be encoded somehow before sending to this script
        QUERY_STRING_POST=$(echo "$QUERY_STRING_POST" | sed "s/'//g" | sed 's/\$//g;s/`//g;s/\*//g;s/\\//g' )        # removes some symbols (like \ * ` $ ') to prevent XSS with Bash and SQL.
        QUERY_STRING_POST=$(echo "$QUERY_STRING_POST" | sed -e :a -e 's/<[^>]*>//g;/</N;//ba')    # removes most html declarations to prevent XSS within documents
        JSON=$(echo "$QUERY_STRING_POST" | jq .)        # json encode - This is a pretty save way to check for valide json code
    ;;
    *)
        response_with_html
        exit 0
    ;;
    esac

else
    response_with_html
    exit 0
fi

# Some Commands ...

response_with_json

exit 0

You will get {"message":"Hello World!"} as an answer when sending JSON-Data via POST to this Script. Every thing else will receive the html document.

Important is also the varialbe $JSON. This variable is free of XSS, but still could have wrong values in it and needs to be verify first. Please keep that in mind.

This code works similar without JSON.
You could get any data this way.
You just need to change the Content-Type for your needs.

Example:

if [ "$REQUEST_METHOD" = "POST" ]; then 
    case "$CONTENT_TYPE" in
    application/x-www-form-urlencoded)
            read -n "$CONTENT_LENGTH" QUERY_STRING_POST
    text/plain)
            read -n "$CONTENT_LENGTH" QUERY_STRING_POST
    ;;
    esac
fi

Last but not least, dont forget to response to all requests, otherwise third party programms wont know if they succeeded