# Content Spoofing

\[TOC\]

## Summary

Application is vulnerable to content spoofing. Content spoofing, also referred to as content injection, arbitrary text injection or virtual defacement, is an attack targeting a user, made possible by an injection vulnerability in a web application. When an application does not properly handles user-supplied data, an attacker can supply content to a web application, typically via a parameter value, that is reflected back to the user. This presents the user with a modified page under the context of the trusted domain.

## Remediation of Content Spoofing

In OA and Workstation, we have various user interfaces that display Success messages in the event of a successful action done by the user, or Error messages as a result of some processing or validation error. These messages are often sent as GET parameters in the URL, making them easy to spoof. In order to allow only specific valid messages and not any random malicious text to be displayed to the users.

for eg. [https://oa.qaorch.com/please\_login.php?e=0&u=vnagaraj&msg=This%20site%20is%20down%20do%20not%20login](https://oa.qaorch.com/please_login.php?e=0&u=vnagaraj&msg=This%20site%20is%20down%20do%20not%20login)

There are certain library files that process the messages in url.

[**Messages.php**](https://github.com/theorchard/orchard/blob/master/library/Orchard/Messages/Messages.php): It stores all the valid success/error messages mapped to their respective unique message id.

**Pattern of message array**:

```text
'UNIQUE_MESSAGE_ID' => array('message' =>'MESSAGE', 'type' => TYPE ,   'pages' => 'DESTINATION_FILE_NAME '),
```

for example :

```text
'tr2r5r2d' => array('message' => 'Orders successfully created.', 'type' => self::SUCCESS_MESSAGE, 'pages' => 'search_ringtone_cut_order_results');
```

_**UNIQUE\_MESSAGE\_ID:**_

* Message id must be unique.
* As per standard we are following  8 digit unique message id.
* There is no pattern to write message id. so, it can be the combination of any alphanumeric. characters

_**MESSAGE:**_ Message which you want to display

_**TYPE**_: It can be SUCCESS\_MESSAGE \($confirm\_msg\) or ERROR\_MESSAGE \($err\_msg\).

_**DESTINATION\_FILE\_NAME**_: This can be a single file without their extensions. If there is a message which needs to be displayed on multiple pages then this can be an array also. eg. : view\_release.php will be considered as `view_release` only.

```text
'pages' => ['view_vendor', 'view_artist', 'view_release'];
```

[**Webmessage.php**](https://github.com/theorchard/orchard/blob/master/library/Orchard/Messages/WebMessage.php): This library does the work of processing and filtering the message content from the confirm\_msg or error\_msg param in the url before it gets displayed on the destination page.

**Functions**:

The getMessage and getMessages function will accept message id/s and message param/s map these ids to the unique messages present in Messages.php file replace the parameter/s in the message/s and return the message/s.

1. **For Single message:**

```text
getMessage($messageId, $messageType, $params = array())
```

_**$messageId**_- This method accepts the message id that is passed as the url param.

_**$messageType**_ - This specifies the message type ie : for SUCCESS\_MESSAGE it is 2 and for ERROR\_MESSAGE it is 1.

_**$params**_ - It specifies an array with param\_names as keys and param\_values that might be present in a success or error message.

Returns the [actual message](content-spoofing.md) corresponding to the given message id.

1. **For Multiple messages:** 

```text
getMessages($messageIds, $messageType, $params = array())
```

_**$messageIds**_ - Array of message ids that are passed as the url param.

_**$messageType**_ - This specifies the message type ie : for SUCCESS\_MESSAGE it is 2 and for ERROR\_MESSAGE it is 1.

_**$params**_ - It specifies an array with param\_names as keys and param\_values that might be present in a success or error message.

Returns an array of messages corresponding to the given message ids.

**Usage:** getMessage and getMessages functions are being called in [disp\_msg.inc](https://github.com/theorchard/orchard/blob/master/public/oa/includes/disp_msg.inc) file to render the Confirm and Error messages on legacy pages.

For zend pages, these functions can be called in the destination controller action where the GET params are being sent to the view to be displayed.

Spoofing prevention patterns and use cases are listed here to facilitate developers in adding any new success or error messages in future.

## Patterns and use cases

### Single Message

**Description**: This can be a simple string message.

Example success message:

`$confirm_msg = ’User inserted successfully.’`

**Spoofing remediation**:

* Replace the message string in code by a random alphanumeric message id.

  `$confirm_msg = ‘7bfc787a’;`

* Pass the message in the confirm\_msg GET param in url

`header("Location: edit_user.php?orchadmin_user_id=$user_id&confirm_msg=$confirm_msg");`

* Add this message id in $messages array in Messages.php file. The message string, the type of message and the destination page that shows the message.

`'7bfc787a' => array('message' => 'User inserted successfully.', 'type' => self::SUCCESS_MESSAGE, 'pages' => 'edit_user'),`

**URLs:**

before : [https://oa.qaorch.com/users/edit\_user.php?orchadmin\_user\_id=1962&confirm\_msg=User info edited successfully](https://oa.qaorch.com/users/edit_user.php?orchadmin_user_id=1962&confirm_msg=User%20info%20edited%20successfully).

After spoofing remediation : [https://oa.qaorch.com/users/edit\_user.php?orchadmin\_user\_id=1962&confirm\_msg=eab8471e](https://oa.qaorch.com/users/edit_user.php?orchadmin_user_id=1962&confirm_msg=eab8471e).

You'll be able to see the message on UI which is mapped with 'eab8471e' id i.e. `User info edited successfully.`

### Single Message with numeric parameter

**Description:** This can be a simple string message with a numeric parameter.

Example success message:

```text
$confirm_msg = ’5 Users have been created successfully.’
```

Where ‘5’ is dynamic and can be used as $num in code.

**Spoofing remediation:**

* Replace the message string in code by a random alphanumeric message id and concatenate the numeric value.

```text
 $confirm_msg = 105jh879;
```

* Pass the message in the confirm\_msg GET param in url

```text
$msgUserCount = $num;
If (!empty($msgUserCount)) {
    $confirm_msg .= '&msg_user_count=' . $msgUserCount;`
}
header('Location: /test/test.php?confirm_msg=' . $confirm_msg);
```

* Add this message id in $messages array in Messages.php file. The message string, the type of message and the destination page that shows the message.

```text
 105jh879 => array ('message' => '{MSG_USER_COUNT} Users have been created successfully.', 'type' => self::SUCCESS_MESSAGE, 'pages' => 'test'),
```

**URLs:**

before : [https://oa.qaorch.com/cont\_mgmt/edit\_track.php?upc=192562647783&action=update\_all\_track&confirm\_msg=Publisher Names have been successfully updated for 3 track\(s](https://oa.qaorch.com/cont_mgmt/edit_track.php?upc=192562647783&action=update_all_track&confirm_msg=Publisher%20Names%20have%20been%20successfully%20updated%20for%203%20track%28s)\).

After spoofing remediation : [https://oa.qaorch.com/cont\_mgmt/edit\_track.php?upc=192562647783&action=update\_all\_track&confirm\_msg=jbs19115&msg\_track\_count=3](https://oa.qaorch.com/cont_mgmt/edit_track.php?upc=192562647783&action=update_all_track&confirm_msg=jbs19115&msg_track_count=3)

You'll be able to see the message on UI which is mapped with 'jbs19115' id i.e. `Publisher Names have been successfully updated for 3 track(s).`

### Single Message with non-numeric parameter

**Description:** This can string message having parameter that is non-numeric. Such parameters cannot be passed directly in URL and hence need to be encrypted.

Example success message:

```text
$confirm_msg = ’User inserted successfully.’
```

Spoofing remediation:

* Replace the message string in code by a random alphanumeric message id. 

```text
$confirm_msg = ‘jbs20511’;
```

* Pass the message in the confirm\_msg GET param in url

```text
header("Location: edit_user.php?orchadmin_user_id=$user_id&confirm_msg=$confirm_msg");
```

* Add this message id in $messages array in Messages.php file. The message string, the type of message and the destination page that shows the message.

```text
'jbs20511' => array('message' => 'Uploading {MSG_FILE_NAME} ...Error! Sorry, a file with this name already exist.', 'type' => self::ERROR_MESSAGE, 'pages' => array('edit_ex_release', 'view_release'), 'params' => ['MSG_FILE_NAME' => 'Decrypt']),
```

**URLs:**

before : [https://oa.qaorch.com/cont\_mgmt/view\_release.php?upc=192562647783&err\_msg=Only files with the following extensions are allowed: %3Cb%3E.jpg .doc .pdf%3C/b%3E%3Cbr%3E](https://oa.qaorch.com/cont_mgmt/view_release.php?upc=192562647783&err_msg=Only%20files%20with%20the%20following%20extensions%20are%20allowed:%20%3Cb%3E.jpg%20.doc%20.pdf%3C/b%3E%3Cbr%3E)

After spoofing remediation : [https://oa.qaorch.com/cont\_mgmt/view\_release.php?upc=192562647783&err\_msg=jbs20507&msg\_file\_extensions\[\]=d2tMQUpGNEttcGpuNXJheXRYcGMydz09:6wf194zryeu0KlV858S/xw=](https://oa.qaorch.com/cont_mgmt/view_release.php?upc=192562647783&err_msg=jbs20507&msg_file_extensions[]=d2tMQUpGNEttcGpuNXJheXRYcGMydz09:6wf194zryeu0KlV858S/xw=)

You'll be able to see the message on UI which is mapped with 'jbs20507' id i.e. `Only files with the following extensions are allowed: .jpg .doc .pdf .`

### Single message with parameter, message repeated with different param values

#### Description

When we have a message that needs to be repeated for different param values, we don't need multiple messages, instead we need to send an array of param values for a message.

#### Example error messages before spoofing remediation

```text
foreach ($upc as $v) {
    if (!checkUPC($v)) {
        $err_msg[] = '<li>UPC: ' . $v . ' is not valid.</li>';
    }
}
if(count($err_msg)){
    header('location: /warehouse/access_asset.php?err_msg=' . urlencode(implode(' ',$err_msg)));
    exit();
}
```

Sample output

```text
UPC: 87432874 is not valid.
UPC: fdsfsdfs is not valid.
```

#### Spoofing remediation

The error message will be replaced by its unique message id. The messages in Message.php will be as follows,

```text
'f5wfx9mh' => array('message' => 'UPC: {MSG_UPC_INVALID} is not valid.', 'type' => self::ERROR_MESSAGE, 'pages' => 'access_asset', 'params' => ['MSG_UPC_INVALID' => 'Decrypt'])
```

The message param will be sent in the url in array format msg\_invalid\_upc\[\].

```text
$encrypt = new \Orchard\Messages\ParamHandlers\Encrypt();
$errUpcs = '';
$errMsg = '';
foreach ($upc as $v) {
    if (!checkUPC($v)) {
        $errUpcs .= '&msg_upc_invalid[]=' . $encrypt->process($v);
    }
}
if ($errUpcs != '') {
    $errMsg = 'err_msg=f5wfx9mh';
    header('location: /warehouse/access_asset.php?' . $errMsg . $errUpcs);
    exit();
}
```

Encrypted params: In this example upc can be a string param which is spoofable, so it is encrypted using the Encrypt class and then sent in the url. For decryption, we specify the Decrypt class in the params array for the message in Messsages.php with the message param name as key, This will ensure decryption is applied on the param before being replaced in the error message.

#### Urls

Before Spoofing remediation [https://oa.qaorch.com/warehouse/access\_asset.php?err\_msg=UPC%3A+87432874+is+not+valid.&lt;%2Fli&gt;+UPC%3A+fdsfsdfs+is+not+valid.&lt;%2Fli&gt;](https://oa.qaorch.com/warehouse/access_asset.php?err_msg=<li>UPC%3A+87432874+is+not+valid.<%2Fli>+<li>UPC%3A+fdsfsdfs+is+not+valid.<%2Fli>)

After spoofing remediation [https://oa.qaorch.com/warehouse/access\_asset.php?err\_msg=f5wfx9mh&msg\_upc\_invalid\[\]=K3lqczVzYnMxc1YwMnRrakUyNVo2QT09:YITbdteRYgKkUUy4yIxZbQ&msg\_upc\_invalid\[\]=bEFmS2NibCtZWWVVbjVndXVqYWZhZz09:WD7\_4WMwr\_75SdX4NGOaUQ](https://oa.qaorch.com/warehouse/access_asset.php?err_msg=f5wfx9mh&msg_upc_invalid[]=K3lqczVzYnMxc1YwMnRrakUyNVo2QT09:YITbdteRYgKkUUy4yIxZbQ&msg_upc_invalid[]=bEFmS2NibCtZWWVVbjVndXVqYWZhZz09:WD7_4WMwr_75SdX4NGOaUQ)

### Multiple messages with single parameter in each message

#### Description

This will be the case when we have multiple messages and each message has a param, also each message can be repeated for different param values.

#### Example error messages

```text
33333333333 is not valid.
194491230760 is not valid.
194491231194 is not valid.
194491216597 is a deleted release.
194491216696 is a deleted release.
```

#### Spoofing remediation

Each message will be replaced by its unique message id. Since we have multiple messages we send them in url in array format err\_msg\[\]. Considering the above example, we have 2 unique messages. Each message is having a param. Each of the param from the two messages will be sent in the url in array format msg\_invlidupc\[\] and msg\_upc\_deletedreleases\[\]

The messages in Message.php will be as follows,

```text
'qkl30jer' => array('message' => '{MSG_UPC_INVALIDUPC} is not valid.', 'type' => self::ERROR_MESSAGE, 'pages' => 'encoding_order_view'),
'v7b6xr16' => array('message' => '{MSG_UPC_DELETEDRELEASES} is a deleted release.', 'type' => self::ERROR_MESSAGE, 'pages' => 'encoding_order_view'),
```

Below code simply illustrates how messages and params are sent in array format in the url,

```text
$errMessages = 'err_msg[]=qkl30jer&err_msg[]=v7b6xr16';

$messageParams = '&msg_ipc_invalidupc[]=' . $invalidUpc1 . '&msg_ipc_invalidupc[]=' . $invalidUpc2 . '&msg_ipc_invalidupc[]=' . $invalidUpc3;
$messageParams .= '&msg_upc_deletedreleases[]=' . $deletedUpc1 . '&msg_upc_deletedreleases[]=' . $deletedUpc2;

header('Location: FILE_NAME.php?' . $err_message . messageParams);
```

#### Urls

Before Spoofing remediation [https://oa.qaorch.com/warehouse/encoding\_order\_view.php?encoding\_order\_id=3179201&err\_msg=33333333333%2C%22+is+not+valid.%22%3Cbr%3E194491230760%2C%22+is+not+valid.%22%3Cbr%3E194491231194%2C%22+is+not+valid.%22%3Cbr%3E194491216597%2C%22+is+a+deleted+release.%22%3Cbr%3E194491216696%2C%22+is+a+deleted+release.%22&errorCode=](https://oa.qaorch.com/warehouse/encoding_order_view.php?encoding_order_id=3179201&err_msg=33333333333%2C%22+is+not+valid.%22%3Cbr%3E194491230760%2C%22+is+not+valid.%22%3Cbr%3E194491231194%2C%22+is+not+valid.%22%3Cbr%3E194491216597%2C%22+is+a+deleted+release.%22%3Cbr%3E194491216696%2C%22+is+a+deleted+release.%22&errorCode=)

After spoofing remediation [https://oa.qaorch.com/warehouse/encoding\_order\_view.php?encoding\_order\_id=3179200&err\_msg\[\]=qkl30jer&err\_msg\[\]=v7b6xr16&msg\_upc\_invalidUPC\[\]=33333333333&msg\_upc\_invalidUPC\[\]=194491230760&msg\_upc\_invalidUPC\[\]=194491231194&msg\_upc\_deletedReleases\[\]=194491216597&msg\_upc\_deletedReleases\[\]=194491216696](https://oa.qaorch.com/warehouse/encoding_order_view.php?encoding_order_id=3179200&err_msg[]=qkl30jer&err_msg[]=v7b6xr16&msg_upc_invalidUPC[]=33333333333&msg_upc_invalidUPC[]=194491230760&msg_upc_invalidUPC[]=194491231194&msg_upc_deletedReleases[]=194491216597&msg_upc_deletedReleases[]=194491216696)

## Zend Framework

In Zend MVC pages, we have error and success messages passed in view variables. Below are the different use cases for Zend pages.

### Zend Action: Success and Error messages sent internally via view params

#### Description

Error and success messages are set and passed to view variables err\_msg and confirm\_msg in the action itself and are not passed in url params.

#### Example error message

```text
$errorMsg = '<li>Sub Account Name is required.</li>';
$this->view->err_msg = $errorMsg;
```

#### Example success message

```text
$confirm_msg = 'Subaccount has been updated successfully.';
$this->view->confirm_msg = $confirm_msg;
```

#### Spoofing remediation

Since the messages get displayed from view variables passed in controller and not through the urls get params, they are not spoofable. No changes to be done for this case.

### Zend Action: Success and Error messages sent via url but to same action

#### Description

Error and success messages are set and passed in url params err\_msg and confirm\_msg from within an action to itself in a redirection url. These messages are fetched from url params at the beginning of the action and passed on to the view variables err\_msg and confirm\_msg respectively.

#### Example of Success message without remediation

```text
public function editsubaccountcarveoutAction()
{
    $this->view->confirm_msg = $this->_getParam('confirm_msg', null);
    ...
    ...
    ...
    $this->getResponse()->setRedirect(
        '/subaccount/editsubaccountcarveout/subaccount_id/' . $subaccountId . '/confirm_msg/' . urlencode('Subaccount carveouts are updated successfully.')
    )->sendResponse();
    ...
    ...
}
```

#### Spoofing remediation

Remove the redirection url and pass the errror and success messages directly in view variables the err\_msg and confirm\_msg respectively. Also remove any code that might fetch messages using url get params at the beginning of the action.

```text
public function editsubaccountcarveoutAction()
{
    ...
    ...
    $this->view->confirm_msg = 'Subaccount carveouts are updated successfully.';
    ...
    ...
}
```

#### URLS

Before Spoofing remediation [https://oa.qaorch.com/subaccount/editsubaccountcarveout/subaccount\_id/25824/confirm\_msg/Subaccount+carveouts+are+updated+successfully.](https://oa.qaorch.com/subaccount/editsubaccountcarveout/subaccount_id/25824/confirm_msg/Subaccount+carveouts+are+updated+successfully.)

After Spoofing remediation [https://oa.qaorch.com/subaccount/editsubaccountcarveout/subaccount\_id/25824](https://oa.qaorch.com/subaccount/editsubaccountcarveout/subaccount_id/25824)

### Rediretion: From Zend action to another Zend action

#### Description

Error and success messages are passed in url params err\_msg and confirm\_msg from one action\(source\) to another action\(destination\) in a redirection url. These messages are fetched from url params at the beginning of the destination action and passed on to the view variables err\_msg and confirm\_msg respectively.

#### Example of Success message without remediation

```text
# Source action
public function editgrasregistrationAction()
{
    ....
    ....
    $this->getResponse()->setRedirect(
        '/subaccount/viewsubaccount/subaccount_id/' . $subaccountId . '/confirm_msg/' . urlencode('Subaccount GRAS Registration updated successfully.')
    )->sendResponse();
}

# Destination action
public function viewsubaccountAction()
{    
    $this->view->confirm_msg = $this->_getParam('confirm_msg', null);
    ...
    ...
}
```

#### Spoofing remediation

Define the success and error messages in Messages.php. Here the destination page is a Zend page ie /subaccount/viewsubaccount action. The pages param will always be set to zf\_index if destination page is a Zend page.

```text
'8t36wg25' => array('message' => 'Subaccount GRAS Registration updated successfully.', 'type' => self::SUCCESS_MESSAGE, 'pages' => 'zf_index'),
```

In source action, pass the corresponding mapped unique message ids in err\_msg and confirm\_msg url params in the redirection url of destination action. In destination action fetch messages using getMessage/s function from WebMessage class. Pass these actual messages that are fetched in the view variables err\_msg and confirm\_msg.

```text
# Source action
public function editgrasregistrationAction()
{
    ....
    ....
    $confirmMsg = '8t36wg25';
    $this->getResponse()->setRedirect(
        '/subaccount/viewsubaccount/subaccount_id/' . $subaccountId . '/confirm_msg/' . $confirmMsg)
    )->sendResponse();
}

# Destination action
public function viewsubaccountAction()
{
    if ($this->_getParam('confirm_msg', null) != null) {
        $this->view->confirm_msg = WebMessage::getMessage($this->_getParam('confirm_msg'), WebMessage::SUCCESS_MESSAGE);
    }
    ...
    ...
}
```

#### URLS

Before Spoofing remediation [https://oa.qaorch.com/subaccount/viewsubaccount/subaccount\_id/25824/confirm\_msg/Subaccount+GRAS+Registration+updated+successfully.](https://oa.qaorch.com/subaccount/viewsubaccount/subaccount_id/25824/confirm_msg/Subaccount+GRAS+Registration+updated+successfully.)

After Spoofing remediation [https://oa.qaorch.com/subaccount/viewsubaccount/subaccount\_id/25824/confirm\_msg/8t36wg25](https://oa.qaorch.com/subaccount/viewsubaccount/subaccount_id/25824/confirm_msg/8t36wg25)

### Redirection: From Zend action to legacy page

#### Description

Error and success messages are passed in url params err\_msg and confirm\_msg of a legacy url from a Zend controller action.

#### Example of Success message without remediation

```text
public function addownerAction()
{
    ...
    ...
    $confirmMsg = 'Digital Rights Representative Has Been Successfully Added';
    $this->getResponse()->setRedirect(
        '/cont_mgmt/view_aggr_drr.php?owner_id=' . $ownerId . '&confirm_msg=' . urlencode($confirmMsg)
    )->sendResponse();
}
```

#### Spoofing remediation

Define the success and error messages in Messages.php. Here the destination page is a leagcy page ie. view\_aggr\_drr.php so pages param will be view\_aggr\_drr.

```text
'67fsd2b4' => array('message' => 'Digital Rights Representative Has Been Successfully Added.', 'type' => self::SUCCESS_MESSAGE, 'pages' => 'view_aggr_drr'),
```

In the controller action, pass the corresponding mapped unique message ids in err\_msg and confirm\_msg url params of the legacy url. As per use cases discussed for use cases above, messages will be decoded in disp\_msg file and displayed.

```text
public function addownerAction()
{
    ...
    ...
    $confirmMsg = '67fsd2b4';
    $this->getResponse()->setRedirect(
        '/cont_mgmt/view_aggr_drr.php?owner_id=' . $ownerId . '&confirm_msg=' . urlencode($confirmMsg)
    )->sendResponse();
}
```

#### URLS

Before Spoofing remediation [https://oa.qaorch.com/cont\_mgmt/view\_aggr\_drr.php?owner\_id=210&confirm\_msg=Partner+Has+Been+Successfully+Added](https://oa.qaorch.com/cont_mgmt/view_aggr_drr.php?owner_id=210&confirm_msg=Partner+Has+Been+Successfully+Added)

After Spoofing remediation [https://oa.qaorch.com/cont\_mgmt/view\_aggr\_drr.php?owner\_id=209&confirm\_msg=61esd2f1](https://oa.qaorch.com/cont_mgmt/view_aggr_drr.php?owner_id=209&confirm_msg=61esd2f1)

**Note:** Please consider that these methods are only applicable for the messages which are passed in the URLs. The messages which are not a part of URL are not exploitable so, there is no need to encode them.

