{"id":694,"date":"2016-11-25T21:21:51","date_gmt":"2016-11-26T04:21:51","guid":{"rendered":"http:\/\/www.mjblythe.com\/hacks\/?p=694"},"modified":"2022-01-04T12:33:18","modified_gmt":"2022-01-04T19:33:18","slug":"packet-sniffing-for-fun-and-profit","status":"publish","type":"post","link":"http:\/\/www.mjblythe.com\/hacks\/2016\/11\/packet-sniffing-for-fun-and-profit\/","title":{"rendered":"Packet sniffing for fun and profit"},"content":{"rendered":"<p><a href=\"http:\/\/www.mjblythe.com\/hacks\/wp-content\/uploads\/2016\/11\/wireshark-capture.png\"><img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-full wp-image-705\" src=\"http:\/\/www.mjblythe.com\/hacks\/wp-content\/uploads\/2016\/11\/wireshark-capture.png\" alt=\"wireshark-capture\" width=\"500\" height=\"500\" \/><\/a><\/p>\n<p>I have a commercial IOT product that I want more control over. Sure, I can control it with the free Android app, but I want my home server to be able to control it, too. This means trying to understand how the app controls it over the network, and attempting to replicate that communication.<\/p>\n<p>This means I have to do some packet sniffing.<\/p>\n<p><!--more--><\/p>\n\n<h2>Simple probing<\/h2>\n<p>First thing first, we&#8217;ll want to figure out what IP address the router has assigned it. This should be as simple as logging on to your router&#8217;s configuration web page &amp; finding the device that you don&#8217;t recognize. If you happen to run DD-WRT on your router, it might look something like this:<\/p>\n<p><a href=\"http:\/\/www.mjblythe.com\/hacks\/wp-content\/uploads\/2016\/11\/wireless-clients.png\"><img loading=\"lazy\" decoding=\"async\" class=\"size-full wp-image-696 alignnone\" src=\"http:\/\/www.mjblythe.com\/hacks\/wp-content\/uploads\/2016\/11\/wireless-clients.png\" alt=\"wireless-clients\" width=\"500\" height=\"305\" srcset=\"http:\/\/www.mjblythe.com\/hacks\/wp-content\/uploads\/2016\/11\/wireless-clients.png 838w, http:\/\/www.mjblythe.com\/hacks\/wp-content\/uploads\/2016\/11\/wireless-clients-300x183.png 300w, http:\/\/www.mjblythe.com\/hacks\/wp-content\/uploads\/2016\/11\/wireless-clients-768x469.png 768w\" sizes=\"auto, (max-width: 500px) 100vw, 500px\" \/><\/a><\/p>\n<p>It just so happens that my target device is listed first: <code>192.168.1.119<\/code><\/p>\n<p>The next thing we can do once we know the IP address is do a port scan using <code>nmap<\/code>. We might get lucky and find that some useful service is exposed.<\/p>\n<p>By default, nmap scans the most common TCP ports:<\/p>\n<blockquote><p><code>&gt; nmap 192.168.1.119<\/code><\/p>\n<p><code><code><\/code><\/code>Starting Nmap 7.12 ( https:\/\/nmap.org ) at 2016-11-25 21:27 MST<br \/>\nNmap scan report for 192.168.1.119<br \/>\nHost is up (0.0015s latency).<br \/>\nAll 1000 scanned ports on 192.168.1.119 are closed<\/p>\n<p><code><br \/>\n<\/code><code>Nmap done: 1 IP address (1 host up) scanned in 7.07 seconds<\/code><\/p><\/blockquote>\n<p>Alternatively, we can specify which ports to scan. Here, I&#8217;m asking it to scan TCP ports 1 thru 10,000:<\/p>\n<blockquote><p><code>&gt; nmap 192.168.1.119 -p 1-10000<\/code><\/p>\n<p><code><code><\/code><\/code>Starting Nmap 7.12 ( https:\/\/nmap.org ) at 2016-11-25 21:28 MST<br \/>\nNmap scan report for 192.168.1.119<br \/>\nHost is up (0.0023s latency).<br \/>\nNot shown: 9999 closed ports<br \/>\nPORT STATE SERVICE<br \/>\n1932\/tcp open unknown<\/p>\n<p><code><br \/>\n<\/code><code>Nmap done: 1 IP address (1 host up) scanned in 53.59 seconds<\/code><\/p><\/blockquote>\n<p>We managed to get lucky, and find an open TCP port! Let&#8217;s connect to it with <code>netcat<\/code> &amp; see what happens:<\/p>\n<blockquote><p><code>&gt; nc 192.168.1.119 1932<\/code><\/p><\/blockquote>\n<p>Unfortunately, it presented no welcome message, and any commands I tried got no response.<\/p>\n<p>Next, let&#8217;s scan the UDP ports to see what pops out. This requires root permissions, and it takes a while. By default, it will increase the time between port probes since it&#8217;s not receiving any responses, so we need to add some <a href=\"http:\/\/security.stackexchange.com\/a\/52581\">additional options<\/a> to speed things along:<\/p>\n<blockquote><p><code>&gt; sudo nmap 192.168.1.119 -sU -p 1-20000 --max-scan-delay 150ms --max-retries 2 --max-rtt-timeout 150ms --min-rate 200<\/code><\/p>\n<p><code><code><\/code><\/code>Starting Nmap 7.12 ( https:\/\/nmap.org ) at 2016-11-25 22:09 MST<br \/>\nWarning: 192.168.1.119 giving up on port because retransmission cap hit (2).<br \/>\nNmap scan report for 192.168.1.119<br \/>\nHost is up (0.0048s latency).<br \/>\nNot shown: 19995 closed ports<br \/>\nPORT STATE SERVICE<br \/>\n25\/udp open|filtered smtp<br \/>\n80\/udp open|filtered http<br \/>\n4096\/udp open|filtered bre<br \/>\n10619\/udp open|filtered unknown<br \/>\n13450\/udp open|filtered unknown<br \/>\nMAC Address: 38:2B:78:00:EB:B3 (ECO Plugs Enterprise)<\/p>\n<p><code><br \/>\n<\/code><code>Nmap done: 1 IP address (1 host up) scanned in 199.26 seconds<\/code><\/p><\/blockquote>\n<p>Again, we can try to connect to these UDP ports with netcat:<\/p>\n<blockquote><p><code>&gt; nc -u 192.168.1.119 25<\/code><\/p><\/blockquote>\n<p>No welcome messages, and no interesting responses to anything I sent.<\/p>\n<p>Time to move along to&#8230;<\/p>\n<h2>Intercepting traffic out to the wider Internet<\/h2>\n<p>High-end routers have a &#8220;monitor port&#8221; feature. Basically, any traffic that flows through the router will be copied to this port so that the traffic can be analyzed. Unfortunately, consumer-grade routers don&#8217;t often have anythign like this.<\/p>\n<p>However, some consumer routers (like the ancient Linksys WRT54GL that I use) can run custom Linux firmware, which can approximate this feature. <a href=\"https:\/\/www.question-defense.com\/2010\/02\/04\/use-wireshark-and-dd-wrt-router-firmware-to-imitate-port-monitoring-on-a-router-switch-port\">This post<\/a> (<a href=\"https:\/\/web.archive.org\/web\/20160417212850\/http:\/\/www.question-defense.com\/2010\/02\/04\/use-wireshark-and-dd-wrt-router-firmware-to-imitate-port-monitoring-on-a-router-switch-port\">cached here<\/a>) describes how to set up some firewall rules so we can observe traffic flowing through our router. The main limitation of this is that we&#8217;ll only monitor traffic that&#8217;s entering or leaving the internal network, not any traffic that stays on the subnet (because this local routing happens in a dedicated routing chip; it isn&#8217;t touched by any Linux software).<\/p>\n<p>An aside: my DD-WRT install is really old, and only supports a weak ssh key exchange protocol. It must be manually enabled like this: <code>ssh -oKexAlgorithms=+diffie-hellman-group1-sha1 root@192.168.1.1<\/code><\/p>\n<p>Before adding our rules, there will probably be nothing:<\/p>\n<blockquote><p><code># iptables -t mangle -L<br \/>\nChain PREROUTING (policy ACCEPT)<br \/>\ntarget     prot opt source               destination         <\/code><\/p>\n<p><code><code><\/code><\/code>Chain INPUT (policy ACCEPT)<br \/>\ntarget prot opt source destination<\/p>\n<p><code><code><\/code><\/code>Chain FORWARD (policy ACCEPT)<br \/>\ntarget prot opt source destination<\/p>\n<p><code><code><\/code><\/code>Chain OUTPUT (policy ACCEPT)<br \/>\ntarget prot opt source destination<\/p>\n<p><code><br \/>\n<\/code><code>Chain POSTROUTING (policy ACCEPT)<br \/>\ntarget     prot opt source               destination     <\/code><\/p><\/blockquote>\n<p>Add our rules, then make sure they&#8217;ve been applied:<\/p>\n<blockquote><p><code># iptables -t mangle -A POSTROUTING -d 192.168.1.119 -j ROUTE --tee --gw 192.168.1.102<br \/>\n# iptables -t mangle -A PREROUTING -s 192.168.1.119 -j ROUTE --tee --gw 192.168.1.102<br \/>\n# iptables -t mangle -L<br \/>\nChain PREROUTING (policy ACCEPT)<br \/>\ntarget     prot opt source               destination<br \/>\nROUTE      0    --  192.168.1.119        anywhere            ROUTE gw:192.168.1.102 tee<\/code><\/p>\n<p><code><code><\/code><\/code>Chain INPUT (policy ACCEPT)<br \/>\ntarget prot opt source destination<\/p>\n<p><code><code><\/code><\/code>Chain FORWARD (policy ACCEPT)<br \/>\ntarget prot opt source destination<\/p>\n<p><code><code><\/code><\/code>Chain OUTPUT (policy ACCEPT)<br \/>\ntarget prot opt source destination<\/p>\n<p><code><br \/>\n<\/code><code>Chain POSTROUTING (policy ACCEPT)<br \/>\ntarget     prot opt source               destination<br \/>\nROUTE      0    --  anywhere             192.168.1.119       ROUTE gw:192.168.1.102 tee<\/code><\/p><\/blockquote>\n<p>Aside #2: in order to run wrieshark as an unprivileged user, do the following:<\/p>\n<blockquote><p><code>&gt; sudo dpkg-reconfigure wireshark-common<br \/>\n#Select Should non-superusers be able to capture packets?  \"yes\"<br \/>\n&gt; sudo usermod -a -G wireshark your-username-here<\/code><\/p><\/blockquote>\n<p>Group settings only take effect at the nest login. So, either log out and in again, or run <code>su your-username-here<\/code> to get a single terminal with the new group applied.<\/p>\n<p>With that in place, we can launch wireshark now. The starting screen should look something like this:<\/p>\n<p><a href=\"http:\/\/www.mjblythe.com\/hacks\/wp-content\/uploads\/2016\/11\/wireshark-startup.png\"><img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-full wp-image-706\" src=\"http:\/\/www.mjblythe.com\/hacks\/wp-content\/uploads\/2016\/11\/wireshark-startup.png\" alt=\"wireshark-startup\" width=\"500\" height=\"500\" \/><\/a><\/p>\n<p>Select the interface you want to monitor (<code>eth0<\/code> for me), and enter in an appropriate capture filter (<code>host 192.168.1.119<\/code> will capture the packets to and from that IP), then hit enter. It should start capturing packets:<\/p>\n<p><a href=\"http:\/\/www.mjblythe.com\/hacks\/wp-content\/uploads\/2016\/11\/wireshark-capture.png\"><img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-full wp-image-705\" src=\"http:\/\/www.mjblythe.com\/hacks\/wp-content\/uploads\/2016\/11\/wireshark-capture.png\" alt=\"wireshark-capture\" width=\"500\" height=\"500\" \/><\/a><\/p>\n<p>Once you&#8217;ve done some interesting activities (restart the unit to observe its initial connections, perform come operations, etc), you can press the red square to stop the capture. At this time, you can dig into the individual packets, or save the capture off to analyze later.<\/p>\n<p>Now that we&#8217;re done with the monitoring, we should delete the firewall rules (and confirm that they have been deleted):<\/p>\n<blockquote><p><code># iptables -t mangle -D POSTROUTING -d 192.168.1.119 -j ROUTE --tee --gw 192.168.1.102<br \/>\n# iptables -t mangle -D PREROUTING -s 192.168.1.119 -j ROUTE --tee --gw 192.168.1.102<br \/>\n# iptables -t mangle -L<br \/>\nChain PREROUTING (policy ACCEPT)<br \/>\ntarget     prot opt source               destination         <\/code><\/p>\n<p><code><code><\/code><\/code>Chain INPUT (policy ACCEPT)<br \/>\ntarget prot opt source destination<\/p>\n<p><code><code><\/code><\/code>Chain FORWARD (policy ACCEPT)<br \/>\ntarget prot opt source destination<\/p>\n<p><code><code><\/code><\/code>Chain OUTPUT (policy ACCEPT)<br \/>\ntarget prot opt source destination<\/p>\n<p><code><br \/>\n<\/code><code>Chain POSTROUTING (policy ACCEPT)<br \/>\ntarget     prot opt source               destination         <\/code><\/p><\/blockquote>\n<h2>Intercepting WiFi traffic<\/h2>\n<p>Of course, you may want to see more of the traffic that&#8217;s being sent by the device. How is it interacting with other devices on your home network? How does it communicate with the cell phone app when the &#8220;cloud&#8221; feature is disabled?<\/p>\n<p>This one is tricky, mostly because we&#8217;ll need a WiFi adaptor that allows us to capture packets that aren&#8217;t intended for us. I tried a few laptops that I had laying around, and none of them seemed to work as well as I had hoped. However, I found that <a href=\"https:\/\/www.adafruit.com\/products\/814\">this USB WiFi adaptor<\/a> works pretty well for me.<\/p>\n<p>Unfortunately, I don&#8217;t think there&#8217;s a way to directly capture with <code>wireshark<\/code> (if there is, please let me know!). I&#8217;ll use <code>airodump-ng<\/code> to dump the traffic, then use <code>wireshark<\/code> to analyze it afterwards.<\/p>\n<p>First, we should check if there are any programs running that might interfere with our capture:<\/p>\n<blockquote><p><code>&gt; sudo airmon-ng check<br \/>\nFound 2 processes that could cause trouble.<br \/>\nIf airodump-ng, aireplay-ng or airtun-ng stops working after<br \/>\na short period of time, you may want to kill (some of) them!<\/code><\/p>\n<p><code><br \/>\n<\/code><code>PID\tName<br \/>\n1005\tavahi-daemon<br \/>\n1020\tavahi-daemon<\/code><\/p><\/blockquote>\n<p>If you want, you can use <code>sudo airmon-ng check kill<\/code> to terminate these processes. I&#8217;ve found that these <code>avahi-daemon<\/code> processes don&#8217;t cause problems. If you&#8217;re running <code>NetworkManager<\/code>, you will want to stop that with this command: <code>sudo service NetworkManager stop<\/code><\/p>\n<p>Next, we need to put the WiFi adaptor into <a href=\"https:\/\/wiki.wireshark.org\/CaptureSetup\/WLAN#Linux\">monitor mode<\/a>, so it will just listen to all packets:<\/p>\n<blockquote><p><code>&gt; sudo airmon-ng start wlan0<br \/>\nFound 2 processes that could cause trouble.<br \/>\nIf airodump-ng, aireplay-ng or airtun-ng stops working after<br \/>\na short period of time, you may want to kill (some of) them!<\/code><\/p>\n<p><code><code><\/code><\/code>PID Name<br \/>\n1005 avahi-daemon<br \/>\n1020 avahi-daemon<\/p>\n<p><code><br \/>\n<\/code><code>Interface\tChipset\t\tDriver<br \/>\nwlan0\t\tUnknown \trtl8192cu - [phy0]<br \/>\n(monitor mode enabled on mon0)<\/code><\/p><\/blockquote>\n<p>This creates a virtual <code>mon0<\/code> interface which is actually the one we&#8217;ll capture on (instead of <code>wlan0<\/code>)<\/p>\n<p>Now, we&#8217;ll need some information about our WiFi network. Specifically, the BSSID (hardware address of the access point), and which WiFi channel it&#8217;s using. DD-WRT gives me this information on the &#8220;Wireless&#8221; tab:<\/p>\n<p><a href=\"http:\/\/www.mjblythe.com\/hacks\/wp-content\/uploads\/2016\/11\/wifi-settings.png\"><img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-full wp-image-708\" src=\"http:\/\/www.mjblythe.com\/hacks\/wp-content\/uploads\/2016\/11\/wifi-settings.png\" alt=\"wifi-settings\" width=\"500\" height=\"233\" srcset=\"http:\/\/www.mjblythe.com\/hacks\/wp-content\/uploads\/2016\/11\/wifi-settings.png 615w, http:\/\/www.mjblythe.com\/hacks\/wp-content\/uploads\/2016\/11\/wifi-settings-300x140.png 300w\" sizes=\"auto, (max-width: 500px) 100vw, 500px\" \/><\/a><\/p>\n<p>Using that information, we&#8217;ll run the <a href=\"https:\/\/ask.wireshark.org\/questions\/13713\/capture-wlan-traffic-using-wireshark\/13750\">following command<\/a>:<\/p>\n<blockquote><p><code>sudo airodump-ng -c 6 --bssid xx:xx:xx:xx:BD:E1 -w dumpfile mon0<\/code><\/p><\/blockquote>\n<p>Where:<\/p>\n<ul>\n<li><code>-c 6<\/code> is the WiFi channel we&#8217;re listening on<\/li>\n<li><code>--bssid xx:xx:xx:xx:BD:E1<\/code> is the hardware address of the access point (the real hardware address&#8230;no &#8220;x&#8221;&#8230;that&#8217;s just to censor my information<\/li>\n<li><code>-w dumpfile<\/code> is the filename where the captures packets are written<\/li>\n<li><code>mon0<\/code> is the virtual interface that we created with airmon-ng<\/li>\n<\/ul>\n<p>While this command is running, it will print various commands to the screen. When you think you&#8217;ve captured what you need, terminate the capture with <code>ctrl+C<\/code>.<\/p>\n<p>It is important that this capture observes the device-in-question <a href=\"https:\/\/ask.wireshark.org\/questions\/17200\/sniff-wpa2-network\">negotiating its initial connection<\/a> to the access point. This can obviously be forced by power-cycling the device, but you may also be able to use <code>aireplay-ng<\/code> to send &#8220;deauth&#8221; packets that would cause the device to re-negotiate.<\/p>\n<p>Now that we&#8217;ve completed the capture, we&#8217;ll need to <a href=\"https:\/\/wiki.wireshark.org\/HowToDecrypt802.11\">set up wireshark<\/a> to be able to decrypt it.<\/p>\n<p>Click on <code>Edit-&gt;Preferences...<\/code>, then navigate to the <code>Protocols-&gt;802.11<\/code> page. It should look like this:<\/p>\n<p><a href=\"http:\/\/www.mjblythe.com\/hacks\/wp-content\/uploads\/2016\/11\/wireshark-wifi-settings.png\"><img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-full wp-image-710\" src=\"http:\/\/www.mjblythe.com\/hacks\/wp-content\/uploads\/2016\/11\/wireshark-wifi-settings.png\" alt=\"wireshark-wifi-settings\" width=\"500\" height=\"355\" srcset=\"http:\/\/www.mjblythe.com\/hacks\/wp-content\/uploads\/2016\/11\/wireshark-wifi-settings.png 705w, http:\/\/www.mjblythe.com\/hacks\/wp-content\/uploads\/2016\/11\/wireshark-wifi-settings-300x213.png 300w\" sizes=\"auto, (max-width: 500px) 100vw, 500px\" \/><\/a><\/p>\n<p>Here, click on Edit&#8230; to open this window, and add your WiFi credentials:<\/p>\n<p><a href=\"http:\/\/www.mjblythe.com\/hacks\/wp-content\/uploads\/2016\/11\/wireshark-wifi-key.png\"><img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-full wp-image-709\" src=\"http:\/\/www.mjblythe.com\/hacks\/wp-content\/uploads\/2016\/11\/wireshark-wifi-key.png\" alt=\"wireshark-wifi-key\" width=\"500\" height=\"377\" srcset=\"http:\/\/www.mjblythe.com\/hacks\/wp-content\/uploads\/2016\/11\/wireshark-wifi-key.png 568w, http:\/\/www.mjblythe.com\/hacks\/wp-content\/uploads\/2016\/11\/wireshark-wifi-key-300x226.png 300w\" sizes=\"auto, (max-width: 500px) 100vw, 500px\" \/><\/a><\/p>\n<p>Once that&#8217;s done, you can open the capture file that was created by <code>airodump-ng<\/code>, and you should be able to see the decrypted traffic (here I&#8217;m using a <a href=\"https:\/\/wiki.wireshark.org\/DisplayFilters\">display filter<\/a> of <code>ip.addr==192.168.1.119<\/code> to focus on the traffic to the device I care about):<\/p>\n<p><a href=\"http:\/\/www.mjblythe.com\/hacks\/wp-content\/uploads\/2016\/11\/wireshark-wifi-capture.png\"><img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-full wp-image-711\" src=\"http:\/\/www.mjblythe.com\/hacks\/wp-content\/uploads\/2016\/11\/wireshark-wifi-capture.png\" alt=\"wireshark-wifi-capture\" width=\"500\" height=\"493\" srcset=\"http:\/\/www.mjblythe.com\/hacks\/wp-content\/uploads\/2016\/11\/wireshark-wifi-capture.png 918w, http:\/\/www.mjblythe.com\/hacks\/wp-content\/uploads\/2016\/11\/wireshark-wifi-capture-300x296.png 300w, http:\/\/www.mjblythe.com\/hacks\/wp-content\/uploads\/2016\/11\/wireshark-wifi-capture-768x757.png 768w\" sizes=\"auto, (max-width: 500px) 100vw, 500px\" \/><\/a><\/p>\n<p>Once you&#8217;re done with the capture, disable the monitoring interface:<\/p>\n<blockquote><p><code>&gt; sudo airmon-ng stop wlan0<\/code><\/p><\/blockquote>\n<p>Also, if you disabled <code>NetworkManager<\/code> earlier, you&#8217;ll want to re-enable it like this: <code>sudo service NetworkManager start<\/code><\/p>\n","protected":false},"excerpt":{"rendered":"<p>I have a commercial IOT product that I want more control over. Sure, I can control it with the free Android app, but I want my home server to be able to control it, too. This means trying to understand how the app controls it over the network, and attempting to replicate that communication. This [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_monsterinsights_skip_tracking":false,"_monsterinsights_sitenote_active":false,"_monsterinsights_sitenote_note":"","_monsterinsights_sitenote_category":0,"footnotes":""},"categories":[7,11,14],"tags":[],"class_list":["post-694","post","type-post","status-publish","format-standard","hentry","category-howto","category-linux","category-reverse-engineering"],"_links":{"self":[{"href":"http:\/\/www.mjblythe.com\/hacks\/wp-json\/wp\/v2\/posts\/694","targetHints":{"allow":["GET"]}}],"collection":[{"href":"http:\/\/www.mjblythe.com\/hacks\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"http:\/\/www.mjblythe.com\/hacks\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"http:\/\/www.mjblythe.com\/hacks\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"http:\/\/www.mjblythe.com\/hacks\/wp-json\/wp\/v2\/comments?post=694"}],"version-history":[{"count":14,"href":"http:\/\/www.mjblythe.com\/hacks\/wp-json\/wp\/v2\/posts\/694\/revisions"}],"predecessor-version":[{"id":1123,"href":"http:\/\/www.mjblythe.com\/hacks\/wp-json\/wp\/v2\/posts\/694\/revisions\/1123"}],"wp:attachment":[{"href":"http:\/\/www.mjblythe.com\/hacks\/wp-json\/wp\/v2\/media?parent=694"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"http:\/\/www.mjblythe.com\/hacks\/wp-json\/wp\/v2\/categories?post=694"},{"taxonomy":"post_tag","embeddable":true,"href":"http:\/\/www.mjblythe.com\/hacks\/wp-json\/wp\/v2\/tags?post=694"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}