如何防止Azure表注入? [英] How the prevent Azure table injection?
问题描述
有没有一般方法可以防止天蓝色存储注入.
Is there a general way to prevent azure storage injection.
如果查询包含用户输入的字符串,例如他的名字.然后可以进行一些注入,例如:jan +'或PartitionKey eq'kees.这样会得到一个对象jan和一个带有partitionKey的对象.
If the query contains a user entered string for example his name. Then it is possible to do some injection like: jan + ' or PartitionKey eq 'kees. This will and up getting an object jan and an object with the partitionKey kees.
一个选项是URLEncoding.在这种情况下,'和'被编码.以上注入不再可行.
One option is URLEncoding. In this case ' and " are encoded. And the above injection is not possible anymore.
这是最好的选择还是更好的选择?
Is this the best option or are there better ones?
推荐答案
根据我的经验,我意识到有两种通用方法可以防止Azure存储表的注入.一个是将字符串'替换为另一个字符串,如;,"或"URLEncode字符串".这是您的选择.另一个是存储表密钥,它使用普通内容的编码格式(例如Base64)进行插播.
Per my experience, I realize that there is two general ways to prevent azure storage table injection. The one is replace the string ' with the other string such as ; , " or URLEncode string of '. This is your option. The other is storage table key using an encoding format(such as Base64) instread of plain content.
这是我的测试Java程序,如下所示:
This is my test Java program as follows:
import org.apache.commons.codec.binary.Base64;
import com.microsoft.azure.storage.CloudStorageAccount;
import com.microsoft.azure.storage.table.CloudTable;
import com.microsoft.azure.storage.table.CloudTableClient;
import com.microsoft.azure.storage.table.TableOperation;
import com.microsoft.azure.storage.table.TableQuery;
import com.microsoft.azure.storage.table.TableQuery.QueryComparisons;
public class TableInjectTest {
private static final String storageConnectString = "DefaultEndpointsProtocol=http;" + "AccountName=<ACCOUNT_NAME>;"
+ "AccountKey=<ACCOUNT_KEY>";
public static void reproduce(String query) {
try {
CloudStorageAccount storageAccount = CloudStorageAccount.parse(storageConnectString);
CloudTableClient tableClient = storageAccount.createCloudTableClient();
// Create table if not exist.
String tableName = "people";
CloudTable cloudTable = new CloudTable(tableName, tableClient);
final String PARTITION_KEY = "PartitionKey";
String partitionFilter = TableQuery.generateFilterCondition(PARTITION_KEY, QueryComparisons.EQUAL, query);
System.out.println(partitionFilter);
TableQuery<CustomerEntity> rangeQuery = TableQuery.from(CustomerEntity.class).where(partitionFilter);
for (CustomerEntity entity : cloudTable.execute(rangeQuery)) {
System.out.println(entity.getPartitionKey() + " " + entity.getRowKey() + "\t" + entity.getEmail() + "\t"
+ entity.getPhoneNumber());
}
} catch (Exception e) {
e.printStackTrace();
}
}
/*
* The one way is replace ' with other symbol string
*/
public static String preventByReplace(String query, String symbol) {
return query.replaceAll("'", symbol);
}
public static void addEntityByBase64PartitionKey() {
try {
CloudStorageAccount storageAccount = CloudStorageAccount.parse(storageConnectString);
CloudTableClient tableClient = storageAccount.createCloudTableClient();
// Create table if not exist.
String tableName = "people";
CloudTable cloudTable = new CloudTable(tableName, tableClient);
String partitionKey = Base64.encodeBase64String("Smith".getBytes());
CustomerEntity customer = new CustomerEntity(partitionKey, "Will");
customer.setEmail("will-smith@contoso.com");
customer.setPhoneNumber("400800600");
TableOperation insertCustomer = TableOperation.insertOrReplace(customer);
cloudTable.execute(insertCustomer);
} catch (Exception e) {
e.printStackTrace();
}
}
// The other way is store PartitionKey using encoding format such as Base64
public static String preventByEncodeBase64(String query) {
return Base64.encodeBase64String(query.getBytes());
}
public static void main(String[] args) {
String queryNormal = "Smith";
reproduce(queryNormal);
/*
* Output as follows:
* PartitionKey eq 'Smith'
* Smith Ben Ben@contoso.com 425-555-0102
* Smith Denise Denise@contoso.com 425-555-0103
* Smith Jeff Jeff@contoso.com 425-555-0105
*/
String queryInjection = "Smith' or PartitionKey lt 'Z";
reproduce(queryInjection);
/*
* Output as follows:
* PartitionKey eq 'Smith' or PartitionKey lt 'Z'
* Webber Peter Peter@contoso.com 425-555-0101 <= This is my information
* Smith Ben Ben@contoso.com 425-555-0102
* Smith Denise Denise@contoso.com 425-555-0103
* Smith Jeff Jeff@contoso.com 425-555-0105
*/
reproduce(preventByReplace(queryNormal, "\"")); // The result same as queryNormal
reproduce(preventByReplace(queryInjection, "\"")); // None result, because the query string is """PartitionKey eq 'Smith" or PartitionKey lt "Z'"""
reproduce(preventByReplace(queryNormal, "&")); // The result same as queryNormal
reproduce(preventByReplace(queryInjection, "&")); // None result, because the query string is """PartitionKey eq 'Smith& or PartitionKey lt &Z'"""
/*
* The second prevent way
*/
addEntityByBase64PartitionKey(); // Will Smith
reproduce(preventByEncodeBase64(queryNormal));
/*
* Output as follows:
* PartitionKey eq 'U21pdGg='
* U21pdGg= Will will-smith@contoso.com 400800600 <= The Base64 string can be decoded to "Smith"
*/
reproduce(preventByEncodeBase64(queryInjection)); //None result
/*
* Output as follows:
* PartitionKey eq 'U21pdGgnIG9yIFBhcnRpdGlvbktleSBsdCAnWg=='
*/
}
}
我认为最好的选择是根据应用程序的感觉选择一种合适的方法来防止查询注入.
I think that the best option is choose a suitable way to prevent query injection on the basis of application sence.
任何问题,请随时让我知道.
Any concerns, please feel free to let me know.
这篇关于如何防止Azure表注入?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!