diff --git a/Readme-ja.md b/Readme-ja.md index bc7d5918..34c9691e 100644 --- a/Readme-ja.md +++ b/Readme-ja.md @@ -17,7 +17,7 @@ Burp Suiteにはアジアの文字エンコーディングの利用に欠点が ## 必須ライブラリ ビルドには別途 [BurpExtLib](https://github.com/raise-isayan/BurpExtLib) のライブラリを必要とします。 -* BurpExtlib v2.0.4 +* BurpExtlib v2.0.10 ## 注意事項 このツールは、私個人が勝手に開発したもので、PortSwigger社は一切関係ありません。本ツールを使用したことによる不具合等についてPortSwiggerに問い合わせないようお願いします。 diff --git a/Readme.md b/Readme.md index 39a6d895..164b398f 100644 --- a/Readme.md +++ b/Readme.md @@ -17,8 +17,8 @@ If you are online, please refer to [help](https://github.com/raise-isayan/Yagura ## Required library Building requires a separate [BurpExtLib](https://github.com/raise-isayan/BurpExtLib) library. -* BurpExtlib v2.0.4 +* BurpExtlib v2.0.10 -##Notes +## Notes This tool was developed by myself and has nothing to do with PortSwigger. Please do not contact PortSwigger for any problems caused by using this tool. diff --git a/help/help-ja.html b/help/help-ja.html index 693fa2d0..88c58f84 100644 --- a/help/help-ja.html +++ b/help/help-ja.html @@ -469,7 +469,7 @@

1. 動作環境

Java
@@ -477,7 +477,7 @@

1. 動作環境

Burp suite
@@ -1829,7 +1829,7 @@

3.9. Version

diff --git a/help/help.html b/help/help.html index 8c48c88b..72fdf3af 100644 --- a/help/help.html +++ b/help/help.html @@ -469,7 +469,7 @@

1. Operating environment

Java
@@ -477,7 +477,7 @@

1. Operating environment

Burp suite
@@ -1830,7 +1830,7 @@

3.9. Version

diff --git a/pom.xml b/pom.xml index 897ddc6c..fc3bc920 100644 --- a/pom.xml +++ b/pom.xml @@ -3,14 +3,14 @@ 4.0.0 burp YaguraExtender - 1.9 + 2.0 jar - ${project.version}.25.0 + ${project.version}.0.0 -Xlint:unchecked UTF-8 - 1.8 - 1.8 + 11 + 11 @@ -36,7 +36,7 @@ maven-compiler-plugin - 3.3 + 3.6.1 ${compilerArgument} true @@ -127,7 +127,7 @@ burp BurpExtlib - 2.0.9 + 2.0.10 com.google.code.gson diff --git a/release/YaguraExtender-v2.0.jar b/release/YaguraExtender-v2.0.jar new file mode 100644 index 00000000..7641d06b Binary files /dev/null and b/release/YaguraExtender-v2.0.jar differ diff --git a/src/main/help/help-ja.adoc b/src/main/help/help-ja.adoc index 942f8bd8..b47aa2a6 100644 --- a/src/main/help/help-ja.adoc +++ b/src/main/help/help-ja.adoc @@ -9,10 +9,10 @@ Language/link:help.html[English] == 動作環境 .Java -* JRE(JDK) 8, 11 (Open JDK を推奨)(https://openjdk.java.net/) +* JRE(JDK) 11 (Open JDK を推奨)(https://openjdk.java.net/) .Burp suite -* 1.7以上 (http://www.portswigger.net/burp/) +* v2020以上 (http://www.portswigger.net/burp/) .開発環境 * NetBean 11.0 (https://netbeans.apache.org/) diff --git a/src/main/help/help.adoc b/src/main/help/help.adoc index e8291e6c..18852ae6 100644 --- a/src/main/help/help.adoc +++ b/src/main/help/help.adoc @@ -9,10 +9,10 @@ Language/link:help-ja.html[Japanese] == Operating environment .Java -* JRE (JDK) 8, 11 (Open JDK is recommended) (https://openjdk.java.net/) +* JRE (JDK) 11 (Open JDK is recommended) (https://openjdk.java.net/) .Burp suite -* 1.7 or higher (http://www.portswigger.net/burp/) +* v2020 or higher (http://www.portswigger.net/burp/) .Development environment * NetBean 11.0 (https://netbeans.apache.org/) diff --git a/src/main/java/burp/BurpExtender.java b/src/main/java/burp/BurpExtender.java index 15391fd6..99e92994 100644 --- a/src/main/java/burp/BurpExtender.java +++ b/src/main/java/burp/BurpExtender.java @@ -9,8 +9,8 @@ import yagura.view.JSONViewTab; import yagura.view.TabbetOption; import yagura.model.MatchReplaceGroup; -import passive.signature.MatchAlert; import yagura.model.OptionProperty; +import passive.signature.MatchAlert; import extend.view.base.HttpMessage; import extend.view.base.MatchItem; import extend.util.BurpWrap; diff --git a/src/main/java/yagura/model/SendToItem.java b/src/main/java/yagura/model/SendToItem.java index 6d9b8868..afbf6b72 100644 --- a/src/main/java/yagura/model/SendToItem.java +++ b/src/main/java/yagura/model/SendToItem.java @@ -4,7 +4,6 @@ import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.IOException; -import java.io.OutputStream; import java.nio.charset.StandardCharsets; import java.util.Properties; import java.util.logging.Level; diff --git a/src/main/java/yagura/model/SendToMenu.java b/src/main/java/yagura/model/SendToMenu.java index aa58305c..d26382dc 100644 --- a/src/main/java/yagura/model/SendToMenu.java +++ b/src/main/java/yagura/model/SendToMenu.java @@ -12,6 +12,7 @@ import extend.util.HttpUtil; import extend.util.Util; import java.awt.Component; +import java.awt.TrayIcon; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.InputEvent; @@ -108,6 +109,24 @@ public void renewMenu(SendToProperty property) { mnuItem.setText(item.getCaption()); if (item.isServer()) { SendToMenuItem sendToItem = new SendToServer(item, this.invocation); + sendToItem.addSendToListener(new SendToListener() { + @Override + public void complete(SendToEvent evt) { + } + + @Override + public void warning(SendToEvent evt) { + BurpExtender.issueAlert("SendToServer", evt.getMessage(), TrayIcon.MessageType.WARNING); + Logger.getLogger(BurpExtender.class.getName()).log(Level.WARNING, evt.getMessage()); + } + + @Override + public void error(SendToEvent evt) { + BurpExtender.issueAlert("SendToServer", evt.getMessage(), TrayIcon.MessageType.ERROR); + Logger.getLogger(BurpExtender.class.getName()).log(Level.SEVERE, evt.getMessage()); } + + }); + sendToList.add(sendToItem); mnuItem.addActionListener(sendToItem); if (property.isSubMenu()) { diff --git a/src/main/java/yagura/model/SendToMenuItem.java b/src/main/java/yagura/model/SendToMenuItem.java index 2f71a903..75c6a922 100644 --- a/src/main/java/yagura/model/SendToMenuItem.java +++ b/src/main/java/yagura/model/SendToMenuItem.java @@ -13,7 +13,6 @@ import java.io.FileOutputStream; import java.io.IOException; import java.util.Arrays; -import java.util.Properties; import java.util.logging.Level; import java.util.logging.Logger; diff --git a/src/main/java/yagura/model/SendToMultiEditor.java b/src/main/java/yagura/model/SendToMultiEditor.java index bbd8e2cf..d9eba84d 100644 --- a/src/main/java/yagura/model/SendToMultiEditor.java +++ b/src/main/java/yagura/model/SendToMultiEditor.java @@ -6,6 +6,8 @@ import java.awt.event.ActionEvent; import java.io.File; import java.io.IOException; +import java.util.logging.Level; +import java.util.logging.Logger; /** * @@ -48,6 +50,7 @@ public void sendToEvent(IHttpRequestResponse[] messageInfo) { Util.executeFormat(this.getTarget(), args); } catch (IOException ex) { this.fireSendToErrorEvent(new SendToEvent(this, ex.getMessage())); + Logger.getLogger(SendToMultiEditor.class.getName()).log(Level.SEVERE, ex.getMessage(), ex); } } } diff --git a/src/main/java/yagura/model/SendToServer.java b/src/main/java/yagura/model/SendToServer.java index da07834e..02dd5cbd 100644 --- a/src/main/java/yagura/model/SendToServer.java +++ b/src/main/java/yagura/model/SendToServer.java @@ -1,29 +1,39 @@ package yagura.model; +import burp.BurpExtender; import burp.IContextMenuInvocation; import extend.util.HttpUtil; import burp.IHttpRequestResponse; import burp.IHttpService; import extend.util.BurpWrap; import extend.util.Util; -import java.awt.event.ActionEvent; -import java.io.BufferedInputStream; +import java.awt.event.ActionEvent; import java.io.ByteArrayOutputStream; import java.io.IOException; -import java.io.InputStream; import java.io.OutputStream; import java.net.Authenticator; import java.net.HttpURLConnection; import java.net.InetSocketAddress; import java.net.PasswordAuthentication; import java.net.Proxy; +import java.net.ProxySelector; import java.net.SocketAddress; -import java.net.URL; +import java.net.URI; +import java.net.http.HttpClient; +import java.net.http.HttpClient.Redirect; +import java.net.http.HttpClient.Version; +import java.net.http.HttpRequest; +import java.net.http.HttpRequest.BodyPublishers; +import java.net.http.HttpResponse; +import java.net.http.HttpResponse.BodyHandlers; import java.nio.charset.StandardCharsets; +import java.time.Duration; import java.util.Properties; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; +import java.util.logging.Level; +import java.util.logging.Logger; /** * @@ -57,116 +67,101 @@ public void sendToEvent(IHttpRequestResponse[] messageInfo) { } } + /* + * https://alvinalexander.com/java/jwarehouse/openjdk-8/jdk/src/share/classes/sun/net/www/protocol/http/HttpURLConnection.java.shtml + */ + private final ExecutorService threadExecutor = Executors.newSingleThreadExecutor(); protected void sendToServer(IHttpRequestResponse messageInfo) { Runnable sendTo = new Runnable() { @Override public void run() { - String boundary = HttpUtil.generateBoundary(); HttpURLConnection conn = null; try { - DummyOutputStream dummy = new DummyOutputStream(); - outMultipart(boundary, dummy, messageInfo); - int contentLength = dummy.getSize(); - - URL url = new URL(getTarget()); // 送信先 // 拡張オプションを取得 Properties prop = getExtendProperty(); - String proxyProtocol = prop.getProperty("proxyProtocol", Proxy.Type.DIRECT.name()); + String proxyProtocol = prop.getProperty("proxyProtocol", Proxy.Type.DIRECT.name()); Proxy proxy = Proxy.NO_PROXY; if (!Proxy.Type.DIRECT.name().equals(proxyProtocol)) { - String proxyHost = prop.getProperty("proxyHost", ""); + String proxyHost = prop.getProperty("proxyHost", ""); if (Proxy.Type.HTTP.name().equals(proxyProtocol)) { int proxyPort = Util.parseIntDefault(prop.getProperty("proxyPort", "8080"), 8080); SocketAddress addr = new InetSocketAddress(proxyHost, proxyPort); - proxy = new Proxy(Proxy.Type.HTTP, addr); - } - else if (Proxy.Type.SOCKS.name().equals(proxyProtocol)) { + proxy = new Proxy(Proxy.Type.HTTP, addr); + } else if (Proxy.Type.SOCKS.name().equals(proxyProtocol)) { int proxyPort = Util.parseIntDefault(prop.getProperty("proxyPort", "1080"), 1080); SocketAddress addr = new InetSocketAddress(proxyHost, proxyPort); - proxy = new Proxy(Proxy.Type.SOCKS, addr); + proxy = new Proxy(Proxy.Type.SOCKS, addr); } - } - String proxyUser = prop.getProperty("proxyUser", ""); - String proxyPasswd = prop.getProperty("proxyPasswd", ""); - Authenticator authenticator = new Authenticator() { - @Override - protected PasswordAuthentication getPasswordAuthentication() { - return new PasswordAuthentication(proxyUser, proxyPasswd.toCharArray()); - } - }; - if (!proxyUser.isEmpty()) { - Authenticator.setDefault(authenticator); } - else { - Authenticator.setDefault(null); + Authenticator authenticator = null; + if (!Proxy.Type.DIRECT.name().equals(proxyProtocol)) { + String proxyUser = prop.getProperty("proxyUser", ""); + String proxyPasswd = prop.getProperty("proxyPasswd", ""); + authenticator = new Authenticator() { + @Override + protected PasswordAuthentication getPasswordAuthentication() { + return new PasswordAuthentication(proxyUser, proxyPasswd.toCharArray()); + } + }; } - conn = (HttpURLConnection) url.openConnection(proxy); - conn.setFixedLengthStreamingMode(contentLength); - conn.setRequestMethod("POST"); - conn.setDoOutput(true); - conn.setRequestProperty("Content-Type", "multipart/form-data; boundary=" + boundary); - conn.connect(); - - OutputStream ostm = null; - try { - ostm = conn.getOutputStream(); - outMultipart(boundary, ostm, messageInfo); - } catch (IOException e) { - fireSendToErrorEvent(new SendToEvent(this, e.getMessage())); - } catch (Exception e) { - fireSendToErrorEvent(new SendToEvent(this, e.getMessage())); - } finally { - if (ostm != null) { - ostm.close(); - } + + String boundary = HttpUtil.generateBoundary(); + HttpClient.Builder builder = HttpClient.newBuilder() + .version(Version.HTTP_1_1) + .followRedirects(Redirect.NEVER) + .connectTimeout(Duration.ofSeconds(10)) + .sslContext(HttpUtil.ignoreSSLContext()); + + if (!Proxy.Type.DIRECT.name().equals(proxyProtocol)) { + ProxySelector staticProxy = new HttpUtil.StaticProxySelector(proxy) { + @Override + public void connectFailed(URI uri, SocketAddress sa, IOException ex) { + fireSendToErrorEvent(new SendToEvent(this, "Error[" + ex.getClass().getName() + "]:" + ex.getMessage())); + Logger.getLogger(SendToServer.class.getName()).log(Level.SEVERE, ex.getMessage(), ex); + } + }; + builder.proxy(staticProxy); } + if (authenticator != null) { + builder.authenticator(authenticator); + } + try ( ByteArrayOutputStream ostm = new ByteArrayOutputStream()) { + outMultipart(boundary, ostm, messageInfo); - InputStream istm = conn.getInputStream(); - ByteArrayOutputStream bostm = new ByteArrayOutputStream(); - try { - BufferedInputStream bistm = new BufferedInputStream(istm); - String decodeMessage; - byte buf[] = new byte[4096]; - int len; - while ((len = bistm.read(buf)) != -1) { - bostm.write(buf, 0, len); - } - int statusCode = conn.getResponseCode(); - decodeMessage = Util.decodeMessage(bostm.toByteArray()); + HttpRequest request = HttpRequest.newBuilder() + .uri(URI.create(getTarget())) // 送信先 + .timeout(Duration.ofSeconds(10)) + .header("Content-Type", "multipart/form-data;boundary=" + boundary) + .POST(BodyPublishers.ofByteArray(ostm.toByteArray())) + .build(); + + HttpClient client = builder.build(); + HttpResponse response = client.send(request, BodyHandlers.ofString()); + int statusCode = response.statusCode(); + String bodyMessage = response.body(); if (statusCode == HttpURLConnection.HTTP_OK) { - if (decodeMessage.length() == 0) { + if (bodyMessage.length() == 0) { fireSendToCompleteEvent(new SendToEvent(this, "Success[" + statusCode + "]")); } else { - fireSendToWarningEvent(new SendToEvent(this, "Warning[" + statusCode + "]:" + decodeMessage)); + fireSendToWarningEvent(new SendToEvent(this, "Warning[" + statusCode + "]:" + bodyMessage)); + Logger.getLogger(SendToServer.class.getName()).log(Level.WARNING, "[" + statusCode + "]", bodyMessage); } } else { // 200以外 - fireSendToErrorEvent(new SendToEvent(this, "Error[" + statusCode + "]:" + decodeMessage)); - } - - } catch (IOException e) { - fireSendToErrorEvent(new SendToEvent(this, "Error[" + e.getClass().getName() + "]:" + e.getMessage())); - } finally { - if (istm != null) { - istm.close(); - } - if (bostm != null) { - bostm.close(); + fireSendToWarningEvent(new SendToEvent(this, "Error[" + statusCode + "]:" + bodyMessage)); + Logger.getLogger(SendToServer.class.getName()).log(Level.WARNING, "[" + statusCode + "]", bodyMessage); } } } catch (IOException ex) { fireSendToErrorEvent(new SendToEvent(this, "Error[" + ex.getClass().getName() + "]:" + ex.getMessage())); + Logger.getLogger(SendToServer.class.getName()).log(Level.SEVERE, ex.getMessage(), ex); } catch (Exception ex) { fireSendToErrorEvent(new SendToEvent(this, "Error[" + ex.getClass().getName() + "]:" + ex.getMessage())); - } finally { - if (conn != null) { - conn.disconnect(); - } + Logger.getLogger(SendToServer.class.getName()).log(Level.SEVERE, ex.getMessage(), ex); } } - }; this.threadExecutor.submit(sendTo); } @@ -200,34 +195,10 @@ public void actionPerformed(ActionEvent e) { sendToEvent(messageInfo); } - class DummyOutputStream extends OutputStream { - - private int size = 0; - - @Override - public void write(int b) throws IOException { - size += 1; - } - - @Override - public void write(byte[] bytes) throws IOException { - size += bytes.length; - } - - @Override - public void write(byte[] b, int off, int len) throws IOException { - size += len; - } - - public int getSize() { - return this.size; - } - } - @Override public boolean isEnabled() { boolean enabled = (this.contextMenu.getInvocationContext() != IContextMenuInvocation.CONTEXT_INTRUDER_PAYLOAD_POSITIONS) - || (this.contextMenu.getInvocationContext() != IContextMenuInvocation.CONTEXT_TARGET_SITE_MAP_TREE); + || (this.contextMenu.getInvocationContext() != IContextMenuInvocation.CONTEXT_TARGET_SITE_MAP_TREE); return enabled; } diff --git a/src/main/java/yagura/view/GeneratePoCTab.java b/src/main/java/yagura/view/GeneratePoCTab.java index 57e63c20..74dddb90 100644 --- a/src/main/java/yagura/view/GeneratePoCTab.java +++ b/src/main/java/yagura/view/GeneratePoCTab.java @@ -16,12 +16,10 @@ import extend.util.SwingUtil; import extend.util.external.TransUtil; import extend.util.Util; -import extend.util.external.JsonUtil; import java.awt.Component; import java.awt.Font; import java.io.BufferedOutputStream; import java.io.File; -import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import java.nio.charset.StandardCharsets; @@ -32,14 +30,12 @@ import java.util.concurrent.ExecutionException; import java.util.logging.Level; import java.util.logging.Logger; -import java.util.regex.Pattern; import javax.swing.JFileChooser; import javax.swing.SwingWorker; import javax.swing.text.Document; import javax.swing.text.EditorKit; import javax.swing.text.JTextComponent; import javax.swing.text.StyledEditorKit; -import javax.swing.tree.DefaultTreeModel; import yagura.model.UniversalViewProperty; /** diff --git a/src/main/java/yagura/view/JTransCoderTab.java b/src/main/java/yagura/view/JTransCoderTab.java index 3ab7de87..010edc7c 100644 --- a/src/main/java/yagura/view/JTransCoderTab.java +++ b/src/main/java/yagura/view/JTransCoderTab.java @@ -7,20 +7,12 @@ import extend.util.Util; import extend.util.HashUtil; import extend.view.model.VerticalFlowLayout; -import java.awt.BorderLayout; -import java.awt.Component; -import java.awt.datatransfer.Clipboard; -import java.awt.datatransfer.DataFlavor; -import java.awt.datatransfer.StringSelection; -import java.awt.datatransfer.Transferable; -import java.awt.datatransfer.UnsupportedFlavorException; -import java.awt.im.InputContext; import extend.util.CertUtil; import extend.util.HttpUtil; import extend.util.external.TransUtil; -import yagura.model.UniversalViewProperty; +import java.awt.BorderLayout; +import java.awt.Component; import java.io.File; -import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.io.UnsupportedEncodingException; @@ -40,12 +32,12 @@ import java.security.cert.X509Certificate; import java.time.LocalDate; import java.util.Map; -import javax.swing.JComponent; import javax.swing.MutableComboBoxModel; -import javax.swing.TransferHandler; -import javax.swing.text.BadLocationException; -import javax.swing.text.Document; -import javax.swing.text.JTextComponent; +import java.io.BufferedOutputStream; +import java.math.BigInteger; +import java.util.HashSet; +import java.util.concurrent.ExecutionException; +import javax.swing.SwingWorker; import org.jdatepicker.JDateComponentFactory; import org.jdatepicker.impl.JDatePickerImpl; import extend.util.external.FormatUtil; @@ -53,12 +45,8 @@ import extend.util.external.TransUtil.DateUnit; import extend.util.external.TransUtil.EncodeType; import extend.util.external.TransUtil.NewLine; -import java.io.BufferedOutputStream; -import java.math.BigInteger; -import java.util.HashSet; -import java.util.concurrent.ExecutionException; -import javax.swing.SwingWorker; import yagura.model.JTransCoderProperty; +import yagura.model.UniversalViewProperty; /** * diff --git a/src/main/java/yagura/view/MatchAlertItemDlg.java b/src/main/java/yagura/view/MatchAlertItemDlg.java index 9c436401..9f5b1cb7 100644 --- a/src/main/java/yagura/view/MatchAlertItemDlg.java +++ b/src/main/java/yagura/view/MatchAlertItemDlg.java @@ -3,8 +3,8 @@ import burp.BurpExtender; import extend.util.SwingUtil; import extend.view.base.CustomDialog; -import yagura.model.MatchAlertItem; import extend.view.base.MatchItem; +import yagura.model.MatchAlertItem; import java.awt.Component; import java.awt.event.ComponentEvent; import java.util.EnumSet; diff --git a/src/main/java/yagura/view/ResultFilterPopup.java b/src/main/java/yagura/view/ResultFilterPopup.java index e47a8836..4bccfe46 100644 --- a/src/main/java/yagura/view/ResultFilterPopup.java +++ b/src/main/java/yagura/view/ResultFilterPopup.java @@ -11,6 +11,7 @@ import extend.view.base.MatchItem.HighlightColor; import extend.util.Util; import extend.view.model.VerticalFlowLayout; +import java.net.HttpURLConnection; import java.util.Comparator; import java.util.EnumSet; import java.util.logging.Level; @@ -449,16 +450,16 @@ public boolean include(RowFilter.Entry entry statusFilter = true; } - if (this.filterProp.getStat2xx() && (200 <= item.getStatusCode() && item.getStatusCode() < 300)) { + if (this.filterProp.getStat2xx() && (HttpURLConnection.HTTP_OK <= item.getStatusCode() && item.getStatusCode() < HttpURLConnection.HTTP_MULT_CHOICE)) { statusFilter = true; } - if (this.filterProp.getStat3xx() && (300 <= item.getStatusCode() && item.getStatusCode() < 400)) { + if (this.filterProp.getStat3xx() && (HttpURLConnection.HTTP_MULT_CHOICE <= item.getStatusCode() && item.getStatusCode() < HttpURLConnection.HTTP_BAD_REQUEST)) { statusFilter = true; } - if (this.filterProp.getStat4xx() && (400 <= item.getStatusCode() && item.getStatusCode() < 500)) { + if (this.filterProp.getStat4xx() && (HttpURLConnection.HTTP_BAD_REQUEST <= item.getStatusCode() && item.getStatusCode() < HttpURLConnection.HTTP_INTERNAL_ERROR)) { statusFilter = true; } - if (this.filterProp.getStat5xx() && (500 <= item.getStatusCode() && item.getStatusCode() < 600)) { + if (this.filterProp.getStat5xx() && (HttpURLConnection.HTTP_INTERNAL_ERROR <= item.getStatusCode() && item.getStatusCode() < 600)) { statusFilter = true; }