String canned_acl = request.getParameter("acl");
CreateBucketRequest createBucketRequest = CreateBucketRequest.builder()
.bucket("foo")
.acl(canned_acl)
.createBucketConfiguration(CreateBucketConfiguration.builder().locationConstraint(region.id()).build())
.build();
acl
매개 변수를 선택한다고 해도 공격자는 이를 public-read-write
로 설정하고 버킷에 대한 전체 익명 액세스 권한을 부여할 수 있습니다.
...
String selectedInvoice = request.getParameter("invoiceDate");
...
AmazonSimpleDBClient sdbc = new AmazonSimpleDBClient(appAWSCredentials);
GetAttributesResult sdbResult = sdbc.getAttributes(new GetAttributesRequest("invoices", selectedInvoice));
...
Example 1
의 코드는 현재 사용자의 송장 목록을 생성하지만 공격자는 이 동작을 무시하고 원하는 송장을 요청할 수 있습니다. 이 예제의 코드가 사용자가 요청한 송장에 접근할 수 있는 권한이 있는지 확인하지 않기 때문에 현재 사용자의 송장이 아닌 송장도 모두 표시합니다.
...
id = this.getIntent().getExtras().getInt("id");
cursor = db.query(Uri.parse(invoices), columns, "id = ? ", {id}, null, null, null);
...
id
의 가능한 모든 값을 고려할 수 없다는 점입니다. 쿼리에서 현재 사용자의 송장 ID 목록을 생성하지만 공격자는 이 동작을 무시하고 원하는 송장을 요청할 수 있습니다. 이 예제의 코드가 사용자가 요청한 송장에 접근할 수 있는 권한이 있는지 확인하지 않기 때문에 현재 사용자의 송장이 아닌 송장도 모두 표시합니다.DirectoryEntry de
를 생성합니다.
...
de = new DirectoryEntry("LDAP://ad.example.com:389/ou=People,dc=example,dc=com");
...
de
에 대해 실행된 모든 LDAP 쿼리는 authentication 및 access control 없이 수행됩니다. 공격자는 디렉터리의 액세스 제어 메커니즘으로 보호되는 레코드에 대한 액세스를 얻기 위해 예기치 못한 방법으로 이러한 쿼리 중 하나를 조작할 수도 있습니다.ldap_simple_bind_s()
를 사용하여 LDAP 디렉터리에 익명으로 바인딩합니다.
...
rc = ldap_simple_bind_s( ld, NULL, NULL );
if ( rc != LDAP_SUCCESS ) {
...
}
...
ld
에 대해 실행된 모든 LDAP 쿼리는 authentication 및 access control 없이 수행됩니다. 공격자는 디렉터리의 액세스 제어 메커니즘으로 보호되는 레코드에 대한 액세스를 얻기 위해 예기치 못한 방법으로 이러한 쿼리 중 하나를 조작할 수도 있습니다.DirContext ctx
를 생성합니다.
...
env.put(Context.SECURITY_AUTHENTICATION, "none");
DirContext ctx = new InitialDirContext(env);
...
ctx
에 대해 실행된 모든 LDAP 쿼리는 authentication 및 access control 없이 수행됩니다. 공격자는 디렉터리의 액세스 제어 메커니즘으로 보호되는 레코드에 대한 액세스를 얻기 위해 예기치 못한 방법으로 이러한 쿼리 중 하나를 조작할 수도 있습니다.
...
$ldapbind = ldap_bind ($ldap, $dn, $password = "" );
...
public boolean isTrusted(String paramString) {
if (this._applicationContext.getPackageName().equalsIgnoreCase(paramString)) {
return true;
}
DATA: id TYPE i.
...
id = request->get_form_field( 'invoiceID' ).
CONCATENATE `INVOICEID = '` id `'` INTO cl_where.
SELECT *
FROM invoices
INTO CORRESPONDING FIELDS OF TABLE itab_invoices
WHERE (cl_where).
ENDSELECT.
...
ID
의 가능한 모든 값을 고려할 수 없다는 점입니다. 인터페이스에서 현재 사용자의 송장 ID 목록을 생성하더라도 공격자는 이 인터페이스를 무시하고 원하는 송장을 요청할 수 있습니다. 이 예제의 코드가 사용자가 요청한 송장에 접근할 수 있는 권한이 있는지 확인하지 않기 때문에 현재 사용자의 송장이 아닌 송장도 모두 표시합니다.
...
var params:Object = LoaderInfo(this.root.loaderInfo).parameters;
var id:int = int(Number(params["invoiceID"]));
var query:String = "SELECT * FROM invoices WHERE id = :id";
stmt.sqlConnection = conn;
stmt.text = query;
stmt.parameters[":id"] = id;
stmt.execute();
...
id
의 가능한 모든 값을 고려할 수 없다는 점입니다. 인터페이스에서 현재 사용자의 송장 ID 목록을 생성하더라도 공격자는 이 인터페이스를 무시하고 원하는 송장을 요청할 수 있습니다. 이 예제의 코드가 사용자가 요청한 송장에 접근할 수 있는 권한이 있는지 확인하지 않기 때문에 현재 사용자의 송장이 아닌 송장도 모두 표시합니다.inputID
값은 사전 정의된 목록에서 제공되며, 바인딩 변수는 SOQL/SOSL injection을 방지하는 데 도움이 됩니다.
...
result = [SELECT Name, Phone FROM Contact WHERE (IsDeleted = false AND Id=:inputID)];
...
inputID
의 값을 수정하지 못하도록 방지하기에는 불충분하다는 점입니다. 공격자가 인터페이스를 우회하고 다른 값으로 요청을 전송할 수 있는 경우 공격자는 다른 연락처 정보에 액세스할 수 있습니다. 이 예제의 코드는 사용자가 요청된 연락처에 액세스할 수 있는 권한이 있는지 확인하지 않으므로, 사용자가 볼 권한이 없는 경우에도 모든 연락처를 표시합니다.
...
int16 id = System.Convert.ToInt16(invoiceID.Text);
var invoice = OrderSystem.getInvoices()
.Where(new Invoice { invoiceID = id });
...
id
의 가능한 모든 값을 고려할 수 없다는 점입니다. 인터페이스에서 현재 사용자의 송장 ID 목록을 생성하더라도 공격자는 이 인터페이스를 무시하고 원하는 송장을 요청할 수 있습니다. 이 예제의 코드가 사용자가 요청한 송장에 접근할 수 있는 권한이 있는지 확인하지 않기 때문에 현재 사용자의 송장이 아닌 송장도 모두 표시합니다.
...
CMyRecordset rs(&dbms);
rs.PrepareSQL("SELECT * FROM invoices WHERE id = ?");
rs.SetParam_int(0,atoi(r.Lookup("invoiceID").c_str()));
rs.SafeExecuteSQL();
...
id
의 가능한 모든 값을 고려할 수 없다는 점입니다. 인터페이스에서 현재 사용자의 송장 ID 목록을 생성하더라도 공격자는 이 인터페이스를 무시하고 원하는 송장을 요청할 수 있습니다. 이 예제의 코드가 사용자가 요청한 송장에 접근할 수 있는 권한이 있는지 확인하지 않기 때문에 현재 사용자의 송장이 아닌 송장도 모두 표시합니다.
...
ACCEPT ID.
EXEC SQL
DECLARE C1 CURSOR FOR
SELECT INVNO, INVDATE, INVTOTAL
FROM INVOICES
WHERE INVOICEID = :ID
END-EXEC.
...
ID
의 가능한 모든 값을 고려할 수 없다는 점입니다. 인터페이스에서 현재 사용자의 송장 ID 목록을 생성하더라도 공격자는 이 인터페이스를 무시하고 원하는 송장을 요청할 수 있습니다. 이 예제의 코드가 사용자가 요청한 송장에 접근할 수 있는 권한이 있는지 확인하지 않기 때문에 현재 사용자의 송장이 아닌 송장도 모두 표시합니다.deleteDatabase
메서드를 실행하면 공격자가 모든 데이터베이스를 삭제할 수 있게 됩니다.
...
id := request.FormValue("invoiceID")
query := "SELECT * FROM invoices WHERE id = ?";
rows, err := db.Query(query, id)
...
id
의 가능한 모든 값을 고려할 수 없다는 점입니다. 인터페이스에서 현재 사용자의 송장 ID 목록을 생성하더라도 공격자는 이 인터페이스를 무시하고 원하는 송장을 요청할 수 있습니다. 이 예제의 코드가 사용자가 요청한 송장에 접근할 수 있는 권한이 있는지 확인하지 않기 때문에 현재 사용자의 송장이 아닌 송장도 모두 표시합니다.
...
id = Integer.decode(request.getParameter("invoiceID"));
String query = "SELECT * FROM invoices WHERE id = ?";
PreparedStatement stmt = conn.prepareStatement(query);
stmt.setInt(1, id);
ResultSet results = stmt.execute();
...
id
의 가능한 모든 값을 고려할 수 없다는 점입니다. 인터페이스에서 현재 사용자의 송장 ID 목록을 생성하더라도 공격자는 이 인터페이스를 무시하고 원하는 송장을 요청할 수 있습니다. 이 예제의 코드가 사용자가 요청한 송장에 접근할 수 있는 권한이 있는지 확인하지 않기 때문에 현재 사용자의 송장이 아닌 송장도 모두 표시합니다.Example 1
을 Android 플랫폼에 맞게 조정합니다.
...
String id = this.getIntent().getExtras().getString("invoiceID");
String query = "SELECT * FROM invoices WHERE id = ?";
SQLiteDatabase db = this.openOrCreateDatabase("DB", MODE_PRIVATE, null);
Cursor c = db.rawQuery(query, new Object[]{id});
...
...
var id = document.form.invoiceID.value;
var query = "SELECT * FROM invoices WHERE id = ?";
db.transaction(function (tx) {
tx.executeSql(query,[id]);
}
)
...
id
의 가능한 모든 값을 고려할 수 없다는 점입니다. 인터페이스에서 현재 사용자의 송장 ID 목록을 생성하더라도 공격자는 이 인터페이스를 무시하고 원하는 송장을 요청할 수 있습니다. 이 예제의 코드가 사용자가 요청한 송장에 접근할 수 있는 권한이 있는지 확인하지 않기 때문에 현재 사용자의 송장이 아닌 송장도 모두 표시합니다.
...
NSManagedObjectContext *context = [appDelegate managedObjectContext];
NSEntityDescription *entityDesc = [NSEntityDescription entityForName:@"Invoices" inManagedObjectContext:context];
NSFetchRequest *request = [[NSFetchRequest alloc] init];
[request setEntity:entityDesc];
NSPredicate *pred = [NSPredicate predicateWithFormat:@"(id = %@)", invoiceId.text];
[request setPredicate:pred];
NSManagedObject *matches = nil;
NSError *error;
NSArray *objects = [context executeFetchRequest:request error:&error];
if ([objects count] == 0) {
status.text = @"No records found.";
} else {
matches = [objects objectAtIndex:0];
invoiceReferenceNumber.text = [matches valueForKey:@"invRefNum"];
orderNumber.text = [matches valueForKey:@"orderNumber"];
status.text = [NSString stringWithFormat:@"%d records found", [objects count]];
}
[request release];
...
id
의 가능한 모든 값을 고려할 수 없다는 점입니다. 인터페이스에서 현재 사용자의 송장 ID 목록을 생성하더라도 공격자는 이 인터페이스를 무시하고 원하는 송장을 요청할 수 있습니다. 이 예제의 코드가 사용자가 요청한 송장에 접근할 수 있는 권한이 있는지 확인하지 않기 때문에 현재 사용자의 송장이 아닌 송장도 모두 표시합니다.
...
$id = $_POST['id'];
$query = "SELECT * FROM invoices WHERE id = ?";
$stmt = $mysqli->prepare($query);
$stmt->bind_param('ss',$id);
$stmt->execute();
...
id
의 가능한 모든 값을 고려할 수 없다는 점입니다. 인터페이스에서 현재 사용자의 송장 ID 목록을 생성하더라도 공격자는 이 인터페이스를 무시하고 원하는 송장을 요청할 수 있습니다. 이 예제의 코드가 사용자가 요청한 송장에 접근할 수 있는 권한이 있는지 확인하지 않기 때문에 현재 사용자의 송장이 아닌 송장도 모두 표시합니다.
procedure get_item (
itm_cv IN OUT ItmCurTyp,
id in varchar2)
is
open itm_cv for ' SELECT * FROM items WHERE ' ||
'invoiceID = :invid' ||
using id;
end get_item;
id
의 가능한 모든 값을 고려할 수 없다는 점입니다. 인터페이스에서 현재 사용자의 송장 ID 목록을 생성하더라도 공격자는 이 인터페이스를 무시하고 원하는 송장을 요청할 수 있습니다. 이 예제의 코드가 사용자가 요청한 송장에 접근할 수 있는 권한이 있는지 확인하지 않기 때문에 현재 사용자의 송장이 아닌 송장도 모두 표시합니다.
...
id = request.POST['id']
c = db.cursor()
stmt = c.execute("SELECT * FROM invoices WHERE id = %s", (id,))
...
id
의 가능한 모든 값을 고려할 수 없다는 점입니다. 인터페이스에서 현재 사용자의 송장 ID 목록을 생성하더라도 공격자는 이 인터페이스를 무시하고 원하는 송장을 요청할 수 있습니다. 이 예제의 코드가 사용자가 요청한 송장에 접근할 수 있는 권한이 있는지 확인하지 않기 때문에 현재 사용자의 송장이 아닌 송장도 모두 표시합니다.
...
id = req['invoiceID'].respond_to(:to_int)
query = "SELECT * FROM invoices WHERE id=?"
stmt = conn.prepare(query)
stmt.execute(id)
...
id
의 가능한 모든 값을 고려할 수 없다는 점입니다. 인터페이스에서 현재 사용자의 송장 ID 목록을 생성하더라도 공격자는 이 인터페이스를 무시하고 원하는 송장을 요청할 수 있습니다. 이 예제의 코드가 사용자가 요청한 송장에 접근할 수 있는 권한이 있는지 확인하지 않기 때문에 현재 사용자의 송장이 아닌 송장도 모두 표시합니다.
def searchInvoice(value:String) = Action.async { implicit request =>
val result: Future[Seq[Invoice]] = db.run {
sql"select * from invoices where id=$value".as[Invoice]
}
...
}
id
의 가능한 모든 값을 고려할 수 없다는 점입니다. 인터페이스에서 현재 사용자의 송장 ID 목록을 생성하더라도 공격자는 이 인터페이스를 무시하고 원하는 송장을 요청할 수 있습니다. 이 예제의 코드가 사용자가 요청한 송장에 접근할 수 있는 권한이 있는지 확인하지 않기 때문에 현재 사용자의 송장이 아닌 송장도 모두 표시합니다.
...
let fetchRequest = NSFetchRequest()
let entity = NSEntityDescription.entityForName("Invoices", inManagedObjectContext: managedContext)
fetchRequest.entity = entity
let pred : NSPredicate = NSPredicate(format:"(id = %@)", invoiceId.text)
fetchRequest.setPredicate = pred
do {
let results = try managedContext.executeFetchRequest(fetchRequest)
let result : NSManagedObject = results.first!
invoiceReferenceNumber.text = result.valueForKey("invRefNum")
orderNumber.text = result.valueForKey("orderNumber")
status.text = "\(results.count) records found"
} catch let error as NSError {
print("Error \(error)")
}
...
id
의 가능한 모든 값을 고려할 수 없다는 점입니다. 인터페이스에서 현재 사용자의 송장 ID 목록을 생성하더라도 공격자는 이 인터페이스를 무시하고 원하는 송장을 요청할 수 있습니다. 이 예제의 코드가 사용자가 요청한 송장에 접근할 수 있는 권한이 있는지 확인하지 않기 때문에 현재 사용자의 송장이 아닌 송장도 모두 표시합니다.
...
id = Request.Form("invoiceID")
strSQL = "SELECT * FROM invoices WHERE id = ?"
objADOCommand.CommandText = strSQL
objADOCommand.CommandType = adCmdText
set objADOParameter = objADOCommand.CreateParameter("id" , adString, adParamInput, 0, 0)
objADOCommand.Parameters("id") = id
...
id
의 가능한 모든 값을 고려할 수 없다는 점입니다. 인터페이스에서 현재 사용자의 송장 ID 목록을 생성하더라도 공격자는 이 인터페이스를 무시하고 원하는 송장을 요청할 수 있습니다. 이 예제의 코드가 사용자가 요청한 송장에 접근할 수 있는 권한이 있는지 확인하지 않기 때문에 현재 사용자의 송장이 아닌 송장도 모두 표시합니다.Metadata
개체가 수락됩니다.Metadata
클래스는 Google Remote Procedure Call(gRPC)에서 사용하는 기본 프로토콜의 헤더 데이터를 저장하는 데 사용되는 경우가 많습니다. io.grpc.ServerInterceptor
클래스를 구현할 때는 Metadata
개체를 확인해야 하며 예외가 발생하면 오류를 반환해야 합니다.Metadata
개체의 입력으로 사용되는 사용자 제어 가능 데이터가 나와 있습니다. 이 개체는 예외가 catch된 후 다음 io.grpc.ServerCallHandler
개체로 전달됩니다.
class PotentialAuthByPassInterceptor implements ServerInterceptor {
@Override
public <ReqT, RespT> ServerCall.Listener<ReqT> interceptCall(ServerCall<ReqT, RespT> call, Metadata metadata, ServerCallHandler<ReqT, RespT> next) {
try {
customValidate(metadata);
} catch (RuntimeException e) {
return next.startCall(call, metadata);
}
...
return Contexts.interceptCall(Context.current(), call, metadata, next);
}
}
static string AllowlistVerify(string name) {
Regex pattern = new Regex(@"^[a-zA-Z\-\.']+$");
if (pattern.IsMatch(name)) {
return name;
}
return null;
}
...
string verifiedName = AllowlistVerify(managerName.Text.trim());
if(verifiedName != null) {
DirectorySearcher src = new DirectorySearcher("(manager=" + verifiedName + ")");
src.SearchRoot = de;
src.SearchScope = SearchScope.Subtree;
foreach(SearchResult res in src.FindAll()) {
...
}
}
empName
의 다른 값을 제공할 경우 발생될 일에 대해 고려하지 못했다는 점입니다. 인터페이스에서 현재 사용자의 직원 ID를 자동으로 제공하지만 공격자는 악의적인 요청의 일부로 다른 값을 제공할 수 있습니다. 이 예제의 코드가 익명의 바인딩에서 쿼리를 실행하므로 현재 인증된 사용자의 ID와 관계 없이 올바른 직원 ID에 대한 디렉터리 항목을 반환할 것입니다.
char* allowlist_verify(char* name) {
const char *error;
int errOffset;
char* regex = "^[a-zA-Z\\-\\.']+$";
pcre* re = pcre_compile(regex, 0, &err, &errOffset, NULL);
int rc = pcre_exec(re, NULL, name, strlen(name), 0, 0, NULL, 0);
if (rc == 1)
return name;
return NULL;
}
...
fgets(managerName, sizeof(managerName), socket);
char* verified_name = allowlist_verify(managerName);
if(verified_name != NULL) {
snprintf(filter, sizeof(filter), "(manager=%s)", verified_name);
if ( ( rc = ldap_search_ext_s( ld, FIND_DN, LDAP_SCOPE_BASE,
filter, NULL, 0, NULL, NULL, LDAP_NO_LIMIT,
LDAP_NO_LIMIT, &result ) ) == LDAP_SUCCESS ) {
...
}
}
username
의 다른 값을 제공할 경우 발생될 일에 대해 고려하지 못했다는 점입니다. 이 예제의 코드가 익명의 바인딩에서 쿼리를 실행하므로 현재 인증된 사용자의 ID와 관계 없이 올바른 직원 ID에 대한 디렉터리 항목을 반환할 것입니다.
...
env.put(Context.SECURITY_AUTHENTICATION, "none");
DirContext ctx = new InitialDirContext(env);
String empID = request.getParameter("empID");
try
{
int id = Integer.parseInt(empID);
BasicAttribute attr = new BasicAttribute("empID", empID);
NamingEnumeration employee =
ctx.search("ou=People,dc=example,dc=com",attr);
...
empID
의 다른 값을 제공할 경우 발생될 일에 대해 고려하지 못했다는 점입니다. 인터페이스에서 현재 사용자의 직원 ID를 자동으로 제공하지만 공격자는 악의적인 요청의 일부로 다른 값을 제공할 수 있습니다. 이 예제의 코드가 익명의 바인딩에서 쿼리를 실행하므로 현재 인증된 사용자의 ID와 관계 없이 올바른 직원 ID에 대한 디렉터리 항목을 반환할 것입니다.<security constraint>
요소는 프로그램에 RBAC(Role-Based Access Control)가 사용되고 있지 않음을 암시합니다. RBAC는 보안 웹 응용 프로그램에서 민감한 작업의 보호를 위해 널리 용인되는 모범 사례입니다. 민감한 작업 또는 데이터에 대한 액세스를 제공하는 응용 프로그램의 경우 권한이 없는 사용자의 액세스를 차단하는 충분한 제어가 없을 수 있습니다. 또한 <url-pattern>
에 와일드카드(*)가 있는 경우 패턴이 지나치게 광범위하다는 표시일 수 있습니다.send
함수 및 해당 변형을 사용하면 프로그래머는 함수에 대한 Ruby 접근 지정자를 우회할 수 있습니다. 특히 프로그래머는 일반적으로는 허용되지 않는 개인(private) 및 보호(protected) 필드에의 접근이 가능합니다.
<property name="filterInvocationDefinitionSource">
<value>
CONVERT_URL_TO_LOWERCASE_BEFORE_COMPARISON
\A/secure/.*\Z=REQUIRES_SECURE_CHANNEL
\A/acegilogin.jsp.*\Z=REQUIRES_SECURE_CHANNEL
\A/j_acegi_security_check.*\Z=REQUIRES_SECURE_CHANNEL
\A.*\Z=REQUIRES_INSECURE_CHANNEL
</value>
</property>
<bean id="bankManagerSecurity" class="org.acegisecurity.intercept.method.aopalliance.MethodSecurityInterceptor">
...
<property name="objectDefinitionSource">
<value>
com.example.service.PrivateCatalog.getData=ROLE_PEON,RUN_AS_UBER_BOSS
...
</value>
</property>
</bean>
url-invoke-disallowed
설정을 사용하면 명확성이 떨어지며 기본값이 예기치 않게 변경될 경우 원치 않는 동작으로 이어질 수 있습니다.HTTP 403
상태 코드가 수신됩니다. 그러나 암시적 설정을 사용하면 항상 명확성이 떨어지고 기본 설정이 물밑에서 변경될 경우 원치 않는 동작으로 이어질 수 있습니다.url-invoke-disallowed
설정으로 구성된 작업 흐름의 예를 보여줍니다.
...
<task-flow-definition id="password">
<default-activity>PasswordPrompt</default-activity>
<view id="PasswordPrompt">
<page>/PasswordPrompt.jsff</page>
</view>
<use-page-fragments/>
</task-flow-definition>
...
paramName
URL 매개 변수의 변환 또는 검증을 수행하지 않도록 구성된 책갈피 지정 가능한 보기의 샘플을 보여줍니다.
...
<bookmark>
<method>#{paramHandler.handleParams}</method>
<url-parameter>
<name>paramName</name>
<value>#{requestScope.paramName}</value>
</url-parameter>
</bookmark>
...
unsecure
속성은 클라이언트에서 그 값이 설정될 수 있는 속성의 목록을 지정합니다.unsecure
속성은 그러한 목록을 지정할 수 있습니다.unsecure
속성 내에 나타날 수 있는 유일한 속성은 disabled
이며, 이는 활성화되는 구성 요소와 그렇지 않은 구성 요소를 클라이언트가 정의하도록 허용합니다. 서버에서만 설정할 수 있는 속성의 값을 클라이언트가 제어하도록 하는 것은 좋은 방법이 아닙니다.unsecure
속성을 사용하는 inputText
구성 요소를 보여줍니다.
...
<af:inputText id="pwdBox"
label="#{resources.PWD}"
value=""#{userBean.password}
unsecure="disabled"
secret="true"
required="true"/>
...
writePermission
만 정의된 콘텐트 공급자를 선언합니다.writePermission
만 정의하면 오해의 소지가 있을 수 있습니다. SQL의 특성상 진정한 쓰기 전용 쿼리를 생성하는 것은 일반적으로 불가능합니다. 사용자가 데이터에 액세스할 수 없는 경우에도 공격자는 where
절을 조작하여 저장된 데이터를 재구성할 수 있습니다.writePermission
으로만 선언된 콘텐트 공급자의 예입니다.<provider android:name=".ContentProvider" android:writePermission="content.permission.WRITE_CONTENT"/>
...
context.registerReceiver(broadcastReceiver, intentFilter);
...