{"id":2039,"date":"2018-01-25T18:50:50","date_gmt":"2018-01-25T09:50:50","guid":{"rendered":"http:\/\/haisins.epac.to\/wordpress\/?p=2039"},"modified":"2021-10-29T22:59:51","modified_gmt":"2021-10-29T13:59:51","slug":"oracle12c","status":"publish","type":"post","link":"http:\/\/haisins.synology.me\/wordpress\/?p=2039","title":{"rendered":"[Oracle 12c] Oracle DB \uc720\uc800\uc758 \ud328\uc2a4\uc6cc\ub4dc \uc800\uc7a5 \uc554\ud638\ud654 \uc54c\uace0\ub9ac\uc998 \ubcc0\uacbd"},"content":{"rendered":"<p><span style=\"color: #ff0000;\">\uc624\ub77c\ud074 12c \ubd80\ud130 DB \uc720\uc800\uc758 \ud328\uc2a4\uc6cc\ub4dc \uc800\uc7a5 \uc54c\uace0\ub9ac\uc998\uc774 SHA512\ub97c \uc0ac\uc6a9\ud558\uac8c \ub418\uc5c8\uc2b5\ub2c8\ub2e4.<\/span><\/p>\n<p><span style=\"color: #ff0000;\">Oracle 11g \ub294 SHA1 11g password algorithm \uc744 \uc0ac\uc6a9 \ud558\uc600\uc2b5\ub2c8\ub2e4.<\/span><\/p>\n<p><a href=\"https:\/\/docs.oracle.com\/cd\/E25054_01\/network.1111\/e16543\/authentication.htm#CHDEFIHB\">https:\/\/docs.oracle.com\/cd\/E25054_01\/network.1111\/e16543\/authentication.htm#CHDEFIHB<\/a><\/p>\n<p><b>Ensuring Against Password Security Threats by Using the SHA-1 Hashing Algorithm<\/b><\/p>\n<p>\u201cThe<a name=\"sthref253\"><\/a> SHA-1 <a name=\"sthref254\"><\/a><a name=\"sthref255\"><\/a>cryptographic hashing algorithm protects against password-based security threats by including support for mixed case characters, special characters, and multibyte characters in passwords. In addition, the SHA-1 hashing algorithm adds a <a href=\"https:\/\/docs.oracle.com\/cd\/E25054_01\/network.1111\/e16543\/glossary.htm#BGBJABIG\"><b>salt<\/b><\/a> to the password when it is hashed, which provides additional protection. This enables your users to create far more complex passwords, and therefore, makes it more difficult for an intruder to gain access to these passwords. <a name=\"sthref256\"><\/a>Oracle recommends that you use <b>the SHA-1 hashing algorithm<\/b>.\u201d<\/p>\n<p>&nbsp;<\/p>\n<h4>The procedure for generating a 11g hash<\/h4>\n<ul>\n<li>An 10 bytes SALT gets generated by Oracle (looks random)<\/li>\n<li>Password (case-sensitive) and SALT (10 bytes) value become concatinated<\/li>\n<li>A SHA1 hash gets generated for the concatinated value<\/li>\n<li>11g password hash becomes: \u201cS:\u201d plus &lt;<em>SHA1 hash \u2013 readable hex representation<\/em>&gt; plus &lt;<em>SALT \u2013 readable hex representation<\/em>, 20 characters&gt;<\/li>\n<\/ul>\n<p>&nbsp;<\/p>\n<p><span style=\"color: #ff0000;\"><strong>Oracle 10g \ub294 3DES password\u00a0 algorithm \uc744 \uc0ac\uc6a9 \ud558\uc600\uc2b5\ub2c8\ub2e4.<\/strong><\/span><\/p>\n<h4>The procedure used for generating a 10g hash<\/h4>\n<ul>\n<li>Convert username to uppercase version of username (username sys becomes SYS)<\/li>\n<li>Convert password to uppercase version of password (password test becomes TEST)<\/li>\n<li>Capatilized username and password gets concatinated (username SYS with password TEST becomes SYSTEST)<\/li>\n<li>Encrypt (using 3DES algorithm) concatinated value with a (permanent \u2013 always the same) secret key<\/li>\n<li>Encrypt (using 3DES algorithm) concatinated value with a secret key (this key are the last 8 bytes of the first encryption)<\/li>\n<li>The actual password hash value will be the last 8 bytes of the second encryption round, stored in a readable hex representation of these 8 bytes \u2013 so 16 characters)<\/li>\n<\/ul>\n<h4><\/h4>\n<p>Oracle 12c \ud14c\uc2a4\ud2b8<\/p>\n<p><a title=\"https:\/\/www.trustwave.com\/Resources\/SpiderLabs-Blog\/Changes-in-Oracle-Database-12c-password-hashes\/\" href=\"https:\/\/www.trustwave.com\/Resources\/SpiderLabs-Blog\/Changes-in-Oracle-Database-12c-password-hashes\/\">https:\/\/www.trustwave.com\/Resources\/SpiderLabs-Blog\/Changes-in-Oracle-Database-12c-password-hashes\/<\/a><\/p>\n<p>&nbsp;<\/p>\n<p>Oracle has made improvements to user password hashes within Oracle Database 12c. By using a PBKDF2-based SHA512 hashing algorithm, instead of simple SHA1 hash, password hashing is more secure. With this post, I&#8217;ll explain some of the changes and their security implications.<\/p>\n<p>With Oracle Database 11g, the <\/p>\n<pre class=\"inline:true decode:1 \">spare4<\/pre>\n<p> column from the <\/p>\n<pre class=\"inline:true decode:1 \">sys.user$<\/pre>\n<p> table stores user password hashes.<\/p>\n<p>This is an example of the <\/p>\n<pre class=\"inline:true decode:1 \">sys.user$.spare4<\/pre>\n<p> entry for user &#8216;<\/p>\n<pre class=\"inline:true decode:1 \">demo<\/pre>\n<p>&#8216; with password &#8216;<\/p>\n<pre class=\"inline:true decode:1 \">epsilon<\/pre>\n<p>&#8216; (pluggable database):<\/p>\n<pre class=\"inline:true decode:1 \">S:8F2D65FB5547B71C8DA3760F10960428CD307B1C6271691FC55C1F56554A;H:DC9894A01797D91D92ECA1DA66242209;T:23D1F8CAC9001F69630ED2DD8DF67DD3BE5C470B5EA97B622F757FE102D8BF14BEDC94A3CC046D10858D885DB656DC0CBF899A79CD8C76B788744844CADE54EEEB4FDEC478FB7C7CBFBBAC57BA3EF22C<\/pre>\n<p>Step-by-step:<\/p>\n<pre class=\"inline:true decode:1 \">SQL&amp;gt; create user demo identified by epsilon;<\/pre>\n<pre class=\"inline:true decode:1 \">User created.<\/pre>\n<pre class=\"inline:true decode:1 \">SQL&amp;gt; select spare4 from sys.user$ where name = 'DEMO';<\/pre>\n<pre class=\"inline:true decode:1 \">SPARE4<\/pre>\n<pre class=\"inline:true decode:1 \">--------------------------------------------------------------------------------<\/pre>\n<pre class=\"inline:true decode:1 \">S:8F2D65FB5547B71C8DA3760F10960428CD307B1C6271691FC55C1F56554A;H:DC9894A01797D91D92ECA1DA66242209;T:23D1F8CAC9001F69630ED2DD8DF67DD3BE5C470B5EA97B622F757FE102D8BF14BEDC94A3CC046D10858D885DB656DC0CBF899A79CD8C76B788744844CADE54EEEB4FDEC478FB7C7CBFBBAC57BA3EF22C<\/pre>\n<pre class=\"inline:true decode:1 \">sys.user$.password<\/pre>\n<p> value for the same user:<\/p>\n<pre class=\"inline:true decode:1 \">SQL&amp;gt; select password from sys.user$ where name = 'DEMO';<\/pre>\n<pre class=\"inline:true decode:1 \">PASSWORD<\/pre>\n<pre class=\"inline:true decode:1 \">--------------------------------------------------------------------------------<\/pre>\n<pre class=\"inline:true decode:1 \">2B7983437FE9FEB6<\/pre>\n<p>This will omit the <\/p>\n<pre class=\"inline:true decode:1 \">password<\/pre>\n<p> value discussion: it is calculated using the same algorithm (uppercase and concatenate username and password then do 3DES hashing) as in previous Oracle Database versions.<\/p>\n<p>The <\/p>\n<pre class=\"inline:true decode:1 \">spare4<\/pre>\n<p> column&#8217;s value has three parts (&#8220;<\/p>\n<pre class=\"inline:true decode:1 \">S:<\/pre>\n<p>&#8220;, &#8220;<\/p>\n<pre class=\"inline:true decode:1 \">H:<\/pre>\n<p>&#8220;, and &#8220;<\/p>\n<pre class=\"inline:true decode:1 \">T:<\/pre>\n<p>&#8220;) separated by semicolons.<\/p>\n<p>The &#8220;<\/p>\n<pre class=\"inline:true decode:1 \">S:<\/pre>\n<p>&#8221; part length is 60 characters or 30 bytes:<\/p>\n<pre class=\"inline:true decode:1 \">8F2D65FB5547B71C8DA3760F10960428CD307B1C6271691FC55C1F56554A<\/pre>\n<p>The &#8220;<\/p>\n<pre class=\"inline:true decode:1 \">H:<\/pre>\n<p>&#8221; part length is 32 characters or 16 bytes:<\/p>\n<pre class=\"inline:true decode:1 \">DC9894A01797D91D92ECA1DA66242209<\/pre>\n<p>Finally, the &#8220;<\/p>\n<pre class=\"inline:true decode:1 \">T:<\/pre>\n<p>&#8221; part length is 160 characters or 80 bytes:<\/p>\n<pre class=\"inline:true decode:1 \">23D1F8CAC9001F69630ED2DD8DF67DD3BE5C470B5EA97B622F757FE102D8BF14BEDC94A3CC046D10858D885DB656DC0CBF899A79CD8C76B788744844CADE54EEEB4FDEC478FB7C7CBFBBAC57BA3EF22C<\/pre>\n<p>So what do they mean exactly?<\/p>\n<h6>The S part<\/h6>\n<p>In Oracle Database 11g there is &#8220;<\/p>\n<pre class=\"inline:true decode:1 \">S:<\/pre>\n<p>&#8221; part and it is created as follows:<\/p>\n<pre class=\"inline:true decode:1 \">password hash (20 bytes) = sha1(password + salt (10 bytes))<\/pre>\n<p>(Visit <a href=\"http:\/\/marcel.vandewaters.nl\/oracle\/security\/password-hashes\">http:\/\/marcel.vandewaters.nl\/oracle\/security\/password-hashes<\/a>for more detail.)<\/p>\n<p>The same is true of Oracle Database 12c: the simple test below proves that.<\/p>\n<p>For the <\/p>\n<pre class=\"inline:true decode:1 \">S<\/pre>\n<p> value from above (<\/p>\n<pre class=\"inline:true decode:1 \">8F2D65FB5547B71C8DA3760F10960428CD307B1C6271691FC55C1F56554A<\/pre>\n<p>):<\/p>\n<p>hash is <\/p>\n<pre class=\"inline:true decode:1 \">8F2D65FB5547B71C8DA3760F10960428CD307B1C\r\n<\/pre>\n<p>salt is <\/p>\n<pre class=\"inline:true decode:1 \">6271691FC55C1F56554A<\/pre>\n<p>Password is &#8220;<\/p>\n<pre class=\"inline:true decode:1 \">epsilon<\/pre>\n<p>&#8220;, so let&#8217;s calculate SHA1 hash from <\/p>\n<pre class=\"inline:true decode:1 \">'epsilon' + 0x6271691FC55C1F56554A<\/pre>\n<p>:<\/p>\n<pre class=\"inline:true decode:1 \">import hashlib<\/pre>\n<pre class=\"inline:true decode:1 \">sha1 = hashlib.sha1()<\/pre>\n<pre class=\"inline:true decode:1 \">sha1.update(&quot;epsilon&quot;)<\/pre>\n<pre class=\"inline:true decode:1 \">sha1.update('\\x62\\x71\\x69\\x1f\\xc5\\x5c\\x1f\\x56\\x55\\x4a')<\/pre>\n<pre class=\"inline:true decode:1 \">sha1.hexdigest().upper()<\/pre>\n<p>That calculation produces:<\/p>\n<p>&#8216;<\/p>\n<pre class=\"inline:true decode:1 \">8F2D65FB5547B71C8DA3760F10960428CD307B1C<\/pre>\n<p>&#8216;<\/p>\n<p>This is identical to the 11g algorithm.<\/p>\n<h6>The H part<\/h6>\n<p>When looking through SQL files under <\/p>\n<pre class=\"inline:true decode:1 \">$ORACLE_HOME\/rdbms\/admin<\/pre>\n<p> one can spot this:<\/p>\n<pre class=\"inline:true decode:1 \">create or replace view DBA_DIGEST_VERIFIERS<\/pre>\n<pre class=\"inline:true decode:1 \">&nbsp; (USERNAME, HAS_DIGEST_VERIFIERS, DIGEST_TYPE) as<\/pre>\n<pre class=\"inline:true decode:1 \">select u.name, 'YES', 'MD5' from user$ u where instr(spare4, 'H:')&amp;gt;0<\/pre>\n<pre class=\"inline:true decode:1 \">union<\/pre>\n<pre class=\"inline:true decode:1 \">select u.name, 'NO', NULL from user$ u where not(instr(spare4, 'H:')&amp;gt;0) or spare4 is null<\/pre>\n<pre class=\"inline:true decode:1 \">\/<\/pre>\n<p>So it appears to be a MD5 hash.<\/p>\n<p>Note that there is SQL code under <\/p>\n<pre class=\"inline:true decode:1 \">$ORACLE_HOME\/rdbms\/admin<\/pre>\n<p> that modifies the <\/p>\n<pre class=\"inline:true decode:1 \">spare4<\/pre>\n<p> column&#8217;s value to remove the <\/p>\n<pre class=\"inline:true decode:1 \">H:<\/pre>\n<p> on downgrade.<\/p>\n<p>This is how <\/p>\n<pre class=\"inline:true decode:1 \">spare4.H<\/pre>\n<p> is calculated: the username is uppercased, then the MD5 hash is calculated from it, and &#8216;<\/p>\n<pre class=\"inline:true decode:1 \">XDB<\/pre>\n<p>&#8216; and password are separated by colons:<\/p>\n<pre class=\"inline:true decode:1 \">import hashlib<\/pre>\n<pre class=\"inline:true decode:1 \">m = hashlib.md5()<\/pre>\n<pre class=\"inline:true decode:1 \">m.update('DEMO:XDB:epsilon')<\/pre>\n<pre class=\"inline:true decode:1 \">m.hexdigest().upper()<\/pre>\n<pre class=\"inline:true decode:1 \">'DC9894A01797D91D92ECA1DA66242209'<\/pre>\n<p>This makes it possible to attack built-in user passwords using pre calculated hashes for dictionary words prefixed with constants like &#8216;<\/p>\n<pre class=\"inline:true decode:1 \">SYSTEM:XDB:<\/pre>\n<p>&#8216;.<\/p>\n<p>The <\/p>\n<pre class=\"inline:true decode:1 \">H<\/pre>\n<p> value seems to be used for digest authentication in XDB.<\/p>\n<h6>The T part<\/h6>\n<p>This applies to 12.1.0.2 only. For previous 12c versions the T part is not available.<\/p>\n<p>Let&#8217;s enable 12c passwords hashes only by updating the <\/p>\n<pre class=\"inline:true decode:1 \">sqlnet.ora<\/pre>\n<p> file (assuming the client is from 12.1.0.2 distribution too):<\/p>\n<pre class=\"inline:true decode:1 \"># sqlnet.ora<\/pre>\n<pre class=\"inline:true decode:1 \">SQLNET.ALLOWED_LOGON_VERSION_SERVER = 12a<\/pre>\n<p>Then re-create the demo user (reconnect the client first):<\/p>\n<pre class=\"inline:true decode:1 \">drop user demo;<\/pre>\n<pre class=\"inline:true decode:1 \">create user demo identified by epsilon;<\/pre>\n<pre class=\"inline:true decode:1 \">select spare4 from sys.user$ where name = 'DEMO';<\/pre>\n<pre class=\"inline:true decode:1 \">H:DC9894A01797D91D92ECA1DA66242209;T:E3243B98974159CC24FD2C9A8B30BA62E0E83B6CA2FC7C55177C3A7F82602E3BDD17CEB9B9091CF9DAD672B8BE961A9EAC4D344BDBA878EDC5DCB5899F689EBD8DD1BE3F67BFF9813A464382381AB36B<\/pre>\n<p>Note that the <\/p>\n<pre class=\"inline:true decode:1 \">spare4<\/pre>\n<p> value no longer has the <\/p>\n<pre class=\"inline:true decode:1 \">S:<\/pre>\n<p> part, only the <\/p>\n<pre class=\"inline:true decode:1 \">H:<\/pre>\n<p> and <\/p>\n<pre class=\"inline:true decode:1 \">T:<\/pre>\n<p> components are there.<br \/>\nIn Oracle Database 12c documentation we can find this:<\/p>\n<blockquote><p>About the 12C Verifier<\/p><\/blockquote>\n<blockquote><p>&#8230; is based on a de-optimized algorithm involving PBKDF2 and SHA512&#8230;<\/p><\/blockquote>\n<p>So the password should be processed via PBKDF2 followed by SHA512 to produce <\/p>\n<pre class=\"inline:true decode:1 \">T<\/pre>\n<p>.<\/p>\n<p>During authentication the server sends so called <\/p>\n<pre class=\"inline:true decode:1 \">AUTH_VFR_DATA<\/pre>\n<p> (which matches the last 16 bytes of the <\/p>\n<pre class=\"inline:true decode:1 \">spare4.T<\/pre>\n<p> value) to the client:<\/p>\n<pre class=\"inline:true decode:1 \">-- Server to client packet snippet<\/pre>\n<pre class=\"inline:true decode:1 \">39 39 39 00 00 00 00 0D-00 00 00 0D 41 55 54 48 999.........AUTH<\/pre>\n<pre class=\"inline:true decode:1 \">5F 56 46 52 5F 44 41 54-41 20 00 00 00 20 38 44 _VFR_DATA.....8D<\/pre>\n<pre class=\"inline:true decode:1 \">44 31 42 45 33 46 36 37-42 46 46 39 38 31 33 41 D1BE3F67BFF9813A<\/pre>\n<pre class=\"inline:true decode:1 \">34 36 34 33 38 32 33 38-31 41 42 33 36 42 15 48 464382381AB36B.H<\/pre>\n<p>So we can divide the <\/p>\n<pre class=\"inline:true decode:1 \">T<\/pre>\n<p> value into two parts (first 64 bytes and the <\/p>\n<pre class=\"inline:true decode:1 \">AUTH_VFR_DATA<\/pre>\n<p>):<\/p>\n<pre class=\"inline:true decode:1 \">E3243B98974159CC24FD2C9A8B30BA62E0E83B6CA2FC7C55177C3A7F82602E3BDD17CEB9B9091CF9DAD672B8BE961A9EAC4D344BDBA878EDC5DCB5899F689EBD<\/pre>\n<p> (first 128 chars or 64 bytes)<\/p>\n<pre class=\"inline:true decode:1 \">8DD1BE3F67BFF9813A464382381AB36B<\/pre>\n<p> (last 32 chars or 16 bytes &#8211; <\/p>\n<pre class=\"inline:true decode:1 \">AUTH_VFR_DATA<\/pre>\n<p>)<\/p>\n<p>Let&#8217;s assume that the <\/p>\n<pre class=\"inline:true decode:1 \">AUTH_VFR_DATA<\/pre>\n<p> is randomly generated when a password is set\/reset. Thus Python code to produce the first 64 bytes of <\/p>\n<pre class=\"inline:true decode:1 \">T<\/pre>\n<p> is (requires <a href=\"https:\/\/www.dlitz.net\/software\/python-pbkdf2\/\">PBKDF2 Python module<\/a>):<\/p>\n<pre class=\"inline:true decode:1 \">import pbkdf2, hashlib<\/pre>\n<pre class=\"inline:true decode:1 \">AUTH_VFR_DATA = b'\\x8d\\xd1\\xbe\\x3f\\x67\\xbf\\xf9\\x81\\x3a\\x46\\x43\\x82\\x38\\x1a\\xb3\\x6b' # This is received from the server once the latest protocol is negotiated<\/pre>\n<pre class=\"inline:true decode:1 \">salt = AUTH_VFR_DATA + b'AUTH_PBKDF2_SPEEDY_KEY'<\/pre>\n<pre class=\"inline:true decode:1 \">key = pbkdf2.PBKDF2(&quot;epsilon&quot;, salt, 4096, hashlib.sha512) # Password<\/pre>\n<pre class=\"inline:true decode:1 \">key_64bytes = key.read(64) # This 64-byte derived key is encrypted by the client and sent to the server as AUTH_PBKDF2_SPEEDY_KEY<\/pre>\n<pre class=\"inline:true decode:1 \">t = hashlib.sha512() # This happens on the server after they key is decrypted from the AUTH_PBKDF2_SPEEDY_KEY value<\/pre>\n<pre class=\"inline:true decode:1 \">t.update(key_64bytes)<\/pre>\n<pre class=\"inline:true decode:1 \">t.update(AUTH_VFR_DATA)<\/pre>\n<pre class=\"inline:true decode:1 \">t.hexdigest().upper() # First 64 bytes of spare4.T: value if password is correct<\/pre>\n<p>This produces:<\/p>\n<pre class=\"inline:true decode:1 \">E3243B98974159CC24FD2C9A8B30BA62E0E83B6CA2FC7C55177C3A7F82602E3BDD17CEB9B9091CF9DAD672B8BE961A9EAC4D344BDBA878EDC5DCB5899F689EBD<\/pre>\n<h6>Summing up<\/h6>\n<p>Oracle has added MD5 hash and PBKDF2-based SHA512 hash in 12c. A quote from Oracle documentation:<\/p>\n<blockquote><p>The cryptographic hash function used for generating the <\/p>\n<pre class=\"inline:true decode:1 \">12C<\/pre>\n<p> verifier is based on a de-optimized algorithm involving PBKDF2 and SHA-512. The PBKDF2 algorithm is used to introduce computational asymmetry in the challenge facing an intruder seeking to recover the original password when in possession of the <\/p>\n<pre class=\"inline:true decode:1 \">12C<\/pre>\n<p> verifier.<\/p><\/blockquote>\n<p>When the MD5 hash is there it weakens security since it is easier to brute force than the PBKDF2-based SHA512 alone.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>\uc624\ub77c\ud074 12c \ubd80\ud130 DB \uc720\uc800\uc758 \ud328\uc2a4\uc6cc\ub4dc \uc800\uc7a5 \uc54c\uace0\ub9ac\uc998\uc774 SHA512\ub97c \uc0ac\uc6a9\ud558\uac8c \ub418\uc5c8\uc2b5\ub2c8\ub2e4. Oracle 11g \ub294 SHA1 11g password algorithm \uc744 \uc0ac\uc6a9 \ud558\uc600\uc2b5\ub2c8\ub2e4. https:\/\/docs.oracle.com\/cd\/E25054_01\/network.1111\/e16543\/authentication.htm#CHDEFIHB Ensuring Against Password Security Threats by Using the SHA-1 Hashing Algorithm \u201cThe SHA-1 cryptographic hashing algorithm protects against password-based security threats by including support for mixed case characters, special characters, and multibyte characters [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":2069,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_bbp_topic_count":0,"_bbp_reply_count":0,"_bbp_total_topic_count":0,"_bbp_total_reply_count":0,"_bbp_voice_count":0,"_bbp_anonymous_reply_count":0,"_bbp_topic_count_hidden":0,"_bbp_reply_count_hidden":0,"_bbp_forum_subforum_count":0,"_monsterinsights_skip_tracking":false,"_monsterinsights_sitenote_active":false,"_monsterinsights_sitenote_note":"","_monsterinsights_sitenote_category":0,"spay_email":""},"categories":[20],"tags":[16],"jetpack_featured_media_url":"https:\/\/i0.wp.com\/haisins.synology.me\/wordpress\/wp-content\/uploads\/2018\/01\/oracle-database-upgrade-12c.jpg?fit=625%2C325","amp_enabled":true,"_links":{"self":[{"href":"http:\/\/haisins.synology.me\/wordpress\/index.php?rest_route=\/wp\/v2\/posts\/2039"}],"collection":[{"href":"http:\/\/haisins.synology.me\/wordpress\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"http:\/\/haisins.synology.me\/wordpress\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"http:\/\/haisins.synology.me\/wordpress\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"http:\/\/haisins.synology.me\/wordpress\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=2039"}],"version-history":[{"count":7,"href":"http:\/\/haisins.synology.me\/wordpress\/index.php?rest_route=\/wp\/v2\/posts\/2039\/revisions"}],"predecessor-version":[{"id":4511,"href":"http:\/\/haisins.synology.me\/wordpress\/index.php?rest_route=\/wp\/v2\/posts\/2039\/revisions\/4511"}],"wp:featuredmedia":[{"embeddable":true,"href":"http:\/\/haisins.synology.me\/wordpress\/index.php?rest_route=\/wp\/v2\/media\/2069"}],"wp:attachment":[{"href":"http:\/\/haisins.synology.me\/wordpress\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=2039"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"http:\/\/haisins.synology.me\/wordpress\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=2039"},{"taxonomy":"post_tag","embeddable":true,"href":"http:\/\/haisins.synology.me\/wordpress\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=2039"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}