Введение
technicalseo.expert - это головоломка для SEO, хотя я сел не имея никакого бэкграунда в SEO, а сейчас работаю скромным датасаентистом. Разработала головоломку Алексис Сандерс, работающая в международном агентстве маркетинга Merkle Inc. Алексис объясняет "Идея игры заключалась в том, чтобы позволить SEO-специалистам изучить технические аспекты своей профессии. Но второй уровень требует глубочайших познаний в HTML, CSS, PHP и Java. Третий уровень был спроектирован так, чтобы никто никогда его не прошёл"
Подготовка
Сразу скажу, что почти все уровни были пройдены с открытым Developers tools на Chrome. Там можно и html страницы поглядеть, и на responce полюбоваться. Так же использовался python (для удобства запускалось все в блокнотах jupyter notebook). Всколзь будет упоминаться Postman, но никакого влияния он не окажет в итоге, так что можно смело его вычеркивать.
Предупреждение!
Если кто-то хочет лично пройти этот челендж - дальше читать противопоказано. Будут скрины и прочее.
Кроме того, прошу прощение у SEO, я не совсем понимаю суть того, что я сделал с точки зрения SEO. Если кого обидел - извиняюсь.
Уровень 1
Красота! А теперь глянем в Developers tool
Немного HTML
<html><head>
<link rel="stylesheet" type="text/css" href="style.css">
<title>Welcome to the SEO Matrix</title>
<meta name="description" content="Sometimes the beginning is not where the story truly begins, sometimes it starts with an invasion of robots, an overbearing government, and a lonely hero.">
<link href="https://fonts.googleapis.com/css?family=VT323" rel="stylesheet">
</head>
<body>
<canvas id="c" height="948" width="1848"></canvas>
<div id="content" style="color:white; font-family: 'VT323', monospace;">
<h1>Welcome to our SEO challenge v1</h1>
<p>You have everything you need. Now make your choice. </p>
<p>You take the blue pill, the story ends. You wake up in your bed and believe whatever you want to believe. You take the red pill, you stay in Wonderland, and I show you how deep the rabbit hole goes.</p>
<p style="visibility:hidden;">The journey begins at the gateway for all robots.</p>
</div>
<!-- Matrix Rain; Nothing to see here people. -->
<style>
body {background: black;}
</style>
<script>
function draw(){ctx.fillStyle="rgba(0, 0, 0, 0.05)",ctx.fillRect(0,0,c.width,c.height),ctx.fillStyle="#0F0",ctx.font=font_size+"px arial";for(var a=0;a<drops.length;a++){var b=j[Math.floor(Math.random()*j.length)];ctx.fillText(b,a*font_size,drops[a]*font_size),drops[a]*font_size>c.height&&Math.random()>.975&&(drops[a]=0),drops[a]++}}var c=document.getElementById("c"),ctx=c.getContext("2d");c.height=window.innerHeight,c.width=window.innerWidth;var j="私は誰ですか?ああ、それは素晴らしいパズルです。1!2@3#4$5%6^7&8*9(0)";j=j.split("");for(var font_size=10,columns=c.width/font_size,drops=[],x=0;x<columns;x++)drops[x]=1;setInterval(draw,33);
</script>
</body></html>
Самое интересное тут строчка
<p style="visibility:hidden;">The journey begins at the gateway for all robots.</p>
Очевидный намек на robots.txt
Идем проверять!
robots.txt
user-agent: *
Disallow:
sitemap: /sitemap.xml
# Level One Clue: The spaces between words are removed, no hyphens.
#
# /\
# / \
# / /\ \
# / ____ \
# /_/ \_\
##############################
# Created by:
# Alexis Sanders: https://twitter.com/AlexisKSanders
#
# Thank you to our part 2 beta testers:
# Max Prin: https://twitter.com/maxxeight
# Dave Thomas: https://www.linkedin.com/in/dave-thomas-2448058/
# Brian Barna: https://www.linkedin.com/in/brianbarna/
#
# Thank you to our part 1 beta testers:
# Masaki Okazawa: https://www.linkedin.com/in/masakiokazawa/
# Steve Valenza: https://www.linkedin.com/in/stevevalenza/
# Max Prin: https://twitter.com/maxxeight
# Kyla Becker: https://www.linkedin.com/in/kylabecker
Штош... Есть подсказка на sitemap, что было очевидно (я зашел туда до того, как прочитал внимательно robots), а дальше что-то интересное. Огронмная буква А. Интригует? Отправляемся дальше, на sitemap.
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
<url>
<loc>/bluepill</loc>
</url>
<url>
<loc>/redpill</loc>
</url>
</urlset>
Что-то про сине-красные пилюли я видел на первой странице... Но для эксперимента я проверил синюю и получил экран Game Over (который я буду получать потом достаточно часто). Проверил многими способами, даже слал разные типы запросов через Postman - итог один. Пьем красную!
Не очень информативно. Может HTML нам раскажет что-то интересное?
HTML
<html><head>
<link rel="stylesheet" type="text/css" href="style.css">
<meta name="ROBOTS" content="NOINDEX, NOFOLLOW">
<link href="https://fonts.googleapis.com/css?family=VT323" rel="stylesheet">
<title>You have chosen the red pill.</title>
<meta name="description" content="Sure, there are grays... but when you come right down to it, at its core, beneath every choice, there's either a one or a zero. Are you a one or a zero?">
</head>
<body>
<div id="content" style="font-family: 'VT323', monospace;">
<h1>Follow me?</h1>
<p>Make your choice.</p>
</div>
<div class="rememberme">
______
| ____|
| |__
| __|
| |____
|______|
</div>
</body></html>
Большая буква Е. АЕ... Еще глаз цепляется за тег meta
<meta name="description" content="Sure, there are grays... but when you come right down to it, at its core, beneath every choice, there's either a one or a zero. Are you a one or a zero?">
Пробуем путь "/1" и переходим...
Неплохо... Что же нам скажет HTML?
HTML
<html><head>
<link rel="stylesheet" type="text/css" href="style.css">
<meta name="ROBOTS" content="NOINDEX, NOFOLLOW">
<link href="https://fonts.googleapis.com/css?family=VT323" rel="stylesheet">
<title>41726520796f75207375726520796f75207769736820746f2074616b65207468697320706174683f</title>
<script async="" src="https://www.google-analytics.com/analytics.js"></script><script type="application/ld+json">
{
"@context": "http://schema.org",
"@type": "WebSite",
"name": "Red Pill",
"alternateName": "The SEO challenge that'll take you into an alternate reality.",
"url": "http://www.example.com/",
"sameAs": "http://www.example.com/funsociety"
}
</script>
</head>
<body id="content" style="font-family: 'VT323', monospace;">
<h1>01011001 01101111 01110101 00100000 01100001 01110010 01100101 00100000 01110100 01101000 01100101 00100000 01100010 01101001 01101110 01100001 01110010 01111001 00100000 01100101 01101100 01101001 01110100 01100101 00101100 00100000 01101110 01101111 01110111 00100000 01110111 01101000 01100001 01110100 00100000 01100001 01100010 01101111 01110101 01110100 00100000 01101000 01100101 01111000 00111111</h1>
<p>5765206172652066736f63696574792e2057652061726520667265652e20576520617265206177616b652e</p>
<div class="rememberme">
__ __
\ \ / /
\ \ /\ / /
\ \/ \/ /
\ /\ /
\/ \/
</div>
</body></html>
Даже расшифровывать нет необходимости... Сразу видно ссылку "/funsociety"
Так даже немного нечестно. Но все равно расшифруем с помощью скромных скриптов python
kek = []
lol = '01011001 01101111 01110101 00100000 01100001 01110010 01100101 00100000 01110100 01101000 01100101 00100000 01100010 01101001 01101110 01100001 01110010 01111001 00100000 01100101 01101100 01101001 01110100 01100101 00101100 00100000 01101110 01101111 01110111 00100000 01110111 01101000 01100001 01110100 00100000 01100001 01100010 01101111 01110101 01110100 00100000 01101000 01100101 01111000 00111111'
for x in lol.split():
kek.append(x)
lol=''
for x in kek:
lol+=chr(int(x,2))
print(lol)
Наградой будет фраза:
You are the binary elite, now what about hex?
Отлично, есть у меня скрипт и на hex...
lol = '5765206172652066736f63696574792e2057652061726520667265652e20576520617265206177616b652e'
# lol = '41726520796f75207375726520796f75207769736820746f2074616b65207468697320706174683f'
kek = []
for x in range(int(len(lol)/2)):
kek.append(lol[x*2:x*2+2])
lol=''
for x in kek:
lol+=chr(int(x,16))
print(lol)
Имеем в итоге две фразы - с заголовка и со страницы.
We are fsociety. We are free. We are awake. - страница
Are you sure you wish to take this path? - заголовок
Ничего необычного. Отправляемся по ссылке.
HTML
<html><head>
<link rel="stylesheet" type="text/css" href="style.css">
<meta name="ROBOTS" content="NOINDEX, NOFOLLOW">
<link href="https://fonts.googleapis.com/css?family=VT323" rel="stylesheet">
<title>Bonsoir, Elliot.</title>
</head>
<body id="content" style="font-family: 'VT323', monospace;">
<h1>We are free. We are...</h1>
<p>...Your transition has been interrupted... </p>
<img src="dontletthedarknessconsumeyou.jpg" alt="/darkarmy">
<div class="rememberme">
__ __
| \/ |
| \ / |
| |\/| |
| | | |
|_| |_|
</div>
Без особой выдумки. Даже немного скучновато. Атрибут alt у картинки очевиден. Новая ссылка "/darkarmy" получена. А за одно и новая буква в копилку.
HTML
<html>
<head>
<link rel="stylesheet" type="text/css" href="style.css">
<META NAME="ROBOTS" CONTENT="NOINDEX, NOFOLLOW">
<link href="https://fonts.googleapis.com/css?family=VT323" rel="stylesheet">
<title>Do not go gentle into that good night</title>
</head>
<body id="content" style="font-family: 'VT323', monospace;">
<h1>Rage, rage against the dying of the light.</h1>
<p>Don't let the darkness consume you, Elliot.</p>
<a href="/darkside" class="hidden"></a>
<div class="rememberme">
| __ \
| |__) |
| _ /
| | \ \
|_| \_\
</div>
</body>
</html>
Новая буква R и очевидная ссылка "/darkside". Идем дальше.
Так просто? Ссыока на самом видном месте?
HTML
<html>
<head>
<link rel="stylesheet" type="text/css" href="style.css">
<META NAME="ROBOTS" CONTENT="NOINDEX, NOFOLLOW">
<link href="https://fonts.googleapis.com/css?family=VT323" rel="stylesheet">
<title>In the darkest times, light shines the brightest.</title>
</head>
<body id="content" style="font-family: 'VT323', monospace;">
<h1>You've taken a dark path, but there is hope yet.</h1>
<p>You're lost, but one day, you might be found. So why not start looking around?</p>
<p class="hidden">Why don't you /followtherabbit</p>
<div class="rememberme">
_
| |
| |
| |
| |____
|______|
</div>
</body>
</html>
А, нет, класс hidden, просто CSS шалит )
Штош, это не наша вина. Но букву L мы все же запомним.
HTML
<html>
<head>
<link rel="stylesheet" type="text/css" href="style.css">
<META NAME="ROBOTS" CONTENT="NOINDEX, NOFOLLOW">
<link href="https://fonts.googleapis.com/css?family=VT323" rel="stylesheet">
<title>If you want to know, follow the white rabbit.</title>
<link rel="amphtml" href="/followtherabbitamp.html">
</head>
<body id="content" style="font-family: 'VT323', monospace;">
<h1>Remember that all I am offering is the truth. Nothing more.</h1>
<p>In another moment down went Alice after it, never once considering how in the world she was to get out again.</p>
<div class="rememberme">
_____
| __ \
| | | |
| | | |
| |__| |
|_____/
</div>
</body>
</html>
Даже думать и читать не хочется, про AMP. Не сегодня по крайней мере. Проходим дальше.
HTML
<html amp lang="en">
<head>
<meta charset="utf-8">
<META NAME="ROBOTS" CONTENT="NOINDEX, NOFOLLOW">
<script async src="https://cdn.ampproject.org/v0.js"></script>
<title></title>
<link rel="canonical" href="/welcome2wonderland" />
<link href="https://fonts.googleapis.com/css?family=VT323" rel="stylesheet">
<style amp-custom>
#content {
background: #;
bottom: 0;
height: 500px;
left: 0;
margin: 1em;
position: absolute;
top: 0;
right: 0;
width: 50%;
padding: 20px;
font-family: 'VT323', monospace;
}
p {
font-size: 200%;
}
.rememberme {visibility:hidden;}
</style>
<meta name="viewport" content="width=device-width,minimum-scale=1,initial-scale=1">
<style amp-boilerplate>body{-webkit-animation:-amp-start 8s steps(1,end) 0s 1 normal both;-moz-animation:-amp-start 8s steps(1,end) 0s 1 normal both;-ms-animation:-amp-start 8s steps(1,end) 0s 1 normal both;animation:-amp-start 8s steps(1,end) 0s 1 normal both}@-webkit-keyframes -amp-start{from{visibility:hidden}to{visibility:visible}}@-moz-keyframes -amp-start{from{visibility:hidden}to{visibility:visible}}@-ms-keyframes -amp-start{from{visibility:hidden}to{visibility:visible}}@-o-keyframes -amp-start{from{visibility:hidden}to{visibility:visible}}@keyframes -amp-start{from{visibility:hidden}to{visibility:visible}}</style><noscript><style amp-boilerplate>body{-webkit-animation:none;-moz-animation:none;-ms-animation:none;animation:none}</style></noscript>
</head>
<body>
<div id="content">
<h1>The Door stands in front of you.</h1>
<p>Door: Why it's simply impassible!</p>
<p>Alice: Why, don't you mean impossible?</p>
<p>Door: No, I do mean impassible. (chuckles) Nothing's impossible!</p>
</div>
</body>
</html>
Снова видим ссылку в теге head и отправляемся в страну чудес, хотя это все начинает навевать скуку... "/welcome2wonderland" у нас и мы идем дальше.
<html>
<head>
<link rel="stylesheet" type="text/css" href="style.css">
<META NAME="ROBOTS" CONTENT="NOINDEX, NOFOLLOW">
<link href="https://fonts.googleapis.com/css?family=VT323" rel="stylesheet">
<title>Welcome to the real world, Neo.</title>
<link rel="alternate" href="/fr/bienvenueaupaysdesmerveilles" hreflang="fr" />
</head>
<body id="content" style="font-family: 'VT323', monospace;">
<h1>Welcome to the real world, Neo.</h1>
<p> I promised you the truth, Neo,
and the truth is that the world you were living in was a lie.</p>
</body>
</html>
Снова очевидная ссылка в head. Даже сыпрятанные буквы пропали! Переходим по "/fr/bienvenueaupaysdesmerveilles" и...
Уже что-то интереснее...
А, не, проходная страница
Достаем ссылку на картинку: "/fr/thequeen.jpg" и видим ссылку.
И снова стандартное послание.
<html>
<head>
<link rel="stylesheet" type="text/css" href="style.css">
<META NAME="ROBOTS" CONTENT="NOINDEX, NOFOLLOW">
<link href="https://fonts.googleapis.com/css?family=VT323" rel="stylesheet">
<meta name="fragment" content="!"/>
<title>Bow down to her majesty, the Red Queen.</title>
</head>
<body id="content" style="font-family: 'VT323', monospace;">
<h1>Off with their escaped fragments!</h1>
<p>My dear, here we must run as fast as we can, just to stay in place. And if you wish to go anywhere you must run twice as fast as that.</p>
</body>
</html>
Как? Нет ссылки? А так можно было?
К счастью через 10 минут беглого стаковерфлоуинга ответ найден - просто добавь воды! В смысле ?_escaped_fragments_=
Теперь немного редиректов и мы пришли на новую старничку: "/bow2thequeennow.html"
<html>
<head>
<link rel="stylesheet" type="text/css" href="style.css">
<META NAME="ROBOTS" CONTENT="NOINDEX, NOFOLLOW">
<link href="https://fonts.googleapis.com/css?family=VT323" rel="stylesheet">
<title>Escape with the Mad Hatter. Time for Tea.</title>
</head>
<body id="content" style="font-family: 'VT323', monospace;">
<h1>Way to go.</h1>
<p>/escapewiththemadhatter</p>
<p>Alice: Where should I go?</p>
<p>Cheshire Cat: That depends on where you want to end up.</p>
<div class="rememberme">
/\
/ \
/ /\ \
/ ____ \
/_/ \_\
</div>
</body>
</html>
О! Снова буковки, а я уже начал скучать! А ссылку можно прочитать и сразу на странице.
Подсказки... Ну зачем было портить все веселье?
<html>
<head>
<link rel="stylesheet" type="text/css" href="style.css">
<META NAME="ROBOTS" CONTENT="NOINDEX, NOFOLLOW">
<link href="https://fonts.googleapis.com/css?family=VT323" rel="stylesheet">
<title>Want a spot of tea?</title>
</head>
<body id="content" style="font-family: 'VT323', monospace;">
<h1>Drink some of that error status code.</h1>
<p>Mad Matter: Have I gone mad?</p>
<p>Alice: I'm afraid so. You're entirely bonkers. But I'll tell you a secret. All the best people are.</p>
<p>The next page in your journey will be the status code of this URL: /XXX</p>
<div class="rememberme">
______
| ____|
| |__
| __|
| |____
|______|
</div>
</body>
</html>
Видим, что следующая ссылка будет "/418"
Но у нас есть чудо скрипт...
С его помощью получаем новую ссылку "/areyoutheone"
<html>
<head>
<link rel="stylesheet" type="text/css" href="style.css">
<META NAME="ROBOTS" CONTENT="NOINDEX, NOFOLLOW">
<link href="https://fonts.googleapis.com/css?family=VT323" rel="stylesheet">
<title>Enjoy your teapot status? lol.</title>
</head>
<body id="content" style="font-family: 'VT323', monospace;">
<h1>Could you be THE one?</h1>
<p>NEO: Morpheus, I know you won't believe me but the Oracle told me I'm not the One.</p>
<p> MORPHEUS: It doesn't matter if I don't believe you, What matters is that you don't believe her.
</p>
<div class="rememberme">
_
| |
| |
| |
| |____
|______|
</div>
</body>
</html>
Пусто! Ссылки нет, только буква... Но нас уже не остановить!
Мы знаем следующую ссылку: "/whatisrealanymore"
И тут я застреваю... Надо идти назад? Я проверил все страницы до... Даже постманом стучался POST запросами и другими нетипичными. Пусто. Ничего. Внезапно на ночь решаю еще раз проверить все ссылки, но так как ночь, то делаю это с телефона.
Что-то новое. Пытаемся понять что произошло и переходим в mobile mode (но уже на следующий день, да) в Chrome... и переходим на новую страницу: "/areyoualonesometimestoo"
И там находим новую ссылку. "/hellofriend"
Пишем сообщение, получаем ссылку, а по пути в HTML находим и еще одну спрятанную букву А. Что дальше?
Вводим фразу из собранных букв, которые я немного переставил (тут оставим немного интриги...)
ТА-ДАМ! Мы прошли задачку. Даже в процессе заскучать успели. Штош... Только где же ссылка на Уровень 2? Кто заметит?