metatag.xss.test 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209
  1. <?php
  2. /**
  3. * @file
  4. * Tests Metatag module to ensure there are no XSS scripting vulnerabilities.
  5. */
  6. /**
  7. * Tests Metatag module to ensure there are no XSS scripting vulnerabilities.
  8. */
  9. class MetatagCoreXSSTest extends MetatagTestHelper {
  10. /**
  11. * String that causes an alert when page titles aren't filtered for xss.
  12. *
  13. * @var string
  14. */
  15. private $xssTitleString = '<script>alert("xss");</script>';
  16. /**
  17. * String that causes an alert when metatags aren't filtered for xss.
  18. *
  19. * @var string
  20. */
  21. private $xssString = '"><script>alert("xss");</script><meta "';
  22. /**
  23. * Rendered xss tag that has escaped attribute to avoid xss injection.
  24. *
  25. * @var string
  26. */
  27. private $escapedXssTag = '<meta name="abstract" content="&quot;&gt;alert(&quot;xss&quot;);" />';
  28. /**
  29. * String that causes an alert when metatags aren't filtered for xss.
  30. *
  31. * "Image" meta tags are processed differently to others, so this checks for a
  32. * different string.
  33. *
  34. * @var string
  35. */
  36. private $xssImageString = '/"><script>alert("image xss");</script><meta "';
  37. /**
  38. * Rendered xss tag that has escaped attribute to avoid xss injection.
  39. *
  40. * @var string
  41. */
  42. private $escapedXssImageTag = '';
  43. /**
  44. * {@inheritdoc}
  45. */
  46. public static function getInfo() {
  47. return array(
  48. 'name' => 'Metatag core tests for XSS.',
  49. 'description' => 'Test Metatag for XSS vulnerabilities.',
  50. 'group' => 'Metatag',
  51. );
  52. }
  53. /**
  54. * {@inheritdoc}
  55. */
  56. function setUp(array $modules = array()) {
  57. parent::setUp($modules);
  58. $content_type = 'page';
  59. // Create an admin user and log them in.
  60. $perms = array(
  61. // Needed for the content type.
  62. 'create ' . $content_type . ' content',
  63. 'delete any ' . $content_type . ' content',
  64. 'edit any ' . $content_type . ' content',
  65. // This permission is required in order to create new revisions.
  66. 'administer nodes',
  67. );
  68. $this->adminUser = $this->createAdminUser($perms);
  69. $this->drupalLogin($this->adminUser);
  70. // Generate the encoded version of $xssImageString.
  71. // '<link rel="image_src" href="' . $xssImageString . '" />'
  72. $prefix = '<link rel="image_src" href="';
  73. // The image tag will be automatically prefixed by the current hostname,
  74. // so adjust the escaped string.
  75. $url = url('', array('absolute' => TRUE));
  76. // Convert the raw string to what it will be when output in the HTML.
  77. $value = ltrim($this->xssImageString, '/');
  78. $value = urlencode($value);
  79. $value = str_replace('+', '%20', $value);
  80. $value = str_replace('%2F', '/', $value);
  81. $suffix = '" />';
  82. $this->escapedXssImageTag = $prefix . $url . $value . $suffix;
  83. }
  84. /**
  85. * Verify XSS injected in global Node config is not rendered.
  86. */
  87. function testXssMetatagConfig() {
  88. // Submit the form with some example XSS values.
  89. $this->drupalGet('admin/config/search/metatags/config/global');
  90. $this->assertResponse(200);
  91. $edit = array(
  92. 'metatags[und][title][value]' => $this->xssTitleString,
  93. 'metatags[und][abstract][value]' => $this->xssString,
  94. 'metatags[und][image_src][value]' => $this->xssImageString,
  95. );
  96. $this->drupalPost(NULL, $edit, t('Save'));
  97. $this->assertResponse(200);
  98. // Use front page to test.
  99. $this->drupalGet('<front>');
  100. // Verify title is clean.
  101. $this->assertNoTitle($this->xssTitleString);
  102. $this->assertNoRaw($this->xssTitleString);
  103. // Verify the abstract is clean.
  104. $this->assertRaw($this->escapedXssTag);
  105. $this->assertNoRaw($this->xssString);
  106. // Verify the image_src is clean.
  107. $this->assertRaw($this->escapedXssImageTag);
  108. $this->assertNoRaw($this->xssImageString);
  109. }
  110. /**
  111. * Verify XSS injected in the entity metatag override field is not rendered.
  112. */
  113. public function testXssEntityOverride() {
  114. $title = 'Test Page';
  115. // Load a page node.
  116. $this->drupalGet('node/add/page');
  117. $this->assertResponse(200);
  118. // Submit the node with some example XSS values.
  119. $edit = array(
  120. 'title' => $title,
  121. 'metatags[und][title][value]' => $this->xssTitleString,
  122. 'metatags[und][description][value]' => $this->xssString,
  123. 'metatags[und][abstract][value]' => $this->xssString,
  124. );
  125. $this->drupalPost(NULL, $edit, t('Save'));
  126. // Verify the page saved.
  127. $this->assertResponse(200);
  128. $this->assertText(t('Basic page @title has been created.', array('@title' => $title)));
  129. // Verify title is not the injected string and thus cleaned.
  130. $this->assertNoTitle($this->xssTitleString);
  131. $this->assertNoRaw($this->xssTitleString);
  132. // Verify the description and abstract are clean.
  133. $this->assertRaw($this->escapedXssTag);
  134. $this->assertNoRaw($this->xssString);
  135. }
  136. /**
  137. * Verify XSS injected in the entity titles are not rendered.
  138. */
  139. public function testXssEntityTitle() {
  140. // Load a page node.
  141. $this->drupalGet('node/add/page');
  142. $this->assertResponse(200);
  143. // Submit the node with some example XSS values.
  144. $edit = array(
  145. 'title' => $this->xssTitleString,
  146. 'body[und][0][value]' => 'hello world',
  147. );
  148. $this->drupalPost(NULL, $edit, t('Save'));
  149. // Verify the page saved.
  150. $this->assertResponse(200);
  151. $this->assertText(t('has been created.'));
  152. // Verify title is not the injected string and thus cleaned.
  153. $this->assertNoRaw($this->xssTitleString);
  154. }
  155. /**
  156. * Verify XSS injected in the body field is not rendered.
  157. */
  158. public function testXssEntityBody() {
  159. $title = 'Hello World';
  160. // Load a page node.
  161. $this->drupalGet('node/add/page');
  162. $this->assertResponse(200);
  163. // Submit the node with a test body value.
  164. $edit = array(
  165. 'title' => $title,
  166. 'body[und][0][value]' => $this->xssString,
  167. );
  168. $this->drupalPost(NULL, $edit, t('Save'));
  169. // Verify the page saved.
  170. $this->assertResponse(200);
  171. $this->assertText(t('Basic page @title has been created.', array('@title' => $title)));
  172. // Verify body field is clean.
  173. $this->assertNoRaw($this->xssString);
  174. }
  175. }