OnionFarm was one of the challenges in UUTCTF which was held in 25-28 April 2019 by Urmia University of Technology. The challenge has been solved by 4 teams. Following, the challenge details and the write up is discussed.
OnionFarm
The challenge said that the flag is inside the following link: http://uutctfysirwosxjx.onion/

The link is a hidden service and it starts with http. Therefore, it should be opened by TOR. Using Tor Browser, the page is loaded.

As it is shown in the above picture, There is a flag signed by a private key (in base64) and SHA-1 hash of its public key is given.
Signed Flag: Y94QDVNr0kOeu3j2cdqOuGyUb+V1KZXMQiEWNktf3g46TeEmKjc9MI4Ox2WaK/JNV433E9VWMAOXGC79hpZ0WO6pfQurBtcoqYj3dCZRKESGY0V4LCxkE6r+NSKZf0HxaYVsMV6uIXEQIKORO+DWCWI2gVNvD4K+Mw4vbHcxpRs=
SHA-1 of the public key:
uutctfysirwosxjxadwzgzy34lrhjknq
But the SHA-1 signature is not in familiar form. Instead the first 16 chars of SHA-1 hash is the same as the hidden web service name:
http://uutctfysirwosxjx.onion/
The TOR System
In version 2 of the onion addresses in TOR system, the onion link is 16 first chars of the public key of the hidden service, encoded in base32 address. Therefore, the main task is getting the public key of this hidden service. TOR itself gives a control port for controlling TOR. Stem is a python library for interacting with TOR control port. Following code from github link, can be used for getting the hidden service descriptors (information).
import sys import argparse import stem from stem.control import Controller def main(): parser = argparse.ArgumentParser(description="%s fetches a Tor hidden " "service descriptor." % sys.argv[0]) parser.add_argument("-p", "--port", type=int, default=9051, help="Tor controller port") parser.add_argument('onion_address', type=str, help='Onion address') args = parser.parse_args() with Controller.from_port(port=args.port) as controller: controller.authenticate() try: hs_descriptor = controller.get_hidden_service_descriptor(args.onion_address) print(hs_descriptor) except stem.DescriptorUnavailable: print("Descriptor not found, the hidden service may be offline.") return 1 if __name__ == '__main__': sys.exit(main())
Using the above code, one can fetch the public key for the hidden service.


The Flag
We’ve found the public key, but the problem is that it is in RSA PUBLIC KEY format. Openssl accepts PEM format which should be PUBLIC KEY. Therefor we need to convert the RSA public key in a readable format. First of all the base64 encoded text, is in ASN.1 format. Using tools such as ASN1JS, public key bytes and modulus can be gained. The online version of ASN1JS is available in jsfiddle website.

Now we have public key (138865786359602944891762156467560871881909108828375427630579384292773) and modulus (527482743). We need to form an PEM file. With the public key and modulus bytes, we can form an XML format. In the following picture, I just show the modulus. The same procedure is done for public key.

In final stage, we need a tool to convert XML format to PEM. I’ve used Superdry Developer .

The final public key in PEM format is:
—–BEGIN PUBLIC KEY—– MIGgMA0GCSqGSIb3DQEBAQUAA4GOADCBigKBgQDFwF6gXXDrPMhAi/3ePAaGtY3h hknEorJT3oXu6qBBPdKjjMTLEw504BsNKzCxGWOG+477WgLaB4KTncupQ65EawXm TjzWX99ongOq32cuuHYjl7LGuqVfzf1uQqjIZpftJouzAxOXq9h3qE2wI0xRVFPH
YIiOat+jhhNG2jkknwIEH3C/dw==
—–END PUBLIC KEY—–
Now we should pass flag to openssl and verify the flag using it, but first we need to base64 decode the flag.

Voila! The flag is: UUTCTF{hIdden_0ni0ns_should_be_harvested}
heh, what a lame
“signing ≠ encryption”
Yes, it was signed by private key. So the public key was needed to verify the signature (decryption).