mirror of
https://github.com/sqlmapproject/sqlmap.git
synced 2026-10-12 02:22:55 +00:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
d465007dfe | ||
|
|
26c8423806 | ||
|
|
26cb07cc26 | ||
|
|
48c55d15ea | ||
|
|
1e03b23ccb | ||
|
|
70168855f9 | ||
|
|
7567ed2f71 | ||
|
|
33c110ac39 | ||
|
|
43eedb63a8 | ||
|
|
4eb5bbd75d | ||
|
|
07e6a0a079 | ||
|
|
4e938ea4fd | ||
|
|
fcb31b85b6 | ||
|
|
e0940438b3 | ||
|
|
01e915e199 | ||
|
|
ba7ab21596 | ||
|
|
bbf7472b42 | ||
|
|
ff61417fc0 | ||
|
|
14bf1e4ce7 | ||
|
|
c4e3ce1dac | ||
|
|
9a0a803025 | ||
|
|
9b46540e00 | ||
|
|
e7469ab570 | ||
|
|
10fe87fb4e | ||
|
|
bb7bd51d94 | ||
|
|
da15701a55 | ||
|
|
6b063e708e | ||
|
|
ba96261a28 | ||
|
|
552077f379 | ||
|
|
0f697418d9 | ||
|
|
bc5b643700 | ||
|
|
282d4b2bea | ||
|
|
9289939ced | ||
|
|
6831031cf7 | ||
|
|
6dc37628a0 | ||
|
|
7c7ecc75ec | ||
|
|
77cb85f2b8 | ||
|
|
9459d5ea15 | ||
|
|
1eeb6c1f5b | ||
|
|
bdf6452af6 | ||
|
|
3127d5bf54 | ||
|
|
9043d9dd05 | ||
|
|
faf154d2b3 | ||
|
|
9958d77572 | ||
|
|
dcb8025f30 | ||
|
|
4b0edeb199 | ||
|
|
ef42495318 | ||
|
|
4d93712c4d | ||
|
|
1ed59267df | ||
|
|
3cb48ffdc3 | ||
|
|
40393b29a0 | ||
|
|
1f0fb7ab48 | ||
|
|
05f92d5d45 | ||
|
|
89c6cc725b | ||
|
|
3275d9c709 | ||
|
|
f445fbe75b |
+3
-1
@@ -1,6 +1,8 @@
|
||||
*.py[cod]
|
||||
output/
|
||||
__pycache__/
|
||||
*.py[cod]
|
||||
.sqlmap_history
|
||||
traffic.txt
|
||||
*~
|
||||
req*.txt
|
||||
.idea/
|
||||
@@ -764,6 +764,9 @@ ultramegaman, <seclists(at)ultramegaman.com>
|
||||
Vinicius, <viniciusmaxdaloop(at)gmail.com>
|
||||
* for reporting a minor bug
|
||||
|
||||
virusdefender
|
||||
* for contributing WAF scripts safeline.py
|
||||
|
||||
w8ay
|
||||
* for contributing an implementation for chunked transfer-encoding (switch --chunked)
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# sqlmap
|
||||
|
||||
[](https://travis-ci.org/sqlmapproject/sqlmap) [](https://www.python.org/) [](https://raw.githubusercontent.com/sqlmapproject/sqlmap/master/LICENSE) [](https://twitter.com/sqlmap)
|
||||
[](https://travis-ci.org/sqlmapproject/sqlmap) [](https://www.python.org/) [](https://raw.githubusercontent.com/sqlmapproject/sqlmap/master/LICENSE) [](https://badge.fury.io/py/sqlmap) [](https://github.com/sqlmapproject/sqlmap/issues?q=is%3Aissue+is%3Aclosed) [](https://twitter.com/sqlmap)
|
||||
|
||||
sqlmap e инструмент за тестване и проникване, с отворен код, който автоматизира процеса на откриване и използване на недостатъците на SQL база данните чрез SQL инжекция, която ги взима от сървъра. Снабден е с мощен детектор, множество специални функции за най-добрия тестер и широк спектър от функции, които могат да се използват за множество цели - извличане на данни от базата данни, достъп до основната файлова система и изпълняване на команди на операционната система.
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# sqlmap
|
||||
|
||||
[](https://travis-ci.org/sqlmapproject/sqlmap) [](https://www.python.org/) [](https://raw.githubusercontent.com/sqlmapproject/sqlmap/master/LICENSE) [](https://twitter.com/sqlmap)
|
||||
[](https://travis-ci.org/sqlmapproject/sqlmap) [](https://www.python.org/) [](https://raw.githubusercontent.com/sqlmapproject/sqlmap/master/LICENSE) [](https://badge.fury.io/py/sqlmap) [](https://github.com/sqlmapproject/sqlmap/issues?q=is%3Aissue+is%3Aclosed) [](https://twitter.com/sqlmap)
|
||||
|
||||
sqlmap es una herramienta para pruebas de penetración "penetration testing" de software libre que automatiza el proceso de detección y explotación de fallos mediante inyección de SQL además de tomar el control de servidores de bases de datos. Contiene un poderoso motor de detección, así como muchas de las funcionalidades escenciales para el "pentester" y una amplia gama de opciones desde la recopilación de información para identificar el objetivo conocido como "fingerprinting" mediante la extracción de información de la base de datos, hasta el acceso al sistema de archivos subyacente para ejecutar comandos en el sistema operativo a través de conexiones alternativas conocidas como "Out-of-band".
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# sqlmap
|
||||
|
||||
[](https://travis-ci.org/sqlmapproject/sqlmap) [](https://www.python.org/) [](https://raw.githubusercontent.com/sqlmapproject/sqlmap/master/LICENSE) [](https://twitter.com/sqlmap)
|
||||
[](https://travis-ci.org/sqlmapproject/sqlmap) [](https://www.python.org/) [](https://raw.githubusercontent.com/sqlmapproject/sqlmap/master/LICENSE) [](https://badge.fury.io/py/sqlmap) [](https://github.com/sqlmapproject/sqlmap/issues?q=is%3Aissue+is%3Aclosed) [](https://twitter.com/sqlmap)
|
||||
|
||||
**sqlmap** est un outil Open Source de test d'intrusion. Cet outil permet d'automatiser le processus de détection et d'exploitation des failles d'injection SQL afin de prendre le contrôle des serveurs de base de données. __sqlmap__ dispose d'un puissant moteur de détection utilisant les techniques les plus récentes et les plus dévastatrices de tests d'intrusion comme L'Injection SQL, qui permet d'accéder à la base de données, au système de fichiers sous-jacent et permet aussi l'exécution des commandes sur le système d'exploitation.
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# sqlmap
|
||||
|
||||
[](https://travis-ci.org/sqlmapproject/sqlmap) [](https://www.python.org/) [](https://raw.githubusercontent.com/sqlmapproject/sqlmap/master/LICENSE) [](https://twitter.com/sqlmap)
|
||||
[](https://travis-ci.org/sqlmapproject/sqlmap) [](https://www.python.org/) [](https://raw.githubusercontent.com/sqlmapproject/sqlmap/master/LICENSE) [](https://badge.fury.io/py/sqlmap) [](https://github.com/sqlmapproject/sqlmap/issues?q=is%3Aissue+is%3Aclosed) [](https://twitter.com/sqlmap)
|
||||
|
||||
Το sqlmap είναι πρόγραμμα ανοιχτού κώδικα, που αυτοματοποιεί την εύρεση και εκμετάλλευση ευπαθειών τύπου SQL Injection σε βάσεις δεδομένων. Έρχεται με μια δυνατή μηχανή αναγνώρισης ευπαθειών, πολλά εξειδικευμένα χαρακτηριστικά για τον απόλυτο penetration tester όπως και με ένα μεγάλο εύρος επιλογών αρχίζοντας από την αναγνώριση της βάσης δεδομένων, κατέβασμα δεδομένων της βάσης, μέχρι και πρόσβαση στο βαθύτερο σύστημα αρχείων και εκτέλεση εντολών στο απευθείας στο λειτουργικό μέσω εκτός ζώνης συνδέσεων.
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# sqlmap
|
||||
|
||||
[](https://travis-ci.org/sqlmapproject/sqlmap) [](https://www.python.org/) [](https://raw.githubusercontent.com/sqlmapproject/sqlmap/master/LICENSE) [](https://twitter.com/sqlmap)
|
||||
[](https://travis-ci.org/sqlmapproject/sqlmap) [](https://www.python.org/) [](https://raw.githubusercontent.com/sqlmapproject/sqlmap/master/LICENSE) [](https://badge.fury.io/py/sqlmap) [](https://github.com/sqlmapproject/sqlmap/issues?q=is%3Aissue+is%3Aclosed) [](https://twitter.com/sqlmap)
|
||||
|
||||
sqlmap je alat namijenjen za penetracijsko testiranje koji automatizira proces detekcije i eksploatacije sigurnosnih propusta SQL injekcije te preuzimanje poslužitelja baze podataka. Dolazi s moćnim mehanizmom za detekciju, mnoštvom korisnih opcija za napredno penetracijsko testiranje te široki spektar opcija od onih za prepoznavanja baze podataka, preko dohvaćanja podataka iz baze, do pristupa zahvaćenom datotečnom sustavu i izvršavanja komandi na operacijskom sustavu korištenjem tzv. "out-of-band" veza.
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# sqlmap
|
||||
|
||||
[](https://travis-ci.org/sqlmapproject/sqlmap) [](https://www.python.org/) [](https://raw.githubusercontent.com/sqlmapproject/sqlmap/master/LICENSE) [](https://twitter.com/sqlmap)
|
||||
[](https://travis-ci.org/sqlmapproject/sqlmap) [](https://www.python.org/) [](https://raw.githubusercontent.com/sqlmapproject/sqlmap/master/LICENSE) [](https://badge.fury.io/py/sqlmap) [](https://github.com/sqlmapproject/sqlmap/issues?q=is%3Aissue+is%3Aclosed) [](https://twitter.com/sqlmap)
|
||||
|
||||
sqlmap merupakan alat _(tool)_ bantu _open source_ dalam melakukan tes penetrasi yang mengotomasi proses deteksi dan eksploitasi kelemahan _SQL injection_ dan pengambil-alihan server basisdata. sqlmap dilengkapi dengan pendeteksi canggih, fitur-fitur hanal bagi _penetration tester_, beragam cara untuk mendeteksi basisdata, hingga mengakses _file system_ dan mengeksekusi perintah dalam sistem operasi melalui koneksi _out-of-band_.
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# sqlmap
|
||||
|
||||
[](https://travis-ci.org/sqlmapproject/sqlmap) [](https://www.python.org/) [](https://raw.githubusercontent.com/sqlmapproject/sqlmap/master/LICENSE) [](https://twitter.com/sqlmap)
|
||||
[](https://travis-ci.org/sqlmapproject/sqlmap) [](https://www.python.org/) [](https://raw.githubusercontent.com/sqlmapproject/sqlmap/master/LICENSE) [](https://badge.fury.io/py/sqlmap) [](https://github.com/sqlmapproject/sqlmap/issues?q=is%3Aissue+is%3Aclosed) [](https://twitter.com/sqlmap)
|
||||
|
||||
sqlmap è uno strumento open source per il penetration testing. Il suo scopo è quello di rendere automatico il processo di scoperta ed exploit di vulnerabilità di tipo SQL injection al fine di compromettere database online. Dispone di un potente motore per la ricerca di vulnerabilità, molti strumenti di nicchia anche per il più esperto penetration tester ed un'ampia gamma di controlli che vanno dal fingerprinting di database allo scaricamento di dati, fino all'accesso al file system sottostante e l'esecuzione di comandi nel sistema operativo attraverso connessioni out-of-band.
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# sqlmap
|
||||
|
||||
[](https://travis-ci.org/sqlmapproject/sqlmap) [](https://www.python.org/) [](https://raw.githubusercontent.com/sqlmapproject/sqlmap/master/LICENSE) [](https://twitter.com/sqlmap)
|
||||
[](https://travis-ci.org/sqlmapproject/sqlmap) [](https://www.python.org/) [](https://raw.githubusercontent.com/sqlmapproject/sqlmap/master/LICENSE) [](https://badge.fury.io/py/sqlmap) [](https://github.com/sqlmapproject/sqlmap/issues?q=is%3Aissue+is%3Aclosed) [](https://twitter.com/sqlmap)
|
||||
|
||||
sqlmapはオープンソースのペネトレーションテスティングツールです。SQLインジェクションの脆弱性の検出、活用、そしてデータベースサーバ奪取のプロセスを自動化します。
|
||||
強力な検出エンジン、ペネトレーションテスターのための多くのニッチ機能、持続的なデータベースのフィンガープリンティングから、データベースのデータ取得やアウトオブバンド接続を介したオペレーティング・システム上でのコマンド実行、ファイルシステムへのアクセスなどの広範囲に及ぶスイッチを提供します。
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# sqlmap
|
||||
|
||||
[](https://travis-ci.org/sqlmapproject/sqlmap) [](https://www.python.org/) [](https://raw.githubusercontent.com/sqlmapproject/sqlmap/master/LICENSE) [](https://twitter.com/sqlmap)
|
||||
[](https://travis-ci.org/sqlmapproject/sqlmap) [](https://www.python.org/) [](https://raw.githubusercontent.com/sqlmapproject/sqlmap/master/LICENSE) [](https://badge.fury.io/py/sqlmap) [](https://github.com/sqlmapproject/sqlmap/issues?q=is%3Aissue+is%3Aclosed) [](https://twitter.com/sqlmap)
|
||||
|
||||
sqlmap to open sourceowe narzędzie do testów penetracyjnych, które automatyzuje procesy detekcji, przejmowania i testowania odporności serwerów SQL na podatność na iniekcję niechcianego kodu. Zawiera potężny mechanizm detekcji, wiele niszowych funkcji dla zaawansowanych testów penetracyjnych oraz szeroki wachlarz opcji począwszy od identyfikacji bazy danych, poprzez wydobywanie z nich danych, a nawet pozwalającuch na dostęp do systemu plików o uruchamianie poleceń w systemie operacyjnym serwera poprzez niestandardowe połączenia.
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# sqlmap
|
||||
|
||||
[](https://travis-ci.org/sqlmapproject/sqlmap) [](https://www.python.org/) [](https://raw.githubusercontent.com/sqlmapproject/sqlmap/master/LICENSE) [](https://twitter.com/sqlmap)
|
||||
[](https://travis-ci.org/sqlmapproject/sqlmap) [](https://www.python.org/) [](https://raw.githubusercontent.com/sqlmapproject/sqlmap/master/LICENSE) [](https://badge.fury.io/py/sqlmap) [](https://github.com/sqlmapproject/sqlmap/issues?q=is%3Aissue+is%3Aclosed) [](https://twitter.com/sqlmap)
|
||||
|
||||
sqlmap é uma ferramenta de teste de penetração de código aberto que automatiza o processo de detecção e exploração de falhas de injeção SQL. Com essa ferramenta é possível assumir total controle de servidores de banco de dados em páginas web vulneráveis, inclusive de base de dados fora do sistema invadido. Ele possui um motor de detecção poderoso, empregando as últimas e mais devastadoras técnicas de teste de penetração por SQL Injection, que permite acessar a base de dados, o sistema de arquivos subjacente e executar comandos no sistema operacional.
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# sqlmap
|
||||
|
||||
[](https://travis-ci.org/sqlmapproject/sqlmap) [](https://www.python.org/) [](https://raw.githubusercontent.com/sqlmapproject/sqlmap/master/LICENSE) [](https://twitter.com/sqlmap)
|
||||
[](https://travis-ci.org/sqlmapproject/sqlmap) [](https://www.python.org/) [](https://raw.githubusercontent.com/sqlmapproject/sqlmap/master/LICENSE) [](https://badge.fury.io/py/sqlmap) [](https://github.com/sqlmapproject/sqlmap/issues?q=is%3Aissue+is%3Aclosed) [](https://twitter.com/sqlmap)
|
||||
|
||||
sqlmap - это инструмент для тестирования уязвимостей с открытым исходным кодом, который автоматизирует процесс обнаружения и использования ошибок SQL-инъекций и захвата серверов баз данных. Он оснащен мощным механизмом обнаружения, множеством приятных функций для профессионального тестера уязвимостей и широким спектром скриптов, которые упрощают работу с базами данных, от сбора данных из базы данных, до доступа к базовой файловой системе и выполнения команд в операционной системе через out-of-band соединение.
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# sqlmap
|
||||
|
||||
[](https://travis-ci.org/sqlmapproject/sqlmap) [](https://www.python.org/) [](https://raw.githubusercontent.com/sqlmapproject/sqlmap/master/LICENSE) [](https://twitter.com/sqlmap)
|
||||
[](https://travis-ci.org/sqlmapproject/sqlmap) [](https://www.python.org/) [](https://raw.githubusercontent.com/sqlmapproject/sqlmap/master/LICENSE) [](https://badge.fury.io/py/sqlmap) [](https://github.com/sqlmapproject/sqlmap/issues?q=is%3Aissue+is%3Aclosed) [](https://twitter.com/sqlmap)
|
||||
|
||||
sqlmap sql injection açıklarını otomatik olarak tespit ve istismar etmeye yarayan açık kaynak bir penetrasyon aracıdır. sqlmap gelişmiş tespit özelliğinin yanı sıra penetrasyon testleri sırasında gerekli olabilecek bir çok aracı, -uzak veritabınınından, veri indirmek, dosya sistemine erişmek, dosya çalıştırmak gibi - işlevleri de barındırmaktadır.
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# sqlmap
|
||||
|
||||
[](https://travis-ci.org/sqlmapproject/sqlmap) [](https://www.python.org/) [](https://raw.githubusercontent.com/sqlmapproject/sqlmap/master/LICENSE) [](https://twitter.com/sqlmap)
|
||||
[](https://travis-ci.org/sqlmapproject/sqlmap) [](https://www.python.org/) [](https://raw.githubusercontent.com/sqlmapproject/sqlmap/master/LICENSE) [](https://badge.fury.io/py/sqlmap) [](https://github.com/sqlmapproject/sqlmap/issues?q=is%3Aissue+is%3Aclosed) [](https://twitter.com/sqlmap)
|
||||
|
||||
sqlmap 是一个开源的渗透测试工具,可以用来自动化的检测,利用SQL注入漏洞,获取数据库服务器的权限。它具有功能强大的检测引擎,针对各种不同类型数据库的渗透测试的功能选项,包括获取数据库中存储的数据,访问操作系统文件甚至可以通过外带数据连接的方式执行操作系统命令。
|
||||
|
||||
|
||||
@@ -20,6 +20,11 @@ from optparse import OptionParser
|
||||
|
||||
if sys.version_info >= (3, 0):
|
||||
xrange = range
|
||||
text_type = str
|
||||
string_types = (str,)
|
||||
else:
|
||||
text_type = unicode
|
||||
string_types = (basestring,)
|
||||
|
||||
# Regex used for recognition of hex encoded characters
|
||||
HEX_ENCODED_CHAR_REGEX = r"(?P<result>\\x[0-9A-Fa-f]{2})"
|
||||
@@ -51,15 +56,15 @@ def safecharencode(value):
|
||||
|
||||
retVal = value
|
||||
|
||||
if isinstance(value, basestring):
|
||||
if any([_ not in SAFE_CHARS for _ in value]):
|
||||
if isinstance(value, string_types):
|
||||
if any(_ not in SAFE_CHARS for _ in value):
|
||||
retVal = retVal.replace(HEX_ENCODED_PREFIX, HEX_ENCODED_PREFIX_MARKER)
|
||||
retVal = retVal.replace('\\', SLASH_MARKER)
|
||||
|
||||
for char in SAFE_ENCODE_SLASH_REPLACEMENTS:
|
||||
retVal = retVal.replace(char, repr(char).strip('\''))
|
||||
|
||||
retVal = reduce(lambda x, y: x + (y if (y in string.printable or isinstance(value, unicode) and ord(y) >= 160) else '\\x%02x' % ord(y)), retVal, (unicode if isinstance(value, unicode) else str)())
|
||||
retVal = reduce(lambda x, y: x + (y if (y in string.printable or isinstance(value, text_type) and ord(y) >= 160) else '\\x%02x' % ord(y)), retVal, type(value)())
|
||||
|
||||
retVal = retVal.replace(SLASH_MARKER, "\\\\")
|
||||
retVal = retVal.replace(HEX_ENCODED_PREFIX_MARKER, HEX_ENCODED_PREFIX)
|
||||
@@ -75,13 +80,13 @@ def safechardecode(value, binary=False):
|
||||
"""
|
||||
|
||||
retVal = value
|
||||
if isinstance(value, basestring):
|
||||
if isinstance(value, string_types):
|
||||
retVal = retVal.replace('\\\\', SLASH_MARKER)
|
||||
|
||||
while True:
|
||||
match = re.search(HEX_ENCODED_CHAR_REGEX, retVal)
|
||||
if match:
|
||||
retVal = retVal.replace(match.group("result"), (unichr if isinstance(value, unicode) else chr)(ord(binascii.unhexlify(match.group("result").lstrip("\\x")))))
|
||||
retVal = retVal.replace(match.group("result"), (unichr if isinstance(value, text_type) else chr)(ord(binascii.unhexlify(match.group("result").lstrip("\\x")))))
|
||||
else:
|
||||
break
|
||||
|
||||
@@ -91,7 +96,7 @@ def safechardecode(value, binary=False):
|
||||
retVal = retVal.replace(SLASH_MARKER, '\\')
|
||||
|
||||
if binary:
|
||||
if isinstance(retVal, unicode):
|
||||
if isinstance(retVal, text_type):
|
||||
retVal = retVal.encode("utf8")
|
||||
|
||||
elif isinstance(value, (list, tuple)):
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
#!/bin/bash
|
||||
|
||||
# Copyright (c) 2006-2013 sqlmap developers (http://sqlmap.org/)
|
||||
# Copyright (c) 2006-2019 sqlmap developers (http://sqlmap.org/)
|
||||
# See the file 'LICENSE' for copying permission
|
||||
|
||||
# Removes trailing spaces from blank lines inside project files
|
||||
|
||||
@@ -1,7 +1,11 @@
|
||||
#!/bin/bash
|
||||
|
||||
# Copyright (c) 2006-2013 sqlmap developers (http://sqlmap.org/)
|
||||
# Copyright (c) 2006-2019 sqlmap developers (http://sqlmap.org/)
|
||||
# See the file 'LICENSE' for copying permission
|
||||
|
||||
# Stress test against Python3
|
||||
for i in $(find . -iname "*.py" | grep -v __init__); do python3 -c 'import '`echo $i | cut -d '.' -f 2 | cut -d '/' -f 2- | sed 's/\//./g'`''; done
|
||||
|
||||
export SQLMAP_DREI=1
|
||||
for i in $(find . -iname "*.py" | grep -v __init__); do python3 -c 'import '`echo $i | cut -d '.' -f 2 | cut -d '/' -f 2- | sed 's/\//./g'`''; done
|
||||
unset SQLMAP_DREI
|
||||
source `dirname "$0"`"/junk.sh"
|
||||
Executable
+7
@@ -0,0 +1,7 @@
|
||||
#!/bin/bash
|
||||
|
||||
# Copyright (c) 2006-2019 sqlmap developers (http://sqlmap.org/)
|
||||
# See the file 'LICENSE' for copying permission
|
||||
|
||||
find . -type d -name "__pycache__" -exec rm -rf {} \; &>/dev/null
|
||||
find . -name "*.pyc" -exec rm -f {} \; &>/dev/null
|
||||
@@ -1,6 +1,6 @@
|
||||
#!/bin/bash
|
||||
|
||||
# Copyright (c) 2006-2013 sqlmap developers (http://sqlmap.org/)
|
||||
# Copyright (c) 2006-2019 sqlmap developers (http://sqlmap.org/)
|
||||
# See the file 'LICENSE' for copying permission
|
||||
|
||||
# Runs py2diatra on all python files (prerequisite: pip install pydiatra)
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#!/bin/bash
|
||||
|
||||
# Copyright (c) 2006-2013 sqlmap developers (http://sqlmap.org/)
|
||||
# Copyright (c) 2006-2019 sqlmap developers (http://sqlmap.org/)
|
||||
# See the file 'LICENSE' for copying permission
|
||||
|
||||
# Runs pyflakes on all python files (prerequisite: apt-get install pyflakes)
|
||||
find . -wholename "./thirdparty" -prune -o -type f -iname "*.py" -exec pyflakes '{}' \;
|
||||
find . -wholename "./thirdparty" -prune -o -type f -iname "*.py" -exec pyflakes '{}' \; | grep -v "redefines '_'"
|
||||
|
||||
@@ -12,10 +12,12 @@ from __future__ import print_function
|
||||
import re
|
||||
import sqlite3
|
||||
import sys
|
||||
import threading
|
||||
import traceback
|
||||
|
||||
if sys.version_info >= (3, 0):
|
||||
from http.client import FOUND
|
||||
from http.client import INTERNAL_SERVER_ERROR
|
||||
from http.client import NOT_FOUND
|
||||
from http.client import OK
|
||||
from http.server import BaseHTTPRequestHandler
|
||||
@@ -27,6 +29,7 @@ else:
|
||||
from BaseHTTPServer import BaseHTTPRequestHandler
|
||||
from BaseHTTPServer import HTTPServer
|
||||
from httplib import FOUND
|
||||
from httplib import INTERNAL_SERVER_ERROR
|
||||
from httplib import NOT_FOUND
|
||||
from httplib import OK
|
||||
from SocketServer import ThreadingMixIn
|
||||
@@ -41,7 +44,7 @@ SCHEMA = """
|
||||
);
|
||||
INSERT INTO users (id, name, surname) VALUES (1, 'luther', 'blisset');
|
||||
INSERT INTO users (id, name, surname) VALUES (2, 'fluffy', 'bunny');
|
||||
INSERT INTO users (id, name, surname) VALUES (3, 'wu', 'ming');
|
||||
INSERT INTO users (id, name, surname) VALUES (3, 'wu', '179ad45c6ce2cb97cf1029e212046e81');
|
||||
INSERT INTO users (id, name, surname) VALUES (4, 'sqlmap/1.0-dev (http://sqlmap.org)', 'user agent header');
|
||||
INSERT INTO users (id, name, surname) VALUES (5, NULL, 'nameisnull');
|
||||
"""
|
||||
@@ -51,17 +54,28 @@ LISTEN_PORT = 8440
|
||||
|
||||
_conn = None
|
||||
_cursor = None
|
||||
_lock = None
|
||||
_server = None
|
||||
|
||||
def init():
|
||||
def init(quiet=False):
|
||||
global _conn
|
||||
global _cursor
|
||||
global _lock
|
||||
|
||||
_conn = sqlite3.connect(":memory:", isolation_level=None, check_same_thread=False)
|
||||
_cursor = _conn.cursor()
|
||||
_lock = threading.Lock()
|
||||
|
||||
_cursor.executescript(SCHEMA)
|
||||
|
||||
if quiet:
|
||||
global print
|
||||
|
||||
def _(*args, **kwargs):
|
||||
pass
|
||||
|
||||
print = _
|
||||
|
||||
class ThreadingServer(ThreadingMixIn, HTTPServer):
|
||||
def finish_request(self, *args, **kwargs):
|
||||
try:
|
||||
@@ -77,6 +91,13 @@ class ReqHandler(BaseHTTPRequestHandler):
|
||||
if query:
|
||||
params.update(parse_qs(query))
|
||||
|
||||
if "<script>" in unquote_plus(query):
|
||||
self.send_response(INTERNAL_SERVER_ERROR)
|
||||
self.send_header("Connection", "close")
|
||||
self.end_headers()
|
||||
self.wfile.write("CLOUDFLARE_ERROR_500S_BOX".encode("utf8"))
|
||||
return
|
||||
|
||||
if hasattr(self, "data"):
|
||||
params.update(parse_qs(self.data))
|
||||
|
||||
@@ -99,17 +120,19 @@ class ReqHandler(BaseHTTPRequestHandler):
|
||||
self.end_headers()
|
||||
|
||||
try:
|
||||
_cursor.execute("SELECT * FROM users WHERE id=%s LIMIT 0, 1" % self.params.get("id", ""))
|
||||
with _lock:
|
||||
_cursor.execute("SELECT * FROM users WHERE id=%s LIMIT 0, 1" % self.params.get("id", ""))
|
||||
results = _cursor.fetchall()
|
||||
|
||||
output = "<b>SQL results:</b>\n"
|
||||
output += "<table border=\"1\">\n"
|
||||
for row in _cursor.fetchall():
|
||||
for row in results:
|
||||
output += "<tr>"
|
||||
for value in row:
|
||||
output += "<td>%s</td>" % value
|
||||
output += "</tr>\n"
|
||||
output += "</table>\n"
|
||||
output += "</body></html>";
|
||||
output += "</body></html>"
|
||||
except Exception as ex:
|
||||
output = "%s: %s" % (re.search(r"'([^']+)'", str(type(ex))).group(1), ex)
|
||||
|
||||
@@ -130,6 +153,9 @@ class ReqHandler(BaseHTTPRequestHandler):
|
||||
self.data = data
|
||||
self.do_REQUEST()
|
||||
|
||||
def log_message(self, format, *args):
|
||||
return
|
||||
|
||||
def run(address=LISTEN_ADDRESS, port=LISTEN_PORT):
|
||||
global _server
|
||||
try:
|
||||
|
||||
@@ -176,8 +176,8 @@ def action():
|
||||
except:
|
||||
raise
|
||||
|
||||
if conf.query:
|
||||
conf.dumper.query(conf.query, conf.dbmsHandler.sqlQuery(conf.query))
|
||||
if conf.sqlQuery:
|
||||
conf.dumper.sqlQuery(conf.sqlQuery, conf.dbmsHandler.sqlQuery(conf.sqlQuery))
|
||||
|
||||
if conf.sqlShell:
|
||||
conf.dbmsHandler.sqlShell()
|
||||
|
||||
@@ -49,7 +49,6 @@ from lib.core.common import urlencode
|
||||
from lib.core.common import wasLastResponseDBMSError
|
||||
from lib.core.common import wasLastResponseHTTPError
|
||||
from lib.core.compat import xrange
|
||||
from lib.core.convert import unicodeencode
|
||||
from lib.core.defaults import defaults
|
||||
from lib.core.data import conf
|
||||
from lib.core.data import kb
|
||||
@@ -100,6 +99,7 @@ from lib.core.settings import SUPPORTED_DBMS
|
||||
from lib.core.settings import UNICODE_ENCODING
|
||||
from lib.core.settings import URI_HTTP_HEADER
|
||||
from lib.core.settings import UPPER_RATIO_BOUND
|
||||
from lib.core.settings import INFERENCE_EQUALS_CHAR
|
||||
from lib.core.threads import getCurrentThreadData
|
||||
from lib.request.connect import Connect as Request
|
||||
from lib.request.comparison import comparison
|
||||
@@ -916,27 +916,26 @@ def checkFalsePositives(injection):
|
||||
if randInt3 > randInt2 > randInt1:
|
||||
break
|
||||
|
||||
if not checkBooleanExpression("%d=%d" % (randInt1, randInt1)):
|
||||
if not checkBooleanExpression("%d%s%d" % (randInt1, INFERENCE_EQUALS_CHAR, randInt1)):
|
||||
retVal = False
|
||||
break
|
||||
|
||||
# Just in case if DBMS hasn't properly recovered from previous delayed request
|
||||
if PAYLOAD.TECHNIQUE.BOOLEAN not in injection.data:
|
||||
checkBooleanExpression("%d=%d" % (randInt1, randInt2))
|
||||
checkBooleanExpression("%d%s%d" % (randInt1, INFERENCE_EQUALS_CHAR, randInt2)) # just in case if DBMS hasn't properly recovered from previous delayed request
|
||||
|
||||
if checkBooleanExpression("%d=%d" % (randInt1, randInt3)): # this must not be evaluated to True
|
||||
if checkBooleanExpression("%d%s%d" % (randInt1, INFERENCE_EQUALS_CHAR, randInt3)): # this must not be evaluated to True
|
||||
retVal = False
|
||||
break
|
||||
|
||||
elif checkBooleanExpression("%d=%d" % (randInt3, randInt2)): # this must not be evaluated to True
|
||||
elif checkBooleanExpression("%d%s%d" % (randInt3, INFERENCE_EQUALS_CHAR, randInt2)): # this must not be evaluated to True
|
||||
retVal = False
|
||||
break
|
||||
|
||||
elif not checkBooleanExpression("%d=%d" % (randInt2, randInt2)): # this must be evaluated to True
|
||||
elif not checkBooleanExpression("%d%s%d" % (randInt2, INFERENCE_EQUALS_CHAR, randInt2)): # this must be evaluated to True
|
||||
retVal = False
|
||||
break
|
||||
|
||||
elif checkBooleanExpression("%d %d" % (randInt3, randInt2)): # this must not be evaluated to True (invalid statement)
|
||||
elif checkBooleanExpression("%d %d" % (randInt3, randInt2)): # this must not be evaluated to True (invalid statement)
|
||||
retVal = False
|
||||
break
|
||||
|
||||
@@ -1611,7 +1610,7 @@ def checkConnection(suppressOutput=False):
|
||||
kb.errorIsNone = True
|
||||
|
||||
if kb.redirectChoice == REDIRECTION.YES and threadData.lastRedirectURL and threadData.lastRedirectURL[0] == threadData.lastRequestUID:
|
||||
if (threadData.lastRedirectURL[1] or "").startswith("https://") and unicodeencode(conf.hostname) in threadData.lastRedirectURL[1]:
|
||||
if (threadData.lastRedirectURL[1] or "").startswith("https://") and conf.hostname in getUnicode(threadData.lastRedirectURL[1]):
|
||||
conf.url = re.sub(r"https?://", "https://", conf.url)
|
||||
match = re.search(r":(\d+)", threadData.lastRedirectURL[1])
|
||||
port = match.group(1) if match else 443
|
||||
|
||||
@@ -48,6 +48,7 @@ from lib.core.decorators import stackedmethod
|
||||
from lib.core.enums import CONTENT_TYPE
|
||||
from lib.core.enums import HASHDB_KEYS
|
||||
from lib.core.enums import HEURISTIC_TEST
|
||||
from lib.core.enums import HTTP_HEADER
|
||||
from lib.core.enums import HTTPMETHOD
|
||||
from lib.core.enums import NOTE
|
||||
from lib.core.enums import PAYLOAD
|
||||
@@ -318,6 +319,13 @@ def start():
|
||||
conf.cookie = targetCookie
|
||||
conf.httpHeaders = list(initialHeaders)
|
||||
conf.httpHeaders.extend(targetHeaders or [])
|
||||
|
||||
if conf.randomAgent or conf.mobile:
|
||||
for header, value in initialHeaders:
|
||||
if header.upper() == HTTP_HEADER.USER_AGENT.upper():
|
||||
conf.httpHeaders.append((header, value))
|
||||
break
|
||||
|
||||
conf.httpHeaders = [conf.httpHeaders[i] for i in xrange(len(conf.httpHeaders)) if conf.httpHeaders[i][0].upper() not in (__[0].upper() for __ in conf.httpHeaders[i + 1:])]
|
||||
|
||||
initTargetEnv()
|
||||
@@ -325,7 +333,7 @@ def start():
|
||||
|
||||
testSqlInj = False
|
||||
|
||||
if PLACE.GET in conf.parameters and not any([conf.data, conf.testParameter]):
|
||||
if PLACE.GET in conf.parameters and not any((conf.data, conf.testParameter)):
|
||||
for parameter in re.findall(r"([^=]+)=([^%s]+%s?|\Z)" % (re.escape(conf.paramDel or "") or DEFAULT_GET_POST_DELIMITER, re.escape(conf.paramDel or "") or DEFAULT_GET_POST_DELIMITER), conf.parameters[PLACE.GET]):
|
||||
paramKey = (conf.hostname, conf.path, PLACE.GET, parameter[0])
|
||||
|
||||
|
||||
@@ -75,7 +75,7 @@ def setHandler():
|
||||
(DBMS.INFORMIX, INFORMIX_ALIASES, InformixMap, InformixConn),
|
||||
]
|
||||
|
||||
_ = max(_ if (conf.get("dbms") or Backend.getIdentifiedDbms() or kb.heuristicExtendedDbms or "").lower() in _[1] else None for _ in items)
|
||||
_ = max(_ if (conf.get("dbms") or Backend.getIdentifiedDbms() or kb.heuristicExtendedDbms or "").lower() in _[1] else "" for _ in items) or None
|
||||
if _:
|
||||
items.remove(_)
|
||||
items.insert(0, _)
|
||||
|
||||
+20
-12
@@ -5,6 +5,7 @@ Copyright (c) 2006-2019 sqlmap developers (http://sqlmap.org/)
|
||||
See the file 'LICENSE' for copying permission
|
||||
"""
|
||||
|
||||
import base64
|
||||
import re
|
||||
|
||||
from lib.core.common import Backend
|
||||
@@ -164,6 +165,11 @@ class Agent(object):
|
||||
|
||||
newValue = self.cleanupPayload(newValue, origValue)
|
||||
|
||||
if re.sub(r" \(.+", "", parameter) in conf.base64Parameter:
|
||||
# TODO: support for POST_HINT
|
||||
newValue = base64.b64encode(newValue)
|
||||
origValue = base64.b64encode(origValue)
|
||||
|
||||
if place in (PLACE.URI, PLACE.CUSTOM_POST, PLACE.CUSTOM_HEADER):
|
||||
_ = "%s%s" % (origValue, kb.customInjectionMark)
|
||||
if kb.postHint == POST_HINT.JSON and not isNumber(newValue) and not '"%s"' % _ in paramString:
|
||||
@@ -300,16 +306,19 @@ class Agent(object):
|
||||
if payload is None:
|
||||
return
|
||||
|
||||
replacements = (
|
||||
("[DELIMITER_START]", kb.chars.start),
|
||||
("[DELIMITER_STOP]", kb.chars.stop),
|
||||
("[AT_REPLACE]", kb.chars.at),
|
||||
("[SPACE_REPLACE]", kb.chars.space),
|
||||
("[DOLLAR_REPLACE]", kb.chars.dollar),
|
||||
("[HASH_REPLACE]", kb.chars.hash_),
|
||||
("[GENERIC_SQL_COMMENT]", GENERIC_SQL_COMMENT)
|
||||
)
|
||||
payload = reduce(lambda x, y: x.replace(y[0], y[1]), replacements, payload)
|
||||
replacements = {
|
||||
"[DELIMITER_START]": kb.chars.start,
|
||||
"[DELIMITER_STOP]": kb.chars.stop,
|
||||
"[AT_REPLACE]": kb.chars.at,
|
||||
"[SPACE_REPLACE]": kb.chars.space,
|
||||
"[DOLLAR_REPLACE]": kb.chars.dollar,
|
||||
"[HASH_REPLACE]": kb.chars.hash_,
|
||||
"[GENERIC_SQL_COMMENT]": GENERIC_SQL_COMMENT
|
||||
}
|
||||
|
||||
for value in re.findall(r"\[[A-Z_]+\]", payload):
|
||||
if value in replacements:
|
||||
payload = payload.replace(value, replacements[value])
|
||||
|
||||
for _ in set(re.findall(r"(?i)\[RANDNUM(?:\d+)?\]", payload)):
|
||||
payload = payload.replace(_, str(randomInt()))
|
||||
@@ -980,8 +989,7 @@ class Agent(object):
|
||||
limitedQuery = limitedQuery.replace(" (SELECT TOP %s" % startTopNums, " (SELECT TOP %d" % num)
|
||||
forgeNotIn = False
|
||||
else:
|
||||
topNum = re.search(r"TOP\s+([\d]+)\s+", limitedQuery, re.I).group(1)
|
||||
limitedQuery = limitedQuery.replace("TOP %s " % topNum, "")
|
||||
limitedQuery = re.sub(r"\bTOP\s+\d+\s*", "", limitedQuery, flags=re.I)
|
||||
|
||||
if forgeNotIn:
|
||||
limitedQuery = limitedQuery.replace("SELECT ", (limitStr % 1), 1)
|
||||
|
||||
+219
-128
@@ -52,7 +52,6 @@ from lib.core.convert import base64unpickle
|
||||
from lib.core.convert import hexdecode
|
||||
from lib.core.convert import htmlunescape
|
||||
from lib.core.convert import stdoutencode
|
||||
from lib.core.convert import unicodeencode
|
||||
from lib.core.convert import utf8encode
|
||||
from lib.core.data import conf
|
||||
from lib.core.data import kb
|
||||
@@ -124,7 +123,7 @@ from lib.core.settings import HOST_ALIASES
|
||||
from lib.core.settings import HTTP_CHUNKED_SPLIT_KEYWORDS
|
||||
from lib.core.settings import IGNORE_SAVE_OPTIONS
|
||||
from lib.core.settings import INFERENCE_UNKNOWN_CHAR
|
||||
from lib.core.settings import INVALID_UNICODE_CHAR_FORMAT
|
||||
from lib.core.settings import INVALID_UNICODE_PRIVATE_AREA
|
||||
from lib.core.settings import IP_ADDRESS_REGEX
|
||||
from lib.core.settings import ISSUES_PAGE
|
||||
from lib.core.settings import IS_WIN
|
||||
@@ -153,6 +152,7 @@ from lib.core.settings import REFLECTED_REPLACEMENT_REGEX
|
||||
from lib.core.settings import REFLECTED_REPLACEMENT_TIMEOUT
|
||||
from lib.core.settings import REFLECTED_VALUE_MARKER
|
||||
from lib.core.settings import REFLECTIVE_MISS_THRESHOLD
|
||||
from lib.core.settings import SAFE_HEX_MARKER
|
||||
from lib.core.settings import SENSITIVE_DATA_REGEX
|
||||
from lib.core.settings import SENSITIVE_OPTIONS
|
||||
from lib.core.settings import STDIN_PIPE_DASH
|
||||
@@ -177,6 +177,7 @@ from thirdparty.magic import magic
|
||||
from thirdparty.odict import OrderedDict
|
||||
from thirdparty.six.moves import configparser as _configparser
|
||||
from thirdparty.six.moves import http_client as _http_client
|
||||
from thirdparty.six.moves import input as _input
|
||||
from thirdparty.six.moves import urllib as _urllib
|
||||
from thirdparty.termcolor.termcolor import colored
|
||||
|
||||
@@ -603,7 +604,20 @@ def paramToDict(place, parameters=None):
|
||||
condition |= place == PLACE.COOKIE and len(intersect((PLACE.COOKIE,), conf.testParameter, True)) > 0
|
||||
|
||||
if condition:
|
||||
testableParameters[parameter] = "=".join(parts[1:])
|
||||
value = "=".join(parts[1:])
|
||||
|
||||
if parameter in (conf.base64Parameter or []):
|
||||
try:
|
||||
oldValue = value
|
||||
value = value.decode("base64")
|
||||
parameters = re.sub(r"\b%s\b" % re.escape(oldValue), value, parameters)
|
||||
except:
|
||||
errMsg = "parameter '%s' does not contain " % parameter
|
||||
errMsg += "valid Base64 encoded value ('%s')" % value
|
||||
raise SqlmapValueException(errMsg)
|
||||
|
||||
testableParameters[parameter] = value
|
||||
|
||||
if not conf.multipleTargets and not (conf.csrfToken and re.search(conf.csrfToken, parameter, re.I)):
|
||||
_ = urldecode(testableParameters[parameter], convall=True)
|
||||
if (_.endswith("'") and _.count("'") == 1 or re.search(r'\A9{3,}', _) or re.search(r'\A-\d+\Z', _) or re.search(DUMMY_USER_INJECTION, _)) and not parameter.upper().startswith(GOOGLE_ANALYTICS_COOKIE_PREFIX):
|
||||
@@ -868,26 +882,43 @@ def singleTimeLogMessage(message, level=logging.INFO, flag=None):
|
||||
kb.singleLogFlags.add(flag)
|
||||
logger.log(level, message)
|
||||
|
||||
def boldifyMessage(message):
|
||||
def boldifyMessage(message, istty=None):
|
||||
"""
|
||||
Sets ANSI bold marking on entire message if parts found in predefined BOLD_PATTERNS
|
||||
|
||||
>>> boldifyMessage("Hello World", istty=True)
|
||||
'Hello World'
|
||||
|
||||
>>> boldifyMessage("GET parameter id is not injectable", istty=True)
|
||||
'\\x1b[1mGET parameter id is not injectable\\x1b[0m'
|
||||
"""
|
||||
|
||||
retVal = message
|
||||
|
||||
if any(_ in message for _ in BOLD_PATTERNS):
|
||||
retVal = setColor(message, bold=True)
|
||||
retVal = setColor(message, bold=True, istty=istty)
|
||||
|
||||
return retVal
|
||||
|
||||
def setColor(message, color=None, bold=False, level=None):
|
||||
def setColor(message, color=None, bold=False, level=None, istty=None):
|
||||
"""
|
||||
Sets ANSI color codes
|
||||
|
||||
>>> setColor("Hello World", color="red", istty=True)
|
||||
'\\x1b[31mHello World\\x1b[0m'
|
||||
"""
|
||||
|
||||
retVal = message
|
||||
level = level or extractRegexResult(r"\[(?P<result>%s)\]" % '|'.join(_[0] for _ in getPublicTypeMembers(LOGGING_LEVELS)), message)
|
||||
|
||||
if isinstance(level, unicode):
|
||||
level = unicodeencode(level)
|
||||
|
||||
if message and getattr(LOGGER_HANDLER, "is_tty", False): # colorizing handler
|
||||
if message and getattr(LOGGER_HANDLER, "is_tty", False) or istty: # colorizing handler
|
||||
if bold or color:
|
||||
retVal = colored(message, color=color, on_color=None, attrs=("bold",) if bold else None)
|
||||
elif level:
|
||||
level = getattr(logging, level, None) if isinstance(level, six.string_types) else level
|
||||
try:
|
||||
level = getattr(logging, level, None)
|
||||
except UnicodeError:
|
||||
level = None
|
||||
retVal = LOGGER_HANDLER.colorize(message, level)
|
||||
|
||||
return retVal
|
||||
@@ -912,24 +943,17 @@ def dataToStdout(data, forceOutput=False, bold=False, content_type=None, status=
|
||||
Writes text to the stdout (console) stream
|
||||
"""
|
||||
|
||||
message = ""
|
||||
|
||||
if not kb.get("threadException"):
|
||||
if forceOutput or not (getCurrentThreadData().disableStdOut or kb.get("wizardMode")):
|
||||
multiThreadMode = isMultiThreadMode()
|
||||
if multiThreadMode:
|
||||
logging._acquireLock()
|
||||
|
||||
if isinstance(data, unicode):
|
||||
message = stdoutencode(data)
|
||||
else:
|
||||
message = data
|
||||
|
||||
try:
|
||||
if conf.get("api"):
|
||||
sys.stdout.write(clearColors(message), status, content_type)
|
||||
sys.stdout.write(stdoutencode(clearColors(data)), status, content_type)
|
||||
else:
|
||||
sys.stdout.write(setColor(message, bold=bold))
|
||||
sys.stdout.write(stdoutencode(setColor(data, bold=bold)))
|
||||
|
||||
sys.stdout.flush()
|
||||
except IOError:
|
||||
@@ -975,7 +999,7 @@ def dataToOutFile(filename, data):
|
||||
|
||||
try:
|
||||
with open(retVal, "w+b") as f: # has to stay as non-codecs because data is raw ASCII encoded data
|
||||
f.write(unicodeencode(data))
|
||||
f.write(getBytes(data))
|
||||
except UnicodeEncodeError as ex:
|
||||
_ = normalizeUnicode(filename)
|
||||
if filename != _:
|
||||
@@ -1039,7 +1063,7 @@ def readInput(message, default=None, checkBatch=True, boolean=False):
|
||||
elif default:
|
||||
options = getUnicode(default, UNICODE_ENCODING)
|
||||
else:
|
||||
options = unicode()
|
||||
options = six.text_type()
|
||||
|
||||
dataToStdout("%s%s\n" % (message, options), forceOutput=not kb.wizardMode, bold=True)
|
||||
|
||||
@@ -1057,7 +1081,7 @@ def readInput(message, default=None, checkBatch=True, boolean=False):
|
||||
dataToStdout("%s" % message, forceOutput=not kb.wizardMode, bold=True)
|
||||
kb.prependFlag = False
|
||||
|
||||
retVal = raw_input().strip() or default
|
||||
retVal = _input().strip() or default
|
||||
retVal = getUnicode(retVal, encoding=sys.stdin.encoding) if retVal else retVal
|
||||
except:
|
||||
try:
|
||||
@@ -1083,9 +1107,8 @@ def randomRange(start=0, stop=1000, seed=None):
|
||||
"""
|
||||
Returns random integer value in given range
|
||||
|
||||
>>> random.seed(0)
|
||||
>>> randomRange(1, 500)
|
||||
423
|
||||
>>> randomRange(1, 500, seed=0)
|
||||
9
|
||||
"""
|
||||
|
||||
if seed is not None:
|
||||
@@ -1101,9 +1124,8 @@ def randomInt(length=4, seed=None):
|
||||
"""
|
||||
Returns random integer value with provided number of digits
|
||||
|
||||
>>> random.seed(0)
|
||||
>>> randomInt(6)
|
||||
874254
|
||||
>>> randomInt(6, seed=0)
|
||||
181911
|
||||
"""
|
||||
|
||||
if seed is not None:
|
||||
@@ -1119,9 +1141,8 @@ def randomStr(length=4, lowercase=False, alphabet=None, seed=None):
|
||||
"""
|
||||
Returns random string value with provided number of characters
|
||||
|
||||
>>> random.seed(0)
|
||||
>>> randomStr(6)
|
||||
'RNvnAv'
|
||||
>>> randomStr(6, seed=0)
|
||||
'aUfWgj'
|
||||
"""
|
||||
|
||||
if seed is not None:
|
||||
@@ -1144,8 +1165,8 @@ def sanitizeStr(value):
|
||||
"""
|
||||
Sanitizes string value in respect to newline and line-feed characters
|
||||
|
||||
>>> sanitizeStr('foo\\n\\rbar')
|
||||
u'foo bar'
|
||||
>>> sanitizeStr('foo\\n\\rbar') == 'foo bar'
|
||||
True
|
||||
"""
|
||||
|
||||
return getUnicode(value).replace("\n", " ").replace("\r", "")
|
||||
@@ -1332,7 +1353,8 @@ def weAreFrozen():
|
||||
"""
|
||||
Returns whether we are frozen via py2exe.
|
||||
This will affect how we find out where we are located.
|
||||
Reference: http://www.py2exe.org/index.cgi/WhereAmI
|
||||
|
||||
# Reference: http://www.py2exe.org/index.cgi/WhereAmI
|
||||
"""
|
||||
|
||||
return hasattr(sys, "frozen")
|
||||
@@ -1569,7 +1591,7 @@ def expandAsteriskForColumns(expression):
|
||||
db, conf.tbl = _.split('.', 1) if '.' in _ else (None, _)
|
||||
|
||||
if db is None:
|
||||
if expression != conf.query:
|
||||
if expression != conf.sqlQuery:
|
||||
conf.db = db
|
||||
else:
|
||||
expression = re.sub(r"([^\w])%s" % re.escape(conf.tbl), "\g<1>%s.%s" % (conf.db, conf.tbl), expression)
|
||||
@@ -1827,7 +1849,7 @@ def safeFilepathEncode(filepath):
|
||||
|
||||
retVal = filepath
|
||||
|
||||
if filepath and isinstance(filepath, unicode):
|
||||
if filepath and isinstance(filepath, six.text_type):
|
||||
retVal = filepath.encode(sys.getfilesystemencoding() or UNICODE_ENCODING)
|
||||
|
||||
return retVal
|
||||
@@ -1914,7 +1936,7 @@ def getFilteredPageContent(page, onlyText=True, split=" "):
|
||||
retVal = page
|
||||
|
||||
# only if the page's charset has been successfully identified
|
||||
if isinstance(page, unicode):
|
||||
if isinstance(page, six.text_type):
|
||||
retVal = re.sub(r"(?si)<script.+?</script>|<!--.+?-->|<style.+?</style>%s" % (r"|<[^>]+>|\t|\n|\r" if onlyText else ""), split, page)
|
||||
retVal = re.sub(r"%s{2,}" % split, split, retVal)
|
||||
retVal = htmlunescape(retVal.strip().strip(split))
|
||||
@@ -1932,7 +1954,7 @@ def getPageWordSet(page):
|
||||
retVal = set()
|
||||
|
||||
# only if the page's charset has been successfully identified
|
||||
if isinstance(page, unicode):
|
||||
if isinstance(page, six.text_type):
|
||||
retVal = set(_.group(0) for _ in re.finditer(r"\w+", getFilteredPageContent(page)))
|
||||
|
||||
return retVal
|
||||
@@ -2061,6 +2083,19 @@ def getConsoleWidth(default=80):
|
||||
|
||||
return width or default
|
||||
|
||||
def shellExec(cmd):
|
||||
"""
|
||||
Executes arbitrary shell command
|
||||
|
||||
>>> shellExec('echo 1').strip() == b'1'
|
||||
True
|
||||
"""
|
||||
|
||||
try:
|
||||
return subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT).communicate()[0] or ""
|
||||
except Exception as ex:
|
||||
return six.text_type(ex)
|
||||
|
||||
def clearConsoleLine(forceOutput=False):
|
||||
"""
|
||||
Clears current console line
|
||||
@@ -2176,7 +2211,8 @@ def average(values):
|
||||
def stdev(values):
|
||||
"""
|
||||
Computes standard deviation of a list of numbers.
|
||||
Reference: http://www.goldb.org/corestats.html
|
||||
|
||||
# Reference: http://www.goldb.org/corestats.html
|
||||
|
||||
>>> stdev([0.9, 0.9, 0.9, 1.0, 0.8, 0.9])
|
||||
0.06324555320336757
|
||||
@@ -2375,12 +2411,10 @@ def getUnicode(value, encoding=None, noneToNull=False):
|
||||
"""
|
||||
Return the unicode representation of the supplied value:
|
||||
|
||||
>>> getUnicode(u'test')
|
||||
u'test'
|
||||
>>> getUnicode('test')
|
||||
u'test'
|
||||
>>> getUnicode(1)
|
||||
u'1'
|
||||
>>> getUnicode('test') == u'test'
|
||||
True
|
||||
>>> getUnicode(1) == u'1'
|
||||
True
|
||||
"""
|
||||
|
||||
if noneToNull and value is None:
|
||||
@@ -2391,11 +2425,11 @@ def getUnicode(value, encoding=None, noneToNull=False):
|
||||
elif isinstance(value, six.binary_type):
|
||||
# Heuristics (if encoding not explicitly specified)
|
||||
candidates = filterNone((encoding, kb.get("pageEncoding") if kb.get("originalPage") else None, conf.get("encoding"), UNICODE_ENCODING, sys.getfilesystemencoding()))
|
||||
if all(_ in value for _ in ('<', '>')):
|
||||
if all(_ in value for _ in (b'<', b'>')):
|
||||
pass
|
||||
elif any(_ in value for _ in (":\\", '/', '.')) and '\n' not in value:
|
||||
elif any(_ in value for _ in (b":\\", b'/', b'.')) and b'\n' not in value:
|
||||
candidates = filterNone((encoding, sys.getfilesystemencoding(), kb.get("pageEncoding") if kb.get("originalPage") else None, UNICODE_ENCODING, conf.get("encoding")))
|
||||
elif conf.get("encoding") and '\n' not in value:
|
||||
elif conf.get("encoding") and b'\n' not in value:
|
||||
candidates = filterNone((encoding, conf.get("encoding"), kb.get("pageEncoding") if kb.get("originalPage") else None, sys.getfilesystemencoding(), UNICODE_ENCODING))
|
||||
|
||||
for candidate in candidates:
|
||||
@@ -2404,14 +2438,10 @@ def getUnicode(value, encoding=None, noneToNull=False):
|
||||
except UnicodeDecodeError:
|
||||
pass
|
||||
|
||||
while True:
|
||||
try:
|
||||
return six.text_type(value, encoding or (kb.get("pageEncoding") if kb.get("originalPage") else None) or UNICODE_ENCODING)
|
||||
except UnicodeDecodeError as ex:
|
||||
try:
|
||||
return six.text_type(value, UNICODE_ENCODING)
|
||||
except:
|
||||
value = value[:ex.start] + "".join(INVALID_UNICODE_CHAR_FORMAT % ord(_) for _ in value[ex.start:ex.end]) + value[ex.end:]
|
||||
try:
|
||||
return six.text_type(value, encoding or (kb.get("pageEncoding") if kb.get("originalPage") else None) or UNICODE_ENCODING)
|
||||
except UnicodeDecodeError:
|
||||
return six.text_type(value, UNICODE_ENCODING, errors="reversible")
|
||||
elif isListLike(value):
|
||||
value = list(getUnicode(_, encoding, noneToNull) for _ in value)
|
||||
return value
|
||||
@@ -2421,10 +2451,44 @@ def getUnicode(value, encoding=None, noneToNull=False):
|
||||
except UnicodeDecodeError:
|
||||
return six.text_type(str(value), errors="ignore") # encoding ignored for non-basestring instances
|
||||
|
||||
def decodeHex(value):
|
||||
"""
|
||||
Returns byte representation of provided hexadecimal value
|
||||
|
||||
>>> decodeHex("313233") == b"123"
|
||||
True
|
||||
"""
|
||||
|
||||
return bytes.fromhex(value) if hasattr(bytes, "fromhex") else value.decode("hex")
|
||||
|
||||
def getBytes(value, encoding=UNICODE_ENCODING, errors="strict"):
|
||||
"""
|
||||
Returns byte representation of provided Unicode value
|
||||
|
||||
>>> getBytes(getUnicode("foo\x01\x83\xffbar")) == b"foo\x01\x83\xffbar"
|
||||
True
|
||||
"""
|
||||
|
||||
retVal = value
|
||||
|
||||
if isinstance(value, six.text_type):
|
||||
if INVALID_UNICODE_PRIVATE_AREA:
|
||||
for char in xrange(0xF0000, 0xF00FF + 1):
|
||||
value = value.replace(unichr(char), "%s%02x" % (SAFE_HEX_MARKER, char - 0xF0000))
|
||||
|
||||
retVal = value.encode(encoding, errors)
|
||||
retVal = re.sub(r"%s([0-9a-f]{2})" % SAFE_HEX_MARKER, lambda _: decodeHex(_.group(1)), retVal)
|
||||
else:
|
||||
retVal = value.encode(encoding, errors)
|
||||
retVal = re.sub(b"\\\\x([0-9a-f]{2})", lambda _: decodeHex(_.group(1)), retVal)
|
||||
|
||||
return retVal
|
||||
|
||||
def longestCommonPrefix(*sequences):
|
||||
"""
|
||||
Returns longest common prefix occuring in given sequences
|
||||
Reference: http://boredzo.org/blog/archives/2007-01-06/longest-common-prefix-in-python-2
|
||||
|
||||
# Reference: http://boredzo.org/blog/archives/2007-01-06/longest-common-prefix-in-python-2
|
||||
|
||||
>>> longestCommonPrefix('foobar', 'fobar')
|
||||
'fo'
|
||||
@@ -2547,11 +2611,12 @@ def adjustTimeDelay(lastQueryDuration, lowerStdLimit):
|
||||
kb.delayCandidates = [candidate] + kb.delayCandidates[:-1]
|
||||
|
||||
if all((_ == candidate for _ in kb.delayCandidates)) and candidate < conf.timeSec:
|
||||
conf.timeSec = candidate
|
||||
if lastQueryDuration / (1.0 * conf.timeSec / candidate) > MIN_VALID_DELAYED_RESPONSE: # Note: to prevent problems with fast responses for heavy-queries like RANDOMBLOB
|
||||
conf.timeSec = candidate
|
||||
|
||||
infoMsg = "adjusting time delay to "
|
||||
infoMsg += "%d second%s due to good response times" % (conf.timeSec, 's' if conf.timeSec > 1 else '')
|
||||
logger.info(infoMsg)
|
||||
infoMsg = "adjusting time delay to "
|
||||
infoMsg += "%d second%s due to good response times" % (conf.timeSec, 's' if conf.timeSec > 1 else '')
|
||||
logger.info(infoMsg)
|
||||
|
||||
def getLastRequestHTTPError():
|
||||
"""
|
||||
@@ -2641,6 +2706,8 @@ def urldecode(value, encoding=None, unsafe="%%&=;+%s" % CUSTOM_INJECTION_MARK_CH
|
||||
|
||||
>>> urldecode('AND%201%3E%282%2B3%29%23', convall=True)
|
||||
u'AND 1>(2+3)#'
|
||||
>>> urldecode('AND%201%3E%282%2B3%29%23', convall=False)
|
||||
u'AND 1>(2%2B3)#'
|
||||
"""
|
||||
|
||||
result = value
|
||||
@@ -2655,17 +2722,19 @@ def urldecode(value, encoding=None, unsafe="%%&=;+%s" % CUSTOM_INJECTION_MARK_CH
|
||||
if convall:
|
||||
result = _urllib.parse.unquote_plus(value) if spaceplus else _urllib.parse.unquote(value)
|
||||
else:
|
||||
result = value
|
||||
charset = set(string.printable) - set(unsafe)
|
||||
|
||||
def _(match):
|
||||
charset = reduce(lambda x, y: x.replace(y, ""), unsafe, string.printable)
|
||||
char = chr(ord(match.group(1).decode("hex")))
|
||||
return char if char in charset else match.group(0)
|
||||
result = value
|
||||
|
||||
if spaceplus:
|
||||
result = result.replace('+', ' ') # plus sign has a special meaning in URL encoded data (hence the usage of _urllib.parse.unquote_plus in convall case)
|
||||
|
||||
result = re.sub(r"%([0-9a-fA-F]{2})", _, result)
|
||||
|
||||
if isinstance(result, str):
|
||||
result = unicode(result, encoding or UNICODE_ENCODING, "replace")
|
||||
result = getUnicode(result, encoding or UNICODE_ENCODING)
|
||||
|
||||
return result
|
||||
|
||||
@@ -2815,6 +2884,9 @@ def extractRegexResult(regex, content, flags=0):
|
||||
retVal = None
|
||||
|
||||
if regex and content and "?P<result>" in regex:
|
||||
if isinstance(content, six.binary_type) and isinstance(regex, six.text_type):
|
||||
regex = getBytes(regex)
|
||||
|
||||
match = re.search(regex, content, flags)
|
||||
|
||||
if match:
|
||||
@@ -2826,8 +2898,8 @@ def extractTextTagContent(page):
|
||||
"""
|
||||
Returns list containing content from "textual" tags
|
||||
|
||||
>>> extractTextTagContent(u'<html><head><title>Title</title></head><body><pre>foobar</pre><a href="#link">Link</a></body></html>')
|
||||
[u'Title', u'foobar']
|
||||
>>> extractTextTagContent('<html><head><title>Title</title></head><body><pre>foobar</pre><a href="#link">Link</a></body></html>')
|
||||
['Title', 'foobar']
|
||||
"""
|
||||
|
||||
page = page or ""
|
||||
@@ -2844,8 +2916,8 @@ def trimAlphaNum(value):
|
||||
"""
|
||||
Trims alpha numeric characters from start and ending of a given value
|
||||
|
||||
>>> trimAlphaNum(u'AND 1>(2+3)-- foobar')
|
||||
u' 1>(2+3)-- '
|
||||
>>> trimAlphaNum('AND 1>(2+3)-- foobar')
|
||||
' 1>(2+3)-- '
|
||||
"""
|
||||
|
||||
while value and value[-1].isalnum():
|
||||
@@ -2976,8 +3048,8 @@ def filterStringValue(value, charRegex, replacement=""):
|
||||
Returns string value consisting only of chars satisfying supplied
|
||||
regular expression (note: it has to be in form [...])
|
||||
|
||||
>>> filterStringValue(u'wzydeadbeef0123#', r'[0-9a-f]')
|
||||
u'deadbeef0123'
|
||||
>>> filterStringValue('wzydeadbeef0123#', r'[0-9a-f]')
|
||||
'deadbeef0123'
|
||||
"""
|
||||
|
||||
retVal = value
|
||||
@@ -2991,8 +3063,8 @@ def filterControlChars(value, replacement=' '):
|
||||
"""
|
||||
Returns string value with control chars being supstituted with replacement character
|
||||
|
||||
>>> filterControlChars(u'AND 1>(2+3)\\n--')
|
||||
u'AND 1>(2+3) --'
|
||||
>>> filterControlChars('AND 1>(2+3)\\n--')
|
||||
'AND 1>(2+3) --'
|
||||
"""
|
||||
|
||||
return filterStringValue(value, PRINTABLE_CHAR_REGEX, replacement)
|
||||
@@ -3214,8 +3286,8 @@ def arrayizeValue(value):
|
||||
"""
|
||||
Makes a list out of value if it is not already a list or tuple itself
|
||||
|
||||
>>> arrayizeValue(u'1')
|
||||
[u'1']
|
||||
>>> arrayizeValue('1')
|
||||
['1']
|
||||
"""
|
||||
|
||||
if not isListLike(value):
|
||||
@@ -3227,8 +3299,8 @@ def unArrayizeValue(value):
|
||||
"""
|
||||
Makes a value out of iterable if it is a list or tuple itself
|
||||
|
||||
>>> unArrayizeValue([u'1'])
|
||||
u'1'
|
||||
>>> unArrayizeValue(['1'])
|
||||
'1'
|
||||
"""
|
||||
|
||||
if isListLike(value):
|
||||
@@ -3246,8 +3318,8 @@ def flattenValue(value):
|
||||
"""
|
||||
Returns an iterator representing flat representation of a given value
|
||||
|
||||
>>> [_ for _ in flattenValue([[u'1'], [[u'2'], u'3']])]
|
||||
[u'1', u'2', u'3']
|
||||
>>> [_ for _ in flattenValue([['1'], [['2'], '3']])]
|
||||
['1', '2', '3']
|
||||
"""
|
||||
|
||||
for i in iter(value):
|
||||
@@ -3263,7 +3335,7 @@ def isListLike(value):
|
||||
|
||||
>>> isListLike([1, 2, 3])
|
||||
True
|
||||
>>> isListLike(u'2')
|
||||
>>> isListLike('2')
|
||||
False
|
||||
"""
|
||||
|
||||
@@ -3306,7 +3378,7 @@ def filterListValue(value, regex):
|
||||
"""
|
||||
|
||||
if isinstance(value, list) and regex:
|
||||
retVal = filter(lambda _: re.search(regex, _, re.I), value)
|
||||
retVal = [_ for _ in value if re.search(regex, _, re.I)]
|
||||
else:
|
||||
retVal = value
|
||||
|
||||
@@ -3326,7 +3398,7 @@ def showHttpErrorCodes():
|
||||
msg += "could mean that some kind of protection is involved (e.g. WAF)"
|
||||
logger.debug(msg)
|
||||
|
||||
def openFile(filename, mode='r', encoding=UNICODE_ENCODING, errors="replace", buffering=1): # "buffering=1" means line buffered (Reference: http://stackoverflow.com/a/3168436)
|
||||
def openFile(filename, mode='r', encoding=UNICODE_ENCODING, errors="reversible", buffering=1): # "buffering=1" means line buffered (Reference: http://stackoverflow.com/a/3168436)
|
||||
"""
|
||||
Returns file handle of a given filename
|
||||
"""
|
||||
@@ -3349,10 +3421,10 @@ def decodeIntToUnicode(value):
|
||||
"""
|
||||
Decodes inferenced integer value to an unicode character
|
||||
|
||||
>>> decodeIntToUnicode(35)
|
||||
u'#'
|
||||
>>> decodeIntToUnicode(64)
|
||||
u'@'
|
||||
>>> decodeIntToUnicode(35) == '#'
|
||||
True
|
||||
>>> decodeIntToUnicode(64) == '@'
|
||||
True
|
||||
"""
|
||||
retVal = value
|
||||
|
||||
@@ -3383,7 +3455,8 @@ def decodeIntToUnicode(value):
|
||||
def md5File(filename):
|
||||
"""
|
||||
Calculates MD5 digest of a file
|
||||
Reference: http://stackoverflow.com/a/3431838
|
||||
|
||||
# Reference: http://stackoverflow.com/a/3431838
|
||||
"""
|
||||
|
||||
checkFile(filename)
|
||||
@@ -3418,6 +3491,16 @@ def checkIntegrity():
|
||||
|
||||
return retVal
|
||||
|
||||
def getDaysFromLastUpdate():
|
||||
"""
|
||||
Get total number of days from last update
|
||||
"""
|
||||
|
||||
if not paths:
|
||||
return
|
||||
|
||||
return int(time.time() - os.path.getmtime(paths.SQLMAP_SETTINGS_PATH)) // (3600 * 24)
|
||||
|
||||
def unhandledExceptionMessage():
|
||||
"""
|
||||
Returns detailed message about occurred unhandled exception
|
||||
@@ -3452,7 +3535,7 @@ def getLatestRevision():
|
||||
"""
|
||||
Retrieves latest revision from the offical repository
|
||||
|
||||
>>> from lib.core.settings import VERSION; getLatestRevision() == VERSION
|
||||
>>> (getLatestRevision() or " ")[0].isdigit()
|
||||
True
|
||||
"""
|
||||
|
||||
@@ -3483,6 +3566,9 @@ def createGithubIssue(errMsg, excMsg):
|
||||
_ = re.sub(r"\s+line \d+", "", _)
|
||||
_ = re.sub(r'File ".+?/(\w+\.py)', r"\g<1>", _)
|
||||
_ = re.sub(r".+\Z", "", _)
|
||||
_ = re.sub(r"(Unicode[^:]*Error:).+", r"\g<1>", _)
|
||||
_ = re.sub(r"= _", "= ", _)
|
||||
|
||||
key = hashlib.md5(_).hexdigest()[:8]
|
||||
|
||||
if key in issues:
|
||||
@@ -3619,21 +3705,23 @@ def decodeStringEscape(value):
|
||||
retVal = value
|
||||
|
||||
if value and '\\' in value:
|
||||
if isinstance(value, unicode):
|
||||
retVal = retVal.encode(UNICODE_ENCODING)
|
||||
charset = "\\%s" % string.whitespace.replace(" ", "")
|
||||
for _ in charset:
|
||||
retVal = retVal.replace(repr(_).strip("'"), _)
|
||||
|
||||
try:
|
||||
retVal = codecs.escape_decode(retVal)[0]
|
||||
except:
|
||||
try:
|
||||
retVal = retVal.decode("string_escape")
|
||||
except:
|
||||
charset = string.whitespace.replace(" ", "")
|
||||
for _ in charset:
|
||||
retVal = retVal.replace(repr(_).strip("'"), _)
|
||||
return retVal
|
||||
|
||||
if isinstance(value, unicode):
|
||||
retVal = getUnicode(retVal)
|
||||
def encodeStringEscape(value):
|
||||
"""
|
||||
Encodes escaped string values (e.g. "\t" -> "\\t")
|
||||
"""
|
||||
|
||||
retVal = value
|
||||
|
||||
if value:
|
||||
charset = "\\%s" % string.whitespace.replace(" ", "")
|
||||
for _ in charset:
|
||||
retVal = retVal.replace(_, repr(_).strip("'"))
|
||||
|
||||
return retVal
|
||||
|
||||
@@ -3646,14 +3734,14 @@ def removeReflectiveValues(content, payload, suppressWarning=False):
|
||||
retVal = content
|
||||
|
||||
try:
|
||||
if all((content, payload)) and isinstance(content, unicode) and kb.reflectiveMechanism and not kb.heuristicMode:
|
||||
if all((content, payload)) and isinstance(content, six.text_type) and kb.reflectiveMechanism and not kb.heuristicMode:
|
||||
def _(value):
|
||||
while 2 * REFLECTED_REPLACEMENT_REGEX in value:
|
||||
value = value.replace(2 * REFLECTED_REPLACEMENT_REGEX, REFLECTED_REPLACEMENT_REGEX)
|
||||
return value
|
||||
|
||||
payload = getUnicode(urldecode(payload.replace(PAYLOAD_DELIMITER, ""), convall=True))
|
||||
regex = _(filterStringValue(payload, r"[A-Za-z0-9]", REFLECTED_REPLACEMENT_REGEX.encode("string_escape")))
|
||||
regex = _(filterStringValue(payload, r"[A-Za-z0-9]", encodeStringEscape(REFLECTED_REPLACEMENT_REGEX)))
|
||||
|
||||
if regex != payload:
|
||||
if all(part.lower() in content.lower() for part in filterNone(regex.split(REFLECTED_REPLACEMENT_REGEX))[1:]): # fast optimization check
|
||||
@@ -3732,18 +3820,20 @@ def removeReflectiveValues(content, payload, suppressWarning=False):
|
||||
def normalizeUnicode(value):
|
||||
"""
|
||||
Does an ASCII normalization of unicode strings
|
||||
Reference: http://www.peterbe.com/plog/unicode-to-ascii
|
||||
|
||||
>>> normalizeUnicode(u'\u0161u\u0107uraj')
|
||||
'sucuraj'
|
||||
# Reference: http://www.peterbe.com/plog/unicode-to-ascii
|
||||
|
||||
>>> normalizeUnicode(u'\u0161u\u0107uraj') == u'sucuraj'
|
||||
True
|
||||
"""
|
||||
|
||||
return unicodedata.normalize("NFKD", value).encode("ascii", "ignore") if isinstance(value, unicode) else value
|
||||
return getUnicode(unicodedata.normalize("NFKD", value).encode("ascii", "ignore")) if isinstance(value, six.text_type) else value
|
||||
|
||||
def safeSQLIdentificatorNaming(name, isTable=False):
|
||||
"""
|
||||
Returns a safe representation of SQL identificator name (internal data format)
|
||||
Reference: http://stackoverflow.com/questions/954884/what-special-characters-are-allowed-in-t-sql-column-retVal
|
||||
|
||||
# Reference: http://stackoverflow.com/questions/954884/what-special-characters-are-allowed-in-t-sql-column-retVal
|
||||
"""
|
||||
|
||||
retVal = name
|
||||
@@ -3929,12 +4019,13 @@ def expandMnemonics(mnemonics, parser, args):
|
||||
def safeCSValue(value):
|
||||
"""
|
||||
Returns value safe for CSV dumping
|
||||
Reference: http://tools.ietf.org/html/rfc4180
|
||||
|
||||
>>> safeCSValue(u'foo, bar')
|
||||
u'"foo, bar"'
|
||||
>>> safeCSValue(u'foobar')
|
||||
u'foobar'
|
||||
# Reference: http://tools.ietf.org/html/rfc4180
|
||||
|
||||
>>> safeCSValue('foo, bar')
|
||||
'"foo, bar"'
|
||||
>>> safeCSValue('foobar')
|
||||
'foobar'
|
||||
"""
|
||||
|
||||
retVal = value
|
||||
@@ -3957,7 +4048,7 @@ def filterPairValues(values):
|
||||
retVal = []
|
||||
|
||||
if not isNoneValue(values) and hasattr(values, '__iter__'):
|
||||
retVal = filter(lambda x: isinstance(x, (tuple, list, set)) and len(x) == 2, values)
|
||||
retVal = [value for value in values if isinstance(value, (tuple, list, set)) and len(value) == 2]
|
||||
|
||||
return retVal
|
||||
|
||||
@@ -4027,7 +4118,7 @@ def asciifyUrl(url, forceQuote=False):
|
||||
|
||||
See also RFC 3987.
|
||||
|
||||
Reference: http://blog.elsdoerfer.name/2008/12/12/opening-iris-in-python/
|
||||
# Reference: http://blog.elsdoerfer.name/2008/12/12/opening-iris-in-python/
|
||||
|
||||
>>> asciifyUrl(u'http://www.\u0161u\u0107uraj.com')
|
||||
u'http://www.xn--uuraj-gxa24d.com'
|
||||
@@ -4057,7 +4148,7 @@ def asciifyUrl(url, forceQuote=False):
|
||||
# _urllib.parse.quote(s.replace('%', '')) != s.replace('%', '')
|
||||
# which would trigger on all %-characters, e.g. "&".
|
||||
if getUnicode(s).encode("ascii", "replace") != s or forceQuote:
|
||||
return _urllib.parse.quote(s.encode(UNICODE_ENCODING) if isinstance(s, unicode) else s, safe=safe)
|
||||
return _urllib.parse.quote(s.encode(UNICODE_ENCODING) if isinstance(s, six.text_type) else s, safe=safe)
|
||||
return s
|
||||
|
||||
username = quote(parts.username, '')
|
||||
@@ -4122,7 +4213,7 @@ def findPageForms(content, url, raise_=False, addToTargets=False):
|
||||
|
||||
class _(io.BytesIO):
|
||||
def __init__(self, content, url):
|
||||
io.BytesIO.__init__(self, unicodeencode(content, kb.pageEncoding) if isinstance(content, unicode) else content)
|
||||
io.BytesIO.__init__(self, getBytes(content, kb.pageEncoding))
|
||||
self._url = url
|
||||
|
||||
def geturl(self):
|
||||
@@ -4383,10 +4474,10 @@ def decodeHexValue(value, raw=False):
|
||||
"""
|
||||
Returns value decoded from DBMS specific hexadecimal representation
|
||||
|
||||
>>> decodeHexValue('3132332031')
|
||||
u'123 1'
|
||||
>>> decodeHexValue(['0x31', '0x32'])
|
||||
[u'1', u'2']
|
||||
>>> decodeHexValue('3132332031') == u'123 1'
|
||||
True
|
||||
>>> decodeHexValue(['0x31', '0x32']) == [u'1', u'2']
|
||||
True
|
||||
"""
|
||||
|
||||
retVal = value
|
||||
@@ -4411,8 +4502,8 @@ def decodeHexValue(value, raw=False):
|
||||
retVal = retVal.decode("utf-16-be")
|
||||
except UnicodeDecodeError:
|
||||
pass
|
||||
if not isinstance(retVal, unicode):
|
||||
retVal = getUnicode(retVal, conf.encoding or "utf8")
|
||||
if not isinstance(retVal, six.text_type):
|
||||
retVal = getUnicode(retVal, conf.encoding or UNICODE_ENCODING)
|
||||
|
||||
return retVal
|
||||
|
||||
@@ -4569,14 +4660,14 @@ def getRequestHeader(request, name):
|
||||
"""
|
||||
Solving an issue with an urllib2 Request header case sensitivity
|
||||
|
||||
Reference: http://bugs.python.org/issue2275
|
||||
# Reference: http://bugs.python.org/issue2275
|
||||
"""
|
||||
|
||||
retVal = None
|
||||
|
||||
if request and request.headers and name:
|
||||
_ = name.upper()
|
||||
retVal = max(value if _ == key.upper() else None for key, value in request.header_items())
|
||||
retVal = max(value if _ == key.upper() else "" for key, value in request.header_items()) or None
|
||||
|
||||
return retVal
|
||||
|
||||
@@ -4844,8 +4935,8 @@ def getSafeExString(ex, encoding=None):
|
||||
Safe way how to get the proper exception represtation as a string
|
||||
(Note: errors to be avoided: 1) "%s" % Exception(u'\u0161') and 2) "%s" % str(Exception(u'\u0161'))
|
||||
|
||||
>>> getSafeExString(SqlmapBaseException('foobar'))
|
||||
u'foobar'
|
||||
>>> getSafeExString(SqlmapBaseException('foobar')) == 'foobar'
|
||||
True
|
||||
"""
|
||||
|
||||
retVal = None
|
||||
|
||||
+4
-4
@@ -37,7 +37,7 @@ class WichmannHill(random.Random):
|
||||
a = int(binascii.hexlify(os.urandom(16)), 16)
|
||||
except NotImplementedError:
|
||||
import time
|
||||
a = int(time.time() * 256) # use fractional seconds
|
||||
a = int(time.time() * 256) # use fractional seconds
|
||||
|
||||
if not isinstance(a, int):
|
||||
a = hash(a)
|
||||
@@ -45,7 +45,7 @@ class WichmannHill(random.Random):
|
||||
a, x = divmod(a, 30268)
|
||||
a, y = divmod(a, 30306)
|
||||
a, z = divmod(a, 30322)
|
||||
self._seed = int(x)+1, int(y)+1, int(z)+1
|
||||
self._seed = int(x) + 1, int(y) + 1, int(z) + 1
|
||||
|
||||
self.gauss_next = None
|
||||
|
||||
@@ -78,7 +78,7 @@ class WichmannHill(random.Random):
|
||||
|
||||
# Note: on a platform using IEEE-754 double arithmetic, this can
|
||||
# never return 0.0 (asserted by Tim; proof too long for a comment).
|
||||
return (x/30269.0 + y/30307.0 + z/30323.0) % 1.0
|
||||
return (x / 30269.0 + y / 30307.0 + z / 30323.0) % 1.0
|
||||
|
||||
def getstate(self):
|
||||
"""Return internal state; can be passed to setstate() later."""
|
||||
@@ -130,7 +130,7 @@ class WichmannHill(random.Random):
|
||||
# Initialize from current time
|
||||
import time
|
||||
t = int(time.time() * 256)
|
||||
t = int((t&0xffffff) ^ (t>>24))
|
||||
t = int((t & 0xffffff) ^ (t >> 24))
|
||||
t, x = divmod(t, 256)
|
||||
t, y = divmod(t, 256)
|
||||
t, z = divmod(t, 256)
|
||||
|
||||
+21
-18
@@ -163,8 +163,10 @@ def htmlunescape(value):
|
||||
|
||||
retVal = value
|
||||
if value and isinstance(value, six.string_types):
|
||||
codes = (("<", '<'), (">", '>'), (""", '"'), (" ", ' '), ("&", '&'), ("'", "'"))
|
||||
retVal = reduce(lambda x, y: x.replace(y[0], y[1]), codes, retVal)
|
||||
replacements = (("<", '<'), (">", '>'), (""", '"'), (" ", ' '), ("&", '&'), ("'", "'"))
|
||||
for code, value in replacements:
|
||||
retVal = retVal.replace(code, value)
|
||||
|
||||
try:
|
||||
retVal = re.sub(r"&#x([^ ;]+);", lambda match: unichr(int(match.group(1), 16)), retVal)
|
||||
except ValueError:
|
||||
@@ -177,25 +179,26 @@ def singleTimeWarnMessage(message): # Cross-referenced function
|
||||
sys.stdout.flush()
|
||||
|
||||
def stdoutencode(data):
|
||||
retVal = None
|
||||
retVal = data
|
||||
|
||||
try:
|
||||
retVal = unicodeencode(data or "", sys.stdout.encoding)
|
||||
if six.PY2:
|
||||
try:
|
||||
retVal = unicodeencode(data or "", sys.stdout.encoding)
|
||||
|
||||
# Reference: http://bugs.python.org/issue1602
|
||||
if IS_WIN:
|
||||
if '?' in retVal and '?' not in retVal:
|
||||
warnMsg = "cannot properly display Unicode characters "
|
||||
warnMsg += "inside Windows OS command prompt "
|
||||
warnMsg += "(http://bugs.python.org/issue1602). All "
|
||||
warnMsg += "unhandled occurrences will result in "
|
||||
warnMsg += "replacement with '?' character. Please, find "
|
||||
warnMsg += "proper character representation inside "
|
||||
warnMsg += "corresponding output files. "
|
||||
singleTimeWarnMessage(warnMsg)
|
||||
# Reference: http://bugs.python.org/issue1602
|
||||
if IS_WIN:
|
||||
if '?' in retVal and '?' not in retVal:
|
||||
warnMsg = "cannot properly display Unicode characters "
|
||||
warnMsg += "inside Windows OS command prompt "
|
||||
warnMsg += "(http://bugs.python.org/issue1602). All "
|
||||
warnMsg += "unhandled occurrences will result in "
|
||||
warnMsg += "replacement with '?' character. Please, find "
|
||||
warnMsg += "proper character representation inside "
|
||||
warnMsg += "corresponding output files. "
|
||||
singleTimeWarnMessage(warnMsg)
|
||||
|
||||
except:
|
||||
retVal = unicodeencode(data or "")
|
||||
except:
|
||||
retVal = unicodeencode(data or "")
|
||||
|
||||
return retVal
|
||||
|
||||
|
||||
@@ -10,6 +10,7 @@ import hashlib
|
||||
import threading
|
||||
|
||||
from lib.core.settings import MAX_CACHE_ITEMS
|
||||
from lib.core.settings import UNICODE_ENCODING
|
||||
from lib.core.datatype import LRUDict
|
||||
from lib.core.threads import getCurrentThreadData
|
||||
|
||||
@@ -24,7 +25,7 @@ def cachedmethod(f, cache=LRUDict(capacity=MAX_CACHE_ITEMS)):
|
||||
|
||||
@functools.wraps(f)
|
||||
def _(*args, **kwargs):
|
||||
key = int(hashlib.md5("|".join(str(_) for _ in (f, args, kwargs))).hexdigest(), 16) & 0x7fffffffffffffff
|
||||
key = int(hashlib.md5("|".join(str(_) for _ in (f, args, kwargs)).encode(UNICODE_ENCODING)).hexdigest(), 16) & 0x7fffffffffffffff
|
||||
|
||||
try:
|
||||
with _lock:
|
||||
|
||||
+10
-10
@@ -17,6 +17,7 @@ from lib.core.common import Backend
|
||||
from lib.core.common import checkFile
|
||||
from lib.core.common import dataToDumpFile
|
||||
from lib.core.common import dataToStdout
|
||||
from lib.core.common import getBytes
|
||||
from lib.core.common import getSafeExString
|
||||
from lib.core.common import getUnicode
|
||||
from lib.core.common import isListLike
|
||||
@@ -26,7 +27,6 @@ from lib.core.common import openFile
|
||||
from lib.core.common import prioritySortColumns
|
||||
from lib.core.common import randomInt
|
||||
from lib.core.common import safeCSValue
|
||||
from lib.core.common import unicodeencode
|
||||
from lib.core.common import unsafeSQLIdentificatorNaming
|
||||
from lib.core.compat import xrange
|
||||
from lib.core.data import conf
|
||||
@@ -242,7 +242,7 @@ class Dump(object):
|
||||
if table and isListLike(table):
|
||||
table = table[0]
|
||||
|
||||
maxlength = max(maxlength, len(unsafeSQLIdentificatorNaming(normalizeUnicode(table) or unicode(table))))
|
||||
maxlength = max(maxlength, len(unsafeSQLIdentificatorNaming(normalizeUnicode(table) or getUnicode(table))))
|
||||
|
||||
lines = "-" * (int(maxlength) + 2)
|
||||
|
||||
@@ -263,7 +263,7 @@ class Dump(object):
|
||||
table = table[0]
|
||||
|
||||
table = unsafeSQLIdentificatorNaming(table)
|
||||
blank = " " * (maxlength - len(normalizeUnicode(table) or unicode(table)))
|
||||
blank = " " * (maxlength - len(normalizeUnicode(table) or getUnicode(table)))
|
||||
self._write("| %s%s |" % (table, blank))
|
||||
|
||||
self._write("+%s+\n" % lines)
|
||||
@@ -358,7 +358,7 @@ class Dump(object):
|
||||
for ctables in dbTables.values():
|
||||
for tables in ctables.values():
|
||||
for table in tables:
|
||||
maxlength1 = max(maxlength1, len(normalizeUnicode(table) or unicode(table)))
|
||||
maxlength1 = max(maxlength1, len(normalizeUnicode(table) or getUnicode(table)))
|
||||
|
||||
for db, counts in dbTables.items():
|
||||
self._write("Database: %s" % unsafeSQLIdentificatorNaming(db) if db else "Current database")
|
||||
@@ -384,7 +384,7 @@ class Dump(object):
|
||||
tables.sort(key=lambda _: _.lower() if hasattr(_, "lower") else _)
|
||||
|
||||
for table in tables:
|
||||
blank1 = " " * (maxlength1 - len(normalizeUnicode(table) or unicode(table)))
|
||||
blank1 = " " * (maxlength1 - len(normalizeUnicode(table) or getUnicode(table)))
|
||||
blank2 = " " * (maxlength2 - len(str(count)))
|
||||
self._write("| %s%s | %d%s |" % (table, blank1, count, blank2))
|
||||
|
||||
@@ -422,8 +422,8 @@ class Dump(object):
|
||||
except:
|
||||
warnFile = True
|
||||
|
||||
_ = unicodeencode(re.sub(r"[^\w]", UNSAFE_DUMP_FILEPATH_REPLACEMENT, unsafeSQLIdentificatorNaming(db)))
|
||||
dumpDbPath = os.path.join(conf.dumpPath, "%s-%s" % (_, hashlib.md5(unicodeencode(db)).hexdigest()[:8]))
|
||||
_ = re.sub(r"[^\w]", UNSAFE_DUMP_FILEPATH_REPLACEMENT, unsafeSQLIdentificatorNaming(db))
|
||||
dumpDbPath = os.path.join(conf.dumpPath, "%s-%s" % (_, hashlib.md5(getBytes(db)).hexdigest()[:8]))
|
||||
|
||||
if not os.path.isdir(dumpDbPath):
|
||||
try:
|
||||
@@ -456,8 +456,8 @@ class Dump(object):
|
||||
|
||||
_ = re.sub(r"[^\w]", UNSAFE_DUMP_FILEPATH_REPLACEMENT, normalizeUnicode(unsafeSQLIdentificatorNaming(table)))
|
||||
if len(_) < len(table) or IS_WIN and table.upper() in WINDOWS_RESERVED_NAMES:
|
||||
_ = unicodeencode(re.sub(r"[^\w]", UNSAFE_DUMP_FILEPATH_REPLACEMENT, unsafeSQLIdentificatorNaming(table)))
|
||||
dumpFileName = os.path.join(dumpDbPath, "%s-%s.%s" % (_, hashlib.md5(unicodeencode(table)).hexdigest()[:8], conf.dumpFormat.lower()))
|
||||
_ = re.sub(r"[^\w]", UNSAFE_DUMP_FILEPATH_REPLACEMENT, unsafeSQLIdentificatorNaming(table))
|
||||
dumpFileName = os.path.join(dumpDbPath, "%s-%s.%s" % (_, hashlib.md5(getBytes(table)).hexdigest()[:8], conf.dumpFormat.lower()))
|
||||
else:
|
||||
dumpFileName = os.path.join(dumpDbPath, "%s.%s" % (_, conf.dumpFormat.lower()))
|
||||
else:
|
||||
@@ -704,7 +704,7 @@ class Dump(object):
|
||||
|
||||
self.dbTableColumns(_)
|
||||
|
||||
def query(self, query, queryRes):
|
||||
def sqlQuery(self, query, queryRes):
|
||||
self.string(query, queryRes, content_type=CONTENT_TYPE.SQL_QUERY)
|
||||
|
||||
def rFile(self, fileData):
|
||||
|
||||
+25
-14
@@ -293,22 +293,25 @@ def _setRequestFromFile():
|
||||
"""
|
||||
|
||||
if conf.requestFile:
|
||||
conf.requestFile = safeExpandUser(conf.requestFile)
|
||||
seen = set()
|
||||
for requestFile in re.split(PARAMETER_SPLITTING_REGEX, conf.requestFile):
|
||||
requestFile = safeExpandUser(requestFile)
|
||||
seen = set()
|
||||
|
||||
if not checkFile(conf.requestFile, False):
|
||||
errMsg = "specified HTTP request file '%s' " % conf.requestFile
|
||||
errMsg += "does not exist"
|
||||
raise SqlmapFilePathException(errMsg)
|
||||
if not checkFile(requestFile, False):
|
||||
errMsg = "specified HTTP request file '%s' " % requestFile
|
||||
errMsg += "does not exist"
|
||||
raise SqlmapFilePathException(errMsg)
|
||||
|
||||
infoMsg = "parsing HTTP request from '%s'" % conf.requestFile
|
||||
logger.info(infoMsg)
|
||||
infoMsg = "parsing HTTP request from '%s'" % requestFile
|
||||
logger.info(infoMsg)
|
||||
|
||||
for target in parseRequestFile(conf.requestFile):
|
||||
url = target[0]
|
||||
if url not in seen:
|
||||
kb.targets.add(target)
|
||||
seen.add(url)
|
||||
for target in parseRequestFile(requestFile):
|
||||
url = target[0]
|
||||
if url not in seen:
|
||||
kb.targets.add(target)
|
||||
if len(kb.targets) > 1:
|
||||
conf.multipleTargets = True
|
||||
seen.add(url)
|
||||
|
||||
if conf.secondReq:
|
||||
conf.secondReq = safeExpandUser(conf.secondReq)
|
||||
@@ -1140,6 +1143,7 @@ def _setHTTPHandlers():
|
||||
handlers.append(keepAliveHandler)
|
||||
|
||||
opener = _urllib.request.build_opener(*handlers)
|
||||
opener.addheaders = [] # Note: clearing default "User-Agent: Python-urllib/X.Y"
|
||||
_urllib.request.install_opener(opener)
|
||||
|
||||
def _setSafeVisit():
|
||||
@@ -1613,6 +1617,13 @@ def _cleanupOptions():
|
||||
else:
|
||||
conf.testParameter = []
|
||||
|
||||
if conf.base64Parameter:
|
||||
conf.base64Parameter = urldecode(conf.base64Parameter)
|
||||
conf.base64Parameter = conf.base64Parameter.replace(" ", "")
|
||||
conf.base64Parameter = re.split(PARAMETER_SPLITTING_REGEX, conf.base64Parameter)
|
||||
else:
|
||||
conf.base64Parameter = []
|
||||
|
||||
if conf.agent:
|
||||
conf.agent = re.sub(r"[\r\n]", "", conf.agent)
|
||||
|
||||
@@ -1705,7 +1716,7 @@ def _cleanupOptions():
|
||||
except re.error:
|
||||
conf.csrfToken = re.escape(conf.csrfToken)
|
||||
finally:
|
||||
class _(unicode):
|
||||
class _(six.text_type):
|
||||
pass
|
||||
conf.csrfToken = _(conf.csrfToken)
|
||||
conf.csrfToken._original = original
|
||||
|
||||
@@ -150,7 +150,7 @@ optDict = {
|
||||
"limitStop": "integer",
|
||||
"firstChar": "integer",
|
||||
"lastChar": "integer",
|
||||
"query": "string",
|
||||
"sqlQuery": "string",
|
||||
"sqlShell": "boolean",
|
||||
"sqlFile": "string",
|
||||
},
|
||||
|
||||
+21
-4
@@ -17,7 +17,7 @@ from lib.core.enums import DBMS_DIRECTORY_NAME
|
||||
from lib.core.enums import OS
|
||||
|
||||
# sqlmap version (<major>.<minor>.<month>.<monthly commit>)
|
||||
VERSION = "1.3.4.0"
|
||||
VERSION = "1.3.5.0"
|
||||
TYPE = "dev" if VERSION.count('.') > 2 and VERSION.split('.')[-1] != '0' else "stable"
|
||||
TYPE_COLORS = {"dev": 33, "stable": 90, "pip": 34}
|
||||
VERSION_STRING = "sqlmap/%s#%s" % ('.'.join(VERSION.split('.')[:-1]) if VERSION.count('.') > 2 and VERSION.split('.')[-1] == '0' else VERSION, TYPE)
|
||||
@@ -65,6 +65,7 @@ ASTERISK_MARKER = "__ASTERISK_MARK__"
|
||||
REPLACEMENT_MARKER = "__REPLACEMENT_MARK__"
|
||||
BOUNDED_INJECTION_MARKER = "__BOUNDED_INJECTION_MARK__"
|
||||
SAFE_VARIABLE_MARKER = "__SAFE__"
|
||||
SAFE_HEX_MARKER = "__SAFE_HEX__"
|
||||
|
||||
RANDOM_INTEGER_MARKER = "[RANDINT]"
|
||||
RANDOM_STRING_MARKER = "[RANDSTR]"
|
||||
@@ -336,6 +337,7 @@ ERROR_PARSING_REGEXES = (
|
||||
r"\[Microsoft\]\[ODBC SQL Server Driver\]\[SQL Server\](?P<result>[^<]+)",
|
||||
r"<b>[^<]*(fatal|error|warning|exception)[^<]*</b>:?\s*(?P<result>[^<]+)",
|
||||
r"(?m)^\s*(fatal|error|warning|exception):?\s*(?P<result>[^\n]+?)$",
|
||||
r"(sql|dbc)[^>'\"]{0,32}(fatal|error|warning|exception)(</b>)?:\s*(?P<result>[^<>]+)",
|
||||
r"(?P<result>[^\n>]*SQL Syntax[^\n<]+)",
|
||||
r"(?s)<li>Error Type:<br>(?P<result>.+?)</li>",
|
||||
r"CDbCommand (?P<result>[^<>\n]*SQL[^<>\n]+)",
|
||||
@@ -381,7 +383,7 @@ URI_INJECTABLE_REGEX = r"//[^/]*/([^\.*?]+)\Z"
|
||||
SENSITIVE_DATA_REGEX = r"(\s|=)(?P<result>[^\s=]*\b%s\b[^\s]*)\s"
|
||||
|
||||
# Options to explicitly mask in anonymous (unhandled exception) reports (along with anything carrying the <hostname> inside)
|
||||
SENSITIVE_OPTIONS = ("hostname", "answers", "data", "dnsDomain", "googleDork", "authCred", "proxyCred", "tbl", "db", "col", "user", "cookie", "proxy", "fileRead", "fileWrite", "fileDest", "testParameter", "authCred")
|
||||
SENSITIVE_OPTIONS = ("hostname", "answers", "data", "dnsDomain", "googleDork", "authCred", "proxyCred", "tbl", "db", "col", "user", "cookie", "proxy", "fileRead", "fileWrite", "fileDest", "testParameter", "authCred", "sqlQuery")
|
||||
|
||||
# Maximum number of threads (avoiding connection issues and/or DoS)
|
||||
MAX_NUMBER_OF_THREADS = 10
|
||||
@@ -530,6 +532,9 @@ BRUTE_COLUMN_EXISTS_TEMPLATE = "EXISTS(SELECT %s FROM %s)"
|
||||
# Data inside shellcodeexec to be filled with random string
|
||||
SHELLCODEEXEC_RANDOM_STRING_MARKER = "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
|
||||
|
||||
# Period after last-update to start nagging about the old revision
|
||||
LAST_UPDATE_NAGGING_DAYS = 60
|
||||
|
||||
# Generic address for checking the Internet connection while using switch --check-internet
|
||||
CHECK_INTERNET_ADDRESS = "https://ipinfo.io/"
|
||||
|
||||
@@ -676,7 +681,7 @@ VALID_TIME_CHARS_RUN_THRESHOLD = 100
|
||||
CHECK_ZERO_COLUMNS_THRESHOLD = 10
|
||||
|
||||
# Boldify all logger messages containing these "patterns"
|
||||
BOLD_PATTERNS = ("' injectable", "provided empty", "leftover chars", "might be injectable", "' is vulnerable", "is not injectable", "does not seem to be", "test failed", "test passed", "live test final result", "test shows that", "the back-end DBMS is", "created Github", "blocked by the target server", "protection is involved", "CAPTCHA", "specific response", "NULL connection is supported", "PASSED", "FAILED")
|
||||
BOLD_PATTERNS = ("' injectable", "provided empty", "leftover chars", "might be injectable", "' is vulnerable", "is not injectable", "does not seem to be", "test failed", "test passed", "live test final result", "test shows that", "the back-end DBMS is", "created Github", "blocked by the target server", "protection is involved", "CAPTCHA", "specific response", "NULL connection is supported", "PASSED", "FAILED", "for more than")
|
||||
|
||||
# TLDs used in randomization of email-alike parameter values
|
||||
RANDOMIZATION_TLDS = ("com", "net", "ru", "org", "de", "jp", "cn", "fr", "it", "pl", "tv", "edu", "in", "ir", "es", "me", "info", "gr", "gov", "ca", "co", "se", "cz", "to", "vn", "nl", "cc", "az", "hu", "ua", "be", "no", "biz", "io", "ch", "ro", "sk", "eu", "us", "tw", "pt", "fi", "at", "lt", "kz", "cl", "hr", "pk", "lv", "la", "pe")
|
||||
@@ -711,6 +716,9 @@ RESTAPI_DEFAULT_ADDRESS = "127.0.0.1"
|
||||
# Default REST-JSON API server listen port
|
||||
RESTAPI_DEFAULT_PORT = 8775
|
||||
|
||||
# Use "Supplementary Private Use Area-A"
|
||||
INVALID_UNICODE_PRIVATE_AREA = False
|
||||
|
||||
# Format used for representing invalid unicode characters
|
||||
INVALID_UNICODE_CHAR_FORMAT = r"\x%02x"
|
||||
|
||||
@@ -818,9 +826,18 @@ th{
|
||||
</style>"""
|
||||
|
||||
# Leaving (dirty) possibility to change values from here (e.g. `export SQLMAP__MAX_NUMBER_OF_THREADS=20`)
|
||||
|
||||
for key, value in os.environ.items():
|
||||
if key.upper().startswith("%s_" % SQLMAP_ENVIRONMENT_PREFIX):
|
||||
_ = key[len(SQLMAP_ENVIRONMENT_PREFIX) + 1:].upper()
|
||||
if _ in globals():
|
||||
globals()[_] = value
|
||||
|
||||
# Installing "reversible" unicode (decoding) error handler
|
||||
def _reversible(ex):
|
||||
if isinstance(ex, UnicodeDecodeError):
|
||||
if INVALID_UNICODE_PRIVATE_AREA:
|
||||
return ("".join(unichr(int('000f00%2x' % ord(_), 16)) for _ in ex.object[ex.start:ex.end]), ex.end)
|
||||
else:
|
||||
return ("".join(INVALID_UNICODE_CHAR_FORMAT % ord(_) for _ in ex.object[ex.start:ex.end]).decode(UNICODE_ENCODING), ex.end)
|
||||
|
||||
codecs.register_error("reversible", _reversible)
|
||||
|
||||
+4
-3
@@ -73,6 +73,7 @@ from lib.core.settings import URI_INJECTABLE_REGEX
|
||||
from lib.core.settings import USER_AGENT_ALIASES
|
||||
from lib.core.settings import XML_RECOGNITION_REGEX
|
||||
from lib.utils.hashdb import HashDB
|
||||
from thirdparty import six
|
||||
from thirdparty.odict import OrderedDict
|
||||
from thirdparty.six.moves import urllib as _urllib
|
||||
|
||||
@@ -409,7 +410,7 @@ def _setRequestParams():
|
||||
message += "Do you want sqlmap to automatically update it in further requests? [y/N] "
|
||||
|
||||
if readInput(message, default='N', boolean=True):
|
||||
class _(unicode):
|
||||
class _(six.text_type):
|
||||
pass
|
||||
conf.csrfToken = _(re.escape(getUnicode(parameter)))
|
||||
conf.csrfToken._original = getUnicode(parameter)
|
||||
@@ -712,7 +713,7 @@ def initTargetEnv():
|
||||
_setDBMS()
|
||||
|
||||
if conf.data:
|
||||
class _(unicode):
|
||||
class _(six.text_type):
|
||||
pass
|
||||
|
||||
kb.postUrlEncode = True
|
||||
@@ -728,7 +729,7 @@ def initTargetEnv():
|
||||
setattr(conf.data, UNENCODED_ORIGINAL_VALUE, original)
|
||||
kb.postSpaceToPlus = '+' in original
|
||||
|
||||
match = re.search(INJECT_HERE_REGEX, conf.data or "") or re.search(INJECT_HERE_REGEX, conf.url or "")
|
||||
match = re.search(INJECT_HERE_REGEX, "%s %s %s" % (conf.url, conf.data, conf.httpHeaders))
|
||||
kb.customInjectionMark = match.group(0) if match else CUSTOM_INJECTION_MARK_CHAR
|
||||
|
||||
def setupTargetEnv():
|
||||
|
||||
+47
-4
@@ -8,21 +8,24 @@ See the file 'LICENSE' for copying permission
|
||||
import codecs
|
||||
import doctest
|
||||
import os
|
||||
import random
|
||||
import re
|
||||
import shutil
|
||||
import sys
|
||||
import tempfile
|
||||
import threading
|
||||
import time
|
||||
import traceback
|
||||
|
||||
from extra.beep.beep import beep
|
||||
from extra.vulnserver import vulnserver
|
||||
from lib.controller.controller import start
|
||||
from lib.core.common import checkIntegrity
|
||||
from lib.core.common import clearConsoleLine
|
||||
from lib.core.common import dataToStdout
|
||||
from lib.core.common import getUnicode
|
||||
from lib.core.common import randomStr
|
||||
from lib.core.common import readXmlFile
|
||||
from lib.core.common import shellExec
|
||||
from lib.core.data import conf
|
||||
from lib.core.data import logger
|
||||
from lib.core.data import paths
|
||||
@@ -44,6 +47,49 @@ class Failures(object):
|
||||
|
||||
_failures = Failures()
|
||||
|
||||
def vulnTest():
|
||||
"""
|
||||
Runs the testing against 'vulnserver'
|
||||
"""
|
||||
|
||||
retVal = True
|
||||
count, length = 0, 6
|
||||
address, port = "127.0.0.10", random.randint(1025, 65535)
|
||||
|
||||
def _thread():
|
||||
vulnserver.init(quiet=True)
|
||||
vulnserver.run(address=address, port=port)
|
||||
|
||||
thread = threading.Thread(target=_thread)
|
||||
thread.daemon = True
|
||||
thread.start()
|
||||
|
||||
for options, checks in (
|
||||
("--flush-session --identify-waf", ("CloudFlare",)),
|
||||
("--flush-session --parse-errors", (": syntax error", "Type: boolean-based blind", "Type: time-based blind", "Type: UNION query", "back-end DBMS: SQLite", "3 columns")),
|
||||
("--banner --schema --dump -T users --binary-fields=surname --where 'id>3'", ("banner: '3", "INTEGER", "TEXT", "id", "name", "surname", "2 entries", "6E616D6569736E756C6C")),
|
||||
("--all --tamper=between,randomcase", ("5 entries", "luther", "blisset", "fluffy", "179ad45c6ce2cb97cf1029e212046e81", "NULL", "nameisnull", "testpass")),
|
||||
("--technique=B --hex --fresh-queries --threads=4 --sql-query='SELECT 987654321'", ("length of query output", ": '987654321'",)),
|
||||
("--technique=T --fresh-queries --sql-query='SELECT 1234'", (": '1234'",)),
|
||||
):
|
||||
output = shellExec("%s %s -u http://%s:%d/?id=1 --batch %s" % (sys.executable, os.path.join(os.path.dirname(__file__), "..", "..", "sqlmap.py"), address, port, options))
|
||||
output = getUnicode(output)
|
||||
|
||||
if not all(check in output for check in checks):
|
||||
retVal = False
|
||||
|
||||
count += 1
|
||||
status = '%d/%d (%d%%) ' % (count, length, round(100.0 * count / length))
|
||||
dataToStdout("\r[%s] [INFO] complete: %s" % (time.strftime("%X"), status))
|
||||
|
||||
clearConsoleLine()
|
||||
if retVal:
|
||||
logger.info("vuln test final result: PASSED")
|
||||
else:
|
||||
logger.error("vuln test final result: FAILED")
|
||||
|
||||
return retVal
|
||||
|
||||
def smokeTest():
|
||||
"""
|
||||
Runs the basic smoke testing of a program
|
||||
@@ -52,9 +98,6 @@ def smokeTest():
|
||||
retVal = True
|
||||
count, length = 0, 0
|
||||
|
||||
if not checkIntegrity():
|
||||
retVal = False
|
||||
|
||||
for root, _, files in os.walk(paths.SQLMAP_ROOT_PATH):
|
||||
if any(_ in root for _ in ("thirdparty", "extra")):
|
||||
continue
|
||||
|
||||
+1
-1
@@ -100,7 +100,7 @@ def exceptionHandledFunction(threadFunction, silent=False):
|
||||
errMsg = ex.message if isinstance(ex, SqlmapBaseException) else "%s: %s" % (type(ex).__name__, ex.message)
|
||||
logger.error("thread %s: '%s'" % (threading.currentThread().getName(), errMsg))
|
||||
|
||||
if conf.get("verbose") > 1:
|
||||
if conf.get("verbose") > 1 and not isinstance(ex, (SqlmapUserQuitException,)):
|
||||
traceback.print_exc()
|
||||
|
||||
def setDaemon(thread):
|
||||
|
||||
+24
-8
@@ -40,6 +40,7 @@ from lib.core.shell import autoCompletion
|
||||
from lib.core.shell import clearHistory
|
||||
from lib.core.shell import loadHistory
|
||||
from lib.core.shell import saveHistory
|
||||
from thirdparty.six.moves import input as _input
|
||||
|
||||
def cmdLineParser(argv=None):
|
||||
"""
|
||||
@@ -54,7 +55,7 @@ def cmdLineParser(argv=None):
|
||||
# Reference: https://stackoverflow.com/a/4012683 (Note: previously used "...sys.getfilesystemencoding() or UNICODE_ENCODING")
|
||||
_ = getUnicode(os.path.basename(argv[0]), encoding=sys.stdin.encoding)
|
||||
|
||||
usage = "%s%s [options]" % ("python " if not IS_WIN else "", "\"%s\"" % _ if " " in _ else _)
|
||||
usage = "%s%s [options]" % ("%s " % os.path.basename(sys.executable) if not IS_WIN else "", "\"%s\"" % _ if " " in _ else _)
|
||||
parser = OptionParser(usage=usage)
|
||||
|
||||
try:
|
||||
@@ -224,7 +225,7 @@ def cmdLineParser(argv=None):
|
||||
|
||||
request.add_option("--eval", dest="evalCode",
|
||||
help="Evaluate provided Python code before the request (e.g. \"import hashlib;id2=hashlib.md5(id).hexdigest()\")")
|
||||
|
||||
|
||||
# Optimization options
|
||||
optimization = OptionGroup(parser, "Optimization", "These options can be used to optimize the performance of sqlmap")
|
||||
|
||||
@@ -448,7 +449,7 @@ def cmdLineParser(argv=None):
|
||||
enumeration.add_option("--last", dest="lastChar", type="int",
|
||||
help="Last query output word character to retrieve")
|
||||
|
||||
enumeration.add_option("--sql-query", dest="query",
|
||||
enumeration.add_option("--sql-query", dest="sqlQuery",
|
||||
help="SQL statement to be executed")
|
||||
|
||||
enumeration.add_option("--sql-shell", dest="sqlShell", action="store_true",
|
||||
@@ -600,7 +601,7 @@ def cmdLineParser(argv=None):
|
||||
help="Parse and display DBMS error messages from responses")
|
||||
|
||||
general.add_option("--preprocess", dest="preprocess",
|
||||
help="Use given script(s) for preprocessing of response data")
|
||||
help="Use given script(s) for preprocessing of response data")
|
||||
|
||||
general.add_option("--repair", dest="repair", action="store_true",
|
||||
help="Redump entries having unknown character marker (%s)" % INFERENCE_UNKNOWN_CHAR)
|
||||
@@ -681,6 +682,10 @@ def cmdLineParser(argv=None):
|
||||
help="Simple wizard interface for beginner users")
|
||||
|
||||
# Hidden and/or experimental options
|
||||
parser.add_option("--base64", dest="base64Parameter",
|
||||
help=SUPPRESS_HELP)
|
||||
# help="Parameter(s) containing Base64 encoded values")
|
||||
|
||||
parser.add_option("--crack", dest="hashFile",
|
||||
help=SUPPRESS_HELP)
|
||||
# help="Load and crack hashes from a file (standalone)")
|
||||
@@ -718,6 +723,9 @@ def cmdLineParser(argv=None):
|
||||
parser.add_option("--live-test", dest="liveTest", action="store_true",
|
||||
help=SUPPRESS_HELP)
|
||||
|
||||
parser.add_option("--vuln-test", dest="vulnTest", action="store_true",
|
||||
help=SUPPRESS_HELP)
|
||||
|
||||
parser.add_option("--stop-fail", dest="stopFail", action="store_true",
|
||||
help=SUPPRESS_HELP)
|
||||
|
||||
@@ -755,7 +763,7 @@ def cmdLineParser(argv=None):
|
||||
return retVal
|
||||
|
||||
parser.formatter._format_option_strings = parser.formatter.format_option_strings
|
||||
parser.formatter.format_option_strings = type(parser.formatter.format_option_strings)(_, parser, type(parser))
|
||||
parser.formatter.format_option_strings = type(parser.formatter.format_option_strings)(_, parser)
|
||||
|
||||
# Dirty hack for making a short option '-hh'
|
||||
option = parser.get_option("--hh")
|
||||
@@ -802,7 +810,7 @@ def cmdLineParser(argv=None):
|
||||
command = None
|
||||
|
||||
try:
|
||||
command = raw_input("sqlmap-shell> ").strip()
|
||||
command = _input("sqlmap-shell> ").strip()
|
||||
command = getUnicode(command, encoding=sys.stdin.encoding)
|
||||
except (KeyboardInterrupt, EOFError):
|
||||
print()
|
||||
@@ -851,6 +859,14 @@ def cmdLineParser(argv=None):
|
||||
elif argv[i] == "-H":
|
||||
if i + 1 < len(argv):
|
||||
extraHeaders.append(argv[i + 1])
|
||||
elif argv[i] == "-r":
|
||||
for j in xrange(i + 2, len(argv)):
|
||||
value = argv[j]
|
||||
if os.path.isfile(value):
|
||||
argv[i + 1] += ",%s" % value
|
||||
argv[j] = ''
|
||||
else:
|
||||
break
|
||||
elif re.match(r"\A\d+!\Z", argv[i]) and argv[max(0, i - 1)] == "--threads" or re.match(r"\A--threads.+\d+!\Z", argv[i]):
|
||||
argv[i] = argv[i][:-1]
|
||||
conf.skipThreadCheck = True
|
||||
@@ -901,7 +917,7 @@ def cmdLineParser(argv=None):
|
||||
if args.dummy:
|
||||
args.url = args.url or DUMMY_URL
|
||||
|
||||
if not any((args.direct, args.url, args.logFile, args.bulkFile, args.googleDork, args.configFile, args.requestFile, args.updateAll, args.smokeTest, args.liveTest, args.wizard, args.dependencies, args.purge, args.sitemapUrl, args.listTampers, args.hashFile)):
|
||||
if not any((args.direct, args.url, args.logFile, args.bulkFile, args.googleDork, args.configFile, args.requestFile, args.updateAll, args.smokeTest, args.vulnTest, args.liveTest, args.wizard, args.dependencies, args.purge, args.sitemapUrl, args.listTampers, args.hashFile)):
|
||||
errMsg = "missing a mandatory option (-d, -u, -l, -m, -r, -g, -c, -x, --list-tampers, --wizard, --update, --purge or --dependencies). "
|
||||
errMsg += "Use -h for basic and -hh for advanced help\n"
|
||||
parser.error(errMsg)
|
||||
@@ -915,7 +931,7 @@ def cmdLineParser(argv=None):
|
||||
# Protection against Windows dummy double clicking
|
||||
if IS_WIN:
|
||||
dataToStdout("\nPress Enter to continue...")
|
||||
raw_input()
|
||||
_input()
|
||||
raise
|
||||
|
||||
debugMsg = "parsing command line"
|
||||
|
||||
@@ -5,13 +5,13 @@ Copyright (c) 2006-2019 sqlmap developers (http://sqlmap.org/)
|
||||
See the file 'LICENSE' for copying permission
|
||||
"""
|
||||
|
||||
import itertools
|
||||
import os
|
||||
|
||||
from lib.core.common import parseXmlFile
|
||||
from lib.core.data import kb
|
||||
from lib.core.data import paths
|
||||
from lib.parse.handler import FingerprintHandler
|
||||
from thirdparty.six.moves import filter as _filter
|
||||
|
||||
def headersParser(headers):
|
||||
"""
|
||||
@@ -30,7 +30,7 @@ def headersParser(headers):
|
||||
"x-powered-by": os.path.join(paths.SQLMAP_XML_BANNER_PATH, "x-powered-by.xml"),
|
||||
}
|
||||
|
||||
for header in itertools.ifilter(lambda _: _ in kb.headerPaths, headers):
|
||||
for header in _filter(lambda _: _ in kb.headerPaths, headers):
|
||||
value = headers[header]
|
||||
xmlfile = kb.headerPaths[header]
|
||||
handler = FingerprintHandler(value, kb.headersFp)
|
||||
|
||||
+16
-11
@@ -14,9 +14,11 @@ import struct
|
||||
import zlib
|
||||
|
||||
from lib.core.common import Backend
|
||||
from lib.core.common import decodeHex
|
||||
from lib.core.common import extractErrorMessage
|
||||
from lib.core.common import extractRegexResult
|
||||
from lib.core.common import filterNone
|
||||
from lib.core.common import getBytes
|
||||
from lib.core.common import getPublicTypeMembers
|
||||
from lib.core.common import getSafeExString
|
||||
from lib.core.common import getUnicode
|
||||
@@ -42,11 +44,11 @@ from lib.core.settings import MAX_CONNECTION_TOTAL_SIZE
|
||||
from lib.core.settings import META_CHARSET_REGEX
|
||||
from lib.core.settings import PARSE_HEADERS_LIMIT
|
||||
from lib.core.settings import SELECT_FROM_TABLE_REGEX
|
||||
from lib.core.settings import UNICODE_ENCODING
|
||||
from lib.core.settings import VIEWSTATE_REGEX
|
||||
from lib.parse.headers import headersParser
|
||||
from lib.parse.html import htmlParser
|
||||
from lib.utils.htmlentities import htmlEntities
|
||||
from thirdparty import six
|
||||
from thirdparty.chardet import detect
|
||||
from thirdparty.odict import OrderedDict
|
||||
|
||||
@@ -155,6 +157,9 @@ def checkCharEncoding(encoding, warn=True):
|
||||
'utf8'
|
||||
"""
|
||||
|
||||
if isinstance(encoding, six.binary_type):
|
||||
encoding = getUnicode(encoding)
|
||||
|
||||
if isListLike(encoding):
|
||||
encoding = unArrayizeValue(encoding)
|
||||
|
||||
@@ -219,13 +224,13 @@ def checkCharEncoding(encoding, warn=True):
|
||||
# Reference: http://www.iana.org/assignments/character-sets
|
||||
# Reference: http://docs.python.org/library/codecs.html
|
||||
try:
|
||||
codecs.lookup(encoding.encode(UNICODE_ENCODING) if isinstance(encoding, unicode) else encoding)
|
||||
except (LookupError, ValueError):
|
||||
codecs.lookup(encoding)
|
||||
except:
|
||||
encoding = None
|
||||
|
||||
if encoding:
|
||||
try:
|
||||
unicode(randomStr(), encoding)
|
||||
six.text_type(getBytes(randomStr()), encoding)
|
||||
except:
|
||||
if warn:
|
||||
warnMsg = "invalid web page charset '%s'" % encoding
|
||||
@@ -313,18 +318,18 @@ def decodePage(page, contentEncoding, contentType):
|
||||
kb.pageEncoding = conf.encoding
|
||||
|
||||
# can't do for all responses because we need to support binary files too
|
||||
if not isinstance(page, unicode) and "text/" in contentType:
|
||||
if isinstance(page, six.binary_type) and "text/" in contentType:
|
||||
# e.g. 	Ãëàâà
|
||||
if "&#" in page:
|
||||
page = re.sub(r"&#x([0-9a-f]{1,2});", lambda _: (_.group(1) if len(_.group(1)) == 2 else "0%s" % _.group(1)).decode("hex"), page)
|
||||
page = re.sub(r"&#(\d{1,3});", lambda _: chr(int(_.group(1))) if int(_.group(1)) < 256 else _.group(0), page)
|
||||
if b"&#" in page:
|
||||
page = re.sub(b"&#x([0-9a-f]{1,2});", lambda _: decodeHex(_.group(1) if len(_.group(1)) == 2 else "0%s" % _.group(1)), page)
|
||||
page = re.sub(b"&#(\d{1,3});", lambda _: chr(int(_.group(1))) if int(_.group(1)) < 256 else _.group(0), page)
|
||||
|
||||
# e.g. %20%28%29
|
||||
if "%" in page:
|
||||
page = re.sub(r"%([0-9a-fA-F]{2})", lambda _: _.group(1).decode("hex"), page)
|
||||
if b"%" in page:
|
||||
page = re.sub(b"%([0-9a-fA-F]{2})", lambda _: decodeHex(_.group(1)), page)
|
||||
|
||||
# e.g. &
|
||||
page = re.sub(r"&([^;]+);", lambda _: chr(htmlEntities[_.group(1)]) if htmlEntities.get(_.group(1), 256) < 256 else _.group(0), page)
|
||||
page = re.sub(b"&([^;]+);", lambda _: chr(htmlEntities[_.group(1)]) if htmlEntities.get(_.group(1), 256) < 256 else _.group(0), page)
|
||||
|
||||
kb.pageEncoding = kb.pageEncoding or checkCharEncoding(getHeuristicCharEncoding(page))
|
||||
|
||||
|
||||
@@ -8,6 +8,7 @@ See the file 'LICENSE' for copying permission
|
||||
import re
|
||||
|
||||
from lib.core.common import extractRegexResult
|
||||
from lib.core.common import getBytes
|
||||
from lib.core.common import getFilteredPageContent
|
||||
from lib.core.common import listToStrValue
|
||||
from lib.core.common import removeDynamicContent
|
||||
@@ -28,6 +29,7 @@ from lib.core.settings import LOWER_RATIO_BOUND
|
||||
from lib.core.settings import UPPER_RATIO_BOUND
|
||||
from lib.core.settings import URI_HTTP_HEADER
|
||||
from lib.core.threads import getCurrentThreadData
|
||||
from thirdparty import six
|
||||
|
||||
def comparison(page, headers, code=None, getRatioValue=False, pageLength=None):
|
||||
_ = _adjust(_comparison(page, headers, code, getRatioValue, pageLength), getRatioValue)
|
||||
@@ -105,10 +107,10 @@ def _comparison(page, headers, code, getRatioValue, pageLength):
|
||||
else:
|
||||
# Preventing "Unicode equal comparison failed to convert both arguments to Unicode"
|
||||
# (e.g. if one page is PDF and the other is HTML)
|
||||
if isinstance(seqMatcher.a, str) and isinstance(page, unicode):
|
||||
page = page.encode(kb.pageEncoding or DEFAULT_PAGE_ENCODING, "ignore")
|
||||
elif isinstance(seqMatcher.a, unicode) and isinstance(page, str):
|
||||
seqMatcher.a = seqMatcher.a.encode(kb.pageEncoding or DEFAULT_PAGE_ENCODING, "ignore")
|
||||
if isinstance(seqMatcher.a, six.binary_type) and isinstance(page, six.text_type):
|
||||
page = getBytes(page, kb.pageEncoding or DEFAULT_PAGE_ENCODING, "ignore")
|
||||
elif isinstance(seqMatcher.a, six.text_type) and isinstance(page, six.binary_type):
|
||||
seqMatcher.a = getBytes(seqMatcher.a, kb.pageEncoding or DEFAULT_PAGE_ENCODING, "ignore")
|
||||
|
||||
if any(_ is None for _ in (page, seqMatcher.a)):
|
||||
return None
|
||||
|
||||
+50
-39
@@ -34,6 +34,7 @@ from lib.core.common import evaluateCode
|
||||
from lib.core.common import extractRegexResult
|
||||
from lib.core.common import filterNone
|
||||
from lib.core.common import findMultipartPostBoundary
|
||||
from lib.core.common import getBytes
|
||||
from lib.core.common import getCurrentThreadData
|
||||
from lib.core.common import getHeader
|
||||
from lib.core.common import getHostHeader
|
||||
@@ -54,7 +55,6 @@ from lib.core.common import singleTimeLogMessage
|
||||
from lib.core.common import singleTimeWarnMessage
|
||||
from lib.core.common import stdev
|
||||
from lib.core.common import wasLastResponseDelayed
|
||||
from lib.core.common import unicodeencode
|
||||
from lib.core.common import unsafeVariableNaming
|
||||
from lib.core.common import urldecode
|
||||
from lib.core.common import urlencode
|
||||
@@ -82,6 +82,7 @@ from lib.core.exception import SqlmapConnectionException
|
||||
from lib.core.exception import SqlmapGenericException
|
||||
from lib.core.exception import SqlmapSyntaxException
|
||||
from lib.core.exception import SqlmapTokenException
|
||||
from lib.core.exception import SqlmapUserQuitException
|
||||
from lib.core.exception import SqlmapValueException
|
||||
from lib.core.settings import ASTERISK_MARKER
|
||||
from lib.core.settings import BOUNDARY_BACKSLASH_MARKER
|
||||
@@ -192,7 +193,7 @@ class Connect(object):
|
||||
|
||||
@staticmethod
|
||||
def _connReadProxy(conn):
|
||||
retVal = ""
|
||||
retVal = b""
|
||||
|
||||
if not kb.dnsMode and conn:
|
||||
headers = conn.info()
|
||||
@@ -277,7 +278,10 @@ class Connect(object):
|
||||
if multipart:
|
||||
post = multipart
|
||||
|
||||
if chunked and post:
|
||||
if not post:
|
||||
chunked = False
|
||||
|
||||
elif chunked:
|
||||
post = _urllib.parse.unquote(post)
|
||||
post = chunkSplitPostData(post)
|
||||
|
||||
@@ -402,22 +406,20 @@ class Connect(object):
|
||||
|
||||
if conf.keepAlive:
|
||||
headers[HTTP_HEADER.CONNECTION] = "keep-alive"
|
||||
|
||||
|
||||
if chunked:
|
||||
headers[HTTP_HEADER.TRANSFER_ENCODING] = "chunked"
|
||||
|
||||
if auxHeaders:
|
||||
headers = forgeHeaders(auxHeaders, headers)
|
||||
|
||||
for key, value in headers.items():
|
||||
for key, value in list(headers.items()):
|
||||
del headers[key]
|
||||
value = unicodeencode(value, kb.pageEncoding)
|
||||
for char in (r"\r", r"\n"):
|
||||
value = re.sub(r"(%s)([^ \t])" % char, r"\g<1>\t\g<2>", value)
|
||||
headers[unicodeencode(key, kb.pageEncoding)] = value.strip("\r\n")
|
||||
headers[getBytes(key)] = getBytes(value.strip("\r\n"))
|
||||
|
||||
url = unicodeencode(url)
|
||||
post = unicodeencode(post)
|
||||
post = getBytes(post)
|
||||
|
||||
if websocket_:
|
||||
ws = websocket.WebSocket()
|
||||
@@ -448,7 +450,7 @@ class Connect(object):
|
||||
logger.log(CUSTOM_LOGGING.TRAFFIC_OUT, requestMsg)
|
||||
else:
|
||||
if method and method not in (HTTPMETHOD.GET, HTTPMETHOD.POST):
|
||||
method = unicodeencode(method)
|
||||
method = getBytes(method)
|
||||
req = MethodRequest(url, post, headers)
|
||||
req.set_method(method)
|
||||
elif url is not None:
|
||||
@@ -604,7 +606,7 @@ class Connect(object):
|
||||
page = getUnicode(page)
|
||||
|
||||
code = ex.code
|
||||
status = getSafeExString(ex)
|
||||
status = getattr(ex, "reason", None) or getSafeExString(ex).split(": ", 1)[-1]
|
||||
|
||||
kb.originalCode = kb.originalCode or code
|
||||
threadData.lastHTTPError = (threadData.lastRequestUID, code, status)
|
||||
@@ -632,6 +634,12 @@ class Connect(object):
|
||||
errMsg = "not authorized, try to provide right HTTP "
|
||||
errMsg += "authentication type and valid credentials (%d)" % code
|
||||
raise SqlmapConnectionException(errMsg)
|
||||
elif chunked and ex.code in (_http_client.METHOD_NOT_ALLOWED, _http_client.LENGTH_REQUIRED):
|
||||
warnMsg = "turning off HTTP chunked transfer encoding "
|
||||
warnMsg += "as it seems that the target site doesn't support it (%d)" % code
|
||||
singleTimeWarnMessage(warnMsg)
|
||||
conf.chunked = kwargs["chunked"] = False
|
||||
return Connect.getPage(**kwargs)
|
||||
elif ex.code == _http_client.NOT_FOUND:
|
||||
if raise404:
|
||||
errMsg = "page not found (%d)" % code
|
||||
@@ -725,8 +733,11 @@ class Connect(object):
|
||||
|
||||
kb.connErrorChoice = readInput(message, default='N', boolean=True)
|
||||
|
||||
if kb.connErrorChoice is False:
|
||||
raise SqlmapConnectionException(warnMsg)
|
||||
if kb.connErrorChoice is not None:
|
||||
if kb.connErrorChoice:
|
||||
raise SqlmapConnectionException(warnMsg)
|
||||
else:
|
||||
raise SqlmapUserQuitException
|
||||
|
||||
if "forcibly closed" in tbMsg:
|
||||
logger.critical(warnMsg)
|
||||
@@ -769,33 +780,33 @@ class Connect(object):
|
||||
|
||||
processResponse(page, responseHeaders, status)
|
||||
|
||||
if conn and getattr(conn, "redurl", None):
|
||||
_ = _urllib.parse.urlsplit(conn.redurl)
|
||||
_ = ("%s%s" % (_.path or "/", ("?%s" % _.query) if _.query else ""))
|
||||
requestMsg = re.sub(r"(\n[A-Z]+ ).+?( HTTP/\d)", r"\g<1>%s\g<2>" % getUnicode(_).replace("\\", "\\\\"), requestMsg, 1)
|
||||
|
||||
if kb.resendPostOnRedirect is False:
|
||||
requestMsg = re.sub(r"(\[#\d+\]:\n)POST ", r"\g<1>GET ", requestMsg)
|
||||
requestMsg = re.sub(r"(?i)Content-length: \d+\n", "", requestMsg)
|
||||
requestMsg = re.sub(r"(?s)\n\n.+", "\n", requestMsg)
|
||||
|
||||
responseMsg += "[#%d] (%s %s):\r\n" % (threadData.lastRequestUID, conn.code, status)
|
||||
else:
|
||||
responseMsg += "[#%d] (%s %s):\r\n" % (threadData.lastRequestUID, code, status)
|
||||
|
||||
if responseHeaders:
|
||||
logHeaders = getUnicode("".join(responseHeaders.headers).strip())
|
||||
|
||||
if not skipLogTraffic:
|
||||
if conn and getattr(conn, "redurl", None):
|
||||
_ = _urllib.parse.urlsplit(conn.redurl)
|
||||
_ = ("%s%s" % (_.path or "/", ("?%s" % _.query) if _.query else ""))
|
||||
requestMsg = re.sub(r"(\n[A-Z]+ ).+?( HTTP/\d)", r"\g<1>%s\g<2>" % getUnicode(_).replace("\\", "\\\\"), requestMsg, 1)
|
||||
|
||||
if kb.resendPostOnRedirect is False:
|
||||
requestMsg = re.sub(r"(\[#\d+\]:\n)POST ", r"\g<1>GET ", requestMsg)
|
||||
requestMsg = re.sub(r"(?i)Content-length: \d+\n", "", requestMsg)
|
||||
requestMsg = re.sub(r"(?s)\n\n.+", "\n", requestMsg)
|
||||
|
||||
responseMsg += "[#%d] (%s %s):\r\n" % (threadData.lastRequestUID, conn.code, status)
|
||||
elif "\n" not in responseMsg:
|
||||
responseMsg += "[#%d] (%s %s):\r\n" % (threadData.lastRequestUID, code, status)
|
||||
|
||||
if responseHeaders:
|
||||
logHeaders = getUnicode("".join(responseHeaders.headers).strip() if six.PY2 else responseHeaders.__bytes__())
|
||||
|
||||
logHTTPTraffic(requestMsg, "%s%s\r\n\r\n%s" % (responseMsg, logHeaders, (page or "")[:MAX_CONNECTION_CHUNK_SIZE]), start, time.time())
|
||||
|
||||
if conf.verbose <= 5:
|
||||
responseMsg += getUnicode(logHeaders)
|
||||
elif conf.verbose > 5:
|
||||
responseMsg += "%s\r\n\r\n%s" % (logHeaders, (page or "")[:MAX_CONNECTION_CHUNK_SIZE])
|
||||
if conf.verbose <= 5:
|
||||
responseMsg += getUnicode(logHeaders)
|
||||
elif conf.verbose > 5:
|
||||
responseMsg += "%s\r\n\r\n%s" % (logHeaders, (page or "")[:MAX_CONNECTION_CHUNK_SIZE])
|
||||
|
||||
if not multipart:
|
||||
logger.log(CUSTOM_LOGGING.TRAFFIC_IN, responseMsg)
|
||||
if not multipart:
|
||||
logger.log(CUSTOM_LOGGING.TRAFFIC_IN, responseMsg)
|
||||
|
||||
return page, responseHeaders, code
|
||||
|
||||
@@ -839,7 +850,7 @@ class Connect(object):
|
||||
|
||||
if conf.httpHeaders:
|
||||
headers = OrderedDict(conf.httpHeaders)
|
||||
contentType = max(headers[_] if _.upper() == HTTP_HEADER.CONTENT_TYPE.upper() else None for _ in headers)
|
||||
contentType = max(headers[_] if _.upper() == HTTP_HEADER.CONTENT_TYPE.upper() else "" for _ in headers) or None
|
||||
|
||||
if (kb.postHint or conf.skipUrlEncode) and postUrlEncode:
|
||||
postUrlEncode = False
|
||||
@@ -1120,7 +1131,7 @@ class Connect(object):
|
||||
|
||||
while True:
|
||||
try:
|
||||
compile(unicodeencode(conf.evalCode.replace(';', '\n')), "", "exec")
|
||||
compile(getBytes(conf.evalCode.replace(';', '\n')), "", "exec")
|
||||
except SyntaxError as ex:
|
||||
if ex.text:
|
||||
original = replacement = ex.text.strip()
|
||||
@@ -1254,7 +1265,7 @@ class Connect(object):
|
||||
warnMsg += "10 or more)"
|
||||
logger.critical(warnMsg)
|
||||
|
||||
if conf.safeFreq > 0:
|
||||
if (conf.safeFreq or 0) > 0:
|
||||
kb.queryCounter += 1
|
||||
if kb.queryCounter % conf.safeFreq == 0:
|
||||
if conf.safeUrl:
|
||||
|
||||
@@ -486,7 +486,7 @@ def getValue(expression, blind=True, union=True, error=True, time=True, fromUser
|
||||
singleTimeWarnMessage(warnMsg)
|
||||
|
||||
# Dirty patch (safe-encoded unicode characters)
|
||||
if isinstance(value, unicode) and "\\x" in value:
|
||||
if isinstance(value, six.text_type) and "\\x" in value:
|
||||
try:
|
||||
candidate = eval(repr(value).replace("\\\\x", "\\x").replace("u'", "'", 1)).decode(conf.encoding or UNICODE_ENCODING)
|
||||
if "\\x" not in candidate:
|
||||
|
||||
@@ -28,6 +28,7 @@ from lib.request import inject
|
||||
from lib.takeover.udf import UDF
|
||||
from lib.takeover.web import Web
|
||||
from lib.takeover.xp_cmdshell import XP_cmdshell
|
||||
from thirdparty.six.moves import input as _input
|
||||
|
||||
class Abstraction(Web, UDF, XP_cmdshell):
|
||||
"""
|
||||
@@ -139,7 +140,7 @@ class Abstraction(Web, UDF, XP_cmdshell):
|
||||
command = None
|
||||
|
||||
try:
|
||||
command = raw_input("os-shell> ")
|
||||
command = _input("os-shell> ")
|
||||
command = getUnicode(command, encoding=sys.stdin.encoding)
|
||||
except KeyboardInterrupt:
|
||||
print()
|
||||
|
||||
@@ -21,6 +21,8 @@ from lib.core.common import dataToStdout
|
||||
from lib.core.common import extractRegexResult
|
||||
from lib.core.common import firstNotNone
|
||||
from lib.core.common import flattenValue
|
||||
from lib.core.common import safeStringFormat
|
||||
from lib.core.common import getBytes
|
||||
from lib.core.common import getConsoleWidth
|
||||
from lib.core.common import getPartRun
|
||||
from lib.core.common import getUnicode
|
||||
@@ -54,7 +56,6 @@ from lib.core.settings import MAX_BUFFERED_PARTIAL_UNION_LENGTH
|
||||
from lib.core.settings import NULL
|
||||
from lib.core.settings import SQL_SCALAR_REGEX
|
||||
from lib.core.settings import TURN_OFF_RESUME_INFO_LIMIT
|
||||
from lib.core.settings import UNICODE_ENCODING
|
||||
from lib.core.threads import getCurrentThreadData
|
||||
from lib.core.threads import runThreads
|
||||
from lib.core.unescaper import unescaper
|
||||
@@ -109,7 +110,7 @@ def _oneShotUnionUse(expression, unpack=True, limited=False):
|
||||
output = extractRegexResult(r"(?P<result>(<row.+?/>)+)", page)
|
||||
if output:
|
||||
try:
|
||||
root = xml.etree.ElementTree.fromstring("<root>%s</root>" % output.encode(UNICODE_ENCODING))
|
||||
root = xml.etree.ElementTree.fromstring(safeStringFormat("<root>%s</root>", getBytes(output)))
|
||||
retVal = ""
|
||||
for column in kb.dumpColumns:
|
||||
base64 = True
|
||||
|
||||
+2
-1
@@ -57,6 +57,7 @@ from thirdparty.bottle.bottle import response
|
||||
from thirdparty.bottle.bottle import run
|
||||
from thirdparty.bottle.bottle import server_names
|
||||
from thirdparty.six.moves import http_client as _http_client
|
||||
from thirdparty.six.moves import input as _input
|
||||
from thirdparty.six.moves import urllib as _urllib
|
||||
|
||||
# Global data storage
|
||||
@@ -762,7 +763,7 @@ def client(host=RESTAPI_DEFAULT_ADDRESS, port=RESTAPI_DEFAULT_PORT, username=Non
|
||||
|
||||
while True:
|
||||
try:
|
||||
command = raw_input("api%s> " % (" (%s)" % taskid if taskid else "")).strip()
|
||||
command = _input("api%s> " % (" (%s)" % taskid if taskid else "")).strip()
|
||||
command = re.sub(r"\A(\w+)", lambda match: match.group(1).lower(), command)
|
||||
except (EOFError, KeyboardInterrupt):
|
||||
print()
|
||||
|
||||
@@ -32,6 +32,7 @@ from lib.core.threads import getCurrentThreadData
|
||||
from lib.core.threads import runThreads
|
||||
from lib.parse.sitemap import parseSitemap
|
||||
from lib.request.connect import Connect as Request
|
||||
from thirdparty import six
|
||||
from thirdparty.beautifulsoup.beautifulsoup import BeautifulSoup
|
||||
from thirdparty.six.moves import http_client as _http_client
|
||||
from thirdparty.six.moves import urllib as _urllib
|
||||
@@ -79,7 +80,7 @@ def crawl(target):
|
||||
if not kb.threadContinue:
|
||||
break
|
||||
|
||||
if isinstance(content, unicode):
|
||||
if isinstance(content, six.text_type):
|
||||
try:
|
||||
match = re.search(r"(?si)<html[^>]*>(.+)</html>", content)
|
||||
if match:
|
||||
|
||||
+33
-76
@@ -50,6 +50,7 @@ from lib.core.common import Backend
|
||||
from lib.core.common import checkFile
|
||||
from lib.core.common import clearConsoleLine
|
||||
from lib.core.common import dataToStdout
|
||||
from lib.core.common import getBytes
|
||||
from lib.core.common import getFileItems
|
||||
from lib.core.common import getPublicTypeMembers
|
||||
from lib.core.common import getSafeExString
|
||||
@@ -102,8 +103,7 @@ def mysql_passwd(password, uppercase=True):
|
||||
'*00E247AC5F9AF26AE0194B41E1E769DEE1429A29'
|
||||
"""
|
||||
|
||||
if isinstance(password, six.text_type):
|
||||
password = password.encode(UNICODE_ENCODING)
|
||||
password = getBytes(password)
|
||||
|
||||
retVal = "*%s" % sha1(sha1(password).digest()).hexdigest()
|
||||
|
||||
@@ -143,11 +143,8 @@ def postgres_passwd(password, username, uppercase=False):
|
||||
'md599e5ea7a6f7c3269995cba3927fd0093'
|
||||
"""
|
||||
|
||||
if isinstance(username, six.text_type):
|
||||
username = username.encode(UNICODE_ENCODING)
|
||||
|
||||
if isinstance(password, six.text_type):
|
||||
password = password.encode(UNICODE_ENCODING)
|
||||
username = getBytes(username)
|
||||
password = getBytes(password)
|
||||
|
||||
retVal = "md5%s" % md5(password + username).hexdigest()
|
||||
|
||||
@@ -232,11 +229,8 @@ def oracle_old_passwd(password, username, uppercase=True): # prior to version '
|
||||
|
||||
IV, pad = "\0" * 8, "\0"
|
||||
|
||||
if isinstance(username, six.text_type):
|
||||
username = username.encode(UNICODE_ENCODING)
|
||||
|
||||
if isinstance(password, six.text_type):
|
||||
password = password.encode(UNICODE_ENCODING)
|
||||
username = getBytes(username)
|
||||
password = getBytes(password)
|
||||
|
||||
unistr = "".join("\0%s" % c for c in (username + password).upper())
|
||||
|
||||
@@ -255,8 +249,7 @@ def md5_generic_passwd(password, uppercase=False):
|
||||
'179ad45c6ce2cb97cf1029e212046e81'
|
||||
"""
|
||||
|
||||
if isinstance(password, six.text_type):
|
||||
password = password.encode(UNICODE_ENCODING)
|
||||
password = getBytes(password)
|
||||
|
||||
retVal = md5(password).hexdigest()
|
||||
|
||||
@@ -268,8 +261,7 @@ def sha1_generic_passwd(password, uppercase=False):
|
||||
'206c80413b9a96c1312cc346b7d2517b84463edd'
|
||||
"""
|
||||
|
||||
if isinstance(password, six.text_type):
|
||||
password = password.encode(UNICODE_ENCODING)
|
||||
password = getBytes(password)
|
||||
|
||||
retVal = sha1(password).hexdigest()
|
||||
|
||||
@@ -281,8 +273,7 @@ def apache_sha1_passwd(password, **kwargs):
|
||||
'{SHA}IGyAQTualsExLMNGt9JRe4RGPt0='
|
||||
"""
|
||||
|
||||
if isinstance(password, six.text_type):
|
||||
password = password.encode(UNICODE_ENCODING)
|
||||
password = getBytes(password)
|
||||
|
||||
return "{SHA}%s" % base64.b64encode(sha1(password).digest())
|
||||
|
||||
@@ -292,11 +283,8 @@ def ssha_passwd(password, salt, **kwargs):
|
||||
'{SSHA}mU1HPTvnmoXOhE4ROHP6sWfbfoRzYWx0'
|
||||
"""
|
||||
|
||||
if isinstance(password, six.text_type):
|
||||
password = password.encode(UNICODE_ENCODING)
|
||||
|
||||
if isinstance(salt, six.text_type):
|
||||
salt = salt.encode(UNICODE_ENCODING)
|
||||
password = getBytes(password)
|
||||
salt = getBytes(salt)
|
||||
|
||||
return "{SSHA}%s" % base64.b64encode(sha1(password + salt).digest() + salt)
|
||||
|
||||
@@ -306,11 +294,8 @@ def ssha256_passwd(password, salt, **kwargs):
|
||||
'{SSHA256}hhubsLrO/Aje9F/kJrgv5ZLE40UmTrVWvI7Dt6InP99zYWx0'
|
||||
"""
|
||||
|
||||
if isinstance(password, six.text_type):
|
||||
password = password.encode(UNICODE_ENCODING)
|
||||
|
||||
if isinstance(salt, six.text_type):
|
||||
salt = salt.encode(UNICODE_ENCODING)
|
||||
password = getBytes(password)
|
||||
salt = getBytes(salt)
|
||||
|
||||
return "{SSHA256}%s" % base64.b64encode(sha256(password + salt).digest() + salt)
|
||||
|
||||
@@ -320,11 +305,8 @@ def ssha512_passwd(password, salt, **kwargs):
|
||||
'{SSHA512}mCUSLfPMhXCQOJl9WHW/QMn9v9sjq7Ht/Wk7iVau8vLOfh+PeynkGMikqIE8sStFd0khdfcCD8xZmC6UyjTxsHNhbHQ='
|
||||
"""
|
||||
|
||||
if isinstance(password, six.text_type):
|
||||
password = password.encode(UNICODE_ENCODING)
|
||||
|
||||
if isinstance(salt, six.text_type):
|
||||
salt = salt.encode(UNICODE_ENCODING)
|
||||
password = getBytes(password)
|
||||
salt = getBytes(salt)
|
||||
|
||||
return "{SSHA512}%s" % base64.b64encode(sha512(password + salt).digest() + salt)
|
||||
|
||||
@@ -334,8 +316,7 @@ def sha224_generic_passwd(password, uppercase=False):
|
||||
'648db6019764b598f75ab6b7616d2e82563a00eb1531680e19ac4c6f'
|
||||
"""
|
||||
|
||||
if isinstance(password, six.text_type):
|
||||
password = password.encode(UNICODE_ENCODING)
|
||||
password = getBytes(password)
|
||||
|
||||
retVal = sha224(password).hexdigest()
|
||||
|
||||
@@ -347,8 +328,7 @@ def sha256_generic_passwd(password, uppercase=False):
|
||||
'13d249f2cb4127b40cfa757866850278793f814ded3c587fe5889e889a7a9f6c'
|
||||
"""
|
||||
|
||||
if isinstance(password, six.text_type):
|
||||
password = password.encode(UNICODE_ENCODING)
|
||||
password = getBytes(password)
|
||||
|
||||
retVal = sha256(password).hexdigest()
|
||||
|
||||
@@ -360,8 +340,7 @@ def sha384_generic_passwd(password, uppercase=False):
|
||||
'6823546e56adf46849343be991d4b1be9b432e42ed1b4bb90635a0e4b930e49b9ca007bc3e04bf0a4e0df6f1f82769bf'
|
||||
"""
|
||||
|
||||
if isinstance(password, six.text_type):
|
||||
password = password.encode(UNICODE_ENCODING)
|
||||
password = getBytes(password)
|
||||
|
||||
retVal = sha384(password).hexdigest()
|
||||
|
||||
@@ -373,8 +352,7 @@ def sha512_generic_passwd(password, uppercase=False):
|
||||
'78ddc8555bb1677ff5af75ba5fc02cb30bb592b0610277ae15055e189b77fe3fda496e5027a3d99ec85d54941adee1cc174b50438fdc21d82d0a79f85b58cf44'
|
||||
"""
|
||||
|
||||
if isinstance(password, six.text_type):
|
||||
password = password.encode(UNICODE_ENCODING)
|
||||
password = getBytes(password)
|
||||
|
||||
retVal = sha512(password).hexdigest()
|
||||
|
||||
@@ -392,11 +370,8 @@ def crypt_generic_passwd(password, salt, **kwargs):
|
||||
'rl.3StKT.4T8M'
|
||||
"""
|
||||
|
||||
if isinstance(password, six.text_type):
|
||||
password = password.encode(UNICODE_ENCODING)
|
||||
|
||||
if isinstance(salt, six.text_type):
|
||||
salt = salt.encode(UNICODE_ENCODING)
|
||||
password = getBytes(password)
|
||||
salt = getBytes(salt)
|
||||
|
||||
return crypt(password, salt)
|
||||
|
||||
@@ -419,14 +394,9 @@ def unix_md5_passwd(password, salt, magic="$1$", **kwargs):
|
||||
|
||||
return output
|
||||
|
||||
if isinstance(password, six.text_type):
|
||||
password = password.encode(UNICODE_ENCODING)
|
||||
|
||||
if isinstance(magic, six.text_type):
|
||||
magic = magic.encode(UNICODE_ENCODING)
|
||||
|
||||
if isinstance(salt, six.text_type):
|
||||
salt = salt.encode(UNICODE_ENCODING)
|
||||
password = getBytes(password)
|
||||
magic = getBytes(magic)
|
||||
salt = getBytes(salt)
|
||||
|
||||
salt = salt[:8]
|
||||
ctx = password + magic + salt
|
||||
@@ -486,11 +456,8 @@ def joomla_passwd(password, salt, **kwargs):
|
||||
'e3d5794da74e917637332e0d21b76328:6GGlnaquVXI80b3HRmSyE3K1wEFFaBIf'
|
||||
"""
|
||||
|
||||
if isinstance(password, six.text_type):
|
||||
password = password.encode(UNICODE_ENCODING)
|
||||
|
||||
if isinstance(salt, six.text_type):
|
||||
salt = salt.encode(UNICODE_ENCODING)
|
||||
password = getBytes(password)
|
||||
salt = getBytes(salt)
|
||||
|
||||
return "%s:%s" % (md5("%s%s" % (password, salt)).hexdigest(), salt)
|
||||
|
||||
@@ -502,11 +469,8 @@ def django_md5_passwd(password, salt, **kwargs):
|
||||
'md5$salt$972141bcbcb6a0acc96e92309175b3c5'
|
||||
"""
|
||||
|
||||
if isinstance(password, six.text_type):
|
||||
password = password.encode(UNICODE_ENCODING)
|
||||
|
||||
if isinstance(salt, six.text_type):
|
||||
salt = salt.encode(UNICODE_ENCODING)
|
||||
password = getBytes(password)
|
||||
salt = getBytes(salt)
|
||||
|
||||
return "md5$%s$%s" % (salt, md5("%s%s" % (salt, password)).hexdigest())
|
||||
|
||||
@@ -518,11 +482,8 @@ def django_sha1_passwd(password, salt, **kwargs):
|
||||
'sha1$salt$6ce0e522aba69d8baa873f01420fccd0250fc5b2'
|
||||
"""
|
||||
|
||||
if isinstance(password, six.text_type):
|
||||
password = password.encode(UNICODE_ENCODING)
|
||||
|
||||
if isinstance(salt, six.text_type):
|
||||
salt = salt.encode(UNICODE_ENCODING)
|
||||
password = getBytes(password)
|
||||
salt = getBytes(salt)
|
||||
|
||||
return "sha1$%s$%s" % (salt, sha1("%s%s" % (salt, password)).hexdigest())
|
||||
|
||||
@@ -534,11 +495,8 @@ def vbulletin_passwd(password, salt, **kwargs):
|
||||
'85c4d8ea77ebef2236fb7e9d24ba9482:salt'
|
||||
"""
|
||||
|
||||
if isinstance(password, six.text_type):
|
||||
password = password.encode(UNICODE_ENCODING)
|
||||
|
||||
if isinstance(salt, six.text_type):
|
||||
salt = salt.encode(UNICODE_ENCODING)
|
||||
password = getBytes(password)
|
||||
salt = getBytes(salt)
|
||||
|
||||
return "%s:%s" % (md5("%s%s" % (md5(password).hexdigest(), salt)).hexdigest(), salt)
|
||||
|
||||
@@ -583,8 +541,7 @@ def wordpress_passwd(password, salt, count, prefix, **kwargs):
|
||||
|
||||
return output
|
||||
|
||||
if isinstance(password, six.text_type):
|
||||
password = password.encode(UNICODE_ENCODING)
|
||||
password = getBytes(password)
|
||||
|
||||
cipher = md5(salt)
|
||||
cipher.update(password)
|
||||
|
||||
+3
-2
@@ -11,6 +11,7 @@ import sqlite3
|
||||
import threading
|
||||
import time
|
||||
|
||||
from lib.core.common import getBytes
|
||||
from lib.core.common import getSafeExString
|
||||
from lib.core.common import getUnicode
|
||||
from lib.core.common import serializeObject
|
||||
@@ -23,9 +24,9 @@ from lib.core.settings import HASHDB_END_TRANSACTION_RETRIES
|
||||
from lib.core.settings import HASHDB_FLUSH_RETRIES
|
||||
from lib.core.settings import HASHDB_FLUSH_THRESHOLD
|
||||
from lib.core.settings import HASHDB_RETRIEVE_RETRIES
|
||||
from lib.core.settings import UNICODE_ENCODING
|
||||
from lib.core.threads import getCurrentThreadData
|
||||
from lib.core.threads import getCurrentThreadName
|
||||
from thirdparty import six
|
||||
|
||||
class HashDB(object):
|
||||
def __init__(self, filepath):
|
||||
@@ -67,7 +68,7 @@ class HashDB(object):
|
||||
|
||||
@staticmethod
|
||||
def hashKey(key):
|
||||
key = key.encode(UNICODE_ENCODING) if isinstance(key, unicode) else repr(key)
|
||||
key = getBytes(key if isinstance(key, six.text_type) else repr(key))
|
||||
retVal = int(hashlib.md5(key).hexdigest(), 16) & 0x7fffffffffffffff # Reference: http://stackoverflow.com/a/4448400
|
||||
return retVal
|
||||
|
||||
|
||||
+56
-37
@@ -21,9 +21,9 @@ __all__ = ["SGMLParser", "SGMLParseError"]
|
||||
|
||||
interesting = re.compile('[&<]')
|
||||
incomplete = re.compile('&([a-zA-Z][a-zA-Z0-9]*|#[0-9]*)?|'
|
||||
'<([a-zA-Z][^<>]*|'
|
||||
'/([a-zA-Z][^<>]*)?|'
|
||||
'![^<>]*)?')
|
||||
'<([a-zA-Z][^<>]*|'
|
||||
'/([a-zA-Z][^<>]*)?|'
|
||||
'![^<>]*)?')
|
||||
|
||||
entityref = re.compile('&([a-zA-Z][-.a-zA-Z0-9]*)[^a-zA-Z0-9]')
|
||||
charref = re.compile('&#([0-9]+)[^0-9]')
|
||||
@@ -58,8 +58,8 @@ class SGMLParseError(RuntimeError):
|
||||
class SGMLParser(_markupbase.ParserBase):
|
||||
# Definition of entities -- derived classes may override
|
||||
entity_or_charref = re.compile('&(?:'
|
||||
'([a-zA-Z][-.a-zA-Z0-9]*)|#([0-9]+)'
|
||||
')(;?)')
|
||||
'([a-zA-Z][-.a-zA-Z0-9]*)|#([0-9]+)'
|
||||
')(;?)')
|
||||
|
||||
def __init__(self, verbose=0):
|
||||
"""Initialize and reset this instance."""
|
||||
@@ -121,32 +121,37 @@ class SGMLParser(_markupbase.ParserBase):
|
||||
i = n
|
||||
break
|
||||
match = interesting.search(rawdata, i)
|
||||
if match: j = match.start()
|
||||
else: j = n
|
||||
if match:
|
||||
j = match.start()
|
||||
else:
|
||||
j = n
|
||||
if i < j:
|
||||
self.handle_data(rawdata[i:j])
|
||||
i = j
|
||||
if i == n: break
|
||||
if i == n:
|
||||
break
|
||||
if rawdata[i] == '<':
|
||||
if starttagopen.match(rawdata, i):
|
||||
if self.literal:
|
||||
self.handle_data(rawdata[i])
|
||||
i = i+1
|
||||
i = i + 1
|
||||
continue
|
||||
k = self.parse_starttag(i)
|
||||
if k < 0: break
|
||||
if k < 0:
|
||||
break
|
||||
i = k
|
||||
continue
|
||||
if rawdata.startswith("</", i):
|
||||
k = self.parse_endtag(i)
|
||||
if k < 0: break
|
||||
if k < 0:
|
||||
break
|
||||
i = k
|
||||
self.literal = 0
|
||||
continue
|
||||
if self.literal:
|
||||
if n > (i + 1):
|
||||
self.handle_data("<")
|
||||
i = i+1
|
||||
i = i + 1
|
||||
else:
|
||||
# incomplete
|
||||
break
|
||||
@@ -157,12 +162,14 @@ class SGMLParser(_markupbase.ParserBase):
|
||||
# This should be removed,
|
||||
# and comments handled only in parse_declaration.
|
||||
k = self.parse_comment(i)
|
||||
if k < 0: break
|
||||
if k < 0:
|
||||
break
|
||||
i = k
|
||||
continue
|
||||
if rawdata.startswith("<?", i):
|
||||
k = self.parse_pi(i)
|
||||
if k < 0: break
|
||||
if k < 0:
|
||||
break
|
||||
i = i+k
|
||||
continue
|
||||
if rawdata.startswith("<!", i):
|
||||
@@ -170,27 +177,30 @@ class SGMLParser(_markupbase.ParserBase):
|
||||
# deployed," this should only be the document type
|
||||
# declaration ("<!DOCTYPE html...>").
|
||||
k = self.parse_declaration(i)
|
||||
if k < 0: break
|
||||
if k < 0:
|
||||
break
|
||||
i = k
|
||||
continue
|
||||
elif rawdata[i] == '&':
|
||||
if self.literal:
|
||||
self.handle_data(rawdata[i])
|
||||
i = i+1
|
||||
i = i + 1
|
||||
continue
|
||||
match = charref.match(rawdata, i)
|
||||
if match:
|
||||
name = match.group(1)
|
||||
self.handle_charref(name)
|
||||
i = match.end(0)
|
||||
if rawdata[i-1] != ';': i = i-1
|
||||
if rawdata[i-1] != ';':
|
||||
i = i-1
|
||||
continue
|
||||
match = entityref.match(rawdata, i)
|
||||
if match:
|
||||
name = match.group(1)
|
||||
self.handle_entityref(name)
|
||||
i = match.end(0)
|
||||
if rawdata[i-1] != ';': i = i-1
|
||||
if rawdata[i-1] != ';':
|
||||
i = i-1
|
||||
continue
|
||||
else:
|
||||
self.error('neither < nor & ??')
|
||||
@@ -199,11 +209,11 @@ class SGMLParser(_markupbase.ParserBase):
|
||||
match = incomplete.match(rawdata, i)
|
||||
if not match:
|
||||
self.handle_data(rawdata[i])
|
||||
i = i+1
|
||||
i = i + 1
|
||||
continue
|
||||
j = match.end(0)
|
||||
if j == n:
|
||||
break # Really incomplete
|
||||
break # Really incomplete
|
||||
self.handle_data(rawdata[i:j])
|
||||
i = j
|
||||
# end while
|
||||
@@ -256,32 +266,33 @@ class SGMLParser(_markupbase.ParserBase):
|
||||
# As a shortcut way to exit, this isn't so bad, but shouldn't
|
||||
# be used to locate the actual end of the start tag since the
|
||||
# < or > characters may be embedded in an attribute value.
|
||||
match = endbracket.search(rawdata, i+1)
|
||||
match = endbracket.search(rawdata, i + 1)
|
||||
if not match:
|
||||
return -1
|
||||
j = match.start(0)
|
||||
# Now parse the data between i+1 and j into a tag and attrs
|
||||
# Now parse the data between i + 1 and j into a tag and attrs
|
||||
attrs = []
|
||||
if rawdata[i:i+2] == '<>':
|
||||
# SGML shorthand: <> == <last open tag seen>
|
||||
k = j
|
||||
tag = self.lasttag
|
||||
else:
|
||||
match = tagfind.match(rawdata, i+1)
|
||||
match = tagfind.match(rawdata, i + 1)
|
||||
if not match:
|
||||
self.error('unexpected call to parse_starttag')
|
||||
k = match.end(0)
|
||||
tag = rawdata[i+1:k].lower()
|
||||
tag = rawdata[i + 1:k].lower()
|
||||
self.lasttag = tag
|
||||
while k < j:
|
||||
match = attrfind.match(rawdata, k)
|
||||
if not match: break
|
||||
if not match:
|
||||
break
|
||||
attrname, rest, attrvalue = match.group(1, 2, 3)
|
||||
if not rest:
|
||||
attrvalue = attrname
|
||||
else:
|
||||
if (attrvalue[:1] == "'" == attrvalue[-1:] or
|
||||
attrvalue[:1] == '"' == attrvalue[-1:]):
|
||||
attrvalue[:1] == '"' == attrvalue[-1:]):
|
||||
# strip quotes
|
||||
attrvalue = attrvalue[1:-1]
|
||||
attrvalue = self.entity_or_charref.sub(
|
||||
@@ -289,7 +300,7 @@ class SGMLParser(_markupbase.ParserBase):
|
||||
attrs.append((attrname.lower(), attrvalue))
|
||||
k = match.end(0)
|
||||
if rawdata[j] == '>':
|
||||
j = j+1
|
||||
j = j + 1
|
||||
self.__starttag_text = rawdata[start_pos:j]
|
||||
self.finish_starttag(tag, attrs)
|
||||
return j
|
||||
@@ -308,13 +319,13 @@ class SGMLParser(_markupbase.ParserBase):
|
||||
# Internal -- parse endtag
|
||||
def parse_endtag(self, i):
|
||||
rawdata = self.rawdata
|
||||
match = endbracket.search(rawdata, i+1)
|
||||
match = endbracket.search(rawdata, i + 1)
|
||||
if not match:
|
||||
return -1
|
||||
j = match.start(0)
|
||||
tag = rawdata[i+2:j].strip().lower()
|
||||
if rawdata[j] == '>':
|
||||
j = j+1
|
||||
j = j + 1
|
||||
self.finish_endtag(tag)
|
||||
return j
|
||||
|
||||
@@ -361,7 +372,8 @@ class SGMLParser(_markupbase.ParserBase):
|
||||
return
|
||||
found = len(self.stack)
|
||||
for i in range(found):
|
||||
if self.stack[i] == tag: found = i
|
||||
if self.stack[i] == tag:
|
||||
found = i
|
||||
while len(self.stack) > found:
|
||||
tag = self.stack[-1]
|
||||
try:
|
||||
@@ -411,7 +423,7 @@ class SGMLParser(_markupbase.ParserBase):
|
||||
|
||||
# Definition of entities -- derived classes may override
|
||||
entitydefs = \
|
||||
{'lt': '<', 'gt': '>', 'amp': '&', 'quot': '"', 'apos': '\''}
|
||||
{'lt': '<', 'gt': '>', 'amp': '&', 'quot': '"', 'apos': '\''}
|
||||
|
||||
def convert_entityref(self, name):
|
||||
"""Convert entity references.
|
||||
@@ -450,10 +462,17 @@ class SGMLParser(_markupbase.ParserBase):
|
||||
pass
|
||||
|
||||
# To be overridden -- handlers for unknown objects
|
||||
def unknown_starttag(self, tag, attrs): pass
|
||||
def unknown_endtag(self, tag): pass
|
||||
def unknown_charref(self, ref): pass
|
||||
def unknown_entityref(self, ref): pass
|
||||
def unknown_starttag(self, tag, attrs):
|
||||
pass
|
||||
|
||||
def unknown_endtag(self, tag):
|
||||
pass
|
||||
|
||||
def unknown_charref(self, ref):
|
||||
pass
|
||||
|
||||
def unknown_entityref(self, ref):
|
||||
pass
|
||||
|
||||
|
||||
class TestSGMLParser(SGMLParser):
|
||||
@@ -511,7 +530,7 @@ class TestSGMLParser(SGMLParser):
|
||||
self.flush()
|
||||
|
||||
|
||||
def test(args = None):
|
||||
def test(args=None):
|
||||
import sys
|
||||
|
||||
if args is None:
|
||||
@@ -548,4 +567,4 @@ def test(args = None):
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
test()
|
||||
test()
|
||||
|
||||
@@ -5,12 +5,13 @@ Copyright (c) 2006-2019 sqlmap developers (http://sqlmap.org/)
|
||||
See the file 'LICENSE' for copying permission
|
||||
"""
|
||||
|
||||
import os
|
||||
import sys
|
||||
import time
|
||||
|
||||
PYVERSION = sys.version.split()[0]
|
||||
|
||||
if PYVERSION >= "3" or PYVERSION < "2.6":
|
||||
if (PYVERSION >= "3" or PYVERSION < "2.6") and not int(os.environ.get("SQLMAP_DREI", 0)):
|
||||
sys.exit("[%s] [CRITICAL] incompatible Python version detected ('%s'). To successfully run sqlmap you'll have to use version 2.6.x or 2.7.x (visit 'https://www.python.org/downloads/')" % (time.strftime("%X"), PYVERSION))
|
||||
|
||||
errors = []
|
||||
|
||||
+7
-7
@@ -12,19 +12,19 @@ class xrange(object):
|
||||
Advanced (re)implementation of xrange (supports slice/copy/etc.)
|
||||
Reference: http://code.activestate.com/recipes/521885-a-pythonic-implementation-of-xrange/
|
||||
|
||||
>>> list(xrange(1, 9)) == range(1, 9)
|
||||
>>> list(xrange(1, 9)) == list(range(1, 9))
|
||||
True
|
||||
>>> list(xrange(8, 0, -16)) == range(8, 0, -16)
|
||||
>>> list(xrange(8, 0, -16)) == list(range(8, 0, -16))
|
||||
True
|
||||
>>> list(xrange(0, 8, 16)) == range(0, 8, 16)
|
||||
>>> list(xrange(0, 8, 16)) == list(range(0, 8, 16))
|
||||
True
|
||||
>>> list(xrange(0, 4, 5)) == range(0, 4, 5)
|
||||
>>> list(xrange(0, 4, 5)) == list(range(0, 4, 5))
|
||||
True
|
||||
>>> list(xrange(4, 0, 3)) == range(4, 0, 3)
|
||||
>>> list(xrange(4, 0, 3)) == list(range(4, 0, 3))
|
||||
True
|
||||
>>> list(xrange(0, -3)) == range(0, -3)
|
||||
>>> list(xrange(0, -3)) == list(range(0, -3))
|
||||
True
|
||||
>>> list(xrange(0, 7, 2)) == range(0, 7, 2)
|
||||
>>> list(xrange(0, 7, 2)) == list(range(0, 7, 2))
|
||||
True
|
||||
>>> foobar = xrange(1, 10)
|
||||
>>> 7 in foobar
|
||||
|
||||
@@ -8,4 +8,4 @@ See the file 'LICENSE' for copying permission
|
||||
from plugins.generic.filesystem import Filesystem as GenericFilesystem
|
||||
|
||||
class Filesystem(GenericFilesystem):
|
||||
pass
|
||||
pass
|
||||
|
||||
@@ -8,4 +8,4 @@ See the file 'LICENSE' for copying permission
|
||||
from plugins.generic.filesystem import Filesystem as GenericFilesystem
|
||||
|
||||
class Filesystem(GenericFilesystem):
|
||||
pass
|
||||
pass
|
||||
|
||||
@@ -8,4 +8,4 @@ See the file 'LICENSE' for copying permission
|
||||
from plugins.generic.enumeration import Enumeration as GenericEnumeration
|
||||
|
||||
class Enumeration(GenericEnumeration):
|
||||
pass
|
||||
pass
|
||||
|
||||
@@ -7,8 +7,8 @@ See the file 'LICENSE' for copying permission
|
||||
|
||||
import binascii
|
||||
|
||||
from lib.core.common import getBytes
|
||||
from lib.core.common import isDBMSVersionAtLeast
|
||||
from lib.core.settings import UNICODE_ENCODING
|
||||
from plugins.generic.syntax import Syntax as GenericSyntax
|
||||
|
||||
class Syntax(GenericSyntax):
|
||||
@@ -28,7 +28,7 @@ class Syntax(GenericSyntax):
|
||||
|
||||
def escaper(value):
|
||||
# Reference: http://stackoverflow.com/questions/3444335/how-do-i-quote-a-utf-8-string-literal-in-sqlite3
|
||||
return "CAST(X'%s' AS TEXT)" % binascii.hexlify(value.encode(UNICODE_ENCODING) if isinstance(value, unicode) else value)
|
||||
return "CAST(X'%s' AS TEXT)" % binascii.hexlify(getBytes(value))
|
||||
|
||||
retVal = expression
|
||||
|
||||
|
||||
@@ -24,6 +24,7 @@ from lib.core.settings import NULL
|
||||
from lib.core.settings import PARAMETER_SPLITTING_REGEX
|
||||
from lib.core.shell import autoCompletion
|
||||
from lib.request import inject
|
||||
from thirdparty.six.moves import input as _input
|
||||
|
||||
class Custom:
|
||||
"""
|
||||
@@ -88,7 +89,7 @@ class Custom:
|
||||
query = None
|
||||
|
||||
try:
|
||||
query = raw_input("sql-shell> ")
|
||||
query = _input("sql-shell> ")
|
||||
query = getUnicode(query, encoding=sys.stdin.encoding)
|
||||
query = query.strip("; ")
|
||||
except KeyboardInterrupt:
|
||||
@@ -110,7 +111,7 @@ class Custom:
|
||||
output = self.sqlQuery(query)
|
||||
|
||||
if output and output != "Quit":
|
||||
conf.dumper.query(query, output)
|
||||
conf.dumper.sqlQuery(query, output)
|
||||
|
||||
elif not output:
|
||||
pass
|
||||
@@ -134,6 +135,6 @@ class Custom:
|
||||
for query in (_ for _ in snippet.split(';' if ';' in snippet else '\n') if _):
|
||||
query = query.strip()
|
||||
if query:
|
||||
conf.dumper.query(query, self.sqlQuery(query))
|
||||
conf.dumper.sqlQuery(query, self.sqlQuery(query))
|
||||
else:
|
||||
conf.dumper.query(snippet, self.sqlQuery(snippet))
|
||||
conf.dumper.sqlQuery(snippet, self.sqlQuery(snippet))
|
||||
|
||||
@@ -597,7 +597,7 @@ class Databases:
|
||||
kb.dumpColumns = []
|
||||
kb.rowXmlMode = True
|
||||
|
||||
for column in extractRegexResult(r"SELECT (?P<result>.+?) FROM", query).split(','):
|
||||
for column in (extractRegexResult(r"SELECT (?P<result>.+?) FROM", query) or "").split(','):
|
||||
kb.dumpColumns.append(randomStr().lower())
|
||||
expression = expression.replace(column, "%s AS %s" % (column, kb.dumpColumns[-1]), 1)
|
||||
|
||||
|
||||
Binary file not shown.
+1
-1
@@ -544,7 +544,7 @@ lastChar = 0
|
||||
|
||||
# SQL statement to be executed.
|
||||
# Example: SELECT 'foo', 'bar'
|
||||
query =
|
||||
sqlQuery =
|
||||
|
||||
# Prompt for an interactive SQL shell.
|
||||
# Valid: True or False
|
||||
|
||||
@@ -43,6 +43,7 @@ try:
|
||||
from lib.core.common import createGithubIssue
|
||||
from lib.core.common import dataToStdout
|
||||
from lib.core.common import filterNone
|
||||
from lib.core.common import getDaysFromLastUpdate
|
||||
from lib.core.common import getSafeExString
|
||||
from lib.core.common import getUnicode
|
||||
from lib.core.common import maskSensitiveData
|
||||
@@ -64,6 +65,7 @@ try:
|
||||
from lib.core.patch import dirtyPatches
|
||||
from lib.core.settings import GIT_PAGE
|
||||
from lib.core.settings import IS_WIN
|
||||
from lib.core.settings import LAST_UPDATE_NAGGING_DAYS
|
||||
from lib.core.settings import LEGAL_DISCLAIMER
|
||||
from lib.core.settings import THREAD_FINALIZATION_TIMEOUT
|
||||
from lib.core.settings import UNICODE_ENCODING
|
||||
@@ -157,10 +159,13 @@ def main():
|
||||
# Postponed imports (faster start)
|
||||
if conf.smokeTest:
|
||||
from lib.core.testing import smokeTest
|
||||
smokeTest()
|
||||
os._exitcode = 1 - (smokeTest() or 0)
|
||||
elif conf.vulnTest:
|
||||
from lib.core.testing import vulnTest
|
||||
os._exitcode = 1 - (vulnTest() or 0)
|
||||
elif conf.liveTest:
|
||||
from lib.core.testing import liveTest
|
||||
liveTest()
|
||||
os._exitcode = 1 - (liveTest() or 0)
|
||||
else:
|
||||
from lib.controller.controller import start
|
||||
if conf.profile and PY2:
|
||||
@@ -171,6 +176,8 @@ def main():
|
||||
try:
|
||||
start()
|
||||
except Exception as ex:
|
||||
os._exitcode = 1
|
||||
|
||||
if "can't start new thread" in getSafeExString(ex):
|
||||
errMsg = "unable to start new threads. Please check OS (u)limits"
|
||||
logger.critical(errMsg)
|
||||
@@ -351,6 +358,11 @@ def main():
|
||||
finally:
|
||||
kb.threadContinue = False
|
||||
|
||||
_ = getDaysFromLastUpdate()
|
||||
if _ > LAST_UPDATE_NAGGING_DAYS:
|
||||
warnMsg = "you haven't updated sqlmap for more than %d days!!!" % _
|
||||
logger.warn(warnMsg)
|
||||
|
||||
if conf.get("showTime"):
|
||||
dataToStdout("\n[*] ending @ %s\n\n" % time.strftime("%X /%Y-%m-%d/"), forceOutput=True)
|
||||
|
||||
@@ -396,10 +408,15 @@ if __name__ == "__main__":
|
||||
main()
|
||||
except KeyboardInterrupt:
|
||||
pass
|
||||
except:
|
||||
if int(os.environ.get("SQLMAP_DREI", 0)):
|
||||
traceback.print_exc()
|
||||
finally:
|
||||
# Reference: http://stackoverflow.com/questions/1635080/terminate-a-multi-thread-python-program
|
||||
if threading.activeCount() > 1:
|
||||
os._exit(0)
|
||||
os._exit(getattr(os, "_exitcode", 0))
|
||||
else:
|
||||
sys.exit(getattr(os, "_exitcode", 0))
|
||||
else:
|
||||
# cancelling postponed imports (because of Travis CI checks)
|
||||
from lib.controller.controller import start
|
||||
|
||||
@@ -7,6 +7,7 @@ See the file 'LICENSE' for copying permission
|
||||
|
||||
import re
|
||||
|
||||
from lib.core.common import decodeHex
|
||||
from lib.core.enums import PRIORITY
|
||||
|
||||
__priority__ = PRIORITY.NORMAL
|
||||
@@ -36,9 +37,9 @@ def tamper(payload, **kwargs):
|
||||
if payload:
|
||||
for match in re.finditer(r"\b0x([0-9a-f]+)\b", retVal):
|
||||
if len(match.group(1)) > 2:
|
||||
result = "CONCAT(%s)" % ','.join("CHAR(%d)" % ord(_) for _ in match.group(1).decode("hex"))
|
||||
result = "CONCAT(%s)" % ','.join("CHAR(%d)" % ord(_) for _ in decodeHex(match.group(1)))
|
||||
else:
|
||||
result = "CHAR(%d)" % ord(match.group(1).decode("hex"))
|
||||
result = "CHAR(%d)" % ord(decodeHex(match.group(1)))
|
||||
retVal = retVal.replace(match.group(0), result)
|
||||
|
||||
return retVal
|
||||
+1
-1
@@ -32,6 +32,6 @@ def tamper(payload, **kwargs):
|
||||
hints = kwargs.get("hints", {})
|
||||
delimiter = kwargs.get("delimiter", DEFAULT_GET_POST_DELIMITER)
|
||||
|
||||
hints[HINT.PREPEND] = delimiter.join("%s=" % "".join(random.sample(string.letters + string.digits, 2)) for _ in xrange(500))
|
||||
hints[HINT.PREPEND] = delimiter.join("%s=" % "".join(random.sample(string.ascii_letters + string.digits, 2)) for _ in xrange(500))
|
||||
|
||||
return payload
|
||||
|
||||
+30
-31
@@ -91,6 +91,11 @@ import sys
|
||||
|
||||
if sys.version_info >= (3, 0):
|
||||
xrange = range
|
||||
text_type = str
|
||||
binary_type = bytes
|
||||
else:
|
||||
text_type = unicode
|
||||
binary_type = str
|
||||
|
||||
try:
|
||||
from htmlentitydefs import name2codepoint
|
||||
@@ -434,19 +439,13 @@ class PageElement(object):
|
||||
def toEncoding(self, s, encoding=None):
|
||||
"""Encodes an object to a string in some encoding, or to Unicode.
|
||||
."""
|
||||
if isinstance(s, unicode):
|
||||
if isinstance(s, text_type):
|
||||
if encoding:
|
||||
s = s.encode(encoding)
|
||||
elif isinstance(s, str):
|
||||
if encoding:
|
||||
s = s.encode(encoding)
|
||||
else:
|
||||
s = unicode(s)
|
||||
elif isinstance(s, binary_type):
|
||||
s = s.encode(encoding or "utf8")
|
||||
else:
|
||||
if encoding:
|
||||
s = self.toEncoding(str(s), encoding)
|
||||
else:
|
||||
s = unicode(s)
|
||||
s = self.toEncoding(str(s), encoding or "utf8")
|
||||
return s
|
||||
|
||||
BARE_AMPERSAND_OR_BRACKET = re.compile("([<>]|"
|
||||
@@ -459,7 +458,7 @@ class PageElement(object):
|
||||
return "&" + self.XML_SPECIAL_CHARS_TO_ENTITIES[x.group(0)[0]] + ";"
|
||||
|
||||
|
||||
class NavigableString(unicode, PageElement):
|
||||
class NavigableString(text_type, PageElement):
|
||||
|
||||
def __new__(cls, value):
|
||||
"""Create a new NavigableString.
|
||||
@@ -469,9 +468,9 @@ class NavigableString(unicode, PageElement):
|
||||
passed in to the superclass's __new__ or the superclass won't know
|
||||
how to handle non-ASCII characters.
|
||||
"""
|
||||
if isinstance(value, unicode):
|
||||
return unicode.__new__(cls, value)
|
||||
return unicode.__new__(cls, value, DEFAULT_OUTPUT_ENCODING)
|
||||
if isinstance(value, text_type):
|
||||
return text_type.__new__(cls, value)
|
||||
return text_type.__new__(cls, value, DEFAULT_OUTPUT_ENCODING)
|
||||
|
||||
def __getnewargs__(self):
|
||||
return (NavigableString.__str__(self),)
|
||||
@@ -1006,7 +1005,7 @@ class SoupStrainer:
|
||||
if isinstance(markup, Tag):
|
||||
markup = markup.name
|
||||
if markup and not isinstance(markup, basestring):
|
||||
markup = unicode(markup)
|
||||
markup = text_type(markup)
|
||||
#Now we know that chunk is either a string, or None.
|
||||
if hasattr(matchAgainst, 'match'):
|
||||
# It's a regexp object.
|
||||
@@ -1016,8 +1015,8 @@ class SoupStrainer:
|
||||
elif hasattr(matchAgainst, 'items'):
|
||||
result = markup.has_key(matchAgainst)
|
||||
elif matchAgainst and isinstance(markup, basestring):
|
||||
if isinstance(markup, unicode):
|
||||
matchAgainst = unicode(matchAgainst)
|
||||
if isinstance(markup, text_type):
|
||||
matchAgainst = text_type(matchAgainst)
|
||||
else:
|
||||
matchAgainst = str(matchAgainst)
|
||||
|
||||
@@ -1181,7 +1180,7 @@ class BeautifulStoneSoup(Tag, sgmllib.SGMLParser):
|
||||
def _feed(self, inDocumentEncoding=None, isHTML=False):
|
||||
# Convert the document to Unicode.
|
||||
markup = self.markup
|
||||
if isinstance(markup, unicode):
|
||||
if isinstance(markup, text_type):
|
||||
if not hasattr(self, 'originalEncoding'):
|
||||
self.originalEncoding = None
|
||||
else:
|
||||
@@ -1792,9 +1791,9 @@ class UnicodeDammit:
|
||||
self._detectEncoding(markup, isHTML)
|
||||
self.smartQuotesTo = smartQuotesTo
|
||||
self.triedEncodings = []
|
||||
if markup == '' or isinstance(markup, unicode):
|
||||
if markup == '' or isinstance(markup, text_type):
|
||||
self.originalEncoding = None
|
||||
self.unicode = unicode(markup)
|
||||
self.unicode = text_type(markup)
|
||||
return
|
||||
|
||||
u = None
|
||||
@@ -1807,7 +1806,7 @@ class UnicodeDammit:
|
||||
if u: break
|
||||
|
||||
# If no luck and we have auto-detection library, try that:
|
||||
if not u and chardet and not isinstance(self.markup, unicode):
|
||||
if not u and chardet and not isinstance(self.markup, text_type):
|
||||
u = self._convertFrom(chardet.detect(self.markup)['encoding'])
|
||||
|
||||
# As a last resort, try utf-8 and windows-1252:
|
||||
@@ -1880,7 +1879,7 @@ class UnicodeDammit:
|
||||
elif data[:4] == '\xff\xfe\x00\x00':
|
||||
encoding = 'utf-32le'
|
||||
data = data[4:]
|
||||
newdata = unicode(data, encoding)
|
||||
newdata = text_type(data, encoding)
|
||||
return newdata
|
||||
|
||||
def _detectEncoding(self, xml_data, isHTML=False):
|
||||
@@ -1893,41 +1892,41 @@ class UnicodeDammit:
|
||||
elif xml_data[:4] == '\x00\x3c\x00\x3f':
|
||||
# UTF-16BE
|
||||
sniffed_xml_encoding = 'utf-16be'
|
||||
xml_data = unicode(xml_data, 'utf-16be').encode('utf-8')
|
||||
xml_data = text_type(xml_data, 'utf-16be').encode('utf-8')
|
||||
elif (len(xml_data) >= 4) and (xml_data[:2] == '\xfe\xff') \
|
||||
and (xml_data[2:4] != '\x00\x00'):
|
||||
# UTF-16BE with BOM
|
||||
sniffed_xml_encoding = 'utf-16be'
|
||||
xml_data = unicode(xml_data[2:], 'utf-16be').encode('utf-8')
|
||||
xml_data = text_type(xml_data[2:], 'utf-16be').encode('utf-8')
|
||||
elif xml_data[:4] == '\x3c\x00\x3f\x00':
|
||||
# UTF-16LE
|
||||
sniffed_xml_encoding = 'utf-16le'
|
||||
xml_data = unicode(xml_data, 'utf-16le').encode('utf-8')
|
||||
xml_data = text_type(xml_data, 'utf-16le').encode('utf-8')
|
||||
elif (len(xml_data) >= 4) and (xml_data[:2] == '\xff\xfe') and \
|
||||
(xml_data[2:4] != '\x00\x00'):
|
||||
# UTF-16LE with BOM
|
||||
sniffed_xml_encoding = 'utf-16le'
|
||||
xml_data = unicode(xml_data[2:], 'utf-16le').encode('utf-8')
|
||||
xml_data = text_type(xml_data[2:], 'utf-16le').encode('utf-8')
|
||||
elif xml_data[:4] == '\x00\x00\x00\x3c':
|
||||
# UTF-32BE
|
||||
sniffed_xml_encoding = 'utf-32be'
|
||||
xml_data = unicode(xml_data, 'utf-32be').encode('utf-8')
|
||||
xml_data = text_type(xml_data, 'utf-32be').encode('utf-8')
|
||||
elif xml_data[:4] == '\x3c\x00\x00\x00':
|
||||
# UTF-32LE
|
||||
sniffed_xml_encoding = 'utf-32le'
|
||||
xml_data = unicode(xml_data, 'utf-32le').encode('utf-8')
|
||||
xml_data = text_type(xml_data, 'utf-32le').encode('utf-8')
|
||||
elif xml_data[:4] == '\x00\x00\xfe\xff':
|
||||
# UTF-32BE with BOM
|
||||
sniffed_xml_encoding = 'utf-32be'
|
||||
xml_data = unicode(xml_data[4:], 'utf-32be').encode('utf-8')
|
||||
xml_data = text_type(xml_data[4:], 'utf-32be').encode('utf-8')
|
||||
elif xml_data[:4] == '\xff\xfe\x00\x00':
|
||||
# UTF-32LE with BOM
|
||||
sniffed_xml_encoding = 'utf-32le'
|
||||
xml_data = unicode(xml_data[4:], 'utf-32le').encode('utf-8')
|
||||
xml_data = text_type(xml_data[4:], 'utf-32le').encode('utf-8')
|
||||
elif xml_data[:3] == '\xef\xbb\xbf':
|
||||
# UTF-8 with BOM
|
||||
sniffed_xml_encoding = 'utf-8'
|
||||
xml_data = unicode(xml_data[3:], 'utf-8').encode('utf-8')
|
||||
xml_data = text_type(xml_data[3:], 'utf-8').encode('utf-8')
|
||||
else:
|
||||
sniffed_xml_encoding = 'ascii'
|
||||
pass
|
||||
|
||||
Vendored
+1
-1
@@ -573,7 +573,7 @@ In practice, you would read the password using something like the
|
||||
getpass module, and generate the salt randomly:
|
||||
|
||||
>>> import random, string
|
||||
>>> saltchars = string.letters + string.digits + './'
|
||||
>>> saltchars = string.ascii_letters + string.digits + './'
|
||||
>>> salt = random.choice(saltchars) + random.choice(saltchars)
|
||||
|
||||
Note that other ASCII characters are accepted in the salt, but the
|
||||
|
||||
+6
-8
@@ -21,16 +21,14 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
"""
|
||||
|
||||
import io
|
||||
import mimetools
|
||||
import mimetypes
|
||||
import os
|
||||
import stat
|
||||
import sys
|
||||
import urllib
|
||||
import urllib2
|
||||
|
||||
from lib.core.compat import choose_boundary
|
||||
from lib.core.exception import SqlmapDataException
|
||||
from thirdparty.six.moves import urllib as _urllib
|
||||
|
||||
class Callable:
|
||||
def __init__(self, anycallable):
|
||||
@@ -41,11 +39,11 @@ class Callable:
|
||||
doseq = 1
|
||||
|
||||
|
||||
class MultipartPostHandler(urllib2.BaseHandler):
|
||||
handler_order = urllib2.HTTPHandler.handler_order - 10 # needs to run first
|
||||
class MultipartPostHandler(_urllib.request.BaseHandler):
|
||||
handler_order = _urllib.request.HTTPHandler.handler_order - 10 # needs to run first
|
||||
|
||||
def http_request(self, request):
|
||||
data = request.get_data()
|
||||
data = request.data
|
||||
|
||||
if isinstance(data, dict):
|
||||
v_files = []
|
||||
@@ -62,7 +60,7 @@ class MultipartPostHandler(urllib2.BaseHandler):
|
||||
raise SqlmapDataException("not a valid non-string sequence or mapping object '%s'" % traceback)
|
||||
|
||||
if len(v_files) == 0:
|
||||
data = urllib.urlencode(v_vars, doseq)
|
||||
data = _urllib.parse.urlencode(v_vars, doseq)
|
||||
else:
|
||||
boundary, data = self.multipart_encode(v_vars, v_files)
|
||||
contenttype = "multipart/form-data; boundary=%s" % boundary
|
||||
@@ -70,7 +68,7 @@ class MultipartPostHandler(urllib2.BaseHandler):
|
||||
# print "Replacing %s with %s" % (request.get_header("content-type"), "multipart/form-data")
|
||||
request.add_unredirected_header("Content-Type", contenttype)
|
||||
|
||||
request.add_data(data)
|
||||
request.data = data
|
||||
return request
|
||||
|
||||
def multipart_encode(vars, files, boundary=None, buf=None):
|
||||
|
||||
@@ -531,6 +531,79 @@ sifra
|
||||
lozinka
|
||||
kljuc
|
||||
|
||||
# turkish
|
||||
numara
|
||||
sira
|
||||
lokasyon
|
||||
kullanici
|
||||
kullanici_adi
|
||||
sifre
|
||||
giris
|
||||
pasif
|
||||
posta
|
||||
adres
|
||||
is_adres
|
||||
ev_adres
|
||||
is_adresi
|
||||
ev_adresi
|
||||
isadresi
|
||||
evadresi
|
||||
il
|
||||
ilce
|
||||
eposta
|
||||
eposta_adres
|
||||
epostaadres
|
||||
eposta_adresi
|
||||
epostaadresi
|
||||
e-posta
|
||||
e-posta_adres
|
||||
e-postaadres
|
||||
e-posta_adresi
|
||||
e-postaadresi
|
||||
e_posta
|
||||
e_posta_adres
|
||||
e_postaadres
|
||||
e_posta_adresi
|
||||
e_postaadresi
|
||||
baglanti
|
||||
gun
|
||||
ay
|
||||
yil
|
||||
saat
|
||||
tarih
|
||||
guncelleme
|
||||
guncellemetarih
|
||||
guncelleme_tarih
|
||||
guncellemetarihi
|
||||
guncelleme_tarihi
|
||||
yetki
|
||||
cinsiyet
|
||||
ulke
|
||||
guncel
|
||||
vergi
|
||||
vergino
|
||||
vergi_no
|
||||
yas
|
||||
dogum
|
||||
dogumtarih
|
||||
dogum_tarih
|
||||
dogumtarihi
|
||||
dogum_tarihi
|
||||
telefon_is
|
||||
telefon_ev
|
||||
telefonis
|
||||
telefonev
|
||||
ev_telefonu
|
||||
is_telefonu
|
||||
ev_telefon
|
||||
is_telefon
|
||||
evtelefonu
|
||||
istelefonu
|
||||
evtelefon
|
||||
istelefon
|
||||
kontak
|
||||
kontaklar
|
||||
|
||||
# List from schemafuzz.py (http://www.beenuarora.com/code/schemafuzz.py)
|
||||
user
|
||||
pass
|
||||
|
||||
@@ -3354,6 +3354,52 @@ aliastype
|
||||
mymps_mail_sendlist
|
||||
mymps_navurl
|
||||
|
||||
# site:tr
|
||||
kullanici
|
||||
kullanicilar
|
||||
yonetici
|
||||
yoneticiler
|
||||
adres
|
||||
adresler
|
||||
yayincilar
|
||||
yayinci
|
||||
urun
|
||||
urunler
|
||||
kategori
|
||||
kategoriler
|
||||
ulke
|
||||
ulkeler
|
||||
siparis
|
||||
siparisler
|
||||
bayi
|
||||
bayiler
|
||||
stok
|
||||
reklam
|
||||
reklamlar
|
||||
site
|
||||
siteler
|
||||
sayfa
|
||||
sayfalar
|
||||
icerik
|
||||
icerikler
|
||||
yazi
|
||||
yazilar
|
||||
genel
|
||||
istatistik
|
||||
istatistikler
|
||||
duyuru
|
||||
duyurular
|
||||
haber
|
||||
haberler
|
||||
komisyon
|
||||
ucret
|
||||
ucretler
|
||||
bilgi
|
||||
basvuru
|
||||
basvurular
|
||||
kontak
|
||||
kontaklar
|
||||
|
||||
# List provided by Pedrito Perez ([email protected])
|
||||
adminstbl
|
||||
admintbl
|
||||
|
||||
+1
-1
@@ -14,7 +14,7 @@ def detect(get_page):
|
||||
|
||||
for vector in WAF_ATTACK_VECTORS:
|
||||
page, headers, code = get_page(get=vector)
|
||||
retval = headers.get("X-Powered-By-360wzb") is not None
|
||||
retval |= headers.get("X-Powered-By-360wzb") is not None
|
||||
retval |= code == 493 and "/wzws-waf-cgi/" in (page or "")
|
||||
retval |= all(_ in (page or "") for _ in ("eventID", "If you are the Webmaster", "<title>493</title>"))
|
||||
if retval:
|
||||
|
||||
+1
-1
@@ -14,7 +14,7 @@ def detect(get_page):
|
||||
|
||||
for vector in WAF_ATTACK_VECTORS:
|
||||
page, headers, _ = get_page(get=vector)
|
||||
retval = headers.get("aeSecure-code") is not None
|
||||
retval |= headers.get("aeSecure-code") is not None
|
||||
retval |= all(_ in (page or "") for _ in ("aeSecure", "aesecure_denied.png"))
|
||||
if retval:
|
||||
break
|
||||
|
||||
+1
-1
@@ -17,7 +17,7 @@ def detect(get_page):
|
||||
|
||||
for vector in WAF_ATTACK_VECTORS:
|
||||
page, headers, _ = get_page(get=vector)
|
||||
retval = re.search(r"\AAL[_-]?(SESS|LB)", headers.get(HTTP_HEADER.SET_COOKIE, ""), re.I) is not None
|
||||
retval |= re.search(r"\AAL[_-]?(SESS|LB)", headers.get(HTTP_HEADER.SET_COOKIE, ""), re.I) is not None
|
||||
retval |= all(_ in (page or "") for _ in ("The server detected a syntax error in your request", "Check your request and all parameters", "Bad Request", "Your request ID was"))
|
||||
if retval:
|
||||
break
|
||||
|
||||
+1
-1
@@ -14,7 +14,7 @@ def detect(get_page):
|
||||
|
||||
for vector in WAF_ATTACK_VECTORS:
|
||||
page, headers, code = get_page(get=vector)
|
||||
retval = code == 405 and any(_ in (page or "") for _ in ("/aqb_cc/error/", "hidden_intercept_time"))
|
||||
retval |= code == 405 and any(_ in (page or "") for _ in ("/aqb_cc/error/", "hidden_intercept_time"))
|
||||
if retval:
|
||||
break
|
||||
|
||||
|
||||
+1
-1
@@ -17,7 +17,7 @@ def detect(get_page):
|
||||
|
||||
for vector in WAF_ATTACK_VECTORS:
|
||||
page, headers, code = get_page(get=vector)
|
||||
retval = re.search(r"Approach Web Application Firewall", headers.get(HTTP_HEADER.SERVER, ""), re.I) is not None
|
||||
retval |= re.search(r"Approach Web Application Firewall", headers.get(HTTP_HEADER.SERVER, ""), re.I) is not None
|
||||
retval |= re.search(r"Approach(</b>)? Web Application Firewall", page or "", re.I) is not None
|
||||
retval |= " Your IP address has been logged and this information could be used by authorities to track you." in (page or "")
|
||||
retval |= all(_ in (page or "") for _ in ("Sorry for the inconvenience!", "If this was an legitimate request please contact us with details!"))
|
||||
|
||||
+1
-1
@@ -14,7 +14,7 @@ def detect(get_page):
|
||||
|
||||
for vector in WAF_ATTACK_VECTORS:
|
||||
page, _, _ = get_page(get=vector)
|
||||
retval = "This request has been blocked by website protection from Armor" in (page or "")
|
||||
retval |= "This request has been blocked by website protection from Armor" in (page or "")
|
||||
if retval:
|
||||
break
|
||||
|
||||
|
||||
+1
-1
@@ -14,7 +14,7 @@ def detect(get_page):
|
||||
|
||||
for vector in WAF_ATTACK_VECTORS:
|
||||
page, headers, code = get_page(get=vector)
|
||||
retval = "The requested URL was rejected. Please consult with your administrator." in (page or "")
|
||||
retval |= "The requested URL was rejected. Please consult with your administrator." in (page or "")
|
||||
retval |= all(_ in (page or "") for _ in ("security.f5aas.com", "Please enable JavaScript to view the page content"))
|
||||
if retval:
|
||||
break
|
||||
|
||||
@@ -0,0 +1,21 @@
|
||||
#!/usr/bin/env python2
|
||||
|
||||
"""
|
||||
Copyright (c) 2006-2019 sqlmap developers (http://sqlmap.org/)
|
||||
See the file 'LICENSE' for copying permission
|
||||
"""
|
||||
|
||||
from lib.core.settings import WAF_ATTACK_VECTORS
|
||||
|
||||
__product__ = "Astra (Czar Securities)"
|
||||
|
||||
def detect(get_page):
|
||||
retval = False
|
||||
|
||||
for vector in WAF_ATTACK_VECTORS:
|
||||
page, headers, code = get_page(get=vector)
|
||||
retval |= all(_ in (page or "") for _ in ("unfortunately our website protection system", "//www.getastra.com"))
|
||||
if retval:
|
||||
break
|
||||
|
||||
return retval
|
||||
+1
-1
@@ -17,7 +17,7 @@ def detect(get_page):
|
||||
|
||||
for vector in WAF_ATTACK_VECTORS:
|
||||
page, headers, code = get_page(get=vector)
|
||||
retval = code == 403 and re.search(r"\bAWS", headers.get(HTTP_HEADER.SERVER, ""), re.I) is not None
|
||||
retval |= code == 403 and re.search(r"\bAWS", headers.get(HTTP_HEADER.SERVER, ""), re.I) is not None
|
||||
if retval:
|
||||
break
|
||||
|
||||
|
||||
+1
-1
@@ -17,7 +17,7 @@ def detect(get_page):
|
||||
|
||||
for vector in WAF_ATTACK_VECTORS:
|
||||
page, headers, _ = get_page(get=vector)
|
||||
retval = re.search(r"\Abarra_counter_session=", headers.get(HTTP_HEADER.SET_COOKIE, ""), re.I) is not None
|
||||
retval |= re.search(r"\Abarra_counter_session=", headers.get(HTTP_HEADER.SET_COOKIE, ""), re.I) is not None
|
||||
retval |= re.search(r"(\A|\b)barracuda_", headers.get(HTTP_HEADER.SET_COOKIE, ""), re.I) is not None
|
||||
retval |= "when this page occurred and the event ID found at the bottom of the page" in (page or "")
|
||||
if retval:
|
||||
|
||||
+1
-1
@@ -14,7 +14,7 @@ def detect(get_page):
|
||||
|
||||
for vector in WAF_ATTACK_VECTORS:
|
||||
page, _, _ = get_page(get=vector)
|
||||
retval = any(_ in (page or "") for _ in ("<title>Bekchy - Access Denided</title>", "<a class=\"btn\" href=\"https://bekchy.com/report\">"))
|
||||
retval |= any(_ in (page or "") for _ in ("<title>Bekchy - Access Denided</title>", "<a class=\"btn\" href=\"https://bekchy.com/report\">"))
|
||||
if retval:
|
||||
break
|
||||
|
||||
|
||||
+1
-1
@@ -14,7 +14,7 @@ def detect(get_page):
|
||||
|
||||
for vector in WAF_ATTACK_VECTORS:
|
||||
page, _, _ = get_page(get=vector)
|
||||
retval = any(_ in (page or "") for _ in ("alt=\"BitNinja|Security check by BitNinja", "your IP will be removed from BitNinja", "<title>Visitor anti-robot validation</title>"))
|
||||
retval |= any(_ in (page or "") for _ in ("alt=\"BitNinja|Security check by BitNinja", "your IP will be removed from BitNinja", "<title>Visitor anti-robot validation</title>"))
|
||||
if retval:
|
||||
break
|
||||
|
||||
|
||||
+1
-1
@@ -17,7 +17,7 @@ def detect(get_page):
|
||||
|
||||
for vector in WAF_ATTACK_VECTORS:
|
||||
page, headers, code = get_page(get=vector)
|
||||
retval = re.search(r"BDWAF", headers.get(HTTP_HEADER.SERVER, ""), re.I) is not None
|
||||
retval |= re.search(r"BDWAF", headers.get(HTTP_HEADER.SERVER, ""), re.I) is not None
|
||||
retval |= re.search(r"Bluedon Web Application Firewall", page or "", re.I) is not None
|
||||
if retval:
|
||||
break
|
||||
|
||||
+1
-1
@@ -14,7 +14,7 @@ def detect(get_page):
|
||||
|
||||
for vector in WAF_ATTACK_VECTORS:
|
||||
page, _, _ = get_page(get=vector)
|
||||
retval = any(_ in (page or "") for _ in ("We're sorry, you are not allowed to proceed", "Your request looks suspicious or similar to automated requests from spam posting software"))
|
||||
retval |= any(_ in (page or "") for _ in ("We're sorry, you are not allowed to proceed", "Your request looks suspicious or similar to automated requests from spam posting software"))
|
||||
if retval:
|
||||
break
|
||||
|
||||
|
||||
+2
-2
@@ -14,9 +14,9 @@ def detect(get_page):
|
||||
|
||||
for vector in WAF_ATTACK_VECTORS:
|
||||
page, headers, code = get_page(get=vector)
|
||||
retval = code >= 400 and headers.get("Powered-By-ChinaCache") is not None
|
||||
retval |= code >= 400 and headers.get("Powered-By-ChinaCache") is not None
|
||||
|
||||
if retval:
|
||||
break
|
||||
|
||||
return retval
|
||||
return retval
|
||||
|
||||
+1
-1
@@ -17,7 +17,7 @@ def detect(get_page):
|
||||
|
||||
for vector in WAF_ATTACK_VECTORS:
|
||||
_, headers, _ = get_page(get=vector)
|
||||
retval = re.search(r"ACE XML Gateway", headers.get(HTTP_HEADER.SERVER, ""), re.I) is not None
|
||||
retval |= re.search(r"ACE XML Gateway", headers.get(HTTP_HEADER.SERVER, ""), re.I) is not None
|
||||
if retval:
|
||||
break
|
||||
|
||||
|
||||
+3
-1
@@ -14,6 +14,8 @@ def detect(get_page):
|
||||
|
||||
for vector in WAF_ATTACK_VECTORS:
|
||||
page, headers, code = get_page(get=vector)
|
||||
retval = code >= 400 and all(_ in (page or "") for _ in ("Cloudbric", "Malicious Code Detected"))
|
||||
retval |= code >= 400 and all(_ in (page or "") for _ in ("Cloudbric", "Malicious Code Detected"))
|
||||
if retval:
|
||||
break
|
||||
|
||||
return retval
|
||||
|
||||
+1
-3
@@ -14,9 +14,7 @@ def detect(get_page):
|
||||
|
||||
for vector in WAF_ATTACK_VECTORS:
|
||||
page, headers, _ = get_page(get=vector)
|
||||
|
||||
retval = all(_ in (page or "") for _ in ("Generated by cloudfront", "Request blocked"))
|
||||
|
||||
retval |= all(_ in (page or "") for _ in ("Generated by cloudfront", "Request blocked"))
|
||||
if retval:
|
||||
break
|
||||
|
||||
|
||||
+1
-1
@@ -17,7 +17,7 @@ def detect(get_page):
|
||||
|
||||
for vector in WAF_ATTACK_VECTORS:
|
||||
_, headers, _ = get_page(get=vector)
|
||||
retval = re.search(r"Protected by COMODO WAF", headers.get(HTTP_HEADER.SERVER, ""), re.I) is not None
|
||||
retval |= re.search(r"Protected by COMODO WAF", headers.get(HTTP_HEADER.SERVER, ""), re.I) is not None
|
||||
if retval:
|
||||
break
|
||||
|
||||
|
||||
+3
-1
@@ -14,7 +14,9 @@ def detect(get_page):
|
||||
|
||||
for vector in WAF_ATTACK_VECTORS:
|
||||
page, _, code = get_page(get=vector)
|
||||
retval = code >= 400 and "This site is protected by CrawlProtect" in (page or "")
|
||||
retval |= code >= 400 and "This site is protected by CrawlProtect" in (page or "")
|
||||
retval |= "<title>CrawlProtect" in (page or "")
|
||||
if retval:
|
||||
break
|
||||
|
||||
return retval
|
||||
|
||||
+1
-1
@@ -14,7 +14,7 @@ def detect(get_page):
|
||||
|
||||
for vector in WAF_ATTACK_VECTORS:
|
||||
page, headers, _ = get_page(get=vector)
|
||||
retval = headers.get("x-distil-cs") is not None
|
||||
retval |= headers.get("x-distil-cs") is not None
|
||||
retval |= any(_ in (page or "") for _ in ("distilCaptchaForm", "distilCallbackGuard", "cdn.distilnetworks.com/images/anomaly-detected.png"))
|
||||
if retval:
|
||||
break
|
||||
|
||||
+1
-1
@@ -14,7 +14,7 @@ def detect(get_page):
|
||||
|
||||
for vector in WAF_ATTACK_VECTORS:
|
||||
page, headers, _ = get_page(get=vector)
|
||||
retval = headers.get("X-dotDefender-denied", "") == "1"
|
||||
retval |= headers.get("X-dotDefender-denied", "") == "1"
|
||||
retval |= any(_ in (page or "") for _ in ("dotDefender Blocked Your Request", '<meta name="description" content="Applicure is the leading provider of web application security', "Please contact the site administrator, and provide the following Reference ID:"))
|
||||
if retval:
|
||||
break
|
||||
|
||||
+1
-1
@@ -17,7 +17,7 @@ def detect(get_page):
|
||||
|
||||
for vector in WAF_ATTACK_VECTORS:
|
||||
_, headers, code = get_page(get=vector)
|
||||
retval = code == 400 and re.search(r"\AECDF", headers.get(HTTP_HEADER.SERVER, ""), re.I) is not None
|
||||
retval |= code == 400 and re.search(r"\AECDF", headers.get(HTTP_HEADER.SERVER, ""), re.I) is not None
|
||||
if retval:
|
||||
break
|
||||
|
||||
|
||||
@@ -17,7 +17,7 @@ def detect(get_page):
|
||||
|
||||
for vector in WAF_ATTACK_VECTORS:
|
||||
page, headers, _ = get_page(get=vector)
|
||||
retval = any((page or "").strip() == _ for _ in ("Invalid GET Data", "Invalid URI")) and re.search(r"\bexp_last_", headers.get(HTTP_HEADER.SET_COOKIE, ""), re.I) is not None
|
||||
retval |= any((page or "").strip() == _ for _ in ("Invalid GET Data", "Invalid URI")) and re.search(r"\bexp_last_", headers.get(HTTP_HEADER.SET_COOKIE, ""), re.I) is not None
|
||||
if retval:
|
||||
break
|
||||
|
||||
|
||||
+1
-1
@@ -17,7 +17,7 @@ def detect(get_page):
|
||||
|
||||
for vector in WAF_ATTACK_VECTORS:
|
||||
page, headers, _ = get_page(get=vector)
|
||||
retval = re.search(r"\AFORTIWAFSID=", headers.get(HTTP_HEADER.SET_COOKIE, ""), re.I) is not None
|
||||
retval |= re.search(r"\AFORTIWAFSID=", headers.get(HTTP_HEADER.SET_COOKIE, ""), re.I) is not None
|
||||
retval |= all(_ in (page or "") for _ in (".fgd_icon", ".blocked", ".authenticate"))
|
||||
if retval:
|
||||
break
|
||||
|
||||
+2
-1
@@ -7,6 +7,7 @@ See the file 'LICENSE' for copying permission
|
||||
|
||||
import re
|
||||
|
||||
from lib.core.common import getUnicode
|
||||
from lib.core.data import kb
|
||||
from lib.core.settings import GENERIC_PROTECTION_REGEX
|
||||
from lib.core.settings import IPS_WAF_CHECK_PAYLOAD
|
||||
@@ -26,7 +27,7 @@ def detect(get_page):
|
||||
|
||||
if code >= 400 or (IPS_WAF_CHECK_PAYLOAD in vector and (code is None or re.search(GENERIC_PROTECTION_REGEX, page or "") and not re.search(GENERIC_PROTECTION_REGEX, original or ""))):
|
||||
if code is not None:
|
||||
kb.wafSpecificResponse = "HTTP/1.1 %s\n%s\n%s" % (code, "".join(_ for _ in (headers.headers if headers else {}) or [] if not _.startswith("URI")), page)
|
||||
kb.wafSpecificResponse = "HTTP/1.1 %s\n%s\n%s" % (code, "".join(getUnicode(_) for _ in (headers.headers if headers else {}) or [] if not _.startswith("URI")), getUnicode(page or ""))
|
||||
|
||||
retval = True
|
||||
break
|
||||
|
||||
+3
-1
@@ -14,6 +14,8 @@ def detect(get_page):
|
||||
|
||||
for vector in WAF_ATTACK_VECTORS:
|
||||
page, _, _ = get_page(get=vector)
|
||||
retval = any(_ in (page or "") for _ in ("Access Denied - GoDaddy Website Firewall", "<title>GoDaddy Security - Access Denied</title>"))
|
||||
retval |= any(_ in (page or "") for _ in ("Access Denied - GoDaddy Website Firewall", "<title>GoDaddy Security - Access Denied</title>"))
|
||||
if retval:
|
||||
break
|
||||
|
||||
return retval
|
||||
|
||||
+1
-1
@@ -17,7 +17,7 @@ def detect(get_page):
|
||||
|
||||
for vector in WAF_ATTACK_VECTORS:
|
||||
page, headers, _ = get_page(get=vector)
|
||||
retval = re.search(r"\Agreywizard", headers.get(HTTP_HEADER.SERVER, ""), re.I) is not None
|
||||
retval |= re.search(r"\Agreywizard", headers.get(HTTP_HEADER.SERVER, ""), re.I) is not None
|
||||
retval |= any(_ in (page or "") for _ in ("We've detected attempted attack or non standard traffic from your IP address", "<title>Grey Wizard</title>"))
|
||||
if retval:
|
||||
break
|
||||
|
||||
+2
-2
@@ -17,8 +17,8 @@ def detect(get_page):
|
||||
|
||||
for vector in WAF_ATTACK_VECTORS:
|
||||
page, headers, _ = get_page(get=vector)
|
||||
retval = re.search(r"\Aimunify360", headers.get(HTTP_HEADER.SERVER, ""), re.I) is not None
|
||||
retval = any(_ in (page or "") for _ in ("protected by Imunify360", "Powered by Imunify360", "imunify360 preloader"))
|
||||
retval |= re.search(r"\Aimunify360", headers.get(HTTP_HEADER.SERVER, ""), re.I) is not None
|
||||
retval |= any(_ in (page or "") for _ in ("protected by Imunify360", "Powered by Imunify360", "imunify360 preloader"))
|
||||
if retval:
|
||||
break
|
||||
|
||||
|
||||
+1
-1
@@ -17,7 +17,7 @@ def detect(get_page):
|
||||
|
||||
for vector in WAF_ATTACK_VECTORS:
|
||||
page, headers, _ = get_page(get=vector)
|
||||
retval = re.search(r"incap_ses|visid_incap", headers.get(HTTP_HEADER.SET_COOKIE, ""), re.I) is not None
|
||||
retval |= re.search(r"incap_ses|visid_incap", headers.get(HTTP_HEADER.SET_COOKIE, ""), re.I) is not None
|
||||
retval |= re.search(r"Incapsula", headers.get("X-CDN", ""), re.I) is not None
|
||||
retval |= "Incapsula incident ID" in (page or "")
|
||||
retval |= all(_ in (page or "") for _ in ("Error code 15", "This request was blocked by the security rules"))
|
||||
|
||||
+1
-1
@@ -14,7 +14,7 @@ def detect(get_page):
|
||||
|
||||
for vector in WAF_ATTACK_VECTORS:
|
||||
page, _, _ = get_page(get=vector)
|
||||
retval = all(_ in (page or "") for _ in ("Reason:", "by Janusec Application Gateway"))
|
||||
retval |= all(_ in (page or "") for _ in ("Reason:", "by Janusec Application Gateway"))
|
||||
if retval:
|
||||
break
|
||||
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user