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
Signed-off-by: William Casarin <
jb...@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)