Archive for March, 2018

In which I get hacked: Part 4

My site was broken into again last night and was down until this morning. What fun.

Welcome to another day of hackage fun.

This morning, the odd “consig.php” with its Base 64 contents and eval was back, along with an updated “.htaccess” file. I called up Bluehost support. They restored a safe version of “.htaccess” and suggested I talk with their “security people”. I said sure.

After a longish hold, they transferred me…to an entirely different company, who for starting at just $40 or so a month (and up), would provide me with a fire wall. The sales pitch was strong, as was their disdain and pricing structure. I thanked them for their time and hung up.

It was time to call back Bluehost again and yell at them a little. This time, they offered to set up an SSL certificate for 90 days at a time.

This might be even more exciting if their own certificate didn’t seem to be wonky:

I also deinstalled and re-installed my plugins, and generally followed the advice passed to me this morning by Jan Östlund in his helpful tweet.

Frankly, it’s been a pretty dreadful day. Of course, the kind words of support from everyone have been a lovely counterpart to the misery of doing sys admin work. I’m surprised so many people have had to deal with this exact situation before. At least I’m not alone.

In which I get hacked: Part 3

This morning, Google issued me an alert that a lot of my pages were 404’ing:

How interesting. So I hopped into my webmaster console to see what was going on.

Lots of 404’s were firing, and the crawl errors were all tied to those image files uploaded to my system by the hack:

I decided it was time to restore the site from backup.

Thanks to UpdraftPlus, I moved the clock back to Mar 20th, and re-created my first two posts in the “In which I get hacked” series.

I also restored my previous authentication, which I quickly updated to a new password. Interestingly, the hack introduced a different login name to my system “zerobyte”. I’m back to my original wordpress names now.

Stuff is still a little messed up on my end as I can no longer upload pictures. The upload process gets the data to the site but the media browser is borked. I have to enter <img src="" /> tags by hand, which is super annoying.

I have my plugins mostly disabled, and will attempt to re-install each of them as well.

Again, any advice and support is greatly welcome. I apologize for losing all my previous comments after restoring from backup. I will particularly miss this gem:

Bless him.

I’ll keep updating if I learn more.

In which I get hacked: Part 2 (restored after backup)

So I’m now working through Google’s Hacked Sites Troubleshooter: https://support.google.com/webmasters/troubleshooter/6155978.

I did not know about the site: search operator, so I followed their instructions, first looking using a site:ericasadun.com websearch, and then moving on to “fetch as google”:

Sure enough I found all those malicious sitemaps that were added this morning:

I returned to my search console and deleted them:

Damn right Skippy, I do. They’re gone now.

I then returned to the troubleshooting page and requested re-indexing. It still shows one of the sitemaps that doesn’t exist anymore (and yes I checked).

I’ll check back in tomorrow and see if the hacked sitemap is gone. I also requested the “reconsideration request” from https://www.google.com/webmasters/tools/manual-action

Yeeps.

In which I get hacked: Part 1 (restored after backup)

Note: This post has been recreating after restoring my site from backup.

This morning, I woke up to a message from Google. Normally I’m very hesitant to open or click these. So I checked the full message headers (View > Message > All Headers), copy pasted the URL it was asking me to click into TextEdit, and looked at it letter by letter. It appeared legit. Someone had added themselves as a new owner for my website:

I went ahead and manually visited https://www.google.com/webmasters/tools/user-admin, selected my account, and sure enough there was a new “owner” listed as of today.  To unverify the hacker, I had to go to my website and remove the Google-specific verification file from my system:

I did that. They could just have as easily unverified me the same way.

I should point out that I not only use four-word passwords but each four-word password has additional strings of numbers and symbols following or interspersed within it. I’m not sure how my security was compromised but it was. I have of course updated my password for the site.

Next, I tried to get in to start finding files modified within the timeframe of the hack. And then, I immediately discovered that Apple has removed telnet from macOS 10.13. (update: turns out I was thinking of the wrong tool. I needed ssh, which I later used to go in to a command line.) So I went in instead using CyberDuck, an ftp client. It wasn’t nearly as easy to track through many  hundreds (thousands?) of files as it would have been at the command line but I think I got ?most? of the problem fixed.

What I found was an incomprehensible “consig.php” file, about 500 image files — each one about 4-8 bytes in size, and masses of items added to sitemap files.

If you’ve had experience with this kind of hack, I would greatly appreciate any additional advice you have. Thanks in advance.

Here’s Google’s help page about when you don’t recognize a new owner: https://support.google.com/webmasters/answer/7281924

Making number checks pretty with unbounded ranges and formatting

This code showed up in a discussion yesterday:

switch averagePosts {
        case 10000000...25000000: return .d
        case 5000000...10000000: return .c
        case 2500000...5000000: return .b
        case 500000...2500000: return .a
        case 250000...500000: return .b
        case 100000...250000: return .c
        case 50000...100000: return .d
        default: return .f
}

I thought it would be much cleaner and easier to use if the coder incorporated unbounded ranges and used Swift’s built-in underscore formatting for their numbers:

switch averagePosts {
case 10_000_000...: return .d
case  5_000_000...: return .c
case  2_500_000...: return .b
case    500_000...: return .a
case    250_000...: return .b
case    100_000...: return .c
case     50_000...: return .d
default:            return .f
}

A few things to note about this rewrite:

Inserting the underscores and aligning the numbers greatly simplifies code validation. Normally I’m not a proponent of making code look “pretty” by adding spaces. Here it serves a very specific purpose, allowing eyeball checks of each number with respect to its fellows.

I kept colon-hugging with default but spaced out the return value to provide a uniform return column for the same reason.

My logic is slightly different from the original as I don’t check for numbers exceeding 25 million. If you wanted to add that, the case would have to be 25_000_001 and not 25_000_000 to exclude the valid value that returns .d. returning .f (the default) instead.

This is a good example of where a full set of Swift range operators would help. Using 25_000_000<..., which would be basically the unbounded half-open-at-the-start operator, could exclude 25 million without using the uglier “I have to add one” hack, which is an example of “have to stop and think” code, which is best avoided.

A full set of operators like those I mentioned in this post would have to be updated for Swift’s new support of unbounded ranges:

  • <... and ...< half open unbounded
  • ... closed (2 values) or unbounded (1 value) or all numbers of type (0 values)
  • <.. and ..< half open, bounded
  • <.< fully open, bounded

Swift Evolution and Civility

Congratulations to Chris Eidhof for all his work shepherding SE-0199 through Swift Evolution. The proposal adds a mutating toggle function for Boolean values to reduce in-code redundancy and enhance readability.

I’m concerned by some un-collegial reactions to its acceptance, which seem to boil down to “this is too trivial a change to the language” stated through sarcasm and ad-hominem attacks: on Twitter, on the evolution forums, and even a mean-spirited Github repository.

If you are passionate about Swift, I urge you to actively participate in the public review and comment process on forums.swift.org. This proposal passed with overwhelming support and the core team has encouraged similar proposals to fill gaps in the standard library.

The curious case of operator assignment

Fire up a playground or skeleton project, add this code, and attempt to compile it.

let lessThan = <

It won’t compile, and your error should read something along the lines of “unary operator cannot be separated from its operand”. Jared Sinclair discovered this issue the other day when trying to work indirectly with comparison operators.

It’s an odd error message given that the default declaration of  < is infix, not prefix. And he and I spent a bit of time the other day tracking down why this error happened and how to work around it.

To give a larger context, take a look at the following snippet:

struct Foo: Comparable {
    static func fooify(_ string: String) -> String {
        return "foo"
    }
    static func ==(lhs: Foo, rhs: Foo) -> Bool { return true }
    static func <(lhs: Foo, rhs: Foo) -> Bool { return true }
}
typealias Fooquatable = (Foo, Foo) -> Bool

This struct defines three static functions: fooify(_), ==, and <. However, you can access only the fooify member by name:

let foofify = Foo.fooify
let lessThan = Foo.< // use of unresolved operator '.<'

So what do you do if you want to pull some Fooquatable static member into an expression? The answer is to both parenthesize and type the operator:

// Parenthesized and typed
let lessThan: Fooquatable = (<) // works 
let fooperations: [Fooquatable] = [(==), (<)] // Works

// Untyped or non-parenthesized
let fooperations = [(==), (<)] // ambiguous use of operator '=='
let fooperations: [Fooquatable] = [==, <] // expected expression after unary operator
let lessThan = (<) // Ambiguous use of operator '<'

This behavior raises several interesting questions: why does Xcode not see or offer to autocomplete static operator implementations, why does it produce the “unary” error message for an infix operator, and why are those parentheses needed?

Xcode does not, at least at this time, include static operator implementations in its completion list. Member operators cannot be referenced using dot syntax (SR-7155). Autocomplete excludes both < and == and you cannot refer to Foo.< or Foo.== in code.

Swift’s “unary” error messages seem to derive from its tokenizer (SR-7131):

if (OperEndLoc == Tok.getLoc())
 diagnose(PreviousLoc, diag::expected_expr_after_unary_operator);
 else
 diagnose(PreviousLoc, diag::expected_prefix_operator)
 .fixItRemoveChars(OperEndLoc, Tok.getLoc());

It’s built in that after the previous operator’s end location, there is a space so it goes to the else clause. A standalone < or == following an assignment wants another token for unary application, which it does not get, rather than treating this as a static method reference. The remove-characters fixit somewhat pointlessly deletes any comment and newline that follows the operator.

The parentheses bypass ambiguity. Adding parentheses, whether in a standalone assignment or as part of a collection of operators, allows the compiler to recognize the operator as a static method. Explicit typing is still needed since you can’t refer to Foo.<.

Jared Sinclair and I tried a lot of workarounds beyond parentheses that all failed:

  • Foo.< did not work, even though operators are not Swift sugar and are full static members.
  • Foo.(<) failed as invalid syntax.
  • Foo[keyPath: \<] and its parenthesized variations were also failures. (“expected expression path in Swift key path”)
  • < as a standalone operator failed as the compiler was unable to resolve adjacent operators. Attempting to manipulate relative precedence had no effect. The compiler never interpreted < as an expression.
  • You cannot try to game the system with “clever” workarounds like: let lessThan: Fooquatable = { return <}() or let lessThan: Fooquatable = { return <; }().
  • (<) worked because the parentheses created an explicit expression value, so there was sufficient disambiguation for the compilation to proceed.

Have any further thoughts? Drop a note and let me know or add to the comments at bugs.swift.org.

Update: Mark Lacey has been working on something for “operators as members“.

New to Swift in Xcode 9.3 Beta 4: SE-0075 and SE-0190 allow better configuration testing

Two Swift enhancements (SE-0075 and SE-0190)  better enable you to configure your code for specific target conditions. They’ve gone live in the 4th beta of Xcode 9.3.

SE-0075 introduces a build configuration import test. This test enables you to check whether you can import certain modules, like UIKit or QuartzCore, enabling you to write cross-platform code that compiles regardless of destination. You can test for common scenarios like: “Am I on an Apple platform?” or “Am I on an UIKit-supporting iOS-like platform such as iOS or tvOS”.

All bets for the specificity of the latter check are off as of WWDC this year, but the configuration test should allow you to test “Am I on a Unified UI Platform”, whatever that turns out to be, so long as there’s a common module, such as UXKit shared across platforms.

It might help to think of this as module-wide protocol conformance. If the platform conforms to a module and can import it, then the code can be built with access to all its APIs.

#if canImport(UIKit)
    // UIKit-based code
#elseif canImport(Cocoa)
    // OSX code
#elseif
    // Workaround/text, whatever
#endif

Before adopting this proposal, testing !(os(Linux) was too brittle. It assumed a binary system of Apple-systems and Linux (and there are many more Swift destinations now). Enumerating every current Apple or non-Apple platform available at a given time is simply not future-proof. Tying the build configuration to a module, establishes a link between available APIs and the ability to import the API’s parent module.

This one turned out to be a really hard one to implement and all the credit goes to Robert Widmann, Rintaro Ishizaki, Ben Cohen, and Jordan Rose (and anyone else who pitched in) for turning an idea into a reality. This was also one of the proposals that gave rise to the new “implement first, propose second” policy that currently governs Swift Evolution. If you want to thank anyone it’s them, not me.

SE-0190 wasn’t as complicated, but it’s still Graydon Hoare who did all the work on making this happen while I was out of commission this past autumn.  In a nutshell, you can use a new platform condition targetEnvironment to test whether your code is running on a simulator and exclude code you know won’t work there.

Until now, you had to use brittle solutions like (arch(i386) || arch(x86_64)) && (!os(macOS)) to check for simulator deployment and (arch(i386) || arch(x86_64)) && os(iOS) specifically for the iOS simulator.  Now you can use #if targetEnvironment(simulator)instead (or its inverse, using !). The design is intentionally wordy to allow additional environment tests to be added at some future date.

So thanks to everyone who made this happen, especially when I could not.