Hacker News new | past | comments | ask | show | jobs | submit login
Adblock Plus filter lists may execute arbitrary code in web pages (armin.dev)
245 points by dessant on April 15, 2019 | hide | past | favorite | 98 comments

Good advice:

"Users may also switch to uBlock Origin.[1] It does not support the $rewrite filter option and it is not vulnerable to the described attack."

[1] https://github.com/gorhill/uBlock

There have been many good reasons to switch to uBlock Origin long before today's issue: speed, memory footprint, no "acceptable ads", etc. I don't know why anyone still uses ABP.

It's mostly a marketing issue in my opinion. ABP was the first ad-blocker to enter the mainstream market back during the Firefox days, and they had virtually no competition for half a decade, before the entire Acceptable Ads controversy. I think unfortunately there is still a significant number of users who just associate "AdBlock == AdBlock Plus".

> a significant number of users who just associate "AdBlock == AdBlock Plus"

AdBlock uses Adblock Plus filtering engine internally and also supports and enables "Acceptable Ads" by default:

> AdBlock is a popular ad blocking extension for Chrome, Opera and Safari, now based on the Adblock Plus code.[1]

* * *

[1] https://github.com/betafish-inc/adblock-releases

Oh, sorry, I was not referring to specifically that AdBlock extension. I wanted to say that users just associate "adblocking extension = AdBlock Plus".

Ah I see, never mind then; and in that case I do agree with your comment.

Any chance you're going to get the uBlock name back? Explaining the story every time I tell someone to switch to uBlock Origin is annoying.

Love ur work with origin

Agreed, in the same way all touchscreen smartphones were/are(?) called iPhones, or people calling all tissues Kleenexes in the US, I think for a huge fraction of laypersons, ABP has an understandably strong grasp on the product category.

There were a lot of people telling others to use AdBlock Plus for a long time, and once a bit of advice like that gets lodged in the public consciousness, it's next to impossible to extract it. I still run into Windows users who still think they need to install WinZip to open ZIP files, for instance, even though Windows has come with ZIP handling built in to its file explorer ever since Windows XP.

This is why brands have immense value.

Also antivirus is the same way. Windows AV is perfectly acceptable for many normal use cases, but people still think they need free AV alternatives like AVG.

Or horrible (in my opinion) paid solutions like McAfee...

>Or horrible (in my opinion) paid solutions like McAfee...

It's not just your opinion. Mr. John McAfee himself, the guy who started the company and whose name it still bears, has publicly stated that McAfee software is "the worst software on the planet"!

If that isn't enough for people to avoid a brand name, then I don't know what is. But apparently, countless businesses are so clueless they keep using McAfee software even though its own founder says it's trash.

> Windows has come with ZIP handling built in to its file explorer ever since Windows XP.

Although it's been molasses-slow in comparison to 3rd party tools since that time as well.

True, but it's Good Enough for most people, who only deal with ZIP files infrequently and generally only ever encounter relatively small ones.

When I talk to these folks and probe why they think they need WinZip, they never say "oh, I was trying to uncompress a 7GB file the other day in Explorer and it took forever." They say "I'm on Windows, and this is a Zip, therefore I need WinZip." They're usually genuinely surprised to find out that this is something Windows can do all by itself.

Does anybody know why this happens? I don't think MSFT would really have issues finding some software engineers to fix this.

I guess this is the reason: https://devblogs.microsoft.com/oldnewthing/20180515-00/?p=98...

> Since its release in Windows XP, Zip folders has not been actively developed. The reason is the usual: Because adding features requires engineering resources, and engineering resources are limited. Furthermore, since the compression and decompression code weren’t written by anybody from Microsoft, there is no expertise in the code base, which means that debugging and making changes is a very difficult undertaking.

“Because adding features requires engineering resources, and engineering resources are limited.“

seems to translate to ‘because we really don’t care’. It’s not as if Microsoft is strapped for cash.

At least they haven't purged it, if this were Google then there would be no ZIP support in newer OS versions.

They even killed ChromeOS ans Chorme updates for a bunch of 3 to 4 year old Chromebooks recently, despite the hardware being fine to run newer ChromeOS.

Why should they? Are they going to make more money if they fix it? Of course not; people aren't basing their usage of Windows on the performance of the built-in unzipper. Advanced users just install a 3rd-party tool, the clueless masses just use the built-in thing and wait and think it's normal. Companies like Microsoft don't care about building the best product they can; they only care about maximizing profits, so the solution that's "good enough" is what they go with. What they have works, poorly, and costs them nothing to maintain, so that's what they stick with.

uBlock Origin for Safari has been abandoned for about a year. :\

Safari's (Webkit's) content blockers are even better imo. Declarative rules that get compiled. Can't intercept arbitrary requests with Javascript logic but I don't think that's necessary. Though it makes something like uMatrix harder to implement.

There's still a need for something like the element zapper which can remove obstructing popups that aren't implemented in Javascript.

Though you can implement this with the content blocker API. You add a rule to the rule list and recompile it, though it does come at the expense of UX and flexibility for sure.

Which has been a part of Content Blockers since day 1.

I wish there was something like uMatrix for Safari but using content blockers. Would really scratch an itch for me.

Safari’d content blockers are next to useless.

Safari is really easy to beat by anti-ad-blocking technology, the only reason for why more publishers won’t do it is because they don’t want to piss off people, but as the minority of people using ad-blockers grows, they’ll get over that fear.

Also FYI injecting scripts in webpages is the only way to prevent anti-ad-blocking from working.

Safari content blocking API is abandoned since 2015 when it was introduced. It simply does not allow using advanced blocking techniques which were developed by Chrome/FF blockers during these years.

It might be enough to handle most of the ads at the moment, but it fails miserably when a website uses any adblock circumvention.

How is it abandoned? Because the API doesn't change more often than I change my underwear? It works well, is efficient and ensures user privacy and safety (from the sort of issues being described in the article) and it gained new capabilities (forcing a HTTPS url) after launch.

As for your specific claim, 1Blocker has an entire section of blocking rules to counter anti-adblock.

Sure, if some site want's to be completely hostile to users, it may still show up. The little cross icon on the tab solves that issue pretty quickly.

So you are telling me that not changing the API in years despite numerous requests is a good thing? Well, I disagree.

Regarding https, this change was made in 2015.

There's a wide spectrum between "abandoned" and "totally up to date." Not everything is black and white.

Well it all depends what the requests are, doesn’t it.

I’m sure some have requested the ability to run javascript, that doesn’t mean it’s a good idea to add that to the api.

> Well it all depends what the requests are, doesn’t it.

Oh, there are all sorts of them.

From simple feature requests (like being able to distinguish fetch/xmlhttprequest) and bug reports (like that it considers requests to subdomains third-party) to something more complicated.

The problem is that regardless of what's requested/reported, there is no reaction.

> I’m sure some have requested the ability to run javascript, that doesn’t mean it’s a good idea to add that to the api.

Desktop Safari allows extensions to run javascript, why would anyone want to make it a part of the content blocking API.

>like that it considers requests to subdomains third-party)

As it should. Sometimes subdomains are third party. If I whitelist example.org I do not want any subdomains to be whitelisted without be explicitely whitelisting *.example.org as a wildcard or any specific subdomains.

Proof of concept: I constantly host what I could consider 3rd party resources on subdomains for clients. eg: billing.example.com where billing. isn't owned or operated by example.com and could be running who knows what in terms of Javascript and Ads that I may or may not trust without whitelisting billing.example.com. The most common of these are specific marketing/tracking forms that they wish to run through some third party marketing agency and not our in-house tracking systems.

Neither xhr nor subdomains sound like valid features/bugs. Just because they don’t agree with changes you want doesn’t mean it’s “abandoned”.

As for why someone would request JS - you’re the one who suggested chrome/ff blockers are “more advanced”. And yet here we are on a thread about arbitrary code execution.

I don't think our discussion can come to any compromise. You seem to believe that not doing anything is a good thing, and the API is already ideal. I have a different opinion. Well, it's okay to have different opinions.

> You seem to believe that not doing anything is a good thing, and the API is already ideal

Not really. I've submitted a request for an enhancement myself (ability to auto-redirect to the canonical URL - to avoid the bullshit of AMP pages) but what you've suggested just don't seem like worthwhile or positive changes IMO.

My argument wasn't "zero change is good" my argument is that it doesn't need much change and a stable API is hardly "abandonment".

At the same time, I merely will not use a website that is so hostile nor do I regularly encounter websites like that. uBlock Origin breaks in this way as well, and the only website I can even recall with this behavior was a shady movie-streaming site I was linked to.

What do you mean by abandoned? I use it and it works for me daily.

Adblock circumvention is a technique when a website reinjects and encrypts the ads when it detects that they were blocked. Kinda like what Facebook does.

Most of the changes and improvements to modern ad blockers are to deal with this kind of ads. Not in Safari, though. Webkit devs did nothing to improve or extend the content blocking API. Not to say that it still imposes the ridiculous rules limitation - you can't have more than 50k rules in a list (while Easylist alone has more than 80k).

I'm not sure what misunderstanding you think I have with regard to adblock circumvention.

I can appreciate that uBlock Origin wants to be a universal condom that works on every website for everyone, but I also don't think it's so damning if the content blocker API is sufficient for that. Yet uBlock Origin and its rule lists still fail at this task as well.

A website can do any number of annoying things that uBlock Origin cannot block including things that aren't even related to ads. I simply refuse to use such websites. In fact, I want to know that a website does these things rather than remain in blissful ignorance. I don't want to support such a website even with my viewership.

I've built content blockers. The rule limit is circumvented by simply bundling multiple rule lists.

Also, 80% of Easylist is crap anyways. The problem with Easylist and things like it is that they become append-only lists because nobody wants to go back and verify that rules still apply. Not to mention all the site-specific rules for sites you'll never visit because it was someone's random hobby horse. But you can absolutely encode Easylist across two content blocker extensions bundled in one app. But in doing so, you'll also realize how easy it is to prune so that it fits in one rule list, there are so many rules for garbage sites.

> I can appreciate that uBlock Origin wants to be a universal condom that works on every website for everyone, but I also don't think it's so damning if the content blocker API is sufficient for that. Yet uBlock Origin and its rule lists still fail at this task as well.

I'd say it is sufficient for 90% of the websites at the moment.

My point is that this is not a constant value. Advertisers adapt and evolve, and content blockers need to do the same.

> A website can do any number of annoying things that uBlock Origin cannot block including things that aren't even related to ads. I simply refuse to use such websites. In fact, I want to know that a website does these things rather than remain in blissful ignorance. I don't want to support such a website even with my viewership.

This is indeed the best way to let site owners know that this approach is unacceptable. I wish everyone were doing the same.

> The rule limit is circumvented by simply bundling multiple rule lists.

Sure, but this is a workaround, quite an ugly one in fact.

> Also, 80% of Easylist is crap anyways

It does contain a lot of redundant rules, maybe 30% of it, but not 80% that's for sure. And what if I want to use more filter lists? The only thing I can do is use the multiple lists workaround. It is simply weird that nothing was done about this limitation in more than 3 years.

I think the limitation is just the simplest trade-off.

For example, an unbounded rule list has unbounded serial compilation time.

A 50k rule list recompiles in a couple seconds on my laptop and quite some time on my iPhone, but multiple rule lists can be compiled in parallel.

I suppose your response to this would be that content blocker recompilation could be made parallel over a single list or made to support incremental recompilation.

And you're probably right. But note that even Chrome's proposed content blocker system has the same limitation. Perhaps it's not as straightforward as it seems and it's not just a result of neglect/abandonment.

I mainly responded because the language you used seemed more damning than necessary. But have you tried 1Blocker X[1] which is built on the content blocker API? It's hard to condemn the content blocking system too much when there's an app that utilizes it to such great effect.

You are right about Apple/Webkit moving slowly on community feedback and bug reports though. I suppose I'm used to the glacial pace of non-critical-path browser issues after my Firefox bug went three years without response until it was fixed after Quantum's release. You are probably more critical here than I am. At Amazon, anything sev3 to sev5 went into a heap so large it was a miracle if anyone opened it again.

[1]: https://itunes.apple.com/us/app/1blocker-x-adblock/id1365531...

That’s an easy one to get around. 1Blocker X has 10 sets of rules.

It is open source. You can probably make it work with a single git merge (judging from experience with uMatrix for Edge).

I use ublock in advanced mode ( broken web by default + white lists ). I have no experience with the non-expert mode and for this reason tend to recommend / install ABP to friends / family.

Somehow, my intuition is that ublock is too advanced/complex for non-tech-affine users.

i use ublock origin with default settings and the end-user browsing experience the same as ABP. click install and never touch it again.

ublock origin is also not owned by a company that takes money from advertisers to be reviewed for the "acceptable ads" list

Kind of funny, I just noticed uBlock Origin blocks requests to uBlock.org under "Badware risks" maybe they should add adblock plus to that list now.

how the hell did the uBlock brand get sold do ABP anyways? (probably the wrong place to ask such things on HN)

I wrote my own thoughts on this on Reddit recently[1], excerpt:

> BetaFish Inc, owner of AdBlock, paid to acquire control of the GitHub repository and control of the ublock.org site last year. The apparent goal was to keep the deception ongoing, and further increase it, as clearly the site is trying to game search engines so to rank ublock.org high in results. They also registered the trademark "uBlock" in Germany, and have been pulling code from "uBlock Origin" repo.

> Nothing that they are doing is user friendly, it's to deceive people who are looking to install "uBlock Origin" into installing "uBlock" instead.

* * *

[1] https://www.reddit.com/r/uBlockOrigin/comments/b8vr9j/got_fo...

thank you for ublock (origin). i was almost fooled into installing the wrong extension when the ublock fork happened. it's shameful that someone would try to take advantage of your hard work like that.

Well this is embarrassing... just double checked what I have installed after reading this, thinking I surely had uBlock Origin. Nope.

Fixed now. Thanks for your work.

>paid to acquire control of the GitHub repository

Paid who?

I think Chris Aljoudi

> https://en.wikipedia.org/wiki/UBlock_Origin

> Through April and May 2015, the uBlock project was forked by Chris Aljoudi, while uBlock Origin reflected the continuing effort by the original developer Raymond Hill. Since April 2015, uBlock Origin has been completely unrelated to the web site ublock.org.

> Shortly after the project division [between uBlock and uBlock Origin], Chris Aljoudi created ublock.org to host uBlock, promote the extension and request donations... In July 2018, uBlock was acquired by AdBlock.

The wording on Wikipedia doesn't seem to match what actually happened.

IIRC, Raymond Hill, the original author of uBlock and current maintainer of uBlock Origin, voluntarily gave the control of uBlock project to Chris Aljoudi because he was tired of dealing with all the bug reports/issues (and Aljoudi offered to take it over, I think).

But due to various reasons, shortly (very shortly, maybe even no gap in between) after, he self-forked uBlock [1] to make uBlock Origin and started to work on it again.

So technically uBlock Origin is the fork, and more importantly, Chris Aljoudi didn't really "fork uBlock", he inherited the main repo.

Note: I'm by no means to defend Aljoudi's practice on uBlock and I'm pretty sure Hill regretted his decision of handing it over. But let's avoid historical revisionism.

[1]: https://web.archive.org/web/20150427225211/https://github.co...

(See the "forked from chrisaljoudi/uBlock" text and readme.MD below)


Edit: [2] Hill's own words about this matter on Apr 11, 2015: https://github.com/gorhill/uBlock/issues/38#issuecomment-918...

Please correct me if I am mistaken, but wasn't https://github.com/gorhill/uBlock where the original uBlock was hosted at? Gorhill might had declared Raymond to be the "owner" of uBlock but to me it is not clear that uBlock Origin is a fork by any means.

It was.

But he later fully transferred (everything, including stars issues and whatever) the repo to Aljoudi (you can do that on GitHub) so it was under Aljoudi's namespace. Then, Hill forked it back, which eventually became the repo for uBlock Origin we have today. It doesn't show "forked from xxx" any more today for reasons I don't know (maybe he recreated it?), but you can still see it in the archive version of it I linked above (you can also check older dates and Chris' one, to show the transfer more clearly).

Interesting, I did not know that you could transfer repos this way on github, thanks.

Did you give away your (implicit) trademark rights to Chris?

Simply giving ownership to a GitHub repo might not be a license.

It seems like uBlock was forked.

The people who forked tried to make some money off the name by asking people for donations. They seemingly failed after the uBlock creator called them out and renamed his work to "uBlock Origin".

So the people who forked sold what they got to ABP and called it a day.

This has been previously discussed on HN:


well they probably paid enough money to the people who sold it. If you were owner of that name, how much would you sell it for?

uBlock Origin is the one to use for the last few years.

(I've worked on filter lists since the Junkbuster and then Privoxy days, through Adblock Plus. Then Adblock Plus suddenly seemed like a bad place to be, and uBlock was similarly questionable, so I moved to uBlock Origin, even though adding new rules there was more work than in ABP. I've been very happy with uBlock Origin, and with its lead developer's apparent benevolent intentions.)

i'm wondering whether adnauseum is safe from this, or rather if it's possibly not safe e.g. with certain lists enabled...

> Users may also switch to uBlock Origin. It does not support the $rewrite filter option

Support for this filter option was discussed (and declined) in uBlock Origin's issue tracker: https://github.com/uBlockOrigin/uBlock-issues/issues/46

We love you gorhill.

Here's a permalink to your explanation in that thread: https://github.com/uBlockOrigin/uBlock-issues/issues/46#issu...

Damn, the developer of uBlock Origin recognized the problem with it immediately, explained it, and shut it down.

He is also the person who posted the parent comment :)

> My hunch tells me this is not good.

After some clicking I found this: https://github.com/uBlockOrigin/uAssets/issues/4080#issuecom... , might be interesting

It's a bit disingenuous to refer to this as an "exploit" all throughout the article. It's a feature, and an intended one at that. It's offering whitelist maintainers more power over their filters. You can disagree with its inclusion in the spec (as I do), but you should make an argument on that premise instead.

Calling it an exploit is no different than claiming .exe files are exploits because they allow arbitrary code to run. Or that browser extensions are exploits because they too can manipulate the page.

It’s rightly referred to as a vulnerability; the term exploit is used to describe a realistic scenario that is enabled by the vulnerable code.

The problem is that you can’t necessarily trust filter maintainers to be completely honest. Users don’t regularly audit the thousands of rules in their filter lists, so a bad or compromised filter could easily introduce a malicious filter in an update. The $rewrite rule lets a filter change what code is being loaded by a webpage (under certain fairly realistic situations).

>The problem is that you can’t necessarily trust filter maintainers to be completely honest.

I agree with that, and it's not a strong security model. But my original point is that the author is using a bad faith argument by describing a feature they dislike as an exploit. It's in spec for what the original authors intended. Just like running an executable program is potentially risky, but a design of the system.

> the author is using a bad faith argument by describing a feature they dislike as an exploit

I read the article and perhaps it's been edited since you commented, but the author states in the introduction that there is a security vulnerability in a feature and provides an exploit. That to me is quite different from calling the feature itself an exploit.

> It's in spec for what the original authors intended. Just like running an executable program is potentially risky, but a design of the system.

While it's true that it is in spec, I see a big difference in terms of how users experience this situation compared to running an executable program. I see this as more analogous to new feature introduced in an executable format that offers a different security guarantee to what users are already comfortable with. I don't see pointing this out as being in bad faith.

I don't believe it's been edited (or I haven't noticed such an edit). However on a subsequent re-read, I can see the author's usage of the term "exploit" is more specific to his example below (the Google Maps attack demo).

While I'd still argue it's "working as intended" (for better or worse), he is at least calling this specific demonstration an exploit rather than the feature as a whole. So I'll step back from that position, at least part way.

Thank you for the clarification on that point.

User expectation is important. You don't generally have to put warnings on knives that they may cut you, but if you made a coffee mug that sliced peoples lips up you would get in trouble.

As a developer, I expect that browser plugins can execute code in some context (though I think general users may not even expect that); but I don't generally expect that plugins will execute code from some arbitrary 3rd party source.

Users rarely audit extension updates either. You could wake up tomorrow with a new rewrite supporting extension. Would you know?

No, and if someone could use that extension to run arbitrary code in my browser I'd consider that an exploit, even if "Added rewrite option" is in the changelog.

I feel like this is another instance of "useful feature gets removed because of security vulturism[1]" --- something which has been happening for a while, but has gotten infuriatingly frequent lately. In this case, the mere fact that you're using a third-party list already suggests trust of the author, or at least an implicit acknowledgement that your ideas of what should be filtered agree.

Ad blocking extensions should consider dropping support for the $rewrite filter option. It’s always possible to abuse the feature to some degree, even if only images or style sheets are allowed to be redirected.

The classic "ban it because it can be abused" mindset. Let's ban the use of computers too, certainly that would be more secure!

Google has been notified about the exploit, but the report was closed as “Intended Behavior”, since they consider the potential security issue to be present solely in the mentioned browser extensions.

As they should, because what user-agents are doing have nothing whatsoever to do with their site.

(Disclaimer: I don't use ABP nor uBlock nor any in-browser blocking extensions, so I have no conflicts of interest here. I use a full MITM proxy which is far more powerful than anything you can do with a browser extension. I wonder what he'll think about that...)

[1] https://news.ycombinator.com/item?id=19660677

It could have been implemented in a more restrictive way to prevent this issue and allow more targeted behaviors, instead it allows third party lists (which already require a users trust) to run code. Previously this wasn't the case.

Can your MITM proxy modify HTTPS traffic? If so, how did you configure your machines to trust the cert you're using?

Can your MITM proxy modify HTTPS traffic? If so, how did you configure your machines to trust the cert you're using?

Yes, of course. It wouldn't be very useful otherwise. The proxy has its own CA, and I install the cert into the trusted roots of all the machines I use.

Making ad block filter lists Turing-complete: really bad idea.

People are talking about uBlock Origin...

I really like it, no doubts it's good and everyone should consider using it.

BUT, since we are talking about uBlock Origin, I'd like to mention another awesome extention Raymond Hill made.

uMatrix (https://github.com/gorhill/uMatrix)

uMatrix alone is very powerful, and will prevent most ads.

Yes you as a user need to do the work, but the result is better.

If you like the idea of uMatrix, you may also look at NoScript!

Actually, I live almost ad free using NoScript + uBlock Origin for at least 2 yrs.

$rewrite... what a dumb feature btw!

I find uMatrix+uBO (with uMatrix set to block everything by default and uBlock Origin set to it's default easy mode) to be best setup. Ads virtually never get through, and most websites don't need javascript at all to read the articles so my uMatrix whitelist is actually surprisingly small.

Well the solution is easy: we just see which of the filterlist publishers are trustworthy and which aren't, and have the extension automatically download this listlist and apply it to its list of filterlists. Of course you need to be sure that the listlist is of trustworthy origin, but you can just check if the supplier of the listlist is itself on the listlist.

More reasons to run Pihole, the setup just took 20 mins including installing Rasbian. Anyone know how to mimic ublock origins filter list in Pihole ?

Unlock can block page elements while pi hole can only block dns. So if the ad is served from the same domain as the site you are visiting, pi hole cannot do anything about it, but ublock can.

> Anyone know how to mimic ublock origins filter list in Pihole ?

You cannot. Pihole may be. Abetter solution for network-wode ad blocking, but some ads (such as push notification spam) use the same domain name as the original site, so pihole can't block them, being just a DNS blacklist.

Adblock/uBlock are much more powerful than PiHole, which can only block DNS requests. Thus you wouldn't be able to use the majority of the filters.

Perhaps there's some proxy out there that would do it. The closest you'll come to it at the moment is either privoxy (proxy with it's own rules) or alternatively, AdGuard Home, which is like pi-hole, but it also understands AdBlock Filters (though to be clear, it still only does host blocking).

Some discussion by gorhill 11 months ago about this: https://github.com/uBlockOrigin/uBlock-issues/issues/46#issu...

Switch to brave!

one more reason not to use it... too bad the people using it won't ever read that (they should have switched years ago, so we know they don't read this kind of news)

I wonder if we need a non-turning complete library for chrome extensions like we have for some packet filtering libraries and bitcoin script.

No regex.

No loops.

Constrained list of functions.

This could go a long way towards opening up the web to more extensions but also keeping it more secure.

I recently did a rev to the Polar chrome extension:


and I had to request a new permission for filtering and they're now taking a WEEK to approve my any updates due to code review.

I really only need to evaluate a URL and add headers.

This doesn't need to be turing complete.

I basically just need to take a HTTP response and headers if they're missing when a specific origin is set.

This is where Safari content blocking extensions are now. The extensions register a list of URLs with Safari with instructions to block.

The relevant API is there in Chrome though currently in beta only; see https://developers.chrome.com/extensions/declarativeNetReque...

Why no regex and (bounded) loops? You don't need turing completeness for either of these.

And what does Turing completeness has to do with security anyway?

Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact