統計情報(30日間)


最新情報をツイート


人気の投稿

安全なアプリ内課金 (iOS5.1以前)

このエントリーをはてなブックマークに追加

※この話題は iOS5.1以前が対象


引用:
攻撃の方法はDNSのレコードを変更してAppStoreのサーバーに対する
リクエストを偽装サーバーにリダイレクトし、偽装サーバーがAppStoreのサーバーの
エミュレーションを行うことで支払ったかのように見せることができる、というものの
ようですね。



なるほど。昨日紹介したライブラリ CargoBay がiTSの証明書確認までやっていた理由がこれでわかった。
Blocksベースの高機能な StoreKit ラッパー - CargoBay | Cocoaの日々情報局

確かに接続先が偽装された場合を想定すると証明書の確認が必要になる。

Appleは昨年7月に安全なアプリ内課金に関する指針と支援コードの提供を行っていた。


対象は iOS5.1以前。

チェック指針は4つ
Check that the SSL certificate used to connect to the App Store server is an EV certificate.
Check that the information returned from validation matches the information in the SKPayment object.
Check that the receipt has a valid signature.
Check that new transactions have a unique transaction ID.

またこのサイトで VerificationController.h/m が配布されている。
ヘッダの内容:
#define IS_IOS6_AWARE (__IPHONE_OS_VERSION_MAX_ALLOWED > __IPHONE_5_1)

#define ITMS_PROD_VERIFY_RECEIPT_URL        @"https://buy.itunes.apple.com/verifyReceipt"
#define ITMS_SANDBOX_VERIFY_RECEIPT_URL     @"https://sandbox.itunes.apple.com/verifyReceipt";

#define KNOWN_TRANSACTIONS_KEY              @"knownIAPTransactions"
#define ITC_CONTENT_PROVIDER_SHARED_SECRET  @"your secret here"

char* base64_encode(const void* buf, size_t size);
void * base64_decode(const char* s, size_t * data_len);

@interface VerificationController : NSObject {
    NSMutableDictionary *transactionsReceiptStorageDictionary;
}

+ (VerificationController *) sharedInstance;


// Checking the results of this is not enough.
// The final verification happens in the connection:didReceiveData: callback within
// this class.  So ensure IAP feaures are unlocked from there.
- (BOOL)verifyPurchase:(SKPaymentTransaction *)transaction;

実装をコードを読むと...見覚えがある。ああ、CargoBay で見たのはこのコードだ。CargoBayはこのコードを元に証明書チェック他の処理を組み込んでいたのか。

- - - -
攻撃自体が恐らく少ない上に iOS6では改善されているとのことなので実際にはここまでやる必要は無いと思われる。

Blocksベースの高機能な StoreKit ラッパー - CargoBay

このエントリーをはてなブックマークに追加

Blocksで書けるのはなかなかいい。



Product Requests はこんな感じで書ける。
NSArray *identifiers = @[
  @"com.example.myapp.apple",
  @"com.example.myapp.pear",
  @"com.example.myapp.banana"
];

[[CargoBay sharedManager] productsWithIdentifiers:[NSSet setWithArray:identifiers]
success:^(NSArray *products, NSArray *invalidIdentifiers) {
  NSLog(@"Products: %@", products);
  NSLog(@"Invalid Identifiers: %@", invalidIdentifiers);
} failure:^(NSError *error) {
  NSLog(@"Error: %@", error);
}];

Payment Queue(トランザクション処理)も同様に Blocksで書ける。
- (void)application:(UIApplication *)application didFinishLoadingWithOptions:(NSDictionary *)options {
  [[CargoBay sharedManager] setPaymentQueueUpdatedTransactionsBlock:^(SKPaymentQueue *queue, NSArray *transactions) {
    NSLog(@"Updated Transactions: %@", transactions);
  }];

  [[SKPaymentQueue defaultQueue] addTransactionObserver:[CargoBay sharedManager]];

  // ...
}



レシートの確認処理用に外部のライブラリ AFNetworkingを利用している。

なお Security.frameworkを組み込むとレシート確認ではiTSの証明書検証を独自に行うようになるだ
(CBCheckReceiptSecurity関数)。アプリ内課金は未経験なのでよくわからないのだがここまでやる必要があるのか?(あるとしたら書くのは面倒なのでこのライブラリはかなり便利)。

- - - -
なお余談だが CargoBay.m 内にあったBase64デコード関数 CBDataFromBase64EncodedString は配列を使ったもので面白かった。出典はCocoa with Loveだった↓

SaaS系サービスは自動継続課金が使えない

このエントリーをはてなブックマークに追加

らしい。参考になる。他に非継続課金(Non-Renewing-Subscriptions)を実装する時の注意点など。



アプリ内課金プログラミング

このエントリーをはてなブックマークに追加

種類や導入の流れなど基本的なところから説明してくれている記事。今後の続きも期待。

事故らない iOS 課金プログラミング - A Day In The Life