fix
This commit is contained in:
@@ -11,7 +11,7 @@ services:
|
||||
# - security_net
|
||||
restart: "always"
|
||||
ports:
|
||||
- "${FARM_PORT}:8000"
|
||||
- "3333:8000"
|
||||
|
||||
postgres:
|
||||
image: postgres:18
|
||||
@@ -6,4 +6,4 @@ WORKDIR /app
|
||||
|
||||
RUN pip install -r requirements.txt
|
||||
|
||||
CMD ["./start_server.sh"]
|
||||
ENTRYPOINT ["/app/start_server.sh"]
|
||||
|
||||
@@ -27,7 +27,7 @@ def post_flags():
|
||||
|
||||
db = database.get()
|
||||
cursor = db.cursor()
|
||||
cursor.executemany("INSERT OR IGNORE INTO flags (flag, sploit, team, time, status) "
|
||||
cursor.executemany("INSERT INTO flags (flag, sploit, team, time, status) "
|
||||
"VALUES (%s, %s, %s, %s, %s)", rows)
|
||||
db.commit()
|
||||
|
||||
|
||||
@@ -1,83 +1,83 @@
|
||||
import socket
|
||||
|
||||
from __init__ import app
|
||||
from models import FlagStatus, SubmitResult
|
||||
|
||||
|
||||
RESPONSES = {
|
||||
FlagStatus.QUEUED: ['timeout', 'game not started', 'try again later', 'game over', 'is not up',
|
||||
'no such flag'],
|
||||
FlagStatus.ACCEPTED: ['accepted', 'congrat'],
|
||||
FlagStatus.REJECTED: ['bad', 'wrong', 'expired', 'unknown', 'your own',
|
||||
'too old', 'not in database', 'already submitted', 'invalid flag',
|
||||
'self', 'invalid', 'already_submitted', 'team_not_found', 'too_old', 'stolen'],
|
||||
}
|
||||
|
||||
READ_TIMEOUT = 5
|
||||
APPEND_TIMEOUT = 0.05
|
||||
BUFSIZE = 4096
|
||||
|
||||
|
||||
def recvall(sock):
|
||||
sock.settimeout(READ_TIMEOUT)
|
||||
chunks = [sock.recv(BUFSIZE)]
|
||||
|
||||
sock.settimeout(APPEND_TIMEOUT)
|
||||
while True:
|
||||
try:
|
||||
chunk = sock.recv(BUFSIZE)
|
||||
if not chunk:
|
||||
break
|
||||
|
||||
chunks.append(chunk)
|
||||
except socket.timeout:
|
||||
break
|
||||
|
||||
sock.settimeout(READ_TIMEOUT)
|
||||
return b''.join(chunks)
|
||||
|
||||
|
||||
def submit_flags(flags, config):
|
||||
try:
|
||||
sock = socket.create_connection((config['SYSTEM_HOST'], config['SYSTEM_PORT']),
|
||||
READ_TIMEOUT)
|
||||
except (socket.error, ConnectionRefusedError) as e:
|
||||
app.logger.error(f"Failed to connect to checksystem: {e}")
|
||||
# Return all flags as QUEUED since we couldn't submit them
|
||||
for item in flags:
|
||||
yield SubmitResult(item.flag, FlagStatus.QUEUED, "Connection failed")
|
||||
return
|
||||
|
||||
try:
|
||||
greeting = recvall(sock)
|
||||
if b'Welcome' not in greeting:
|
||||
raise Exception('Checksystem does not greet us: {}'.format(greeting))
|
||||
|
||||
sock.sendall(config['TEAM_TOKEN'].encode() + b'\n')
|
||||
invite = recvall(sock)
|
||||
if b'enter your flags' not in invite:
|
||||
raise Exception('Team token seems to be invalid: {}'.format(invite))
|
||||
|
||||
unknown_responses = set()
|
||||
for item in flags:
|
||||
sock.sendall(item.flag.encode() + b'\n')
|
||||
response = recvall(sock).decode().strip()
|
||||
if response:
|
||||
response = response.splitlines()[0]
|
||||
response = response.replace('[{}] '.format(item.flag), '')
|
||||
|
||||
response_lower = response.lower()
|
||||
for status, substrings in RESPONSES.items():
|
||||
if any(s in response_lower for s in substrings):
|
||||
found_status = status
|
||||
break
|
||||
else:
|
||||
found_status = FlagStatus.QUEUED
|
||||
if response not in unknown_responses:
|
||||
unknown_responses.add(response)
|
||||
app.logger.warning('Unknown checksystem response (flag will be resent): %s', response)
|
||||
|
||||
yield SubmitResult(item.flag, found_status, response)
|
||||
|
||||
finally:
|
||||
sock.close()
|
||||
import socket
|
||||
|
||||
from __init__ import app
|
||||
from models import FlagStatus, SubmitResult
|
||||
|
||||
|
||||
RESPONSES = {
|
||||
FlagStatus.QUEUED: ['timeout', 'game not started', 'try again later', 'game over', 'is not up',
|
||||
'no such flag'],
|
||||
FlagStatus.ACCEPTED: ['accepted', 'congrat'],
|
||||
FlagStatus.REJECTED: ['bad', 'wrong', 'expired', 'unknown', 'your own',
|
||||
'too old', 'not in database', 'already submitted', 'invalid flag',
|
||||
'self', 'invalid', 'already_submitted', 'team_not_found', 'too_old', 'stolen'],
|
||||
}
|
||||
|
||||
READ_TIMEOUT = 5
|
||||
APPEND_TIMEOUT = 0.05
|
||||
BUFSIZE = 4096
|
||||
|
||||
|
||||
def recvall(sock):
|
||||
sock.settimeout(READ_TIMEOUT)
|
||||
chunks = [sock.recv(BUFSIZE)]
|
||||
|
||||
sock.settimeout(APPEND_TIMEOUT)
|
||||
while True:
|
||||
try:
|
||||
chunk = sock.recv(BUFSIZE)
|
||||
if not chunk:
|
||||
break
|
||||
|
||||
chunks.append(chunk)
|
||||
except socket.timeout:
|
||||
break
|
||||
|
||||
sock.settimeout(READ_TIMEOUT)
|
||||
return b''.join(chunks)
|
||||
|
||||
|
||||
def submit_flags(flags, config):
|
||||
try:
|
||||
sock = socket.create_connection((config['SYSTEM_HOST'], config['SYSTEM_PORT']),
|
||||
READ_TIMEOUT)
|
||||
except (socket.error, ConnectionRefusedError) as e:
|
||||
app.logger.error(f"Failed to connect to checksystem: {e}")
|
||||
# Return all flags as QUEUED since we couldn't submit them
|
||||
for item in flags:
|
||||
yield SubmitResult(item.flag, FlagStatus.QUEUED, "Connection failed")
|
||||
return
|
||||
|
||||
try:
|
||||
greeting = recvall(sock)
|
||||
if b'Welcome' not in greeting:
|
||||
raise Exception('Checksystem does not greet us: {}'.format(greeting))
|
||||
|
||||
sock.sendall(config['TEAM_TOKEN'].encode() + b'\n')
|
||||
invite = recvall(sock)
|
||||
if b'enter your flags' not in invite:
|
||||
raise Exception('Team token seems to be invalid: {}'.format(invite))
|
||||
|
||||
unknown_responses = set()
|
||||
for item in flags:
|
||||
sock.sendall(item.flag.encode() + b'\n')
|
||||
response = recvall(sock).decode().strip()
|
||||
if response:
|
||||
response = response.splitlines()[0]
|
||||
response = response.replace('[{}] '.format(item.flag), '')
|
||||
|
||||
response_lower = response.lower()
|
||||
for status, substrings in RESPONSES.items():
|
||||
if any(s in response_lower for s in substrings):
|
||||
found_status = status
|
||||
break
|
||||
else:
|
||||
found_status = FlagStatus.QUEUED
|
||||
if response not in unknown_responses:
|
||||
unknown_responses.add(response)
|
||||
app.logger.warning('Unknown checksystem response (flag will be resent): %s', response)
|
||||
|
||||
yield SubmitResult(item.flag, found_status, response)
|
||||
|
||||
finally:
|
||||
sock.close()
|
||||
|
||||
@@ -1,76 +1,76 @@
|
||||
# Based on https://gist.github.com/xmikasax/90a0ce5736a4274e46b9958f836951e7
|
||||
|
||||
import socket
|
||||
|
||||
from __init__ import app
|
||||
from models import FlagStatus, SubmitResult
|
||||
|
||||
|
||||
RESPONSES = {
|
||||
FlagStatus.QUEUED: ['timeout', 'game not started', 'try again later', 'game over', 'is not up',
|
||||
'no such flag'],
|
||||
FlagStatus.ACCEPTED: ['accepted', 'congrat'],
|
||||
FlagStatus.REJECTED: ['bad', 'wrong', 'expired', 'unknown', 'your own',
|
||||
'too old', 'not in database', 'already submitted', 'invalid flag',
|
||||
'self', 'invalid', 'already_submitted', 'team_not_found', 'too_old', 'stolen'],
|
||||
}
|
||||
|
||||
READ_TIMEOUT = 5
|
||||
APPEND_TIMEOUT = 0.05
|
||||
BUFSIZE = 4096
|
||||
|
||||
|
||||
def recvall(sock):
|
||||
sock.settimeout(READ_TIMEOUT)
|
||||
chunks = [sock.recv(BUFSIZE)]
|
||||
|
||||
sock.settimeout(APPEND_TIMEOUT)
|
||||
while True:
|
||||
try:
|
||||
chunk = sock.recv(BUFSIZE)
|
||||
if not chunk:
|
||||
break
|
||||
|
||||
chunks.append(chunk)
|
||||
except socket.timeout:
|
||||
break
|
||||
|
||||
sock.settimeout(READ_TIMEOUT)
|
||||
return b''.join(chunks)
|
||||
|
||||
|
||||
def submit_flags(flags, config):
|
||||
sock = socket.create_connection((config['SYSTEM_HOST'], config['SYSTEM_PORT']),
|
||||
READ_TIMEOUT)
|
||||
|
||||
greeting = recvall(sock)
|
||||
if b'Welcome' not in greeting:
|
||||
raise Exception('Checksystem does not greet us: {}'.format(greeting))
|
||||
|
||||
sock.sendall(config['TEAM_TOKEN'].encode() + b'\n')
|
||||
invite = recvall(sock)
|
||||
if b'enter your flags' not in invite:
|
||||
raise Exception('Team token seems to be invalid: {}'.format(invite))
|
||||
|
||||
unknown_responses = set()
|
||||
for item in flags:
|
||||
sock.sendall(item.flag.encode() + b'\n')
|
||||
response = recvall(sock).decode().strip()
|
||||
if response:
|
||||
response = response.splitlines()[0]
|
||||
response = response.replace('[{}] '.format(item.flag), '')
|
||||
|
||||
response_lower = response.lower()
|
||||
for status, substrings in RESPONSES.items():
|
||||
if any(s in response_lower for s in substrings):
|
||||
found_status = status
|
||||
break
|
||||
else:
|
||||
found_status = FlagStatus.QUEUED
|
||||
if response not in unknown_responses:
|
||||
unknown_responses.add(response)
|
||||
app.logger.warning('Unknown checksystem response (flag will be resent): %s', response)
|
||||
|
||||
yield SubmitResult(item.flag, found_status, response)
|
||||
|
||||
sock.close()
|
||||
# Based on https://gist.github.com/xmikasax/90a0ce5736a4274e46b9958f836951e7
|
||||
|
||||
import socket
|
||||
|
||||
from __init__ import app
|
||||
from models import FlagStatus, SubmitResult
|
||||
|
||||
|
||||
RESPONSES = {
|
||||
FlagStatus.QUEUED: ['timeout', 'game not started', 'try again later', 'game over', 'is not up',
|
||||
'no such flag'],
|
||||
FlagStatus.ACCEPTED: ['accepted', 'congrat'],
|
||||
FlagStatus.REJECTED: ['bad', 'wrong', 'expired', 'unknown', 'your own',
|
||||
'too old', 'not in database', 'already submitted', 'invalid flag',
|
||||
'self', 'invalid', 'already_submitted', 'team_not_found', 'too_old', 'stolen'],
|
||||
}
|
||||
|
||||
READ_TIMEOUT = 5
|
||||
APPEND_TIMEOUT = 0.05
|
||||
BUFSIZE = 4096
|
||||
|
||||
|
||||
def recvall(sock):
|
||||
sock.settimeout(READ_TIMEOUT)
|
||||
chunks = [sock.recv(BUFSIZE)]
|
||||
|
||||
sock.settimeout(APPEND_TIMEOUT)
|
||||
while True:
|
||||
try:
|
||||
chunk = sock.recv(BUFSIZE)
|
||||
if not chunk:
|
||||
break
|
||||
|
||||
chunks.append(chunk)
|
||||
except socket.timeout:
|
||||
break
|
||||
|
||||
sock.settimeout(READ_TIMEOUT)
|
||||
return b''.join(chunks)
|
||||
|
||||
|
||||
def submit_flags(flags, config):
|
||||
sock = socket.create_connection((config['SYSTEM_HOST'], config['SYSTEM_PORT']),
|
||||
READ_TIMEOUT)
|
||||
|
||||
greeting = recvall(sock)
|
||||
if b'Welcome' not in greeting:
|
||||
raise Exception('Checksystem does not greet us: {}'.format(greeting))
|
||||
|
||||
sock.sendall(config['TEAM_TOKEN'].encode() + b'\n')
|
||||
invite = recvall(sock)
|
||||
if b'enter your flags' not in invite:
|
||||
raise Exception('Team token seems to be invalid: {}'.format(invite))
|
||||
|
||||
unknown_responses = set()
|
||||
for item in flags:
|
||||
sock.sendall(item.flag.encode() + b'\n')
|
||||
response = recvall(sock).decode().strip()
|
||||
if response:
|
||||
response = response.splitlines()[0]
|
||||
response = response.replace('[{}] '.format(item.flag), '')
|
||||
|
||||
response_lower = response.lower()
|
||||
for status, substrings in RESPONSES.items():
|
||||
if any(s in response_lower for s in substrings):
|
||||
found_status = status
|
||||
break
|
||||
else:
|
||||
found_status = FlagStatus.QUEUED
|
||||
if response not in unknown_responses:
|
||||
unknown_responses.add(response)
|
||||
app.logger.warning('Unknown checksystem response (flag will be resent): %s', response)
|
||||
|
||||
yield SubmitResult(item.flag, found_status, response)
|
||||
|
||||
sock.close()
|
||||
|
||||
@@ -1,46 +1,46 @@
|
||||
import requests
|
||||
|
||||
from __init__ import app
|
||||
from models import FlagStatus, SubmitResult
|
||||
|
||||
|
||||
RESPONSES = {
|
||||
FlagStatus.QUEUED: ['timeout', 'game not started', 'try again later', 'game over', 'is not up',
|
||||
'no such flag'],
|
||||
FlagStatus.ACCEPTED: ['accepted', 'congrat'],
|
||||
FlagStatus.REJECTED: ['bad', 'wrong', 'expired', 'unknown', 'your own',
|
||||
'too old', 'not in database', 'already submitted', 'invalid flag'],
|
||||
}
|
||||
# The RuCTF checksystem adds a signature to all correct flags. It returns
|
||||
# "invalid flag" verdict if the signature is invalid and "no such flag" verdict if
|
||||
# the signature is correct but the flag was not found in the checksystem database.
|
||||
#
|
||||
# The latter situation happens if a checker puts the flag to the service before putting it
|
||||
# to the checksystem database. We should resent the flag later in this case.
|
||||
|
||||
|
||||
TIMEOUT = 5
|
||||
|
||||
|
||||
def submit_flags(flags, config):
|
||||
r = requests.put(config['SYSTEM_URL'],
|
||||
headers={'X-Team-Token': config['SYSTEM_TOKEN']},
|
||||
json=[item.flag for item in flags], timeout=TIMEOUT)
|
||||
|
||||
unknown_responses = set()
|
||||
for item in r.json():
|
||||
response = item['msg'].strip()
|
||||
response = response.replace('[{}] '.format(item['flag']), '')
|
||||
|
||||
response_lower = response.lower()
|
||||
for status, substrings in RESPONSES.items():
|
||||
if any(s in response_lower for s in substrings):
|
||||
found_status = status
|
||||
break
|
||||
else:
|
||||
found_status = FlagStatus.QUEUED
|
||||
if response not in unknown_responses:
|
||||
unknown_responses.add(response)
|
||||
app.logger.warning('Unknown checksystem response (flag will be resent): %s', response)
|
||||
|
||||
yield SubmitResult(item['flag'], found_status, response)
|
||||
import requests
|
||||
|
||||
from __init__ import app
|
||||
from models import FlagStatus, SubmitResult
|
||||
|
||||
|
||||
RESPONSES = {
|
||||
FlagStatus.QUEUED: ['timeout', 'game not started', 'try again later', 'game over', 'is not up',
|
||||
'no such flag'],
|
||||
FlagStatus.ACCEPTED: ['accepted', 'congrat'],
|
||||
FlagStatus.REJECTED: ['bad', 'wrong', 'expired', 'unknown', 'your own',
|
||||
'too old', 'not in database', 'already submitted', 'invalid flag'],
|
||||
}
|
||||
# The RuCTF checksystem adds a signature to all correct flags. It returns
|
||||
# "invalid flag" verdict if the signature is invalid and "no such flag" verdict if
|
||||
# the signature is correct but the flag was not found in the checksystem database.
|
||||
#
|
||||
# The latter situation happens if a checker puts the flag to the service before putting it
|
||||
# to the checksystem database. We should resent the flag later in this case.
|
||||
|
||||
|
||||
TIMEOUT = 5
|
||||
|
||||
|
||||
def submit_flags(flags, config):
|
||||
r = requests.put(config['SYSTEM_URL'],
|
||||
headers={'X-Team-Token': config['SYSTEM_TOKEN']},
|
||||
json=[item.flag for item in flags], timeout=TIMEOUT)
|
||||
|
||||
unknown_responses = set()
|
||||
for item in r.json():
|
||||
response = item['msg'].strip()
|
||||
response = response.replace('[{}] '.format(item['flag']), '')
|
||||
|
||||
response_lower = response.lower()
|
||||
for status, substrings in RESPONSES.items():
|
||||
if any(s in response_lower for s in substrings):
|
||||
found_status = status
|
||||
break
|
||||
else:
|
||||
found_status = FlagStatus.QUEUED
|
||||
if response not in unknown_responses:
|
||||
unknown_responses.add(response)
|
||||
app.logger.warning('Unknown checksystem response (flag will be resent): %s', response)
|
||||
|
||||
yield SubmitResult(item['flag'], found_status, response)
|
||||
|
||||
@@ -1,74 +1,74 @@
|
||||
import socket
|
||||
|
||||
from __init__ import app
|
||||
from models import FlagStatus, SubmitResult
|
||||
|
||||
|
||||
RESPONSES = {
|
||||
FlagStatus.QUEUED: ['timeout', 'game not started', 'try again later', 'game over', 'is not up',
|
||||
'no such flag'],
|
||||
FlagStatus.ACCEPTED: ['accepted', 'congrat'],
|
||||
FlagStatus.REJECTED: ['bad', 'wrong', 'expired', 'unknown', 'your own',
|
||||
'too old', 'not in database', 'already submitted', 'invalid flag'],
|
||||
}
|
||||
# The RuCTF checksystem adds a signature to all correct flags. It returns
|
||||
# "invalid flag" verdict if the signature is invalid and "no such flag" verdict if
|
||||
# the signature is correct but the flag was not found in the checksystem database.
|
||||
#
|
||||
# The latter situation happens if a checker puts the flag to the service before putting it
|
||||
# to the checksystem database. We should resent the flag later in this case.
|
||||
|
||||
READ_TIMEOUT = 5
|
||||
APPEND_TIMEOUT = 0.05
|
||||
BUFSIZE = 4096
|
||||
|
||||
|
||||
def recvall(sock):
|
||||
sock.settimeout(READ_TIMEOUT)
|
||||
chunks = [sock.recv(BUFSIZE)]
|
||||
|
||||
sock.settimeout(APPEND_TIMEOUT)
|
||||
while True:
|
||||
try:
|
||||
chunk = sock.recv(BUFSIZE)
|
||||
if not chunk:
|
||||
break
|
||||
|
||||
chunks.append(chunk)
|
||||
except socket.timeout:
|
||||
break
|
||||
|
||||
sock.settimeout(READ_TIMEOUT)
|
||||
return b''.join(chunks)
|
||||
|
||||
|
||||
def submit_flags(flags, config):
|
||||
sock = socket.create_connection((config['SYSTEM_HOST'], config['SYSTEM_PORT']),
|
||||
READ_TIMEOUT)
|
||||
|
||||
greeting = recvall(sock)
|
||||
if b'Enter your flags' not in greeting:
|
||||
raise Exception('Checksystem does not greet us: {}'.format(greeting))
|
||||
|
||||
unknown_responses = set()
|
||||
for item in flags:
|
||||
sock.sendall(item.flag.encode() + b'\n')
|
||||
response = recvall(sock).decode().strip()
|
||||
if response:
|
||||
response = response.splitlines()[0]
|
||||
response = response.replace('[{}] '.format(item.flag), '')
|
||||
|
||||
response_lower = response.lower()
|
||||
for status, substrings in RESPONSES.items():
|
||||
if any(s in response_lower for s in substrings):
|
||||
found_status = status
|
||||
break
|
||||
else:
|
||||
found_status = FlagStatus.QUEUED
|
||||
if response not in unknown_responses:
|
||||
unknown_responses.add(response)
|
||||
app.logger.warning('Unknown checksystem response (flag will be resent): %s', response)
|
||||
|
||||
yield SubmitResult(item.flag, found_status, response)
|
||||
|
||||
sock.close()
|
||||
import socket
|
||||
|
||||
from __init__ import app
|
||||
from models import FlagStatus, SubmitResult
|
||||
|
||||
|
||||
RESPONSES = {
|
||||
FlagStatus.QUEUED: ['timeout', 'game not started', 'try again later', 'game over', 'is not up',
|
||||
'no such flag'],
|
||||
FlagStatus.ACCEPTED: ['accepted', 'congrat'],
|
||||
FlagStatus.REJECTED: ['bad', 'wrong', 'expired', 'unknown', 'your own',
|
||||
'too old', 'not in database', 'already submitted', 'invalid flag'],
|
||||
}
|
||||
# The RuCTF checksystem adds a signature to all correct flags. It returns
|
||||
# "invalid flag" verdict if the signature is invalid and "no such flag" verdict if
|
||||
# the signature is correct but the flag was not found in the checksystem database.
|
||||
#
|
||||
# The latter situation happens if a checker puts the flag to the service before putting it
|
||||
# to the checksystem database. We should resent the flag later in this case.
|
||||
|
||||
READ_TIMEOUT = 5
|
||||
APPEND_TIMEOUT = 0.05
|
||||
BUFSIZE = 4096
|
||||
|
||||
|
||||
def recvall(sock):
|
||||
sock.settimeout(READ_TIMEOUT)
|
||||
chunks = [sock.recv(BUFSIZE)]
|
||||
|
||||
sock.settimeout(APPEND_TIMEOUT)
|
||||
while True:
|
||||
try:
|
||||
chunk = sock.recv(BUFSIZE)
|
||||
if not chunk:
|
||||
break
|
||||
|
||||
chunks.append(chunk)
|
||||
except socket.timeout:
|
||||
break
|
||||
|
||||
sock.settimeout(READ_TIMEOUT)
|
||||
return b''.join(chunks)
|
||||
|
||||
|
||||
def submit_flags(flags, config):
|
||||
sock = socket.create_connection((config['SYSTEM_HOST'], config['SYSTEM_PORT']),
|
||||
READ_TIMEOUT)
|
||||
|
||||
greeting = recvall(sock)
|
||||
if b'Enter your flags' not in greeting:
|
||||
raise Exception('Checksystem does not greet us: {}'.format(greeting))
|
||||
|
||||
unknown_responses = set()
|
||||
for item in flags:
|
||||
sock.sendall(item.flag.encode() + b'\n')
|
||||
response = recvall(sock).decode().strip()
|
||||
if response:
|
||||
response = response.splitlines()[0]
|
||||
response = response.replace('[{}] '.format(item.flag), '')
|
||||
|
||||
response_lower = response.lower()
|
||||
for status, substrings in RESPONSES.items():
|
||||
if any(s in response_lower for s in substrings):
|
||||
found_status = status
|
||||
break
|
||||
else:
|
||||
found_status = FlagStatus.QUEUED
|
||||
if response not in unknown_responses:
|
||||
unknown_responses.add(response)
|
||||
app.logger.warning('Unknown checksystem response (flag will be resent): %s', response)
|
||||
|
||||
yield SubmitResult(item.flag, found_status, response)
|
||||
|
||||
sock.close()
|
||||
|
||||
@@ -1,26 +1,26 @@
|
||||
from themis.finals.attack.helper import Helper
|
||||
from themis.finals.attack.result import Result
|
||||
|
||||
from models import FlagStatus, SubmitResult
|
||||
|
||||
|
||||
RESPONSES = {
|
||||
FlagStatus.ACCEPTED: [Result.SUCCESS_FLAG_ACCEPTED],
|
||||
FlagStatus.REJECTED: [Result.ERROR_FLAG_EXPIRED, Result.ERROR_FLAG_YOURS,
|
||||
Result.ERROR_FLAG_SUBMITTED, Result.ERROR_FLAG_NOT_FOUND],
|
||||
}
|
||||
|
||||
|
||||
def submit_flags(flags, config):
|
||||
h = Helper(config['SYSTEM_HOST'])
|
||||
codes = h.attack(*[item.flag for item in flags])
|
||||
|
||||
for item, code in zip(flags, codes):
|
||||
for status, possible_codes in RESPONSES.items():
|
||||
if code in possible_codes:
|
||||
found_status = status
|
||||
break
|
||||
else:
|
||||
found_status = FlagStatus.QUEUED
|
||||
|
||||
yield SubmitResult(item.flag, found_status, code.name)
|
||||
from themis.finals.attack.helper import Helper
|
||||
from themis.finals.attack.result import Result
|
||||
|
||||
from models import FlagStatus, SubmitResult
|
||||
|
||||
|
||||
RESPONSES = {
|
||||
FlagStatus.ACCEPTED: [Result.SUCCESS_FLAG_ACCEPTED],
|
||||
FlagStatus.REJECTED: [Result.ERROR_FLAG_EXPIRED, Result.ERROR_FLAG_YOURS,
|
||||
Result.ERROR_FLAG_SUBMITTED, Result.ERROR_FLAG_NOT_FOUND],
|
||||
}
|
||||
|
||||
|
||||
def submit_flags(flags, config):
|
||||
h = Helper(config['SYSTEM_HOST'])
|
||||
codes = h.attack(*[item.flag for item in flags])
|
||||
|
||||
for item, code in zip(flags, codes):
|
||||
for status, possible_codes in RESPONSES.items():
|
||||
if code in possible_codes:
|
||||
found_status = status
|
||||
break
|
||||
else:
|
||||
found_status = FlagStatus.QUEUED
|
||||
|
||||
yield SubmitResult(item.flag, found_status, code.name)
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,26 +1,26 @@
|
||||
@import url("https://fonts.googleapis.com/css?family=Open+Sans:300italic,400italic,700italic,400,300,700");
|
||||
|
||||
.navbar-brand {
|
||||
font-family: "Open Sans", "Helvetica Neue", Helvetica, Arial, sans-serif;
|
||||
font-size: 19px;
|
||||
font-weight: 300;
|
||||
padding: 15px 15px;
|
||||
color: #e52250;
|
||||
}
|
||||
|
||||
.logo {
|
||||
height: 30px;
|
||||
}
|
||||
|
||||
.table td {
|
||||
font-size: 14px;
|
||||
padding: 0.65rem 0.75rem;
|
||||
}
|
||||
|
||||
textarea {
|
||||
resize: none;
|
||||
}
|
||||
|
||||
#text-with-flags {
|
||||
height: 80px;
|
||||
}
|
||||
@import url("https://fonts.googleapis.com/css?family=Open+Sans:300italic,400italic,700italic,400,300,700");
|
||||
|
||||
.navbar-brand {
|
||||
font-family: "Open Sans", "Helvetica Neue", Helvetica, Arial, sans-serif;
|
||||
font-size: 19px;
|
||||
font-weight: 300;
|
||||
padding: 15px 15px;
|
||||
color: #e52250;
|
||||
}
|
||||
|
||||
.logo {
|
||||
height: 30px;
|
||||
}
|
||||
|
||||
.table td {
|
||||
font-size: 14px;
|
||||
padding: 0.65rem 0.75rem;
|
||||
}
|
||||
|
||||
textarea {
|
||||
resize: none;
|
||||
}
|
||||
|
||||
#text-with-flags {
|
||||
height: 80px;
|
||||
}
|
||||
|
||||
10
server/static/js/jquery.min.js
vendored
10
server/static/js/jquery.min.js
vendored
File diff suppressed because one or more lines are too long
@@ -1,144 +1,144 @@
|
||||
function padLeft(s, length) {
|
||||
s = s.toString();
|
||||
while (s.length < length)
|
||||
s = '0' + s;
|
||||
return s;
|
||||
}
|
||||
|
||||
function dateToString(date) {
|
||||
return padLeft(date.getFullYear(), 4) + '-' + padLeft(date.getMonth() + 1, 2) + '-' +
|
||||
padLeft(date.getDate(), 2) + ' ' +
|
||||
padLeft(date.getHours(), 2) + ':' + padLeft(date.getMinutes(), 2) + ':' +
|
||||
padLeft(date.getSeconds(), 2);
|
||||
}
|
||||
|
||||
function escapeHtml(text) {
|
||||
return $('<div>').text(text).html();
|
||||
}
|
||||
|
||||
function generateFlagTableRows(rows) {
|
||||
var html = '';
|
||||
rows.forEach(function (item) {
|
||||
var cells = [
|
||||
item.sploit,
|
||||
item.team !== null ? item.team : '',
|
||||
item.flag,
|
||||
dateToString(new Date(item.time * 1000)),
|
||||
item.status,
|
||||
item.checksystem_response !== null ? item.checksystem_response : ''
|
||||
];
|
||||
|
||||
html += '<tr>';
|
||||
cells.forEach(function (text) {
|
||||
html += '<td>' + escapeHtml(text) + '</td>';
|
||||
});
|
||||
html += '</tr>';
|
||||
});
|
||||
return html;
|
||||
}
|
||||
|
||||
function generatePaginator(totalCount, rowsPerPage, pageNumber) {
|
||||
var totalPages = Math.ceil(totalCount / rowsPerPage);
|
||||
var firstShown = Math.max(1, pageNumber - 3);
|
||||
var lastShown = Math.min(totalPages, pageNumber + 3);
|
||||
|
||||
var html = '';
|
||||
if (firstShown > 1)
|
||||
html += '<li class="page-item"><a class="page-link" href="#" data-content="1">«</a></li>';
|
||||
|
||||
for (var i = firstShown; i <= lastShown; i++) {
|
||||
var extraClasses = (i === pageNumber ? "active" : "");
|
||||
html += '<li class="page-item ' + extraClasses + '">' +
|
||||
'<a class="page-link" href="#" data-content="' + i + '">' + i + '</a>' +
|
||||
'</li>';
|
||||
}
|
||||
|
||||
if (lastShown < totalPages)
|
||||
html += '<li class="page-item">' +
|
||||
'<a class="page-link" href="#" data-content="' + totalPages + '">»</a>' +
|
||||
'</li>';
|
||||
return html;
|
||||
}
|
||||
|
||||
function getPageNumber() {
|
||||
return parseInt($('#page-number').val());
|
||||
}
|
||||
|
||||
function setPageNumber(number) {
|
||||
$('#page-number').val(number);
|
||||
}
|
||||
|
||||
var queryInProgress = false;
|
||||
|
||||
function showFlags() {
|
||||
if (queryInProgress)
|
||||
return;
|
||||
queryInProgress = true;
|
||||
|
||||
$('.search-results').hide();
|
||||
$('.query-status').html('Loading...').show();
|
||||
|
||||
$.post('/ui/show_flags', $('#show-flags-form').serialize())
|
||||
.done(function (response) {
|
||||
$('.search-results tbody').html(generateFlagTableRows(response.rows));
|
||||
|
||||
$('.search-results .total-count').text(response.total_count);
|
||||
$('.search-results .pagination').html(generatePaginator(
|
||||
response.total_count, response.rows_per_page, getPageNumber()));
|
||||
$('.search-results .page-link').click(function (event) {
|
||||
event.preventDefault();
|
||||
|
||||
setPageNumber($(this).data("content"));
|
||||
showFlags();
|
||||
});
|
||||
|
||||
$('.query-status').hide();
|
||||
$('.search-results').show();
|
||||
})
|
||||
.fail(function () {
|
||||
$('.query-status').html("Failed to load flags from the farm server");
|
||||
})
|
||||
.always(function () {
|
||||
queryInProgress = false;
|
||||
});
|
||||
}
|
||||
|
||||
function postFlagsManual() {
|
||||
if (queryInProgress)
|
||||
return;
|
||||
queryInProgress = true;
|
||||
|
||||
$.post('/ui/post_flags_manual', $('#post-flags-manual-form').serialize())
|
||||
.done(function () {
|
||||
var sploitSelect = $('#sploit-select');
|
||||
if ($('#sploit-manual-option').empty())
|
||||
sploitSelect.append($('<option id="sploit-manual-option">Manual</option>'));
|
||||
sploitSelect.val('Manual');
|
||||
|
||||
$('#team-select, #flag-input, #time-since-input, #time-until-input, ' +
|
||||
'#status-select, #checksystem-response-input').val('');
|
||||
|
||||
queryInProgress = false;
|
||||
showFlags();
|
||||
})
|
||||
.fail(function () {
|
||||
$('.query-status').html("Failed to post flags to the farm server");
|
||||
queryInProgress = false;
|
||||
});
|
||||
}
|
||||
|
||||
$(function () {
|
||||
showFlags();
|
||||
|
||||
$('#show-flags-form').submit(function (event) {
|
||||
event.preventDefault();
|
||||
|
||||
setPageNumber(1);
|
||||
showFlags();
|
||||
});
|
||||
$('#post-flags-manual-form').submit(function (event) {
|
||||
event.preventDefault();
|
||||
|
||||
postFlagsManual();
|
||||
});
|
||||
});
|
||||
function padLeft(s, length) {
|
||||
s = s.toString();
|
||||
while (s.length < length)
|
||||
s = '0' + s;
|
||||
return s;
|
||||
}
|
||||
|
||||
function dateToString(date) {
|
||||
return padLeft(date.getFullYear(), 4) + '-' + padLeft(date.getMonth() + 1, 2) + '-' +
|
||||
padLeft(date.getDate(), 2) + ' ' +
|
||||
padLeft(date.getHours(), 2) + ':' + padLeft(date.getMinutes(), 2) + ':' +
|
||||
padLeft(date.getSeconds(), 2);
|
||||
}
|
||||
|
||||
function escapeHtml(text) {
|
||||
return $('<div>').text(text).html();
|
||||
}
|
||||
|
||||
function generateFlagTableRows(rows) {
|
||||
var html = '';
|
||||
rows.forEach(function (item) {
|
||||
var cells = [
|
||||
item.sploit,
|
||||
item.team !== null ? item.team : '',
|
||||
item.flag,
|
||||
dateToString(new Date(item.time * 1000)),
|
||||
item.status,
|
||||
item.checksystem_response !== null ? item.checksystem_response : ''
|
||||
];
|
||||
|
||||
html += '<tr>';
|
||||
cells.forEach(function (text) {
|
||||
html += '<td>' + escapeHtml(text) + '</td>';
|
||||
});
|
||||
html += '</tr>';
|
||||
});
|
||||
return html;
|
||||
}
|
||||
|
||||
function generatePaginator(totalCount, rowsPerPage, pageNumber) {
|
||||
var totalPages = Math.ceil(totalCount / rowsPerPage);
|
||||
var firstShown = Math.max(1, pageNumber - 3);
|
||||
var lastShown = Math.min(totalPages, pageNumber + 3);
|
||||
|
||||
var html = '';
|
||||
if (firstShown > 1)
|
||||
html += '<li class="page-item"><a class="page-link" href="#" data-content="1">«</a></li>';
|
||||
|
||||
for (var i = firstShown; i <= lastShown; i++) {
|
||||
var extraClasses = (i === pageNumber ? "active" : "");
|
||||
html += '<li class="page-item ' + extraClasses + '">' +
|
||||
'<a class="page-link" href="#" data-content="' + i + '">' + i + '</a>' +
|
||||
'</li>';
|
||||
}
|
||||
|
||||
if (lastShown < totalPages)
|
||||
html += '<li class="page-item">' +
|
||||
'<a class="page-link" href="#" data-content="' + totalPages + '">»</a>' +
|
||||
'</li>';
|
||||
return html;
|
||||
}
|
||||
|
||||
function getPageNumber() {
|
||||
return parseInt($('#page-number').val());
|
||||
}
|
||||
|
||||
function setPageNumber(number) {
|
||||
$('#page-number').val(number);
|
||||
}
|
||||
|
||||
var queryInProgress = false;
|
||||
|
||||
function showFlags() {
|
||||
if (queryInProgress)
|
||||
return;
|
||||
queryInProgress = true;
|
||||
|
||||
$('.search-results').hide();
|
||||
$('.query-status').html('Loading...').show();
|
||||
|
||||
$.post('/ui/show_flags', $('#show-flags-form').serialize())
|
||||
.done(function (response) {
|
||||
$('.search-results tbody').html(generateFlagTableRows(response.rows));
|
||||
|
||||
$('.search-results .total-count').text(response.total_count);
|
||||
$('.search-results .pagination').html(generatePaginator(
|
||||
response.total_count, response.rows_per_page, getPageNumber()));
|
||||
$('.search-results .page-link').click(function (event) {
|
||||
event.preventDefault();
|
||||
|
||||
setPageNumber($(this).data("content"));
|
||||
showFlags();
|
||||
});
|
||||
|
||||
$('.query-status').hide();
|
||||
$('.search-results').show();
|
||||
})
|
||||
.fail(function () {
|
||||
$('.query-status').html("Failed to load flags from the farm server");
|
||||
})
|
||||
.always(function () {
|
||||
queryInProgress = false;
|
||||
});
|
||||
}
|
||||
|
||||
function postFlagsManual() {
|
||||
if (queryInProgress)
|
||||
return;
|
||||
queryInProgress = true;
|
||||
|
||||
$.post('/ui/post_flags_manual', $('#post-flags-manual-form').serialize())
|
||||
.done(function () {
|
||||
var sploitSelect = $('#sploit-select');
|
||||
if ($('#sploit-manual-option').empty())
|
||||
sploitSelect.append($('<option id="sploit-manual-option">Manual</option>'));
|
||||
sploitSelect.val('Manual');
|
||||
|
||||
$('#team-select, #flag-input, #time-since-input, #time-until-input, ' +
|
||||
'#status-select, #checksystem-response-input').val('');
|
||||
|
||||
queryInProgress = false;
|
||||
showFlags();
|
||||
})
|
||||
.fail(function () {
|
||||
$('.query-status').html("Failed to post flags to the farm server");
|
||||
queryInProgress = false;
|
||||
});
|
||||
}
|
||||
|
||||
$(function () {
|
||||
showFlags();
|
||||
|
||||
$('#show-flags-form').submit(function (event) {
|
||||
event.preventDefault();
|
||||
|
||||
setPageNumber(1);
|
||||
showFlags();
|
||||
});
|
||||
$('#post-flags-manual-form').submit(function (event) {
|
||||
event.preventDefault();
|
||||
|
||||
postFlagsManual();
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,48 +1,48 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>Login Required</title>
|
||||
<style>
|
||||
body {
|
||||
font-family: sans-serif;
|
||||
max-width: 500px;
|
||||
margin: 40px auto;
|
||||
padding: 20px;
|
||||
}
|
||||
.login-form {
|
||||
border: 1px solid #ccc;
|
||||
padding: 20px;
|
||||
border-radius: 4px;
|
||||
}
|
||||
input[type="password"] {
|
||||
width: 100%;
|
||||
padding: 8px;
|
||||
margin: 10px 0;
|
||||
border: 1px solid #ccc;
|
||||
border-radius: 4px;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
input[type="submit"] {
|
||||
background-color: #4CAF50;
|
||||
color: white;
|
||||
padding: 10px 15px;
|
||||
border: none;
|
||||
border-radius: 4px;
|
||||
cursor: pointer;
|
||||
}
|
||||
input[type="submit"]:hover {
|
||||
background-color: #45a049;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class="login-form">
|
||||
<h2>Добро пожаловать!</h2>
|
||||
<form method="POST">
|
||||
<label for="password">Пароль:</label>
|
||||
<input type="password" id="password" name="password" required>
|
||||
<input type="submit" value="Войти">
|
||||
</form>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>Login Required</title>
|
||||
<style>
|
||||
body {
|
||||
font-family: sans-serif;
|
||||
max-width: 500px;
|
||||
margin: 40px auto;
|
||||
padding: 20px;
|
||||
}
|
||||
.login-form {
|
||||
border: 1px solid #ccc;
|
||||
padding: 20px;
|
||||
border-radius: 4px;
|
||||
}
|
||||
input[type="password"] {
|
||||
width: 100%;
|
||||
padding: 8px;
|
||||
margin: 10px 0;
|
||||
border: 1px solid #ccc;
|
||||
border-radius: 4px;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
input[type="submit"] {
|
||||
background-color: #4CAF50;
|
||||
color: white;
|
||||
padding: 10px 15px;
|
||||
border: none;
|
||||
border-radius: 4px;
|
||||
cursor: pointer;
|
||||
}
|
||||
input[type="submit"]:hover {
|
||||
background-color: #45a049;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class="login-form">
|
||||
<h2>Добро пожаловать!</h2>
|
||||
<form method="POST">
|
||||
<label for="password">Пароль:</label>
|
||||
<input type="password" id="password" name="password" required>
|
||||
<input type="submit" value="Войти">
|
||||
</form>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@@ -1,150 +1,150 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
|
||||
<meta name="description" content="">
|
||||
<meta name="author" content="">
|
||||
<link rel="icon" href="/static/logo.png">
|
||||
|
||||
<title>Poison Berries Farm - Server</title>
|
||||
|
||||
<link href="/static/css/bootswatch-flatly.css" rel="stylesheet">
|
||||
<link href="/static/css/style.css" rel="stylesheet">
|
||||
</head>
|
||||
|
||||
<body>
|
||||
|
||||
<nav class="navbar navbar-expand-lg navbar-dark bg-dark py-0">
|
||||
<img class="logo" src="/static/img/logo.png">
|
||||
<div class="navbar-brand">Poison Berries Farm</div>
|
||||
</nav>
|
||||
|
||||
<div class="container mt-4">
|
||||
<div class="row mb-4">
|
||||
<div class="col-lg-8">
|
||||
<div class="card border-light">
|
||||
<div class="card-body">
|
||||
<h4 class="card-title">Show Flags</h4>
|
||||
<form id="show-flags-form">
|
||||
<div class="row mb-2">
|
||||
<div class="col-md-4">
|
||||
<label for="sploit-select">Sploit</label>
|
||||
<select class="form-control form-control-sm" id="sploit-select" name="sploit">
|
||||
<option value="">All</option>
|
||||
{% for item in distinct_values['sploit'] %}
|
||||
<option>{{ item }}</option>
|
||||
{% endfor %}
|
||||
</select>
|
||||
</div>
|
||||
<div class="col-md-4">
|
||||
<label for="team-select">Team</label>
|
||||
<select class="form-control form-control-sm" id="team-select" name="team">
|
||||
<option value="">All</option>
|
||||
{% for item in distinct_values['team'] %}
|
||||
<option>{{ item }}</option>
|
||||
{% endfor %}
|
||||
</select>
|
||||
</div>
|
||||
<div class="col-md-4">
|
||||
<label for="flag-input">
|
||||
Flag
|
||||
<small class="text-muted ml-2">substring, case-insensitive</small>
|
||||
</label>
|
||||
<input type="text" class="form-control form-control-sm" id="flag-input" name="flag">
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-3">
|
||||
<div class="col-md-3">
|
||||
<label for="time-since-input">
|
||||
Since
|
||||
<small class="text-muted ml-2">{{ server_tz_name }}</small>
|
||||
</label>
|
||||
<input type="text" class="form-control form-control-sm" id="time-since-input"
|
||||
name="time-since"
|
||||
placeholder="yyyy-mm-dd hh:mm">
|
||||
</div>
|
||||
<div class="col-md-3">
|
||||
<label for="time-until-input">
|
||||
Until
|
||||
<small class="text-muted ml-2">{{ server_tz_name }}</small>
|
||||
</label>
|
||||
<input type="text" class="form-control form-control-sm" id="time-until-input"
|
||||
name="time-until"
|
||||
placeholder="yyyy-mm-dd hh:mm">
|
||||
</div>
|
||||
<div class="col-md-2">
|
||||
<label for="status-select">Status</label>
|
||||
<select class="form-control form-control-sm" id="status-select" name="status">
|
||||
<option value="">All</option>
|
||||
{% for item in distinct_values['status'] %}
|
||||
<option>{{ item }}</option>
|
||||
{% endfor %}
|
||||
</select>
|
||||
</div>
|
||||
<div class="col-md-4">
|
||||
<label for="checksystem-response-input">
|
||||
Checksystem response
|
||||
</label>
|
||||
<input type="text" class="form-control form-control-sm" id="checksystem-response-input"
|
||||
name="checksystem_response">
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-12">
|
||||
<button type="submit" class="btn btn-primary btn-sm submit-btn">Show</button>
|
||||
</div>
|
||||
</div>
|
||||
<input type="hidden" value="1" id="page-number" name="page-number">
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-lg-4">
|
||||
<div class="card border-light">
|
||||
<div class="card-body">
|
||||
<h4 class="card-title">Add Flags Manually</h4>
|
||||
<form id="post-flags-manual-form">
|
||||
<label for="text-with-flags">
|
||||
Text with flags
|
||||
<small class="text-muted ml-2">flag format: {{ flag_format }}</small>
|
||||
</label>
|
||||
<textarea class="form-control form-control-sm mb-3" id="text-with-flags" name="text"></textarea>
|
||||
<button type="submit" class="btn btn-primary btn-sm">Send</button>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="mb-3 text-center query-status"></div>
|
||||
|
||||
<div class="search-results" style="display: none;">
|
||||
<p>Found <span class="total-count"></span> flags</p>
|
||||
|
||||
<ul class="pagination pagination-sm"></ul>
|
||||
|
||||
<table class="table table-hover">
|
||||
<thead>
|
||||
<tr class="table-secondary">
|
||||
<th scope="col">Sploit</th>
|
||||
<th scope="col">Team</th>
|
||||
<th scope="col">Flag</th>
|
||||
<th scope="col">Time</th>
|
||||
<th scope="col">Status</th>
|
||||
<th scope="col">Checksystem Response</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody></tbody>
|
||||
</table>
|
||||
|
||||
<ul class="pagination pagination-sm"></ul>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script src="/static/js/jquery.min.js"></script>
|
||||
<script src="/static/js/ui.js"></script>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
|
||||
<meta name="description" content="">
|
||||
<meta name="author" content="">
|
||||
<link rel="icon" href="/static/logo.png">
|
||||
|
||||
<title>Poison Berries Farm - Server</title>
|
||||
|
||||
<link href="/static/css/bootswatch-flatly.css" rel="stylesheet">
|
||||
<link href="/static/css/style.css" rel="stylesheet">
|
||||
</head>
|
||||
|
||||
<body>
|
||||
|
||||
<nav class="navbar navbar-expand-lg navbar-dark bg-dark py-0">
|
||||
<img class="logo" src="/static/img/logo.png">
|
||||
<div class="navbar-brand">Poison Berries Farm</div>
|
||||
</nav>
|
||||
|
||||
<div class="container mt-4">
|
||||
<div class="row mb-4">
|
||||
<div class="col-lg-8">
|
||||
<div class="card border-light">
|
||||
<div class="card-body">
|
||||
<h4 class="card-title">Show Flags</h4>
|
||||
<form id="show-flags-form">
|
||||
<div class="row mb-2">
|
||||
<div class="col-md-4">
|
||||
<label for="sploit-select">Sploit</label>
|
||||
<select class="form-control form-control-sm" id="sploit-select" name="sploit">
|
||||
<option value="">All</option>
|
||||
{% for item in distinct_values['sploit'] %}
|
||||
<option>{{ item }}</option>
|
||||
{% endfor %}
|
||||
</select>
|
||||
</div>
|
||||
<div class="col-md-4">
|
||||
<label for="team-select">Team</label>
|
||||
<select class="form-control form-control-sm" id="team-select" name="team">
|
||||
<option value="">All</option>
|
||||
{% for item in distinct_values['team'] %}
|
||||
<option>{{ item }}</option>
|
||||
{% endfor %}
|
||||
</select>
|
||||
</div>
|
||||
<div class="col-md-4">
|
||||
<label for="flag-input">
|
||||
Flag
|
||||
<small class="text-muted ml-2">substring, case-insensitive</small>
|
||||
</label>
|
||||
<input type="text" class="form-control form-control-sm" id="flag-input" name="flag">
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-3">
|
||||
<div class="col-md-3">
|
||||
<label for="time-since-input">
|
||||
Since
|
||||
<small class="text-muted ml-2">{{ server_tz_name }}</small>
|
||||
</label>
|
||||
<input type="text" class="form-control form-control-sm" id="time-since-input"
|
||||
name="time-since"
|
||||
placeholder="yyyy-mm-dd hh:mm">
|
||||
</div>
|
||||
<div class="col-md-3">
|
||||
<label for="time-until-input">
|
||||
Until
|
||||
<small class="text-muted ml-2">{{ server_tz_name }}</small>
|
||||
</label>
|
||||
<input type="text" class="form-control form-control-sm" id="time-until-input"
|
||||
name="time-until"
|
||||
placeholder="yyyy-mm-dd hh:mm">
|
||||
</div>
|
||||
<div class="col-md-2">
|
||||
<label for="status-select">Status</label>
|
||||
<select class="form-control form-control-sm" id="status-select" name="status">
|
||||
<option value="">All</option>
|
||||
{% for item in distinct_values['status'] %}
|
||||
<option>{{ item }}</option>
|
||||
{% endfor %}
|
||||
</select>
|
||||
</div>
|
||||
<div class="col-md-4">
|
||||
<label for="checksystem-response-input">
|
||||
Checksystem response
|
||||
</label>
|
||||
<input type="text" class="form-control form-control-sm" id="checksystem-response-input"
|
||||
name="checksystem_response">
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-12">
|
||||
<button type="submit" class="btn btn-primary btn-sm submit-btn">Show</button>
|
||||
</div>
|
||||
</div>
|
||||
<input type="hidden" value="1" id="page-number" name="page-number">
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-lg-4">
|
||||
<div class="card border-light">
|
||||
<div class="card-body">
|
||||
<h4 class="card-title">Add Flags Manually</h4>
|
||||
<form id="post-flags-manual-form">
|
||||
<label for="text-with-flags">
|
||||
Text with flags
|
||||
<small class="text-muted ml-2">flag format: {{ flag_format }}</small>
|
||||
</label>
|
||||
<textarea class="form-control form-control-sm mb-3" id="text-with-flags" name="text"></textarea>
|
||||
<button type="submit" class="btn btn-primary btn-sm">Send</button>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="mb-3 text-center query-status"></div>
|
||||
|
||||
<div class="search-results" style="display: none;">
|
||||
<p>Found <span class="total-count"></span> flags</p>
|
||||
|
||||
<ul class="pagination pagination-sm"></ul>
|
||||
|
||||
<table class="table table-hover">
|
||||
<thead>
|
||||
<tr class="table-secondary">
|
||||
<th scope="col">Sploit</th>
|
||||
<th scope="col">Team</th>
|
||||
<th scope="col">Flag</th>
|
||||
<th scope="col">Time</th>
|
||||
<th scope="col">Status</th>
|
||||
<th scope="col">Checksystem Response</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody></tbody>
|
||||
</table>
|
||||
|
||||
<ul class="pagination pagination-sm"></ul>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script src="/static/js/jquery.min.js"></script>
|
||||
<script src="/static/js/ui.js"></script>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
|
||||
Reference in New Issue
Block a user