[PATCH damus 2/2] Prevent forged profile zap attacks

The fake note zap attack made me realize that there is a way to do fake
profile zaps using a similar technique. Since damus only checks the
first ptag if it is a profile zap, this means you could include multiple
ptags, the first one being the fake profile with the fake zapper, and
the second p tag as the real target.

This would allow a fake zapper to create a fake a zap, while the zap
notification would still appear for the second ptag because damus
listens for zap events via #p, and that would match the second ptag.

To fix this, ensure that zaps only have at most 1 ptag and 0 or 1 etag.
my CLN zapper checks this but if we don't check this here as well then
we run into fake zap issues.

Changelog-Fixed: Fix potential fake profile zap attacks
Cc: Tony Giorgio <tonygiorgio@protonmail.com>
Cc: benthecarman <benthecarman@live.com>
Cc: Vitor Pamplona <vitor@vitorpamplona.com>
Cc: Kieran <kieran@harkin.me>
Cc: Jonathan Staab <shtaab@gmail.com>
Cc: Mike Dilger <mike@mikedilger.com>
Signed-off-by: William Casarin <jb55@jb55.com>
---
 damus/Models/HomeModel.swift | 17 +++++++++++++++--
 1 file changed, 15 insertions(+), 2 deletions(-)

diff --git a/damus/Models/HomeModel.swift b/damus/Models/HomeModel.swift
index e727c9c1..b52a0d23 100644
--- a/damus/Models/HomeModel.swift
+++ b/damus/Models/HomeModel.swift
@@ -1239,11 +1239,24 @@ enum ProcessZapResult {
 // securely get the zap target's pubkey. this can be faked so we need to be
 // careful
 func get_zap_target_pubkey(ev: NostrEvent, events: EventCache) -> String? {
-    if let etag = event_tag(ev, name: "e") {
+    let etags = ev.referenced_ids
+
+    if let etag = etags.first {
+        // ensure that there is only 1 etag to stop fake note zap attacks
+        guard etags.count == 1 else {
+            return nil
+        }
         // we can't trust the p tag on note zaps because they can be faked
         return damus_state.events.lookup(etag)?.pubkey
     } else {
-        return event_tag(ev, name: "p")
+        let ptags = ev.referenced_pubkeys
+
+        // ensure that there is only 1 ptag to stop fake profile zap attacks
+        guard ptags.count == 1 else {
+            return nil
+        }
+
+        return ptags.first?.id
     }
 }
 
-- 
2.39.2 (Apple Git-143)

Received on Sunday, 9 July 2023 06:14:58 UTC