I try to send a byte[] () over a established SSL Connection (handshake etc is done).
The result: The byte[] is spitted into two packets (see debug below):
First packet: just the first byte of the application data (**01**) .
Second packet: the rest (fe db 01 00 ...) 650 Bytes
Is there a way to commit all application data bytes in one packet?
Stream to send 651 Bytes:
**01** fe db 01 00 00 02 83 3c 3f 78 6d 6c 20 76 65 72 73 69 6f 6e 3d 22 31 2e 30 22 20 65 6e 63 6f 64 69 6e 67 3d 22 75 73 2d 61 73 63 69 69 22 20 73 74 61 6e 64 61 6c 6f 6e 65 3d 22 6e 6f 22 3f 3e …
javax.net.debug output
Padded plaintext before ENCRYPTION: len = 32
0000: **01** 06 03 06 46 7F 7F AE D4 E8 30 5D B7 DB 3C 44 ....F.....0]..<D
0010: 02 08 C9 2A A1 0A 0A 0A 0A 0A 0A 0A 0A 0A 0A 0A ...*............
1, WRITE: TLSv1 Application Data, length = 32
[Raw write]: length = 37
0000: 17 03 01 00 20 B3 4E EE CE 5B 69 EC A5 4A 80 7F .... .N..[i..J..
0010: D6 03 35 AF 6A 7B 85 17 B7 46 A2 31 B2 EF 7E D0 ..5.j....F.1....
0020: EA 1B 67 7E ED ..g..
Padded plaintext before ENCRYPTION: len = 672
0000: FE DB 01 00 00 02 83 3C 3F 78 6D 6C 20 76 65 72 .......<?xml ver
0010: 73 69 6F 6E 3D 22 31 2E 30 22 20 65 6E 63 6F 64 sion="1.0" encod
0020: 69 6E 67 3D 22 75 73 2D 61 73 63 69 69 22 20 73 ing="us-ascii" s
0030: 74 61 6E 64 61 6C 6F 6E 65 3D 22 6E 6F 22 3F 3E tandalone="no"?>
[…]
Sun's impl comments:
By default, we counter chosen plaintext issues on CBC mode
ciphersuites in SSLv3/TLS1.0 by sending one byte of application
data in the first record of every payload, and the rest in
subsequent record(s). Note that the issues have been solved in
TLS 1.1 or later.
Experiment with SSLEngine.wrap( largePlainText ) shows that it produces 2 SSL records, the 1st record contains 1 byte of plain text, the 2nd record contains 15846 bytes of plain text.
The receiver API probably handle record-by-record, so it'll return 1 byte for the 1st read.
We can also observe this behavior in other SSL impls, e.g. HTTPS requests from web browsers.
OpenSSL inserts empty records against the attack. If the receiver is Java SSL socket, the input stream cannot return 0 bytes for read(), so the record is skipped. Other receivers may not be prepared for a 0-length record and may break.
The assumption you're making about reading the byte[] exactly as you write them on the other end is a classic TCP mistake. It's not actually specific to SSL/TLS, but could also happen with a TCP connection.
There is no guarantee in TCP (and in SSL/TLS) that the reader's buffer will be filled with the exact same packet length as the packets in the writer's buffer. All TCP guarantees is in-order delivery, so you'll eventually get all your data, but you have to treat it as a stream.
This is why protocols that use TCP rely on indicators and delimiters to tell the other end when to stop reading certain messages.
For example, HTTP 1.1 uses a blank line to indicate when the headers end, and it uses the Content-Length header to tell the recipient what entity length to expect (or chunked transfer encoding). SMTP also uses line returns and . at the end of a message.
If you're designing your own protocol, you need to define a way for the recipient to know when what you define as meaningful units of data are delimited. When you read the data, read such indicators, and fill in your read buffer until you get the amount of bytes you expect or until you find the delimiter that you've defined.
I had the same problem until I saw this page:
http://bugs.java.com/bugdatabase/view_bug.do?bug_id=7157903
So, I run the JVM with -Djsse.enableCBCProtection=false parameter and now the data is not splitted.
Best regards
Related
I found that when using Java.util.zip.GzipOutputStream, when I called flush() first then close(). The deflator always produce two bytes ('00' and '03' in hex) before writing the trailer. What does these two bytes mean? Why flush() does not flush all bytes in the compressor? I have already set the stream syncFlush to true. (In my use case I need to force flush the stream)
This is the test code I write.
File file = new File("gtest.gz");
OutputStream out = new FileOutputStream(file);
GZIPOutputStream gzipOutputStream = new GZIPOutputStream(out, true);
gzipOutputStream.write("Each gzip file generated by JAVA GzipOutputStream has byte '0003' before Trailer"
.getBytes());
gzipOutputStream.flush();
gzipOutputStream.close();
And I run hexdump -C gtest.gz get
00000000 1f 8b 08 00 00 00 00 00 00 00 72 4d 4c ce 50 48 |..........rML.PH|
00000010 af ca 2c 50 48 cb cc 49 55 48 4f cd 4b 2d 4a 2c |..,PH..IUHO.K-J,|
00000020 49 4d 51 48 aa 54 f0 72 0c 73 54 70 07 ca f9 97 |IMQH.T.r.sTp....|
00000030 96 14 94 96 04 97 14 a5 26 e6 2a 64 24 16 03 25 |........&.*d$..%|
00000040 4b 52 15 d4 0d 0c 0c 8c d5 15 92 52 d3 f2 8b 52 |KR.........R...R|
00000050 15 42 8a 12 81 06 14 01 00 00 00 ff ff 03 00 96 |.B..............|
00000060 ef 3b 5d 50 00 00 00 |.;]P...|
00000067
The last 8 bytes are trailer of Gzip and the two bytes before '03' '00' will always be produced whatever content I change.
I’m writing a program in java that send official invoice information to the Fiscal Administration. This public service provided certificates to use in the SSL connection to the web services and to encrypt some especial data fields inside the request body message.
I’m having an EOFException error during the handshake phase after client and server have agreed to communicate using the agreed cipher suite that in this case is TLS_RSA_WITH_AES_128_CBC_SHA.
Following the SSL protocol the client perform with success a test using the new cipher and send the test data to the server so the server can also repeat the same test and confirm that it is also capable of encrypt and decrypt data. And in this point the server send the EOFException.
Here is the last part of the SSL communication log:
Send a quick confirmation to the server verifying that we know the private key corresponding to the client certificate we just sent...
* CertificateVerify
[write] MD5 and SHA1 hashes: len = 262
binary data here too large not displayed
main, WRITE: TLSv1 Handshake, length = 262
[Raw write]: length = 267
binary data here too large not displayed
*Tell the server we're changing to the newly established cipher suite. All further messages will be encrypted using the parameters we just established. *
main, WRITE: TLSv1 Change Cipher Spec, length = 1
[Raw write]: length = 6
0000: 14 03 01 00 01 01
... and finishes with success
..Finished
We send an encrypted Finished message to verify everything worked.
verify_data: { 221, 96, 47, 110, 19, 170, 244, 8, 37, 152, 160, 40 }
...
The client encrypt the test data..
[write] MD5 and SHA1 hashes: len = 16
0000: 14 00 00 0C DD 60 2F 6E 13 AA F4 08 25 98 A0 28 .....`/n....%..(
Padded plaintext before ENCRYPTION: len = 48
0000: 14 00 00 0C DD 60 2F 6E 13 AA F4 08 25 98 A0 28 .....`/n....%..(
0010: 10 7F 85 11 EC 6D 5D ED 21 70 27 F4 DC 23 C0 9B .....m].!p'..#..
0020: A7 6F C2 80 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B .o..............
main, WRITE: TLSv1 Handshake, length = 48
* ...and send the test data to the server so that the server can do the same test and confirm that encrypted communication can be established (53 bytes = 48 from the test data + 5 from header) *
[Raw write]: length = 53
0000: 16 03 01 00 30 1C 17 08 0F 49 C9 6A 7A 8B 8C 48 ....0....I.jz..H
0010: BA 57 2D CB 06 46 1E 65 61 7C 5F 74 F2 08 AB 12 .W-..F.ea._t....
0020: 91 47 72 8C 8F 84 0A CB D7 29 E2 FD 84 B2 FD 9E .Gr......)......
0030: 47 DC 13 60 B4 G..`.
...and the server respond with the EOFException error
main, received EOFException: error
main, handling exception: javax.net.ssl.SSLHandshakeException: Remote host closed
connection during handshake
%% Invalidated: [Session-1, TLS_RSA_WITH_AES_128_CBC_SHA]
main, SEND TLSv1 ALERT: fatal, description = handshake_failure
Padded plaintext before ENCRYPTION: len = 32
0000: 02 28 BC 65 1A CA 68 87 79 84 5F 64 16 F5 28 72 .(.e..h.y._d..(r
0010: F7 8A 69 72 93 D8 09 09 09 09 09 09 09 09 09 09 ..ir............
main, WRITE: TLSv1 Alert, length = 32
[Raw write]: length = 37
0000: 15 03 01 00 20 0D 9A 35 18 B7 98 4B 7B AF 82 4E .... ..5...K...N
0010: 1A EE 7D AC 5D D5 49 05 4E 74 B9 77 E4 CD 87 61 ....].I.Nt.w...a
0020: 23 03 5C 9C 7E #...
main, called closeSocket()
main, called close()
main, called closeInternal(true)
I have no idea on what might be the cause for such a failure and how to programmatically influence the outcome of this step in the process. I’ve tried force the use of other ciphers recognized by both client and server such as SSL_RSA_WITH_RC4_128_MD5 but the error remain.
Any thoughts on how to solve this problem?
Any thoughts on how to solve this problem?
I suggest that you get in contact with the people who run that service, and get them to look at their logs to see why their server is closing the connection during SSL setup.
(Strictly speaking, the server does not "respond with [an] EOFException error". It is actually closing the TCP connection and the client-side Java libraries are throwing the exception. You are likely to get a more helpful response from the maintainers of the service if you use correct terminology.)
I'm recompiling a Java program, and I have the following method:
public static native String getMyString(String s);
getMyString is implemented inside mylibrary.so, and looks like follows:
; Scrambler::getMyString(char const*)
EXPORT _ZN9Scrambler18getMyStringEPKc
_ZN9Scrambler18getMyStringEPKc
LDR R1, =(mystring - 0x14FC8)
PUSH {R4-R6,LR}
ADD R1, PC ; "mystring"
MOV R4, R0
BLX strcasecmp
CMP R0, #0
BNE.W loc_150FC
which than ends up in
LDR R5, =(unk_6AE24 - 0x14FD8)
ADD R5, PC
The R5 seems to be the return value here.
The unk_6AE24 looks like follows:
27
68 5D 6D 06 3F 10 6D 26 32 10 56 12 06 3F 32 5D
12 27 26 4B 0D 5D 27 4B 6E 0D 2B 06 32 5D 68 24
3F 32 06 24 70 56 00 63 69 4C 1D 06 5A 7F 0C 34
1E 67 3B 63 32 5F 16 1D 34 5F 1E 32 42 69 18 49
3F 51 49 0C 1F 0C 0E 77 2F 44 69 7F 5A 0C 0B 34
0C 34 1C 24 32 5F 7F 00 00 00 00 1D 30 3B 5F 30
IDA suggests, that the string in question is 27 68 5D 6D or "'h]m", but I'm having my doubts. When I was using c++ ages ago, the strings used to end with 0, which would make for return value of 27 68 5D 6D 06 3F 10 6D 26 32 10 56 12 06 3F 32 5D 12 27 26 4B 0D 5D 27 4B 6E 0D 2B 06 32 5D 68 24 3F 32 06 24 70 56 . Or we could be talking about java string, which may have its own format.
What kind of string will getMyString return?
What kind of string will getMyString return?
It will return a java.lang.String, you can get that from the declaration.
The actual character data will (probably) be one redirection away from that. (a String is probably a pointer to a char array and a size). Keep in mind that in Java, a char is 16 bits.
What are you trying to do, anyway? Much easier to just set a breakpoint right after getMyString returns and look at the return value in a debugger.
The following code snippet attempts to create a Tib DaemonManager connecting to a particular rvd, and then query for that rvd's services.
public static void main(String[] args) throws RuntimeException {
DaemonManager daemonManager = new DaemonManager("http://foo.com:7580");
if(daemonManager.getDaemonType() == DaemonManager.RVD) {
DaemonProxy daemonProxy = daemonManager.getDaemonProxy();
final RvdProxy rvdProxy = (RvdProxy) daemonProxy;
Service[] services = rvdProxy.getServices();
System.out.println(services.length); //prints 0
for (Service service : services) {
System.out.println(service.getNetwork());
}
}
}
This prints zero, even though the web interface for this rvd lists multiple available services. Why might this happen?
The daemon I am connecting to is running v 7.5.1 of the software, and the rvconfig.jar that I am using is from v 7.5.1 as well.
Is there a gotcha when using Tibco's DaemonManager that is causing me to come unstuck?
I used Wireshark to look at the traffic being sent between my RvdProxy and the RVD itself, and it looks like a lot of HTTP GET traffic. For example:
0000 00 1e 0b a4 d1 7c 00 12 d9 7c 8a bf 08 00 45 00 .....|.. .|....E.
0010 03 87 a4 58 40 00 3d 06 66 90 0a 09 14 15 0a 0a ...X#.=. f.......
0020 07 61 1d 9c bf 09 fe 1e d6 82 6e 77 b9 52 80 18 .a...... ..nw.R..
0030 00 1b 05 43 00 00 01 01 08 0a ac 1c 6f 67 07 b2 ...C.... ....og..
0040 86 1f 72 3d 23 30 30 38 30 38 30 3e 3c 66 6f 6e ..r=#008 080><fon
0050 74 20 66 61 63 65 3d 48 65 6c 76 65 74 69 63 61 t face=H elvetica
0060 2c 41 72 69 61 6c 20 73 69 7a 65 3d 32 20 63 6f ,Arial s ize=2 co
0070 6c 6f 72 3d 23 46 46 46 46 46 46 3e 3c 62 3e 43 lor=#FFF FFF><b>C
Sure enough, upon further inspection, it turns out that the requests being made by the proxy are to the web pages served by the Daemon itself - so the proxy API is just a screen-scraper.
But why am I getting no services if they appear on the web pages that are being screen-scraped?
Switch on debugging:
System.setProperty("com.tibco.tibrv.config.debug","classes-to-debug")
And you find that the pattern being used to extract the services from the web-page...
/services,GET~~~~~\
service_detail\\?(\\d+)>\\1</a>.*?size=2>(\\d+\\.\\d+\\.\\d+\\.\\d+)</td>.*?size=2>
(\\d+)</td>.*?size=2>(\\d+)</td>~~~~~\
...fails to match anything! In my case it is because my service networks are not of the form (\\d+\\.\\d+\\.\\d+\\.\\d+) but rather of the form ;(\\d+\\.\\d+\\.\\d+\\.\\d+) - note the leading semicolon. This subtle difference is the source of all of my problems!
This looks like a bug in the rvconfig jar - which needs to be raised with Tibco! :(
We have an applet-servlet communication that we'd like to record with JMeter's HTTP proxy.
It works with GET messages until the applet sends an HTTP POST message which includes some serialized Java objects (built-in types), then we get this error in the Applet:
alt text http://img339.imageshack.us/img339/9238/appletservletjmeterhttp.png
OK, so there's some JVM version conflict somewhere in the queue. But where?
The communication runs OK without JMeter, that is: Applet -> Tomcat -> Servlet. All on my local machine.
But it doesn't work through JMeter: Applet -> JMeter proxy -> Tomcat -> Servlet. Also all on my machine.
It is as if JMeter was modifying the POST message content...
I tested it with the Apache proxy as well, working fine.
Even funnier thing is that I have only one version of Java installed, one JDK and one JRE. Both 1.6.0_07...
Thought I'd ask before starting digging deeper in the rabbit hole ;-)
Here is the hex dump of the POST data sent directly to Tomcat:
00000348 ac ed 00 05 73 72 00 11 6a 61 76 61 2e 6c 61 6e ....sr.. java.lan
00000358 67 2e 49 6e 74 65 67 65 72 12 e2 a0 a4 f7 81 87 g.Intege r.......
00000368 38 02 00 01 49 00 05 76 61 6c 75 65 78 72 00 10 8...I..v aluexr..
00000378 6a 61 76 61 2e 6c 61 6e 67 2e 4e 75 6d 62 65 72 java.lan g.Number
00000388 86 ac 95 1d 0b 94 e0 8b 02 00 00 78 70 00 00 01 ........ ...xp...
00000398 7b {
And here is the data when sent through JMeter:
00000128 ac ed 00 05 73 72 00 11 6a 61 76 61 2e 6c 61 6e ....sr.. java.lan
00000138 67 2e 49 6e 74 65 67 65 72 12 e2 a0 a4 f7 3f 3f g.Intege r.....??
00000148 38 02 00 01 49 00 05 76 61 6c 75 65 78 72 00 10 8...I..v aluexr..
00000158 6a 61 76 61 2e 6c 61 6e 67 2e 4e 75 6d 62 65 72 java.lan g.Number
00000168 3f ac 3f 1d 0b 3f e0 3f 02 00 00 78 70 00 00 01 ?.?..?.? ...xp...
00000178 7b {
A lot of "3f"s in the second dump...
So this is definitely some kind of an encoding problem.
The content type is set correctly in the header:
POST /ABCOrder/ABCServlet?cmd=getNetworkConnection HTTP/1.1
Connection: keep-alive
Content-Type: application/octet-stream
Host: 109.107.148.164:8443
Accept: text/html, image/gif, image/jpeg, *; q=.2, */*; q=.2
User-Agent: Mozilla/4.0 (Windows Vista 6.0) Java/1.6.0_14
Content-Length: 81
Here is the solution:
JMeter has a config file, bin/jmeter.properties.
Here you can find an option where you can set the binary content types:
# Binary content-type handling
# These content-types will be handled by saving the request in a file:
proxy.binary.types=application/x-amf,application/x-java-serialized-object
Now I don't know why application/octet-stream isn't included by default, but you can simply add it to the list, and you are done.
proxy.binary.types=application/x-amf,application/x-java-serialized-object,application/octet-stream
This is how I found it out:
https://issues.apache.org/bugzilla/show_bug.cgi?id=44808
Did a search on JMeter closed bugs... :-)
Someone else is reporting a very similar: http://markmail.org/message/pl5erin2isehm5q6. I can't find any issue related to this problem in their bug tracker though. It looks like you won the privilege to dig deeper in the rabbit hole :)
The accepted answer only allows recording static requests.
This will not be realistic as it will not allow any variabilisation of requests (for example changing the searched word, ...) so you will always be stress testing the same bunch of data.
To make it a real test, you need to use a third party plugin.
A commercial JMeter plugin allows this, see:
http://ubikloadpack.com/
To make your tests realistic, you will need to variabilize content in the serialized objects.
This Java Serialization plugin will allow the following:
Easy recording of traffic with JMeter Proxy Server, a Test Plan using custom Sampler will be created
Easy variabilization of requests (which will appear as XML) through as easy syntax as for example ${searchedWord} where searchedWord can come from a CSV or any user defined variable.
Easy extraction of data from responses using JMeter standard Post Processors
Easy debugging of Request/Responses through standard JMeter View Results Tree element
Disclaimer :I work for this company.