입력 검증 및 표현 문제는 메타 문자, 대체 인코딩 및 숫자 표현 때문에 발생합니다. 보안 문제는 입력을 신뢰하기 때문에 발생합니다. 문제로는 "Buffer Overflows", "Cross-Site Scripting" 공격, "SQL Injection", 그 외 여러 가지가 있습니다.
...
// "type" parameter expected to be either: "Email" or "Username"
string type = request["type"];
string value = request["value"];
string password = request["password"];
var ddb = new AmazonDynamoDBClient();
var attrValues = new Dictionary<string,AttributeValue>();
attrValues[":value"] = new AttributeValue(value);
attrValues[":password"] = new AttributeValue(password);
var scanRequest = new ScanRequest();
scanRequest.FilterExpression = type + " = :value AND Password = :password";
scanRequest.TableName = "users";
scanRequest.ExpressionAttributeValues = attrValues;
var scanResponse = await ddb.ScanAsync(scanRequest);
...
Email = :value AND Password = :password
Username = :value AND Password = :password
type
에 예상 값만 포함된 경우에만 정확하게 동작합니다. 공격자가 :value = :value OR :value
같은 입력 값을 제공하면 쿼리는 다음과 같습니다.:value = :value OR :value = :value AND Password = :password
:value = :value
조건을 추가하면 where 절이 항상 true로 평가되므로 쿼리는 전자 메일 소유자와 관계없이 users
컬렉션에 저장된 모든 항목을 반환합니다.
...
// "type" parameter expected to be either: "Email" or "Username"
String type = request.getParameter("type")
String value = request.getParameter("value")
String password = request.getParameter("password")
DynamoDbClient ddb = DynamoDbClient.create();
HashMap<String, AttributeValue> attrValues = new HashMap<String,AttributeValue>();
attrValues.put(":value", AttributeValue.builder().s(value).build());
attrValues.put(":password", AttributeValue.builder().s(password).build());
ScanRequest queryReq = ScanRequest.builder()
.filterExpression(type + " = :value AND Password = :password")
.tableName("users")
.expressionAttributeValues(attrValues)
.build();
ScanResponse response = ddb.scan(queryReq);
...
Email = :value AND Password = :password
Username = :value AND Password = :password
type
에 예상 값만 포함된 경우에만 정확하게 동작합니다. 공격자가 :value = :value OR :value
같은 입력 값을 제공하면 쿼리는 다음과 같습니다.:value = :value OR :value = :value AND Password = :password
:value = :value
조건을 추가하면 where 절이 항상 true로 평가되므로 쿼리는 전자 메일 소유자와 관계없이 users
컬렉션에 저장된 모든 항목을 반환합니다.
...
String userName = User.Identity.Name;
String emailId = request["emailId"];
var coll = mongoClient.GetDatabase("MyDB").GetCollection<BsonDocument>("emails");
var docs = coll.Find(new BsonDocument("$where", "this.name == '" + name + "'")).ToList();
...
this.owner == "<userName>" && this.emailId == "<emailId>"
emailId
에 작은따옴표가 들어 있지 않은 경우에만 정확하게 동작합니다. 사용자 이름이 wiley
인 공격자가 emailId
에 문자열 123' || '4' != '5
를 입력하면 쿼리는 다음과 같이 생성됩니다.
this.owner == 'wiley' && this.emailId == '123' || '4' != '5'
|| '4' != '5'
조건을 추가하면 where 절이 항상 true
로 평가되므로 쿼리는 전자 메일 소유자와 관계없이 emails
컬렉션에 저장된 모든 항목을 반환합니다.
...
String userName = ctx.getAuthenticatedUserName();
String emailId = request.getParameter("emailId")
MongoCollection<Document> col = mongoClient.getDatabase("MyDB").getCollection("emails");
BasicDBObject Query = new BasicDBObject();
Query.put("$where", "this.owner == \"" + userName + "\" && this.emailId == \"" + emailId + "\"");
FindIterable<Document> find= col.find(Query);
...
this.owner == "<userName>" && this.emailId == "<emailId>"
emailId
에 큰따옴표가 들어 있지 않은 경우에만 정확하게 동작합니다. 사용자 이름이 wiley
인 공격자가 emailId
에 문자열 123" || "4" != "5
를 입력하면 쿼리는 다음과 같이 생성됩니다.
this.owner == "wiley" && this.emailId == "123" || "4" != "5"
|| "4" != "5"
조건을 추가하면 where 절이 항상 true로 평가되므로 쿼리는 전자 메일 소유자와 관계없이 emails
컬렉션에 저장된 모든 항목을 반환합니다.
...
userName = req.field('userName')
emailId = req.field('emaiId')
results = db.emails.find({"$where", "this.owner == \"" + userName + "\" && this.emailId == \"" + emailId + "\""});
...
this.owner == "<userName>" && this.emailId == "<emailId>"
emailId
에 큰따옴표가 들어 있지 않은 경우에만 정확하게 동작합니다. 사용자 이름이 wiley
인 공격자가 emailId
에 문자열 123" || "4" != "5
를 입력하면 쿼리는 다음과 같이 생성됩니다.
this.owner == "wiley" && this.emailId == "123" || "4" != "5"
|| "4" != "5"
조건을 추가하면 where
절이 항상 true로 평가되므로 쿼리는 전자 메일 소유자와 관계없이 emails
컬렉션에 저장된 모든 항목을 반환합니다.
...
NSString *emailId = [self getEmailIdFromUser];
NSString *query = [NSString stringWithFormat:@"id == '%@'", emailId];
RLMResults<Email *> *emails = [Email objectsInRealm:realm where:query];
...
id == '<emailId value>'
emailId
에 작은따옴표가 들어 있지 않은 경우에만 정확하게 동작합니다. 공격자가 123' or '4' != '5
에 emailId
문자열을 입력하면 쿼리는 다음과 같습니다.
id == '123' or '4' != '5'
or '4' != '5'
조건을 추가하면 where
절이 항상 true로 평가되기 때문에, 쿼리는 전자 메일 소유자와 관계없이 emails
컬렉션에 저장된 모든 항목을 반환합니다.
...
let emailId = getFromUser("emailId")
let email = realm.objects(Email.self).filter("id == '" + emailId + "'")
...
id == '<emailId value>'
emailId
에 작은따옴표가 들어 있지 않은 경우에만 정확하게 동작합니다. 공격자가 123' or '4' != '5
에 emailId
문자열을 입력하면 쿼리는 다음과 같습니다.
id == '123' or '4' != '5'
or '4' != '5'
조건을 추가하면 filter
절이 항상 true로 평가되기 때문에, 쿼리는 전자 메일 소유자와 관계없이 emails
컬렉션에 저장된 모든 항목을 반환합니다.unserialize()
함수로 전달되기 전에 신뢰할 수 없는 데이터가 올바르게 정화되지 않는 경우 발생합니다. 공격자는 취약한 unserialize()
호출에 특히 수동으로 직렬화한 문자열을 전달할 수 있어 응용 프로그램 영역에서 임의 PHP object injection을 야기합니다. 이 취약점의 심각도는 응용 프로그램 영역에서 사용 가능한 클래스에 따라 달라집니다. __wakeup
또는 __destruct
같은 PHP 매직 메서드를 구현하는 클래스는 이러한 메서드 내에서 코드를 수행할 수 있으므로 공격자가 관심을 갖기 쉽습니다.__destruct()
매직 메서드를 구현하고 클래스 속성으로 정의된 시스템 명령을 실행하는 PHP 클래스를 보여줍니다. 또한 사용자 공급 데이터가 포함된 unserialize()
에 대한 불안정한 호출도 있습니다.
...
class SomeAvailableClass {
public $command=null;
public function __destruct() {
system($this->command);
}
}
...
$user = unserialize($_GET['user']);
...
Example 1
에서 응용 프로그램은 직렬화된 User
개체를 예상하지만 공격자는 command
속성을 위해 사전 정의된 값으로 SomeAvailableClass
의 직렬화된 버전을 실제로 제공할 수 있습니다.
GET REQUEST: http://server/page.php?user=O:18:"SomeAvailableClass":1:{s:7:"command";s:8:"uname -a";}
$user
개체에 대한 다른 참조가 없을 때 즉시 호출되며 공격자가 제공한 명령을 실행합니다.unserialize()
가 "속성 지향 프로그래밍"이라는 기술을 사용하여 호출된 경우 선언된 다른 클래스를 연결할 수 있습니다. "속성 지향 프로그래밍"은 BlackHat 2010 컨퍼런스에서 Stefan Esser가 소개한 기술입니다. 이 기술을 통해 공격자는 고유한 페이로드를 만들도록 기존의 코드를 재사용할 수 있습니다.YAML.load()
같은 데이터를 역직렬화하는 함수로 전달되기 전에 신뢰할 수 없는 데이터가 올바르게 정화되지 않는 경우에 발생합니다. 공격자가 특수하게 만들어진 직렬화된 문자열을 취약한 YAML.load()
호출에 전달하면 역직렬화 시 클래스가 응용 프로그램으로 로드되는 경우 임의의 Ruby 개체가 프로그램에 주입됩니다. 이렇게 되면 cross-site scripting 취약점을 찾기 위한 검증 로직을 우회하는 등의 다양한 공격 기회에 무방비 상태로 노출될 수 있으며, 하드코드된 값처럼 보이는 값을 통한 SQL Injection 공격이나 심지어 전체 코드 실행까지 발생할 수 있습니다.YAML.load()
에 대한 불안정한 호출도 있습니다.
...
class Transaction
attr_accessor :id
def initialize(num=nil)
@id = num.is_a?(Numeric) ? num : nil
end
def print_details
unless @id.nil?
print $conn.query("SELECT * FROM transactions WHERE id=#{@id}")
end
end
end
...
user = YAML.load(params[:user]);
user.print_details
...
Example 1
에서 응용 프로그램은 print_details
라는 함수가 포함되기도 하는 직렬화된 User
개체가 필요할 수 있지만 공격자는 실제로 해당 @id
속성 값이 미리 정의된 직렬화된 버전의 Transaction
개체를 제공할 수 있습니다. 따라서 다음과 같은 요청은 @id
가 숫자 값인지 여부를 확인하려는 검증 검사를 우회하도록 허용할 수 있습니다.
GET REQUEST: http://server/page?user=!ruby%2Fobject%3ATransaction%0Aid%3A4%20or%205%3D5%0A
user
매개 변수에 !ruby/object:Transaction\nid:4 or 5=5\n
가 할당되어 있음을 알 수 있습니다.@id
가 "4 or 5=5"
로 설정된 Transaction
유형의 개체가 생성됩니다. 개발자는 User#print_details()
를 호출하려고 하지만 이제 Transaction#print_details()
를 호출하게 되며, Ruby의 문자열 보간은 SELECT * FROM transactions WHERE id=4 or 5=5
쿼리를 실행하도록 SQL 쿼리가 변경된다는 것을 의미하게 됩니다. 별도의 절이 추가되었기 때문에 쿼리는 true
로 평가되며 transactions
테이블 내에서 개발자가 의도했던 단일 행 대신 모든 행을 반환하게 됩니다.YAML.load()
가 "속성 지향 프로그래밍"이라는 기술을 사용하여 호출된 경우 선언된 다른 클래스를 연결할 수 있습니다. "속성 지향 프로그래밍"은 BlackHat 2010 컨퍼런스에서 Stefan Esser가 소개한 기술입니다. 이 기술을 통해 공격자는 고유한 페이로드를 만들도록 기존의 코드를 재사용할 수 있습니다.Value Stack
컨텍스트의 EL 식을 평가할 수 있도록 합니다. 확인되지 않은 식을 Value Stack
과 비교하여 평가할 수 있게 하면 공격자가 액세스하여 시스템 변수를 수정하거나 임의의 코드를 실행할 수 있게 됩니다.
OgnlContext ctx = new OgnlContext();
String expression = request.getParameter("input");
Object expr = Ognl.parseExpression(expression);
Object value = Ognl.getValue(expr, ctx, root);
System.out.println("Value: " + value);
(#rt = @java.lang.Runtime@getRuntime(),#rt.exec("calc.exe"))
%{expr}
)을 사용합니다. 첫 번째 평가의 결과를 제어하는 공격자는 두 번째 OGNL 평가에서 평가될 식을 제어하고 임의의 OGNL 식을 삽입할 수 있습니다.redirectAction
결과는 매개 변수를 두 번 평가하는 것으로 알려져 있습니다. 이 경우 actionName
매개 변수의 강제 OGNL 식의 결과가 redirect
요청 매개 변수를 제공하여 공격자에 의해 제어될 수 있습니다.
...
<action name="index" class="com.acme.MyAction">
<result type="redirectAction">
<param name="actionName">${#parameters['redirect']}</param>
<param name="namespace">/foo</param>
</result>
</action>
...
%{#parameters['redirect']}
식을 평가하여 OGNL 식으로 평가될 사용자 제어 문자열을 반환하여 공격자가 임의의 OGNL 식을 평가할 수 있도록 합니다.execute()
외의 메서드가 노출될 수 있습니다. "동적 메서드 호출"이 활성화된 경우 !
(느낌표) 문자 또는 method:
접두사를 Action URL에 사용하여 Action의 모든 공개 메서드를 호출할 수 있습니다. Struts 2 버전 2.3.20
에서는 이전에 리플렉션을 기반으로 한 대체 메서드 호출 메커니즘이 OGNL을 대신 사용하도록 바뀌었는데 공격자는 이를 통해 대체 메서드 이름 대신 악성 OGNL 식을 제공할 수 있습니다.