This example attempts to write user messages to a message file and allow users to view them.
While the programmer intends for the MessageFile to only include data, an attacker can provide a message such as:
BadPHP
$MessageFile = "messages.out";if ($_GET["action"] == "NewMessage") {$name = $_GET["name"];$message = $_GET["message"];$handle = fopen($MessageFile, "a+");fwrite($handle, "<b>$name</b> says '$message'<hr>\n");fclose($handle);echo "Message Saved!<p>\n";}else if ($_GET["action"] == "ViewMessages") {include($MessageFile);}
edit-config.pl: This CGI script is used to modify settings in a configuration file.
The script intends to take the 'action' parameter and invoke one of a variety of functions based on the value of that parameter - config_file_add_key(), config_file_set_key(), or config_file_delete_key(). It could set up a conditional to invoke each function separately, but eval() is a powerful way of doing the same thing in fewer lines of code, especially when a large number of functions or variables are involved. Unfortunately, in this case, the attacker can provide other values in the action parameter, such as:
BadPerl
use CGI qw(:standard); sub config_file_add_key { my ($fname, $key, $arg) = @_; # code to add a field/key to a file goes here } sub config_file_set_key { my ($fname, $key, $arg) = @_; # code to set key to a particular file goes here } sub config_file_delete_key { my ($fname, $key, $arg) = @_; # code to delete key from a particular file goes here } sub handleConfigAction { my ($fname, $action) = @_;my $key = param('key');my $val = param('val'); # this is super-efficient code, especially if you have to invoke # any one of dozens of different functions! my $code = "config_file_$action_key(\$fname, \$key, \$val);";eval($code); } $configfile = "/home/cwe/config.txt";print header;if (defined(param('action'))) {handleConfigAction($configfile, param('action'));}else {print "No action specified!\n";}
This simple python3 script asks a user to supply a comma-separated list of numbers as input and adds them together.
The eval() function can take the user-supplied list and convert it into a Python list object, therefore allowing the programmer to use list comprehension methods to work with the data. However, if code is supplied to the eval() function, it will execute that code. For example, a malicious user could supply the following string:
BadPython
def main(): sum = 0 try: numbers = eval(input("Enter a comma-separated list of numbers: ")) except SyntaxError: print("Error: invalid input") return for num in numbers: sum = sum + num print(f"Sum of {numbers} = {sum}") main()
This simple python3 script asks a user to supply a comma-separated list of numbers as input and adds them together.
The eval() function can take the user-supplied list and convert it into a Python list object, therefore allowing the programmer to use list comprehension methods to work with the data. However, if code is supplied to the eval() function, it will execute that code. For example, a malicious user could supply the following string:
GoodPython
def main(): sum = 0 numbers = input("Enter a comma-separated list of numbers: ").split(",") try: for num in numbers: sum = sum + int(num) print(f"Sum of {numbers} = {sum}") except ValueError: print("Error: invalid input") main()
The following code is a workflow job written using YAML. The code attempts to download pull request artifacts, unzip from the artifact called pr.zip and extract the value of the file NR into a variable "pr_number" that will be used later in another job. It attempts to create a github workflow environment variable, writing to $GITHUB_ENV. The environment variable value is retrieved from an external resource.
The code does not neutralize the value of the file NR, e.g. by validating that NR only contains a number (CWE-1284). The NR file is attacker controlled because it originates from a pull request that produced pr.zip. The attacker could escape the existing pr_number and create a new variable using a "\n" (CWE-93) followed by any environment variable to be added such as:
BadOther
name: Deploy Preview jobs: deploy: runs-on: ubuntu-latest steps: - name: 'Download artifact' uses: actions/github-script with: script: | var artifacts = await github.actions.listWorkflowRunArtifacts({ owner: context.repo.owner, repo: context.repo.repo, run_id: ${{ github.event.workflow_run.id }}, }); var matchPrArtifact = artifacts.data.artifacts.filter((artifact) => { return artifact.name == "pr" })[0]; var downloadPr = await github.actions.downloadArtifact({ owner: context.repo.owner, repo: context.repo.repo, artifact_id: matchPrArtifact.id, archive_format: 'zip', }); var fs = require('fs'); fs.writeFileSync('${{github.workspace}}/pr.zip', Buffer.from(downloadPr.data)); - run: | unzip pr.zip echo "pr_number=$(cat NR)" >> $GITHUB_ENV
The following code is a workflow job written using YAML. The code attempts to download pull request artifacts, unzip from the artifact called pr.zip and extract the value of the file NR into a variable "pr_number" that will be used later in another job. It attempts to create a github workflow environment variable, writing to $GITHUB_ENV. The environment variable value is retrieved from an external resource.
The code does not neutralize the value of the file NR, e.g. by validating that NR only contains a number (CWE-1284). The NR file is attacker controlled because it originates from a pull request that produced pr.zip. The attacker could escape the existing pr_number and create a new variable using a "\n" (CWE-93) followed by any environment variable to be added such as:
GoodOther
The code could be modified to validate that the NR file only contains a numeric value, or the code could retrieve the PR number from a more trusted source.