public async Task <string> Put(string host, string id, string flag, int vuln) { var client = new AsyncHttpClient(GetBaseUri(host), true); var result = await client.DoRequestAsync(HttpMethod.Get, ApiGenerate, null, NetworkOpTimeout, MaxHttpBodySize).ConfigureAwait(false); if (result.StatusCode != HttpStatusCode.OK) { throw new CheckerException(result.StatusCode.ToExitCode(), $"get {ApiGenerate} failed"); } var rubik = DoIt.TryOrDefault(() => JsonSerializer.Deserialize <GeneratedRubik>(result.BodyAsString)); if (rubik == default) { throw new CheckerException(ExitCode.MUMBLE, $"invalid {ApiGenerate} response"); } await Console.Error.WriteLineAsync($"rubik '{rubik.Rubik}', signed '{rubik.Value}'").ConfigureAwait(false); string solution; try { solution = DoIt.TryOrDefault(() => SolveHelper.ConvertOutputSolution(RubikSolver.FindSolution(SolveHelper.ConvertInputCube(rubik.Rubik), 32, 10000))); } catch (RubikSolveException e) { await Console.Error.WriteLineAsync(e.Message).ConfigureAwait(false); throw new CheckerException(ExitCode.MUMBLE, $"invalid {ApiGenerate} response: unsolvable puzzle"); } await Console.Error.WriteLineAsync($"solution '{solution}'").ConfigureAwait(false); await RndUtil.RndDelay(MaxDelay).ConfigureAwait(false); var login = RndText.RandomWord(RndUtil.GetInt(MinRandomFieldLength, MaxRandomFieldLength)).RandomLeet().RandomUpperCase(); var pass = RndText.RandomWord(RndUtil.GetInt(MinRandomFieldLength, MaxRandomFieldLength)).RandomLeet().RandomUpperCase(); await Console.Error.WriteLineAsync($"name '{login}', pass '{pass}', bio '{flag}'").ConfigureAwait(false); var query = $"?login={WebUtility.UrlEncode(login)}&pass={WebUtility.UrlEncode(pass)}&bio={WebUtility.UrlEncode(flag)}&puzzle={WebUtility.UrlEncode(rubik.Value)}&solution={WebUtility.UrlEncode(solution)}"; result = await client.DoRequestAsync(HttpMethod.Post, ApiSolve + query, null, NetworkOpTimeout, MaxHttpBodySize).ConfigureAwait(false); if (result.StatusCode != HttpStatusCode.OK) { throw new CheckerException(result.StatusCode.ToExitCode(), $"post {ApiSolve} failed"); } var sln = DoIt.TryOrDefault(() => JsonSerializer.Deserialize <Solution>(result.BodyAsString)); if (sln == default || sln.Login != login || sln.MovesCount != solution.Length) { throw new CheckerException(ExitCode.MUMBLE, $"invalid {ApiSolve} response"); } await Console.Error.WriteLineAsync($"solution '{solution}'").ConfigureAwait(false); var cookie = client.Cookies.GetCookieHeader(GetBaseUri(host)); await Console.Error.WriteLineAsync($"cookie '{cookie}'").ConfigureAwait(false); if (string.IsNullOrEmpty(cookie) || cookie.Length > 512) { throw new CheckerException(result.StatusCode.ToExitCode(), $"invalid {ApiSolve} response: cookies"); } return($"{login}:{pass}:{Convert.ToBase64String(Encoding.UTF8.GetBytes(cookie))}"); }
public async Task Check(string host) { var client = new AsyncHttpClient(GetBaseUri(host), true); var result = await client.DoRequestAsync(HttpMethod.Get, "/", null, NetworkOpTimeout, MaxHttpBodySize).ConfigureAwait(false); if (result.StatusCode != HttpStatusCode.OK) { throw new CheckerException(result.StatusCode.ToExitCode(), "get / failed"); } await RndUtil.RndDelay(MaxDelay).ConfigureAwait(false); result = await client.DoRequestAsync(HttpMethod.Get, ApiGenerate, null, NetworkOpTimeout, MaxHttpBodySize).ConfigureAwait(false); if (result.StatusCode != HttpStatusCode.OK) { throw new CheckerException(result.StatusCode.ToExitCode(), $"get {ApiGenerate} failed"); } var rubik = DoIt.TryOrDefault(() => JsonSerializer.Deserialize <GeneratedRubik>(result.BodyAsString)); if (rubik == default) { throw new CheckerException(ExitCode.MUMBLE, $"invalid {ApiGenerate} response"); } await Console.Error.WriteLineAsync($"rubik '{rubik.Rubik}', signed '{rubik.Value}'").ConfigureAwait(false); await RndUtil.RndDelay(MaxDelay).ConfigureAwait(false); var login = RndText.RandomWord(RndUtil.GetInt(MinRandomFieldLength, MaxRandomFieldLength)).RandomLeet().RandomUpperCase(); var pass = RndText.RandomWord(RndUtil.GetInt(MinRandomFieldLength, MaxRandomFieldLength)).RandomLeet().RandomUpperCase(); var flag = RndText.RandomWord(RndUtil.GetInt(MinRandomFieldLength, MaxRandomFieldLength)).RandomLeet().RandomUpperCase(); await Console.Error.WriteLineAsync($"name '{login}', pass '{pass}', bio '{flag}'").ConfigureAwait(false); var solution = RndRubik.RandomSolution(MinRandomSolutionLength, MaxRandomSolutionLength); var query = $"?login={WebUtility.UrlEncode(login)}&pass={WebUtility.UrlEncode(pass)}&bio={WebUtility.UrlEncode(flag)}&puzzle={WebUtility.UrlEncode(rubik.Value)}&solution={WebUtility.UrlEncode(solution)}"; result = await client.DoRequestAsync(HttpMethod.Post, ApiSolve + query, null, NetworkOpTimeout, MaxHttpBodySize).ConfigureAwait(false); if (result.StatusCode != (HttpStatusCode)418) { throw new CheckerException(result.StatusCode == HttpStatusCode.OK ? ExitCode.MUMBLE : result.StatusCode.ToExitCode(), $"invalid {ApiSolve} response"); } await RndUtil.RndDelay(MaxDelay).ConfigureAwait(false); result = await client.DoRequestAsync(HttpMethod.Get, ApiAuth, null, NetworkOpTimeout, MaxHttpBodySize).ConfigureAwait(false); if (result.StatusCode != HttpStatusCode.OK) { throw new CheckerException(result.StatusCode.ToExitCode(), $"get {ApiAuth} failed"); } var user = DoIt.TryOrDefault(() => JsonSerializer.Deserialize <User>(result.BodyAsString)); if (user == default || user.Login != login || user.Bio != flag) { throw new CheckerException(ExitCode.MUMBLE, $"invalid {ApiAuth} response"); } }
public async Task Get(string host, string id, string flag, int vuln) { var parts = id.Split(':', 4); if (parts.Length != 4) { throw new Exception($"Invalid flag id '{id}'"); } var login = parts[0]; var pass = parts[1]; var cookie = Encoding.UTF8.GetString(Convert.FromBase64String(parts[2])); var encodedQuery = parts[3]; var client = new AsyncHttpClient(GetBaseUri(host), true); if (RndUtil.GetInt(0, 2) == 0) { await Console.Error.WriteLineAsync($"login by cookie '{cookie}'").ConfigureAwait(false); client.Cookies.SetCookies(GetBaseUri(host), cookie); } else { await Console.Error.WriteLineAsync($"login with login '{login}' and pass '{pass}'").ConfigureAwait(false); var loginQuery = $"?login={WebUtility.UrlEncode(login)}&password={WebUtility.UrlEncode(pass)}"; var signInResult = await client.DoRequestAsync(HttpMethod.Post, ApiAuthSignIn + loginQuery).ConfigureAwait(false); if (signInResult.StatusCode != HttpStatusCode.OK) { throw new CheckerException(signInResult.StatusCode.ToExitCode(), $"get {ApiAuthSignIn} failed"); } await Console.Error.WriteLineAsync($"cookie '{client.Cookies.GetCookieHeader(GetBaseUri(host))}'").ConfigureAwait(false); await RndUtil.RndDelay(MaxDelay).ConfigureAwait(false); } var query = RndUtil.Choice("?query=&myOnly=on", "?query=" + encodedQuery); var result = await client.DoRequestAsync(HttpMethod.Get, ApiNotesSearch + query, null, NetworkOpTimeout, MaxHttpBodySize).ConfigureAwait(false); if (result.StatusCode != HttpStatusCode.OK) { throw new CheckerException(result.StatusCode.ToExitCode(), $"get {ApiNotesSearch} failed"); } var notes = DoIt.TryOrDefault(() => JsonSerializer.Deserialize <List <Note> >(result.BodyAsString)); if (notes == default) { throw new CheckerException(ExitCode.MUMBLE, $"invalid {ApiNotesSearch} response"); } await Console.Error.WriteLineAsync($"found '{notes.Count}' notes by query '{query}'").ConfigureAwait(false); var note = notes.FirstOrDefault(note => note.Author.Contains(flag) || note.Title.Contains(flag) || note.Text.Contains(flag)); if (note == null) { throw new CheckerException(ExitCode.CORRUPT, "flag not found"); } //NOTE: Also check phrase query if (!query.StartsWith("?query=%22") || !query.EndsWith("%22")) { return; } var words = WebUtility.UrlDecode(encodedQuery).Trim('"', ' ').Split().Where(word => !string.IsNullOrWhiteSpace(word)).Distinct().ToArray(); if (words.Length < 2) { return; } query = string.Join(' ', words.Reverse()); if (note.Author.Contains(query, StringComparison.InvariantCultureIgnoreCase) || note.Title.Contains(query, StringComparison.InvariantCultureIgnoreCase) || note.Text.Contains(query, StringComparison.InvariantCultureIgnoreCase)) { return; } query = "?query=" + WebUtility.UrlEncode('"' + query + '"'); await Console.Error.WriteLineAsync($"check phrase query reversed '{query}'").ConfigureAwait(false); result = await client.DoRequestAsync(HttpMethod.Get, ApiNotesSearch + query, null, NetworkOpTimeout, MaxHttpBodySize).ConfigureAwait(false); if (result.StatusCode != HttpStatusCode.OK) { throw new CheckerException(result.StatusCode.ToExitCode(), $"get {ApiNotesSearch} failed"); } notes = DoIt.TryOrDefault(() => JsonSerializer.Deserialize <List <Note> >(result.BodyAsString)); if (notes == default) { throw new CheckerException(ExitCode.MUMBLE, $"invalid {ApiNotesSearch} response"); } await Console.Error.WriteLineAsync($"found '{notes.Count}' notes by query '{query}'").ConfigureAwait(false); if (notes.Any(note => note.Author.Contains(flag) || note.Title.Contains(flag) || note.Text.Contains(flag))) { throw new CheckerException(ExitCode.MUMBLE, $"invalid {ApiNotesSearch} response: phrase query"); } }
public async Task <string> Put(string host, string id, string flag, int vuln) { var client = new AsyncHttpClient(GetBaseUri(host), true); var login = RndText.RandomWord(RndUtil.GetInt(MinRandomFieldLength, MaxRandomFieldLength)).RandomLeet().RandomUpperCase(); var name = RndText.RandomWord(RndUtil.GetInt(MinRandomFieldLength, MaxRandomFieldLength)).RandomLeet().RandomUpperCase(); var pass = RndText.RandomWord(RndUtil.GetInt(MinRandomFieldLength, MaxRandomFieldLength)).RandomLeet().RandomUpperCase(); await Console.Error.WriteLineAsync($"login '{login}', name '{name}', pass '{pass}'").ConfigureAwait(false); var signUpQuery = $"?login={WebUtility.UrlEncode(login)}&name={WebUtility.UrlEncode(name)}&password={WebUtility.UrlEncode(pass)}"; var result = await client.DoRequestAsync(HttpMethod.Post, ApiAuthSignUp + signUpQuery, null, NetworkOpTimeout, MaxHttpBodySize).ConfigureAwait(false); if (result.StatusCode != HttpStatusCode.OK) { throw new CheckerException(result.StatusCode.ToExitCode(), $"get {ApiAuthSignUp} failed"); } await RndUtil.RndDelay(MaxDelay).ConfigureAwait(false); var items = Enumerable.Range(0, RndUtil.GetInt(1, 3)).Select(i => new Note { Title = RndText.RandomText(RndUtil.GetInt(MinRandomTitleLength, MaxRandomTitleLength)).RandomUmlauts(), Text = RndText.RandomText(RndUtil.GetInt(MinRandomTextLength, MaxRandomTextLength)).RandomUmlauts() }).ToArray(); var itemWithFlag = RndUtil.Choice(items); if (RndUtil.GetInt(0, 2) == 0) { itemWithFlag.Text = flag; } else { itemWithFlag.Title = flag; } itemWithFlag.IsPrivate = true; foreach (var item in items) { await Console.Error.WriteLineAsync($"title '{item.Title}', text '{item.Text}', isPrivate '{item.IsPrivate}'").ConfigureAwait(false); var q = $"?title={WebUtility.UrlEncode(item.Title)}&text={WebUtility.UrlEncode(item.Text)}" + (item.IsPrivate ? "&isPrivate=on" : null); result = await client.DoRequestAsync(HttpMethod.Post, ApiNotesAdd + q, null, NetworkOpTimeout).ConfigureAwait(false); if (result.StatusCode != HttpStatusCode.OK) { throw new CheckerException(result.StatusCode.ToExitCode(), $"post {ApiNotesAdd} failed"); } await RndUtil.RndDelay(MaxDelay).ConfigureAwait(false); } var query = GetRandomQuery(itemWithFlag); if (query.Trim('\"', ' ').Length <= 4) //NOTE: too low entropy { query = flag; } await Console.Error.WriteLineAsync($"random query '{query}'").ConfigureAwait(false); var cookie = client.Cookies.GetCookieHeader(GetBaseUri(host)); await Console.Error.WriteLineAsync($"cookie '{cookie}'").ConfigureAwait(false); var bytes = DoIt.TryOrDefault(() => Encoding.UTF8.GetBytes(cookie)); if (bytes == null || bytes.Length > 1024) { throw new CheckerException(result.StatusCode.ToExitCode(), "too large or invalid cookies"); } return($"{login}:{pass}:{Convert.ToBase64String(bytes)}:{WebUtility.UrlEncode(query)}"); }
public async Task <string> Put(string host, string id, string flag, int vuln) { var len = vuln == 1 ? RndUtil.Choice(11, 14) : RndUtil.Choice(12, 15); var name = RndText.RandomWord(len).RandomLeet().RandomUpperCase(); var b64Name = Convert.ToBase64String(Encoding.ASCII.GetBytes(name)); var b64Entropy = Convert.ToBase64String(Encoding.ASCII.GetBytes(flag)); await Console.Error.WriteLineAsync($"name '{name}', b64name '{b64Name}', entropy '{b64Entropy}'").ConfigureAwait(false); using (var bmp = RndBitmap.RndBmp(RndUtil.ThreadStaticRnd.Next(32) + 96, RndUtil.ThreadStaticRnd.Next(32) + 96)) using (var wsClient = await AsyncWebSocketClient.TryConnectAsync(GetBaseWsUri(host), MaxWsMsgSize, NetworkOpTimeout).ConfigureAwait(false)) { if (wsClient == null) { throw new CheckerException(ExitCode.DOWN, "ws connect failed"); } await Console.Error.WriteLineAsync("ws connected").ConfigureAwait(false); if (await wsClient.TryWaitMessageAsync(buffer => Tuple.Create(buffer.Count == 2 && buffer.Array[0] == (byte)'h' && buffer.Array[1] == (byte)'i', buffer), NetworkOpTimeout).ConfigureAwait(false) == default(ArraySegment <byte>)) { throw new CheckerException(ExitCode.MUMBLE, "await hello failed"); } await Console.Error.WriteLineAsync("ws hello received").ConfigureAwait(false); // ReSharper disable once AccessToDisposedClosure var wsTask = Task.Run(() => wsClient.TryWaitMessageAsync(buffer => { if (!ProtoBufHelper.TryDeserialize <Transmission>(buffer, out var transmission)) { throw new CheckerException(ExitCode.MUMBLE, "invalid ws data"); } return(Tuple.Create(transmission.Name == b64Name, transmission)); }, NetworkOpTimeout)); await RndUtil.RndDelay(MaxDelay).ConfigureAwait(false); var httpClient = new AsyncHttpClient(GetBaseHttpUri(host)); var result = await httpClient.DoRequestAsync(WebRequestMethods.Http.Put, PutRelative, new WebHeaderCollection { { "X-SG1-Name", b64Name }, { "X-SG1-Entropy", b64Entropy } }, bmp.ToByteArray(), NetworkOpTimeout, MaxHttpBodySize).ConfigureAwait(false); if (result.StatusCode != HttpStatusCode.OK) { throw new CheckerException(result.StatusCode.ToExitCode(), $"put {PutRelative} failed"); } var key = result.Headers?["X-SG1-Key"]; if (string.IsNullOrEmpty(key)) { throw new CheckerException(ExitCode.MUMBLE, $"invalid {PutRelative} response"); } if (!ProtoBufHelper.TryDeserialize(result.Body, out Spectrum spectrum)) { throw new CheckerException(ExitCode.MUMBLE, $"invalid {PutRelative} response"); } var expectedSpectrum = bmp.CalcSpectrum(); if (!spectrum.ComponentEquals(expectedSpectrum)) { throw new CheckerException(ExitCode.MUMBLE, $"invalid {PutRelative} response"); } await RndUtil.RndDelay(MaxDelay).ConfigureAwait(false); var msg = await wsTask.ConfigureAwait(false); if (msg == null || msg.Name != b64Name) { throw new CheckerException(ExitCode.MUMBLE, "await msg failed"); } var flagid = $"{b64Name}:{Convert.ToBase64String(Encoding.ASCII.GetBytes(key))}"; await Console.Out.WriteLineAsync(flagid).ConfigureAwait(false); return(flagid); } }