linuxgemini's space of text

I talk about software and more. Sometimes in English, bazen de Türkçe.

Endpoint: https://pttws.ptt.gov.tr/cepptt/mssnvrPttaceaemaa/gonderitakipvepostakod/gonderisorguYurticiveYurtDisi

Request Method: GET

Query Strings

  • barkod: (13 alphanumerical characters long tracking code) RXEXAMPLE00TR
  • tokenIdBildirim: (likely pushnotif uuid, leave empty) ''
  • kaynak: ANDROID or IOS

Headers

  • Content-Type: application/json
  • User-Agent: ek.ptt
  • App-Version: unknown

Warning

Although the returned data is JSON, server response Content-Type is text/plain for some reason.

Python Example

import requests
import json

trackingcode = "RXEXAMPLE00TR"

url = f"https://pttws.ptt.gov.tr/cepptt/mssnvrPttaceaemaa/gonderitakipvepostakod/gonderisorguYurticiveYurtDisi?barkod={trackingcode}&tokenIdBildirim=''&kaynak=ANDROID"

headers = {
  'User-Agent': 'ek.ptt',
  'Content-Type': 'application/json',
  'App-Version': 'unknown'
}

response = requests.request("GET", url, headers=headers)

data = json.loads(response.text)

print(response.text)

Needed:

(r, s, v) is the signature model used.

r can be read on PM3 with the command hf mf rdbl 69 B 4b791bea7bcc

s can be read on PM3 with the command hf mf rdbl 70 B 4b791bea7bcc

v is the UID of the card.

Example:

r is 19505576ED327D8F8870C86B1ED00898

s is BFEDFFF27CC82FC515BA2EEC26050873

and v, which is the UID, is BD2A4146.

Utilize the recover_pk.py script from the root of the Proxmark3 repository, like below:

python3 tools/recover_pk.py BD2A4146 19505576ED327D8F8870C86B1ED00898BFEDFFF27CC82FC515BA2EEC26050873

You'll get an output like below:

linuxgemini@linuxgemini-fx:~/gitworkflow/proxmark3$ python3 tools/recover_pk.py BD2A4146 19505576ED327D8F8870C86B1ED00898BFEDFFF27CC82FC515BA2EEC26050873

Assuming curve=secp128r1
========================
Assuming hash=None
Possible uncompressed Pk(s):
044f6d3f294dea5737f0f46ffee88a356eed95695dd7e0c27a591e6f6f65962baf
04e0a90de0f96a5c99d9bb6dae8252c86591945e886828bac51a20f47e71554a46
Assuming hash=md5
Possible uncompressed Pk(s):
045adce9091c63e52868fa983e518d8b0f8afafd0315a546f60c9c688a09115e51
0452e4e7c195f75e8b8bd0bdbead61ede72017a1c1f48607376c956d0e9c4764ad
Assuming hash=sha1
Possible uncompressed Pk(s):
0412710ae8d4b8383841e25258771d8ae2f15f3f5f0587ef148ea82c96e9bb2ceb
0479eda8ee440bf8a8cade01c52d22ac4c5fc77ca034188d1436190130565c44d2
Assuming hash=sha256
Possible uncompressed Pk(s):
04f6f1f263353789c6276ebf3fe64ea0043c1e8e2e7be204f65f1b133055b26d81
04284dd1719bb62d8368284320673c2fd21d04e815ec6e6f07ff009053f92ed6e5
Assuming hash=sha512
Possible uncompressed Pk(s):
0439cd2bbe5e6c81f388f2fc320dd097f014b33b941e708a50acbdacac8d56afeb
04dce974f5462e4ad2ddb3cfafb640a2ac32923552068c9f7b4e393bf5db397749

Assuming curve=secp128r2
========================
Assuming hash=None
Assuming hash=md5
Assuming hash=sha1
Assuming hash=sha256
Assuming hash=sha512

Compare the Pk outputs with the test cases inside recover_pk.py to see which one will match, in this case its 044F6D3F294DEA5737F0F46FFEE88A356EED95695DD7E0C27A591E6F6F65962BAF which is the Pk of NXP MIFARE Classic EV1.

Warning: This method requires to have the paid version of Google Workspace. And you probably shouldn't have other users in your Google Workspace while using this.

On the Google Admin Console, go to Apps -> Google Workspace -> Gmail.

Go to Advanced Settings on the bottom of the Gmail page.

On the Gmail Advanced Settings page, scroll down to the Routing settings group. Or...

...find the SMTP relay service.

Configure an SMTP relay service to have the settings:

  • Allowed senders: Only addresses in my domains
  • Authentication: Require SMTP authentication checked
  • Encryption: Require TLS encryption checked

Save the settings and now you can set up the SMTP settings on your email client:

  • SMTP Server Address: smtp-relay.gmail.com
  • SMTP Server Port: 587 for STARTTLS, 465 for SSL/TLS
  • SMTP Username: Your Google Workspace account address (with your domain as well, like an@example.com)
  • SMTP Password: Your Google Workspace account password

And done! You can now reply from any other name under your domain.

tl;dr Unobfuscated Compiled Java APIs = Jackpot

Now that Ave wrote about TCKK, its time to talk about my side of things.

I was able to sniff out my TCKK certificate back in 2017 but haven't gotten much deeper ever since.

...till 18th of December, 2020. Within 12 hours, I was able to supersede all my previous work with extremely deep work.

Screenshot of a Java Console Applet (what's not shown: Card Verifiable Certificates and Identity Hashes)

So, how did that happen? Cue e-Government portal logins.

The e-Government portal, e-Devlet, has a login method with TCKK; which I actually use.

The login method is basically a Java Web Applet (fancy way to say dynamic jar download/execution) that interfaces with e-Devlet and the TCKK to sign a challenge nonce and crosscheck the signature.

However, this app is not obfuscated.

And there's a tar like jar packager called jar.

Remove the GUI applet, repackage the rest and there you have it. The basic (and technically the enterprise) API is now accessible to you. Use the TS 13679 standard or decompile the API with FernFlower (included with IntelliJ IDEA) to understand it.

Reading the standard and looking up the API functions it looks like these are accessible without authentication:

  • ID Number
  • ID Serial
  • Name and Surname
  • ID ((Verification)) Certificate
  • ID ((Verification)) Sub-Root Certificate
  • Chip Serial
  • Chip Version Info
  • Hashes of the Identity Security Objects (and salts of the first 3 items of this list)
  • TCKK Version
  • TCKK Template Version

Rest either requires PIN1 (which you know) with Role Authentication (which the reading party has to have), or PIN2 (which you don't know and is only used for the other Electronic Signature Applet.)

This is all I dug up within 2 days! I hope to find more.

Contact

If you're from TUBİTAK and somehow ended up here, feel free to contact me at tckk <kuyruklu a> linuxgemini <nokta> space!

Seriously though.

I am known for writing cursed JavaScript applets but this one, went above my own charts.

So, lets glance over this curse.

        for (const line of dataLines) {
            // ignore comments, some use "%", some use "#"
            if (line.startsWith("%") || line.startsWith("#")) continue;
            // ignore empty lines
            if (line.length === 0 || line.match(/^\s+$/)) continue;
            // if line starts with one of below
            if (line.startsWith("refer:") || line.startsWith("whois:") || line.startsWith("ReferralServer:")) {
                // split line by spaces, ignore the first value (which is the value identifier), join spaces and strip beginning and end spaces
                let stripped = this.__strStrip(line.split(" ").slice(1).join(" "));
                // push the stripped one
                whoisServersRaw.push(stripped);
            }
            // uh, if this is a domain whois result, do some regex magic I cba explaining this
            if (this.__strStrip(line).match(/^\w+ WHOIS Server: /i)) {
                let strippassone = this.__strStrip(line).replace(/^\w+ WHOIS Server: /i, "");
                whoisServersRaw.push(strippassone);
            }
        }

        // well, rwhois not really whois
        for (const server of whoisServersRaw) {
            if (server.startsWith("rwhois://") || server.includes(":4321")) continue;
            whoisServers.push(server.replace("whois://", ""));
        }

WHOIS is a big free for all. Parsing the output for recursive WHOIS is not only important, but a whole other craftwork.

Now, that was referral parsing but uh; how do you even get the right encoded data?

Right, WHOIS doesn't specify an encoding. Luckily, whois(1) comes to rescue. So this became a thing:

                let encoding = (this.__extQuirks[host] ? this.__extQuirks[host].encoding : chardet.detect(data));
                return resolve(iconv.decode(data, encoding));

Then there's the conversion of event-driven Node.js TCP stack to async-await style calls.

Then, there was the simple web app. Well that was easier than the WHOIS client.

w.iye.be is a test instance for the code for new-iwhois.

The code is available at GitHub.

It occured to me while watching the Sega Mega Drive/Genesis demo Overdrive by the demo/art group TiTAN, while I was always amazed with the audiovisual work, this exact moment on the demo gets me thrilling every single time (timestamped embed):

God dammit strobe you're a genius.

The same feeling happens on the 1987-93 intro of Tomorrow's World as well (not a timestamped embed but it happens around the scene transition at 0:20):

IMDB says that the tune was “Written and performed by Joe Campbell and Paul Hart”. A big thanks to them and the graphic design team at the time at the BBC who made the magnificent intro.

This “thrill” comes from multiple angles. Like having a somewhat wide tune knowledge or just having a greater respect to the appreciated work.

Moments like these are also the composer's goal. To make them thrilled to be in the moment, pulling them into the wormhole of whats coming next.

I miss these kinds of productions on today's world.

(I started writing this at the beginning of May 2020, and probably finalizing near July; so yeah be warned.)

Ever since I released my writeup about the (in)security of Türk Telekom's home gateway management, the VoIP config I found stuck in my head.

This led to many attempts to create a large home phone system. I failed hard. However in the process of doing that, I learned how cursed SIP services are and even got a free Cisco IP Phone from an ISP contact.

SIP Trunking not working with...correct data?

SIP servers/gateways never completely follow the actual standards guiding the protocol.

For example; Türk Telekom's “SIP server” is actually an IMS (IP Multimedia Subsystem) gateway from ZTE and sends incoming calls with the tel: URI instead of the usual sip: URI.

Asterisk doesn't support tel: URIs at all. Kamailio kinda does, but breaks very often due to the VoIP config I mentioned above. 3CX worked at the time I tested (around mid 2019), however I really don't like commercial “licensing” of products utilizing SIP.

FreeSWITCH from SignalWire on the other hand... It. just. works.™️ It has its own quirks as well, but I'll go into that a bit later.

There are many issues other than this too, however this is just the beginning of many problems a PBX trunk operator can face.

“I thought pressing 0 would go to the main menu!”

Let's talk about DTMF. But not its analog perspective of it but rather how its (mis)implemented on the digital world.

Today, we have a few different DTMF signaling methods. All comes down to two types.

  • Inband
  • Out-of-band

Inband is still in-call tone-generation. However some implementations do it slightly different than others (ie. event “packets” in the RTP stream (see RFC 4733 and the deprecated RFC 2833)).

Out-of-band is literally done out of RTP. You either send the tone “map” via a SIP INFO or SIP NOTIFY message. In larger telco operations, SS6 and/or SS7 are utilized. (also see RFC 4733 and the deprecated RFC 2833 because somehow both of these contain descriptions for both types????)

On today's VoIP providers, none of them fully detail what method (and how) they support. And that's where the fun starts.

Twilio supports both inband and OOB signaling (as its defined in RFC 2833) however if you do SIP trunking, make sure that you use OOB because most of the time their “inband” doesn't seem to work.

NetGSM, a large Turkish VoIP provider (along with almost all Turkish VoIP providers) supports the good ol' inband only. So if your trunk has a global setting for DTMF, now its time to do this for each trunk.

If you double trunk and have a Cisco phone connected, well good luck.

“OH MY GOD WHAT IS THIS CONFIGURATION”

Well, welcome to the wonderful hell of PBX configuration. Unless you have a polished frontend like FreePBX (which utilizes Asterisk) etc. you need to mess with files. A crap ton of them.

Asterisk is by far the easiest, if you use the legacy dialplan and peer configurations.

FreeSWITCH however, consists of hundreds of XML files interconnected with each other in such way that one variable in one file eventually gets overridden by another file. If you don't check your configuration at least 100 times, you'll probably realize that you have RTP Early Media off and Mixed RTP Codec Negotiation disabled.

Faxing the Fax machine never works as expected

This is a short rant about FreeSWITCH's SpanDSP module. For no certain reason, it only does T.30/38 and both are broken in some ways. I just gave up trying to get it working.

Just LEAVE IT

Yeah, once you set up your trunks and get it to work, never ever look back to it. At least that's what I've done.

For now.

So, I finally made a blog. I have to thank Ave for introducing Writefreely to me.