Facebook CTF 2019 featured quite a fair number of challenges. I played this weekend (and spent far more time than I’d like to admit) with some coworkers and interns. Here’s the writeup to the crypto challenge keybaseish.
Visiting the website gave me the following landing page:
Trying to register a new account gives an error:
Poking around doesn’t yield much, as this is a crypto challenge and not a (eeuuugh) web challenge. However, I was pretty sure that the Forgot your password?
option was where I’d find the flag:
First thing I did was take a look at the Twitter page given:
The Twitter handle @baseishcoinfou1 only has a few tweets. Based off of the description given on the Forgot your password?
page, I assume I have to somehow spoof myself as that baseishcoinfou1 guy to log in.
The script given to generate a signature from the pin on the page:
sign.py
1 | from Crypto.PublicKey import RSA |
Looks like a simple RSA problem! I like RSA problems since they’re (more or less) straightforward and simple if you understand the math behind RSA.
Just to test the script, I ran it:
1 | python sign.py |
Somehow, I feel like there weren’t supposed to be escapes for the newlines, but oh well. Everything seems to check out here.
So the idea seems to be that by supplying the website with a public key that matches the signature with a given pin, then I can verify my identity. This is pretty poor security, obviously, especially given the fact that I have control over the exponent (which I stupidly overlooked for at least several hours). The equation for the signature is as follows:
1 | pin = signature^e mod n |
I have the pin given to me by the website, the signature from the Twitter page of baseishcoinfou1, and the exponent. All I need is a valid n
.
For the exponent, I’ll choose 5
. Why 5
? It is relatively low and means that when I exponentiate the signature, the n
can be represented by the same number of bits. Basically:
1 | kn + pin = signature^e |
In my case, I’m going to assume k = 1
, making the problem very trivial. In effect:
1 | n = signature^e - pin |
I wrote a short Python script to calculate this:
solve.py
1 | # Signature from the Twitter page of baseishcoinfou1 |
Running the script yields the following public key:
1 | 5:156152259934610603327242777109298638373934572320003018946780705593035129444427250712903196953268692654576940252842426080729553952653677882004392693966587497895771126063209172520687408155983845138814448218643812756870429001677159139697312185528286445629870220439486395991895413533025617686453330864683812555753179156400433858871091471963735884941049381029699284926525734780530683371637232542486580601832498002442370205259218637335066255536340402863614960635863279257288993952331758568563539255171752333659803630559976542479997459049186400474006649599261061239561731085004017823362429679461455596473090496147014713630612514413037251048846131962952608974559597665037989589516588758915639505296076818565509671460227096392858914958248349719519761080165615153613390888909577250254133864459387364823840496709605537195438529272540877498372727188018102166924786597538072319044503910010189326796934513137869684765977644563798377464844285519970335294217160696344254550102370879793030817756422968722131250375494110628633064924047523515038128770714301615363185342011455425978139447595336835379107137242896370138133354739730815895341370949542102301040465958437918589288157598747503502123011375289921007339937318514618737528870366815796019608309972031321180211231027906387141262192775078672105433479871010768651433527003348326639168952600370384527925162635252188830536959099871687232387447443824170080109823399109258223217519865552564954330502656132579024379460503613264612232039663908389480448494284442261160415871697947245392343456421606992172540775590 |
When inputting this as the public key into the form, I get the flag.