Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Protect readLine() against DoS #9

Closed
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@

package org.elasticsearch.gradle.internal.conventions.info;

import io.github.pixee.security.BoundedLineReader;
import org.gradle.api.Action;
import org.gradle.api.logging.Logger;
import org.gradle.api.logging.Logging;
Expand Down Expand Up @@ -45,7 +46,7 @@ public static int findDefaultParallel(Project project) {
String currentID = "";

try (BufferedReader reader = new BufferedReader(new FileReader(cpuInfoFile))) {
for (String line = reader.readLine(); line != null; line = reader.readLine()) {
for (String line = BoundedLineReader.readLine(reader, 5_000_000); line != null; line = BoundedLineReader.readLine(reader, 5_000_000)) {
if (line.contains(":")) {
List<String> parts = Arrays.stream(line.split(":", 2)).map(String::trim).collect(Collectors.toList());
String name = parts.get(0);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
*/
package org.elasticsearch.gradle.internal.info;

import io.github.pixee.security.BoundedLineReader;
import org.apache.commons.io.IOUtils;
import org.elasticsearch.gradle.internal.BwcVersions;
import org.elasticsearch.gradle.internal.conventions.info.GitInfo;
Expand Down Expand Up @@ -360,7 +361,7 @@ public static String getResourceContents(String resourcePath) {
BufferedReader reader = new BufferedReader(new InputStreamReader(GlobalBuildInfoPlugin.class.getResourceAsStream(resourcePath)))
) {
StringBuilder b = new StringBuilder();
for (String line = reader.readLine(); line != null; line = reader.readLine()) {
for (String line = BoundedLineReader.readLine(reader, 5_000_000); line != null; line = BoundedLineReader.readLine(reader, 5_000_000)) {
if (b.length() != 0) {
b.append('\n');
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
*/
package org.elasticsearch.gradle.testclusters;

import io.github.pixee.security.BoundedLineReader;
import org.gradle.api.GradleException;
import org.gradle.api.logging.Logger;
import org.gradle.api.logging.Logging;
Expand Down Expand Up @@ -245,7 +246,7 @@ public void runAndWait() throws IOException {
for (BufferedReader bufferedReader : toRead) {
if (bufferedReader.ready()) {
readData = true;
logger.lifecycle(bufferedReader.readLine());
logger.lifecycle(BoundedLineReader.readLine(bufferedReader, 5_000_000));
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
*/
package org.elasticsearch.client.benchmark.ops.bulk;

import io.github.pixee.security.BoundedLineReader;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.elasticsearch.ElasticsearchException;
Expand Down Expand Up @@ -101,7 +102,7 @@ public void execute() {
String line;
int bulkIndex = 0;
List<String> bulkData = new ArrayList<>(bulkSize);
while ((line = reader.readLine()) != null) {
while ((line = BoundedLineReader.readLine(reader, 5_000_000)) != null) {
if (bulkIndex == bulkSize) {
sendBulk(bulkData);
// reset data structures
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@

package org.elasticsearch.client;

import io.github.pixee.security.BoundedLineReader;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.http.Header;
Expand Down Expand Up @@ -170,7 +171,7 @@ static String buildTraceResponse(HttpResponse httpResponse) throws IOException {
}
try (BufferedReader reader = new BufferedReader(new InputStreamReader(entity.getContent(), charset))) {
String line;
while ((line = reader.readLine()) != null) {
while ((line = BoundedLineReader.readLine(reader, 5_000_000)) != null) {
responseLine.append("\n# ").append(line);
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@

package org.elasticsearch.plugins.cli;

import io.github.pixee.security.BoundedLineReader;
import org.apache.lucene.search.spell.LevenshteinDistance;
import org.apache.lucene.util.CollectionUtil;
import org.apache.lucene.util.Constants;
Expand Down Expand Up @@ -579,9 +580,9 @@ private Path downloadAndValidate(final String urlString, final Path tmpDir, fina
*/
final BufferedReader checksumReader = new BufferedReader(new InputStreamReader(in, StandardCharsets.UTF_8));
if (digestAlgo.equals("SHA-1")) {
expectedChecksum = checksumReader.readLine();
expectedChecksum = BoundedLineReader.readLine(checksumReader, 5_000_000);
} else {
final String checksumLine = checksumReader.readLine();
final String checksumLine = BoundedLineReader.readLine(checksumReader, 5_000_000);
final String[] fields = checksumLine.split(" {2}");
if (officialPlugin && fields.length != 2 || officialPlugin == false && fields.length > 2) {
throw new UserException(ExitCodes.IO_ERROR, "Invalid checksum file at " + checksumUrl);
Expand All @@ -603,7 +604,7 @@ private Path downloadAndValidate(final String urlString, final Path tmpDir, fina
}
}
}
if (checksumReader.readLine() != null) {
if (BoundedLineReader.readLine(checksumReader, 5_000_000) != null) {
throw new UserException(ExitCodes.IO_ERROR, "Invalid checksum file at " + checksumUrl);
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@

package org.elasticsearch.server.cli;

import io.github.pixee.security.BoundedLineReader;
import org.elasticsearch.bootstrap.BootstrapInfo;

import java.io.BufferedReader;
Expand Down Expand Up @@ -76,7 +77,7 @@ void drain() {
public void run() {
try {
String line;
while ((line = reader.readLine()) != null) {
while ((line = BoundedLineReader.readLine(reader, 5_000_000)) != null) {
if (line.isEmpty() == false && line.charAt(0) == SERVER_READY_MARKER) {
ready = true;
readyOrDead.countDown();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@

package org.elasticsearch.server.cli;

import io.github.pixee.security.BoundedLineReader;
import org.elasticsearch.bootstrap.ServerArgs;
import org.elasticsearch.cli.ExitCodes;
import org.elasticsearch.cli.UserException;
Expand Down Expand Up @@ -289,7 +290,7 @@ static void parse(
) throws IOException {
int lineNumber = 0;
while (true) {
final String line = br.readLine();
final String line = BoundedLineReader.readLine(br, 5_000_000);
lineNumber++;
if (line == null) {
break;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@

package org.elasticsearch.grok;

import io.github.pixee.security.BoundedLineReader;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
Expand Down Expand Up @@ -138,7 +139,7 @@ private static PatternBank loadPatternsFromDirectory(List<String> patternNames,
private static void loadPatternsFromFile(Map<String, String> patternBank, InputStream inputStream) throws IOException {
String line;
BufferedReader br = new BufferedReader(new InputStreamReader(inputStream, StandardCharsets.UTF_8));
while ((line = br.readLine()) != null) {
while ((line = BoundedLineReader.readLine(br, 5_000_000)) != null) {
String trimmedLine = line.replaceAll("^\\s+", "");
if (trimmedLine.startsWith("#") || trimmedLine.length() == 0) {
continue;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@

package org.elasticsearch.common.ssl;

import io.github.pixee.security.BoundedLineReader;
import org.elasticsearch.core.CharArrays;

import java.io.BufferedReader;
Expand Down Expand Up @@ -128,9 +129,9 @@ public static PrivateKey readPrivateKey(Path path, Supplier<char[]> passwordSupp
*/
static PrivateKey parsePrivateKey(Path keyPath, Supplier<char[]> passwordSupplier) throws IOException, GeneralSecurityException {
try (BufferedReader bReader = Files.newBufferedReader(keyPath, StandardCharsets.UTF_8)) {
String line = bReader.readLine();
String line = BoundedLineReader.readLine(bReader, 5_000_000);
while (null != line && line.startsWith(HEADER) == false) {
line = bReader.readLine();
line = BoundedLineReader.readLine(bReader, 5_000_000);
}
if (null == line) {
throw new SslConfigException("Error parsing Private Key [" + keyPath.toAbsolutePath() + "], file is empty");
Expand Down Expand Up @@ -170,18 +171,18 @@ static PrivateKey parsePrivateKey(Path keyPath, Supplier<char[]> passwordSupplie
* @throws IOException if the EC Parameter footer is missing
*/
private static BufferedReader removeECHeaders(BufferedReader bReader) throws IOException {
String line = bReader.readLine();
String line = BoundedLineReader.readLine(bReader, 5_000_000);
while (line != null) {
if (OPENSSL_EC_PARAMS_FOOTER.equals(line.trim())) {
break;
}
line = bReader.readLine();
line = BoundedLineReader.readLine(bReader, 5_000_000);
}
if (null == line || OPENSSL_EC_PARAMS_FOOTER.equals(line.trim()) == false) {
throw new IOException("Malformed PEM file, EC Parameters footer is missing");
}
// Verify that the key starts with the correct header before passing it to parseOpenSslEC
if (OPENSSL_EC_HEADER.equals(bReader.readLine()) == false) {
if (OPENSSL_EC_HEADER.equals(BoundedLineReader.readLine(bReader, 5_000_000)) == false) {
throw new IOException("Malformed PEM file, EC Key header is missing");
}
return bReader;
Expand All @@ -194,18 +195,18 @@ private static BufferedReader removeECHeaders(BufferedReader bReader) throws IOE
* @throws IOException if the EC Parameter footer is missing
*/
private static BufferedReader removeDsaHeaders(BufferedReader bReader) throws IOException {
String line = bReader.readLine();
String line = BoundedLineReader.readLine(bReader, 5_000_000);
while (line != null) {
if (OPENSSL_DSA_PARAMS_FOOTER.equals(line.trim())) {
break;
}
line = bReader.readLine();
line = BoundedLineReader.readLine(bReader, 5_000_000);
}
if (null == line || OPENSSL_DSA_PARAMS_FOOTER.equals(line.trim()) == false) {
throw new IOException("Malformed PEM file, DSA Parameters footer is missing");
}
// Verify that the key starts with the correct header before passing it to parseOpenSslDsa
if (OPENSSL_DSA_HEADER.equals(bReader.readLine()) == false) {
if (OPENSSL_DSA_HEADER.equals(BoundedLineReader.readLine(bReader, 5_000_000)) == false) {
throw new IOException("Malformed PEM file, DSA Key header is missing");
}
return bReader;
Expand All @@ -222,13 +223,13 @@ private static BufferedReader removeDsaHeaders(BufferedReader bReader) throws IO
*/
private static PrivateKey parsePKCS8(BufferedReader bReader) throws IOException, GeneralSecurityException {
StringBuilder sb = new StringBuilder();
String line = bReader.readLine();
String line = BoundedLineReader.readLine(bReader, 5_000_000);
while (line != null) {
if (PKCS8_FOOTER.equals(line.trim())) {
break;
}
sb.append(line.trim());
line = bReader.readLine();
line = BoundedLineReader.readLine(bReader, 5_000_000);
}
if (null == line || PKCS8_FOOTER.equals(line.trim()) == false) {
throw new IOException("Malformed PEM file, PEM footer is invalid or missing");
Expand Down Expand Up @@ -263,7 +264,7 @@ public static PrivateKey parsePKCS8PemString(String pemString) throws IOExceptio
private static PrivateKey parseOpenSslEC(BufferedReader bReader, Supplier<char[]> passwordSupplier) throws IOException,
GeneralSecurityException {
StringBuilder sb = new StringBuilder();
String line = bReader.readLine();
String line = BoundedLineReader.readLine(bReader, 5_000_000);
Map<String, String> pemHeaders = new HashMap<>();
while (line != null) {
if (OPENSSL_EC_FOOTER.equals(line.trim())) {
Expand All @@ -276,7 +277,7 @@ private static PrivateKey parseOpenSslEC(BufferedReader bReader, Supplier<char[]
} else {
sb.append(line.trim());
}
line = bReader.readLine();
line = BoundedLineReader.readLine(bReader, 5_000_000);
}
if (null == line || OPENSSL_EC_FOOTER.equals(line.trim()) == false) {
throw new IOException("Malformed PEM file, PEM footer is invalid or missing");
Expand All @@ -300,7 +301,7 @@ private static PrivateKey parseOpenSslEC(BufferedReader bReader, Supplier<char[]
private static PrivateKey parsePKCS1Rsa(BufferedReader bReader, Supplier<char[]> passwordSupplier) throws IOException,
GeneralSecurityException {
StringBuilder sb = new StringBuilder();
String line = bReader.readLine();
String line = BoundedLineReader.readLine(bReader, 5_000_000);
Map<String, String> pemHeaders = new HashMap<>();

while (line != null) {
Expand All @@ -315,7 +316,7 @@ private static PrivateKey parsePKCS1Rsa(BufferedReader bReader, Supplier<char[]>
} else {
sb.append(line.trim());
}
line = bReader.readLine();
line = BoundedLineReader.readLine(bReader, 5_000_000);
}
if (null == line || PKCS1_FOOTER.equals(line.trim()) == false) {
throw new IOException("Malformed PEM file, PEM footer is invalid or missing");
Expand All @@ -339,7 +340,7 @@ private static PrivateKey parsePKCS1Rsa(BufferedReader bReader, Supplier<char[]>
private static PrivateKey parseOpenSslDsa(BufferedReader bReader, Supplier<char[]> passwordSupplier) throws IOException,
GeneralSecurityException {
StringBuilder sb = new StringBuilder();
String line = bReader.readLine();
String line = BoundedLineReader.readLine(bReader, 5_000_000);
Map<String, String> pemHeaders = new HashMap<>();

while (line != null) {
Expand All @@ -354,7 +355,7 @@ private static PrivateKey parseOpenSslDsa(BufferedReader bReader, Supplier<char[
} else {
sb.append(line.trim());
}
line = bReader.readLine();
line = BoundedLineReader.readLine(bReader, 5_000_000);
}
if (null == line || OPENSSL_DSA_FOOTER.equals(line.trim()) == false) {
throw new IOException("Malformed PEM file, PEM footer is invalid or missing");
Expand All @@ -377,13 +378,13 @@ private static PrivateKey parseOpenSslDsa(BufferedReader bReader, Supplier<char[
*/
private static PrivateKey parsePKCS8Encrypted(BufferedReader bReader, char[] keyPassword) throws IOException, GeneralSecurityException {
StringBuilder sb = new StringBuilder();
String line = bReader.readLine();
String line = BoundedLineReader.readLine(bReader, 5_000_000);
while (line != null) {
if (PKCS8_ENCRYPTED_FOOTER.equals(line.trim())) {
break;
}
sb.append(line.trim());
line = bReader.readLine();
line = BoundedLineReader.readLine(bReader, 5_000_000);
}
if (null == line || PKCS8_ENCRYPTED_FOOTER.equals(line.trim()) == false) {
throw new IOException("Malformed PEM file, PEM footer is invalid or missing");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
import com.google.cloud.storage.Storage;
import com.google.cloud.storage.StorageOptions;
import com.google.cloud.storage.StorageRetryStrategy;
import io.github.pixee.security.BoundedLineReader;

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
Expand Down Expand Up @@ -252,7 +253,7 @@ static String getDefaultProjectId(@Nullable Proxy proxy) throws IOException {
try (InputStream input = connection.getInputStream()) {
if (connection.getResponseCode() == 200) {
try (BufferedReader reader = new BufferedReader(new InputStreamReader(input, UTF_8))) {
return reader.readLine();
return BoundedLineReader.readLine(reader, 5_000_000);
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@

package org.elasticsearch.discovery.ec2;

import io.github.pixee.security.BoundedLineReader;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.elasticsearch.common.Strings;
Expand Down Expand Up @@ -49,7 +50,7 @@ static Optional<String> getMetadataToken(String metadataTokenUrl) {
var in = urlConnection.getInputStream();
var reader = new BufferedReader(new InputStreamReader(in, StandardCharsets.UTF_8))
) {
return Optional.ofNullable(reader.readLine()).filter(s -> s.isBlank() == false);
return Optional.ofNullable(BoundedLineReader.readLine(reader, 5_000_000)).filter(s -> s.isBlank() == false);
} catch (IOException e) {
logger.warn("Unable to get a session token from IMDSv2 URI: " + metadataTokenUrl, e);
return Optional.empty();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@

import com.amazonaws.util.EC2MetadataUtils;
import com.amazonaws.util.json.Jackson;
import io.github.pixee.security.BoundedLineReader;

import org.elasticsearch.SpecialPermission;
import org.elasticsearch.common.network.NetworkService;
Expand Down Expand Up @@ -158,7 +159,7 @@ static Settings getAvailabilityZoneNodeAttributes(Settings settings, String azMe
BufferedReader urlReader = new BufferedReader(new InputStreamReader(in, StandardCharsets.UTF_8))
) {

final String metadataResult = urlReader.readLine();
final String metadataResult = BoundedLineReader.readLine(urlReader, 5_000_000);
if ((metadataResult == null) || (metadataResult.length() == 0)) {
throw new IllegalStateException("no ec2 metadata returned from " + url);
} else {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
package org.elasticsearch.discovery.ec2;

import com.amazonaws.util.EC2MetadataUtils;
import io.github.pixee.security.BoundedLineReader;

import org.elasticsearch.common.network.NetworkService.CustomNameResolver;
import org.elasticsearch.core.IOUtils;
Expand Down Expand Up @@ -95,7 +96,7 @@ public static InetAddress[] resolve(Ec2HostnameType type) throws IOException {
in = SocketAccess.doPrivilegedIOException(urlConnection::getInputStream);
BufferedReader urlReader = new BufferedReader(new InputStreamReader(in, StandardCharsets.UTF_8));

String metadataResult = urlReader.readLine();
String metadataResult = BoundedLineReader.readLine(urlReader, 5_000_000);
if (metadataResult == null || metadataResult.length() == 0) {
throw new IOException("no gce metadata returned from [" + url + "] for [" + type.configName + "]");
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@

package org.elasticsearch.action.admin.cluster.node.hotthreads;

import io.github.pixee.security.BoundedLineReader;
import org.elasticsearch.action.FailedNodeException;
import org.elasticsearch.action.support.TransportAction;
import org.elasticsearch.action.support.nodes.BaseNodesResponse;
Expand Down Expand Up @@ -63,7 +64,7 @@ private LinesIterator(String input) {

private void advance() {
try {
nextLine = reader.readLine();
nextLine = BoundedLineReader.readLine(reader, 5_000_000);
} catch (IOException e) {
assert false : e; // no actual IO happens here
}
Expand Down
Loading
Loading