Skip to content

Commit

Permalink
Merge pull request #48 from BuffaloWill/python-docx-vulnerable
Browse files Browse the repository at this point in the history
Python docx vulnerable
  • Loading branch information
BuffaloWill authored May 5, 2023
2 parents 0594702 + b5e4514 commit 9efdcd1
Show file tree
Hide file tree
Showing 7 changed files with 66 additions and 34 deletions.
32 changes: 16 additions & 16 deletions lib/lib.rb
Original file line number Diff line number Diff line change
Expand Up @@ -38,13 +38,14 @@ def oxml_file_defaults()
return d
end

# This is the most basic option. Given an exploit type, what to exploit (e.g. /etc/passwd) and
# a file type it will build an oxml xxe.
def build_file(params)
# proto (required): protocol on connect back
# hostname (required): hostname to connect to
# file (required): the file to write
# file_type
# xml_file
#
# file_type (required): file extension -- e.g. docx
# hostname (required): connect back host -- this is confusing as it's not used by every combination

oxmls = oxml_file_defaults()
pl = read_payloads()

Expand All @@ -55,21 +56,20 @@ def build_file(params)
ip = params["proto"]+"://"+params["hostname"]
end

if params[:file] != nil
# TODO support svg
# TODO support xml
input_file = params[:file][:tempfile].read
nname = "temp_#{Time.now.to_i}_"
ext = params[:file][:filename].split('.').last
rand_file = "./output/#{nname}_z.#{ext}"
File.open(rand_file, 'wb') {|f| f.write(input_file) }
file_exploit = rand_file
# This takes in a file type and picks the file from the samples.
input_file = oxmls[params["file_type"]][0]
if input_file == ""
raise StandardError, "Error: File could not be found based on file_type"
end

nname = "temp_#{Time.now.to_i}_"
ext = params["file_type"]
rand_file = "./output/#{nname}_z.#{ext}"
# Make a copy of the sample and place it into the rand_file
FileUtils::copy_file(input_file,rand_file)

if oxmls.include?(params["file_type"])
xml_file = params["xml_file"].size > 0 ? params["xml_file"] : oxmls[params["file_type"]][1]
file_exploit = oxmls[params["file_type"]][0]
fn = insert_payload_docx(file_exploit,xml_file,pl[params["payload"]][0],ip,params["exfil_file"])
fn = string_replace(pl[params["payload"]][0],rand_file,ip,params["exfil_file"])
elsif params["file_type"] == "svg"
fn = insert_payload_svg("./samples/sample.svg",pl[params["payload"]][0],ip,params["exfil_file"])
elsif params["file_type"] == "xml"
Expand Down
6 changes: 2 additions & 4 deletions lib/util.rb
Original file line number Diff line number Diff line change
Expand Up @@ -200,6 +200,8 @@ def jpg_poc(hostname)
return nm
end

# Given the xxe payload, the input_file (e.g. output_foo_rand.docx), and what to exfiltrate --
# this will replace §.
def string_replace(payload,input_file,ip,exfiltrate)
targets = []

Expand All @@ -225,14 +227,10 @@ def string_replace(payload,input_file,ip,exfiltrate)
FileUtils::copy_file(input_file,rand_file)

targets.each do |target|

document = read_rels(rand_file,"#{target}")

docx_xml = payload(document,payload,ip,exfiltrate)

# replace string
docx_xml = docx_xml.gsub("§","&xxe;")

docx_modify(rand_file, docx_xml, target)
end

Expand Down
17 changes: 17 additions & 0 deletions test/python-docx-vulnerable/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
FROM debian:stable-20230502-slim

# Install Python3 and pip3
RUN apt-get update && apt-get install -y python3 python3-pip

# Install python-docx library
RUN pip3 install python-docx==0.8.4
RUN pip3 install flask

# Set working directory
WORKDIR /app

# Copy your Python code to the container
COPY app.py .

# Run your Python code when the container starts
CMD ["python3", "app.py"]
18 changes: 18 additions & 0 deletions test/python-docx-vulnerable/app.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
from flask import Flask, render_template, request
import docx

app = Flask(__name__)

@app.route('/', methods=['GET', 'POST'])
def upload_file():
if request.method == 'POST':
file = request.files['file']
if file:
document = docx.Document(file)
main_content = '\n\n'.join([paragraph.text for paragraph in document.paragraphs])
# Print the main content to the console
return 'File uploaded and parsed successfully!' + "\n"+main_content
return render_template('upload.html')

if __name__ == '__main__':
app.run(host='0.0.0.0')
12 changes: 12 additions & 0 deletions test/upload_file_to_endpoint.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
require 'rest-client'

file_path = ARGV[0]
if !file_path
puts "Please provide a file path as a command line argument."
exit
end

file = File.new(file_path)

response = RestClient.post('http://localhost:5000/', :file => file)
puts response
13 changes: 0 additions & 13 deletions views/build.slim
Original file line number Diff line number Diff line change
Expand Up @@ -41,19 +41,6 @@ table style="width: 70%;"
| Description of File
td style="width: 70%"
input type="text" style="width: 90%" name="desc" value=""
tr
td style="width: 30%"
h4 Advanced Optional Settings
tr
td style="width: 30%"
| Specify XML File for DOCX/XSLX/PPTX/ODT
td style="width: 70%"
input type="text" style="width: 90%" name="xml_file" value=""
tr
td style="width: 30%"
| File To Replace (Must Match File Type)
td style="width: 70%"
input type="file" name="file"
tr
td style="width: 30%"
tr
Expand Down
2 changes: 1 addition & 1 deletion views/help.slim
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
td style='width: 50%'
= v[1]
td style='width: 35%'
= clean_xml(v[0]).gsub("\n","")
= v[0].gsub("\n","")
table style='width: 100%;'
h4 Payload Variables
tbody
Expand Down

0 comments on commit 9efdcd1

Please sign in to comment.