Bug #73767 [Com]: script in document.write (string) in <script> in html get corrupted
| From: | justin dot maxwell at tibit dot com | Date: | Sat, 17 Dec 2016 16:30:42 +0000 |
| Subject: | Bug #73767 [Com]: script in document.write (string) in <script> in html get corrupted | ||
| References: | 1 | Groups: | php.bugs |
| Request: | Send a blank email to php-bugs+get-206103@lists.php.net to get a copy of this message | ||
Edit report at https://bugs.php.net/bug.php?id=73767&edit=1
ID: 73767
Comment by: justin dot maxwell at tibit dot com
Reported by: justin dot maxwell at tibit dot com
Summary: script in document.write (string) in <script> in
html get corrupted
Status: Not a bug
Type: Bug
Package: DOM XML related
Operating System: Mint 18
PHP Version: 7.0.14
Block user comment: N
Private report: N
New Comment:
BETTER EXAMPLE:
This uses javascript taken directly from an example at http://api.jquery.com/append/.
Otherwise, it is exactly the same behaviour and bug.
Input HTML:
<!DOCTYPE html>
<html>
<head>
<title>Test libxml</title>
</head>
<body>
<script type="text/javascript">
$( ".inner" ).append( "<p>Test</p>" );
</script>
</body>
</html>
Process:
$doc= new DOMDocument();
$doc->loadHTML('text-libxml.html');
$doc->saveHTML();
Output: (with added line breaks)
<!DOCTYPE html>
<html>
<head>
<title>Test libxml</title>
</head>
<body>
<script type="text/javascript">
$( ".inner" ).append( "<p>Test" );
</script>
</body>
</html>
Note that the closing </p> tag from the source JavaScript string has been stripped out by the
DOMDocument HTML Load/Save.
Previous Comments:
------------------------------------------------------------------------
[2016-12-17 14:47:33] justin dot maxwell at tibit dot com
You have MISREAD what I wrote, and WRONGLY CLOSED this bug report.
The BUG(!) is that the string is NOT treated as* CDATA and the string is CHANGED.
You say:
> Why you think JavaScript code ... some.js"></scr'+'ipt>'
> must yield ... some.js">'+'ipt>'
I DON'T THINK THAT! THAT IS WHAT IT DOES NOW! THAT IS WHAT THE BUG IS!
You would know this if you had tried the trivial sample provided. I'm entitled to some
CAPSLOCK.
This bug makes libxml, and so standard PHP, deficient for use as a simple filtering proxy, as it
cannot be relied on to simply load served, VALID (albeit very poorly constructed) HTML, without
corrupting character strings on certain (poorly constructed) sites in a way that can massively
affect the way that the page is subsequently rendered.
Furthermore: For what ought to be obvious reasons, you cannot say BOTH:
> chars in the string must be encoded, AND
> Contents inside script tag is CDATA
*In any event, per HTML5 the spec section 4.11.1.2
"Restrictions for contents of script elements"
1) This is NOT 'CDATA' ('\' does not escape inside CDATA)
2) There is NO REQUIREMENT to encode characters inside script elements.
In particular, see the code snippet in the HTML5 spec section referenced above that is preceded by
the words "the problem is avoided entirely:" that recommends an approach that includes
unencoded < >.
---
An ending word:
I am hugely grateful for all the developers who help maintain and enhance PHP and similar projects.
What your efforts, much of it voluntary, mean, is not lost on me.
But I am annoyed at this response, because after hours tracking down this obscure, weird, freaky
bug, and then taking the time to file a bug report, including a complete test case requiring
three-lines of PHP -- rather than just execute that, the responder has basically not bothered to
properly read the report, assumed I'm an idiot, told me I'm stupid (in not so many words),
and CLOSED the bug report; when it would have taken perhaps thirty seconds to see that the bug is
DOING what he is wrongly accusing me of wrongly WANTING.
And now, to bolster this, I've had to dive back into the depths of HTML5 specs, just to make
sure that everything I previously understood, and am stating here, is, in fact, correct; and to
bolster the case for re-opening this bug. Which, incidentally, is no longer causing me a problem,
because I preg_replace the problematic string to add the additional '+' per the third
<scr... line in the report description, which is sufficient to have the server HTML load and save
without corruption by libxml. I'm just wanting to help the next person who hits it.
Again, thanks. Will someone please re-open so I don't have to open a new report?
Cheers.
------------------------------------------------------------------------
[2016-12-17 00:59:47] yohgaki@php.net
Besides chars in the string must be URL encoded or entity at least, and this kind of simple
JavaScript injections must be prevented at program that generates JavaScript.
Why you think JavaScript code
'<scr'+'ipt src="http://example.com/some.js"></scr'+'ipt>'
must yield
'<scr'+'ipt src="http://example.com/some.js">'+'ipt>'
?
This is totally wrong thing to do. Contents inside script tag is CDATA and it must return string as
it is.
BTW, if your system allows such string generation from user's inputs, there is no reliable way
to prevent injection attacks.
------------------------------------------------------------------------
[2016-12-16 23:38:33] justin dot maxwell at tibit dot com
Description:
------------
---
From manual page: http://www.php.net/book.libxml
---
PHP 7.0.8-0ubuntu0.16.04.3
I have no control of the site with this erm, <expletive> oldskool hacky code in it, but I need
to parse it.
See the HTML snippet in the test script for details, but after loadHTML, saveHTML, the string
parameter to document.write is missing a piece.
On input, it is: '<scr'+'ipt src="http://example.com/some.js"></scr'+'ipt>'
On output : '<scr'+'ipt src="http://example.com/some.js">'+'ipt>'
Which of course wreaks havoc with the unclosed injected script tag.
Incidentally, : '<scr'+'ipt src="http://example.com/some.js"><'+'/scr'+'ipt>'
... on first glance, seems to be parsed without corruption.
Test script:
---------------
Using HTML as beneath
$doc= new DOMDocument();
$doc->loadHTMLFile('test-libxml.html');
$doc->saveHTML();
<!DOCTYPE html>
<html>
<head>
<title>Test libxml</title>
</head>
<body>
<script type="text/javascript">
document.write('<scr'+'ipt src="http://example.com/some.js"></scr'+'ipt>');
</script>
</body>
</html>
Expected result:
----------------
<!DOCTYPE html>
<html>
<head>
<title>Test libxml</title>
</head>
<body>
<script type="text/javascript">
document.write('<scr'+'ipt src="http://example.com/some.js">'+'ipt>');
</script>
</body>
</html>
Actual result:
--------------
<!DOCTYPE html>
<html>
<head>
<title>Test libxml</title>
</head>
<body>
<script type="text/javascript">
document.write('<scr'+'ipt src="http://example.com/some.js"></scr'+'ipt>');
</script>
</body>
</html>
------------------------------------------------------------------------
--
Edit this bug report at https://bugs.php.net/bug.php?id=73767&edit=1